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

com.crabshue.commons.xpath.XPathFactoryUtils Maven / Gradle / Ivy

package com.crabshue.commons.xpath;

import java.util.HashMap;
import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
import javax.xml.xpath.XPathFactoryConfigurationException;
import javax.xml.xpath.XPathVariableResolver;

import net.sf.saxon.Configuration;
import net.sf.saxon.xpath.XPathFactoryImpl;
import org.xml.sax.InputSource;

import com.crabshue.commons.exceptions.ApplicationException;
import com.crabshue.commons.exceptions.SystemException;
import com.crabshue.commons.exceptions.context.CommonErrorContext;
import com.crabshue.commons.exceptions.utils.ExceptionMessageUtils;
import com.crabshue.commons.xml.namespace.NamespaceContextResolver;
import com.crabshue.commons.xpath.exceptions.XPathErrorContext;
import com.crabshue.commons.xpath.exceptions.XPathErrorType;
import lombok.NonNull;
import net.sf.saxon.lib.NamespaceConstant;

/**
 * Utility class for building XPaths.
 *
 */
public class XPathFactoryUtils {

    private static final String SAXON_XPATH_FACTORY = "net.sf.saxon.xpath.XPathFactoryImpl";

    private static XPathFactory xPathFactory;

    protected XPathFactoryUtils() {
    }

    /**
     * Create a new {@link XPath} with an {@link InputSource}.
     *
     * @param inputSource the input source.
     * @return the create XPath.
     * @see #newXPath(InputSource, Map)
     */
    public static XPath newXPath(@NonNull final InputSource inputSource) {

        return newXPath(inputSource, new HashMap<>());
    }

    /**
     * Create a new {@link XPath} with an {@link InputSource} with a variables map.
     *
     * @param inputSource the input source.
     * @param variables   the variables.
     * @return the created XPath.
     */
    public static XPath newXPath(@NonNull final InputSource inputSource,
        @NonNull final Map variables) {

        return newXPath(inputSource, variables, null);
    }

    /**
     * Create a new {@link XPath} with an {@link InputSource} with a variables map.
     *
     * @param inputSource the input source.
     * @param variables   the variables.
     * @param configuration the saxon configuration
     * @return the created XPath.
     */
    public static XPath newXPath(@NonNull final InputSource inputSource,
                                 @NonNull final Map variables,
                                 final Configuration configuration) {

        final XPathFactory xPathFactory = provideXPathFactory();

        if(configuration != null) {
            ((XPathFactoryImpl) xPathFactory).setConfiguration(configuration);
        }

        final XPath xpath = xPathFactory.newXPath();

        xpath.setNamespaceContext(new NamespaceContextResolver(inputSource));

        xpath.setXPathVariableResolver(new XPathVariableResolver() {
            @Override
            public Object resolveVariable(final QName qName) {
                final String variableName = qName.getLocalPart();
                if (!variables.containsKey(variableName)) {

                    throw new ApplicationException(XPathErrorType.ERROR_XPATH_EVALUATION, "Cannot resolve variable for XPath evaluation")
                        .addContextValue(XPathErrorContext.VARIABLE_NAME, variableName)
                        .addContextValue(XPathErrorContext.LIST, ExceptionMessageUtils.printMap(variables, String::toString, String::toString));
                }
                return variables.get(qName.getLocalPart());
            }
        });
        return xpath;
    }


    /**
     * Provide (create if not exists) a {@link XPathFactory}.
     *
     * @return the XPath factory
     */
    public static XPathFactory provideXPathFactory() {
        if (xPathFactory == null) {
            xPathFactory = newXpathFactory();
        }
        return xPathFactory;
    }

    /**
     * Create a new {@link XPathFactory}.
     *
     * @return the new XPath factory.
     */
    public static XPathFactory newXpathFactory() {
        try {
            return XPathFactory.newInstance(
                NamespaceConstant.OBJECT_MODEL_SAXON,
                SAXON_XPATH_FACTORY,
                XmlPathCalculator.class.getClass().getClassLoader());
        } catch (XPathFactoryConfigurationException e) {
            throw new SystemException(XPathErrorType.ERROR_XPATH_EVALUATION, e.getMessage())
                .addContextValue(CommonErrorContext.CAUSE, e.getMessage());
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy