All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.moviejukebox.tools.DOMHelper Maven / Gradle / Ivy

There is a newer version: 2.9
Show newest version
/*
 *      Copyright (c) 2004-2012 YAMJ Members
 *      http://code.google.com/p/moviejukebox/people/list
 *
 *      Web: http://code.google.com/p/moviejukebox/
 *
 *      This software is licensed under a Creative Commons License
 *      See this page: http://code.google.com/p/moviejukebox/wiki/License
 *
 *      For any reuse or distribution, you must make clear to others the
 *      license terms of this work.
 */
package com.moviejukebox.tools;

import com.moviejukebox.writer.MovieNFOReader;
import java.io.*;
import java.net.URL;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.w3c.dom.*;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
 * Generic set of routines to process the DOM model data Used for read XML files.
 *
 * @author Stuart.Boston
 *
 */
public class DOMHelper {

    private static final Logger logger = Logger.getLogger(DOMHelper.class);
    private static final String logMessage = "DOMHelper: ";
    private static final String DEFAULT_RETURN = "";
    private static final String YES = "yes";
    private static final String TYPE_ROOT = "xml";

    /**
     * Add a child element to a parent element
     *
     * @param doc
     * @param parentElement
     * @param elementName
     * @param elementValue
     */
    public static void appendChild(Document doc, Element parentElement, String elementName, String elementValue) {
        appendChild(doc, parentElement, elementName, elementValue, null);
    }

    /**
     * Add a child element to a parent element with a set of attributes
     *
     * @param doc
     * @param parentElement
     * @param elementName
     * @param elementValue
     * @param childAttributes
     */
    public static void appendChild(Document doc, Element parentElement, String elementName, String elementValue, Map childAttributes) {
        Element child = doc.createElement(elementName);
        Text text = doc.createTextNode(elementValue);
        child.appendChild(text);

        if (childAttributes != null && !childAttributes.isEmpty()) {
            for (Map.Entry attrib : childAttributes.entrySet()) {
                child.setAttribute(attrib.getKey(), attrib.getValue());
            }
        }

        parentElement.appendChild(child);
    }

    /**
     * Append a child element to a parent element with a single attribute/value pair
     *
     * @param doc
     * @param parentElement
     * @param elementName
     * @param elementValue
     * @param attribName
     * @param attribValue
     */
    public static void appendChild(Document doc, Element parentElement, String elementName, String elementValue, String attribName, String attribValue) {
        Element child = doc.createElement(elementName);
        Text text = doc.createTextNode(elementValue);
        child.appendChild(text);
        child.setAttribute(attribName, attribValue);
        parentElement.appendChild(child);
    }

    /**
     * Convert a DOM document to a string
     *
     * @param doc
     * @return
     * @throws TransformerException
     */
    public static String convertDocToString(Document doc) throws TransformerException {
        //set up a transformer
        TransformerFactory transfac = TransformerFactory.newInstance();
        Transformer trans = transfac.newTransformer();
        trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, YES);
        trans.setOutputProperty(OutputKeys.INDENT, YES);

        //create string from xml tree
        StringWriter sw = new StringWriter();
        StreamResult result = new StreamResult(sw);
        DOMSource source = new DOMSource(doc);
        trans.transform(source, result);
        return sw.toString();
    }

    /**
     * Create a blank Document
     *
     * @return a Document
     * @throws ParserConfigurationException
     */
    public static Document createDocument() throws ParserConfigurationException {
        DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
        return docBuilder.newDocument();
    }

    /**
     * Get a DOM document from the supplied string
     *
     * @param docString
     * @return
     */
    public static Document getDocFromString(String docString) {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        InputSource is = new InputSource(new StringReader(docString));
        DocumentBuilder db;
        Document doc = null;

        try {
            db = dbf.newDocumentBuilder();
            doc = db.parse(is);
            return doc;
        } catch (SAXException ex) {
            String errorString = docString.substring(0, Math.min(40, docString.length()));
            logger.warn(logMessage + "Failed to get document from " + errorString + " Error: " + ex.getMessage());
        } catch (IOException ex) {
            String errorString = docString.substring(0, Math.min(40, docString.length()));
            logger.warn(logMessage + "Failed to get document from " + errorString + " Error: " + ex.getMessage());
        } catch (ParserConfigurationException ex) {
            String errorString = docString.substring(0, Math.min(40, docString.length()));
            logger.warn(logMessage + "Failed to get document from " + errorString + " Error: " + ex.getMessage());
        }

        return doc;
    }

    /**
     * Get a DOM document from the supplied file
     *
     * @param xmlFile
     * @return
     * @throws MalformedURLException
     * @throws IOException
     * @throws ParserConfigurationException
     * @throws SAXException
     */
    public static Document getDocFromFile(File xmlFile) throws ParserConfigurationException, SAXException, IOException {
        URL url = xmlFile.toURI().toURL();
        InputStream in = url.openStream();
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc;

        // Custom error handler
        db.setErrorHandler(new SaxErrorHandler());

        try {
            doc = db.parse(in);
        } catch (SAXParseException ex) {
            doc = null;
        } finally {
            // close the stream
            in.close();
        }

        if (doc == null) {
            // try wrapping the file in a root
            String wrappedFile = wrapInXml(FileTools.readFileToString(xmlFile));
            doc = db.parse(new InputSource(new StringReader(wrappedFile)));
        }

        doc.getDocumentElement().normalize();
        return doc;
    }

    /**
     * Gets the string value of the tag element name passed
     *
     * @param element
     * @param tagName
     * @return
     */
    public static String getValueFromElement(Element element, String tagName) {
        String returnValue = DEFAULT_RETURN;

        try {
            NodeList nlElement = element.getElementsByTagName(tagName);
            Element tagElement = (Element) nlElement.item(0);
            NodeList tagNodeList = tagElement.getChildNodes();
            returnValue = ((Node) tagNodeList.item(0)).getNodeValue();
        } catch (Exception ignore) {
            return returnValue;
        }

        return returnValue;
    }

    /**
     * Get an element from a parent element node
     *
     * @param eParent
     * @param elementName
     * @return
     */
    public static Element getElementByName(Element eParent, String elementName) {
        NodeList nlParent = eParent.getElementsByTagName(elementName);
        for (int looper = 0; looper < nlParent.getLength(); looper++) {
            if (nlParent.item(looper).getNodeType() == Node.ELEMENT_NODE) {
                return (Element) nlParent.item(looper);
            }
        }
        return null;
    }

    /**
     * Write the Document out to a file using nice formatting
     *
     * @param doc The document to save
     * @param localFile The file to write to
     * @return
     */
    public static boolean writeDocumentToFile(Document doc, String localFilename) {
        return writeDocumentToFile(doc, new File(localFilename));
    }

    /**
     * Write the Document out to a file using nice formatting
     *
     * @param doc The document to save
     * @param localFile The file to write to
     * @return
     */
    public static boolean writeDocumentToFile(Document doc, File localFile) {
        try {
            Transformer trans = TransformerFactory.newInstance().newTransformer();

            // Define the output properties
            trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
            trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            trans.setOutputProperty(OutputKeys.INDENT, YES);
            trans.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
            doc.setXmlStandalone(true);

            trans.transform(new DOMSource(doc), new StreamResult(localFile));
            return true;
        } catch (Exception error) {
            logger.error(logMessage + "Error writing the document to " + localFile);
            logger.error(logMessage + "Message: " + error.getMessage());
            return false;
        }
    }

    /**
     * Override the standard Sax ErrorHandler with this one, to minimise noise about failed parsing errors
     */
    public static class SaxErrorHandler implements ErrorHandler {

        @Override
        public void warning(SAXParseException exception) throws SAXException {
//            logger.warn(buildMessage(exception, "Warning"));
            throw new SAXParseException(null, null, exception);
        }

        @Override
        public void error(SAXParseException exception) throws SAXException {
//            logger.warn(buildMessage(exception, "Error"));
            throw new SAXParseException(null, null, exception);
        }

        @Override
        public void fatalError(SAXParseException exception) throws SAXException {
//            logger.warn(buildMessage(exception, "Fatal Error"));
            throw new SAXParseException(null, null, exception);
        }

        public String buildMessage(SAXParseException exception) {
            return buildMessage(exception, null);
        }

        public String buildMessage(SAXParseException exception, String level) {
            StringBuilder message = new StringBuilder("Parsing ");
            if (StringUtils.isNotBlank(level)) {
                message.append(level);
            } else {
                message.append("Error");
            }
            message.append(" - ");
            message.append(" Line: ").append(exception.getLineNumber());
            message.append(" Column: ").append(exception.getColumnNumber());
            message.append(" Message: ").append(exception.getMessage());
            return message.toString();
        }
    }

    /**
     * Take a file and wrap it in a new root element
     *
     * @param fileString
     * @return
     */
    public static String wrapInXml(String fileString) {
        StringBuilder newOutput = new StringBuilder(fileString);

        int posMovie = fileString.indexOf("<" + MovieNFOReader.TYPE_MOVIE);
        int posTvShow = fileString.indexOf("<" + MovieNFOReader.TYPE_TVSHOW);
        int posEpisode = fileString.indexOf("<" + MovieNFOReader.TYPE_EPISODE);

        boolean posValid = Boolean.FALSE;

        if (posMovie == -1) {
            posMovie = fileString.length();
        } else {
            posValid = Boolean.TRUE;
        }

        if (posTvShow == -1) {
            posTvShow = fileString.length();
        } else {
            posValid = Boolean.TRUE;
        }

        if (posEpisode == -1) {
            posEpisode = fileString.length();
        } else {
            posValid = Boolean.TRUE;
        }

        if (posValid) {
            int pos = Math.min(posMovie, Math.min(posTvShow, posEpisode));
            newOutput.insert(pos, "<" + TYPE_ROOT + ">");
            newOutput.append("");
        }

        return newOutput.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy