Coverage Report - org.kuali.rice.core.api.util.xml.XmlHelper
 
Classes in this File Line Coverage Branch Coverage Complexity
XmlHelper
0%
0/96
0%
0/40
3.071
 
 1  
 /*
 2  
  * Copyright 2005-2007 The Kuali Foundation
 3  
  *
 4  
  *
 5  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  * http://www.opensource.org/licenses/ecl2.php
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.kuali.rice.core.api.util.xml;
 18  
 
 19  
 import org.apache.commons.lang.StringUtils;
 20  
 import org.apache.commons.logging.Log;
 21  
 import org.apache.commons.logging.LogFactory;
 22  
 import org.jdom.Document;
 23  
 import org.jdom.Element;
 24  
 import org.jdom.JDOMException;
 25  
 import org.jdom.Namespace;
 26  
 import org.jdom.input.DOMBuilder;
 27  
 import org.jdom.input.SAXBuilder;
 28  
 import org.w3c.dom.Node;
 29  
 import org.w3c.dom.NodeList;
 30  
 import org.xml.sax.InputSource;
 31  
 import org.xml.sax.SAXException;
 32  
 
 33  
 import javax.xml.parsers.DocumentBuilder;
 34  
 import javax.xml.parsers.DocumentBuilderFactory;
 35  
 import javax.xml.parsers.ParserConfigurationException;
 36  
 import javax.xml.transform.OutputKeys;
 37  
 import javax.xml.transform.Source;
 38  
 import javax.xml.transform.Transformer;
 39  
 import javax.xml.transform.TransformerException;
 40  
 import javax.xml.transform.TransformerFactory;
 41  
 import javax.xml.transform.dom.DOMResult;
 42  
 import javax.xml.transform.stream.StreamSource;
 43  
 import javax.xml.xpath.XPath;
 44  
 import javax.xml.xpath.XPathConstants;
 45  
 import javax.xml.xpath.XPathExpressionException;
 46  
 import java.io.BufferedReader;
 47  
 import java.io.IOException;
 48  
 import java.io.InputStream;
 49  
 import java.io.Reader;
 50  
 import java.io.StringReader;
 51  
 import java.lang.reflect.Method;
 52  
 import java.util.ArrayList;
 53  
 import java.util.Collection;
 54  
 
 55  
 
 56  
 /**
 57  
  * Provides a set of utilities for XML-related operations on org.jdom & org.w3c
 58  
  * xml Objects.
 59  
  *
 60  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 61  
  */
 62  
 public final class XmlHelper {
 63  0
     private static final Log LOG = LogFactory.getLog(XmlHelper.class);
 64  
 
 65  0
     private XmlHelper() {
 66  0
         throw new UnsupportedOperationException("do not call");
 67  
     }
 68  
 
 69  
     /**
 70  
      * Creates jdom Document from a Reader.  Does not close the reader.
 71  
      *
 72  
      * @param xmlStream the reader representing the xmlstream
 73  
      * @return jdom document
 74  
      */
 75  
     public static org.jdom.Document buildJDocument(Reader xmlStream) {
 76  
         // use SAX Builder
 77  
         // don't verify for speed reasons
 78  0
         final SAXBuilder builder = new SAXBuilder(false);
 79  
         try {
 80  0
             return builder.build(xmlStream);
 81  0
         } catch (IOException e) {
 82  0
             throw new XmlException("Invalid xml string. ", e);
 83  0
         } catch (JDOMException e) {
 84  0
             throw new XmlException("Invalid xml string. ", e);
 85  
         }
 86  
     }
 87  
 
 88  
     /**
 89  
      * Creates jdom Document from a w3c Document.  Does not close the reader.
 90  
      *
 91  
      * @param document the w3c document
 92  
      * @return jdom document
 93  
      */
 94  
     public static org.jdom.Document buildJDocument(org.w3c.dom.Document document) {
 95  0
         return new DOMBuilder().build(document);
 96  
     }
 97  
 
 98  
     /**
 99  
      * Find all Elements in document of a particular name
 100  
      *
 101  
      * @param root the starting Element to scan
 102  
      * @param elementName name of the Element to scan for
 103  
      * @return collection of the Elements found.
 104  
      *         returns an empty collection if none are found.
 105  
      */
 106  
     public static Collection<Element> findElements(Element root, String elementName) {
 107  0
         Collection<Element> elementList = new ArrayList<Element>();
 108  
 
 109  0
         if (root == null) {
 110  0
             return elementList;
 111  
         }
 112  
 
 113  0
         XmlHelper.findElements(root, elementName, elementList);
 114  
 
 115  0
         return elementList;
 116  
     }
 117  
 
 118  
     public static void appendXml(Node parentNode, String xml) throws SAXException, IOException, ParserConfigurationException {
 119  0
         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 120  0
         factory.setValidating(false);
 121  0
         org.w3c.dom.Document xmlDocument = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
 122  0
         org.w3c.dom.Element xmlDocumentElement = xmlDocument.getDocumentElement();
 123  0
         Node importedNode = parentNode.getOwnerDocument().importNode(xmlDocumentElement, true);
 124  0
         parentNode.appendChild(importedNode);
 125  0
     }
 126  
 
 127  
     public static org.w3c.dom.Document readXml(String xml) throws TransformerException {
 128  0
         Source source = new StreamSource(new BufferedReader(new StringReader(xml)));
 129  0
         DOMResult result = new DOMResult();
 130  0
         Transformer transformer = TransformerFactory.newInstance().newTransformer();
 131  0
         transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
 132  0
         transformer.transform(source, result);
 133  0
         return (org.w3c.dom.Document) result.getNode();
 134  
     }
 135  
 
 136  
     public static void propagateNamespace(Element element, Namespace namespace) {
 137  0
         element.setNamespace(namespace);
 138  0
         for (Object childElement : element.getChildren()) {
 139  0
             propagateNamespace((Element) childElement, namespace);
 140  
         }
 141  0
     }
 142  
 
 143  
     public static org.w3c.dom.Document trimXml(InputStream input) throws SAXException, IOException, ParserConfigurationException {
 144  0
         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 145  0
         factory.setIgnoringElementContentWhitespace(true);
 146  0
         DocumentBuilder builder = factory.newDocumentBuilder();
 147  0
         org.w3c.dom.Document oldDocument = builder.parse(input);
 148  0
         org.w3c.dom.Element naviElement = oldDocument.getDocumentElement();
 149  0
         trimElement(naviElement);
 150  0
         return oldDocument;
 151  
     }
 152  
 
 153  
     public static Document trimSAXXml(InputStream input) throws JDOMException, SAXException, IOException, ParserConfigurationException {
 154  0
         SAXBuilder builder = new SAXBuilder(false);
 155  0
         Document oldDocument = builder.build(input);
 156  0
         Element naviElement = oldDocument.getRootElement();
 157  0
         trimSAXElement(naviElement);
 158  0
         return oldDocument;
 159  
     }
 160  
 
 161  
     /**
 162  
      * Convenience method that performs an xpath evaluation to determine whether the expression
 163  
      * evaluates to true (a node exists).
 164  
      * This is method exists only to disambiguate the cases of determining the *presence* of a node
 165  
      * and determining the *boolean value of the node as converted from a string*, as the syntaxes
 166  
      * are very similar and could be misleading.
 167  
      *
 168  
      * @param xpath      the XPath object
 169  
      * @param expression the XPath expression
 170  
      * @param object     the object on which to evaluate the expression as required by the XPath API, typically a Node
 171  
      * @return whether the result of the expression evaluation, which is whether or not a node was present
 172  
      * @throws XPathExpressionException if the expression fails
 173  
      */
 174  
     public static boolean pathExists(XPath xpath, String expression, Object object) throws XPathExpressionException {
 175  0
         return ((Boolean) xpath.evaluate(expression, object, XPathConstants.BOOLEAN)).booleanValue();
 176  
     }
 177  
 
 178  
     public static org.w3c.dom.Element propertiesToXml(org.w3c.dom.Document doc, Object o, String elementName) throws Exception {
 179  0
         Class<?> c = o.getClass();
 180  0
         org.w3c.dom.Element wrapper = doc.createElement(elementName);
 181  0
         Method[] methods = c.getMethods();
 182  0
         for (Method method : methods) {
 183  0
             String name = method.getName();
 184  0
             if ("getClass".equals(name)) {
 185  0
                 continue;
 186  
             }
 187  0
             if (!name.startsWith("get") || method.getParameterTypes().length > 0) {
 188  0
                 continue;
 189  
             }
 190  0
             name = name.substring("get".length());
 191  0
             name = StringUtils.uncapitalize(name);
 192  
             try {
 193  0
                 Object result = method.invoke(o);
 194  
                 final String value;
 195  0
                 if (result == null) {
 196  0
                     LOG.debug("value of " + name + " method on object " + o.getClass() + " is null");
 197  0
                     value = "";
 198  
                 } else {
 199  0
                     value = result.toString();
 200  
                 }
 201  0
                 org.w3c.dom.Element fieldE = doc.createElement(name);
 202  0
                 fieldE.appendChild(doc.createTextNode(value));
 203  0
                 wrapper.appendChild(fieldE);
 204  0
             } catch (Exception e) {
 205  0
                 throw new XmlException("Error accessing method '" + method.getName() + "' of instance of " + c, e);
 206  0
             }
 207  
         }
 208  0
         return wrapper;
 209  
     }
 210  
 
 211  
     /**
 212  
      * This function is tail-recursive and just adds the root to the list if it
 213  
      * matches and checks the children.
 214  
      *
 215  
      * @param root the root element to search under
 216  
      * @param elementName the element name to find
 217  
      * @param list a list of found element
 218  
      */
 219  
     private static void findElements(Element root, String elementName, Collection<Element> list) {
 220  0
         if (root != null) {
 221  0
             if (root.getName().equals(elementName)) {
 222  0
                 list.add(root);
 223  
             }
 224  
 
 225  0
             for (Object item : root.getChildren()) {
 226  0
                 if (item != null) {
 227  0
                     XmlHelper.findElements((Element) item, elementName, list);
 228  
                 }
 229  
             }
 230  
         }
 231  0
     }
 232  
 
 233  
     private static void trimElement(Node node) throws SAXException, IOException, ParserConfigurationException {
 234  
 
 235  0
         if (node.hasChildNodes()) {
 236  0
             NodeList children = node.getChildNodes();
 237  0
             for (int i = 0; i < children.getLength(); i++) {
 238  0
                 Node child = children.item(i);
 239  0
                 if (child != null) {
 240  0
                     trimElement(child);
 241  
                 }
 242  
             }
 243  0
         } else {
 244  0
             if (node.getNodeType() == Node.TEXT_NODE) {
 245  0
                 String text = node.getNodeValue();
 246  0
                 text = StringUtils.isEmpty(text) ? "" : text.trim();
 247  0
                 node.setNodeValue(text);
 248  
             }
 249  
         }
 250  0
     }
 251  
 
 252  
     private static void trimSAXElement(Element element) throws SAXException, IOException, ParserConfigurationException {
 253  
 
 254  0
         if (!element.getChildren().isEmpty()) {
 255  0
             for (Object child : element.getChildren()) {
 256  0
                 if (child != null) {
 257  0
                     trimSAXElement((Element) child);
 258  
                 }
 259  
             }
 260  
         } else {
 261  0
             String text = element.getTextTrim();
 262  0
             if (StringUtils.isEmpty(text)) {
 263  0
                 text = "";
 264  
             }
 265  0
             element.setText(text);
 266  
         }
 267  0
     }
 268  
 }