package org.lttpp.eemory.dom.impl; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; import java.util.Set; import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; import org.lttpp.eemory.Constants; import org.lttpp.eemory.Messages; import org.lttpp.eemory.dom.Attribute; import org.lttpp.eemory.dom.DOMException; import org.lttpp.eemory.dom.Document; import org.lttpp.eemory.dom.DocumentFragment; import org.lttpp.eemory.dom.DocumentType; import org.lttpp.eemory.dom.Element; import org.lttpp.eemory.dom.Node; import org.lttpp.eemory.dom.Text; import org.lttpp.eemory.util.ConstantsUtil; import org.lttpp.eemory.util.DomUtil; import org.lttpp.eemory.util.ListUtil; public class DocumentImpl extends NodeImpl implements Document { private boolean standalone; private String xmlVersion; private String encoding; protected DocumentImpl() { standalone = true; xmlVersion = Constants.XML_VERSION_1_0; encoding = CharEncoding.UTF_8; } @Override public Element getDocumentElement() { return (Element) getChildNodeByType(ELEMENT_NODE, DOCUMENT_FRAGMENT_NODE); } @Override public Element createElement(final String name) { ElementImpl e = new ElementImpl(name); e.setOwnerDocument(this); return e; } @Override public DocumentFragment createDocumentFragment() { DocumentFragmentImpl f = new DocumentFragmentImpl(); f.setOwnerDocument(this); return f; } @Override public Text createTextNode(final String text) { TextImpl t = new TextImpl(text); t.setOwnerDocument(this); return t; } @Override public Attribute createAttribute(final String name) { AttributeImpl a = new AttributeImpl(name); a.setOwnerDocument(this); return a; } @Override public DocumentType createDocumentType(final String name, final String publicId, final String systemId) { DocumentTypeImpl t = new DocumentTypeImpl(name, publicId, systemId); t.setOwnerDocument(this); return t; } @Override public List<Node> getElementsByTagName(final String name) { if (name.equals(ConstantsUtil.STAR)) { return getChildNodes(); } else { List<Node> matched = ListUtil.list(); Iterator<Node> iter = getChildNodes().iterator(); while (iter.hasNext()) { Node node = iter.next(); if (node.getNodeName().equals(name)) { matched.add(node); } if (node instanceof Element) { matched.addAll(((Element) node).getElementsByTagName(name)); } } return matched; } } @Override public String getInputEncoding() { return null; } @Override public String getXmlEncoding() { return encoding; } @Override public void setXMLEncoding(final String encoding) { this.encoding = encoding; } @Override public boolean getXmlStandalone() { return standalone; } @Override public void setXmlStandalone(final boolean standalone) { this.standalone = standalone; } @Override public String getXmlVersion() { return xmlVersion; } @Override public void setXmlVersion(final String xmlVersion) { this.xmlVersion = xmlVersion; } @Override public short getNodeType() { return Node.DOCUMENT_NODE; } @Override public boolean getStrictErrorChecking() { return true; } @Override public void setStrictErrorChecking(final boolean strictErrorChecking) { } @Override public Node importNode(final Node sourceNode, final boolean deep) throws DOMException { if (!canImport(sourceNode)) { throw new DOMException(DOMException.NOT_SUPPORTED_ERR, Messages.DOM_Error0); } Node clonedNode = sourceNode.cloneNode(deep); ((NodeImpl) clonedNode).setParentNode(null); if (clonedNode instanceof Attribute) { ((AttributeImpl) clonedNode).setOwnerElement(null); } impOrt(clonedNode); return clonedNode; } private void impOrt(final Node clonedNode) { adopt(clonedNode); } private boolean canImport(final Node sourceNode) { return canAdopt(sourceNode); } @Override public Node adoptNode(final Node sourceNode) throws DOMException { if (canAdopt(sourceNode)) { throw new DOMException(DOMException.NOT_SUPPORTED_ERR, Messages.DOM_Error1); } Node parent = sourceNode.getParentNode(); if (parent != null) { parent.removeChild(sourceNode); ((NodeImpl) sourceNode).setParentNode(null); } if (sourceNode instanceof Attribute) { ((AttributeImpl) sourceNode).setOwnerElement(null); } adopt(sourceNode); return sourceNode; } private void adopt(final Node sourceNode) { ((NodeImpl) sourceNode).setOwnerDocument(this); Set<Entry<String, Node>> set = sourceNode.getAttributes().entrySet(); for (Entry<String, Node> e : set) { adopt(e.getValue()); } for (Node n : sourceNode.getChildNodes()) { adopt(n); } } private boolean canAdopt(final Node sourceNode) { return sourceNode.getNodeType() != DOCUMENT_NODE && sourceNode.getNodeType() != DOCUMENT_TYPE_NODE; } @Override public void normalizeDocument() { normalize(); } @Override public String toString() { String standalone = this.standalone ? StringUtils.EMPTY : StringUtils.SPACE + Constants.STANDALONE + ConstantsUtil.EQUAL + ConstantsUtil.DOUBLE_QUOTE + Constants.NO + ConstantsUtil.DOUBLE_QUOTE; String head = ConstantsUtil.LEFT_ANGLE_BRACKET + ConstantsUtil.QUESTION_MARK + Constants.XML + StringUtils.SPACE + Constants.VERSION + ConstantsUtil.EQUAL + ConstantsUtil.DOUBLE_QUOTE + xmlVersion + ConstantsUtil.DOUBLE_QUOTE + StringUtils.SPACE + Constants.ENCODING + ConstantsUtil.EQUAL + ConstantsUtil.DOUBLE_QUOTE + encoding + ConstantsUtil.DOUBLE_QUOTE + standalone + ConstantsUtil.QUESTION_MARK + ConstantsUtil.RIGHT_ANGLE_BRACKET; String body = StringUtils.EMPTY; Node doctype = null; for (Node child : getChildNodes()) { if (child == null) { continue; } if (child.getNodeType() == Node.DOCUMENT_TYPE_NODE) { doctype = child; } else { body += child.toString(); } } body = DomUtil.toString(doctype) + body; return head + body; } }