001    // ===========================================================================
002    // Copyright (c) 1996 Mort Bay Consulting Pty. Ltd. All rights reserved.
003    // $Id: Element.java,v 1.1 2004/03/23 13:59:49 laurent Exp $
004    // ---------------------------------------------------------------------------
005    
006    // Laurent Martelli <laurent@aopsys.com> - 21 mar. 2004:
007    // Added appendAttribute() and addCssClass() mehods
008    
009    package org.objectweb.jac.aspects.gui.web.html;
010    
011    import java.io.IOException;
012    import java.io.OutputStream;
013    import java.io.OutputStreamWriter;
014    import java.io.StringWriter;
015    import java.io.Writer;
016    import java.util.Enumeration;
017    import java.util.Hashtable;
018    import org.mortbay.util.Code;
019    
020    /* -------------------------------------------------------------------- */
021    /** HTML Element.
022     * <p>This abstract class is the base for all HTML Elements.
023     * The feature of an abstract HTML Element is that it can be added to
024     * HTML Pages, HTML Composites and several other HTML Elements derivations.
025     * Elements may also have attributes set, which are handled by the derived
026     * Element.
027     * @see Page
028     * @see Composite
029     * @version $Id: Element.java,v 1.1 2004/03/23 13:59:49 laurent Exp $
030     * @author Greg Wilkins
031    */
032    public abstract class Element
033    {
034        /* ----------------------------------------------------------------- */
035        public static final String
036            noAttributes="",
037            ALIGN="align",
038            LEFT="left",
039            RIGHT="right",
040            CENTER="center",
041            VALIGN="valign",
042            TOP="top",
043            BOTTOM="bottom",
044            MIDDLE="middle",
045            WIDTH="width",
046            HEIGHT="height",
047            SIZE="size",
048            COLOR="color",
049            BGCOLOR="bgcolor",
050            STYLE="style",
051            CLASS="class",
052            ID="id";
053        
054            
055        
056        /* ----------------------------------------------------------------- */
057        /** Dimensions >=0 if set*/
058        private int width=-1;
059        private int height=-1;
060        private int size=-1;
061    
062        /* ----------------------------------------------------------------- */
063        /** The space separated string of HTML element attributes.
064         */
065        private String attributes=null;
066        protected Hashtable attributeMap=null;
067    
068        /* ----------------------------------------------------------------- */
069        /** Default constructor.
070         */
071        public Element(){}
072    
073        /* ----------------------------------------------------------------- */
074        /** Construct with attributes.
075         * @param attributes The initial attributes of the element
076         */
077        public Element(String attributes)
078        {
079            attribute(attributes);
080        }
081    
082        /* ----------------------------------------------------------------- */
083        /** Write element to a Writer.
084         * This abstract method is called by the Page or other containing
085         * Element to write the HTML for this element. This must be implemented
086         * by the derived Element classes.
087         * @param out Writer to write the element to.
088         */
089        public abstract void write(Writer out)
090             throws IOException;
091    
092        /* ----------------------------------------------------------------- */
093        /** Write Element to an OutputStream.
094         * Calls print(Writer) and checks errors
095         * Elements that override this method should also override
096         * write(Writer) to avoid infinite recursion.
097         * @param out OutputStream to write the element to.
098         */
099        public void write(OutputStream out)
100             throws IOException
101        {
102            Writer writer = new OutputStreamWriter(out);
103            write(writer);
104            writer.flush();
105        }
106        
107        /* ----------------------------------------------------------------- */
108        /** Write Element to an OutputStream.
109         * Calls print(Writer) and checks errors
110         * Elements that override this method should also override
111         * write(Writer) to avoid infinite recursion.
112         * @param out OutputStream to write the element to.
113         */
114        public void write(OutputStream out, String encoding)
115             throws IOException
116        {
117            Writer writer = new OutputStreamWriter(out,encoding);
118            write(writer);
119            writer.flush();
120        }
121    
122        /* ----------------------------------------------------------------- */
123        public String attributes()
124        {
125            if (attributes==null && attributeMap==null)
126                return noAttributes;
127    
128            StringBuffer buf = new StringBuffer(128);
129            synchronized(buf)
130            {
131                if (attributeMap!=null)
132                {
133                    Enumeration e = attributeMap.keys();
134                    while (e.hasMoreElements())
135                    {
136                        buf.append(' ');
137                        String a = (String)e.nextElement();
138                        buf.append(a);
139                        buf.append('=');
140                        buf.append("\"");
141                        buf.append(attributeMap.get(a).toString());
142                        buf.append("\"");
143                    }
144                }
145                
146                if(attributes!=null && attributes.length()>0)
147                {
148                    if (!attributes.startsWith(" "))
149                        buf.append(' ');
150                    buf.append(attributes);
151                }
152            }
153    
154            return buf.toString();
155        }
156    
157        /* ----------------------------------------------------------------- */
158        /** Add element Attributes.
159         * The attributes are added to the Element attributes (separated with
160         * a space). The attributes are available to the derived class in the
161         * protected member String <I>attributes</I>
162         * @deprecated Use attribute(String).
163         * @param attributes String of HTML attributes to add to the element.
164         * @return This Element so calls can be chained.
165         */
166        public Element attributes(String attributes)
167        {
168            if (Code.debug() && attributes!=null && attributes.indexOf('=')>=0)
169                Code.warning("Set attribute with old method: "+attributes+
170                             " on " + getClass().getName());
171    
172            if (attributes==null)
173            {
174                this.attributes=null;
175                return this;
176            }
177            
178            if (attributes==noAttributes)
179                return this;
180            
181            if (this.attributes==null)
182                this.attributes=attributes;
183            else
184                this.attributes += ' '+attributes;
185            return this;
186        }
187    
188        /* ------------------------------------------------------------ */
189        /** Set attributes from another Element.
190         * @param e Element
191         * @return This Element
192         */
193        public Element setAttributesFrom(Element e)
194        {
195            attributes=e.attributes;
196            attributeMap=(Hashtable)e.attributeMap.clone();
197            return this;
198        }
199    
200        
201        /* ----------------------------------------------------------------- */
202        /** Add element Attributes.
203         * The attributes are added to the Element attributes (separated with
204         * a space). The attributes are available to the derived class in the
205         * protected member String <I>attributes</I>
206         * @param attributes String of HTML attributes to add to the element.
207         * A null attribute clears the current attributes.
208         * @return This Element so calls can be chained.
209         */
210        public Element attribute(String attributes)
211        {
212            if (Code.debug() && attributes!=null && attributes.indexOf('=')>=0)
213                Code.warning("Set attribute with old method: "+attributes+
214                             " on " + getClass().getName());
215            
216            if (attributes==null ||
217                this.attributes==null ||
218                this.attributes==noAttributes ||
219                this.attributes.length()==0)
220                this.attributes=attributes;
221            else
222                this.attributes += ' '+attributes;
223            return this;
224        }
225        
226        /* ----------------------------------------------------------------- */
227        /** Add quoted element Attributes and value.
228         * @param attribute String of HTML attribute tag
229         * @param value String value of the attribute to be quoted
230         * @return This Element so calls can be chained.
231         */
232        public Element attribute(String attribute, Object value)
233        {
234            if (attributeMap==null)
235                attributeMap=new Hashtable(10);
236            
237            if (value!=null)
238            {
239                if (value instanceof String && ((String)value).indexOf('"')!=-1)
240                    value=quoteAttributeValue((String)value);
241    
242                attributeMap.put(attribute,value.toString());
243            }
244            return this;
245        }
246    
247        static String quoteAttributeValue(String value) {
248            String s=(String)value;
249            int q=0;
250            while((q=s.indexOf('"',q))>=0)
251            {
252                s=s.substring(0,q)+"""+s.substring(++q);
253                q+=6;
254            }
255            return s;
256        }
257    
258        public Element appendAttribute(String attribute, Object value) 
259        {
260            if (attributeMap==null)
261                attributeMap=new Hashtable(10);
262            
263            if (value!=null)
264            {
265                if (value instanceof String && ((String)value).indexOf('"')!=-1)
266                    value=quoteAttributeValue((String)value);
267                String currentValue = (String)attributeMap.get(attribute);
268                if (currentValue!=null)
269                    value = currentValue+value;
270                attributeMap.put(attribute,value);
271            }
272            return this;
273        }
274        /* ----------------------------------------------------------------- */
275        /** Add quoted element Attributes and value.
276         * @param attribute String of HTML attribute tag
277         * @param value String value of the attribute to be quoted
278         * @return This Element so calls can be chained.
279         */
280        public Element attribute(String attribute, long value)
281        {
282            if (attributeMap==null)
283                attributeMap=new Hashtable(10);
284            
285            attributeMap.put(attribute,Long.toString(value));
286            return this;
287        }
288    
289        /* ----------------------------------------------------------------- */
290        /** Convert Element to String.
291         * Uses write() to convert the HTML Element to a string.
292         * @return String of the HTML element
293         */
294        public String toString()
295        {
296            try{
297                StringWriter out = new StringWriter();
298                write(out);
299                out.flush();
300                return out.toString();
301            }
302            catch(IOException e){
303                Code.ignore(e);
304            }
305            return null;    
306        }
307        
308        /* ----------------------------------------------------------------- */
309        /** left justify.
310         * Convenience method equivalent to attribute("align","left"). Not
311         * applicable to all Elements.
312         */
313        public Element left()
314        {
315            return attribute(ALIGN,LEFT);
316        }
317        
318        /* ----------------------------------------------------------------- */
319        /** right justify.
320         * Convenience method equivalent to attribute("align","right"). Not
321         * applicable to all Elements.
322         */
323        public Element right()
324        {
325            return attribute(ALIGN,RIGHT);
326        }
327        
328        /* ----------------------------------------------------------------- */
329        /** Center.
330         * Convenience method equivalent to attribute("align","center"). Not
331         * applicable to all Elements.
332         */
333        public Element center()
334        {
335            return attribute(ALIGN,CENTER);
336        }
337        
338        /* ----------------------------------------------------------------- */
339        /** Top align.
340         * Convenience method equivalent to attribute("valign","top"). Not
341         * applicable to all Elements.
342         */
343        public Element top()
344        {
345            return attribute(VALIGN,TOP);
346        }
347        
348        /* ----------------------------------------------------------------- */
349        /** Bottom align.
350         * Convenience method equivalent to attribute("valign","bottom"). Not
351         * applicable to all Elements.
352         */
353        public Element bottom()
354        {
355            return attribute(VALIGN,BOTTOM);
356        }
357        
358        /* ----------------------------------------------------------------- */
359        /** Middle align.
360         * Convenience method equivalent to attribute("valign","middle"). Not
361         * applicable to all Elements.
362         */
363        public Element middle()
364        {
365            return attribute(VALIGN,MIDDLE);
366        }
367        
368        /* ----------------------------------------------------------------- */
369        /** set width.
370         * Convenience method equivalent to attribute("width",w). Not
371         * applicable to all Elements.
372         */
373        public Element width(int w)
374        {
375            width=w;
376            return attribute(WIDTH,w);
377        }
378        
379        /* ----------------------------------------------------------------- */
380        /** set width.
381         * Convenience method equivalent to attribute("width",w). Not
382         * applicable to all Elements.
383         */
384        public Element width(String w)
385        {
386            width=-1;
387            return attribute(WIDTH,w);
388        }
389        
390        /* ----------------------------------------------------------------- */
391        public int width()
392        {
393            return width;
394        }
395        
396        /* ----------------------------------------------------------------- */
397        /** set height.
398         * Convenience method equivalent to attribute("height",h). Not
399         * applicable to all Elements.
400         */
401        public Element height(int h)
402        {
403            height=h;
404            return attribute(HEIGHT,h);
405        }
406        
407        /* ----------------------------------------------------------------- */
408        /** set height.
409         * Convenience method equivalent to attribute("height",h). Not
410         * applicable to all Elements.
411         */
412        public Element height(String h)
413        {
414            height=-1;
415            return attribute(HEIGHT,h);
416        }
417        
418        /* ----------------------------------------------------------------- */
419        public int height()
420        {
421            return height;
422        }
423        
424        /* ----------------------------------------------------------------- */
425        /** set size.
426         * Convenience method equivalent to attribute("size",s). Not
427         * applicable to all Elements.
428         */
429        public Element size(int s)
430        {
431            size=s;
432            return attribute(SIZE,s);
433        }
434        
435        /* ----------------------------------------------------------------- */
436        /** set size.
437         * Convenience method equivalent to attribute("size",s). Not
438         * applicable to all Elements.
439         */
440        public Element size(String s)
441        {
442            size=-1;
443            return attribute(SIZE,s);
444        }
445        
446        /* ----------------------------------------------------------------- */
447        public int size()
448        {
449            return size;
450        }
451        
452        /* ----------------------------------------------------------------- */
453        /** set color.
454         * Convenience method equivalent to attribute("color",color). Not
455         * applicable to all Elements.
456         */
457        public Element color(String color)
458        {
459            return attribute(COLOR,color);
460        }
461        
462        /* ----------------------------------------------------------------- */
463        /** set BGCOLOR.
464         * Convenience method equivalent to attribute("bgcolor",color). Not
465         * applicable to all Elements.
466         */
467        public Element bgColor(String color)
468        {
469            return attribute(BGCOLOR,color);
470        }
471        
472        /* ----------------------------------------------------------------- */
473        /** set CSS CLASS.
474         */
475        public Element cssClass(String c)
476        {
477            return attribute(CLASS,c);
478        }
479    
480        /* ----------------------------------------------------------------- */
481        /** add a css CLASS
482         */
483        public Element addCssClass(String c)
484        {
485            return appendAttribute(CLASS," "+c);
486        }
487        
488        /* ----------------------------------------------------------------- */
489        /** set CSS ID.
490         * Convenience method equivalent to attribute("id",id).
491         */
492        public Element cssID(String id)
493        {
494            return attribute(ID,id);
495        }
496        
497        /* ----------------------------------------------------------------- */
498        /** set Style.
499         * Convenience method equivalent to attribute("style",style).
500         */
501        public Element style(String style)
502        {
503            return attribute(STYLE,style);
504        }
505    }
506    
507    
508    
509