package org.concordion.api; import java.util.ArrayList; import java.util.List; import nu.xom.Attribute; import nu.xom.Elements; import nu.xom.Node; import nu.xom.Nodes; import nu.xom.XPathContext; public final class Element { public static final String XHTML_PREFIX = "xhtml"; public static final String XHTML_URI = "http://www.w3.org/1999/xhtml"; private static XPathContext namespaceMappings = new XPathContext(XHTML_PREFIX, XHTML_URI); private final nu.xom.Element xomElement; public Element(String name) { this(new nu.xom.Element(name)); } /** * For internal use only. */ public Element(nu.xom.Element xomElement) { this.xomElement = xomElement; } public String getText() { return xomElement.getValue(); } public Element addStyleClass(String styleClass) { String currentClass = getAttributeValue("class"); if (currentClass != null) { styleClass = currentClass + " " + styleClass; } addAttribute("class", styleClass); return this; } public Element appendNonBreakingSpace() { return appendText("\u00A0"); } public Element appendText(String text) { xomElement.appendChild(new nu.xom.Text(text)); return this; } public Element appendNonBreakingSpaceIfBlank() { if (isBlank()) { appendNonBreakingSpace(); } return this; } public Element prependText(String text) { xomElement.insertChild(new nu.xom.Text(text), 0); return this; } public Element prependChild(Element element) { xomElement.insertChild(element.xomElement, 0); return this; } public void appendChild(Element element) { xomElement.appendChild(element.xomElement); } private Node[] getChildNodes() { Node[] childNodes = new Node[xomElement.getChildCount()]; for (int i = 0; i < xomElement.getChildCount(); i++) { childNodes[i] = xomElement.getChild(i); } return childNodes; } public void moveChildrenTo(Element element) { for (Node childNode : getChildNodes()) { childNode.detach(); element.xomElement.appendChild(childNode); } } public Element setId(String id) { addAttribute("id", id); return this; } public Element addAttribute(String localName, String value) { xomElement.addAttribute(new Attribute(localName, value)); return this; } public String getAttributeValue(String name) { return xomElement.getAttributeValue(name); } private boolean isBlank() { return getText().trim().equals(""); } public String toXML() { return xomElement.toXML(); } public Element getRootElement() { return new Element(xomElement.getDocument().getRootElement()); } public Element getFirstChildElement(String name) { nu.xom.Element body = xomElement.getFirstChildElement(name); if (body == null) { return null; } return new Element(body); } public boolean hasChildren() { return xomElement.getChildCount() > 0; } @Override public int hashCode() { return xomElement.hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Element other = (Element) obj; if (xomElement == null) { if (other.xomElement != null) { return false; } } else if (!xomElement.equals(other.xomElement)) { return false; } return true; } public String getLocalName() { return xomElement.getLocalName(); } public boolean isNamed(String name) { return getLocalName().equals(name); } public Element[] getDescendantElements(String name) { List<Element> descendants = new ArrayList<Element>(); Nodes nodes = xomElement.query(xpathForElementName(name), namespaceMappings); for (int i = 0; i < nodes.size(); i++) { descendants.add(new Element((nu.xom.Element)nodes.get(i))); } descendants.remove(this); return descendants.toArray(new Element[0]); } private String xpathForElementName(String name) { return ".//" + name + " | " + ".//" + XHTML_PREFIX + ":" + name; } public Element[] getChildElements(String name) { return wrapXomElements(xomElement.getChildElements(name)); } public Element[] getChildElements() { return wrapXomElements(xomElement.getChildElements()); } private Element[] wrapXomElements(Elements xomElements) { int count = xomElements.size(); Element[] elements = new Element[count]; for (int i = 0; i < count; i++) { elements[i] = new Element(xomElements.get(i)); } return elements; } public Element getFirstDescendantNamed(String name) { Element[] descendantElements = getDescendantElements(name); return descendantElements.length == 0 ? null : descendantElements[0]; } public void appendSister(Element element) { nu.xom.Element xomParentElement = (nu.xom.Element) xomElement.getParent(); int elementIndex = xomParentElement.indexOf(xomElement); xomParentElement.insertChild(element.xomElement, elementIndex + 1); } }