com.omertron.thetvdbapi.tools.DOMHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.omertron.thetvdbapi.tools.DOMHelper.java

Source

/*
 *      Copyright (c) 2004-2014 Matthew Altman & Stuart Boston
 *
 *      This file is part of TheTVDB API.
 *
 *      TheTVDB API is free software: you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation, either version 3 of the License, or
 *      any later version.
 *
 *      TheTVDB API is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with TheTVDB API.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
package com.omertron.thetvdbapi.tools;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
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.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.ws.WebServiceException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;
import org.yamj.api.common.http.CommonHttpClient;

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

    private static final Logger LOG = LoggerFactory.getLogger(DOMHelper.class);
    private static final String YES = "yes";
    private static final String ENCODING = "UTF-8";
    private static final int RETRY_COUNT = 5;
    // Milliseconds to retry
    private static final int RETRY_TIME = 250;
    private static CommonHttpClient httpClient = null;
    // Constants
    private static final String ERROR_WRITING = "Error writing the document to ";
    private static final String ERROR_UNABLE_TO_ENCODE_URL = "Unable to encode URL: ";
    private static final String ERROR_UNABLE_TO_PARSE = "Unable to parse TheTVDb response, please try again later.";

    // Hide the constructor
    protected DOMHelper() {
        // prevents calls from subclass
        throw new UnsupportedOperationException();
    }

    public static void setHttpClient(CommonHttpClient newHttpClient) {
        httpClient = newHttpClient;
    }

    /**
     * Gets the string value of the tag element name passed
     *
     * @param element
     * @param tagName
     * @return
     */
    public static String getValueFromElement(Element element, String tagName) {
        NodeList elementNodeList = element.getElementsByTagName(tagName);
        if (elementNodeList == null) {
            return "";
        } else {
            Element tagElement = (Element) elementNodeList.item(0);
            if (tagElement == null) {
                return "";
            }

            NodeList tagNodeList = tagElement.getChildNodes();
            if (tagNodeList == null || tagNodeList.getLength() == 0) {
                return "";
            }
            return ((Node) tagNodeList.item(0)).getNodeValue();
        }
    }

    /**
     * Get a DOM document from the supplied URL
     *
     * @param url
     * @return
     */
    public static synchronized Document getEventDocFromUrl(String url) {
        InputStream in = null;
        Document doc = null;

        try {
            String webPage = getValidWebpage(url);

            if (StringUtils.isNotBlank(webPage)) {
                in = new ByteArrayInputStream(webPage.getBytes(ENCODING));

                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                DocumentBuilder db = dbf.newDocumentBuilder();

                doc = db.parse(in);
                in.close();
                doc.getDocumentElement().normalize();
            }
        } catch (UnsupportedEncodingException ex) {
            throw new WebServiceException(ERROR_UNABLE_TO_ENCODE_URL + url, ex);
        } catch (ParserConfigurationException error) {
            throw new WebServiceException(ERROR_UNABLE_TO_PARSE, error);
        } catch (SAXException error) {
            throw new WebServiceException(ERROR_UNABLE_TO_PARSE, error);
        } catch (IOException error) {
            throw new WebServiceException(ERROR_UNABLE_TO_PARSE, error);
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                // Input Stream was already closed or null
                LOG.trace("Failed to close InputStream", ex);
            }
        }

        return doc;
    }

    private static String getValidWebpage(String url) {
        // Count the number of times we download the web page
        int retryCount = 0;
        // Is the web page valid
        boolean valid = false;
        String webPage;

        try {
            while (!valid && (retryCount < RETRY_COUNT)) {
                retryCount++;
                webPage = requestWebPage(url);
                if (StringUtils.isNotBlank(webPage)) {
                    // See if the ID is null
                    if (!webPage.contains("<id>") || webPage.contains("<id></id>")) {
                        // Wait an increasing amount of time the more retries that happen
                        waiting(retryCount * RETRY_TIME);
                        continue;
                    } else {
                        valid = true;
                    }
                }

                // Couldn't get a valid webPage so, quit.
                if (!valid) {
                    throw new WebServiceException("Failed to download data from " + url);
                }

                return webPage;
            }
        } catch (UnsupportedEncodingException ex) {
            throw new WebServiceException(ERROR_UNABLE_TO_ENCODE_URL + url, ex);
        } catch (IOException ex) {
            throw new WebServiceException("Unable to download URL: " + url, ex);
        }

        return null;
    }

    /**
     * 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();
    }

    /**
     * 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 localFile) {
        try {
            TransformerFactory transfact = TransformerFactory.newInstance();
            Transformer trans = transfact.newTransformer();
            trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, YES);
            trans.setOutputProperty(OutputKeys.INDENT, YES);
            trans.transform(new DOMSource(doc), new StreamResult(new File(localFile)));
            return true;
        } catch (TransformerConfigurationException ex) {
            LOG.warn(ERROR_WRITING + localFile, ex);
            return false;
        } catch (TransformerException ex) {
            LOG.warn(ERROR_WRITING + localFile, ex);
            return false;
        }
    }

    /**
     * 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) {
        Element child = doc.createElement(elementName);
        Text text = doc.createTextNode(elementValue);
        child.appendChild(text);
        parentElement.appendChild(child);
    }

    /**
     * Wait for a few milliseconds
     *
     * @param milliseconds
     */
    private static void waiting(int milliseconds) {
        long t0, t1;
        t0 = System.currentTimeMillis();
        do {
            t1 = System.currentTimeMillis();
        } while ((t1 - t0) < milliseconds);
    }

    private static String requestWebPage(String url) throws IOException {
        return httpClient.requestContent(url, Charset.forName(ENCODING));
    }
}