You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by dm...@apache.org on 2002/04/28 06:36:27 UTC

cvs commit: jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri EvalContext.java

dmitri      02/04/27 21:36:27

  Modified:    jxpath/src/java/org/apache/commons/jxpath/ri
                        EvalContext.java
  Log:
  Now implements Iterator
  
  Revision  Changes    Path
  1.13      +207 -48   jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/EvalContext.java
  
  Index: EvalContext.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/EvalContext.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- EvalContext.java	26 Apr 2002 03:28:37 -0000	1.12
  +++ EvalContext.java	28 Apr 2002 04:36:27 -0000	1.13
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/EvalContext.java,v 1.12 2002/04/26 03:28:37 dmitri Exp $
  - * $Revision: 1.12 $
  - * $Date: 2002/04/26 03:28:37 $
  + * $Header: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/EvalContext.java,v 1.13 2002/04/28 04:36:27 dmitri Exp $
  + * $Revision: 1.13 $
  + * $Date: 2002/04/28 04:36:27 $
    *
    * ====================================================================
    * The Apache Software License, Version 1.1
  @@ -69,6 +69,7 @@
   import org.apache.commons.jxpath.ri.model.NodeIterator;
   import org.apache.commons.jxpath.ri.model.NodePointer;
   import org.apache.commons.jxpath.ri.model.beans.*;
  +import org.apache.commons.jxpath.util.ValueUtils;
   
   /**
    * An XPath evaluation context.
  @@ -78,13 +79,14 @@
    * implement behavior of various XPath axes: "child::", "parent::" etc.
    *
    * @author Dmitri Plotnikov
  - * @version $Revision: 1.12 $ $Date: 2002/04/26 03:28:37 $
  + * @version $Revision: 1.13 $ $Date: 2002/04/28 04:36:27 $
    */
  -public abstract class EvalContext implements ExpressionContext {
  +public abstract class EvalContext implements ExpressionContext, Iterator {
       protected EvalContext parentContext;
       protected RootContext rootContext;
       protected int position = 0;
       private boolean startedSetIteration = false;
  +    private boolean done = false;
   
       public EvalContext(EvalContext parentContext){
           this.parentContext = parentContext;
  @@ -103,6 +105,52 @@
       }
   
       /**
  +     * Returns true if there are mode nodes matching the context's constraints.
  +     */
  +    public boolean hasNext(){
  +        if (done){
  +            return false;
  +        }
  +        if (position == 0){
  +            while (nextSet()){
  +                if (nextNode()){
  +                    return true;
  +                }
  +            }
  +            return false;
  +        }
  +        return true;
  +    }
  +    
  +    /**
  +     * Returns the next node pointer in the context
  +     */
  +    public Object next(){
  +        if (done || (position == 0 && !hasNext())){
  +            throw new NoSuchElementException();
  +        }
  +        NodePointer pointer = getCurrentNodePointer();
  +        if (!nextNode()){
  +            done = true;
  +            while (nextSet()){
  +                if (nextNode()){
  +                    done = false;
  +                    break;
  +                }
  +            }
  +        }
  +        return pointer;
  +    }
  +
  +    /**
  +     * Operation is not supported
  +     */
  +    public void remove(){
  +        throw new UnsupportedOperationException(
  +            "JXPath iterators cannot remove nodes");
  +    }
  +    
  +    /**
        * Returns the list of all Pointers in this context
        */
       public List getContextNodeList() {
  @@ -111,7 +159,7 @@
               reset();
           }
           List list = new ArrayList();
  -        while (next()) {
  +        while (nextNode()) {
               list.add(getCurrentNodePointer());
           }
           if (pos != 0) {
  @@ -133,7 +181,7 @@
           }
           List list = new ArrayList();
           while (nextSet()){
  -            while (next()) {
  +            while (nextNode()) {
                   list.add(getCurrentNodePointer());
               }
           }
  @@ -156,7 +204,7 @@
           }
           List list = new ArrayList();
           while (nextSet()){
  -            while (next()) {
  +            while (nextNode()) {
                   list.add(getCurrentNodePointer().getValue());
               }
           }
  @@ -201,14 +249,13 @@
       }
   
       /**
  -     * If the iteration has not started yet, starts the iteration and
  -     * returns the first encountered Pointer that matches the current
  -     * step's criteria.  Otherwise, returns the current pointer.
  +     * Returns the first encountered Pointer that matches the current
  +     * context's criteria.
        */
       public Pointer getSingleNodePointer(){
           reset();
           while(nextSet()){
  -            if (next()){
  +            if (nextNode()){
                   return getCurrentNodePointer();
               }
           }
  @@ -234,7 +281,7 @@
           if (!startedSetIteration) {
               startedSetIteration = true;
               while (parentContext.nextSet()) {
  -                if (parentContext.next()) {
  +                if (parentContext.nextNode()) {
                       return true;
                   }
               }
  @@ -243,14 +290,14 @@
   
           // In subsequent calls, we see if the parent context
           // has any nodes left in the current set
  -        if (parentContext.next()) {
  +        if (parentContext.nextNode()) {
               return true;
           }
   
           // If not, we look for the next set that contains
           // at least one node
           while (parentContext.nextSet()) {
  -            if (parentContext.next()) {
  +            if (parentContext.nextNode()) {
                   return true;
               }
           }
  @@ -260,7 +307,7 @@
        * Returns true if there is another object in the current set.
        * Switches the current position and node to the next object.
        */
  -    public abstract boolean next();
  +    public abstract boolean nextNode();
   
       /**
        * Moves the current position to the specified index. Used with integer
  @@ -292,12 +339,33 @@
       public Object eval(Expression expression){
           return eval(expression, true);
       }
  -
  +    
  +    public Iterator iterate(Expression expression){
  +        Object result = eval(expression, false);
  +        if (result instanceof EvalContext){
  +            return new ValueIterator((EvalContext)result);
  +        }
  +        return ValueUtils.iterate(result);
  +    }
  +    
  +    public Iterator iteratePointers(Expression expression){
  +        Object result = eval(expression, false);
  +        if (result == null){
  +            return Collections.EMPTY_LIST.iterator();
  +        }
  +        if (result instanceof EvalContext){
  +            return (EvalContext)result;
  +        }
  +        return new PointerIterator(ValueUtils.iterate(result), 
  +                    new QName(null, "value"), 
  +                    getRootContext().getCurrentNodePointer().getLocale());
  +    }
  +    
       /**
        * Evaluates the expression. If the result is a node set, returns
        * the whole set if firstMatch==false or the first element otherwise.
        */
  -    public Object eval(Expression expression, boolean firstMatch){
  +    private Object eval(Expression expression, boolean firstMatch){
           Object value = null;
           switch (expression.getEvaluationMode()){
               case Expression.EVALUATION_MODE_ONCE:
  @@ -393,7 +461,12 @@
               return coreFunction((CoreFunction)expression);
   
           case Expression.OP_LOCATION_PATH:
  -            return path((LocationPath)expression, firstMatch);
  +            if (firstMatch){
  +                return getSingleNodePointerForPath((LocationPath)expression);
  +            }
  +            else {
  +                return path((LocationPath)expression);
  +            }
   
           case Expression.OP_EXPRESSION_PATH:
               return expressionPath((ExpressionPath)expression, firstMatch);
  @@ -594,7 +667,7 @@
       private Set valueSet(){
           HashSet set = new HashSet();
           while(nextSet()){
  -            while(next()){
  +            while(nextNode()){
                   NodePointer pointer = getCurrentNodePointer();
                   set.add(pointer.getValue());
               }
  @@ -735,7 +808,7 @@
           }
           else if (object instanceof EvalContext){
               EvalContext ctx = (EvalContext)object;
  -            return ctx.nextSet() && ctx.next();
  +            return ctx.nextSet() && ctx.nextNode();
           }
           else if (object instanceof String){
               return ((String)object).length() != 0;
  @@ -747,11 +820,25 @@
       }
   
       /**
  -     * Walks a location path
  +     * Walks a location path and finds a single node that matches the path
        */
  -    protected Object path(LocationPath path, boolean firstMatch){
  -        Step steps[] = path.getSteps();
  -
  +    protected Pointer getSingleNodePointerForPath(LocationPath path) {
  +        // Create a chain of contexts
  +        EvalContext rootContext;
  +        if (path.isAbsolute()) {
  +            rootContext = getRootContext();
  +        }
  +        else {
  +            rootContext = this;
  +        }
  +        return getSingleNodePointerForSteps(
  +                    new InitialContext(rootContext), path);
  +    }
  +    /**
  +     * Walks a location path and returns a context containing all
  +     * nodes matching the path
  +     */
  +    protected EvalContext path(LocationPath path){
           // Create a chain of contexts
           EvalContext rootContext;
           if (path.isAbsolute()){
  @@ -760,7 +847,7 @@
           else {
               rootContext = this;
           }
  -        return evalSteps(new InitialContext(rootContext), path, firstMatch);
  +        return evalSteps(new InitialContext(rootContext), path);
       }
   
       /**
  @@ -805,21 +892,51 @@
                   context = new PredicateContext(context, predicates[j]);
               }
           }
  -        return evalSteps(context, path, firstMatch);
  +        if (firstMatch){
  +            return getSingleNodePointerForSteps(context, path);
  +        }
  +        else {
  +            return evalSteps(context, path);
  +        }
       }
   
       /**
  -     * Given a root context, walks a path therefrom
  +     * Given a root context, walks a path therefrom and finds the 
  +     * pointer to the first element matching the path.
        */
  -    private Object evalSteps(EvalContext context, Path path, boolean firstMatch){
  +    private Pointer getSingleNodePointerForSteps(EvalContext context, Path path){
           Step steps[] = path.getSteps();
  +        if (steps.length == 0){
  +            return context.getSingleNodePointer();
  +        }
   
  -        if (firstMatch && steps.length != 0){
  -            boolean basic = path.getEvaluationHint(Path.BASIC_PATH_HINT).equals(Boolean.TRUE);
  -            if (basic){
  -                NodePointer ptr = (NodePointer)context.getSingleNodePointer();
  -                return SimplePathInterpreter.interpretPath(this, ptr, steps);
  +        if (path.getEvaluationHint(Path.BASIC_PATH_HINT).equals(Boolean.TRUE)){
  +            NodePointer ptr = (NodePointer)context.getSingleNodePointer();
  +            return SimplePathInterpreter.interpretPath(this, ptr, steps);
  +        }
  +        else {
  +            for (int i = 0; i < steps.length; i++){
  +                context = createContextForStep(context, steps[i].getAxis(), steps[i].getNodeTest());
  +                Expression predicates[] = steps[i].getPredicates();
  +                if (predicates != null){
  +                    for (int j = 0; j < predicates.length; j++){
  +                        context = new PredicateContext(context, predicates[j]);
  +                    }
  +                }
               }
  +    
  +            return context.getSingleNodePointer();
  +        }
  +    }
  +
  +    /**
  +     * Given a root context, walks a path therefrom and builds a context
  +     * that contains all nodes matching the path.
  +     */
  +    private EvalContext evalSteps(EvalContext context, Path path){
  +        Step steps[] = path.getSteps();
  +        if (steps.length == 0){
  +            return context;
           }
   
           for (int i = 0; i < steps.length; i++){
  @@ -832,14 +949,7 @@
               }
           }
   
  -        if (firstMatch){
  -            Pointer ptr = context.getSingleNodePointer();
  -//            System.err.println("GETTING CTX POINTER: " + context + " " + ptr);
  -            return ptr;
  -        }
  -        else {
  -            return context;
  -        }
  +        return context;
       }
   
       /**
  @@ -950,7 +1060,7 @@
           int old = getCurrentPosition();
           reset();
           int count = 0;
  -        while(next()){
  +        while(nextNode()){
               count++;
           }
   
  @@ -977,7 +1087,7 @@
           if (value instanceof EvalContext){
               EvalContext ctx = (EvalContext)value;
               while(ctx.nextSet()){
  -                while(ctx.next()){
  +                while(ctx.nextNode()){
                       count++;
                   }
               }
  @@ -1012,7 +1122,7 @@
           Object set = eval(function.getArg1(), false);
           if (set instanceof EvalContext){
               EvalContext ctx = (EvalContext)set;
  -            if (ctx.nextSet() && ctx.next()){
  +            if (ctx.nextSet() && ctx.nextNode()){
                   String str = ctx.getCurrentNodePointer().getNamespaceURI();
                   return str == null ? "" : str;
               }
  @@ -1028,7 +1138,7 @@
           Object set = eval(function.getArg1(), false);
           if (set instanceof EvalContext){
               EvalContext ctx = (EvalContext)set;
  -            if (ctx.nextSet() && ctx.next()){
  +            if (ctx.nextSet() && ctx.nextNode()){
                   return ctx.getCurrentNodePointer().getName().getName();
               }
           }
  @@ -1043,7 +1153,7 @@
           Object set = eval(function.getArg1(), false);
           if (set instanceof EvalContext){
               EvalContext ctx = (EvalContext)set;
  -            if (ctx.nextSet() && ctx.next()){
  +            if (ctx.nextSet() && ctx.nextNode()){
                   return ctx.getCurrentNodePointer().getExpandedName().toString();
               }
           }
  @@ -1259,7 +1369,7 @@
               double sum = 0.0;
               EvalContext ctx = (EvalContext)v;
               while (ctx.nextSet()){
  -                while (ctx.next()){
  +                while (ctx.nextNode()){
                       sum += doubleValue(ctx.getCurrentNodePointer());
                   }
               }
  @@ -1291,6 +1401,55 @@
           if (function.getArgumentCount() != count){
               throw new JXPathException("Incorrect number of argument: "
                   + function);
  +        }
  +    }
  +    
  +    public static class PointerIterator implements Iterator {
  +        private Iterator iterator;
  +        private QName qname;
  +        private Locale locale;
  +        
  +        public PointerIterator(Iterator it, QName qname, Locale locale){
  +            this.iterator = it;
  +            this.qname = qname;
  +            this.locale = locale;
  +        }
  +        
  +        public boolean hasNext(){
  +            return iterator.hasNext();
  +        }
  +        
  +        public Object next(){
  +            Object o = iterator.next();            
  +            return NodePointer.newNodePointer(qname, o, locale);
  +        }
  +        
  +        public void remove(){
  +            throw new UnsupportedOperationException();
  +        }
  +    }
  +    
  +    public static class ValueIterator implements Iterator {
  +        private Iterator iterator;
  +        
  +        public ValueIterator(Iterator it){
  +            this.iterator = it;
  +        }
  +        
  +        public boolean hasNext(){
  +            return iterator.hasNext();
  +        }
  +        
  +        public Object next(){
  +            Object o = iterator.next();
  +            if (o instanceof Pointer){
  +                return ((Pointer)o).getValue();
  +            }
  +            return o;
  +        }
  +        
  +        public void remove(){
  +            throw new UnsupportedOperationException();
           }
       }
   }
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>