sascha@4070: package de.intevation.utils;
sascha@4070: 
sascha@4070: import java.io.BufferedInputStream;
sascha@4070: import java.io.File;
teichmann@4772: import java.io.FileInputStream;
sascha@4070: import java.io.IOException;
sascha@4070: import java.io.InputStream;
sascha@4095: import java.io.OutputStream;
sascha@4095: import java.io.StringWriter;
sascha@4070: 
sascha@4070: import java.util.HashMap;
sascha@4070: import java.util.Map;
sascha@4070: 
sascha@4070: import javax.xml.namespace.NamespaceContext;
sascha@4070: import javax.xml.namespace.QName;
sascha@4070: 
teichmann@4772: import javax.xml.parsers.DocumentBuilderFactory;
teichmann@4772: import javax.xml.parsers.ParserConfigurationException;
teichmann@4772: 
teichmann@4772: import javax.xml.transform.Transformer;
teichmann@4772: import javax.xml.transform.TransformerConfigurationException;
teichmann@4772: import javax.xml.transform.TransformerException;
teichmann@4772: import javax.xml.transform.TransformerFactory;
teichmann@4772: import javax.xml.transform.TransformerFactoryConfigurationError;
teichmann@4772: 
teichmann@4772: import javax.xml.transform.dom.DOMResult;
teichmann@4772: import javax.xml.transform.dom.DOMSource;
teichmann@4772: 
teichmann@4772: import javax.xml.transform.stream.StreamResult;
teichmann@4772: import javax.xml.transform.stream.StreamSource;
teichmann@4772: 
sascha@4070: import javax.xml.xpath.XPath;
sascha@4070: import javax.xml.xpath.XPathExpressionException;
sascha@4070: import javax.xml.xpath.XPathFactory;
sascha@4070: import javax.xml.xpath.XPathVariableResolver;
sascha@4070: 
teichmann@4772: import org.apache.log4j.Logger;
sascha@4083: 
teichmann@4772: import org.w3c.dom.Document;
sascha@4083: 
teichmann@4772: import org.xml.sax.SAXException;
sascha@4083: 
sascha@4070: public final class XML
sascha@4070: {
sascha@4070:     /** Logger for this class. */
sascha@4070:     private static Logger log = Logger.getLogger(XML.class);
sascha@4070: 
sascha@4070:     public static class MapXPathVariableResolver
teichmann@4736:     implements          XPathVariableResolver
sascha@4070:     {
sascha@4070:         protected Map<String, String> variables;
sascha@4070: 
sascha@4070: 
sascha@4070:         public MapXPathVariableResolver() {
sascha@4070:             this.variables = new HashMap<String, String>();
sascha@4070:         }
sascha@4070: 
sascha@4070: 
sascha@4070:         public MapXPathVariableResolver(Map<String, String> variables) {
sascha@4070:             this.variables = variables;
sascha@4070:         }
sascha@4070: 
sascha@4070: 
sascha@4070:         public void addVariable(String name, String value) {
sascha@4070:             variables.put(name, value);
sascha@4070:         }
sascha@4070: 
sascha@4070: 
sascha@4070:         @Override
sascha@4070:         public Object resolveVariable(QName variableName) {
sascha@4070:             String key = variableName.getLocalPart();
sascha@4070:             return variables.get(key);
sascha@4070:         }
sascha@4070:     } // class MapXPathVariableResolver
sascha@4070: 
sascha@4070:     private XML() {
sascha@4070:     }
sascha@4070: 
sascha@4095:         /**
sascha@4095:      * Creates a new XML document
sascha@4095:      * @return the new XML document ot null if something went wrong during
sascha@4095:      * creation.
sascha@4095:      */
sascha@4095:     public static final Document newDocument() {
sascha@4095:         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
sascha@4095:         factory.setNamespaceAware(true);
sascha@4095: 
sascha@4095:         try {
sascha@4095:             return factory.newDocumentBuilder().newDocument();
sascha@4095:         }
sascha@4095:         catch (ParserConfigurationException pce) {
sascha@4095:             log.error(pce.getLocalizedMessage(), pce);
sascha@4095:         }
sascha@4095:         return null;
sascha@4095:     }
sascha@4095: 
sascha@4070:     /**
sascha@4070:      * Loads a XML document namespace aware from a file
sascha@4070:      * @param file The file to load.
sascha@4070:      * @return the XML document or null if something went wrong
sascha@4070:      * during loading.
sascha@4070:      */
sascha@4070:     public static final Document parseDocument(File file) {
sascha@4072:         return parseDocument(file, Boolean.TRUE);
sascha@4072:     }
sascha@4072: 
sascha@4072:     public static final Document parseDocument(File file, Boolean namespaceAware) {
sascha@4070:         InputStream inputStream = null;
sascha@4070:         try {
sascha@4070:             inputStream = new BufferedInputStream(new FileInputStream(file));
sascha@4072:             return parseDocument(inputStream, namespaceAware);
sascha@4070:         }
sascha@4070:         catch (IOException ioe) {
sascha@4070:             log.error(ioe.getLocalizedMessage(), ioe);
sascha@4070:         }
sascha@4070:         finally {
sascha@4070:             if (inputStream != null) {
sascha@4070:                 try { inputStream.close(); }
sascha@4070:                 catch (IOException ioe) {}
sascha@4070:             }
sascha@4070:         }
sascha@4070:         return null;
sascha@4070:     }
sascha@4070: 
sascha@4070: 
sascha@4070:     public static final Document parseDocument(InputStream inputStream) {
sascha@4070:         return parseDocument(inputStream, Boolean.TRUE);
sascha@4070:     }
sascha@4070: 
sascha@4070:     public static final Document parseDocument(
sascha@4070:         InputStream inputStream,
sascha@4070:         Boolean     namespaceAware
sascha@4070:     ) {
sascha@4070:         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
sascha@4070: 
sascha@4070:         if (namespaceAware != null) {
sascha@4070:             factory.setNamespaceAware(namespaceAware.booleanValue());
sascha@4070:         }
sascha@4070: 
sascha@4070:         try {
sascha@4070:             return factory.newDocumentBuilder().parse(inputStream);
sascha@4070:         }
sascha@4070:         catch (ParserConfigurationException pce) {
sascha@4070:             log.error(pce.getLocalizedMessage(), pce);
sascha@4070:         }
sascha@4070:         catch (SAXException se) {
sascha@4070:             log.error(se.getLocalizedMessage(), se);
sascha@4070:         }
sascha@4070:         catch (IOException ioe) {
sascha@4070:             log.error(ioe.getLocalizedMessage(), ioe);
sascha@4070:         }
sascha@4070:         return null;
sascha@4070:     }
sascha@4070: 
sascha@4070: 
sascha@4070:     /**
sascha@4070:      * Creates a new XPath without a namespace context.
sascha@4070:      * @return the new XPath.
sascha@4070:      */
sascha@4070:     public static final XPath newXPath() {
sascha@4070:         return newXPath(null, null);
sascha@4070:     }
sascha@4070: 
sascha@4070:     /**
sascha@4070:      * Creates a new XPath with a given namespace context.
sascha@4070:      * @param namespaceContext The namespace context to be used or null
sascha@4070:      * if none should be used.
sascha@4070:      * @return The new XPath
sascha@4070:      */
sascha@4070:     public static final XPath newXPath(
sascha@4070:         NamespaceContext      namespaceContext,
sascha@4070:         XPathVariableResolver resolver)
sascha@4070:     {
sascha@4070:         XPathFactory factory = XPathFactory.newInstance();
sascha@4070:         XPath        xpath   = factory.newXPath();
sascha@4070:         if (namespaceContext != null) {
sascha@4070:             xpath.setNamespaceContext(namespaceContext);
sascha@4070:         }
sascha@4070: 
sascha@4070:         if (resolver != null) {
sascha@4070:             xpath.setXPathVariableResolver(resolver);
sascha@4070:         }
sascha@4070:         return xpath;
sascha@4070:     }
sascha@4070: 
sascha@4070:     /**
sascha@4070:      * Evaluates an XPath query on a given object and returns the result
sascha@4070:      * as a given type. No namespace context is used.
sascha@4070:      * @param root  The object which is used as the root of the tree to
sascha@4070:      * be searched in.
sascha@4070:      * @param query The XPath query
sascha@4070:      * @param returnTyp The type of the result.
sascha@4070:      * @return The result of type 'returnTyp' or null if something
sascha@4070:      * went wrong during XPath evaluation.
sascha@4070:      */
sascha@4070:     public static final Object xpath(
sascha@4070:         Object root,
sascha@4070:         String query,
sascha@4070:         QName  returnTyp
sascha@4070:     ) {
sascha@4070:         return xpath(root, query, returnTyp, null);
sascha@4070:     }
sascha@4070: 
sascha@4070:     /**
sascha@4070:      * Evaluates an XPath query on a given object and returns the result
sascha@4070:      * as a given type. Optionally a namespace context is used.
sascha@4070:      * @param root The object which is used as the root of the tree to
sascha@4070:      * be searched in.
sascha@4070:      * @param query The XPath query
sascha@4070:      * @param returnType The type of the result.
sascha@4070:      * @param namespaceContext The namespace context to be used or null
sascha@4070:      * if none should be used.
sascha@4070:      * @return The result of type 'returnTyp' or null if something
sascha@4070:      * went wrong during XPath evaluation.
sascha@4070:      */
sascha@4070:     public static final Object xpath(
sascha@4070:         Object           root,
sascha@4070:         String           query,
sascha@4070:         QName            returnType,
sascha@4070:         NamespaceContext namespaceContext
sascha@4070:     ) {
sascha@4070:         return xpath(root, query, returnType, namespaceContext, null);
sascha@4070:     }
sascha@4070: 
sascha@4070:     public static final Object xpath(
sascha@4070:         Object           root,
sascha@4070:         String           query,
sascha@4070:         QName            returnType,
sascha@4070:         NamespaceContext namespaceContext,
sascha@4070:         Map<String, String> variables)
sascha@4070:     {
sascha@4070:         if (root == null) {
sascha@4070:             return null;
sascha@4070:         }
sascha@4070: 
sascha@4070:         XPathVariableResolver resolver = variables != null
sascha@4070:             ? new MapXPathVariableResolver(variables)
sascha@4070:             : null;
sascha@4070: 
sascha@4070:         try {
sascha@4070:             XPath xpath = newXPath(namespaceContext, resolver);
sascha@4070:             if (xpath != null) {
sascha@4070:                 return xpath.evaluate(query, root, returnType);
sascha@4070:             }
sascha@4070:         }
sascha@4070:         catch (XPathExpressionException xpee) {
sascha@4070:             log.error(xpee.getLocalizedMessage(), xpee);
sascha@4070:         }
sascha@4070: 
sascha@4070:         return null;
sascha@4070:     }
sascha@4083: 
sascha@4083:     public static Document transform(
sascha@4083:         Document           document,
sascha@4083:         File               xformFile
sascha@4083:     ) {
sascha@4083:         try {
sascha@4083:             Transformer transformer =
sascha@4083:                 TransformerFactory
sascha@4083:                     .newInstance()
sascha@4083:                     .newTransformer(
sascha@4083:                         new StreamSource(xformFile));
sascha@4083: 
sascha@4083:             DOMResult result = new DOMResult();
sascha@4083: 
sascha@4083:             transformer.transform(new DOMSource(document), result);
sascha@4083: 
sascha@4083:             return (Document)result.getNode();
sascha@4083:         }
sascha@4083:         catch (TransformerConfigurationException tce) {
sascha@4083:             log.error(tce, tce);
sascha@4083:         }
sascha@4083:         catch (TransformerException te) {
sascha@4083:             log.error(te, te);
sascha@4083:         }
sascha@4083: 
sascha@4083:         return null;
sascha@4083:     }
sascha@4095: 
sascha@4095:    /**
sascha@4095:      * Streams out an XML document to a given output stream.
sascha@4095:      * @param document The document to be streamed out.
sascha@4095:      * @param out      The output stream to be used.
sascha@4095:      * @return true if operation succeeded else false.
sascha@4095:      */
sascha@4095:     public static boolean toStream(Document document, OutputStream out) {
sascha@4095:         try {
sascha@4095:             Transformer transformer =
sascha@4095:                 TransformerFactory.newInstance().newTransformer();
sascha@4095:             DOMSource    source = new DOMSource(document);
sascha@4095:             StreamResult result = new StreamResult(out);
sascha@4095:             transformer.transform(source, result);
sascha@4095:             return true;
sascha@4095:         }
sascha@4095:         catch (TransformerConfigurationException tce) {
sascha@4095:             log.error(tce.getLocalizedMessage(), tce);
sascha@4095:         }
sascha@4095:         catch (TransformerFactoryConfigurationError tfce) {
sascha@4095:             log.error(tfce.getLocalizedMessage(), tfce);
sascha@4095:         }
sascha@4095:         catch (TransformerException te) {
sascha@4095:             log.error(te.getLocalizedMessage(), te);
sascha@4095:         }
sascha@4095: 
sascha@4095:         return false;
sascha@4095:     }
sascha@4095: 
sascha@4095:     public static String toString(Document document) {
sascha@4095:         try {
sascha@4095:             Transformer transformer =
sascha@4095:                 TransformerFactory.newInstance().newTransformer();
sascha@4095:             DOMSource    source = new DOMSource(document);
sascha@4095:             StringWriter out    = new StringWriter();
sascha@4095:             StreamResult result = new StreamResult(out);
sascha@4095:             transformer.transform(source, result);
sascha@4095:             out.flush();
sascha@4095:             return out.toString();
sascha@4095:         }
sascha@4095:         catch (TransformerConfigurationException tce) {
sascha@4095:             log.error(tce.getLocalizedMessage(), tce);
sascha@4095:         }
sascha@4095:         catch (TransformerFactoryConfigurationError tfce) {
sascha@4095:             log.error(tfce.getLocalizedMessage(), tfce);
sascha@4095:         }
sascha@4095:         catch (TransformerException te) {
sascha@4095:             log.error(te.getLocalizedMessage(), te);
sascha@4095:         }
sascha@4095: 
sascha@4095:         return null;
sascha@4095:     }
sascha@4070: }
sascha@4070: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :