org.cauldron.einstein.ri.core.model.data.xml.dom.DOMUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.cauldron.einstein.ri.core.model.data.xml.dom.DOMUtil.java

Source

/******************************************************************************
 *                                                                            *
 *                                                                            *
 *     All works are (C) 2008 - Mangala Solutions Ltd and Paremus Ltd.
 *                                                                            *
 *     Jointly liicensed to Mangala Solutions and Paremus under one           *
 *     or more contributor license agreements.  See the NOTICE file           *
 *     distributed with this work for additional information                  *
 *     regarding copyright ownership.  Mangala Solutions and Paremus          *
 *     licenses this file to you under the Apache License, Version            *
 *     2.0 (the "License"); you may not use this file except in               *
 *     compliance with the License.  You may obtain a copy of the             *
 *     License at                                                             *
 *                                                                            *
 *             http://www.apache.org/licenses/LICENSE-2.0                     *
 *                                                                            *
 *     Unless required by applicable law or agreed to in writing,             *
 *     software distributed under the License is distributed on an            *
 *     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY                 *
 *     KIND, either express or implied.  See the License for the              *
 *     specific language governing permissions and limitations                *
 *     under the License.                                                     *
 *                                                                            *
 ******************************************************************************/

package org.cauldron.einstein.ri.core.model.data.xml.dom;

import com.thoughtworks.xstream.XStream;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.cauldron.einstein.api.message.data.exception.DataConversionRuntimeException;
import org.cauldron.einstein.api.message.data.model.DataObject;
import org.cauldron.einstein.ri.core.log.Logger;
import org.cauldron.einstein.ri.core.runtime.EinsteinRIRuntimeFactory;
import org.contract4j5.contract.Post;
import org.contract4j5.contract.Pre;
import org.w3c.dom.*;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * @author Neil Ellis
 */
@org.contract4j5.contract.Contract
public class DOMUtil {

    private static final Logger log = Logger.getLogger(DOMUtil.class);

    private static final XStream xstream = new XStream();
    private static final DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
    private static final TransformerFactory transformerFactory = TransformerFactory.newInstance();

    static XMLDOMDataObject createXMLDOMObjectFromArbitraryObject(Object o) {
        if (o == null) {
            log.debug("Creating XMLDOM Null DataObject.");
            try {
                return new XMLDOMDataObject(
                        docBuilderFactory.newDocumentBuilder().newDocument().createDocumentFragment());
            } catch (ParserConfigurationException e) {
                throw new DataConversionRuntimeException(e);
            }
        }
        return new XMLDOMDataObject(createDOMFromObject(o));
    }

    @Post
    @Pre
    static DocumentFragment createDOMFromObject(List<DataObject> objects) {
        log.debug("Creating XMLDOM DataList.");
        DocumentBuilder docBuilder = null;
        try {
            docBuilder = docBuilderFactory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            throw new DataConversionRuntimeException(e);
        }
        DocumentFragment fragment;
        Document doc = docBuilder.newDocument();
        fragment = doc.createDocumentFragment();
        for (DataObject dataObject : objects) {
            final XMLDOMDataObject object = (XMLDOMDataObject) EinsteinRIRuntimeFactory.getInstance().getRuntime()
                    .getRosettaStone().convert(XMLDOMDataModel.class, dataObject);
            final Node node = object.getNode();
            doc.adoptNode(node);
            fragment.appendChild(node);
        }
        return fragment;
    }

    @Post
    @Pre
    static Node createDOMFromObject(Object o) {
        Document doc;
        try {
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
            if (o instanceof String) {
                log.debug("Creating XMLDOM DataObject from String");
                doc = docBuilder.parse(new ByteArrayInputStream(((String) o).getBytes()));
            } else if (o instanceof byte[]) {
                log.debug("Creating XMLDOM DataObject from byte[]");
                doc = docBuilder.parse(new ByteArrayInputStream((byte[]) o));
            } else if (o instanceof InputStream) {
                log.debug("Creating XMLDOM DataObject from InpuStream");
                doc = docBuilder.parse((InputStream) o);
                //            } else if (o instanceof NodeList) {
                //                log.debug("Creating XMLDOM DataObject from NodeList");
                //                if(true)throw new Error();
                //                NodeList nodeList = (NodeList) o;
                //                fragment = buildFragmentFromNodeList(docBuilder, nodeList);
                //                return fragment;

            } else if (o instanceof Node) {
                log.debug("Building fragment from a node.");
                return (Node) o;
            } else {
                log.debug("Creating XMLDOM DataObject from Object");
                doc = docBuilder.parse(new ByteArrayInputStream(xstream.toXML(o).getBytes()));
            }
        } catch (ParserConfigurationException e) {
            throw new DataConversionRuntimeException(e);
        } catch (SAXException e) {
            throw new DataConversionRuntimeException(e);
        } catch (IOException e) {
            throw new DataConversionRuntimeException(e);
            //        } catch (TransformerException e) {
            //            throw new DataConversionRuntimeException(e);
        }
        final DocumentFragment fragment = doc.createDocumentFragment();
        final Element element = doc.getDocumentElement();
        fragment.getOwnerDocument().adoptNode(element);
        fragment.appendChild(element);
        return fragment;
    }

    @Post
    @Pre
    public static DocumentFragment buildFragmentFromNodeList(DocumentBuilder docBuilder, NodeList nodeList)
            throws IOException, TransformerException, SAXException {
        Document doc;
        DocumentFragment fragment;
        /*
        I know this is convoluted but it's very difficult to actually add a bunch of random nodes to
        a document fragment without getting errors. This works by normalizing the nodes.
         */
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byteArrayOutputStream.write("<dummy>".getBytes());
        Transformer xformer = transformerFactory.newTransformer();
        xformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        for (int i = 0; i < nodeList.getLength(); i++) {
            Source source = new DOMSource(nodeList.item(i));
            Result result = new StreamResult(byteArrayOutputStream);
            xformer.transform(source, result);
        }
        byteArrayOutputStream.write("</dummy>".getBytes());
        log.debug("Dumy node {0}.", byteArrayOutputStream);

        doc = docBuilder.parse(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
        fragment = doc.createDocumentFragment();
        nodeList = doc.getDocumentElement().getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            log.debug("Moving temporary node.");
            final Node node = nodeList.item(i);
            doc.adoptNode(node);
            fragment.appendChild(node);
        }
        log.debug("Fragment is now {0}.", fragment);
        return fragment;
    }

    //
    //    @Post
    //    @Pre
    //    public static Node cloneNode(DocumentBuilder docBuilder, Node node) throws
    //                                                                        IOException,
    //                                                                        TransformerException,
    //                                                                        SAXException {
    //        Document doc;
    //        DocumentFragment fragment;
    //        /*
    //            I know this is convoluted but it's very difficult to actually add a bunch of random nodes to
    //            a document fragment without getting errors. This works by normalizing the nodes.
    //         */
    //        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    //        byteArrayOutputStream.write("<dummy>".getBytes());
    //        Transformer xformer = transformerFactory.newTransformer();
    //        xformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
    //        Source source = new DOMSource(node);
    //        Result result = new StreamResult(byteArrayOutputStream);
    //        xformer.transform(source, result);
    //        byteArrayOutputStream.write("</dummy>".getBytes());
    //        log.debug("Dumy node {0}.", byteArrayOutputStream);
    //
    //        doc = docBuilder.parse(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
    //        fragment = doc.createDocumentFragment();
    //        NodeList nodeList = doc.getDocumentElement().getChildNodes();
    //        for (int i = 0; i < nodeList.getLength(); i++) {
    //            log.debug("Moving temporary node.");
    //            final Node newNode = nodeList.item(i);
    //            doc.adoptNode(newNode);
    //            fragment.appendChild(newNode);
    //        }
    //        log.debug("Fragment is now {0}.", fragment);
    //        return fragment;
    //    }

    @Post
    @Pre
    public static DocumentFragment buildFragmentFromNode(DocumentBuilder docBuilder, Node node)
            throws IOException, TransformerException, SAXException {
        Document doc;
        DocumentFragment fragment;
        /*
        I know this is convoluted but it's very difficult to actually add a bunch of random nodes to
        a document fragment without getting errors. XML DOM APIs are bloomin sketchy so this guarantees
        that the node can be added.  Need to throw this rubbish away and use a better XML API really.
         */
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byteArrayOutputStream.write("<dummy>".getBytes());
        Transformer xformer = transformerFactory.newTransformer();
        xformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        Source source = new DOMSource(node);
        Result result = new StreamResult(byteArrayOutputStream);
        xformer.transform(source, result);
        byteArrayOutputStream.write("</dummy>".getBytes());

        log.debug("Dumy node {0}.", byteArrayOutputStream);

        doc = docBuilder.parse(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
        fragment = doc.createDocumentFragment();
        final Element element = doc.getDocumentElement();
        if (element.hasChildNodes()) {
            //has child nodes, not text.
            NodeList nodeList = element.getChildNodes();
            for (int i = 0; i < nodeList.getLength(); i++) {
                log.debug("Moving temporary node.");
                final Node newNode = nodeList.item(i);
                doc.adoptNode(newNode);
                fragment.appendChild(newNode);
            }
        }

        log.debug("Fragment is now {0}.", ReflectionToStringBuilder.reflectionToString(fragment));
        return fragment;
    }

}