vgritsenko    2004/03/04 05:52:20

  Modified:    java/src/org/apache/xindice/core/query
                        XPathQueryResolver.java
  Log:
  Zap tabs; reformat.
  
  Revision  Changes    Path
  1.29      +1190 
-1410xml-xindice/java/src/org/apache/xindice/core/query/XPathQueryResolver.java
  
  Index: XPathQueryResolver.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xindice/java/src/org/apache/xindice/core/query/XPathQueryResolver.java,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- XPathQueryResolver.java   4 Mar 2004 13:18:49 -0000       1.28
  +++ XPathQueryResolver.java   4 Mar 2004 13:52:20 -0000       1.29
  @@ -85,1464 +85,1244 @@
    *
    * @version CVS $Revision$, $Date$
    */
  -public final class XPathQueryResolver extends SimpleConfigurable implements 
QueryResolver
  -{
  -     private static final Log log = 
LogFactory.getLog(XPathQueryResolver.class);
  -
  -     private static final Key[] EMPTY_KEYS = new Key[0];
  -     private static final Key[][] EMPTY_KEYSET = new Key[0][0];
  -     private static final String WILDCARD = "*";
  -     // private static final String THISNODE = ".";
  -     // private static final String PARENTNODE = "..";
  +public final class XPathQueryResolver extends SimpleConfigurable implements 
QueryResolver {
  +    private static final Log log = 
LogFactory.getLog(XPathQueryResolver.class);
   
  -     private static final String AUTOINDEX = "autoindex";
  +    private static final Key[] EMPTY_KEYS = new Key[0];
  +    private static final Key[][] EMPTY_KEYSET = new Key[0][0];
  +    private static final String WILDCARD = "*";
  +    // private static final String THISNODE = ".";
  +    // private static final String PARENTNODE = "..";
   
  -     public static final String STYLE_XPATH = "XPath";
  +    private static final String AUTOINDEX = "autoindex";
   
  -     // Maps Xalan Comparisons To IndexQuery
  -     private static final int[] OpMap = {
  +    public static final String STYLE_XPATH = "XPath";
  +
  +    // Maps Xalan Comparisons To IndexQuery
  +    private static final int[] OpMap = {
           IndexQuery.NEQ, IndexQuery.EQ, IndexQuery.LEQ, IndexQuery.LT, 
IndexQuery.GEQ, IndexQuery.GT
       };
   
  -     private DefaultErrorHandler errorListener = new DefaultErrorHandler();
  -     private boolean autoIndex = false;
  +    private DefaultErrorHandler errorListener = new DefaultErrorHandler();
  +    private boolean autoIndex = false;
   
   
  -     public void setConfig(Configuration config) throws XindiceException
  -     {
  -             super.setConfig(config);
  -             autoIndex = config.getBooleanAttribute(AUTOINDEX, autoIndex);
  -     }
  -
  -     public String getQueryStyle()
  -     {
  -             return STYLE_XPATH;
  -     }
  -
  -     public void setQueryEngine(QueryEngine engine)
  -     {
  -             // Not used: this.engine = engine;
  -     }
  -
  -     public Query compileQuery(Collection context, String query, 
NamespaceMap nsMap, Key[] keys) throws QueryException
  -     {
  -             return new XPathQuery(context, query, nsMap, keys);
  -     }
  -
  -     public NodeSet query(Collection context, String query, NamespaceMap 
nsMap, Key[] keys) throws QueryException
  -     {
  -             XPathQuery xq = new XPathQuery(context, query, nsMap, keys);
  -             return xq.execute();
  -     }
  +    public void setConfig(Configuration config) throws XindiceException {
  +        super.setConfig(config);
  +        autoIndex = config.getBooleanAttribute(AUTOINDEX, autoIndex);
  +    }
  +
  +    public String getQueryStyle() {
  +        return STYLE_XPATH;
  +    }
  +
  +    public void setQueryEngine(QueryEngine engine) {
  +        // Not used: this.engine = engine;
  +    }
  +
  +    public Query compileQuery(Collection context, String query, NamespaceMap 
nsMap, Key[] keys)
  +            throws QueryException {
  +        return new XPathQuery(context, query, nsMap, keys);
  +    }
  +
  +    public NodeSet query(Collection context, String query, NamespaceMap 
nsMap, Key[] keys)
  +            throws QueryException {
  +        XPathQuery xq = new XPathQuery(context, query, nsMap, keys);
  +        return xq.execute();
  +    }
   
        /**
  -      * XPathQuery
  -      */
  -     private class XPathQuery implements Query
  -     {
  -             public Collection context;
  -             public IndexManager idxMgr;
  -             public NamespaceMap nsMap;
  -             public PrefixResolver pr;
  -             public SymbolTable symbols;
  -             public String query;
  -             public Compiler cmp;
  -             public XPath xp;
  -             public Key[] keys;
  -
  -             public XPathQuery(Collection context, String query, 
NamespaceMap nsMap, Key[] keys) throws QueryException
  -             {
  -                     this.context = context;
  -                     this.query = query;
  -                     this.nsMap = nsMap;
  -                     this.keys = keys;
  -
  -                     Expression ex = null;
  -
  -                     try
  -                     {
  -                             if (nsMap != null)
  -                             {
  -                                     Node n = nsMap.getContextNode();
  -                                     pr = new PrefixResolverDefault(n);
  -                             }
  -
  -                             XPathParser parser = new 
XPathParser(errorListener, null);
  -                             cmp = new Compiler(errorListener, null);
  -                             parser.initXPath(cmp, query, pr);
  -                             ex = cmp.compile(0);
  -
  -                             symbols = context.getSymbols();
  -                             idxMgr = context.getIndexManager();
  -                     }
  -                     catch (Exception e)
  -                     {
  -                             throw new CompilationException("Error Compiling 
XPath Expression", e);
  -                     }
  -                     if (ex == null)
  -                     {
  -                             throw new CompilationException("Error Compiling 
XPath Expression: XPath Compiler.compile returned null");
  -                     }
  -             }
  -
  -             public String getQueryStyle()
  -             {
  -                     return STYLE_XPATH;
  -             }
  -
  -             public String getQueryString()
  -             {
  -                     return query;
  -             }
  -
  -             public Collection getQueryContext()
  -             {
  -                     return context;
  -             }
  -
  -             public NamespaceMap getNamespaceMap()
  -             {
  -                     return nsMap;
  -             }
  -
  -             public Key[] getKeySet()
  -             {
  -                     return keys;
  -             }
  -
  -             public NodeSet execute() throws QueryException
  -             {
  -                     try
  -                     {
  -                             Key[] keySet = keys;
  -
  -                             // TODO: Add logic to do an indexed check on 
provided
  -                             //       keySets that are larger than a certain 
minimum
  -
  -                             if (keys == null && idxMgr != null)
  -                             {
  -                                     // Issue the query using Indexes
  -                                     try
  -                                     {
  -                                             Object obj = evaluate(null, 0);
  -                                             if (obj instanceof NamedKeys)
  -                                             {
  -                                                     keySet = ((NamedKeys) 
obj).keys;
  -                                             }
  -                                     }
  -                                     catch (Exception e)
  -                                     {
  -                                             if (log.isWarnEnabled())
  -                                             {
  -                                                     log.warn("ignored 
exception", e);
  -                                             }
  -                                     }
  -                             }
  -
  -                             if (keySet == null)
  -                             {
  -                                     // Fall back to a Collection scan
  -                                     SortedSet set = new TreeSet();
  -                                     RecordSet rs = 
context.getFiler().getRecordSet();
  -                                     while (rs.hasMoreRecords())
  -                                     {
  -                                             set.add(rs.getNextKey());
  -                                     }
  -                                     keySet = (Key[]) 
set.toArray(EMPTY_KEYS);
  -                             }
  -
  -                             return new ResultSet(context, pr, keySet, 
query);
  -                     }
  -                     catch (Exception e)
  -                     {
  -                             if (e instanceof QueryException)
  -                             {
  -                                     throw (QueryException) 
e.fillInStackTrace();
  -                             }
  -                             throw new ProcessingException("Error executing 
XPath query: " + e.getMessage());
  -                     }
  -             }
  -
  -             private Key[] andKeys(List list)
  -             {
  -                     if (!list.isEmpty())
  -                     {
  -                             if (list.size() > 1)
  -                             {
  -                                     Key[][] keys = (Key[][]) 
list.toArray(EMPTY_KEYSET);
  -                                     return QueryEngine.andKeySets(keys);
  -                             }
  -                             else
  -                                     return (Key[]) list.get(0);
  -                     }
  -                     else
  -                             return null;
  -             }
  +     * XPathQuery
  +     */
  +    private class XPathQuery implements Query {
  +        public Collection context;
  +        public IndexManager idxMgr;
  +        public NamespaceMap nsMap;
  +        public PrefixResolver pr;
  +        public SymbolTable symbols;
  +        public String query;
  +        public Compiler cmp;
  +        public XPath xp;
  +        public Key[] keys;
  +
  +             public XPathQuery(Collection context, String query, 
NamespaceMap nsMap, Key[] keys)
  +                throws QueryException {
  +            this.context = context;
  +            this.query = query;
  +            this.nsMap = nsMap;
  +            this.keys = keys;
   
  -             // Evaluation Methods
  +            Expression ex = null;
  +                     try {
  +                if (nsMap != null) {
  +                    Node n = nsMap.getContextNode();
  +                    pr = new PrefixResolverDefault(n);
  +                }
  +
  +                XPathParser parser = new XPathParser(errorListener, null);
  +                cmp = new Compiler(errorListener, null);
  +                parser.initXPath(cmp, query, pr);
  +                ex = cmp.compile(0);
   
  -             /**
  -              * evaluate does a partial evaluation of the XPath in
  -              * order to determine the optimal indexes to prepare for
  -              * the query and retrieve the Document subset that will be
  -              * used for the actual XPath query.
  -              * <br><br>
  -              * This will return an instance of one of the following classes:
  -              * <pre>
  -              *    String    If the sub-expression resolves to a Node Name
  -              *    XNumber   If the sub-expression resolves to a Number
  -              *    XString   If the sub-expression resolves to a String
  -              *    XBoolean  If the sub-expression resolves to a Boolean
  -              *    NamedKeys If the sub-expression resolves to a Key set
  -              *    null      If the sub-expression resolves to anything else
  -              * </pre>
  -              *
  -              * @param owner The parent node name for this context
  -              * @param pos The position to start at (recursively called)
  -              * @return Some Object result
  -              */
  -             private Object evaluate(String owner, int pos) throws Exception
  -             {
  -                     int op = cmp.getOp(pos);
  -                     if (op == -1)
  -                     {
  -                             return null;
  -                     }
  -
  -                     switch (op)
  -                     {
  -
  -                             case OpCodes.OP_LOCATIONPATH :
  -                                     return evalLocationPath(owner, pos);
  -
  -                             case OpCodes.OP_ARGUMENT :
  -                             case OpCodes.OP_XPATH :
  -                             case OpCodes.OP_PREDICATE :
  -                                     return evaluate(owner, 
Compiler.getFirstChildPos(pos));
  -
  -                             case OpCodes.OP_OR :
  -                             case OpCodes.OP_AND :
  -                                     return evalSetComparison(op, owner, 
pos);
  -
  -                             case OpCodes.OP_NOTEQUALS :
  -                             case OpCodes.OP_EQUALS :
  -                             case OpCodes.OP_LTE :
  -                             case OpCodes.OP_LT :
  -                             case OpCodes.OP_GTE :
  -                             case OpCodes.OP_GT :
  -                                     return evalValComparison(op, owner, 
pos);
  -
  -                             case OpCodes.OP_PLUS :
  -                             case OpCodes.OP_MINUS :
  -                             case OpCodes.OP_MULT :
  -                             case OpCodes.OP_DIV :
  -                             case OpCodes.OP_MOD :
  -                             case OpCodes.OP_QUO :
  -                                     return evalMathOperation(op, owner, 
pos);
  -
  -                             case OpCodes.OP_NEG :
  -                             case OpCodes.OP_STRING :
  -                             case OpCodes.OP_BOOL :
  -                             case OpCodes.OP_NUMBER :
  -                                     return evalUnaryOperation(op, owner, 
pos);
  -
  -                             case OpCodes.OP_UNION :
  -                                     return evalUnion(owner, pos);
  -
  -                             case OpCodes.OP_VARIABLE :
  -                                     break;
  -
  -                             case OpCodes.OP_GROUP :
  -                                     return evaluate(owner, 
Compiler.getFirstChildPos(pos));
  -
  -                             case OpCodes.OP_EXTFUNCTION :
  -                                     break;
  -
  -                             case OpCodes.OP_FUNCTION :
  -                                     return evalFunction(owner, pos);
  -
  -                             case OpCodes.FROM_ANCESTORS :
  -                             case OpCodes.FROM_ANCESTORS_OR_SELF :
  -                             case OpCodes.FROM_ATTRIBUTES :
  -                             case OpCodes.FROM_CHILDREN :
  -                             case OpCodes.FROM_DESCENDANTS :
  -                             case OpCodes.FROM_DESCENDANTS_OR_SELF :
  -                             case OpCodes.FROM_FOLLOWING :
  -                             case OpCodes.FROM_FOLLOWING_SIBLINGS :
  -                             case OpCodes.FROM_PARENT :
  -                             case OpCodes.FROM_PRECEDING :
  -                             case OpCodes.FROM_PRECEDING_SIBLINGS :
  -                             case OpCodes.FROM_NAMESPACE :
  -                             case OpCodes.FROM_SELF :
  -                             case OpCodes.FROM_ROOT :
  -                                     return evalAxis(op, owner, pos);
  -
  -                             case OpCodes.NODENAME :
  -                             case OpCodes.OP_LITERAL :
  -                             case OpCodes.OP_NUMBERLIT :
  -                                     return evalLiteral(owner, pos);
  -
  -                             case OpCodes.NODETYPE_TEXT :
  -                             case OpCodes.NODETYPE_NODE :
  -                                     return owner;
  -
  -                             case OpCodes.NODETYPE_ANYELEMENT :
  -                             case OpCodes.ELEMWILDCARD :
  -                                     return WILDCARD;
  -
  -                             case OpCodes.NODETYPE_ROOT :
  -                             case OpCodes.NODETYPE_COMMENT :
  -                             case OpCodes.NODETYPE_PI :
  -                             case OpCodes.NODETYPE_FUNCTEST :
  -                                     break;
  -
  -                             default :
  -                                     if (log.isWarnEnabled())
  -                                     {
  -                                             log.warn("Unknown: " + op);
  -                                     }
  -                     }
  -                     return null;
  -             }
  -
  -             private Object evalLocationPath(String owner, int pos) throws 
Exception
  -             {
  -                     int lp = Compiler.getFirstChildPos(pos);
  -                     List ks = new ArrayList();
  -                     String name = null;
  -                     boolean attr = false;
  -                     while (cmp.getOp(lp) != -1)
  -                     {
  -                             Object obj = evaluate(owner, lp);
  -                             if (obj instanceof NamedKeys)
  -                             {
  -                                     NamedKeys nk = (NamedKeys) obj;
  -                                     if (nk.name != null)
  -                                     {
  -                                             attr = nk.attribute;
  -                                             if (attr)
  -                                             {
  -                                                     if (name == null)
  -                                                     {
  -                                                             name = owner;
  -                                                     }
  -                                                     if (name != null)
  -                                                     {
  -                                                             StringBuffer sb 
= new StringBuffer(32);
  -                                                             sb.append(name);
  -                                                             sb.append('@');
  -                                                             
sb.append(nk.name);
  -                                                             name = 
sb.toString();
  -                                                     }
  -                                             }
  -                                             else
  -                                             {
  -                                                     name = nk.name;
  -                                             }
  -                                     }
  -                                     if (nk.keys != null)
  -                                     {
  -                                             ks.add(nk.keys);
  -                                     }
  -                                     else if (name != null)
  -                                     {
  -                                             // Try to use a NameIndex to 
resolve the path component
  -                                             // can match a wildcard node 
name here if pattern is "*" then every document matches
  -                                             if (attr == false && 
"*".equals(name))
  -                                             {
  -                                                     SortedSet set = new 
TreeSet();
  -                                                     RecordSet rs = 
context.getFiler().getRecordSet();
  -                                                     while 
(rs.hasMoreRecords())
  -                                                     {
  -                                                             
set.add(rs.getNextKey());
  -                                                     }
  -                                                     
ks.add(set.toArray(EMPTY_KEYS));
  -                                             }
  -                                             else
  -                                             {
  -                                                     // Try to use a 
NameIndex to resolve the path component
  -                                                     IndexPattern pattern = 
new IndexPattern(symbols, name, nsMap);
  -                                                     Indexer idx = 
context.getIndexManager().getBestIndexer(Indexer.STYLE_NODENAME, pattern);
  -                                                     if (idx != null)
  -                                                     {
  -                                                             IndexMatch[] 
matches = idx.queryMatches(new IndexQueryANY(pattern));
  -                                                             Key[] keys = 
QueryEngine.getUniqueKeys(matches);
  -                                                             ks.add(keys);
  -                                                     }
  -                                             }
  -                                     }
  -                             }
  -                             lp = cmp.getNextOpPos(lp);
  -                     }
  -                     return new NamedKeys(name, attr, andKeys(ks));
  -             }
  -
  -             private Object evalUnion(String owner, int pos) throws Exception
  -             {
  -                     int l = Compiler.getFirstChildPos(pos);
  -                     int r = cmp.getNextOpPos(l);
  -                     Object left = evaluate(owner, l);
  -
  -                     if (left instanceof NamedKeys && ((NamedKeys) 
left).keys != null)
  -                     {
  -                             Object right = evaluate(owner, r);
  -
  -                             if (right instanceof NamedKeys && ((NamedKeys) 
right).keys != null)
  -                             {
  -                                     Key[][] keys = new Key[][] 
{((NamedKeys) left).keys, ((NamedKeys) right).keys };
  -                                     return new NamedKeys(null, false, 
QueryEngine.orKeySets(keys));
  -                             }
  -                     }
  -                     // no index query of left part of union
  -                     // or no index query of right part of union => must do
  -                     /// collection scan
  -                     return null;
  -             }
  -
  -             private Object evalSetComparison(int op, String owner, int pos) 
throws Exception
  -             {
  -                     int l = Compiler.getFirstChildPos(pos);
  -                     int r = cmp.getNextOpPos(l);
  -                     Object left = evaluate(owner, l);
  -
  -                     if (left instanceof NamedKeys && ((NamedKeys) 
left).keys != null)
  -                     {
  -                             // have left keys
  -                             if (((NamedKeys) left).keys.length == 0 && op 
== OpCodes.OP_AND)
  -                             {
  -                                     // left keyset empty implies result of 
AND would be empty
  -                                     return new NamedKeys(null, false, 
((NamedKeys) left).keys);
  -                             }
  -
  -                             Object right = evaluate(owner, r);
  -                             if (right instanceof NamedKeys && ((NamedKeys) 
right).keys != null)
  -                             {
  -                                     // have keys for both left and right
  -
  -                                     if (op == OpCodes.OP_AND)
  -                                     {
  -                                             if (((NamedKeys) 
right).keys.length == 0)
  -                                             {
  -                                                     // right keyset empty 
implies result of AND would be empty
  -                                                     return new 
NamedKeys(null, false, ((NamedKeys) right).keys);
  -                                             }
  -
  -                                             Key[][] keys = new Key[][] 
{((NamedKeys) left).keys, ((NamedKeys) right).keys };
  -                                             return new NamedKeys(null, 
false, QueryEngine.andKeySets(keys));
  -                                     }
  -                                     else
  -                                     {
  -
  -                                             // OR operation
  -                                             if (((NamedKeys) 
left).keys.length == 0)
  -                                             {
  -                                                     // OR operation and 
left empty implies result is right set
  -                                                     return new 
NamedKeys(null, false, ((NamedKeys) right).keys);
  -                                             }
  -
  -                                             if (((NamedKeys) 
right).keys.length == 0)
  -                                             {
  -                                                     // OR operation and 
right empty implies result is left set
  -                                                     return new 
NamedKeys(null, false, ((NamedKeys) left).keys);
  -                                             }
  -
  -                                             Key[][] keys = new Key[][] 
{((NamedKeys) left).keys, ((NamedKeys) right).keys };
  -                                             return new NamedKeys(null, 
false, QueryEngine.orKeySets(keys));
  -                                     }
  -                             }
  -                             else
  -                             {
  -                                     // have left keys but not right can 
infer that AND operation
  -                                     // result cannot contain more than left 
set so return that
  -                                     if (op == OpCodes.OP_AND)
  -                                     {
  -                                             return new NamedKeys(null, 
false, ((NamedKeys) left).keys);
  -                                     }
  -                             }
  -                     }
  -                     else
  -                     {
  -                             // do not have left keys
  -                             Object right = evaluate(owner, r);
  -                             if (right instanceof NamedKeys && ((NamedKeys) 
right).keys != null)
  -                             {
  -                                     // have right keys but not left can 
infer that AND operation
  -                                     // result cannot contain more than 
right set so return that
  -                                     if (op == OpCodes.OP_AND)
  -                                     {
  -                                             return new NamedKeys(null, 
false, ((NamedKeys) right).keys);
  -                                     }
  -                             }
  -                     }
  -
  -                     // punt
  -                     return null;
  -             }
  -
  -             private Object evalValComparison(int op, String owner, int pos) 
throws Exception
  -             {
  -
  -                     int l = Compiler.getFirstChildPos(pos);
  -                     int r = cmp.getNextOpPos(l);
  -
  -                     Object left = evaluate(owner, l);
  -                     if (!(left instanceof XObject || left instanceof 
NamedKeys))
  -                     {
  -                             // can't evaluate
  -                             return null;
  -                     }
  -
  -                     Object right = evaluate(owner, r);
  -                     if ((left instanceof NamedKeys && right instanceof 
XObject)
  -                             || (left instanceof XObject && right instanceof 
NamedKeys))
  -                     {
  -                             // try to evaluate through indexed search
  -                             return queryComparison(op, owner, left, right);
  -                     }
  -
  -                     // could handle comparison of nodeset to boolean here
  -                     // boolean converts to 1.0 (true) or 0.0 (false)
  -                     // nodeset converts to 1.0 (non-empty) or 0.0 (empty)
  -                     // but since this is a rare and odd comparison we don't 
bother now...
  -                     if (left instanceof XObject && right instanceof XObject)
  -                     {
  -                             switch (op)
  -                             {
  -                                     case OpCodes.OP_NOTEQUALS :
  -                                             return new XBoolean(((XObject) 
left).notEquals((XObject) right));
  -                                     case OpCodes.OP_EQUALS :
  -                                             return new XBoolean(((XObject) 
left).equals((XObject) right));
  -                                     case OpCodes.OP_LTE :
  -                                             return new XBoolean(((XObject) 
left).lessThanOrEqual((XObject) right));
  -                                     case OpCodes.OP_LT :
  -                                             return new XBoolean(((XObject) 
left).lessThan((XObject) right));
  -                                     case OpCodes.OP_GTE :
  -                                             return new XBoolean(((XObject) 
left).greaterThanOrEqual((XObject) right));
  -                                     case OpCodes.OP_GT :
  -                                             return new XBoolean(((XObject) 
left).greaterThan((XObject) right));
  -                                     default :
  -                                             return null; // Won't happen
  -                             }
  -                     }
  -
  -                     // can't evaluate here...
  -                     return null;
  -             }
  -
  -             private strictfp Object evalMathOperation(int op, String owner, 
int pos) throws Exception
  -             {
  -                     int lc = Compiler.getFirstChildPos(pos);
  -                     int rc = cmp.getNextOpPos(lc);
  -                     Object left = evaluate(owner, lc);
  -
  -                     if (left instanceof XObject)
  -                     {
  -                             Object right = evaluate(owner, rc);
  -                             if (right instanceof XObject)
  -                             {
  -                                     switch (op)
  -                                     {
  -                                             case OpCodes.OP_PLUS :
  -                                                     return new 
XNumber(((XObject) left).num() + ((XObject) right).num());
  -                                             case OpCodes.OP_MINUS :
  -                                                     return new 
XNumber(((XObject) left).num() - ((XObject) right).num());
  -                                             case OpCodes.OP_MULT :
  -                                                     return new 
XNumber(((XObject) left).num() * ((XObject) right).num());
  -                                             case OpCodes.OP_DIV :
  -                                                     return new 
XNumber(((XObject) left).num() / ((XObject) right).num());
  -                                             case OpCodes.OP_MOD :
  -                                                     return new 
XNumber(((XObject) left).num() % ((XObject) right).num());
  -                                             case OpCodes.OP_QUO :
  -                                                     return new 
XNumber(((XObject) left).num() / ((XObject) right).num());
  -                                             default :
  -                                                     return null; // Won't 
happen
  -                                     }
  -                             }
  -                     }
  -
  -                     // can't evaluate
  -                     return null;
  -             }
  -
  -             private Object evalUnaryOperation(int op, String owner, int 
pos) throws Exception
  -             {
  -                     Object val = evaluate(owner, 
Compiler.getFirstChildPos(pos));
  -                     if (val instanceof XObject)
  -                     {
  -                             switch (op)
  -                             {
  -                                     case OpCodes.OP_NEG :
  -                                             return new XNumber(- ((XObject) 
val).num());
  -                                     case OpCodes.OP_STRING :
  -                                             return new XString(((XObject) 
val).str());
  -                                     case OpCodes.OP_BOOL :
  -                                             return new XBoolean(((XObject) 
val).bool());
  -                                     case OpCodes.OP_NUMBER :
  -                                             return new XNumber(((XObject) 
val).num());
  -                                     default :
  -                                             return null; // Won't happen
  -                             }
  -                     }
  -                     if (val instanceof NamedKeys)
  -                     {
  -                             NamedKeys nk = (NamedKeys) val;
  -                             // we may be able to convert the nodeset to the 
proper type
  -                             // and return an answer numeric operations 
imply conversion to
  -                             // string and then to number
  -                             // we can't convert to string
  -                             // we can handle conversion to boolean (empty 
or not empty)
  -                             if (nk.keys != null && op == OpCodes.OP_BOOL)
  -                             {
  -                                     return nk.keys.length == 0 ? 
XBoolean.S_FALSE : XBoolean.S_TRUE;
  -                             }
  -                     }
  -                     return null;
  -             }
  -
  -             private Object evalFunction(String owner, int pos) throws 
Exception
  -             {
  -                     int idx = Compiler.getFirstChildPos(pos);
  -                     int id = cmp.getOp(idx);
  -                     // note: in the XPath op table, the
  -                     // op code is stored at the current position index 
passed to us
  -                     // the size of the current op is stored in the next 
location
  -                     // thus, the index of the location just beyond the 
function
  -                     // arguments for the current op (which is also the 
index of the next op)
  -                     // is equal to the current postion + the size of the 
current operation - 1
  -                     // (the getOp(index) method merely returns the int 
value stored in the op table
  -                     // at the specified index. That value is an op code, a 
size, or the index
  -                     // of an token or ... (see 
org.apache.xpath.compiler.OpCodes for the
  -                     // various items that can be part of an operation)
  -                     int endFunc = pos + cmp.getOp(pos + 1) - 1;
  -
  -                     List args = new ArrayList();
  -                     int lp = idx + 1;
  -                     while (lp < endFunc)
  -                     {
  -                             args.add(evaluate(owner, lp));
  -                             lp = cmp.getNextOpPos(lp);
  -                     }
  -
  -                     switch (id)
  -                     {
  -                             case FunctionTable.FUNC_BOOLEAN :
  -                                     return funcBoolean(args);
  -                             case FunctionTable.FUNC_CEILING :
  -                                     return funcCeiling(args);
  -                             case FunctionTable.FUNC_CONCAT :
  -                                     return funcConcat(args);
  -                             case FunctionTable.FUNC_CONTAINS :
  -                                     return funcContains(args);
  -                             case FunctionTable.FUNC_FALSE :
  -                                     return XBoolean.S_FALSE;
  -                             case FunctionTable.FUNC_FLOOR :
  -                                     return funcFloor(args);
  -                             case FunctionTable.FUNC_NORMALIZE_SPACE :
  -                                     return funcNormalizeSpace(args);
  -                             case FunctionTable.FUNC_NOT :
  -                                     return funcNot(args);
  -                             case FunctionTable.FUNC_NUMBER :
  -                                     return funcNumber(args);
  -                             case FunctionTable.FUNC_ROUND :
  -                                     return funcRound(args);
  -                             case FunctionTable.FUNC_STARTS_WITH :
  -                                     return funcStartsWith(owner, args);
  -                             case FunctionTable.FUNC_STRING :
  -                                     return funcString(args);
  -                             case FunctionTable.FUNC_STRING_LENGTH :
  -                                     return funcStringLength(args);
  -                             case FunctionTable.FUNC_SUBSTRING :
  -                                     return funcSubstring(args);
  -                             case FunctionTable.FUNC_SUBSTRING_AFTER :
  -                                     return funcSubstringAfter(args);
  -                             case FunctionTable.FUNC_SUBSTRING_BEFORE :
  -                                     return funcSubstringBefore(args);
  -                             case FunctionTable.FUNC_TRANSLATE :
  -                                     return funcTranslate(args);
  -                             case FunctionTable.FUNC_TRUE :
  -                                     return XBoolean.S_TRUE;
  -                             default :
  -                                     return null;
  -                     }
  -             }
  -
  -             private Object evalAxis(int op, String owner, int pos) throws 
Exception
  -             {
  -                     String nsURI = cmp.getStepNS(pos);
  -                     owner = (String) evaluate(owner, 
Compiler.getFirstChildPosOfStep(pos));
  -                     //owner = cmp.getStepLocalName(pos);
  -
  -                     if (nsURI != null && nsMap != null)
  -                     {
  -                             // We have to determine the prefix that was used
  -                             // There has to be an easier way to do this 
with Xalan
  -                             String pfx = null;
  -                             Iterator i = nsMap.keySet().iterator();
  -                             while (i.hasNext())
  -                             {
  -                                     String p = (String) i.next();
  -                                     if 
(nsMap.getNamespaceURI(p).equals(nsURI))
  -                                     {
  -                                             pfx = p;
  -                                             break;
  -                                     }
  -                             }
  -                             if (pfx != null)
  -                             {
  -                                     StringBuffer sb = new StringBuffer(32);
  -                                     sb.append(pfx);
  -                                     sb.append(':');
  -                                     sb.append(owner);
  -                                     owner = sb.toString();
  -                             }
  -                     }
  -
  -                     int rp = cmp.getFirstPredicateOpPos(pos);
  -
  -                     List ks = new ArrayList();
  -                     while (rp < pos + cmp.getOp(pos + 1))
  -                     {
  -                             Object obj = evaluate(owner, rp);
  -                             if (obj instanceof NamedKeys)
  -                             {
  -                                     NamedKeys nk = (NamedKeys) obj;
  -                                     if (nk.keys != null)
  -                                     {
  -                                             ks.add(nk.keys);
  -                                     }
  -                             }
  -                             rp = cmp.getNextOpPos(rp);
  -                     }
  -                     return new NamedKeys(owner, (op == 
OpCodes.FROM_ATTRIBUTES), andKeys(ks));
  -             }
  -
  -             private Object evalLiteral(String owner, int pos)
  -             {
  -                     int idx = cmp.getOp(Compiler.getFirstChildPos(pos));
  -                     switch (idx)
  -                     {
  -                             case OpCodes.EMPTY :
  -                                     return owner;
  -                             case OpCodes.ELEMWILDCARD :
  -                                     return WILDCARD;
  -                             default :
  -                                     return cmp.getToken(idx);
  -                     }
  -             }
  -
  -             // XPath Functions
  -
  -             private Object funcBoolean(List args) throws Exception
  -             {
  -                     if (args.size() == 1)
  -                     {
  -                             Object o = args.get(0);
  -                             if (o instanceof XObject)
  -                             {
  -                                     if (((XObject) o).bool())
  -                                     {
  -                                             return XBoolean.S_TRUE;
  -                                     }
  -                                     else
  -                                     {
  -                                             return XBoolean.S_FALSE;
  -                                     }
  -                             }
  -                             else
  -                             {
  -                                     if (o instanceof NamedKeys)
  -                                     {
  -                                             NamedKeys nk = (NamedKeys) o;
  -                                             if (nk.keys == null)
  -                                             {
  -                                                     return null;
  -                                             }
  -                                             if (nk.keys.length == 0)
  -                                             {
  -                                                     // nodeset empty 
converts to boolean false
  -                                                     return XBoolean.S_FALSE;
  -                                             }
  -                                             return XBoolean.S_TRUE;
  -                                     }
  -                             }
  -                     }
  -                     return null;
  -             }
  -
  -             private Object funcCeiling(List args) throws Exception
  -             {
  -                     if (args.size() == 1)
  -                     {
  -                             Object o = args.get(0);
  -                             if (o instanceof XObject)
  -                             {
  -                                     return new XNumber(Math.ceil(((XObject) 
o).num()));
  -                             }
  -                     }
  -                     return null;
  -             }
  -
  -             private Object funcConcat(List args)
  -             {
  -                     StringBuffer sb = new StringBuffer();
  -                     for (int i = 0; i < args.size(); i++)
  -                     {
  -                             Object o = args.get(i);
  -                             if (o instanceof XObject)
  -                             {
  -                                     sb.append(((XObject) o).str());
  -                             }
  -                             else
  -                             {
  -                                     return null;
  -                             }
  -                     }
  -                     return new XString(sb.toString());
  -             }
  -
  -             private Object funcContains(List args)
  -             {
  -                     if (args.size() == 2)
  -                     {
  -                             Object o = args.get(0);
  -                             Object s = args.get(1);
  -                             if (o instanceof XObject && s instanceof 
XObject)
  -                             {
  -                                     if (((XObject) 
o).str().indexOf(((XObject) s).str()) != -1)
  -                                     {
  -                                             return XBoolean.S_TRUE;
  -                                     }
  -                                     else
  -                                     {
  -                                             return XBoolean.S_FALSE;
  -                                     }
  -                             }
  -                     }
  -                     return null;
  -             }
  -
  -             private Object funcFloor(List args) throws Exception
  -             {
  -                     if (args.size() == 1)
  -                     {
  -                             Object o = args.get(0);
  -                             if (o instanceof XObject)
  -                             {
  -                                     return new 
XNumber(Math.floor(((XObject) o).num()));
  -                             }
  -                     }
  -                     return null;
  -             }
  -
  -             private Object funcNormalizeSpace(List args)
  -             {
  -                     if (args.size() == 1)
  -                     {
  -                             Object o = args.get(0);
  -                             if (o instanceof XObject)
  -                             {
  -                                     return new 
XString(QueryEngine.normalizeString(((XObject) o).str()));
  -                             }
  -                     }
  -                     return null;
  -             }
  -
  -             private Object funcNot(List args) throws Exception
  -             {
  -                     if (args.size() == 1)
  -                     {
  -                             Object o = args.get(0);
  -                             if (o instanceof XObject)
  -                             {
  -                                     if (((XObject) o).bool())
  -                                     {
  -                                             return XBoolean.S_FALSE;
  -                                     }
  -                                     else
  -                                     {
  -                                             return XBoolean.S_TRUE;
  -                                     }
  -                             }
  -                             else
  -                             {
  -                                     if (o instanceof NamedKeys)
  -                                     {
  -                                             NamedKeys nk = (NamedKeys) o;
  -                                             if (nk.keys == null)
  -                                             {
  -                                                     return null;
  -                                             }
  -                                             if (nk.keys.length == 0)
  -                                             {
  -                                                     // nodeset empty 
converts to boolean false => not false => true
  -                                                     return XBoolean.S_TRUE;
  -                                             }
  -                                             return XBoolean.S_FALSE;
  -                                     }
  -                                     return null;
  -                             }
  -
  -                     }
  -                     return null;
  -             }
  -
  -             private Object funcNumber(List args) throws Exception
  -             {
  -                     if (args.size() == 1)
  -                     {
  -                             Object o = args.get(0);
  -                             if (o instanceof XObject)
  -                             {
  -                                     return new XNumber(((XObject) o).num());
  -                             }
  -                     }
  -                     return null;
  -             }
  -
  -             private Object funcRound(List args) throws Exception
  -             {
  -                     if (args.size() == 1)
  -                     {
  -                             Object o = args.get(0);
  -                             if (o instanceof XObject)
  -                             {
  -                                     return new 
XNumber(Math.round(((XObject) o).num()));
  -                             }
  -                     }
  -                     return null;
  -             }
  -
  -             private Object funcStartsWith(String owner, List args)
  -             {
  -                     if (args.size() == 2)
  -                     {
  -                             Object o = args.get(0);
  -                             Object s = args.get(1);
  -
  -                             if (o instanceof XObject && s instanceof 
XObject)
  -                             {
  -                                     if (((XObject) 
o).str().startsWith(((XObject) s).str()))
  -                                     {
  -                                             return XBoolean.S_TRUE;
  -                                     }
  -                                     else
  -                                     {
  -                                             return XBoolean.S_FALSE;
  -                                     }
  -                             }
  -                             else if (o instanceof NamedKeys && s instanceof 
XObject)
  -                             {
  -                                     NamedKeys nk = (NamedKeys) o;
  -                                     String ps;
  -                                     if (nk.attribute && 
nk.name.indexOf('@') == -1)
  -                                     {
  -                                             ps = owner + "@" + nk.name;
  -                                     }
  -                                     else
  -                                     {
  -                                             ps = nk.name;
  -                                     }
  -
  -                                     IndexPattern pattern = new 
IndexPattern(symbols, ps, nsMap);
  -
  -                                     XObject obj = (XObject) s;
  -                                     Value val1 = new Value(obj.str());
  -
  -                                     IndexQuery iq = new 
IndexQuerySW(pattern, val1);
  -                                     return queryIndexes(nk, iq, ps, 
obj.getType());
  -                             }
  -                     }
  -                     return null;
  -             }
  -
  -             private Object funcString(List args)
  -             {
  -                     if (args.size() == 1)
  -                     {
  -                             Object o = args.get(0);
  -                             if (o instanceof XObject)
  -                             {
  -                                     return new XString(((XObject) o).str());
  -                             }
  -                     }
  -                     return null;
  -             }
  -
  -             private Object funcStringLength(List args)
  -             {
  -                     if (args.size() == 1)
  -                     {
  -                             Object o = args.get(0);
  -                             if (o instanceof XObject)
  -                             {
  -                                     return new XNumber(((XObject) 
o).str().length());
  -                             }
  -                     }
  -                     return null;
  -             }
  -
  -             private Object funcSubstring(List args) throws Exception
  -             {
  -                     if (args.size() == 2 || args.size() == 3)
  -                     {
  -                             Object o = args.get(0);
  -                             Object pos = args.get(1);
  -                             Object len = args.size() == 3 ? args.get(2) : 
null;
  -                             if (o instanceof XObject && pos instanceof 
XObject && (len == null || len instanceof XObject))
  -                             {
  -                                     int ipos = (int) ((XObject) pos).num() 
- 1;
  -                                     if (len != null)
  -                                     {
  -                                             int ilen = (int) ((XObject) 
len).num();
  -                                             return new XString(((XObject) 
o).str().substring(ipos, ipos + ilen));
  -                                     }
  -                                     else
  -                                             return new XString(((XObject) 
o).str().substring(ipos));
  -                             }
  -                     }
  -                     return null;
  -             }
  -
  -             private Object funcSubstringAfter(List args)
  -             {
  -                     if (args.size() == 2)
  -                     {
  -                             Object o = args.get(0);
  -                             Object s = args.get(1);
  -                             if (o instanceof XObject && s instanceof 
XObject)
  -                             {
  -                                     String val = ((XObject) o).str();
  -                                     String sub = ((XObject) s).str();
  -                                     int i = val.indexOf(sub);
  -                                     if (i == -1)
  -                                     {
  -                                             return new XString("");
  -                                     }
  -                                     else
  -                                     {
  -                                             return new 
XString(val.substring(i + sub.length()));
  -                                     }
  -                             }
  -                     }
  -                     return null;
  -             }
  -
  -             private Object funcSubstringBefore(List args)
  -             {
  -                     if (args.size() == 2)
  -                     {
  -                             Object o = args.get(0);
  -                             Object s = args.get(1);
  -                             if (o instanceof XObject && s instanceof 
XObject)
  -                             {
  -                                     String val = ((XObject) o).str();
  -                                     String sub = ((XObject) s).str();
  -                                     int i = val.indexOf(sub);
  -                                     if (i == -1)
  -                                     {
  -                                             return new XString("");
  -                                     }
  -                                     else
  -                                     {
  -                                             return new 
XString(val.substring(0, i));
  -                                     }
  -                             }
  -                     }
  -                     return null;
  -             }
  -
  -             private Object funcTranslate(List args)
  -             {
  -                     if (args.size() == 3)
  -                     {
  -                             Object o = args.get(0);
  -                             Object c1 = args.get(1);
  -                             Object c2 = args.get(2);
  -                             if (o instanceof XObject && c1 instanceof 
XObject && c2 instanceof XObject)
  -                             {
  -                                     char ch1 = ((XObject) 
c1).str().charAt(0);
  -                                     char ch2 = ((XObject) 
c2).str().charAt(0);
  -                                     return new XString(((XObject) 
o).str().replace(ch1, ch2));
  -                             }
  -                     }
  -                     return null;
  -             }
  +                symbols = context.getSymbols();
  +                idxMgr = context.getIndexManager();
  +            } catch (Exception e) {
  +                throw new CompilationException("Error Compiling XPath 
Expression: " + e.getMessage(), e);
  +            }
   
  -             // The Actual Querying Methods
  +            if (ex == null) {
  +                throw new CompilationException("Error Compiling XPath 
Expression: XPath Compiler.compile returned null");
  +            }
  +        }
  +
  +        public String getQueryStyle() {
  +            return STYLE_XPATH;
  +        }
  +
  +        public String getQueryString() {
  +            return query;
  +        }
  +
  +        public Collection getQueryContext() {
  +            return context;
  +        }
  +
  +        public NamespaceMap getNamespaceMap() {
  +            return nsMap;
  +        }
  +
  +        public Key[] getKeySet() {
  +            return keys;
  +        }
   
  -             /**
  -              * queryIndexes actually performs index-based querying on 
behalf of
  -              * the evaluation methods.
  -              *
  -              * @param nk The NamedKeys instance to use for matches
  -              * @param iq The actual IndexQuery to use for resolution
  -              * @param ps The pattern String to possibly use for index gen
  -              * @param objType The object type to possibly use for index gen
  -              * @return The resulting Keys (if any)
  -              */
  -             private Object queryIndexes(NamedKeys nk, IndexQuery iq, String 
ps, int objType)
  -             {
  -                     try
  -                     {
  -                             // TODO: Add logic to use an EmptyKeySet if a 
name doesn't already
  -                             //       exist in the SymbolTable.  This will 
eliminate the need
  -                             //       to do a collection scan in those cases 
where somebody
  -                             //       typed an element or attribute name 
incorrectly.
  -
  -                             IndexPattern pattern = iq.getPattern();
  -
  -                             Indexer idx = 
context.getIndexManager().getBestIndexer(Indexer.STYLE_NODEVALUE, pattern);
  -                             if (idx != null)
  -                             {
  -                                     return new NamedKeys(nk.name, 
nk.attribute, QueryEngine.getUniqueKeys(idx.queryMatches(iq)));
  -                             }
  -                             else if (autoIndex)
  -                             {
  -                                     // TODO: This has to *not* be hardcoded
  -                                     Element e = new 
DocumentImpl().createElement("index");
  -                                     e.setAttribute("class", 
"org.apache.xindice.core.indexer.ValueIndexer");
  -                                     e.setAttribute("name", "xp_" + ps);
  -                                     e.setAttribute("pattern", ps);
  -
  -                                     // Set the type for the index
  -                                     String type = null;
  -                                     switch (objType)
  -                                     {
  -                                             case XObject.CLASS_BOOLEAN :
  -                                                     type = "boolean";
  -                                                     break;
  -                                             case XObject.CLASS_NUMBER :
  -                                                     type = "double";
  -                                                     break;
  -                                             case XObject.CLASS_STRING :
  -                                                     if (ps.indexOf('@') != 
-1)
  -                                                     {
  -                                                             type = "string";
  -                                                     }
  -                                                     else
  -                                                     {
  -                                                             type = 
"trimmed";
  -                                                     }
  -                                                     break;
  -                                             default :
  -                                                     if (log.isWarnEnabled())
  -                                                     {
  -                                                             
log.warn("invalid object type : " + objType);
  -                                                     }
  -                                     }
  -                                     if (type != null)
  -                                     {
  -                                             e.setAttribute("type", type);
  -                                     }
  -
  -                                     idxMgr.create(new Configuration(e));
  -                             }
  -                     }
  -                     catch (Exception e)
  -                     {
  -                             if (log.isWarnEnabled())
  -                             {
  -                                     log.warn("ignored exception", e);
  -                             }
  -                     }
  -                     return null;
  -             }
  +             public NodeSet execute() throws QueryException {
  +                     try {
  +                Key[] keySet = keys;
  +
  +                // TODO: Add logic to do an indexed check on provided
  +                //       keySets that are larger than a certain minimum
  +
  +                if (keys == null && idxMgr != null) {
  +                    // Issue the query using Indexes
  +                    try {
  +                        Object obj = evaluate(null, 0);
  +                        if (obj instanceof NamedKeys) {
  +                            keySet = ((NamedKeys) obj).keys;
  +                        }
  +                    } catch (Exception e) {
  +                        if (log.isWarnEnabled()) {
  +                            log.warn("ignored exception", e);
  +                        }
  +                    }
  +                }
  +
  +                if (keySet == null) {
  +                    // Fall back to a Collection scan
  +                    SortedSet set = new TreeSet();
  +                    RecordSet rs = context.getFiler().getRecordSet();
  +                    while (rs.hasMoreRecords()) {
  +                        set.add(rs.getNextKey());
  +                    }
  +                    keySet = (Key[]) set.toArray(EMPTY_KEYS);
  +                }
  +
  +                return new ResultSet(context, pr, keySet, query);
  +            } catch (Exception e) {
  +                if (e instanceof QueryException) {
  +                    throw (QueryException) e.fillInStackTrace();
  +                }
  +                throw new ProcessingException("Error executing XPath query: 
" + e.getMessage(), e);
  +            }
  +        }
  +
  +        private Key[] andKeys(List list) {
  +            if (!list.isEmpty()) {
  +                if (list.size() > 1) {
  +                    Key[][] keys = (Key[][]) list.toArray(EMPTY_KEYSET);
  +                    return QueryEngine.andKeySets(keys);
  +                } else
  +                    return (Key[]) list.get(0);
  +            } else {
  +                return null;
  +            }
  +        }
  +
  +        // Evaluation Methods
   
                /**
  -              * queryComparison performs a comparison query use the operands 
that
  -              * are passed to it, and returns the resulting Keys.
  -              *
  -              * @param op The Operator
  -              * @param owner The Owner Node
  -              * @param left The left Operand
  -              * @param right The right Operand
  -              * @return The resulting Keys (if any)
  -              */
  -             private Object queryComparison(int op, String owner, Object 
left, Object right)
  -             {
  -                     op = OpMap[op - OpCodes.OP_NOTEQUALS];
  -
  -                     if (left instanceof XObject)
  -                     {
  -                             // Check if we have to switch the operation
  -                             if (op == IndexQuery.GT || op == IndexQuery.LT 
|| op == IndexQuery.GEQ || op == IndexQuery.LEQ)
  -                             {
  -                                     op = -op;
  -                             }
  -                             // Swap the operands
  -                             Object tmp = left;
  -                             left = right;
  -                             right = tmp;
  -                     }
  -
  -                     if (!(left instanceof NamedKeys && right instanceof 
XObject))
  -                     {
  -                             // can't handle it
  -                             return null;
  -                     }
  -
  -                     NamedKeys nk = (NamedKeys) left;
  -                     XObject obj = (XObject) right;
  -
  -                     String ps;
  -                     if (nk.attribute && nk.name.indexOf('@') == -1)
  -                     {
  -                             ps = owner + "@" + nk.name;
  -                     }
  -                     else
  -                     {
  -                             ps = nk.name;
  -                     }
  -
  -                     IndexQuery iq;
  -                     IndexPattern pattern = new IndexPattern(symbols, ps, 
nsMap);
  -                     String value = obj.str();
  -
  -                     switch (op)
  -                     {
  -                             case IndexQuery.NEQ :
  -                                     iq = new IndexQueryNEQ(pattern, value);
  -                                     break;
  -                             case IndexQuery.EQ :
  -                                     iq = new IndexQueryEQ(pattern, value);
  -                                     break;
  -                             case IndexQuery.LEQ :
  -                                     iq = new IndexQueryLEQ(pattern, value);
  -                                     break;
  -                             case IndexQuery.LT :
  -                                     iq = new IndexQueryLT(pattern, value);
  -                                     break;
  -                             case IndexQuery.GEQ :
  -                                     iq = new IndexQueryGEQ(pattern, value);
  -                                     break;
  -                             case IndexQuery.GT :
  -                                     iq = new IndexQueryGT(pattern, value);
  -                                     break;
  -                             default :
  -                                     iq = null; // Won't happen
  -                     }
  -
  -                     return queryIndexes(nk, iq, ps, obj.getType());
  -             }
  -     }
  +         * evaluate does a partial evaluation of the XPath in order to
  +         * determine the optimal indexes to prepare for the query and 
retrieve
  +         * the Document subset that will be used for the actual XPath query.
  +         *
  +         * <p>This will return an instance of one of the following classes:
  +         * <pre>
  +         *    String    If the sub-expression resolves to a Node Name
  +         *    XNumber   If the sub-expression resolves to a Number
  +         *    XString   If the sub-expression resolves to a String
  +         *    XBoolean  If the sub-expression resolves to a Boolean
  +         *    NamedKeys If the sub-expression resolves to a Key set
  +         *    null      If the sub-expression resolves to anything else
  +         * </pre>
  +         *
  +         * @param owner The parent node name for this context
  +         * @param pos   The position to start at (recursively called)
  +         * @return Some Object result
  +         */
  +        private Object evaluate(String owner, int pos) throws Exception {
  +            int op = cmp.getOp(pos);
  +            if (op == -1) {
  +                return null;
  +            }
  +
  +                     switch (op) {
  +                case OpCodes.OP_LOCATIONPATH:
  +                    return evalLocationPath(owner, pos);
  +
  +                case OpCodes.OP_ARGUMENT:
  +                case OpCodes.OP_XPATH:
  +                case OpCodes.OP_PREDICATE:
  +                    return evaluate(owner, Compiler.getFirstChildPos(pos));
  +
  +                case OpCodes.OP_OR:
  +                case OpCodes.OP_AND:
  +                    return evalSetComparison(op, owner, pos);
  +
  +                case OpCodes.OP_NOTEQUALS:
  +                case OpCodes.OP_EQUALS:
  +                case OpCodes.OP_LTE:
  +                case OpCodes.OP_LT:
  +                case OpCodes.OP_GTE:
  +                case OpCodes.OP_GT:
  +                    return evalValComparison(op, owner, pos);
  +
  +                case OpCodes.OP_PLUS:
  +                case OpCodes.OP_MINUS:
  +                case OpCodes.OP_MULT:
  +                case OpCodes.OP_DIV:
  +                case OpCodes.OP_MOD:
  +                case OpCodes.OP_QUO:
  +                    return evalMathOperation(op, owner, pos);
  +
  +                case OpCodes.OP_NEG:
  +                case OpCodes.OP_STRING:
  +                case OpCodes.OP_BOOL:
  +                case OpCodes.OP_NUMBER:
  +                    return evalUnaryOperation(op, owner, pos);
  +
  +                case OpCodes.OP_UNION:
  +                    return evalUnion(owner, pos);
  +
  +                case OpCodes.OP_VARIABLE:
  +                    break;
  +
  +                case OpCodes.OP_GROUP:
  +                    return evaluate(owner, Compiler.getFirstChildPos(pos));
  +
  +                case OpCodes.OP_EXTFUNCTION:
  +                    break;
  +
  +                case OpCodes.OP_FUNCTION:
  +                    return evalFunction(owner, pos);
  +
  +                case OpCodes.FROM_ANCESTORS:
  +                case OpCodes.FROM_ANCESTORS_OR_SELF:
  +                case OpCodes.FROM_ATTRIBUTES:
  +                case OpCodes.FROM_CHILDREN:
  +                case OpCodes.FROM_DESCENDANTS:
  +                case OpCodes.FROM_DESCENDANTS_OR_SELF:
  +                case OpCodes.FROM_FOLLOWING:
  +                case OpCodes.FROM_FOLLOWING_SIBLINGS:
  +                case OpCodes.FROM_PARENT:
  +                case OpCodes.FROM_PRECEDING:
  +                case OpCodes.FROM_PRECEDING_SIBLINGS:
  +                case OpCodes.FROM_NAMESPACE:
  +                case OpCodes.FROM_SELF:
  +                case OpCodes.FROM_ROOT:
  +                    return evalAxis(op, owner, pos);
  +
  +                case OpCodes.NODENAME:
  +                case OpCodes.OP_LITERAL:
  +                case OpCodes.OP_NUMBERLIT:
  +                    return evalLiteral(owner, pos);
  +
  +                case OpCodes.NODETYPE_TEXT:
  +                case OpCodes.NODETYPE_NODE:
  +                    return owner;
  +
  +                case OpCodes.NODETYPE_ANYELEMENT:
  +                case OpCodes.ELEMWILDCARD:
  +                    return WILDCARD;
  +
  +                case OpCodes.NODETYPE_ROOT:
  +                case OpCodes.NODETYPE_COMMENT:
  +                case OpCodes.NODETYPE_PI:
  +                case OpCodes.NODETYPE_FUNCTEST:
  +                    break;
  +
  +                default :
  +                    if (log.isWarnEnabled()) {
  +                        log.warn("Unknown: " + op);
  +                    }
  +            }
  +            return null;
  +        }
  +
  +             private Object evalLocationPath(String owner, int pos) throws 
Exception {
  +            int lp = Compiler.getFirstChildPos(pos);
  +            List ks = new ArrayList();
  +            String name = null;
  +            boolean attr = false;
  +                     while (cmp.getOp(lp) != -1) {
  +                Object obj = evaluate(owner, lp);
  +                             if (obj instanceof NamedKeys) {
  +                    NamedKeys nk = (NamedKeys) obj;
  +                    if (nk.name != null) {
  +                        attr = nk.attribute;
  +                        if (attr) {
  +                            if (name == null) {
  +                                name = owner;
  +                            }
  +                            if (name != null) {
  +                                StringBuffer sb = new StringBuffer(32);
  +                                sb.append(name);
  +                                sb.append('@');
  +                                sb.append(nk.name);
  +                                name = sb.toString();
  +                            }
  +                        } else {
  +                            name = nk.name;
  +                        }
  +                    }
  +                                     if (nk.keys != null) {
  +                        ks.add(nk.keys);
  +                    }
  +                    else if (name != null) {
  +                        // Try to use a NameIndex to resolve the path 
component
  +                        // can match a wildcard node name here if pattern is 
"*" then every document matches
  +                        if (attr == false && "*".equals(name)) {
  +                            SortedSet set = new TreeSet();
  +                            RecordSet rs = context.getFiler().getRecordSet();
  +                            while (rs.hasMoreRecords()) {
  +                                set.add(rs.getNextKey());
  +                            }
  +                            ks.add(set.toArray(EMPTY_KEYS));
  +                        } else {
  +                            // Try to use a NameIndex to resolve the path 
component
  +                            IndexPattern pattern = new IndexPattern(symbols, 
name, nsMap);
  +                            Indexer idx = 
context.getIndexManager().getBestIndexer(Indexer.STYLE_NODENAME, pattern);
  +                            if (idx != null) {
  +                                IndexMatch[] matches = idx.queryMatches(new 
IndexQueryANY(pattern));
  +                                Key[] keys = 
QueryEngine.getUniqueKeys(matches);
  +                                ks.add(keys);
  +                            }
  +                        }
  +                    }
  +                }
  +                lp = cmp.getNextOpPos(lp);
  +            }
  +            return new NamedKeys(name, attr, andKeys(ks));
  +        }
  +
  +        private Object evalUnion(String owner, int pos) throws Exception {
  +            int l = Compiler.getFirstChildPos(pos);
  +            int r = cmp.getNextOpPos(l);
  +            Object left = evaluate(owner, l);
  +
  +            if (left instanceof NamedKeys && ((NamedKeys) left).keys != 
null) {
  +                Object right = evaluate(owner, r);
  +
  +                if (right instanceof NamedKeys && ((NamedKeys) right).keys 
!= null) {
  +                    Key[][] keys = new Key[][]{((NamedKeys) left).keys, 
((NamedKeys) right).keys};
  +                    return new NamedKeys(null, false, 
QueryEngine.orKeySets(keys));
  +                }
  +            }
  +
  +            // no index query of left part of union
  +            // or no index query of right part of union => must do
  +            /// collection scan
  +            return null;
  +        }
  +
  +             private Object evalSetComparison(int op, String owner, int pos) 
throws Exception {
  +            int l = Compiler.getFirstChildPos(pos);
  +            int r = cmp.getNextOpPos(l);
  +            Object left = evaluate(owner, l);
  +
  +                     if (left instanceof NamedKeys && ((NamedKeys) 
left).keys != null) {
  +                // have left keys
  +                if (((NamedKeys) left).keys.length == 0 && op == 
OpCodes.OP_AND) {
  +                    // left keyset empty implies result of AND would be empty
  +                    return new NamedKeys(null, false, ((NamedKeys) 
left).keys);
  +                }
  +
  +                Object right = evaluate(owner, r);
  +                             if (right instanceof NamedKeys && ((NamedKeys) 
right).keys != null) {
  +                    // have keys for both left and right
  +                                     if (op == OpCodes.OP_AND) {
  +                        if (((NamedKeys) right).keys.length == 0) {
  +                            // right keyset empty implies result of AND 
would be empty
  +                            return new NamedKeys(null, false, ((NamedKeys) 
right).keys);
  +                        }
   
  -     /**
  -      * NamedKeys
  -      */
  +                        Key[][] keys = new Key[][]{((NamedKeys) left).keys, 
((NamedKeys) right).keys};
  +                        return new NamedKeys(null, false, 
QueryEngine.andKeySets(keys));
  +                    } else {
  +                        // OR operation
  +                        if (((NamedKeys) left).keys.length == 0) {
  +                            // OR operation and left empty implies result is 
right set
  +                            return new NamedKeys(null, false, ((NamedKeys) 
right).keys);
  +                        }
  +
  +                        if (((NamedKeys) right).keys.length == 0) {
  +                            // OR operation and right empty implies result 
is left set
  +                            return new NamedKeys(null, false, ((NamedKeys) 
left).keys);
  +                        }
  +
  +                        Key[][] keys = new Key[][]{((NamedKeys) left).keys, 
((NamedKeys) right).keys};
  +                        return new NamedKeys(null, false, 
QueryEngine.orKeySets(keys));
  +                    }
  +                } else {
  +                    // have left keys but not right can infer that AND 
operation
  +                    // result cannot contain more than left set so return 
that
  +                    if (op == OpCodes.OP_AND) {
  +                        return new NamedKeys(null, false, ((NamedKeys) 
left).keys);
  +                    }
  +                }
  +            } else {
  +                // do not have left keys
  +                Object right = evaluate(owner, r);
  +                if (right instanceof NamedKeys && ((NamedKeys) right).keys 
!= null) {
  +                    // have right keys but not left can infer that AND 
operation
  +                    // result cannot contain more than right set so return 
that
  +                    if (op == OpCodes.OP_AND) {
  +                        return new NamedKeys(null, false, ((NamedKeys) 
right).keys);
  +                    }
  +                }
  +            }
  +
  +            // punt
  +            return null;
  +        }
  +
  +        private Object evalValComparison(int op, String owner, int pos) 
throws Exception {
  +            int l = Compiler.getFirstChildPos(pos);
  +            int r = cmp.getNextOpPos(l);
  +
  +            Object left = evaluate(owner, l);
  +            if (!(left instanceof XObject || left instanceof NamedKeys)) {
  +                // can't evaluate
  +                return null;
  +            }
  +
  +            Object right = evaluate(owner, r);
  +            if ((left instanceof NamedKeys && right instanceof XObject)
  +                    || (left instanceof XObject && right instanceof 
NamedKeys)) {
  +                // try to evaluate through indexed search
  +                return queryComparison(op, owner, left, right);
  +            }
  +
  +            // could handle comparison of nodeset to boolean here
  +            // boolean converts to 1.0 (true) or 0.0 (false)
  +            // nodeset converts to 1.0 (non-empty) or 0.0 (empty)
  +            // but since this is a rare and odd comparison we don't bother 
now...
  +            if (left instanceof XObject && right instanceof XObject) {
  +                switch (op) {
  +                    case OpCodes.OP_NOTEQUALS:
  +                        return new XBoolean(((XObject) 
left).notEquals((XObject) right));
  +                    case OpCodes.OP_EQUALS:
  +                        return new XBoolean(((XObject) 
left).equals((XObject) right));
  +                    case OpCodes.OP_LTE:
  +                        return new XBoolean(((XObject) 
left).lessThanOrEqual((XObject) right));
  +                    case OpCodes.OP_LT:
  +                        return new XBoolean(((XObject) 
left).lessThan((XObject) right));
  +                    case OpCodes.OP_GTE:
  +                        return new XBoolean(((XObject) 
left).greaterThanOrEqual((XObject) right));
  +                    case OpCodes.OP_GT:
  +                        return new XBoolean(((XObject) 
left).greaterThan((XObject) right));
  +                    default :
  +                        return null; // Won't happen
  +                }
  +            }
  +
  +            // can't evaluate here...
  +            return null;
  +        }
  +
  +        private strictfp Object evalMathOperation(int op, String owner, int 
pos) throws Exception {
  +            int lc = Compiler.getFirstChildPos(pos);
  +            int rc = cmp.getNextOpPos(lc);
  +            Object left = evaluate(owner, lc);
  +
  +            if (left instanceof XObject) {
  +                Object right = evaluate(owner, rc);
  +                if (right instanceof XObject) {
  +                    switch (op) {
  +                        case OpCodes.OP_PLUS:
  +                            return new XNumber(((XObject) left).num() + 
((XObject) right).num());
  +                        case OpCodes.OP_MINUS:
  +                            return new XNumber(((XObject) left).num() - 
((XObject) right).num());
  +                        case OpCodes.OP_MULT:
  +                            return new XNumber(((XObject) left).num() * 
((XObject) right).num());
  +                        case OpCodes.OP_DIV:
  +                            return new XNumber(((XObject) left).num() / 
((XObject) right).num());
  +                        case OpCodes.OP_MOD:
  +                            return new XNumber(((XObject) left).num() % 
((XObject) right).num());
  +                        case OpCodes.OP_QUO:
  +                            return new XNumber(((XObject) left).num() / 
((XObject) right).num());
  +                        default :
  +                            return null; // Won't happen
  +                    }
  +                }
  +            }
  +
  +            // can't evaluate
  +            return null;
  +        }
  +
  +        private Object evalUnaryOperation(int op, String owner, int pos) 
throws Exception {
  +            Object val = evaluate(owner, Compiler.getFirstChildPos(pos));
  +            if (val instanceof XObject) {
  +                switch (op) {
  +                    case OpCodes.OP_NEG:
  +                        return new XNumber(-((XObject) val).num());
  +                    case OpCodes.OP_STRING:
  +                        return new XString(((XObject) val).str());
  +                    case OpCodes.OP_BOOL:
  +                        return new XBoolean(((XObject) val).bool());
  +                    case OpCodes.OP_NUMBER:
  +                        return new XNumber(((XObject) val).num());
  +                    default:
  +                        return null; // Won't happen
  +                }
  +            }
  +            if (val instanceof NamedKeys) {
  +                NamedKeys nk = (NamedKeys) val;
  +                // we may be able to convert the nodeset to the proper type
  +                // and return an answer numeric operations imply conversion 
to
  +                // string and then to number
  +                // we can't convert to string
  +                // we can handle conversion to boolean (empty or not empty)
  +                if (nk.keys != null && op == OpCodes.OP_BOOL) {
  +                    return nk.keys.length == 0 ? XBoolean.S_FALSE : 
XBoolean.S_TRUE;
  +                }
  +            }
  +            return null;
  +        }
  +
  +        private Object evalFunction(String owner, int pos) throws Exception {
  +            int idx = Compiler.getFirstChildPos(pos);
  +            int id = cmp.getOp(idx);
  +
  +            // NOTE: In the XPath op table, the
  +            // op code is stored at the current position index passed to us
  +            // the size of the current op is stored in the next location
  +            // thus, the index of the location just beyond the function
  +            // arguments for the current op (which is also the index of the 
next op)
  +            // is equal to the current postion + the size of the current 
operation - 1
  +            // (the getOp(index) method merely returns the int value stored 
in the op table
  +            // at the specified index. That value is an op code, a size, or 
the index
  +            // of an token or ... (see org.apache.xpath.compiler.OpCodes for 
the
  +            // various items that can be part of an operation)
  +            int endFunc = pos + cmp.getOp(pos + 1) - 1;
  +
  +            List args = new ArrayList();
  +            int lp = idx + 1;
  +            while (lp < endFunc) {
  +                args.add(evaluate(owner, lp));
  +                lp = cmp.getNextOpPos(lp);
  +            }
  +
  +            switch (id) {
  +                case FunctionTable.FUNC_BOOLEAN:
  +                    return funcBoolean(args);
  +                case FunctionTable.FUNC_CEILING:
  +                    return funcCeiling(args);
  +                case FunctionTable.FUNC_CONCAT:
  +                    return funcConcat(args);
  +                case FunctionTable.FUNC_CONTAINS:
  +                    return funcContains(args);
  +                case FunctionTable.FUNC_FALSE:
  +                    return XBoolean.S_FALSE;
  +                case FunctionTable.FUNC_FLOOR:
  +                    return funcFloor(args);
  +                case FunctionTable.FUNC_NORMALIZE_SPACE:
  +                    return funcNormalizeSpace(args);
  +                case FunctionTable.FUNC_NOT:
  +                    return funcNot(args);
  +                case FunctionTable.FUNC_NUMBER:
  +                    return funcNumber(args);
  +                case FunctionTable.FUNC_ROUND:
  +                    return funcRound(args);
  +                case FunctionTable.FUNC_STARTS_WITH:
  +                    return funcStartsWith(owner, args);
  +                case FunctionTable.FUNC_STRING:
  +                    return funcString(args);
  +                case FunctionTable.FUNC_STRING_LENGTH:
  +                    return funcStringLength(args);
  +                case FunctionTable.FUNC_SUBSTRING:
  +                    return funcSubstring(args);
  +                case FunctionTable.FUNC_SUBSTRING_AFTER:
  +                    return funcSubstringAfter(args);
  +                case FunctionTable.FUNC_SUBSTRING_BEFORE:
  +                    return funcSubstringBefore(args);
  +                case FunctionTable.FUNC_TRANSLATE:
  +                    return funcTranslate(args);
  +                case FunctionTable.FUNC_TRUE:
  +                    return XBoolean.S_TRUE;
  +                default:
  +                    return null;
  +            }
  +        }
  +
  +        private Object evalAxis(int op, String owner, int pos) throws 
Exception {
  +            String nsURI = cmp.getStepNS(pos);
  +            owner = (String) evaluate(owner, 
Compiler.getFirstChildPosOfStep(pos));
  +            // owner = cmp.getStepLocalName(pos);
  +
  +            if (nsURI != null && nsMap != null) {
  +                // We have to determine the prefix that was used
  +                // There has to be an easier way to do this with Xalan
  +                String pfx = null;
  +                Iterator i = nsMap.keySet().iterator();
  +                while (i.hasNext()) {
  +                    String p = (String) i.next();
  +                    if (nsMap.getNamespaceURI(p).equals(nsURI)) {
  +                        pfx = p;
  +                        break;
  +                    }
  +                }
  +                if (pfx != null) {
  +                    StringBuffer sb = new StringBuffer(32);
  +                    sb.append(pfx);
  +                    sb.append(':');
  +                    sb.append(owner);
  +                    owner = sb.toString();
  +                }
  +            }
  +
  +            int rp = cmp.getFirstPredicateOpPos(pos);
  +
  +            List ks = new ArrayList();
  +            while (rp < pos + cmp.getOp(pos + 1)) {
  +                Object obj = evaluate(owner, rp);
  +                if (obj instanceof NamedKeys) {
  +                    NamedKeys nk = (NamedKeys) obj;
  +                    if (nk.keys != null) {
  +                        ks.add(nk.keys);
  +                    }
  +                }
  +                rp = cmp.getNextOpPos(rp);
  +            }
  +            return new NamedKeys(owner, (op == OpCodes.FROM_ATTRIBUTES), 
andKeys(ks));
  +        }
  +
  +        private Object evalLiteral(String owner, int pos) {
  +            int idx = cmp.getOp(Compiler.getFirstChildPos(pos));
  +            switch (idx) {
  +                case OpCodes.EMPTY:
  +                    return owner;
  +                case OpCodes.ELEMWILDCARD:
  +                    return WILDCARD;
  +                default:
  +                    return cmp.getToken(idx);
  +            }
  +        }
  +
  +        // XPath Functions
  +
  +        private Object funcBoolean(List args) throws Exception {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject) {
  +                    if (((XObject) o).bool()) {
  +                        return XBoolean.S_TRUE;
  +                    } else {
  +                        return XBoolean.S_FALSE;
  +                    }
  +                } else {
  +                    if (o instanceof NamedKeys) {
  +                        NamedKeys nk = (NamedKeys) o;
  +                        if (nk.keys == null) {
  +                            return null;
  +                        }
  +                        if (nk.keys.length == 0) {
  +                            // nodeset empty converts to boolean false
  +                            return XBoolean.S_FALSE;
  +                        }
  +                        return XBoolean.S_TRUE;
  +                    }
  +                }
  +            }
  +            return null;
  +        }
  +
  +        private Object funcCeiling(List args) throws Exception {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject) {
  +                    return new XNumber(Math.ceil(((XObject) o).num()));
  +                }
  +            }
  +            return null;
  +        }
  +
  +        private Object funcConcat(List args) {
  +            StringBuffer sb = new StringBuffer();
  +            for (int i = 0; i < args.size(); i++) {
  +                Object o = args.get(i);
  +                if (o instanceof XObject) {
  +                    sb.append(((XObject) o).str());
  +                } else {
  +                    return null;
  +                }
  +            }
  +            return new XString(sb.toString());
  +        }
  +
  +        private Object funcContains(List args) {
  +            if (args.size() == 2) {
  +                Object o = args.get(0);
  +                Object s = args.get(1);
  +                if (o instanceof XObject && s instanceof XObject) {
  +                    if (((XObject) o).str().indexOf(((XObject) s).str()) != 
-1) {
  +                        return XBoolean.S_TRUE;
  +                    } else {
  +                        return XBoolean.S_FALSE;
  +                    }
  +                }
  +            }
  +            return null;
  +        }
  +
  +        private Object funcFloor(List args) throws Exception {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject) {
  +                    return new XNumber(Math.floor(((XObject) o).num()));
  +                }
  +            }
  +            return null;
  +        }
  +
  +        private Object funcNormalizeSpace(List args) {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject) {
  +                    return new 
XString(QueryEngine.normalizeString(((XObject) o).str()));
  +                }
  +            }
  +            return null;
  +        }
  +
  +        private Object funcNot(List args) throws Exception {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject) {
  +                    if (((XObject) o).bool()) {
  +                        return XBoolean.S_FALSE;
  +                    } else {
  +                        return XBoolean.S_TRUE;
  +                    }
  +                } else {
  +                    if (o instanceof NamedKeys) {
  +                        NamedKeys nk = (NamedKeys) o;
  +                        if (nk.keys == null) {
  +                            return null;
  +                        }
  +                        if (nk.keys.length == 0) {
  +                            // nodeset empty converts to boolean false => 
not false => true
  +                            return XBoolean.S_TRUE;
  +                        }
  +                        return XBoolean.S_FALSE;
  +                    }
  +                    return null;
  +                }
  +
  +            }
  +            return null;
  +        }
  +
  +        private Object funcNumber(List args) throws Exception {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject) {
  +                    return new XNumber(((XObject) o).num());
  +                }
  +            }
  +            return null;
  +        }
  +
  +        private Object funcRound(List args) throws Exception {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject) {
  +                    return new XNumber(Math.round(((XObject) o).num()));
  +                }
  +            }
  +            return null;
  +        }
  +
  +        private Object funcStartsWith(String owner, List args) {
  +            if (args.size() == 2) {
  +                Object o = args.get(0);
  +                Object s = args.get(1);
  +
  +                if (o instanceof XObject && s instanceof XObject) {
  +                    if (((XObject) o).str().startsWith(((XObject) s).str())) 
{
  +                        return XBoolean.S_TRUE;
  +                    } else {
  +                        return XBoolean.S_FALSE;
  +                    }
  +                } else if (o instanceof NamedKeys && s instanceof XObject) {
  +                    NamedKeys nk = (NamedKeys) o;
  +                    String ps;
  +                    if (nk.attribute && nk.name.indexOf('@') == -1) {
  +                        ps = owner + "@" + nk.name;
  +                    } else {
  +                        ps = nk.name;
  +                    }
  +
  +                    IndexPattern pattern = new IndexPattern(symbols, ps, 
nsMap);
  +
  +                    XObject obj = (XObject) s;
  +                    Value val1 = new Value(obj.str());
  +
  +                    IndexQuery iq = new IndexQuerySW(pattern, val1);
  +                    return queryIndexes(nk, iq, ps, obj.getType());
  +                }
  +            }
  +            return null;
  +        }
  +
  +        private Object funcString(List args) {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject) {
  +                    return new XString(((XObject) o).str());
  +                }
  +            }
  +            return null;
  +        }
  +
  +        private Object funcStringLength(List args) {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject) {
  +                    return new XNumber(((XObject) o).str().length());
  +                }
  +            }
  +            return null;
  +        }
  +
  +        private Object funcSubstring(List args) throws Exception {
  +            if (args.size() == 2 || args.size() == 3) {
  +                Object o = args.get(0);
  +                Object pos = args.get(1);
  +                Object len = args.size() == 3 ? args.get(2) : null;
  +                if (o instanceof XObject && pos instanceof XObject && (len 
== null || len instanceof XObject)) {
  +                    int ipos = (int) ((XObject) pos).num() - 1;
  +                    if (len != null) {
  +                        int ilen = (int) ((XObject) len).num();
  +                        return new XString(((XObject) 
o).str().substring(ipos, ipos + ilen));
  +                    } else
  +                        return new XString(((XObject) 
o).str().substring(ipos));
  +                }
  +            }
  +            return null;
  +        }
  +
  +        private Object funcSubstringAfter(List args) {
  +            if (args.size() == 2) {
  +                Object o = args.get(0);
  +                Object s = args.get(1);
  +                if (o instanceof XObject && s instanceof XObject) {
  +                    String val = ((XObject) o).str();
  +                    String sub = ((XObject) s).str();
  +                    int i = val.indexOf(sub);
  +                    if (i == -1) {
  +                        return new XString("");
  +                    } else {
  +                        return new XString(val.substring(i + sub.length()));
  +                    }
  +                }
  +            }
  +            return null;
  +        }
  +
  +        private Object funcSubstringBefore(List args) {
  +            if (args.size() == 2) {
  +                Object o = args.get(0);
  +                Object s = args.get(1);
  +                if (o instanceof XObject && s instanceof XObject) {
  +                    String val = ((XObject) o).str();
  +                    String sub = ((XObject) s).str();
  +                    int i = val.indexOf(sub);
  +                    if (i == -1) {
  +                        return new XString("");
  +                    } else {
  +                        return new XString(val.substring(0, i));
  +                    }
  +                }
  +            }
  +            return null;
  +        }
  +
  +        private Object funcTranslate(List args) {
  +            if (args.size() == 3) {
  +                Object o = args.get(0);
  +                Object c1 = args.get(1);
  +                Object c2 = args.get(2);
  +                if (o instanceof XObject && c1 instanceof XObject && c2 
instanceof XObject) {
  +                    char ch1 = ((XObject) c1).str().charAt(0);
  +                    char ch2 = ((XObject) c2).str().charAt(0);
  +                    return new XString(((XObject) o).str().replace(ch1, 
ch2));
  +                }
  +            }
  +            return null;
  +        }
  +
  +        // The Actual Querying Methods
  +
  +             /**
  +         * queryIndexes actually performs index-based querying on behalf of 
the evaluation methods.
  +         *
  +         * @param nk      The NamedKeys instance to use for matches
  +         * @param iq      The actual IndexQuery to use for resolution
  +         * @param ps      The pattern String to possibly use for index gen
  +         * @param objType The object type to possibly use for index gen
  +         * @return The resulting Keys (if any)
  +         */
  +        private Object queryIndexes(NamedKeys nk, IndexQuery iq, String ps, 
int objType) {
  +                     try {
  +                // TODO: Add logic to use an EmptyKeySet if a name doesn't 
already
  +                //       exist in the SymbolTable.  This will eliminate the 
need
  +                //       to do a collection scan in those cases where 
somebody
  +                //       typed an element or attribute name incorrectly.
  +
  +                IndexPattern pattern = iq.getPattern();
  +
  +                Indexer idx = 
context.getIndexManager().getBestIndexer(Indexer.STYLE_NODEVALUE, pattern);
  +                             if (idx != null) {
  +                    return new NamedKeys(nk.name, nk.attribute, 
QueryEngine.getUniqueKeys(idx.queryMatches(iq)));
  +                } else if (autoIndex) {
  +                    // TODO: This has to *not* be hardcoded
  +                    Element e = new DocumentImpl().createElement("index");
  +                    e.setAttribute("class", 
"org.apache.xindice.core.indexer.ValueIndexer");
  +                    e.setAttribute("name", "xp_" + ps);
  +                    e.setAttribute("pattern", ps);
  +
  +                    // Set the type for the index
  +                    String type = null;
  +                    switch (objType) {
  +                        case XObject.CLASS_BOOLEAN:
  +                            type = "boolean";
  +                            break;
  +                        case XObject.CLASS_NUMBER:
  +                            type = "double";
  +                            break;
  +                        case XObject.CLASS_STRING:
  +                            if (ps.indexOf('@') != -1) {
  +                                type = "string";
  +                            } else {
  +                                type = "trimmed";
  +                            }
  +                            break;
  +                        default :
  +                            if (log.isWarnEnabled()) {
  +                                log.warn("invalid object type : " + objType);
  +                            }
  +                    }
  +
  +                    if (type != null) {
  +                        e.setAttribute("type", type);
  +                    }
   
  -     private class NamedKeys
  -     {
  -             public boolean attribute = false;
  -             public String name;
  -             public Key[] keys;
  -
  -             public NamedKeys(String name, boolean attribute, Key[] keys)
  -             {
  -                     this.name = name;
  -                     this.attribute = attribute;
  -                     this.keys = keys;
  -             }
  -     }
  +                    idxMgr.create(new Configuration(e));
  +                }
  +            } catch (Exception e) {
  +                if (log.isWarnEnabled()) {
  +                    log.warn("ignored exception", e);
  +                }
  +            }
  +            return null;
  +        }
  +
  +        /**
  +         * queryComparison performs a comparison query use the operands that 
are passed to it, and returns the resulting
  +         * Keys.
  +         *
  +         * @param op    The Operator
  +         * @param owner The Owner Node
  +         * @param left  The left Operand
  +         * @param right The right Operand
  +         * @return The resulting Keys (if any)
  +         */
  +        private Object queryComparison(int op, String owner, Object left, 
Object right) {
  +            op = OpMap[op - OpCodes.OP_NOTEQUALS];
  +
  +            if (left instanceof XObject) {
  +                // Check if we have to switch the operation
  +                if (op == IndexQuery.GT || op == IndexQuery.LT || op == 
IndexQuery.GEQ || op == IndexQuery.LEQ) {
  +                    op = -op;
  +                }
  +                // Swap the operands
  +                Object tmp = left;
  +                left = right;
  +                right = tmp;
  +            }
  +
  +            if (!(left instanceof NamedKeys && right instanceof XObject)) {
  +                // can't handle it
  +                return null;
  +            }
  +
  +            NamedKeys nk = (NamedKeys) left;
  +            XObject obj = (XObject) right;
  +
  +            String ps;
  +            if (nk.attribute && nk.name.indexOf('@') == -1) {
  +                ps = owner + "@" + nk.name;
  +            } else {
  +                ps = nk.name;
  +            }
  +
  +            IndexQuery iq;
  +            IndexPattern pattern = new IndexPattern(symbols, ps, nsMap);
  +            String value = obj.str();
  +
  +            switch (op) {
  +                case IndexQuery.NEQ:
  +                    iq = new IndexQueryNEQ(pattern, value);
  +                    break;
  +                case IndexQuery.EQ:
  +                    iq = new IndexQueryEQ(pattern, value);
  +                    break;
  +                case IndexQuery.LEQ:
  +                    iq = new IndexQueryLEQ(pattern, value);
  +                    break;
  +                case IndexQuery.LT:
  +                    iq = new IndexQueryLT(pattern, value);
  +                    break;
  +                case IndexQuery.GEQ:
  +                    iq = new IndexQueryGEQ(pattern, value);
  +                    break;
  +                case IndexQuery.GT:
  +                    iq = new IndexQueryGT(pattern, value);
  +                    break;
  +                default :
  +                    iq = null; // Won't happen
  +            }
  +
  +            return queryIndexes(nk, iq, ps, obj.getType());
  +        }
  +    }
  +
  +    /**
  +     * NamedKeys
  +     */
  +
  +    private class NamedKeys {
  +        public boolean attribute = false;
  +        public String name;
  +        public Key[] keys;
  +
  +        public NamedKeys(String name, boolean attribute, Key[] keys) {
  +            this.name = name;
  +            this.attribute = attribute;
  +            this.keys = keys;
  +        }
  +    }
   
        /**
  -      * ResultSet
  -      */
  +     * ResultSet
  +     */
   
  -     private class ResultSet implements NodeSet {
  -             public Collection context;
  -             public String query;
  -             public ErrorListener errors;
  -             public PrefixResolver pr;
  -             public XPath xp;
  -
  -             public Key[] keySet;
  -             public int keyPos = 0;
  -             public NodeIterator ni;
  -             public Object node;
  +    private class ResultSet implements NodeSet {
  +        public Collection context;
  +        public String query;
  +        public ErrorListener errors;
  +        public PrefixResolver pr;
  +        public XPath xp;
  +
  +        public Key[] keySet;
  +        public int keyPos = 0;
  +        public NodeIterator ni;
  +        public Object node;
   
                public ResultSet(Collection context, PrefixResolver pr, Key[] 
keySet, String query) {
  -                     this.context = context;
  -                     this.pr = pr;
  -                     this.keySet = keySet;
  -                     this.query = query;
  -
  -                     errors = new ErrorListener() {
  -                             public void fatalError(TransformerException te) 
{
  -                                     if (log.isFatalEnabled()) {
  -                                             log.fatal("No message", te);
  -                                     }
  -                             }
  -
  -                             public void error(TransformerException te) {
  -                                     if (log.isErrorEnabled()) {
  -                                             log.error("No message", te);
  -                                     }
  -                             }
  -
  -                             public void warning(TransformerException te) {
  -                                     if (log.isWarnEnabled()) {
  -                                             log.warn("No message", te);
  -                                     }
  -                             }
  -                     };
  +            this.context = context;
  +            this.pr = pr;
  +            this.keySet = keySet;
  +            this.query = query;
  +
  +            errors = new ErrorListener() {
  +                public void fatalError(TransformerException te) {
  +                    if (log.isFatalEnabled()) {
  +                        log.fatal("No message", te);
  +                    }
  +                }
  +
  +                public void error(TransformerException te) {
  +                    if (log.isErrorEnabled()) {
  +                        log.error("No message", te);
  +                    }
  +                }
  +
  +                public void warning(TransformerException te) {
  +                    if (log.isWarnEnabled()) {
  +                        log.warn("No message", te);
  +                    }
  +                }
  +            };
   
  -                     try {
  -                             prepareNextNode();
  +            try {
  +                prepareNextNode();
               } catch (Exception e) {
  -                             throw new 
XindiceRuntimeException(e.getMessage());
  -                     }
  -             }
  +                throw new XindiceRuntimeException(e.getMessage());
  +            }
  +        }
   
                private void prepareNextNode() throws XMLDBException, 
TransformerException, DBException {
  -                     node = null;
  +            node = null;
   
                        while (keyPos < keySet.length) {
  -                             DBDocument d = (DBDocument) 
context.getDocument(keySet[keyPos++]);
  -                             if (d == null) {
  -                                     continue;
  -                             }
  -
  -                             Node n = d.getDocumentElement();
  -
  -                             XPathContext xpc = new XPathContext();
  -                             PrefixResolver pfx;
  -                             if (pr == null) {
  -                                     pfx = new 
PrefixResolverDefault(d.getDocumentElement());
  -                                     xp = new XPath(query, null, pfx, 
XPath.SELECT, errors);
  -                             } else {
  -                                     pfx = pr;
  -                                     if (xp == null) {
  -                                             xp = new XPath(query, null, 
pfx, XPath.SELECT, errors);
  -                                     }
  -                             }
  +                DBDocument d = (DBDocument) 
context.getDocument(keySet[keyPos++]);
  +                if (d == null) {
  +                    continue;
  +                }
  +
  +                Node n = d.getDocumentElement();
  +
  +                XPathContext xpc = new XPathContext();
  +                PrefixResolver pfx;
  +                if (pr == null) {
  +                    pfx = new PrefixResolverDefault(d.getDocumentElement());
  +                    xp = new XPath(query, null, pfx, XPath.SELECT, errors);
  +                } else {
  +                    pfx = pr;
  +                    if (xp == null) {
  +                        xp = new XPath(query, null, pfx, XPath.SELECT, 
errors);
  +                    }
  +                }
   
  -                             final XObject xobject = xp.execute(xpc, n, pfx);
  +                final XObject xobject = xp.execute(xpc, n, pfx);
                                switch (xobject.getType()) {
                       // case XObject.CLASS_RTREEEFRAG :
  -                                     default :
  -                                             throw new XMLDBException(
  -                                                     
ErrorCodes.NOT_IMPLEMENTED,
  -                                                     "Unsupported result 
type: " + xobject.getTypeString());
  -
  -                                     case XObject.CLASS_NODESET :
  -                                             ni = xobject.nodeset();
  -                                             node = ni.nextNode();
  -                                             break;
  +                    default :
  +                        throw new XMLDBException(ErrorCodes.NOT_IMPLEMENTED,
  +                                                 "Unsupported result type: " 
+ xobject.getTypeString());
  +
  +                    case XObject.CLASS_NODESET:
  +                        ni = xobject.nodeset();
  +                        node = ni.nextNode();
  +                        break;
   
  -                                     case XObject.CLASS_BOOLEAN :
  -                                             ni = EMPTY_NODE_ITERATOR;
  +                    case XObject.CLASS_BOOLEAN:
  +                        ni = EMPTY_NODE_ITERATOR;
   
                           node = new 
DocumentImpl().createTextNode(Boolean.toString(xobject.bool()));
                           if (n instanceof DBNode) {
  -                            
((TextImpl)node).setSource(((DBNode)n).getSource());
  +                            ((TextImpl) node).setSource(((DBNode) 
n).getSource());
                           }
  -                                             break;
  +                        break;
   
  -                                     case XObject.CLASS_STRING :
  -                                             ni = EMPTY_NODE_ITERATOR;
  +                    case XObject.CLASS_STRING:
  +                        ni = EMPTY_NODE_ITERATOR;
   
                           node = new 
DocumentImpl().createTextNode(xobject.str());
                           if (n instanceof DBNode) {
  -                            
((TextImpl)node).setSource(((DBNode)n).getSource());
  +                            ((TextImpl) node).setSource(((DBNode) 
n).getSource());
                           }
  -                                             break;
  +                        break;
   
  -                                     case XObject.CLASS_NUMBER :
  -                                             ni = EMPTY_NODE_ITERATOR;
  +                    case XObject.CLASS_NUMBER:
  +                        ni = EMPTY_NODE_ITERATOR;
   
                           node = new 
DocumentImpl().createTextNode(Double.toString(xobject.num()));
                           if (n instanceof DBNode) {
  -                            
((TextImpl)node).setSource(((DBNode)n).getSource());
  +                            ((TextImpl) node).setSource(((DBNode) 
n).getSource());
                           }
  -                                             break;
  -                             }
  +                        break;
  +                }
   
  -                             if (node != null) {
  -                                     break;
  -                             }
  -                     }
  -             }
  -
  -             public boolean hasMoreNodes() {
  -                     return node != null;
  -             }
  -
  -             public Object getNextNode() {
  -                     Object n = node;
  -
  -                     node = ni.nextNode();
  -                     if (node == null) {
  -                             try {
  -                                     prepareNextNode();
  -                             } catch (Exception e) {
  -                                     throw new 
XindiceRuntimeException(e.getMessage());
  -                             }
  -                     }
  -
  -                     return n;
  -             }
  -     }
  +                if (node != null) {
  +                    break;
  +                }
  +            }
  +        }
  +
  +        public boolean hasMoreNodes() {
  +            return node != null;
  +        }
  +
  +        public Object getNextNode() {
  +            Object n = node;
  +
  +            node = ni.nextNode();
  +            if (node == null) {
  +                try {
  +                    prepareNextNode();
  +                } catch (Exception e) {
  +                    throw new XindiceRuntimeException(e.getMessage());
  +                }
  +            }
  +
  +            return n;
  +        }
  +    }
   
        /* This only implements what we need internally */
  -     private static class EmptyNodeIterator implements NodeIterator
  -     {
  +    private static class EmptyNodeIterator implements NodeIterator {
   
  -             /* (non-Javadoc)
  -              * @see org.w3c.dom.traversal.NodeIterator#getWhatToShow()
  -              */
  -             public int getWhatToShow()
  -             {
  -                     throw new UnsupportedOperationException();
  -             }
  -
  -             /* (non-Javadoc)
  -              * @see org.w3c.dom.traversal.NodeIterator#detach()
  -              */
  -             public void detach()
  -             {
  -                     throw new UnsupportedOperationException();
  -             }
  -
  -             /* (non-Javadoc)
  -              * @see 
org.w3c.dom.traversal.NodeIterator#getExpandEntityReferences()
  -              */
  -             public boolean getExpandEntityReferences()
  -             {
  -                     throw new UnsupportedOperationException();
  -             }
  -
  -             /* (non-Javadoc)
  -              * @see org.w3c.dom.traversal.NodeIterator#getRoot()
  -              */
  -             public Node getRoot()
  -             {
  -                     throw new UnsupportedOperationException();
  -             }
  -
  -             /* (non-Javadoc)
  -              * @see org.w3c.dom.traversal.NodeIterator#nextNode()
  -              */
  -             public Node nextNode() throws DOMException
  -             {
  -                     return null;
  -             }
  -
  -             /* (non-Javadoc)
  -              * @see org.w3c.dom.traversal.NodeIterator#previousNode()
  -              */
  -             public Node previousNode() throws DOMException
  -             {
  -                     throw new UnsupportedOperationException();
  -             }
  -
  -             /* (non-Javadoc)
  -              * @see org.w3c.dom.traversal.NodeIterator#getFilter()
  -              */
  -             public NodeFilter getFilter()
  -             {
  -                     throw new UnsupportedOperationException();
  -             }
  -     }
  +        /* (non-Javadoc)
  +         * @see org.w3c.dom.traversal.NodeIterator#getWhatToShow()
  +         */
  +        public int getWhatToShow() {
  +            throw new UnsupportedOperationException();
  +        }
  +
  +        /* (non-Javadoc)
  +         * @see org.w3c.dom.traversal.NodeIterator#detach()
  +         */
  +        public void detach() {
  +            throw new UnsupportedOperationException();
  +        }
  +
  +        /* (non-Javadoc)
  +         * @see 
org.w3c.dom.traversal.NodeIterator#getExpandEntityReferences()
  +         */
  +        public boolean getExpandEntityReferences() {
  +            throw new UnsupportedOperationException();
  +        }
  +
  +        /* (non-Javadoc)
  +         * @see org.w3c.dom.traversal.NodeIterator#getRoot()
  +         */
  +        public Node getRoot() {
  +            throw new UnsupportedOperationException();
  +        }
  +
  +        /* (non-Javadoc)
  +         * @see org.w3c.dom.traversal.NodeIterator#nextNode()
  +         */
  +        public Node nextNode() throws DOMException {
  +            return null;
  +        }
  +
  +        /* (non-Javadoc)
  +         * @see org.w3c.dom.traversal.NodeIterator#previousNode()
  +         */
  +        public Node previousNode() throws DOMException {
  +            throw new UnsupportedOperationException();
  +        }
  +
  +        /* (non-Javadoc)
  +         * @see org.w3c.dom.traversal.NodeIterator#getFilter()
  +         */
  +        public NodeFilter getFilter() {
  +            throw new UnsupportedOperationException();
  +        }
  +    }
   
  -     private final static NodeIterator EMPTY_NODE_ITERATOR = new 
EmptyNodeIterator();
  +    private final static NodeIterator EMPTY_NODE_ITERATOR = new 
EmptyNodeIterator();
   }
  
  
  

Reply via email to