001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.modeler.util;
018
019 import java.io.IOException;
020 import java.io.InputStream;
021 import java.io.OutputStream;
022 import java.io.StringReader;
023
024 import javax.xml.parsers.DocumentBuilder;
025 import javax.xml.parsers.DocumentBuilderFactory;
026 import javax.xml.parsers.ParserConfigurationException;
027 import javax.xml.transform.OutputKeys;
028 import javax.xml.transform.Transformer;
029 import javax.xml.transform.TransformerException;
030 import javax.xml.transform.TransformerFactory;
031 import javax.xml.transform.dom.DOMSource;
032 import javax.xml.transform.stream.StreamResult;
033
034 import org.w3c.dom.Document;
035 import org.w3c.dom.NamedNodeMap;
036 import org.w3c.dom.Node;
037 import org.xml.sax.EntityResolver;
038 import org.xml.sax.InputSource;
039 import org.xml.sax.SAXException;
040
041
042 /**
043 * Few simple utils to read DOM
044 *
045 * @author Costin Manolache
046 */
047 public class DomUtil {
048 private static org.apache.commons.logging.Log log=
049 org.apache.commons.logging.LogFactory.getLog( DomUtil.class );
050
051 // -------------------- DOM utils --------------------
052
053 /** Get the trimed text content of a node or null if there is no text
054 */
055 public static String getContent(Node n ) {
056 if( n==null ) return null;
057 Node n1=DomUtil.getChild(n, Node.TEXT_NODE);
058
059 if( n1==null ) return null;
060
061 String s1=n1.getNodeValue();
062 return s1.trim();
063 }
064
065 /** Get the first element child.
066 * @param parent lookup direct childs
067 * @param name name of the element. If null return the first element.
068 */
069 public static Node getChild( Node parent, String name ) {
070 if( parent==null ) return null;
071 Node first=parent.getFirstChild();
072 if( first==null ) return null;
073
074 for (Node node = first; node != null;
075 node = node.getNextSibling()) {
076 //System.out.println("getNode: " + name + " " + node.getNodeName());
077 if( node.getNodeType()!=Node.ELEMENT_NODE)
078 continue;
079 if( name != null &&
080 name.equals( node.getNodeName() ) ) {
081 return node;
082 }
083 if( name == null ) {
084 return node;
085 }
086 }
087 return null;
088 }
089
090 public static String getAttribute(Node element, String attName ) {
091 NamedNodeMap attrs=element.getAttributes();
092 if( attrs==null ) return null;
093 Node attN=attrs.getNamedItem(attName);
094 if( attN==null ) return null;
095 return attN.getNodeValue();
096 }
097
098 public static void setAttribute(Node node, String attName, String val) {
099 NamedNodeMap attributes=node.getAttributes();
100 Node attNode=node.getOwnerDocument().createAttribute(attName);
101 attNode.setNodeValue( val );
102 attributes.setNamedItem(attNode);
103 }
104
105 public static void removeAttribute( Node node, String attName ) {
106 NamedNodeMap attributes=node.getAttributes();
107 attributes.removeNamedItem(attName);
108 }
109
110
111 /** Set or replace the text value
112 */
113 public static void setText(Node node, String val) {
114 Node chld=DomUtil.getChild(node, Node.TEXT_NODE);
115 if( chld == null ) {
116 Node textN=node.getOwnerDocument().createTextNode(val);
117 node.appendChild(textN);
118 return;
119 }
120 // change the value
121 chld.setNodeValue(val);
122 }
123
124 /** Find the first direct child with a given attribute.
125 * @param parent
126 * @param elemName name of the element, or null for any
127 * @param attName attribute we're looking for
128 * @param attVal attribute value or null if we just want any
129 */
130 public static Node findChildWithAtt(Node parent, String elemName,
131 String attName, String attVal) {
132
133 Node child=DomUtil.getChild(parent, Node.ELEMENT_NODE);
134 if( attVal== null ) {
135 while( child!= null &&
136 ( elemName==null || elemName.equals( child.getNodeName())) &&
137 DomUtil.getAttribute(child, attName) != null ) {
138 child=getNext(child, elemName, Node.ELEMENT_NODE );
139 }
140 } else {
141 while( child!= null &&
142 ( elemName==null || elemName.equals( child.getNodeName())) &&
143 ! attVal.equals( DomUtil.getAttribute(child, attName)) ) {
144 child=getNext(child, elemName, Node.ELEMENT_NODE );
145 }
146 }
147 return child;
148 }
149
150
151 /** Get the first child's content ( ie it's included TEXT node ).
152 */
153 public static String getChildContent( Node parent, String name ) {
154 Node first=parent.getFirstChild();
155 if( first==null ) return null;
156 for (Node node = first; node != null;
157 node = node.getNextSibling()) {
158 //System.out.println("getNode: " + name + " " + node.getNodeName());
159 if( name.equals( node.getNodeName() ) ) {
160 return getContent( node );
161 }
162 }
163 return null;
164 }
165
166 /** Get the first direct child with a given type
167 */
168 public static Node getChild( Node parent, int type ) {
169 Node n=parent.getFirstChild();
170 while( n!=null && type != n.getNodeType() ) {
171 n=n.getNextSibling();
172 }
173 if( n==null ) return null;
174 return n;
175 }
176
177 /** Get the next sibling with the same name and type
178 */
179 public static Node getNext( Node current ) {
180 String name=current.getNodeName();
181 int type=current.getNodeType();
182 return getNext( current, name, type);
183 }
184
185 /** Return the next sibling with a given name and type
186 */
187 public static Node getNext( Node current, String name, int type) {
188 Node first=current.getNextSibling();
189 if( first==null ) return null;
190
191 for (Node node = first; node != null;
192 node = node.getNextSibling()) {
193
194 if( type >= 0 && node.getNodeType() != type ) continue;
195 //System.out.println("getNode: " + name + " " + node.getNodeName());
196 if( name==null )
197 return node;
198 if( name.equals( node.getNodeName() ) ) {
199 return node;
200 }
201 }
202 return null;
203 }
204
205 public static class NullResolver implements EntityResolver {
206 public InputSource resolveEntity (String publicId,
207 String systemId)
208 throws SAXException, IOException
209 {
210 if( log.isTraceEnabled())
211 log.trace("ResolveEntity: " + publicId + " " + systemId);
212 return new InputSource(new StringReader(""));
213 }
214 }
215
216 public static void setAttributes( Object o, Node parent)
217 {
218 NamedNodeMap attrs=parent.getAttributes();
219 if( attrs==null ) return;
220
221 for (int i=0; i<attrs.getLength(); i++ ) {
222 Node n=attrs.item(i);
223 String name=n.getNodeName();
224 String value=n.getNodeValue();
225
226 if( log.isTraceEnabled() )
227 log.trace("Attribute " + parent.getNodeName() + " " +
228 name + "=" + value);
229 try {
230 IntrospectionUtils.setProperty(o, name, value);
231 } catch( Exception ex ) {
232 ex.printStackTrace();
233 }
234 }
235 }
236
237 /** Read XML as DOM.
238 */
239 public static Document readXml(InputStream is)
240 throws SAXException, IOException, ParserConfigurationException
241 {
242 DocumentBuilderFactory dbf =
243 DocumentBuilderFactory.newInstance();
244
245 dbf.setValidating(false);
246 dbf.setIgnoringComments(false);
247 dbf.setIgnoringElementContentWhitespace(true);
248 //dbf.setCoalescing(true);
249 //dbf.setExpandEntityReferences(true);
250
251 DocumentBuilder db = null;
252 db = dbf.newDocumentBuilder();
253 db.setEntityResolver( new NullResolver() );
254
255 // db.setErrorHandler( new MyErrorHandler());
256
257 Document doc = db.parse(is);
258 return doc;
259 }
260
261 public static void writeXml( Node n, OutputStream os )
262 throws TransformerException
263 {
264 TransformerFactory tf=TransformerFactory.newInstance();
265 //identity
266 Transformer t=tf.newTransformer();
267 t.setOutputProperty(OutputKeys.INDENT, "yes");
268 t.transform(new DOMSource( n ), new StreamResult( os ));
269 }
270 }