Wed, 01 Dec 2010 11:02:38 -0800
6851834: Javadoc doclet needs a structured approach to generate the output HTML.
Reviewed-by: jjg
1 /*
2 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.doclets.formats.html.markup;
28 import java.util.*;
29 import com.sun.tools.doclets.internal.toolkit.Content;
30 import com.sun.tools.doclets.internal.toolkit.util.*;
32 /**
33 * Class for generating HTML tree for javadoc output.
34 *
35 * @author Bhavesh Patel
36 */
37 public class HtmlTree extends Content {
39 private HtmlTag htmlTag;
40 private Map<HtmlAttr,String> attrs = Collections.<HtmlAttr,String>emptyMap();
41 private List<Content> content = Collections.<Content>emptyList();
42 public static final Content EMPTY = new StringContent("");
44 /**
45 * Constructor to construct HtmlTree object.
46 *
47 * @param tag HTML tag for the HtmlTree object
48 */
49 public HtmlTree(HtmlTag tag) {
50 htmlTag = nullCheck(tag);
51 }
53 /**
54 * Constructor to construct HtmlTree object.
55 *
56 * @param tag HTML tag for the HtmlTree object
57 * @param contents contents to be added to the tree
58 */
59 public HtmlTree(HtmlTag tag, Content... contents) {
60 this(tag);
61 for (Content content: contents)
62 addContent(content);
63 }
65 /**
66 * Adds an attribute for the HTML tag.
67 *
68 * @param attrName name of the attribute
69 * @param attrValue value of the attribute
70 */
71 public void addAttr(HtmlAttr attrName, String attrValue) {
72 if (attrs.isEmpty())
73 attrs = new LinkedHashMap<HtmlAttr,String>();
74 attrs.put(nullCheck(attrName), nullCheck(attrValue));
75 }
77 /**
78 * Adds a style for the HTML tag.
79 *
80 * @param style style to be added
81 */
82 public void addStyle(HtmlStyle style) {
83 addAttr(HtmlAttr.CLASS, style.toString());
84 }
86 /**
87 * Adds content for the HTML tag.
88 *
89 * @param tagContent tag content to be added
90 */
91 public void addContent(Content tagContent) {
92 if (tagContent == HtmlTree.EMPTY || tagContent.isValid()) {
93 if (content.isEmpty())
94 content = new ArrayList<Content>();
95 content.add(tagContent);
96 }
97 }
99 /**
100 * This method adds a string content to the htmltree. If the last content member
101 * added is a StringContent, append the string to that StringContent or else
102 * create a new StringContent and add it to the html tree.
103 *
104 * @param stringContent string content that needs to be added
105 */
106 public void addContent(String stringContent) {
107 if (!content.isEmpty()) {
108 Content lastContent = content.get(content.size() - 1);
109 if (lastContent instanceof StringContent)
110 lastContent.addContent(stringContent);
111 else
112 addContent(new StringContent(stringContent));
113 }
114 else
115 addContent(new StringContent(stringContent));
116 }
118 /**
119 * Generates an HTML anchor tag.
120 *
121 * @param ref reference url for the anchor tag
122 * @param body content for the anchor tag
123 * @return an HtmlTree object
124 */
125 public static HtmlTree A(String ref, Content body) {
126 HtmlTree htmltree = new HtmlTree(HtmlTag.A, nullCheck(body));
127 htmltree.addAttr(HtmlAttr.HREF, nullCheck(ref));
128 return htmltree;
129 }
131 /**
132 * Generates an HTML anchor tag with name attribute and content.
133 *
134 * @param name name for the anchor tag
135 * @param body content for the anchor tag
136 * @return an HtmlTree object
137 */
138 public static HtmlTree A_NAME(String name, Content body) {
139 HtmlTree htmltree = HtmlTree.A_NAME(name);
140 htmltree.addContent(nullCheck(body));
141 return htmltree;
142 }
144 /**
145 * Generates an HTML anchor tag with name attribute.
146 *
147 * @param name name for the anchor tag
148 * @return an HtmlTree object
149 */
150 public static HtmlTree A_NAME(String name) {
151 HtmlTree htmltree = new HtmlTree(HtmlTag.A);
152 htmltree.addAttr(HtmlAttr.NAME, nullCheck(name));
153 return htmltree;
154 }
156 /**
157 * Generates a CAPTION tag with some content.
158 *
159 * @param body content for the tag
160 * @return an HtmlTree object for the CAPTION tag
161 */
162 public static HtmlTree CAPTION(Content body) {
163 HtmlTree htmltree = new HtmlTree(HtmlTag.CAPTION, nullCheck(body));
164 return htmltree;
165 }
167 /**
168 * Generates a CODE tag with some content.
169 *
170 * @param body content for the tag
171 * @return an HtmlTree object for the CODE tag
172 */
173 public static HtmlTree CODE(Content body) {
174 HtmlTree htmltree = new HtmlTree(HtmlTag.CODE, nullCheck(body));
175 return htmltree;
176 }
178 /**
179 * Generates a DD tag with some content.
180 *
181 * @param body content for the tag
182 * @return an HtmlTree object for the DD tag
183 */
184 public static HtmlTree DD(Content body) {
185 HtmlTree htmltree = new HtmlTree(HtmlTag.DD, nullCheck(body));
186 return htmltree;
187 }
189 /**
190 * Generates a DL tag with some content.
191 *
192 * @param body content for the tag
193 * @return an HtmlTree object for the DL tag
194 */
195 public static HtmlTree DL(Content body) {
196 HtmlTree htmltree = new HtmlTree(HtmlTag.DL, nullCheck(body));
197 return htmltree;
198 }
200 /**
201 * Generates a DIV tag with the style class attributes. It also encloses
202 * a content.
203 *
204 * @param styleClass stylesheet class for the tag
205 * @param body content for the tag
206 * @return an HtmlTree object for the DIV tag
207 */
208 public static HtmlTree DIV(HtmlStyle styleClass, Content body) {
209 HtmlTree htmltree = new HtmlTree(HtmlTag.DIV, nullCheck(body));
210 if (styleClass != null)
211 htmltree.addStyle(styleClass);
212 return htmltree;
213 }
215 /**
216 * Generates a DIV tag with some content.
217 *
218 * @param body content for the tag
219 * @return an HtmlTree object for the DIV tag
220 */
221 public static HtmlTree DIV(Content body) {
222 return DIV(null, body);
223 }
225 /**
226 * Generates a DT tag with some content.
227 *
228 * @param body content for the tag
229 * @return an HtmlTree object for the DT tag
230 */
231 public static HtmlTree DT(Content body) {
232 HtmlTree htmltree = new HtmlTree(HtmlTag.DT, nullCheck(body));
233 return htmltree;
234 }
236 /**
237 * Generates a EM tag with some content.
238 *
239 * @param body content to be added to the tag
240 * @return an HtmlTree object for the EM tag
241 */
242 public static HtmlTree EM(Content body) {
243 HtmlTree htmltree = new HtmlTree(HtmlTag.EM, nullCheck(body));
244 return htmltree;
245 }
247 /**
248 * Generates a FRAME tag.
249 *
250 * @param src the url of the document to be shown in the frame
251 * @param name specifies the name of the frame
252 * @param title the title for the frame
253 * @param scrolling specifies whether to display scrollbars in the frame
254 * @return an HtmlTree object for the FRAME tag
255 */
256 public static HtmlTree FRAME(String src, String name, String title, String scrolling) {
257 HtmlTree htmltree = new HtmlTree(HtmlTag.FRAME);
258 htmltree.addAttr(HtmlAttr.SRC, nullCheck(src));
259 htmltree.addAttr(HtmlAttr.NAME, nullCheck(name));
260 htmltree.addAttr(HtmlAttr.TITLE, nullCheck(title));
261 if (scrolling != null)
262 htmltree.addAttr(HtmlAttr.SCROLLING, scrolling);
263 return htmltree;
264 }
266 /**
267 * Generates a Frame tag.
268 *
269 * @param src the url of the document to be shown in the frame
270 * @param name specifies the name of the frame
271 * @param title the title for the frame
272 * @return an HtmlTree object for the SPAN tag
273 */
274 public static HtmlTree FRAME(String src, String name, String title) {
275 return FRAME(src, name, title, null);
276 }
278 /**
279 * Generates a FRAMESET tag.
280 *
281 * @param cols the size of columns in the frameset
282 * @param rows the size of rows in the frameset
283 * @param title the title for the frameset
284 * @param onload the script to run when the document loads
285 * @return an HtmlTree object for the FRAMESET tag
286 */
287 public static HtmlTree FRAMESET(String cols, String rows, String title, String onload) {
288 HtmlTree htmltree = new HtmlTree(HtmlTag.FRAMESET);
289 if (cols != null)
290 htmltree.addAttr(HtmlAttr.COLS, cols);
291 if (rows != null)
292 htmltree.addAttr(HtmlAttr.ROWS, rows);
293 htmltree.addAttr(HtmlAttr.TITLE, nullCheck(title));
294 htmltree.addAttr(HtmlAttr.ONLOAD, nullCheck(onload));
295 return htmltree;
296 }
298 /**
299 * Generates a heading tag (h1 to h6) with the title and style class attributes. It also encloses
300 * a content.
301 *
302 * @param headingTag the heading tag to be generated
303 * @param printTitle true if title for the tag needs to be printed else false
304 * @param styleClass stylesheet class for the tag
305 * @param body content for the tag
306 * @return an HtmlTree object for the tag
307 */
308 public static HtmlTree HEADING(HtmlTag headingTag, boolean printTitle,
309 HtmlStyle styleClass, Content body) {
310 HtmlTree htmltree = new HtmlTree(headingTag, nullCheck(body));
311 if (printTitle)
312 htmltree.addAttr(HtmlAttr.TITLE, Util.stripHtml(body.toString()));
313 if (styleClass != null)
314 htmltree.addStyle(styleClass);
315 return htmltree;
316 }
318 /**
319 * Generates a heading tag (h1 to h6) with style class attribute. It also encloses
320 * a content.
321 *
322 * @param headingTag the heading tag to be generated
323 * @param styleClass stylesheet class for the tag
324 * @param body content for the tag
325 * @return an HtmlTree object for the tag
326 */
327 public static HtmlTree HEADING(HtmlTag headingTag, HtmlStyle styleClass, Content body) {
328 return HEADING(headingTag, false, styleClass, body);
329 }
331 /**
332 * Generates a heading tag (h1 to h6) with the title attribute. It also encloses
333 * a content.
334 *
335 * @param headingTag the heading tag to be generated
336 * @param printTitle true if the title for the tag needs to be printed else false
337 * @param body content for the tag
338 * @return an HtmlTree object for the tag
339 */
340 public static HtmlTree HEADING(HtmlTag headingTag, boolean printTitle, Content body) {
341 return HEADING(headingTag, printTitle, null, body);
342 }
344 /**
345 * Generates a heading tag (h1 to h6) with some content.
346 *
347 * @param headingTag the heading tag to be generated
348 * @param body content for the tag
349 * @return an HtmlTree object for the tag
350 */
351 public static HtmlTree HEADING(HtmlTag headingTag, Content body) {
352 return HEADING(headingTag, false, null, body);
353 }
355 /**
356 * Generates an HTML tag with lang attribute. It also adds head and body
357 * content to the HTML tree.
358 *
359 * @param lang language for the HTML document
360 * @param head head for the HTML tag
361 * @param body body for the HTML tag
362 * @return an HtmlTree object for the HTML tag
363 */
364 public static HtmlTree HTML(String lang, Content head, Content body) {
365 HtmlTree htmltree = new HtmlTree(HtmlTag.HTML, nullCheck(head), nullCheck(body));
366 htmltree.addAttr(HtmlAttr.LANG, nullCheck(lang));
367 return htmltree;
368 }
370 /**
371 * Generates a I tag with some content.
372 *
373 * @param body content for the tag
374 * @return an HtmlTree object for the I tag
375 */
376 public static HtmlTree I(Content body) {
377 HtmlTree htmltree = new HtmlTree(HtmlTag.I, nullCheck(body));
378 return htmltree;
379 }
381 /**
382 * Generates a LI tag with some content.
383 *
384 * @param body content for the tag
385 * @return an HtmlTree object for the LI tag
386 */
387 public static HtmlTree LI(Content body) {
388 return LI(null, body);
389 }
391 /**
392 * Generates a LI tag with some content.
393 *
394 * @param styleClass style for the tag
395 * @param body content for the tag
396 * @return an HtmlTree object for the LI tag
397 */
398 public static HtmlTree LI(HtmlStyle styleClass, Content body) {
399 HtmlTree htmltree = new HtmlTree(HtmlTag.LI, nullCheck(body));
400 if (styleClass != null)
401 htmltree.addStyle(styleClass);
402 return htmltree;
403 }
405 /**
406 * Generates a LINK tag with the rel, type, href and title attributes.
407 *
408 * @param rel relevance of the link
409 * @param type type of link
410 * @param href the path for the link
411 * @param title title for the link
412 * @return an HtmlTree object for the LINK tag
413 */
414 public static HtmlTree LINK(String rel, String type, String href, String title) {
415 HtmlTree htmltree = new HtmlTree(HtmlTag.LINK);
416 htmltree.addAttr(HtmlAttr.REL, nullCheck(rel));
417 htmltree.addAttr(HtmlAttr.TYPE, nullCheck(type));
418 htmltree.addAttr(HtmlAttr.HREF, nullCheck(href));
419 htmltree.addAttr(HtmlAttr.TITLE, nullCheck(title));
420 return htmltree;
421 }
423 /**
424 * Generates a META tag with the http-equiv, content and charset attributes.
425 *
426 * @param http-equiv http equiv attribute for the META tag
427 * @param content type of content
428 * @param charset character set used
429 * @return an HtmlTree object for the META tag
430 */
431 public static HtmlTree META(String httpEquiv, String content, String charSet) {
432 HtmlTree htmltree = new HtmlTree(HtmlTag.META);
433 htmltree.addAttr(HtmlAttr.HTTP_EQUIV, nullCheck(httpEquiv));
434 htmltree.addAttr(HtmlAttr.CONTENT, nullCheck(content));
435 htmltree.addAttr(HtmlAttr.CHARSET, nullCheck(charSet));
436 return htmltree;
437 }
439 /**
440 * Generates a META tag with the name and content attributes.
441 *
442 * @param name name attribute
443 * @param content type of content
444 * @return an HtmlTree object for the META tag
445 */
446 public static HtmlTree META(String name, String content) {
447 HtmlTree htmltree = new HtmlTree(HtmlTag.META);
448 htmltree.addAttr(HtmlAttr.NAME, nullCheck(name));
449 htmltree.addAttr(HtmlAttr.CONTENT, nullCheck(content));
450 return htmltree;
451 }
453 /**
454 * Generates a NOSCRIPT tag with some content.
455 *
456 * @param body content of the noscript tag
457 * @return an HtmlTree object for the NOSCRIPT tag
458 */
459 public static HtmlTree NOSCRIPT(Content body) {
460 HtmlTree htmltree = new HtmlTree(HtmlTag.NOSCRIPT, nullCheck(body));
461 return htmltree;
462 }
464 /**
465 * Generates a P tag with some content.
466 *
467 * @param body content of the Paragraph tag
468 * @return an HtmlTree object for the P tag
469 */
470 public static HtmlTree P(Content body) {
471 return P(null, body);
472 }
474 /**
475 * Generates a P tag with some content.
476 *
477 * @param styleClass style of the Paragraph tag
478 * @param body content of the Paragraph tag
479 * @return an HtmlTree object for the P tag
480 */
481 public static HtmlTree P(HtmlStyle styleClass, Content body) {
482 HtmlTree htmltree = new HtmlTree(HtmlTag.P, nullCheck(body));
483 if (styleClass != null)
484 htmltree.addStyle(styleClass);
485 return htmltree;
486 }
488 /**
489 * Generates a SMALL tag with some content.
490 *
491 * @param body content for the tag
492 * @return an HtmlTree object for the SMALL tag
493 */
494 public static HtmlTree SMALL(Content body) {
495 HtmlTree htmltree = new HtmlTree(HtmlTag.SMALL, nullCheck(body));
496 return htmltree;
497 }
499 /**
500 * Generates a STRONG tag with some content.
501 *
502 * @param body content for the tag
503 * @return an HtmlTree object for the STRONG tag
504 */
505 public static HtmlTree STRONG(Content body) {
506 HtmlTree htmltree = new HtmlTree(HtmlTag.STRONG, nullCheck(body));
507 return htmltree;
508 }
510 /**
511 * Generates a SPAN tag with some content.
512 *
513 * @param body content for the tag
514 * @return an HtmlTree object for the SPAN tag
515 */
516 public static HtmlTree SPAN(Content body) {
517 return SPAN(null, body);
518 }
520 /**
521 * Generates a SPAN tag with style class attribute and some content.
522 *
523 * @param styleClass style class for the tag
524 * @param body content for the tag
525 * @return an HtmlTree object for the SPAN tag
526 */
527 public static HtmlTree SPAN(HtmlStyle styleClass, Content body) {
528 HtmlTree htmltree = new HtmlTree(HtmlTag.SPAN, nullCheck(body));
529 if (styleClass != null)
530 htmltree.addStyle(styleClass);
531 return htmltree;
532 }
534 /**
535 * Generates a Table tag with border, width and summary attributes and
536 * some content.
537 *
538 * @param border border for the table
539 * @param width width of the table
540 * @param summary summary for the table
541 * @param body content for the table
542 * @return an HtmlTree object for the TABLE tag
543 */
544 public static HtmlTree TABLE(int border, int width, String summary,
545 Content body) {
546 HtmlTree htmltree = new HtmlTree(HtmlTag.TABLE, nullCheck(body));
547 htmltree.addAttr(HtmlAttr.BORDER, Integer.toString(border));
548 htmltree.addAttr(HtmlAttr.WIDTH, Integer.toString(width));
549 htmltree.addAttr(HtmlAttr.SUMMARY, nullCheck(summary));
550 return htmltree;
551 }
553 /**
554 * Generates a Table tag with style class, border, cell padding,
555 * cellspacing and summary attributes and some content.
556 *
557 * @param styleClass style of the table
558 * @param border border for the table
559 * @param cellPadding cell padding for the table
560 * @param cellSpacing cell spacing for the table
561 * @param summary summary for the table
562 * @param body content for the table
563 * @return an HtmlTree object for the TABLE tag
564 */
565 public static HtmlTree TABLE(HtmlStyle styleClass, int border, int cellPadding,
566 int cellSpacing, String summary, Content body) {
567 HtmlTree htmltree = new HtmlTree(HtmlTag.TABLE, nullCheck(body));
568 if (styleClass != null)
569 htmltree.addStyle(styleClass);
570 htmltree.addAttr(HtmlAttr.BORDER, Integer.toString(border));
571 htmltree.addAttr(HtmlAttr.CELLPADDING, Integer.toString(cellPadding));
572 htmltree.addAttr(HtmlAttr.CELLSPACING, Integer.toString(cellSpacing));
573 htmltree.addAttr(HtmlAttr.SUMMARY, nullCheck(summary));
574 return htmltree;
575 }
577 /**
578 * Generates a Table tag with border, cell padding,
579 * cellspacing and summary attributes and some content.
580 *
581 * @param border border for the table
582 * @param cellPadding cell padding for the table
583 * @param cellSpacing cell spacing for the table
584 * @param summary summary for the table
585 * @param body content for the table
586 * @return an HtmlTree object for the TABLE tag
587 */
588 public static HtmlTree TABLE(int border, int cellPadding,
589 int cellSpacing, String summary, Content body) {
590 return TABLE(null, border, cellPadding, cellSpacing, summary, body);
591 }
593 /**
594 * Generates a TD tag with style class attribute and some content.
595 *
596 * @param styleClass style for the tag
597 * @param body content for the tag
598 * @return an HtmlTree object for the TD tag
599 */
600 public static HtmlTree TD(HtmlStyle styleClass, Content body) {
601 HtmlTree htmltree = new HtmlTree(HtmlTag.TD, nullCheck(body));
602 if (styleClass != null)
603 htmltree.addStyle(styleClass);
604 return htmltree;
605 }
607 /**
608 * Generates a TD tag for an HTML table with some content.
609 *
610 * @param body content for the tag
611 * @return an HtmlTree object for the TD tag
612 */
613 public static HtmlTree TD(Content body) {
614 return TD(null, body);
615 }
617 /**
618 * Generates a TH tag with style class and scope attributes and some content.
619 *
620 * @param styleClass style for the tag
621 * @param scope scope of the tag
622 * @param body content for the tag
623 * @return an HtmlTree object for the TH tag
624 */
625 public static HtmlTree TH(HtmlStyle styleClass, String scope, Content body) {
626 HtmlTree htmltree = new HtmlTree(HtmlTag.TH, nullCheck(body));
627 if (styleClass != null)
628 htmltree.addStyle(styleClass);
629 htmltree.addAttr(HtmlAttr.SCOPE, nullCheck(scope));
630 return htmltree;
631 }
633 /**
634 * Generates a TH tag with scope attribute and some content.
635 *
636 * @param scope scope of the tag
637 * @param body content for the tag
638 * @return an HtmlTree object for the TH tag
639 */
640 public static HtmlTree TH(String scope, Content body) {
641 return TH(null, scope, body);
642 }
644 /**
645 * Generates a TITLE tag with some content.
646 *
647 * @param body content for the tag
648 * @return an HtmlTree object for the TITLE tag
649 */
650 public static HtmlTree TITLE(Content body) {
651 HtmlTree htmltree = new HtmlTree(HtmlTag.TITLE, nullCheck(body));
652 return htmltree;
653 }
655 /**
656 * Generates a TR tag for an HTML table with some content.
657 *
658 * @param body content for the tag
659 * @return an HtmlTree object for the TR tag
660 */
661 public static HtmlTree TR(Content body) {
662 HtmlTree htmltree = new HtmlTree(HtmlTag.TR, nullCheck(body));
663 return htmltree;
664 }
666 /**
667 * Generates a UL tag with the style class attribute and some content.
668 *
669 * @param styleClass style for the tag
670 * @param body content for the tag
671 * @return an HtmlTree object for the UL tag
672 */
673 public static HtmlTree UL(HtmlStyle styleClass, Content body) {
674 HtmlTree htmltree = new HtmlTree(HtmlTag.UL, nullCheck(body));
675 htmltree.addStyle(nullCheck(styleClass));
676 return htmltree;
677 }
679 /**
680 * {@inheritDoc}
681 */
682 public boolean isEmpty() {
683 return (!hasContent() && !hasAttrs());
684 }
686 /**
687 * Returns true if the HTML tree has content.
688 *
689 * @return true if the HTML tree has content else return false
690 */
691 public boolean hasContent() {
692 return (!content.isEmpty());
693 }
695 /**
696 * Returns true if the HTML tree has attributes.
697 *
698 * @return true if the HTML tree has attributes else return false
699 */
700 public boolean hasAttrs() {
701 return (!attrs.isEmpty());
702 }
704 /**
705 * Returns true if the HTML tree has a specific attribute.
706 *
707 * @param attrName name of the attribute to check within the HTML tree
708 * @return true if the HTML tree has the specified attribute else return false
709 */
710 public boolean hasAttr(HtmlAttr attrName) {
711 return (attrs.containsKey(attrName));
712 }
714 /**
715 * Returns true if the HTML tree is valid. This check is more specific to
716 * standard doclet and not exactly similar to W3C specifications. But it
717 * ensures HTML validation.
718 *
719 * @return true if the HTML tree is valid
720 */
721 public boolean isValid() {
722 switch (htmlTag) {
723 case A :
724 return (hasAttr(HtmlAttr.NAME) || (hasAttr(HtmlAttr.HREF) && hasContent()));
725 case BR :
726 return (!hasContent() && (!hasAttrs() || hasAttr(HtmlAttr.CLEAR)));
727 case FRAME :
728 return (hasAttr(HtmlAttr.SRC) && !hasContent());
729 case HR :
730 return (!hasContent());
731 case IMG :
732 return (hasAttr(HtmlAttr.SRC) && hasAttr(HtmlAttr.ALT) && !hasContent());
733 case LINK :
734 return (hasAttr(HtmlAttr.HREF) && !hasContent());
735 case META :
736 return (hasAttr(HtmlAttr.CONTENT) && !hasContent());
737 default :
738 return hasContent();
739 }
740 }
742 /**
743 * Returns true if the element is an inline element.
744 *
745 * @return true if the HTML tag is an inline element
746 */
747 public boolean isInline() {
748 return (htmlTag.blockType == HtmlTag.BlockType.INLINE);
749 }
751 /**
752 * {@inheritDoc}
753 */
754 public void write(StringBuilder contentBuilder) {
755 if (!isInline() && !endsWithNewLine(contentBuilder))
756 contentBuilder.append("\n");
757 String tagString = htmlTag.toString();
758 contentBuilder.append("<" + tagString);
759 Iterator<HtmlAttr> iterator = attrs.keySet().iterator();
760 HtmlAttr key;
761 String value = "";
762 while (iterator.hasNext()) {
763 key = iterator.next();
764 value = attrs.get(key);
765 contentBuilder.append(" " + key.toString());
766 if (!value.isEmpty())
767 contentBuilder.append("=\"" + value + "\"");
768 }
769 contentBuilder.append(">");
770 for (Content c : content)
771 c.write(contentBuilder);
772 if (htmlTag.endTagRequired())
773 contentBuilder.append("</" + tagString + ">");
774 if (!isInline())
775 contentBuilder.append("\n");
776 }
777 }