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