package marubinotto.util.xml; import java.util.HashMap; import java.util.Map; import java.util.Stack; import marubinotto.util.Assert; public class XmlStringBuilder { private StringBuilder buffer = new StringBuilder(); private static class Element { public String name; public Element(String name) { this.name = name; } } private Stack<Element> elementStack = new Stack<Element>(); private Map<Element, Boolean> hasChildren = new HashMap<Element, Boolean>(); public static XmlStringBuilder create(String elementName) { XmlStringBuilder builder = new XmlStringBuilder(); return builder.element(elementName); } public XmlStringBuilder element(String name) { Assert.Arg.notNull(name, "name"); onChildAdded(); this.buffer.append("<"); this.buffer.append(name); this.elementStack.push(new Element(name)); return this; } public XmlStringBuilder attribute(String name, Object value) { Assert.Arg.notNull(name, "name"); Assert.Arg.notNull(value, "value"); this.buffer.append(" "); this.buffer.append(name); this.buffer.append("=\""); this.buffer.append(value.toString()); this.buffer.append("\""); return this; } public XmlStringBuilder text(String text) { Assert.Arg.notNull(text, "text"); onChildAdded(); this.buffer.append(text); return this; } public XmlStringBuilder end() { Element element = this.elementStack.pop(); if (hasChildren(element)) { this.buffer.append("</"); this.buffer.append(element.name); this.buffer.append(">"); } else { this.buffer.append("/>"); } return this; } public XmlStringBuilder endAll() { while (!elementStack.isEmpty()) { end(); } return this; } @Override public String toString() { endAll(); return this.buffer.toString(); } // Internal private boolean hasChildren(Element element) { Boolean flag = this.hasChildren.get(element); return flag != null && flag.equals(Boolean.TRUE); } private void onChildAdded() { if (this.elementStack.isEmpty()) return; Element parent = this.elementStack.peek(); if (!hasChildren(parent)) { this.buffer.append(">"); this.hasChildren.put(parent, Boolean.TRUE); } } }