org.dawb.passerelle.common.utils.XMLUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.dawb.passerelle.common.utils.XMLUtils.java

Source

/*
 * Copyright (c) 2012 European Synchrotron Radiation Facility,
 *                    Diamond Light Source Ltd.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
package org.dawb.passerelle.common.utils;

import java.io.File;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import org.apache.commons.digester.substitution.MultiVariableExpander;
import org.apache.commons.digester.substitution.VariableSubstitutor;
import org.dawb.common.util.io.Grep;
import org.eclipse.core.resources.IFile;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

public class XMLUtils {

    private static final String VARIABLE_EXPRESSION = "\\$\\{([a-zA-Z0-9_ ]+)\\}";

    /**
     * Returns a list of strings surrounded by ${ } in the file.
     * @param file
     * @return
     * @throws Exception 
     */
    public static List<String> getVariables(String data) throws Exception {
        return Grep.group(data, VARIABLE_EXPRESSION, 1);
    }

    /**
     * Returns a list of strings surrounded by ${ } in the file.
     * @param file
     * @return
     * @throws Exception 
     */
    public static List<CharSequence> getVariables(IFile file) throws Exception {
        return Grep.group(file, VARIABLE_EXPRESSION, 1);
    }

    private static final Pattern HEADER_PATTERN = Pattern.compile("^\\<\\?.+\\?\\>(.*)", Pattern.DOTALL);

    public static Map<String, String> getVariables(final Map<?, ?> variables, final String xmlSource,
            final Map<String, String> scalarSource) throws Exception {

        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        docFactory.setNamespaceAware(false); // never forget this!
        docFactory.setValidating(false);
        DocumentBuilder builder = docFactory.newDocumentBuilder();
        Document doc = null;

        XPathFactory factory = XPathFactory.newInstance();
        XPath xpath = factory.newXPath();

        final Map<String, String> values = new HashMap<String, String>(variables.size());
        for (Object varName : variables.keySet()) {
            final String varValue = (String) variables.get(varName.toString());
            if (varValue == null || "".equals(varValue)) {
                values.put(varName.toString(), scalarSource.get(varName));
                continue;
            }

            if ("/".equals(varValue)) {
                values.put(varName.toString(), xmlSource);
                continue;
            }

            final XPathExpression exp = xpath.compile(varValue);
            if (doc == null)
                doc = builder.parse(new InputSource(new StringReader(xmlSource)));

            final NodeList nodeList = (NodeList) exp.evaluate(doc, XPathConstants.NODESET);
            values.put(varName.toString(), getNodeValue(nodeList));
        }

        // We allow names of variables to expand values of other variables.
        final Map<String, String> all = new HashMap<String, String>(values.size());
        all.putAll(scalarSource);
        all.putAll(values);

        final Map<String, String> ret = new HashMap<String, String>(variables.size());
        final MultiVariableExpander expander = new MultiVariableExpander();
        expander.addSource("$", all);

        // Create a substitutor with the expander
        final VariableSubstitutor substitutor = new VariableSubstitutor(expander);

        for (final String varName : values.keySet()) {

            if (!varName.contains("$")) {
                ret.put(varName, values.get(varName));
            } else {
                ret.put(substitutor.substitute(varName), values.get(varName));
            }
        }

        return ret;
    }

    private static String getNodeValue(NodeList nodeList)
            throws TransformerFactoryConfigurationError, TransformerException {

        final Transformer serializer = TransformerFactory.newInstance().newTransformer();
        serializer.setURIResolver(null);

        final StringBuilder buf = new StringBuilder();
        for (int i = 0; i < nodeList.getLength(); i++) {
            final StringWriter sw = new StringWriter();
            serializer.transform(new DOMSource(nodeList.item(i)), new StreamResult(sw));
            String xml = sw.toString();
            final Matcher matcher = HEADER_PATTERN.matcher(xml);
            if (matcher.matches()) {
                xml = matcher.group(1);
            }
            buf.append(xml);
            buf.append("\n");
        }

        return buf.toString();
    }

    public static String getXPathValue(IFile file, String xPath) throws Exception {

        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        docFactory.setNamespaceAware(false); // never forget this!
        docFactory.setValidating(false);
        DocumentBuilder builder = docFactory.newDocumentBuilder();

        XPathFactory factory = XPathFactory.newInstance();
        XPath xpath = factory.newXPath();
        final XPathExpression exp = xpath.compile(xPath);

        Document doc = builder.parse(new InputSource(file.getContents()));

        final NodeList nodeList = (NodeList) exp.evaluate(doc, XPathConstants.NODESET);
        return XMLUtils.getNodeValue(nodeList);
    }

    // Same method as above but with File instead of IFile as input type
    // TODO: Remove code duplication
    public static String getXPathValue(File file, String xPath) throws Exception {

        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        docFactory.setNamespaceAware(false); // never forget this!
        docFactory.setValidating(false);
        DocumentBuilder builder = docFactory.newDocumentBuilder();

        XPathFactory factory = XPathFactory.newInstance();
        XPath xpath = factory.newXPath();
        final XPathExpression exp = xpath.compile(xPath);

        Document doc = builder.parse(new InputSource(file.getAbsolutePath()));

        final NodeList nodeList = (NodeList) exp.evaluate(doc, XPathConstants.NODESET);
        return XMLUtils.getNodeValue(nodeList);
    }

    /**
     * 
     * @param xPath
     * @throws Exception - if path invalid.
     */
    public static void isLegalXPath(final String xPath) throws Exception {
        XPathFactory factory = XPathFactory.newInstance();
        XPath xpath = factory.newXPath();
        xpath.compile(xPath);
    }

}