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

org.apache.xmlbeans.impl.store.Query Maven / Gradle / Ivy

Go to download

The Apache Commons Codec package contains simple encoder and decoders for various formats such as Base64 and Hexadecimal. In addition to these widely used encoders and decoders, the codec package also maintains a collection of phonetic encoding utilities.

The newest version!
/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed 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.xmlbeans.impl.store;

import org.apache.xmlbeans.*;
import org.apache.xmlbeans.impl.common.DefaultClassLoaderResourceLoader;
import org.apache.xmlbeans.impl.common.XPath;
import org.w3c.dom.*;

import javax.xml.namespace.QName;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Date;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;

public abstract class Query
{
    public static final String QUERY_DELEGATE_INTERFACE = "QUERY_DELEGATE_INTERFACE";
    public static String _useDelegateForXQuery = "use delegate for xquery";
    public static String _useXdkForXQuery = "use xdk for xquery";

    private static String _delIntfName;
    //private static HashMap _delegateQueryCache = new HashMap();

    private static HashMap _xdkQueryCache = new HashMap();
    private static Method _xdkCompileQuery;
    private static boolean _xdkAvailable = true;  // at the beginning assume is available

    private static HashMap _xqrlQueryCache = new HashMap(); //todo check for memory leaks
    private static Method _xqrlCompileQuery;
    private static boolean _xqrlAvailable = true;  // at the beginning assume is available

    private static HashMap _xqrl2002QueryCache = new HashMap();
    private static Method  _xqrl2002CompileQuery;
    private static boolean _xqrl2002Available = true;  // at the beginning assume is available

    static
    {
        String id = "META-INF/services/org.apache.xmlbeans.impl.store.QueryDelegate.QueryInterface";
        InputStream in = new DefaultClassLoaderResourceLoader().getResourceAsStream(id);
        try
        {
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            _delIntfName = br.readLine().trim();
            br.close();
        }
        catch (Exception e)
        {
            _delIntfName = null;
        }
    }

    abstract XmlObject[] objectExecute(Cur c, XmlOptions options);

    abstract XmlCursor cursorExecute(Cur c, XmlOptions options);

    //
    // Xqrl store specific implementation of compiled path/query
    //

    static XmlObject[] objectExecQuery(Cur c, String queryExpr, XmlOptions options)
    {
        return getCompiledQuery(queryExpr, options).objectExecute(c, options);
    }

    static XmlCursor cursorExecQuery(Cur c, String queryExpr, XmlOptions options)
    {
        return getCompiledQuery(queryExpr, options).cursorExecute(c, options);
    }

    public static synchronized Query getCompiledQuery(String queryExpr, XmlOptions options)
    {
        return getCompiledQuery(queryExpr, Path.getCurrentNodeVar(options), options);
    }

    static synchronized Query getCompiledQuery(String queryExpr, String currentVar, XmlOptions options)
    {
        assert queryExpr != null;
        options = XmlOptions.maskNull(options);
        Query query;

        if (options.hasOption(Path._forceXqrl2002ForXpathXQuery))
        {
            query = (Query)_xqrl2002QueryCache.get(queryExpr);
            if (query!=null)
                return query;

            query = getXqrl2002CompiledQuery(queryExpr, currentVar);
            if (query!=null)
            {
                _xqrl2002QueryCache.put(queryExpr, query);
                return query;
            }
            throw new RuntimeException("No 2002 query engine found.");
        }

        //Parse the query via XBeans: need to figure out end of prolog
        //in order to bind $this...not good but...
        Map boundary = new HashMap();
        int boundaryVal = 0;
        try
        {
            XPath.compileXPath(queryExpr, currentVar, boundary);
        }
        catch (XPath.XPathCompileException e)
        {
            //don't care if it fails, just care about boundary
        }
        finally
        {
            boundaryVal = boundary.get(XPath._NS_BOUNDARY) == null ? 0 :
                ((Integer) boundary.get(XPath._NS_BOUNDARY)).intValue();
        }

        if (options.hasOption(_useXdkForXQuery))
        {
            //try XDK
            query = (Query) _xdkQueryCache.get(queryExpr);
            if (query != null)
                return query;

            query = createXdkCompiledQuery(queryExpr, currentVar);
            if (query != null)
            {
                _xdkQueryCache.put(queryExpr, query);
                return query;
            }
        }

        if (!options.hasOption(_useDelegateForXQuery))
        {
        //try XQRL
        query = (Query) _xqrlQueryCache.get(queryExpr);
        if (query != null)
            return query;

        query = createXqrlCompiledQuery(queryExpr, currentVar);
        if (query != null)
        {
            _xqrlQueryCache.put(queryExpr, query);
            return query;
        }
        }

        //otherwise (if _useDelegateForXQuery option is set), 
        //or if xqrl is not found, try delegate
        //query = (Query) _delegateQueryCache.get(queryExpr);

        //if (query != null)
        //    return query;

        String delIntfName = 
            options.hasOption(QUERY_DELEGATE_INTERFACE) ? 
                (String)options.get(QUERY_DELEGATE_INTERFACE) : _delIntfName;
        query = DelegateQueryImpl.createDelegateCompiledQuery(delIntfName, queryExpr, currentVar, boundaryVal, options);

        if (query != null)
        {
            //_delegateQueryCache.put(queryExpr, query);
            return query;
        }

        throw new RuntimeException("No query engine found");
    }

    public static synchronized String compileQuery(String queryExpr, XmlOptions options)
    {
        getCompiledQuery(queryExpr, options);
        return queryExpr;
    }

    private static Query createXdkCompiledQuery(String queryExpr, String currentVar)
    {
        //if the XDK engine has been determined unavailable, return null
        if ( !_xdkAvailable ) return null;
        if ( _xdkCompileQuery == null)
        {
            try
            {
                Class xdkImpl = Class.forName("org.apache.xmlbeans.impl.store.OXQXBXqrlImpl");

                _xdkCompileQuery =
                    xdkImpl.getDeclaredMethod("compileQuery",
                        new Class[]{String.class, String.class, Boolean.class});
            }
            catch (ClassNotFoundException e)
            {
                _xdkAvailable = false;
                return null;
            }
            catch (Exception e)
            {
                _xdkAvailable = false;
                throw new RuntimeException(e.getMessage(), e);
            }
        }

        Object[] args = new Object[]{queryExpr, currentVar, new Boolean(true)};

        try
        {
            return (Query) _xdkCompileQuery.invoke(null, args);
        }
        catch (InvocationTargetException e)
        {
            Throwable t = e.getCause();
            throw new RuntimeException(t.getMessage(), t);
        }
        catch (IllegalAccessException e)
        {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    private static Query createXqrlCompiledQuery(String queryExpr, String currentVar)
    {
        //if the XQRL engine has been determined unavailable, return null
        if ( !_xqrlAvailable ) return null;
        if ( _xqrlCompileQuery == null)
        {
            try
            {
                Class xqrlImpl = Class.forName("org.apache.xmlbeans.impl.store.XqrlImpl");

                _xqrlCompileQuery =
                        xqrlImpl.getDeclaredMethod("compileQuery",
                                new Class[]{String.class, String.class, Boolean.class});
            }
            catch (ClassNotFoundException e)
            {
                _xqrlAvailable = false;
                return null;
            }
            catch (Exception e)
            {
                _xqrlAvailable = false;
                throw new RuntimeException(e.getMessage(), e);
            }
        }

        Object[] args = new Object[]{queryExpr, currentVar, new Boolean(true)};

        try
        {
            return (Query) _xqrlCompileQuery.invoke(null, args);
        }
        catch (InvocationTargetException e)
        {
            Throwable t = e.getCause();
            throw new RuntimeException(t.getMessage(), t);
        }
        catch (IllegalAccessException e)
        {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    private static Query getXqrl2002CompiledQuery(String queryExpr, String currentVar)
    {
        if (_xqrl2002Available && _xqrl2002CompileQuery == null)
        {
            try
            {
                Class xqrlImpl = Class.forName("org.apache.xmlbeans.impl.store.Xqrl2002Impl");

                _xqrl2002CompileQuery =
                        xqrlImpl.getDeclaredMethod("compileQuery",
                                new Class[]{String.class, String.class, Boolean.class});
            }
            catch (ClassNotFoundException e)
            {
                _xqrl2002Available = false;
                return null;
            }
            catch (Exception e)
            {
                _xqrl2002Available = false;
                throw new RuntimeException(e.getMessage(), e);
            }
        }

        Object[] args = new Object[]{queryExpr, currentVar, new Boolean(true)};

        try
        {
            return (Query) _xqrl2002CompileQuery.invoke(null, args);
        }
        catch (InvocationTargetException e)
        {
            Throwable t = e.getCause();
            throw new RuntimeException(t.getMessage(), t);
        }
        catch (IllegalAccessException e)
        {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    private static final class DelegateQueryImpl extends Query
    {
        private DelegateQueryImpl(QueryDelegate.QueryInterface xqueryImpl)
        {
            _xqueryImpl = xqueryImpl;
        }

        static Query createDelegateCompiledQuery(String delIntfName,
                                                 String queryExpr,
                                                 String currentVar,
                                                 int boundary,
                                                 XmlOptions xmlOptions)
        {
            assert !(currentVar.startsWith(".") || currentVar.startsWith(".."));
            QueryDelegate.QueryInterface impl =
                QueryDelegate.createInstance(delIntfName, queryExpr,
                                             currentVar, boundary, xmlOptions);
            if (impl == null)
                return null;

            return new DelegateQueryImpl(impl);
        }

        XmlObject[] objectExecute(Cur c, XmlOptions options)
        {
            return new DelegateQueryEngine(_xqueryImpl, c, options).objectExecute();
        }

        XmlCursor cursorExecute(Cur c, XmlOptions options)
        {
            return new DelegateQueryEngine(_xqueryImpl, c, options).cursorExecute();
        }


        private static class DelegateQueryEngine
        {
            public DelegateQueryEngine(QueryDelegate.QueryInterface xqImpl,
                                    Cur c, XmlOptions opt)
            {

                _engine = xqImpl;
                _version = c._locale.version();
                _cur = c.weakCur(this);
                _options = opt;

            }

            public XmlObject[] objectExecute()
            {
                if (_cur != null && _version != _cur._locale.version())
                //throw new ConcurrentModificationException
                // ("Document changed during select")
                    ;

                Map bindings = (Map) XmlOptions.maskNull(_options).
                    get(XmlOptions.XQUERY_VARIABLE_MAP);
                List resultsList;
                resultsList = _engine.execQuery(_cur.getDom(), bindings);

                assert resultsList.size() > -1;

                XmlObject[] result = new XmlObject[resultsList.size()];
                int i;
                for (i = 0; i < resultsList.size(); i++) {
                    //copy objects into the locale
                    Locale l = Locale.getLocale(_cur._locale._schemaTypeLoader,
                            _options);

                    l.enter();
                    Object node = resultsList.get(i);
                    Cur res = null;
                    try {
                        //typed function results of XQuery
                        if (!(node instanceof Node)) {
                            //TODO: exact same code as Path.java
                            //make a common super-class and pull this--what to name that
                            //superclass???
                            res = l.load("").tempCur();
                            res.setValue(node.toString());
                            SchemaType type=getType(node);
                            Locale.autoTypeDocument(res, type, null);
                            result[i] = res.getObject();
                        }
                        else
                            res = loadNode(l, (Node) node);
                        result[i] = res.getObject();
                    }
                    catch (XmlException e) {
                        throw new RuntimeException(e);
                    }
                    finally {
                        l.exit();
                    }
                    res.release();
                }
                release();
                _engine = null;
                return result;
            }
            private SchemaType getType(Object node)
            {
                SchemaType type;
                if (node instanceof Integer)
                    type = XmlInteger.type;
                else if (node instanceof Double)
                    type = XmlDouble.type;
                else if (node instanceof Long)
                    type = XmlLong.type;
                else if (node instanceof Float)
                    type = XmlFloat.type;
                else if (node instanceof BigDecimal)
                    type = XmlDecimal.type;
                else if (node instanceof Boolean)
                    type = XmlBoolean.type;
                else if (node instanceof String)
                    type = XmlString.type;
                else if (node instanceof Date)
                    type = XmlDate.type;
                else
                    type = XmlAnySimpleType.type;
                return type;
            }
            public XmlCursor cursorExecute()
            {
                if (_cur != null && _version != _cur._locale.version())
                //throw new ConcurrentModificationException
                // ("Document changed during select")
                    ;

                Map bindings = (Map) XmlOptions.maskNull(_options).
                    get(XmlOptions.XQUERY_VARIABLE_MAP);
                List resultsList;
                resultsList = _engine.execQuery(_cur.getDom(), bindings);

                assert resultsList.size() > -1;

                int i;
                _engine = null;

                Locale locale = Locale.getLocale(_cur._locale._schemaTypeLoader, _options);
                locale.enter();
                Locale.LoadContext _context = new Cur.CurLoadContext(locale, _options);
                Cursor resultCur = null;
                try {
                    for (i = 0; i < resultsList.size(); i++) {
                        loadNodeHelper(locale, (Node) resultsList.get(i), _context);
                    }
                    Cur c = _context.finish();
                    Locale.associateSourceName(c, _options);
                    Locale.autoTypeDocument(c, null, _options);
                    resultCur = new Cursor(c);
                }
                catch (Exception e) {
                }
                finally {
                    locale.exit();
                }
                release();
                return resultCur;
            }


            public void release()
            {
                if (_cur != null) {
                    _cur.release();
                    _cur = null;
                }
            }


            private Cur loadNode(Locale locale, Node node)
            {
                Locale.LoadContext context = new Cur.CurLoadContext(locale, _options);

                try {
                    loadNodeHelper(locale, node, context);
                    Cur c = context.finish();
                    Locale.associateSourceName(c, _options);
                    Locale.autoTypeDocument(c, null, _options);
                    return c;
                }
                catch (Exception e) {
                    throw new XmlRuntimeException(e.getMessage(), e);
                }
            }

            private void loadNodeHelper(Locale locale, Node node, Locale.LoadContext context)
            {
                if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
                        QName attName = new QName(node.getNamespaceURI(),
                            node.getLocalName(),
                            node.getPrefix());
                        context.attr(attName, node.getNodeValue());
                        }
                else
                        locale.loadNode(node, context);

            }


            private Cur _cur;
            private QueryDelegate.QueryInterface _engine;
            private long _version;
            private XmlOptions _options;
        }

        private QueryDelegate.QueryInterface _xqueryImpl;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy