KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jbpm > bpel > xml > util > NodeUtil


1 package org.jbpm.bpel.xml.util;
2
3 import java.io.IOException JavaDoc;
4 import java.io.InputStream JavaDoc;
5 import java.io.StringReader JavaDoc;
6 import java.net.URL JavaDoc;
7 import java.util.ArrayList JavaDoc;
8 import java.util.HashMap JavaDoc;
9 import java.util.Iterator JavaDoc;
10 import java.util.Map JavaDoc;
11 import java.util.NoSuchElementException JavaDoc;
12
13 import javax.xml.namespace.QName JavaDoc;
14 import javax.xml.parsers.DocumentBuilder JavaDoc;
15 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
16 import javax.xml.parsers.ParserConfigurationException JavaDoc;
17 import javax.xml.soap.SOAPElement JavaDoc;
18 import javax.xml.soap.SOAPException JavaDoc;
19 import javax.xml.transform.Transformer JavaDoc;
20 import javax.xml.transform.TransformerConfigurationException JavaDoc;
21 import javax.xml.transform.TransformerFactory JavaDoc;
22 import javax.xml.transform.stream.StreamSource JavaDoc;
23
24 import org.apache.commons.collections.Predicate;
25 import org.apache.commons.collections.iterators.FilterIterator;
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.jaxen.JaxenException;
29 import org.jaxen.Navigator;
30 import org.jaxen.SimpleNamespaceContext;
31 import org.jaxen.UnsupportedAxisException;
32 import org.jaxen.XPath;
33 import org.jaxen.dom.DOMXPath;
34 import org.jaxen.dom.DocumentNavigator;
35 import org.w3c.dom.Attr JavaDoc;
36 import org.w3c.dom.Document JavaDoc;
37 import org.w3c.dom.Element JavaDoc;
38 import org.w3c.dom.NamedNodeMap JavaDoc;
39 import org.w3c.dom.Node JavaDoc;
40 import org.w3c.dom.NodeList JavaDoc;
41 import org.xml.sax.InputSource JavaDoc;
42 import org.xml.sax.SAXException JavaDoc;
43
44 import org.jbpm.bpel.xml.BpelConstants;
45
46 import com.ibm.wsdl.util.xml.DOMUtils;
47
48 /**
49  * @author Alejandro Guízar
50  * @version $Revision: 1.3 $ $Date: 2005/06/23 20:48:05 $
51  */

52 public class NodeUtil {
53   
54   private static ThreadLocal JavaDoc documentBuilderLocal = new ThreadLocal JavaDoc() {
55     
56     protected Object JavaDoc initialValue() {
57       DocumentBuilderFactory JavaDoc factory = DocumentBuilderFactory.newInstance();
58       factory.setNamespaceAware(true);
59       factory.setValidating(true);
60       factory.setCoalescing(true);
61       factory.setIgnoringElementContentWhitespace(true);
62       try {
63         // Pick XML Schema as the schema language
64
factory.setAttribute(JAXP_SCHEMA_LANGUAGE, BpelConstants.NS_XML_SCHEMA);
65       }
66       catch (IllegalArgumentException JavaDoc e) {
67         log.fatal("The JAXP implementation does not support XML Schema validation. " +
68             " BPEL readers will not work properly.", e);
69         throw new AssertionError JavaDoc(e);
70       }
71       try {
72         // Do full type checking
73
factory.setAttribute("http://apache.org/xml/features/validation/schema-full-checking", Boolean.TRUE);
74         // Only do schema validation if a schema is specified as a namespace
75
factory.setAttribute("http://apache.org/xml/features/validation/dynamic", Boolean.TRUE);
76       }
77       catch (IllegalArgumentException JavaDoc e) {
78         log.warn("The JAXP implementation is not Xerces. Cannot enable dynamic schema validation." +
79             " XML documents without xsi:schemaLocation in their root element will not parse.");
80       }
81       try {
82         DocumentBuilder JavaDoc documentBuilder = factory.newDocumentBuilder();
83         documentBuilder.setEntityResolver(new LocalEntityResolver());
84         return documentBuilder;
85       }
86       catch (ParserConfigurationException JavaDoc e) {
87         throw new RuntimeException JavaDoc("could not create document builder", e);
88       }
89     }
90   };
91
92   private static final String JavaDoc JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
93   static final Log log = LogFactory.getLog(NodeUtil.class);
94   
95   /* Suppresses default constructor, ensuring non-instantiability */
96   private NodeUtil() {
97   }
98   
99   public static Element JavaDoc getElement(Node JavaDoc parentElem, String JavaDoc localName) {
100     return getElement(parentElem, null, localName);
101   }
102   
103   public static Element JavaDoc getElement(Node JavaDoc parentElem, String JavaDoc namespaceURI, String JavaDoc localName) {
104     for (Node JavaDoc child = parentElem.getFirstChild(); child != null; child = child.getNextSibling()) {
105       if (QNameElementPredicate.evaluate(child, namespaceURI, localName)) {
106         return (Element JavaDoc) child;
107       }
108     }
109     return null;
110   }
111   
112   public static Iterator JavaDoc getElements(Node JavaDoc parentNode, String JavaDoc namespaceURI) {
113     return new FilterIterator(new NodeIterator(parentNode), new NamespaceElementPredicate(namespaceURI));
114   }
115   
116   public static Iterator JavaDoc getElements(Node JavaDoc parentNode, String JavaDoc namespaceURI, String JavaDoc localName) {
117     return new FilterIterator(new NodeIterator(parentNode), new QNameElementPredicate(namespaceURI, localName));
118   }
119   
120   public static Iterator JavaDoc getNodes(Node JavaDoc parentNode) {
121     return new NodeIterator(parentNode);
122   }
123   
124   public static String JavaDoc getAttribute(Element JavaDoc ownerElem, String JavaDoc attrName) {
125     Attr JavaDoc attribute = ownerElem.getAttributeNode(attrName);
126     return attribute != null ? attribute.getValue() : null;
127   }
128   
129   public static QName JavaDoc getQName(String JavaDoc prefixedName, Element JavaDoc contextElement) {
130     String JavaDoc prefix;
131     String JavaDoc namespaceURI;
132     String JavaDoc localPart;
133     
134     int index = prefixedName.indexOf(':');
135     if (index == -1) {
136       localPart = prefixedName;
137       prefix = "";
138       namespaceURI = "";
139     }
140     else {
141       localPart = prefixedName.substring(index + 1);
142       prefix = prefixedName.substring(0, index);
143       namespaceURI = DOMUtils.getNamespaceURIFromPrefix(contextElement, prefix);
144     }
145     return new QName JavaDoc(namespaceURI, localPart, prefix);
146   }
147   
148   public static Object JavaDoc getValue(Node JavaDoc node) {
149     Object JavaDoc value = null;
150     switch (node.getNodeType()) {
151     case Node.ELEMENT_NODE:
152       value = getValue((Element JavaDoc) node);
153       break;
154     default:
155       value = node.getNodeValue();
156     }
157     return value;
158   }
159   
160   public static Object JavaDoc getValue(Element JavaDoc elem) {
161     Object JavaDoc value;
162     Node JavaDoc firstChild = elem.getFirstChild();
163     if (firstChild != null) {
164       switch (firstChild.getNodeType()) {
165       case Node.TEXT_NODE:
166       case Node.CDATA_SECTION_NODE:
167       case Node.COMMENT_NODE:
168         // value is that of the immediate text node
169
// TODO add support for data type binding
170
value = firstChild.getNodeValue();
171         break;
172       default: {
173         Node JavaDoc child = firstChild.getNextSibling();
174         // are there multiple children?
175
if (child != null) {
176           ArrayList JavaDoc childNodes = new ArrayList JavaDoc();
177           childNodes.add(firstChild);
178           do {
179             childNodes.add(child);
180             child = child.getNextSibling();
181           } while (child != null);
182           // value is the list of child nodes
183
value = childNodes;
184         }
185         else {
186           // value is the single child without wrapping
187
value = firstChild;
188         }
189       }
190       }
191     }
192     else {
193       // no children, no value
194
value = null;
195     }
196     return value;
197   }
198
199   public static void setValue(Node JavaDoc node, Object JavaDoc value) {
200     switch (node.getNodeType()) {
201     case Node.ELEMENT_NODE:
202       setValue((Element JavaDoc) node, value);
203       break;
204     case Node.ATTRIBUTE_NODE:
205       setValue((Attr JavaDoc) node, value);
206       break;
207     default:
208       node.setNodeValue(value.toString());
209     }
210   }
211   
212   public static void setValue(Attr JavaDoc attr, Object JavaDoc value) {
213     if (value instanceof Node JavaDoc) {
214       Node JavaDoc source = (Node JavaDoc) value;
215       switch (source.getNodeType()) {
216       case Node.ELEMENT_NODE:
217         attr.setValue(getValue((Element JavaDoc) source).toString());
218         break;
219       default:
220         attr.setValue(source.getNodeValue());
221       }
222     }
223     else {
224       attr.setValue(value.toString());
225     }
226   }
227   
228   public static void setValue(Element JavaDoc elem, Object JavaDoc value) {
229     if (value instanceof Node JavaDoc) {
230       Node JavaDoc source = (Node JavaDoc) value;
231       switch (source.getNodeType()) {
232       case Node.ELEMENT_NODE: {
233         copy(elem, (Element JavaDoc) source);
234         break;
235       }
236       default:
237         setValue(elem, source.getNodeValue());
238       }
239     }
240     else {
241       // TODO add support for data type binding
242
setValue(elem, value.toString());
243     }
244   }
245   
246   public static void setValue(Element JavaDoc elem, String JavaDoc value) {
247     Node JavaDoc firstChild = elem.getFirstChild();
248     if (firstChild != null) {
249       switch (firstChild.getNodeType()) {
250       case Node.TEXT_NODE:
251       case Node.CDATA_SECTION_NODE:
252       case Node.COMMENT_NODE:
253         // set the value is of the immediate text node
254
firstChild.setNodeValue(value);
255         break;
256       default:
257         removeChildNodes(elem);
258         elem.appendChild(elem.getOwnerDocument().createTextNode(value));
259       }
260     }
261     else {
262       elem.appendChild(elem.getOwnerDocument().createTextNode(value));
263     }
264   }
265   
266   public static void copy(Element JavaDoc target, Element JavaDoc source) {
267     // attributes
268
removeAttributes(target);
269     if (source.hasAttributes()) {
270       NamedNodeMap JavaDoc attributes = source.getAttributes();
271       for (int i = 0, n = attributes.getLength(); i < n; i++) {
272         Attr JavaDoc attribute = (Attr JavaDoc) attributes.item(i);
273         String JavaDoc namespaceURI = attribute.getNamespaceURI();
274         if (namespaceURI == null)
275           target.setAttribute(attribute.getName(), attribute.getValue());
276         else
277           target.setAttributeNS(namespaceURI, attribute.getName(), attribute.getValue());
278       }
279     }
280     // child nodes
281
removeChildNodes(target);
282     Document JavaDoc document = target.getOwnerDocument();
283     if (source.hasChildNodes()) {
284       for (Node JavaDoc child = source.getFirstChild(); child != null; child = child.getNextSibling()) {
285         Node JavaDoc newChild;
286         switch (child.getNodeType()) {
287         case Node.ELEMENT_NODE: {
288           Element JavaDoc newElem = document.createElementNS(child.getNamespaceURI(), child.getNodeName());
289           copy(newElem, (Element JavaDoc) child);
290           newChild = newElem;
291           break;
292         }
293         case Node.TEXT_NODE:
294           newChild = document.createTextNode(child.getNodeValue());
295           break;
296         case Node.CDATA_SECTION_NODE:
297           newChild = document.createCDATASection(child.getNodeValue());
298           break;
299         case Node.COMMENT_NODE:
300           newChild = document.createComment(child.getNodeValue());
301           break;
302         default:
303           newChild = document.importNode(child, true);
304         }
305         target.appendChild(newChild);
306       }
307     }
308   }
309   
310   public static void copy(SOAPElement JavaDoc target, Element JavaDoc source) throws SOAPException JavaDoc {
311     // attributes
312
removeAttributes(target);
313     if (source.hasAttributes()) {
314       NamedNodeMap JavaDoc attributes = source.getAttributes();
315       for (int i = 0, n = attributes.getLength(); i < n; i++) {
316         Attr JavaDoc attribute = (Attr JavaDoc) attributes.item(i);
317         String JavaDoc namespaceURI = attribute.getNamespaceURI();
318         if (namespaceURI == null)
319           target.setAttribute(attribute.getName(), attribute.getValue());
320         else if (namespaceURI.equals(BpelConstants.NS_XMLNS))
321           target.addNamespaceDeclaration(attribute.getLocalName(), attribute.getValue());
322         else
323           target.setAttributeNS(namespaceURI, attribute.getName(), attribute.getValue());
324       }
325     }
326     target.removeContents();
327     if (source.hasChildNodes()) {
328       for (Node JavaDoc child = source.getFirstChild(); child != null; child = child.getNextSibling()) {
329         switch (child.getNodeType()) {
330         case Node.ELEMENT_NODE: {
331           String JavaDoc namespaceURI = child.getNamespaceURI();
332           SOAPElement JavaDoc newElem = namespaceURI != null ?
333               target.addChildElement(child.getLocalName(), child.getPrefix(), namespaceURI) :
334               target.addChildElement(child.getLocalName(), "");
335           copy(newElem, (Element JavaDoc) child);
336           break;
337         }
338         case Node.COMMENT_NODE:
339         case Node.TEXT_NODE:
340         case Node.CDATA_SECTION_NODE:
341           target.addTextNode(child.getNodeValue());
342           break;
343         // default: any other node type is discarded
344
}
345       }
346     }
347   }
348   
349   public static Node JavaDoc appendForeignChild(Node JavaDoc node, Node JavaDoc importedChild) {
350     return node.appendChild(node.getOwnerDocument().importNode(importedChild, true));
351   }
352   
353   public static void addNamespace(Element JavaDoc elem, String JavaDoc namespaceURI, String JavaDoc prefix) {
354     elem.setAttributeNS(BpelConstants.NS_XMLNS, "xmlns:" + prefix, namespaceURI);
355   }
356   
357   public static void removeAttributes(Element JavaDoc elem) {
358     if (elem.hasAttributes()) {
359       NamedNodeMap JavaDoc attributes = elem.getAttributes();
360       for (int i = 0, n = attributes.getLength(); i < n; i++) {
361         elem.removeAttributeNode((Attr JavaDoc) attributes.item(i));
362       }
363     }
364   }
365   
366   public static void removeChildNodes(Node JavaDoc node) {
367     if (node.hasChildNodes()) {
368       NodeList JavaDoc children = node.getChildNodes();
369       for (int i = 0, n = children.getLength(); i < n; i++) {
370         node.removeChild(children.item(i));
371       }
372     }
373   }
374   
375   public static Document JavaDoc createDocument() {
376     return getDocumentBuilder().newDocument();
377   }
378   
379   /**
380    * Parses the XML document contained in the given string into a DOM document.
381    * @param text a string containing the document to parse
382    * @return a new DOM document representing the XML content
383    * @throws SAXException if any parse errors occur
384    */

385   public static Element JavaDoc parseElement(String JavaDoc text) throws SAXException JavaDoc {
386     try {
387       DocumentBuilderFactory JavaDoc factory = DocumentBuilderFactory.newInstance();
388       factory.setNamespaceAware(true);
389       DocumentBuilder JavaDoc builder = factory.newDocumentBuilder();
390       return builder.parse(new InputSource JavaDoc(new StringReader JavaDoc(text))).getDocumentElement();
391     }
392     catch (IOException JavaDoc e) {
393       log.error(e);
394       throw new RuntimeException JavaDoc("i/o operation failed on a string reader", e);
395     }
396     catch (ParserConfigurationException JavaDoc e) {
397       throw new RuntimeException JavaDoc("could not create document builder", e);
398     }
399   }
400
401   /**
402    * Gets a validating document builder local to the current thread.
403    * @return a validating document builder local to the current thread
404    */

405   public static DocumentBuilder JavaDoc getDocumentBuilder() {
406     DocumentBuilder JavaDoc builder = (DocumentBuilder JavaDoc) documentBuilderLocal.get();
407     return builder;
408   }
409   
410   public static Map JavaDoc getNamespaceDeclarations(Element JavaDoc elem) {
411     Map JavaDoc namespaceDeclarations = new HashMap JavaDoc();
412     try {
413       Navigator nav = DocumentNavigator.getInstance();
414       Iterator JavaDoc namespaceAxis = nav.getNamespaceAxisIterator(elem);
415       while (namespaceAxis.hasNext()) {
416         Object JavaDoc namespace = namespaceAxis.next();
417         String JavaDoc prefix = nav.getNamespacePrefix(namespace);
418         String JavaDoc uri = nav.getNamespaceStringValue(namespace);
419         if (!namespaceDeclarations.containsKey(prefix)) {
420           namespaceDeclarations.put(prefix, uri);
421         }
422       }
423       // remove the default namespace declaration
424
namespaceDeclarations.remove("");
425     }
426     catch (UnsupportedAxisException e) {
427       log.fatal("The Jaxen DOM navigator does not support the namespace axis." +
428             " Cannot determine the namespace declarations of DOM elements.");
429       throw new AssertionError JavaDoc(e);
430     }
431     return namespaceDeclarations;
432   }
433   
434   public static Object JavaDoc evaluateXPath(String JavaDoc text, Object JavaDoc context, Map JavaDoc namespaces) {
435     try {
436       XPath xpath = new DOMXPath(text);
437       if (namespaces != null) {
438         xpath.setNamespaceContext(new SimpleNamespaceContext(namespaces));
439       }
440       return xpath.evaluate(context);
441     }
442     catch (JaxenException e) {
443       log.error(e);
444       throw new RuntimeException JavaDoc("could not evaluate xpath", e);
445     }
446   }
447
448   private static class NodeIterator implements Iterator JavaDoc {
449
450     private Node JavaDoc currentNode;
451     private Node JavaDoc lastReturned;
452     
453     NodeIterator(Node JavaDoc parentNode) {
454       currentNode = parentNode.getFirstChild();
455     }
456   
457     public boolean hasNext() {
458       return currentNode != null;
459     }
460   
461     public Object JavaDoc next() {
462       if (currentNode == null) throw new NoSuchElementException JavaDoc();
463       lastReturned = currentNode;
464       currentNode = lastReturned.getNextSibling();
465       return lastReturned;
466     }
467     
468     public void remove() {
469       if (lastReturned == null) throw new IllegalStateException JavaDoc();
470       Node JavaDoc parentNode = lastReturned.getParentNode();
471       if (parentNode != null)
472         parentNode.removeChild(lastReturned);
473       lastReturned = null;
474     }
475   }
476
477   private static class NamespaceElementPredicate implements Predicate {
478     
479     private String JavaDoc namespaceURI;
480     
481     public NamespaceElementPredicate(String JavaDoc namespaceURI) {
482       this.namespaceURI = namespaceURI;
483     }
484
485     public boolean evaluate(Object JavaDoc arg) {
486       return evaluate((Node JavaDoc) arg, namespaceURI);
487     }
488     
489     static boolean evaluate(Node JavaDoc node, String JavaDoc namespaceURI) {
490       return node.getNodeType() == Node.ELEMENT_NODE
491       && (namespaceURI != null ?
492           namespaceURI.equals(node.getNamespaceURI())
493           : node.getNamespaceURI() == null);
494     }
495   }
496   
497   private static class QNameElementPredicate implements Predicate {
498     
499     private String JavaDoc namespaceURI;
500     private String JavaDoc localName;
501   
502     QNameElementPredicate(String JavaDoc namespaceURI, String JavaDoc localName) {
503       this.namespaceURI = namespaceURI;
504       this.localName = localName;
505     }
506   
507     public boolean evaluate(Object JavaDoc arg) {
508       return evaluate((Node JavaDoc) arg, namespaceURI, localName);
509     }
510     
511     static boolean evaluate(Node JavaDoc node, String JavaDoc namespaceURI, String JavaDoc localName) {
512       return node.getNodeType() == Node.ELEMENT_NODE
513       && (namespaceURI != null ?
514           namespaceURI.equals(node.getNamespaceURI())
515           : node.getNamespaceURI() == null)
516       && localName.equals(node.getLocalName());
517     }
518   }
519
520   public static Transformer JavaDoc createUpgrader(URL JavaDoc upgraderURL) {
521     TransformerFactory JavaDoc factory = TransformerFactory.newInstance();
522     Transformer JavaDoc upgrader = null;
523     InputStream JavaDoc stream = null;
524     try {
525       stream = upgraderURL.openStream();
526       upgrader = factory.newTransformer(new StreamSource JavaDoc(stream));
527     }
528     catch (TransformerConfigurationException JavaDoc e) {
529       log.error("unable to create upgrader " + upgraderURL, e);
530     }
531     catch (IOException JavaDoc e) {
532       log.error("unable to read upgrader " + upgraderURL, e);
533     }
534     finally {
535       try {
536         stream.close();
537       } catch (IOException JavaDoc e) {
538         log.error("unable to close xsl template " + upgraderURL, e);
539       }
540     }
541     
542     return upgrader;
543   }
544 }
545
Popular Tags