commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dmi...@apache.org
Subject cvs commit: jakarta-commons/jxpath/xdocs users-guide.xml
Date Tue, 25 Mar 2003 02:41:35 GMT
dmitri      2003/03/24 18:41:35

  Modified:    jxpath   project.xml
               jxpath/src/java/org/apache/commons/jxpath/ri
                        EvalContext.java JXPathContextReferenceImpl.java
               jxpath/src/java/org/apache/commons/jxpath/ri/axes
                        InitialContext.java PredicateContext.java
                        RootContext.java SimplePathInterpreter.java
                        UnionContext.java
               jxpath/src/java/org/apache/commons/jxpath/ri/compiler
                        ExpressionPath.java
               jxpath/src/java/org/apache/commons/jxpath/ri/model
                        NodePointer.java VariablePointer.java
               jxpath/src/java/org/apache/commons/jxpath/ri/model/beans
                        CollectionPointer.java PropertyIterator.java
               jxpath/src/java/org/apache/commons/jxpath/util
                        BasicTypeConverter.java
               jxpath/src/test/org/apache/commons/jxpath/ri/compiler
                        ExtensionFunctionTest.java TestFunctions.java
               jxpath/src/test/org/apache/commons/jxpath/ri/model
                        BeanModelTestCase.java
               jxpath/src/test/org/apache/commons/jxpath/util
                        BasicTypeConverterTest.java
               jxpath/xdocs users-guide.xml
  Added:       jxpath/src/java/org/apache/commons/jxpath BasicNodeSet.java
               jxpath/src/java/org/apache/commons/jxpath/ri/axes
                        NodeSetContext.java
               jxpath/src/java/org/apache/commons/jxpath/ri/model/beans
                        CollectionAttributeNodeIterator.java
                        CollectionChildNodeIterator.java
                        CollectionNodeIterator.java
               jxpath/src/test/org/apache/commons/jxpath/ri StressTest.java
  Log:
  Fixed collection as return value of extension function
  Reduced the amount of cloning
  
  Revision  Changes    Path
  1.13      +10 -10    jakarta-commons/jxpath/project.xml
  
  Index: project.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/project.xml,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- project.xml	11 Mar 2003 00:59:10 -0000	1.12
  +++ project.xml	25 Mar 2003 02:41:33 -0000	1.13
  @@ -93,18 +93,18 @@
   
     <reports>
       <report>maven-junit-report-plugin</report>
  -    <!--
  +    
       <report>maven-jdepend-plugin</report>
       <report>maven-checkstyle-plugin</report>
  -    <report>maven-changelog-plugin</report>
  -    <report>maven-developer-activity-plugin</report>
  -    <report>maven-file-activity-plugin</report>
  -    <report>maven-javadoc-plugin</report>
  +    <!--report>maven-changelog-plugin</report-->
  +    <!--report>maven-developer-activity-plugin</report-->
  +    <!--report>maven-file-activity-plugin</report-->
  +    <!--report>maven-javadoc-plugin</report-->
       <report>maven-jxr-plugin</report>
  -    <report>maven-license-plugin</report>
  -    <report>maven-linkcheck-plugin</report>
  -    <report>maven-tasklist-plugin</report>
  -    <report>maven-clover-plugin</report>
  -    -->
  +    <!--report>maven-license-plugin</report-->
  +    <!--report>maven-linkcheck-plugin</report-->
  +    <!--report>maven-tasklist-plugin</report-->
  +    <!--report>maven-clover-plugin</report-->
  +    
     </reports>
   </project>
  
  
  
  1.1                  jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/BasicNodeSet.java
  
  Index: BasicNodeSet.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/BasicNodeSet.java,v 1.1 2003/03/25 02:41:33 dmitri Exp $
   * $Revision: 1.1 $
   * $Date: 2003/03/25 02:41:33 $
   *
   * ====================================================================
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 2001, Plotnix, Inc,
   * <http://www.plotnix.com/>.
   * For more information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.commons.jxpath;
  
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.List;
  
  /**
   * A simple implementation of NodeSet that behaves as a collection of pointers. 
   * @author Dmitri Plotnikov
   * @version $Revision: 1.1 $ $Date: 2003/03/25 02:41:33 $
   */
  public class BasicNodeSet implements NodeSet {
      private List pointers = new ArrayList();
      private List readOnlyPointers;
      private List nodes;
      private List values;
  
      public void add(Pointer pointer) {
          pointers.add(pointer);
          readOnlyPointers = null;
      }
      
      public void remove(Pointer pointer) {
          pointers.remove(pointer);
          readOnlyPointers = null;
      }
      
      public List getPointers() {
          if (readOnlyPointers == null) {
              readOnlyPointers = Collections.unmodifiableList(pointers);
          }
          return readOnlyPointers;
      }
  
      public List getNodes() {
          if (nodes == null) {
              nodes = new ArrayList();
              for (int i = 0; i < pointers.size(); i++) {
                  Pointer pointer = (Pointer) pointers.get(i);
                  nodes.add(pointer.getValue());
              }
              nodes = Collections.unmodifiableList(nodes);
          }
          return nodes;
      }
  
      public List getValues() {
          if (values == null) {
              values = new ArrayList();
              for (int i = 0; i < pointers.size(); i++) {
                  Pointer pointer = (Pointer) pointers.get(i);
                  values.add(pointer.getValue());
              }
              values = Collections.unmodifiableList(values);
          }
          return values;
      }
      
      public String toString() {
          return pointers.toString();
      }
  }
  
  
  
  1.24      +17 -56    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.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- EvalContext.java	11 Mar 2003 00:59:18 -0000	1.23
  +++ EvalContext.java	25 Mar 2003 02:41:33 -0000	1.24
  @@ -69,6 +69,7 @@
   import java.util.List;
   import java.util.NoSuchElementException;
   
  +import org.apache.commons.jxpath.BasicNodeSet;
   import org.apache.commons.jxpath.ExpressionContext;
   import org.apache.commons.jxpath.JXPathContext;
   import org.apache.commons.jxpath.JXPathException;
  @@ -176,7 +177,7 @@
                   throw new NoSuchElementException();
               }
               hasPerformedIteratorStep = false;
  -            return (NodePointer) getCurrentNodePointer().clone();
  +            return getCurrentNodePointer();
           }
       }
   
  @@ -214,9 +215,9 @@
               while (nextNode()) {
                   NodePointer pointer = getCurrentNodePointer();
                   if (!set.contains(pointer)) {
  -                    Pointer cln = (Pointer) pointer.clone();
  -                    set.add(cln);
  -                    list.add(cln);
  +//                    Pointer cln = (Pointer) pointer.clone();
  +                    set.add(pointer);
  +                    list.add(pointer);
                   }
               }
           }
  @@ -268,8 +269,14 @@
                       + "should not request pointer list while "
                       + "iterating over an EvalContext");
           }
  -        
  -        return new SimpleNodeSet();
  +        BasicNodeSet set = new BasicNodeSet();
  +        while (nextSet()) {
  +            while (nextNode()) {
  +                set.add(getCurrentNodePointer());
  +            }
  +        }
  +
  +        return set;
       }
   
       public String toString() {
  @@ -376,50 +383,4 @@
           this.position = position;
           return true;
       }
  -    
  -    class SimpleNodeSet implements NodeSet {
  -        private List pointers;
  -        private List nodes;
  -        private List values;
  -
  -        public SimpleNodeSet() {
  -            pointers = new ArrayList();
  -            while (nextSet()) {
  -                while (nextNode()) {
  -                    pointers.add(getCurrentNodePointer());
  -                }
  -            }
  -        }
  -
  -        public List getPointers() {
  -            return Collections.unmodifiableList(pointers);
  -        }
  -
  -        public List getNodes() {
  -            if (nodes == null) {
  -                List pointers = getPointers();
  -                nodes = new ArrayList();
  -                for (int i = 0; i < pointers.size(); i++) {
  -                    Pointer pointer = (Pointer) pointers.get(i);
  -                    nodes.add(pointer.getValue());
  -                }
  -                nodes = Collections.unmodifiableList(nodes);
  -            }
  -            return nodes;
  -        }
  -
  -        public List getValues() {
  -            if (values == null) {
  -                List pointers = getPointers();
  -                values = new ArrayList();
  -                for (int i = 0; i < pointers.size(); i++) {
  -                    Pointer pointer = (Pointer) pointers.get(i);
  -                    values.add(pointer.getValue());
  -                }
  -                values = Collections.unmodifiableList(values);
  -            }
  -            return values;
  -        }
  -    }
  -    
   }
  
  
  
  1.31      +21 -17    jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/JXPathContextReferenceImpl.java
  
  Index: JXPathContextReferenceImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/JXPathContextReferenceImpl.java,v
  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- JXPathContextReferenceImpl.java	11 Mar 2003 00:59:18 -0000	1.30
  +++ JXPathContextReferenceImpl.java	25 Mar 2003 02:41:33 -0000	1.31
  @@ -103,7 +103,8 @@
   public class JXPathContextReferenceImpl extends JXPathContext {
       
       /**
  -     * Change this to <code>false</code> to disable soft caching of CompiledExpressions. 
  +     * Change this to <code>false</code> to disable soft caching of 
  +     * CompiledExpressions. 
        */
       public static final boolean USE_SOFT_CACHE = true;
       
  @@ -227,9 +228,8 @@
        * 
        * Override this to return an aternate compiler.
        */
  -    protected Compiler getCompiler(){
  +    protected Compiler getCompiler() {
           return COMPILER;
  -        
       }
       
       protected CompiledExpression compilePath(String xpath) {
  @@ -247,7 +247,9 @@
               if (expr == null) {
                   expr =
                       (Expression) Parser.parseExpression(xpath, getCompiler());
  -                compiled.put(xpath, new SoftReference(expr));
  +                synchronized (compiled) {
  +                    compiled.put(xpath, new SoftReference(expr));
  +                }
                   if (cleanupCount++ >= CLEANUP_THRESHOLD) {
                       cleanupCache();
                   }
  @@ -265,14 +267,16 @@
       }
   
       private static void cleanupCache() {
  -        Iterator it = compiled.entrySet().iterator();
  -        while (it.hasNext()) {
  -            Map.Entry me = (Map.Entry) it.next();
  -            if (((SoftReference) me.getValue()).get() == null) {
  -                it.remove();
  +        synchronized (compiled) {
  +            Iterator it = compiled.entrySet().iterator();
  +            while (it.hasNext()) {
  +                Map.Entry me = (Map.Entry) it.next();
  +                if (((SoftReference) me.getValue()).get() == null) {
  +                    it.remove();
  +                }
               }
  +            cleanupCount = 0;
           }
  -        cleanupCount = 0;
       }
   
       /**
  @@ -539,7 +543,7 @@
           }
       }
   
  -    public JXPathContext getRelativeContext(Pointer pointer){
  +    public JXPathContext getRelativeContext(Pointer pointer) {
           Object contextBean = pointer.getNode();
           if (contextBean == null) {
               throw new JXPathException(
  @@ -550,11 +554,11 @@
       }
       
       public synchronized Pointer getContextPointer() {
  -        return (Pointer) contextPointer.clone();
  +        return contextPointer;
       }
   
       private synchronized NodePointer getAbsoluteRootPointer() {
  -        return (NodePointer) rootPointer.clone();
  +        return (NodePointer) rootPointer;
       }
   
       private EvalContext getEvalContext() {
  
  
  
  1.11      +6 -5      jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/axes/InitialContext.java
  
  Index: InitialContext.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/axes/InitialContext.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- InitialContext.java	11 Mar 2003 00:59:20 -0000	1.10
  +++ InitialContext.java	25 Mar 2003 02:41:34 -0000	1.11
  @@ -81,7 +81,8 @@
   
       public InitialContext(EvalContext parentContext) {
           super(parentContext);
  -        nodePointer = parentContext.getCurrentNodePointer();
  +        nodePointer =
  +            (NodePointer) parentContext.getCurrentNodePointer().clone();
           if (nodePointer != null) {
               collection =
                   (nodePointer.getIndex() == NodePointer.WHOLE_COLLECTION);
  
  
  
  1.19      +7 -5      jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/axes/PredicateContext.java
  
  Index: PredicateContext.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/axes/PredicateContext.java,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- PredicateContext.java	11 Mar 2003 00:59:20 -0000	1.18
  +++ PredicateContext.java	25 Mar 2003 02:41:34 -0000	1.19
  @@ -154,7 +154,9 @@
               return false;
           }
           dynamicPropertyPointer =
  -            ((PropertyOwnerPointer) parent).getPropertyPointer();
  +            (PropertyPointer) ((PropertyOwnerPointer) parent)
  +                .getPropertyPointer()
  +                .clone();
           return true;
       }
   
  
  
  
  1.12      +11 -4     jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/axes/RootContext.java
  
  Index: RootContext.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/axes/RootContext.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- RootContext.java	11 Mar 2003 00:59:20 -0000	1.11
  +++ RootContext.java	25 Mar 2003 02:41:34 -0000	1.12
  @@ -63,6 +63,7 @@
   
   import org.apache.commons.jxpath.Function;
   import org.apache.commons.jxpath.JXPathContext;
  +import org.apache.commons.jxpath.NodeSet;
   import org.apache.commons.jxpath.ri.EvalContext;
   import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl;
   import org.apache.commons.jxpath.ri.QName;
  @@ -124,6 +125,12 @@
       }
   
       public EvalContext getConstantContext(Object constant) {
  +        if (constant instanceof NodeSet) {
  +            return new NodeSetContext(
  +                new RootContext(jxpathContext, null),
  +                (NodeSet) constant);
  +        }
  +                
           NodePointer pointer;
           if (constant instanceof NodePointer) {
               pointer = (NodePointer) constant;
  
  
  
  1.11      +3 -3      jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/axes/SimplePathInterpreter.java
  
  Index: SimplePathInterpreter.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/axes/SimplePathInterpreter.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- SimplePathInterpreter.java	11 Mar 2003 00:59:20 -0000	1.10
  +++ SimplePathInterpreter.java	25 Mar 2003 02:41:34 -0000	1.11
  @@ -250,6 +250,7 @@
               // execute remaining steps for each node,
               // looking for the best quality match
               int bestQuality = 0;
  +            childPointer = (NodePointer) childPointer.clone();
               NodePointer bestMatch = null;
               int count = childPointer.getLength();
               for (int i = 0; i < count; i++) {
  @@ -525,13 +526,11 @@
               //  if so - proceed to the next predicate
               NodePointer bestMatch = null;
               int bestQuality = 0;
  +            child = (NodePointer) child.clone();
               int count = child.getLength();
               for (int i = 0; i < count; i++) {
                   child.setIndex(i);
                   NodePointer valuePointer = valuePointer(child);
  -                if (valuePointer == child) {
  -                    valuePointer = (NodePointer) child.clone();
  -                }
                   NodePointer pointer;
                   if ((valuePointer instanceof PropertyOwnerPointer)
                       || valuePointer.isCollection()) {
  @@ -672,6 +671,7 @@
           int index = indexFromPredicate(context, predicate);
           NodePointer pointer = parent;
           if (isCollectionElement(pointer, index)) {
  +            pointer = (NodePointer) pointer.clone();
               pointer.setIndex(index);
               return doPredicate(
                   context,
  
  
  
  1.10      +22 -49    jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/axes/UnionContext.java
  
  Index: UnionContext.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/axes/UnionContext.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- UnionContext.java	11 Mar 2003 00:59:20 -0000	1.9
  +++ UnionContext.java	25 Mar 2003 02:41:34 -0000	1.10
  @@ -61,10 +61,9 @@
    */
   package org.apache.commons.jxpath.ri.axes;
   
  -import java.util.ArrayList;
   import java.util.HashSet;
  -import java.util.List;
   
  +import org.apache.commons.jxpath.BasicNodeSet;
   import org.apache.commons.jxpath.ri.EvalContext;
   import org.apache.commons.jxpath.ri.model.NodePointer;
   
  @@ -75,13 +74,13 @@
    * @author Dmitri Plotnikov
    * @version $Revision$ $Date$
    */
  -public class UnionContext extends EvalContext {
  +public class UnionContext extends NodeSetContext {
       private boolean startedSet = false;
       private EvalContext contexts[];
  -    private List list;
  +    private boolean prepared = false;
   
       public UnionContext(EvalContext parentContext, EvalContext contexts[]) {
  -        super(parentContext);
  +        super(parentContext, new BasicNodeSet());
           this.contexts = contexts;
       }
   
  @@ -92,50 +91,24 @@
           return super.getDocumentOrder();
       }
   
  -    public NodePointer getCurrentNodePointer() {
  -        if (position == 0) {
  -            if (!setPosition(1)) {
  -                return null;
  -            }
  -        }
  -        return (NodePointer) list.get(position - 1);
  -    }
  -
       public boolean setPosition(int position) {
  -        super.setPosition(position);
  -        if (list == null) {
  -            prepareList();
  -        }
  -        return position >= 1 && position <= list.size();
  -    }
  -
  -    public boolean nextSet() {
  -        if (startedSet) {
  -            return false;
  -        }
  -        startedSet = true;
  -        return true;
  -    }
  -
  -    public boolean nextNode() {
  -        return setPosition(position + 1);
  -    }
  -
  -    private void prepareList() {
  -        list = new ArrayList();
  -        HashSet set = new HashSet();
  -        for (int i = 0; i < contexts.length; i++) {
  -            EvalContext ctx = (EvalContext) contexts[i];
  -            while (ctx.nextSet()) {
  -                while (ctx.nextNode()) {
  -                    NodePointer ptr = ctx.getCurrentNodePointer();
  -                    if (!set.contains(ptr)) {
  -                        ptr = (NodePointer) ptr.clone();
  -                        list.add(ptr);
  -                        set.add(ptr);
  +        if (!prepared) {
  +            prepared = true;
  +            BasicNodeSet nodeSet = (BasicNodeSet) getNodeSet();
  +            HashSet set = new HashSet();
  +            for (int i = 0; i < contexts.length; i++) {
  +                EvalContext ctx = (EvalContext) contexts[i];
  +                while (ctx.nextSet()) {
  +                    while (ctx.nextNode()) {
  +                        NodePointer ptr = ctx.getCurrentNodePointer();
  +                        if (!set.contains(ptr)) {
  +                            nodeSet.add(ptr);
  +                            set.add(ptr);
  +                        }
                       }
                   }
               }
           }
  +        return super.setPosition(position);
       }
   }
  
  
  
  1.1                  jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/axes/NodeSetContext.java
  
  Index: NodeSetContext.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/axes/NodeSetContext.java,v 1.1 2003/03/25 02:41:34 dmitri Exp $
   * $Revision: 1.1 $
   * $Date: 2003/03/25 02:41:34 $
   *
   * ====================================================================
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 2001, Plotnix, Inc,
   * <http://www.plotnix.com/>.
   * For more information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.commons.jxpath.ri.axes;
  
  import org.apache.commons.jxpath.NodeSet;
  import org.apache.commons.jxpath.ri.EvalContext;
  import org.apache.commons.jxpath.ri.model.NodePointer;
  
  /**
   * A simple context that is based on a NodeSet.
   *
   * @author Dmitri Plotnikov
   * @version $Revision: 1.1 $ $Date: 2003/03/25 02:41:34 $
   */
  public class NodeSetContext extends EvalContext {
      private boolean startedSet = false;
      private NodeSet nodeSet;
  
      public NodeSetContext(EvalContext parentContext, NodeSet nodeSet) {
          super(parentContext);
          this.nodeSet = nodeSet;
      }
      
      public NodeSet getNodeSet() {
          return nodeSet;
      }
  
      public NodePointer getCurrentNodePointer() {
          if (position == 0) {
              if (!setPosition(1)) {
                  return null;
              }
          }
          return (NodePointer) nodeSet.getPointers().get(position - 1);
      }
  
      public boolean setPosition(int position) {
          super.setPosition(position);
          return position >= 1 && position <= nodeSet.getPointers().size();
      }
  
      public boolean nextSet() {
          if (startedSet) {
              return false;
          }
          startedSet = true;
          return true;
      }
  
      public boolean nextNode() {
          return setPosition(position + 1);
      }
  }
  
  
  1.9       +6 -5      jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/compiler/ExpressionPath.java
  
  Index: ExpressionPath.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/compiler/ExpressionPath.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- ExpressionPath.java	11 Mar 2003 00:59:22 -0000	1.8
  +++ ExpressionPath.java	25 Mar 2003 02:41:34 -0000	1.9
  @@ -63,6 +63,7 @@
   
   import org.apache.commons.jxpath.ri.EvalContext;
   import org.apache.commons.jxpath.ri.axes.InitialContext;
  +import org.apache.commons.jxpath.ri.axes.NodeSetContext;
   import org.apache.commons.jxpath.ri.axes.PredicateContext;
   import org.apache.commons.jxpath.ri.axes.SimplePathInterpreter;
   import org.apache.commons.jxpath.ri.axes.UnionContext;
  @@ -202,7 +203,7 @@
   
           if (firstMatch
               && isSimpleExpressionPath()
  -            && !(context instanceof UnionContext)) {
  +            && !(context instanceof NodeSetContext)) {
               EvalContext ctx = context;
               NodePointer ptr = (NodePointer) ctx.getSingleNodePointer();
               if (ptr != null
  
  
  
  1.18      +10 -6     jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/model/NodePointer.java
  
  Index: NodePointer.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/model/NodePointer.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- NodePointer.java	11 Mar 2003 00:59:23 -0000	1.17
  +++ NodePointer.java	25 Mar 2003 02:41:34 -0000	1.18
  @@ -325,9 +325,9 @@
           return getValuePointer().getImmediateNode();
       }
       
  -    public Object getRootNode(){
  +    public Object getRootNode() {
           if (rootNode == null) {
  -            if (parent != null){
  +            if (parent != null) {
                   rootNode = parent.getRootNode();
               }
               else {
  @@ -369,6 +369,10 @@
               }
               QName testName = ((NodeNameTest) test).getNodeName();
               QName nodeName = getName();
  +            if (nodeName == null) {
  +                return false;
  +            }
  +            
               String testPrefix = testName.getPrefix();
               String nodePrefix = nodeName.getPrefix();
               if (!equalStrings(testPrefix, nodePrefix)) {
  
  
  
  1.15      +7 -5      jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/model/VariablePointer.java
  
  Index: VariablePointer.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/model/VariablePointer.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- VariablePointer.java	11 Mar 2003 00:59:23 -0000	1.14
  +++ VariablePointer.java	25 Mar 2003 02:41:34 -0000	1.15
  @@ -229,7 +229,9 @@
                   throw new JXPathException(
                       "Factory could not create object path: " + asPath());
               }
  -            setIndex(index);
  +            NodePointer cln = (NodePointer) clone();
  +            cln.setIndex(index);
  +            return cln;
           }
           return this;
       }
  
  
  
  1.15      +13 -7     jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/model/beans/CollectionPointer.java
  
  Index: CollectionPointer.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/model/beans/CollectionPointer.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- CollectionPointer.java	11 Mar 2003 00:59:25 -0000	1.14
  +++ CollectionPointer.java	25 Mar 2003 02:41:34 -0000	1.15
  @@ -208,14 +208,20 @@
                   boolean reverse, NodePointer startWith)
       {
           if (index == WHOLE_COLLECTION) {
  -            return null;
  +            return new CollectionChildNodeIterator(
  +                this,
  +                test,
  +                reverse,
  +                startWith);
  +        }
  +        else {
  +            return getValuePointer().childIterator(test, reverse, startWith);
           }
  -        return getValuePointer().childIterator(test, reverse, startWith);
       }
   
       public NodeIterator attributeIterator(QName name) {
           if (index == WHOLE_COLLECTION) {
  -            return null;
  +            return new CollectionAttributeNodeIterator(this, name);
           }
           return getValuePointer().attributeIterator(name);
       }
  
  
  
  1.10      +7 -7      jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/model/beans/PropertyIterator.java
  
  Index: PropertyIterator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/model/beans/PropertyIterator.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- PropertyIterator.java	11 Mar 2003 00:59:25 -0000	1.9
  +++ PropertyIterator.java	25 Mar 2003 02:41:34 -0000	1.10
  @@ -91,7 +91,8 @@
           boolean reverse,
           NodePointer startWith) 
       {
  -        propertyNodePointer = pointer.getPropertyPointer();
  +        propertyNodePointer =
  +            (PropertyPointer) pointer.getPropertyPointer().clone();
           this.name = name;
           this.reverse = reverse;
           this.includeStart = true;
  @@ -149,8 +150,7 @@
               }
           }
           try {
  -            NodePointer clone = (NodePointer) propertyNodePointer.clone();
  -            return clone.getValuePointer();
  +            return propertyNodePointer.getValuePointer();
           }
           catch (Throwable ex) {
               // @todo: should this exception be reported in any way?
  
  
  
  1.1                  jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/model/beans/CollectionAttributeNodeIterator.java
  
  Index: CollectionAttributeNodeIterator.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/model/beans/CollectionAttributeNodeIterator.java,v 1.1 2003/03/25 02:41:34 dmitri Exp $
   * $Revision: 1.1 $
   * $Date: 2003/03/25 02:41:34 $
   *
   * ====================================================================
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 2001, Plotnix, Inc,
   * <http://www.plotnix.com/>.
   * For more information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */package org.apache.commons.jxpath.ri.model.beans;
  
  import org.apache.commons.jxpath.ri.QName;
  import org.apache.commons.jxpath.ri.model.NodeIterator;
  import org.apache.commons.jxpath.ri.model.NodePointer;
  
  /**
   * Combines attribute node iterators of all elements of a collection into one
   * aggregate attribute node iterator.
   *
   * @author Dmitri Plotnikov
   * @version $Revision: 1.1 $ $Date: 2003/03/25 02:41:34 $
   */
  public class CollectionAttributeNodeIterator extends CollectionNodeIterator {
  
      private QName name;
  
      public CollectionAttributeNodeIterator(
          CollectionPointer pointer,
          QName name) 
      {
          super(pointer, false, null);
          this.name = name;
      }
  
      protected NodeIterator getElementNodeIterator(NodePointer elementPointer) {
          return elementPointer.attributeIterator(name);
      }
  }
  
  
  
  1.1                  jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/model/beans/CollectionChildNodeIterator.java
  
  Index: CollectionChildNodeIterator.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/model/beans/CollectionChildNodeIterator.java,v 1.1 2003/03/25 02:41:34 dmitri Exp $
   * $Revision: 1.1 $
   * $Date: 2003/03/25 02:41:34 $
   *
   * ====================================================================
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 2001, Plotnix, Inc,
   * <http://www.plotnix.com/>.
   * For more information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */package org.apache.commons.jxpath.ri.model.beans;
  
  import org.apache.commons.jxpath.ri.compiler.NodeTest;
  import org.apache.commons.jxpath.ri.model.NodeIterator;
  import org.apache.commons.jxpath.ri.model.NodePointer;
  
  /**
   * Combines child node iterators of all elements of a collection into one
   * aggregate child node iterator.
   *
   * @author Dmitri Plotnikov
   * @version $Revision: 1.1 $ $Date: 2003/03/25 02:41:34 $
   */
  public class CollectionChildNodeIterator extends CollectionNodeIterator {
  
      private NodeTest test;
  
      public CollectionChildNodeIterator(
          CollectionPointer pointer,
          NodeTest test,
          boolean reverse,
          NodePointer startWith) 
      {
          super(pointer, reverse, startWith);
          this.test = test;
      }
  
      protected NodeIterator getElementNodeIterator(NodePointer elementPointer) {
          return elementPointer.childIterator(test, false, null);
      }
  }
  
  
  
  1.1                  jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/model/beans/CollectionNodeIterator.java
  
  Index: CollectionNodeIterator.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/model/beans/CollectionNodeIterator.java,v 1.1 2003/03/25 02:41:34 dmitri Exp $
   * $Revision: 1.1 $
   * $Date: 2003/03/25 02:41:34 $
   *
   * ====================================================================
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 2001, Plotnix, Inc,
   * <http://www.plotnix.com/>.
   * For more information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */package org.apache.commons.jxpath.ri.model.beans;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import org.apache.commons.jxpath.JXPathException;
  import org.apache.commons.jxpath.ri.model.NodeIterator;
  import org.apache.commons.jxpath.ri.model.NodePointer;
  
  /**
   * Combines node iterators of all elements of a collection into one
   * aggregate node iterator.
   *
   * @author Dmitri Plotnikov
   * @version $Revision: 1.1 $ $Date: 2003/03/25 02:41:34 $
   */
  public abstract class CollectionNodeIterator implements NodeIterator {
      private CollectionPointer pointer;
      private boolean reverse;
      private NodePointer startWith; 
      private int position;
      private List collection;
  
      protected CollectionNodeIterator(
          CollectionPointer pointer,
          boolean reverse,
          NodePointer startWith) 
      {
          this.pointer = pointer;
          this.reverse = reverse;
          this.startWith = startWith;
      }
      
      /**
       * Implemened by subclasses to produce child/attribute node iterators.
       */
      protected abstract NodeIterator 
              getElementNodeIterator(NodePointer elementPointer);
  
      public int getPosition() {
          return position;
      }
  
      public boolean setPosition(int position) {
          if (collection == null) {
              prepare();
          }
          
          if (position < 1 || position > collection.size()) {
              return false;
          }
          this.position = position;
          return true;
      }
  
      public NodePointer getNodePointer() {
          if (position == 0) {
              return null;
          }
          return (NodePointer) collection.get(position - 1);
      }
      
      private void prepare() {
          collection = new ArrayList();
          NodePointer ptr = (NodePointer) pointer.clone();
          int length = ptr.getLength();
          for (int i = 0; i < length; i++) {
              ptr.setIndex(i);
              NodePointer elementPointer = ptr.getValuePointer();
              NodeIterator iter = getElementNodeIterator(elementPointer);
  
              for (int j = 1; iter.setPosition(j); j++) {
                  NodePointer childPointer = iter.getNodePointer();
                  if (reverse) {
                      collection.add(0, childPointer);
                  }
                  else {
                      collection.add(childPointer);
                  }
              }
          }
          if (startWith != null) {
              int index = collection.indexOf(startWith);
              if (index == -1) {
                  throw new JXPathException(
                      "Invalid starting pointer for iterator: " + startWith);
              }
              while (collection.size() > index) {
                  if (!reverse) {
                      collection.remove(collection.size() - 1);
                  }
                  else {
                      collection.remove(0);
                  }
              }
          }
      }
  }
  
  
  
  1.8       +78 -66    jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/util/BasicTypeConverter.java
  
  Index: BasicTypeConverter.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/util/BasicTypeConverter.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- BasicTypeConverter.java	11 Mar 2003 00:59:34 -0000	1.7
  +++ BasicTypeConverter.java	25 Mar 2003 02:41:34 -0000	1.8
  @@ -157,9 +157,14 @@
               else if (Collection.class.isAssignableFrom(toType)) {
                   return canCreateCollection(toType);
               }
  -            else if (Array.getLength(object) == 1) {
  -                Object value = Array.get(object, 0);
  -                return canConvert(value, toType);
  +            else {
  +                if (Array.getLength(object) > 0) {
  +                    Object value = Array.get(object, 0);
  +                    return canConvert(value, toType);
  +                }
  +                else {
  +                    return canConvert("", toType);
  +                }
               }
           }
           else if (object instanceof Collection) {
  @@ -178,16 +183,21 @@
               else if (Collection.class.isAssignableFrom(toType)) {
                   return canCreateCollection(toType);
               }
  -            else if (((Collection) object).size() == 1) {
  -                Object value;
  -                if (object instanceof List) {
  -                    value = ((List) object).get(0);
  +            else {
  +                if (((Collection) object).size() > 0) {
  +                    Object value;
  +                    if (object instanceof List) {
  +                        value = ((List) object).get(0);
  +                    }
  +                    else {
  +                        Iterator it = ((Collection) object).iterator();
  +                        value = it.next();
  +                    }
  +                    return canConvert(value, toType);
                   }
                   else {
  -                    Iterator it = ((Collection) object).iterator();
  -                    value = it.next();
  +                    return canConvert("", toType);
                   }
  -                return canConvert(value, toType);
               }
           }
           else if (object instanceof NodeSet) {
  @@ -198,6 +208,7 @@
           }
           return false;
       }
  +
       /**
        * Converts the supplied object to the specified
        * type. Throws a runtime exception if the conversion is
  @@ -220,39 +231,7 @@
               return object;
           }
   
  -        if (toType == String.class) {
  -            return object.toString();
  -        }
  -
  -        if (object instanceof Boolean) {
  -            if (toType == boolean.class) {
  -                return object;
  -            }
  -            boolean value = ((Boolean) object).booleanValue();
  -            return allocateNumber(toType, value ? 1 : 0);
  -        }
  -        else if (object instanceof Number) {
  -            double value = ((Number) object).doubleValue();
  -            if (toType == boolean.class || toType == Boolean.class) {
  -                return value == 0.0 ? Boolean.FALSE : Boolean.TRUE;
  -            }
  -            if (toType.isPrimitive()
  -                || Number.class.isAssignableFrom(toType)) {
  -                return allocateNumber(toType, value);
  -            }
  -        }
  -        else if (object instanceof Character) {
  -            if (toType == char.class) {
  -                return object;
  -            }
  -        }
  -        else if (object instanceof String) {
  -            Object value = convertStringToPrimitive(object, toType);
  -            if (value != null) {
  -                return value;
  -            }
  -        }
  -        else if (fromType.isArray()) {
  +        if (fromType.isArray()) {
               int length = Array.getLength(object);
               if (toType.isArray()) {
                   Class cType = toType.getComponentType();
  @@ -271,9 +250,14 @@
                   }
                   return unmodifiableCollection(collection);
               }
  -            else if (length == 1) {
  -                Object value = Array.get(object, 0);
  -                return convert(value, toType);
  +            else {
  +                if (length > 0) { 
  +                    Object value = Array.get(object, 0);
  +                    return convert(value, toType);
  +                }
  +                else {
  +                    return convert("", toType);
  +                }
               }
           }
           else if (object instanceof Collection) {
  @@ -293,24 +277,21 @@
                   collection.addAll((Collection) object);
                   return unmodifiableCollection(collection);
               }
  -            else if (length == 1) {
  -                Object value;
  -                if (object instanceof List) {
  -                    value = ((List) object).get(0);
  +            else {
  +                if (length > 0) {
  +                    Object value;
  +                    if (object instanceof List) {
  +                        value = ((List) object).get(0);
  +                    }
  +                    else {
  +                        Iterator it = ((Collection) object).iterator();
  +                        value = it.next();
  +                    }
  +                    return convert(value, toType);
                   }
                   else {
  -                    Iterator it = ((Collection) object).iterator();
  -                    value = it.next();
  +                    return convert("", toType);
                   }
  -                return convert(value, toType);
  -            }
  -            else {
  -                throw new RuntimeException(
  -                    "Cannot convert collection to "
  -                        + toType
  -                        + ", it contains "
  -                        + length
  -                        + " elements");
               }
           }
           else if (object instanceof NodeSet) {
  @@ -319,6 +300,37 @@
           else if (object instanceof Pointer) {
               return convert(((Pointer) object).getValue(), toType);
           }
  +        else if (toType == String.class) {
  +            return object.toString();
  +        }
  +        else if (object instanceof Boolean) {
  +            if (toType == boolean.class) {
  +                return object;
  +            }
  +            boolean value = ((Boolean) object).booleanValue();
  +            return allocateNumber(toType, value ? 1 : 0);
  +        }
  +        else if (object instanceof Number) {
  +            double value = ((Number) object).doubleValue();
  +            if (toType == boolean.class || toType == Boolean.class) {
  +                return value == 0.0 ? Boolean.FALSE : Boolean.TRUE;
  +            }
  +            if (toType.isPrimitive()
  +                || Number.class.isAssignableFrom(toType)) {
  +                return allocateNumber(toType, value);
  +            }
  +        }
  +        else if (object instanceof Character) {
  +            if (toType == char.class) {
  +                return object;
  +            }
  +        }
  +        else if (object instanceof String) {
  +            Object value = convertStringToPrimitive(object, toType);
  +            if (value != null) {
  +                return value;
  +            }
  +        }
           
           throw new RuntimeException(
               "Cannot convert " + object.getClass() + " to " + toType);
  @@ -503,7 +515,7 @@
               throw new UnsupportedOperationException();
           }
           
  -        public Object clone(){
  +        public Object clone() {
               return this;
           }
           
  
  
  
  1.1                  jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/ri/StressTest.java
  
  Index: StressTest.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/ri/StressTest.java,v 1.1 2003/03/25 02:41:34 dmitri Exp $
   * $Revision: 1.1 $
   * $Date: 2003/03/25 02:41:34 $
   *
   * ====================================================================
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 2001, Plotnix, Inc,
   * <http://www.plotnix.com/>.
   * For more information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.commons.jxpath.ri;
  
  import junit.framework.TestCase;
  
  import org.apache.commons.jxpath.JXPathContext;
  
  /**
   * Test thread safety.
   *
   * @author Dmitri Plotnikov
   * @version $Revision: 1.1 $ $Date: 2003/03/25 02:41:34 $
   */
  
  public class StressTest extends TestCase {
      
      private static final int THREAD_COUNT = 50;
      private static final int THREAD_DURATION = 1000;
      private static JXPathContext context;
      private static int count;
      private static Throwable exception;
          
      /**
       * Construct a new instance of this test case.
       *
       * @param name Name of the test case
       */
      public StressTest(String name) {
          super(name);
      }
  
      public void testThreads() throws Throwable {
          context = JXPathContext.newContext(null, new Double(100));
          Thread[] threadArray = new Thread[THREAD_COUNT];
          for (int i = 0; i < THREAD_COUNT; i++) {
              threadArray[i] = new Thread(new StressRunnable());
          }
          
          for (int i = 0; i < threadArray.length; i++) {
              threadArray[i].start();
          }
  
          for (int i = 0; i < threadArray.length; i++) {
              try {
                  threadArray[i].join();
              }
              catch (InterruptedException e) {
                  assertTrue("Interrupted", false);
              }
          }
  
          if (exception != null) {
              throw exception;
          }
          assertEquals("Test count", THREAD_COUNT * THREAD_DURATION, count);
      }    
  
      private final class StressRunnable implements Runnable {
          public void run() {
              for (int j = 0; j < THREAD_DURATION && exception == null; j++) {
                  try { 
                      double random = 1 + Math.random();
                      double sum =
                          ((Double) context.getValue("/ + " + random))
                              .doubleValue();
                      assertEquals(100 + random, sum, 0.0001);
                      synchronized (context) {
                          count++;
                      }
                  }                    
                  catch (Throwable t) {
                      exception = t;
                  }
              }
          }
      }
  }
  
  
  1.8       +53 -5     jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/ri/compiler/ExtensionFunctionTest.java
  
  Index: ExtensionFunctionTest.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/ri/compiler/ExtensionFunctionTest.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- ExtensionFunctionTest.java	11 Mar 2003 00:59:36 -0000	1.7
  +++ ExtensionFunctionTest.java	25 Mar 2003 02:41:34 -0000	1.8
  @@ -290,7 +290,9 @@
           // Two ClassFunctions are sharing the same prefix.
           // This is TestFunctions2
           assertXPathValue(context, "string(test:increment(8))", "9");
  -
  +        
  +        // See that a NodeSet gets properly converted to a string
  +        assertXPathValue(context, "test:string(/beans/name)", "Name 1");
       }
   
       public void testExpressionContext() {
  @@ -330,6 +332,52 @@
               context,
               "/beans[contains(test:path(), '[2]')]/name",
               "Name 2");
  +    }
  +    
  +    public void testCollectionReturn() {
  +        assertXPathValueIterator(
  +            context,
  +            "test:collection()/name",
  +            list("foo", "bar"));
  +
  +        assertXPathPointerIterator(
  +            context,
  +            "test:collection()/name",
  +            list("/.[1]/name", "/.[2]/name"));
  +            
  +        assertXPathValue(
  +            context,
  +            "test:collection()/name",
  +            "foo");        
  +
  +        assertXPathValue(
  +            context,
  +            "test:collection()/@name",
  +            "foo");        
  +    }
  +
  +    public void testNodeSetReturn() {
  +        assertXPathValueIterator(
  +            context,
  +            "test:nodeSet()/name",
  +            list("Name 1", "Name 2"));
  +
  +        assertXPathPointerIterator(
  +            context,
  +            "test:nodeSet()/name",
  +            list("/beans[1]/name", "/beans[2]/name"));
  +            
  +        assertXPathValueAndPointer(
  +            context,
  +            "test:nodeSet()/name",
  +            "Name 1",
  +            "/beans[1]/name");        
  +
  +        assertXPathValueAndPointer(
  +            context,
  +            "test:nodeSet()/@name",
  +            "Name 1",
  +            "/beans[1]/@name");
       }
   
       private static class Context implements ExpressionContext {
  
  
  
  1.6       +28 -4     jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/ri/compiler/TestFunctions.java
  
  Index: TestFunctions.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/ri/compiler/TestFunctions.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- TestFunctions.java	11 Mar 2003 00:59:36 -0000	1.5
  +++ TestFunctions.java	25 Mar 2003 02:41:34 -0000	1.6
  @@ -61,11 +61,15 @@
    */
   package org.apache.commons.jxpath.ri.compiler;
   
  +import java.util.ArrayList;
   import java.util.Collection;
   import java.util.Iterator;
   import java.util.Map;
   
  +import org.apache.commons.jxpath.BasicNodeSet;
   import org.apache.commons.jxpath.ExpressionContext;
  +import org.apache.commons.jxpath.JXPathContext;
  +import org.apache.commons.jxpath.NestedTestBean;
   import org.apache.commons.jxpath.Pointer;
   import org.apache.commons.jxpath.NodeSet;
   
  @@ -160,5 +164,25 @@
       
       public static int countPointers(NodeSet nodeSet) {
           return nodeSet.getPointers().size();
  +    }
  +    
  +    public static String string(String string) {
  +        return string;
  +    }
  +    
  +    public static Collection collection() {
  +        ArrayList list = new ArrayList();
  +        list.add(new NestedTestBean("foo"));
  +        list.add(new NestedTestBean("bar"));
  +        return list;
  +    }
  +    
  +    public static NodeSet nodeSet(ExpressionContext context) {
  +        JXPathContext jxpathCtx = context.getJXPathContext();
  +        BasicNodeSet set = new BasicNodeSet();
  +        set.add(jxpathCtx.getPointer("/beans[1]"));
  +        set.add(jxpathCtx.getPointer("/beans[2]"));
  +        
  +        return set;
       }
   }
  
  
  
  1.13      +5 -5      jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/ri/model/BeanModelTestCase.java
  
  Index: BeanModelTestCase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/ri/model/BeanModelTestCase.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- BeanModelTestCase.java	11 Mar 2003 00:59:37 -0000	1.12
  +++ BeanModelTestCase.java	25 Mar 2003 02:41:35 -0000	1.13
  @@ -837,7 +837,7 @@
                   new Integer(1),
                   "/nestedBean/beans[last() + 1]");
           }
  -        catch (Exception e){
  +        catch (Exception e) {
               ex = true;
           }
           assertTrue("Exception thrown on invalid path for creation", ex);
  
  
  
  1.4       +73 -4     jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/util/BasicTypeConverterTest.java
  
  Index: BasicTypeConverterTest.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/test/org/apache/commons/jxpath/util/BasicTypeConverterTest.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- BasicTypeConverterTest.java	11 Mar 2003 00:59:40 -0000	1.3
  +++ BasicTypeConverterTest.java	25 Mar 2003 02:41:35 -0000	1.4
  @@ -65,11 +65,15 @@
   import java.lang.reflect.Array;
   import java.util.ArrayList;
   import java.util.Arrays;
  +import java.util.Collections;
   import java.util.Date;
   import java.util.List;
   
   import junit.framework.TestCase;
   
  +import org.apache.commons.jxpath.NodeSet;
  +import org.apache.commons.jxpath.Pointer;
  +
   /**
    * Tests BasicTypeConverter
    * 
  @@ -144,4 +148,69 @@
               expected,
               result);
       }
  +    
  +    public void testSingletonCollectionToString() {
  +        assertConversion(Collections.singleton("Earth"), String.class, "Earth");
  +    }
  +
  +    public void testSingletonArrayToString() {
  +        assertConversion(new String[] { "Earth" }, String.class, "Earth");
  +    }
  +
  +    public void testPointerToString() {
  +        assertConversion(new Pointer() {
  +            public Object getValue() {
  +                return "value";
  +            }
  +            public Object getNode() {
  +                return null;
  +            }
  +            public void setValue(Object value) {
  +            }
  +            public Object getRootNode() {
  +                return null;
  +            }
  +            public String asPath() {
  +                return null;
  +            }
  +            public Object clone() {
  +                return null;
  +            }
  +            public int compareTo(Object o) {
  +                return 0;
  +            }
  +        }, String.class, "value");
  +    }
  +
  +    public void testNodeSetToString() {
  +        assertConversion(new NodeSet() {
  +            public List getNodes() {
  +                return null;
  +            }
  +            public List getPointers() {
  +                return null;
  +            }
  +            public List getValues() {
  +                List list = new ArrayList();
  +                list.add("hello");
  +                list.add("goodbye");
  +                return Collections.singletonList(list);
  +            }
  +        }, String.class, "hello");
  +    }
  +
  +    // succeeds in current version
  +    public void testNodeSetToInteger() {
  +        assertConversion(new NodeSet() {
  +            public List getNodes() {
  +                return null;
  +            }
  +            public List getPointers() {
  +                return null;
  +            }
  +            public List getValues() {
  +                return Collections.singletonList("9");
  +            }
  +        }, Integer.class, new Integer(9));
  +    }    
   }
  
  
  
  1.12      +12 -0     jakarta-commons/jxpath/xdocs/users-guide.xml
  
  Index: users-guide.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/xdocs/users-guide.xml,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- users-guide.xml	19 Feb 2003 00:59:51 -0000	1.11
  +++ users-guide.xml	25 Mar 2003 02:41:35 -0000	1.12
  @@ -116,6 +116,8 @@
               </li>
               <li><a href="#Collections as Arguments">Collections as Arguments</a>
               </li>
  +            <li><a href="#Collection as the Return Value">Collection as the Return Value</a>
  +            </li>
             </ul>
           </li>
           <li><a href="#Type Conversions">Type Conversions</a>
  @@ -1183,6 +1185,7 @@
         </subsection>
         
         <subsection name="Collections as Arguments">
  +        <p>
            There are two ways a collection can be passed to an extension function:
            as a <a href="apidocs/org/apache/commons/jxpath/NodeSet.html"><code>NodeSet</code></a>
            or as a Collection proper.  If the argument type is declared
  @@ -1190,6 +1193,7 @@
            out of the node set and pass those to the function as a regular collection.
            Note that a collection is always passed to an extension function by value -
            it cannot be modified.
  +        </p>
   
   <!--============================ + SOURCE + ============================-->
   <source>
  @@ -1234,6 +1238,14 @@
   </source>
   <!--============================ - SOURCE - ============================-->
   
  +      </subsection>
  +      <subsection name="Collection as the Return Value">
  +        <p>
  +         A custom function can return a collection of arbitrary objects or a NodeSet.
  +         The simple implementation of NodeSet, 
  +         <a href="apidocs/org/apache/commons/jxpath/BasicNodeSet.html#setLocale">BasicNodeSet</a>,
  +         may come handy.
  +        </p>
         </subsection>
       </section>
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message