// Copyright (C) 2003-2009 by Object Mentor, Inc. All rights reserved. // Released under the terms of the CPL Common Public License version 1.0. package fitnesse.html; import java.util.LinkedList; import java.util.List; public class HtmlTag extends HtmlElement { public LinkedList<HtmlElement> childTags = new LinkedList<HtmlElement>(); protected List<Attribute> attributes = new LinkedList<Attribute>(); protected String tagName = "youreIt"; public String tail; public String head; public boolean isInline; public HtmlTag(String tagName) { this.tagName = tagName; } public HtmlTag(String tagName, String content) { this(tagName); add(content); } public HtmlTag(String tagName, HtmlElement child) { this(tagName); add(child); } public String tagName() { return tagName; } public String html() { return html(0); } public String htmlInline() { isInline = true; return html(0); } public String html(int depth) { return new HtmlFormatter(depth).format(); } private boolean hasChildren() { return childTags.size() > 0; } public void add(String s) { add(new RawHtml(s)); } public void add(HtmlElement element) { childTags.add(element); } public void addAttribute(String key, String value) { attributes.add(new Attribute(key, value)); } public void use(String s) { use(new RawHtml(s)); } public void use(HtmlElement element) { childTags.clear(); add(element); } public String getAttribute(String key) { for (Attribute attribute : attributes) { if (key != null && key.equals(attribute.name)) return attribute.value; } return null; } protected String makeIndent(int depth) { String indent = ""; for (int i = 0; i < depth; i++) indent += '\t'; return indent; } public static class Attribute { public String name; public String value; public Attribute(String name, String value) { this.name = name; this.value = value; } } private class HtmlFormatter { private int depth; private boolean childTagWasMade; private boolean lastMadeChildWasNotTag; private boolean firstElement; public HtmlFormatter(int depth) { this.depth = depth; } public String format() { return makeTabs() + makeHead() + makeTag() + makeAttributes() + makeTagEnd() + makeChildren() + makeEndTag() + makeTail() + makeLineEnd(); } private String makeEndTag() { return hasChildren() ? "</" + tagName() + ">" : ""; } private String makeLineEnd() { return isInline ? "" : endl; } private String makeTail() { return tail == null ? "" : tail; } private String makeChildren() { String children = ""; if (hasChildren()) { children = makeChildrenWithoutTrailingIndent(); if (childTagWasMade && !isInline) children += makeTabs(); } return children; } private String makeChildrenWithoutTrailingIndent() { String children = ""; childTagWasMade = false; lastMadeChildWasNotTag = false; firstElement = true; for (HtmlElement element : childTags) { children += makeChildFromElement(element); firstElement = false; } return children; } private String makeChildFromElement(HtmlElement element) { boolean childIsTag = element instanceof HtmlTag; String child = childIsTag ? makeChildFromTag((HtmlTag) element) : element.html(); prepareForNextElement(childIsTag); return child; } private void prepareForNextElement(boolean childIsTag) { childTagWasMade |= childIsTag; lastMadeChildWasNotTag = !childIsTag; } private String makeChildFromTag(HtmlTag element) { return (childShouldStartWithNewLine() ? endl : "") + ((HtmlTag) element).html(depth + 1); } private boolean childShouldStartWithNewLine() { return (firstElement || lastMadeChildWasNotTag) && !isInline; } private String makeTagEnd() { return hasChildren() ? ">" : "/>"; } private String makeAttributes() { String attributes = ""; for (Attribute attribute : HtmlTag.this.attributes) { attributes += " " + attribute.name + "=\"" + attribute.value + "\""; } return attributes; } private String makeTag() { return "<" + tagName(); } private String makeHead() { return head == null ? "" : head; } private String makeTabs() { return makeIndent(depth); } } }