org.apache.hise.utils.XQueryEvaluator.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hise.utils.XQueryEvaluator.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF 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.apache.hise.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;

import net.sf.saxon.Configuration;
import net.sf.saxon.dom.DocumentWrapper;
import net.sf.saxon.dom.NodeOverNodeInfo;
import net.sf.saxon.expr.JPConverter;
import net.sf.saxon.functions.FunctionLibraryList;
import net.sf.saxon.functions.JavaExtensionLibrary;
import net.sf.saxon.om.NodeInfo;
import net.sf.saxon.om.StructuredQName;
import net.sf.saxon.om.ValueRepresentation;
import net.sf.saxon.query.DynamicQueryContext;
import net.sf.saxon.query.StaticQueryContext;
import net.sf.saxon.query.XQueryExpression;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.value.SequenceType;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Node;

/**
 * 
 * @author Rafa Rusin
 */
public class XQueryEvaluator {

    private Log __log = LogFactory.getLog(XQueryEvaluator.class);

    public static ThreadLocal<Object> contextObjectTL = new ThreadLocal<Object>();

    private Map<QName, Object> vars = new HashMap<QName, Object>();
    private Map<String, String> namespaces = new HashMap<String, String>();

    private Configuration config = Configuration.makeConfiguration(null, null);
    private JavaExtensionLibrary jel = new JavaExtensionLibrary(config);

    private Object contextObject;

    public void bindVariable(QName var, Object value) {
        vars.put(var, value);
    }

    public void declareJavaClass(String uri, Class clazz) {
        jel.declareJavaClass(uri, clazz);
    }

    public void declareNamespace(String prefix, String namespace) {
        namespaces.put(prefix, namespace);
    }

    public void setContextObject(Object contextObject) {
        this.contextObject = contextObject;
    }

    public ValueRepresentation convertJavaToSaxon(Object obj) {
        try {
            if (obj == null)
                obj = "";

            if (obj instanceof Node) {
                NodeInfo v = new DocumentWrapper((Node) obj, "", config).getRoot();
                return v;
            } else {
                return JPConverter.allocate(obj.getClass(), null).convert(obj, null);
            }
        } catch (XPathException e) {
            throw new RuntimeException("", e);
        }
    }

    public List evaluateExpression(String expr, org.w3c.dom.Node contextNode) {
        try {
            contextObjectTL.set(contextObject);
            {
                FunctionLibraryList fll = new FunctionLibraryList();
                fll.addFunctionLibrary(jel);
                config.setExtensionBinder("java", fll);
            }

            StaticQueryContext sqc = new StaticQueryContext(config);
            for (Map.Entry<String, String> namespace : namespaces.entrySet()) {
                sqc.declareNamespace(namespace.getKey(), namespace.getValue());
            }
            for (QName var : vars.keySet()) {
                sqc.declareGlobalVariable(StructuredQName.fromClarkName(var.toString()), SequenceType.SINGLE_ITEM,
                        convertJavaToSaxon(vars.get(var)), false);
            }
            DynamicQueryContext dqc = new DynamicQueryContext(config);
            XQueryExpression e = sqc.compileQuery(expr);

            if (contextNode != null) {
                if (!(contextNode instanceof Document || contextNode instanceof DocumentFragment)) {
                    try {
                        contextNode = DOMUtils.parse(DOMUtils.domToString(contextNode));
                    } catch (Exception e1) {
                        throw new RuntimeException("", e1);
                    }
                    //                    DocumentFragment frag = contextNode.getOwnerDocument().createDocumentFragment();
                    //                    frag.appendChild(contextNode);
                    //                    contextNode = frag;
                }
                dqc.setContextItem(new DocumentWrapper(contextNode, "", config));
            }

            List value = e.evaluate(dqc);
            List value2 = new ArrayList();
            for (Object o : value) {
                Object o2 = o;
                if (o2 instanceof NodeInfo) {
                    try {
                        Node o3 = DOMUtils.parse(DOMUtils.domToString(NodeOverNodeInfo.wrap((NodeInfo) o2)))
                                .getDocumentElement();
                        o2 = o3;
                    } catch (Exception e1) {
                        throw new RuntimeException("Error converting result", e1);
                    }
                }
                //                o2 = JavaDOMWrapper.unwrap(o2);
                value2.add(o2);
            }
            __log.debug("result for expression " + expr + " " + value2 + " value class "
                    + (value2 == null ? null : value2.getClass()));
            return value2;
        } catch (XPathException e) {
            __log.error("Expression: \n" + expr, e);
            throw new RuntimeException(e);
        } finally {
            contextObjectTL.set(null);
        }
    }
}