View Javadoc

1   /*
2    * Copyright 2010-2013 Capgemini
3    * Licensed under the Apache License, Version 2.0 (the "License"); 
4    * you may not use this file except in compliance with the License. 
5    * You may obtain a copy of the License at 
6    * 
7    * http://www.apache.org/licenses/LICENSE-2.0 
8    * 
9    * Unless required by applicable law or agreed to in writing, software 
10   * distributed under the License is distributed on an "AS IS" BASIS, 
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
12   * See the License for the specific language governing permissions and 
13   * limitations under the License. 
14   * 
15   */
16  package org.xmlfield.core.impl.dom;
17  
18  import static com.google.common.base.Preconditions.checkArgument;
19  import static com.google.common.base.Preconditions.checkNotNull;
20  import static org.apache.commons.lang.StringUtils.substringAfter;
21  
22  import org.apache.commons.lang.StringUtils;
23  import org.w3c.dom.Attr;
24  import org.w3c.dom.Document;
25  import org.w3c.dom.Element;
26  import org.w3c.dom.NamedNodeMap;
27  import org.w3c.dom.Node;
28  import org.xmlfield.core.api.XmlFieldNode;
29  import org.xmlfield.core.api.XmlFieldNodeList;
30  import org.xmlfield.core.api.XmlFieldNodeModifier;
31  import org.xmlfield.core.impl.dom.cleanup.InputSanitizer;
32  import org.xmlfield.core.internal.NamespaceMap;
33  import org.xmlfield.core.internal.XPathUtils;
34  
35  /**
36   * Default xml field node modifier implementation
37   * <p>
38   * DomNodeModifier is thread safe.
39   * 
40   * @author Guillaume Mary <guillaume.mary@capgemini.com>
41   * 
42   */
43  public class DomNodeModifier implements XmlFieldNodeModifier {
44  
45  	private static Element _createElement(final NamespaceMap namespaces,
46  			final Document document, final String elementName) {
47  
48  		String prefix = XPathUtils.getElementPrefix(elementName);
49  
50  		if (prefix == null) {
51  			return document.createElement(elementName);
52  		}
53  
54  		if (namespaces == null) {
55  			throw new IllegalArgumentException("No namespaceURI defined for <"
56  					+ elementName + ">");
57  		}
58  
59  		String uri = namespaces.get(prefix);
60  
61  		if (uri == null) {
62  			throw new IllegalArgumentException("No namespaceURI defined for <"
63  					+ elementName + ">");
64  		}
65  
66  		String localName = substringAfter(elementName, ":");
67  
68  		return document.createElementNS(uri, localName);
69  
70  	}
71  
72  	@Override
73  	public void createAttribute(XmlFieldNode node, String attributeName,
74  			String textContent) {
75  		checkNotNull(node, "node");
76  		checkNotNull(attributeName, "attributeName");
77  		final Document document = getNodeDocument((Node) node.getNode());
78  
79  		final Attr attribute = document.createAttribute(attributeName);
80  
81  		((Element) node.getNode()).setAttributeNode(attribute);
82  
83  		if (textContent != null) {
84  
85  			attribute.setTextContent(InputSanitizer.sanitizeText(textContent));
86  		}
87  
88  	}
89  
90  	@Override
91  	public XmlFieldNode createElement(NamespaceMap namespaces,
92  			XmlFieldNode node, String elementName) {
93  		return createElement(namespaces, node, elementName, null);
94  	}
95  
96  	@Override
97  	public XmlFieldNode createElement(NamespaceMap namespaces,
98  			XmlFieldNode node, String elementName, String textContent) {
99  		checkNotNull(node, "node");
100 		checkArgument(node.getNode() instanceof Node);
101 		if (StringUtils.isEmpty(elementName)) {
102 			return node;
103 		}
104 
105 		final Document document = getNodeDocument((Node) node.getNode());
106 
107 		final Element element = _createElement(namespaces, document,
108 				elementName);
109 
110 		((Node) node.getNode()).appendChild(element);
111 
112 		if (textContent != null) {
113 
114 			element.appendChild(document.createTextNode(InputSanitizer
115 					.sanitizeText(textContent)));
116 		}
117 
118 		return new DomNode(element);
119 	}
120 
121 	private Document getNodeDocument(final Node node) {
122 
123 		checkNotNull(node, "node");
124 
125 		for (Node n = node; n != null; n = n.getParentNode()) {
126 
127 			if (Document.class.isInstance(n)) {
128 
129 				return (Document) n;
130 			}
131 		}
132 
133 		throw new IllegalArgumentException("Node has no Document ancestor.");
134 	}
135 
136 	@Override
137 	public XmlFieldNode insertBefore(XmlFieldNode contextNode,
138 			XmlFieldNode newChild, XmlFieldNode refChild) {
139 		checkNotNull(contextNode, "contextNode");
140 		checkNotNull(newChild, "newChild");
141 		checkNotNull(refChild, "refChild");
142 		Node insertedNode = ((Node) contextNode.getNode()).insertBefore(
143 				(Node) newChild.getNode(), (Node) refChild.getNode());
144 		return new DomNode(insertedNode);
145 	}
146 
147 	@Override
148 	public XmlFieldNode removeAttribute(XmlFieldNode node, String attributeName) {
149 		checkNotNull(node, "node");
150 		checkNotNull(attributeName, "attributeName");
151 		NamedNodeMap nnMap = ((Node) node.getNode()).getAttributes();
152 		if (nnMap.getNamedItem(attributeName) == null) {
153 			return null;
154 		}
155 		return new DomNode(nnMap.removeNamedItem(attributeName));
156 	}
157 
158 	@Override
159 	public XmlFieldNode removeChild(XmlFieldNode node, XmlFieldNode oldChild) {
160 		checkNotNull(node, "node");
161 		checkNotNull(oldChild, "oldChild");
162 		Node removedNode = ((Node) node.getNode()).removeChild((Node) oldChild
163 				.getNode());
164 		if (removedNode != null) {
165 			return oldChild;
166 		}
167 		return null;
168 	}
169 
170 	@Override
171 	public void removeChildren(final XmlFieldNodeList nodesToRemove) {
172 		checkNotNull(nodesToRemove, "nodesToRemove");
173 		for (int i = nodesToRemove.getLength() - 1; i >= 0; i--) {
174 			final Node currentNode = (Node) nodesToRemove.item(i).getNode();
175 			currentNode.getParentNode().removeChild(currentNode);
176 		}
177 	}
178 }