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/src/java/org/apache/commons/jxpath/util BasicTypeConverter.java
Date Wed, 19 Feb 2003 00:59:53 GMT
dmitri      2003/02/18 16:59:53

  Modified:    jxpath/xdocs users-guide.xml
               jxpath/src/java/org/apache/commons/jxpath/ri/axes
                        RootContext.java
               jxpath/src/java/org/apache/commons/jxpath Pointer.java
                        JXPathContext.java
               jxpath/src/java/org/apache/commons/jxpath/ri/model
                        NodePointer.java
               jxpath/src/java/org/apache/commons/jxpath/ri/compiler
                        LocationPath.java
               jxpath/src/java/org/apache/commons/jxpath/ri
                        JXPathContextReferenceImpl.java
               jxpath/src/test/org/apache/commons/jxpath/ri/model
                        BeanModelTestCase.java
               jxpath/src/java/org/apache/commons/jxpath/util
                        BasicTypeConverter.java
  Log:
  Added support for relative contexts
  
  Revision  Changes    Path
  1.11      +36 -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.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- users-guide.xml	7 Feb 2003 00:51:40 -0000	1.10
  +++ users-guide.xml	19 Feb 2003 00:59:51 -0000	1.11
  @@ -104,6 +104,8 @@
           </li>
           <li><a href="#Pointers">Pointers</a>
           </li>
  +        <li><a href="#Relative Contexts">Relative Contexts</a>
  +        </li>
           <li><a href="#Extension Functions">Extension Functions</a>
             <ul>
               <li><a href="#Standard Extension Functions">Standard Extension
Functions</a>
  @@ -985,6 +987,40 @@
         </p>
       </section>
   
  +    <section name="Relative Contexts">
  +      <p>
  +        If you need to evaluate multiple paths relative to a certain node
  +        in the object graph, you might want to create a relative JXPathContext.
  +      </p>
  +      <p>
  +        First obtain the pointer for the location that is supposed to define
  +        the relative context.  Then obtain the relative context by calling
  +        <code>context.getRelativeContext(pointer)</code>.
  +      </p>
  +
  +<!--============================ + SOURCE + ============================-->
  +<source>
  +                                                                       <b/>
  + JXPathContext context = JXPathContext.newContext(bean);
  +
  + Pointer addressPtr = context.getPointer("/employees[1]/addresses[2]");
  +
  + JXPathContext relativeContext = 
  +              context.getRelativeContext(addressPtr);
  +
  + // Evaluate relative path 
  + String zipCode = (String)relativeContext.getValue("zipCode");
  +
  + // Evaluate absolute path
  + String name = (String)relativeContext.getValue("/employees[1]/name");
  +
  + // Use the parent axis to locate the employee for the current address
  + Double salary = (Double)relativeContext.getValue("../salary");
  +
  + </source>
  +<!--============================ - SOURCE - ============================-->
  +
  +    </section>
   
       <section name="Extension Functions">
         <p>
  
  
  
  1.10      +24 -25    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.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- RootContext.java	11 Jan 2003 05:41:23 -0000	1.9
  +++ RootContext.java	19 Feb 2003 00:59:51 -0000	1.10
  @@ -75,55 +75,52 @@
    * @version $Revision$ $Date$
    */
   public class RootContext extends EvalContext {
  -    private boolean startedSet = false;
  -    private boolean started = false;
  -    private JXPathContextReferenceImpl parent;
  +    private JXPathContextReferenceImpl jxpathContext;
       private NodePointer pointer;
       private Object registers[];
       private int availableRegister = 0;
       public static final Object UNKNOWN_VALUE = new Object();
       private static final int MAX_REGISTER = 4;
   
  -    public RootContext(JXPathContextReferenceImpl parent, NodePointer pointer) {
  +    public RootContext(
  +        JXPathContextReferenceImpl jxpathContext,
  +        NodePointer pointer) 
  +    {
           super(null);
  -        this.parent = parent;
  +        this.jxpathContext = jxpathContext;
           this.pointer = pointer;
       }
   
       public JXPathContext getJXPathContext() {
  -        return parent;
  +        return jxpathContext;
       }
   
       public RootContext getRootContext() {
           return this;
       }
  +    
  +    public EvalContext getAbsoluteRootContext() {
  +        return jxpathContext.getAbsoluteRootContext();
  +    }
   
       public NodePointer getCurrentNodePointer() {
           return pointer;
       }
   
       public int getCurrentPosition() {
  -        return 1;
  +        throw new UnsupportedOperationException();
       }
   
       public boolean nextNode() {
  -        if (started) {
  -            return false;
  -        }
  -        started = true;
  -        return true;
  +        throw new UnsupportedOperationException();
       }
   
       public boolean nextSet() {
  -        if (startedSet) {
  -            return false;
  -        }
  -        startedSet = true;
  -        return true;
  +        throw new UnsupportedOperationException();
       }
   
       public boolean setPosition(int position) {
  -        return position == 1;
  +        throw new UnsupportedOperationException();
       }
   
       public EvalContext getConstantContext(Object constant) {
  @@ -135,16 +132,18 @@
               pointer =
                   NodePointer.newNodePointer(new QName(null, ""), constant, null);
           }
  -        return new InitialContext(new RootContext(parent, pointer));
  +        return new InitialContext(new RootContext(jxpathContext, pointer));
       }
   
       public EvalContext getVariableContext(QName variableName) {
           return new InitialContext(
  -            new RootContext(parent, parent.getVariablePointer(variableName)));
  +            new RootContext(
  +                jxpathContext,
  +                jxpathContext.getVariablePointer(variableName)));
       }
   
       public Function getFunction(QName functionName, Object[] parameters) {
  -        return parent.getFunction(functionName, parameters);
  +        return jxpathContext.getFunction(functionName, parameters);
       }
   
       public Object getRegisteredValue(int id) {
  
  
  
  1.6       +17 -5     jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/Pointer.java
  
  Index: Pointer.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/Pointer.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Pointer.java	11 Jan 2003 05:41:22 -0000	1.5
  +++ Pointer.java	19 Feb 2003 00:59:52 -0000	1.6
  @@ -61,6 +61,8 @@
    */
   package org.apache.commons.jxpath;
   
  +import java.io.Serializable;
  +
   /**
    * Pointers represent locations of objects and their properties
    * in Java object graphs. JXPathContext has methods
  @@ -78,7 +80,7 @@
    * @author Dmitri Plotnikov
    * @version $Revision$ $Date$
    */
  -public interface Pointer {
  +public interface Pointer extends Cloneable, Comparable, Serializable {
   
       /**
        * Returns the value of the object, property or collection element
  @@ -108,6 +110,11 @@
       void setValue(Object value);
   
       /**
  +     * Returns the node this pointer is based on. 
  +     */
  +    Object getRootNode();
  +    
  +    /**
        * Returns a string that is a proper "canonical" XPath that corresponds to
        * this pointer.  Consider this example:
        * <p><code>Pointer  ptr = ctx.getPointer("//employees[firstName = 'John']")
  @@ -120,4 +127,9 @@
        * /departments[@name = 'HR']/employees[3]"</code>.
        */
       String asPath();
  +    
  +    /**
  +     * Pointers are cloneable
  +     */
  +    Object clone();
   }
  
  
  
  1.15      +13 -5     jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/JXPathContext.java
  
  Index: JXPathContext.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/JXPathContext.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- JXPathContext.java	29 Jan 2003 18:15:17 -0000	1.14
  +++ JXPathContext.java	19 Feb 2003 00:59:52 -0000	1.15
  @@ -442,7 +442,7 @@
       }
   
       /**
  -     * Creates  a new JXPathContext with the specified bean as the root node and
  +     * Creates a new JXPathContext with the specified bean as the root node and
        * the specified parent context. Variables defined in a parent context can
        * be referenced in XPaths passed to the child context.
        */
  @@ -482,6 +482,14 @@
        * Returns a Pointer for the context bean.
        */
       public abstract Pointer getContextPointer();
  +
  +    /**
  +     * Returns a JXPathContext that is relative to the current JXPathContext.
  +     * The supplied pointer becomes the context pointer of the new context.
  +     * The relative context inherits variables, extension functions, locale etc
  +     * from the parent context.
  +     */
  +    public abstract JXPathContext getRelativeContext(Pointer pointer);
   
       /**
        * Installs a custom implementation of the Variables interface.
  
  
  
  1.16      +18 -5     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.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- NodePointer.java	11 Jan 2003 05:41:24 -0000	1.15
  +++ NodePointer.java	19 Feb 2003 00:59:52 -0000	1.16
  @@ -83,12 +83,13 @@
    * @author Dmitri Plotnikov
    * @version $Revision$ $Date$
    */
  -public abstract class NodePointer implements Pointer, Cloneable, Comparable {
  +public abstract class NodePointer implements Pointer {
   
       public static final int WHOLE_COLLECTION = Integer.MIN_VALUE;
       protected int index = WHOLE_COLLECTION;
       public static final String UNKNOWN_NAMESPACE = "<<unknown namespace>>";
       private boolean attribute = false;
  +    private transient Object rootNode;
   
       /**
        * Allocates an entirely new NodePointer by iterating through all installed
  @@ -322,6 +323,18 @@
        */
       public Object getNode() {
           return getValuePointer().getImmediateNode();
  +    }
  +    
  +    public Object getRootNode(){
  +        if (rootNode == null) {
  +            if (parent != null){
  +                rootNode = parent.getRootNode();
  +            }
  +            else {
  +                rootNode = getImmediateNode();
  +            }
  +        }
  +        return rootNode;
       }
       
       /**
  
  
  
  1.8       +10 -10    jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/compiler/LocationPath.java
  
  Index: LocationPath.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jxpath/src/java/org/apache/commons/jxpath/ri/compiler/LocationPath.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- LocationPath.java	19 Jan 2003 23:59:24 -0000	1.7
  +++ LocationPath.java	19 Feb 2003 00:59:52 -0000	1.8
  @@ -107,12 +107,12 @@
           // Create a chain of contexts
           EvalContext rootContext;
           if (isAbsolute()) {
  -            rootContext = context.getRootContext();
  +            rootContext = context.getRootContext().getAbsoluteRootContext();
           }
           else {
  -            rootContext = context;
  +            rootContext = new InitialContext(context);
           }
  -        return evalSteps(new InitialContext(rootContext));
  +        return evalSteps(rootContext);
       }
   
   
  @@ -120,11 +120,11 @@
           // Create a chain of contexts
           EvalContext rootContext;
           if (isAbsolute()) {
  -            rootContext = context.getRootContext();
  +            rootContext = context.getRootContext().getAbsoluteRootContext();
           }
           else {
  -            rootContext = context;
  +            rootContext = new InitialContext(context);
           }
  -        return getSingleNodePointerForSteps(new InitialContext(rootContext));
  +        return getSingleNodePointerForSteps(rootContext);
       }
   }
  
  
  
  1.28      +85 -24    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.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- JXPathContextReferenceImpl.java	18 Feb 2003 18:11:37 -0000	1.27
  +++ JXPathContextReferenceImpl.java	19 Feb 2003 00:59:52 -0000	1.28
  @@ -80,6 +80,7 @@
   import org.apache.commons.jxpath.PackageFunctions;
   import org.apache.commons.jxpath.Pointer;
   import org.apache.commons.jxpath.Variables;
  +import org.apache.commons.jxpath.ri.axes.InitialContext;
   import org.apache.commons.jxpath.ri.axes.RootContext;
   import org.apache.commons.jxpath.ri.compiler.Expression;
   import org.apache.commons.jxpath.ri.compiler.LocationPath;
  @@ -101,12 +102,17 @@
    */
   public class JXPathContextReferenceImpl extends JXPathContext {
       
  +    /**
  +     * Change this to <code>false</code> to disable soft caching of CompiledExpressions.

  +     */
  +    public static final boolean USE_SOFT_CACHE = true;
  +    
       private static final Compiler COMPILER = new TreeCompiler();
       private static Map compiled = new HashMap();
       private static final PackageFunctions GENERIC_FUNCTIONS =
           new PackageFunctions("", null);
  -    private static final boolean USE_SOFT_CACHE = true;
       private static int cleanupCount = 0;
  +    
       private static Vector nodeFactories = new Vector();
       private static NodePointerFactory nodeFactoryArray[] = null;
       static {
  @@ -144,7 +150,8 @@
           createNodeFactoryArray();
       }
   
  -    private NodePointer rootPointer;
  +    private Pointer rootPointer;
  +    private Pointer contextPointer;
   
       // The frequency of the cache cleanup
       private static final int CLEANUP_THRESHOLD = 500;
  @@ -152,10 +159,36 @@
       protected JXPathContextReferenceImpl(JXPathContext parentContext,
                                            Object contextBean) 
       {
  +        this(parentContext, contextBean, null);
  +    }
  +
  +    public JXPathContextReferenceImpl(
  +        JXPathContext parentContext,
  +        Object contextBean,
  +        Pointer contextPointer) 
  +    {
           super(parentContext, contextBean);
  +
           synchronized (nodeFactories) {
               createNodeFactoryArray();
           }
  +                
  +        if (contextPointer != null) {
  +            this.contextPointer = contextPointer;
  +            this.rootPointer =
  +                NodePointer.newNodePointer(
  +                    new QName(null, "root"),
  +                    contextPointer.getRootNode(),
  +                    getLocale());
  +        }
  +        else {
  +            this.contextPointer =
  +                NodePointer.newNodePointer(
  +                    new QName(null, "root"),
  +                    contextBean,
  +                    getLocale());
  +            this.rootPointer = this.contextPointer;
  +        }
       }
   
       private static void createNodeFactoryArray() {
  @@ -172,6 +205,7 @@
               });
           }
       }
  +    
       /**
        * Call this with a custom NodePointerFactory to add support for
        * additional types of objects.  Make sure the factory returns
  @@ -188,11 +222,21 @@
           return nodeFactoryArray;
       }
   
  +    /**
  +     * Returns a static instance of TreeCompiler.
  +     * 
  +     * Override this to return an aternate compiler.
  +     */
  +    protected Compiler getCompiler(){
  +        return COMPILER;
  +        
  +    }
  +    
       protected CompiledExpression compilePath(String xpath) {
           return new JXPathCompiledExpression(xpath, compileExpression(xpath));
       }
   
  -    private static Expression compileExpression(String xpath) {
  +    private Expression compileExpression(String xpath) {
           Expression expr;
           if (USE_SOFT_CACHE) {
               expr = null;
  @@ -201,7 +245,8 @@
                   expr = (Expression) ref.get();
               }
               if (expr == null) {
  -                expr = (Expression) Parser.parseExpression(xpath, COMPILER);
  +                expr =
  +                    (Expression) Parser.parseExpression(xpath, getCompiler());
                   compiled.put(xpath, new SoftReference(expr));
                   if (cleanupCount++ >= CLEANUP_THRESHOLD) {
                       cleanupCache();
  @@ -211,7 +256,8 @@
           else {
               expr = (Expression) compiled.get(xpath);
               if (expr == null) {
  -                expr = (Expression) Parser.parseExpression(xpath, COMPILER);
  +                expr =
  +                    (Expression) Parser.parseExpression(xpath, getCompiler());
                   compiled.put(xpath, expr);
               }
           }
  @@ -238,7 +284,7 @@
       }
   
       public Object getValue(String xpath, Expression expr) {
  -        Object result = expr.computeValue(getRootContext());
  +        Object result = expr.computeValue(getEvalContext());
           if (result instanceof EvalContext) {
               EvalContext ctx = (EvalContext) result;
               result = ctx.getSingleNodePointer();
  @@ -303,7 +349,7 @@
       }
   
       public Iterator iterate(String xpath, Expression expr) {
  -        return expr.iterate(getRootContext());
  +        return expr.iterate(getEvalContext());
       }
   
       public Pointer getPointer(String xpath) {
  @@ -311,7 +357,7 @@
       }
   
       public Pointer getPointer(String xpath, Expression expr) {
  -        Object result = expr.computeValue(getRootContext());
  +        Object result = expr.computeValue(getEvalContext());
           if (result instanceof EvalContext) {
               result = ((EvalContext) result).getSingleNodePointer();
           }
  @@ -347,7 +393,7 @@
   
       public Pointer createPath(String xpath, Expression expr) {
           try {
  -            Object result = expr.computeValue(getRootContext());
  +            Object result = expr.computeValue(getEvalContext());
               Pointer pointer = null;
   
               if (result instanceof Pointer) {
  @@ -396,8 +442,7 @@
           Object value,
           boolean create) 
       {
  -        Object result = expr.computeValue(getRootContext());
  -        //        System.err.println("RESULT: " + result);
  +        Object result = expr.computeValue(getEvalContext());
           Pointer pointer = null;
   
           if (result instanceof Pointer) {
  @@ -449,7 +494,7 @@
       }
   
       public Iterator iteratePointers(String xpath, Expression expr) {
  -        return expr.iteratePointers(getRootContext());
  +        return expr.iteratePointers(getEvalContext());
       }
   
       public void removePath(String xpath) {
  @@ -477,7 +522,7 @@
       public void removeAll(String xpath, Expression expr) {
           try {
               ArrayList list = new ArrayList();
  -            Iterator it = expr.iterate(getRootContext());
  +            Iterator it = expr.iterate(getEvalContext());
               while (it.hasNext()) {
                   list.add(it.next());
               }
  @@ -494,16 +539,32 @@
           }
       }
   
  -    public synchronized Pointer getContextPointer() {
  -        if (rootPointer == null) {
  -            rootPointer = NodePointer.newNodePointer(new QName(null, "root"),
  -                getContextBean(), getLocale());
  +    public JXPathContext getRelativeContext(Pointer pointer){
  +        Object contextBean = pointer.getNode();
  +        if (contextBean == null) {
  +            throw new JXPathException(
  +                "Cannot create a relative context for a non-existent node: "
  +                    + pointer);
           }
  -        return (Pointer) rootPointer.clone();
  +        return new JXPathContextReferenceImpl(this, contextBean, pointer);
  +    }
  +    
  +    public synchronized Pointer getContextPointer() {
  +        return (Pointer) contextPointer.clone();
  +    }
  +
  +    private synchronized NodePointer getAbsoluteRootPointer() {
  +        return (NodePointer) rootPointer.clone();
  +    }
  +
  +    private EvalContext getEvalContext() {
  +        return new InitialContext(
  +            new RootContext(this, (NodePointer) getContextPointer()));
       }
   
  -    private EvalContext getRootContext() {
  -        return new RootContext(this, (NodePointer) getContextPointer());
  +    public EvalContext getAbsoluteRootContext() {
  +        return new InitialContext(
  +            new RootContext(this, getAbsoluteRootPointer()));
       }
   
       public NodePointer getVariablePointer(QName name) {
  
  
  
  1.11      +34 -4     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.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- BeanModelTestCase.java	18 Feb 2003 18:11:37 -0000	1.10
  +++ BeanModelTestCase.java	19 Feb 2003 00:59:52 -0000	1.11
  @@ -956,4 +956,34 @@
               null,
               context.getValue("nestedBean"));
       }
  +    
  +    public void testRelativeContextRelativePath() {
  +        JXPathContext relative =
  +            context.getRelativeContext(context.getPointer("nestedBean"));
  +        
  +        assertXPathValueAndPointer(relative, 
  +            "int", 
  +            new Integer(1), 
  +            "/nestedBean/int");
  +    }
  +
  +    public void testRelativeContextAbsolutePath() {
  +        JXPathContext relative =
  +            context.getRelativeContext(context.getPointer("nestedBean"));
  +        
  +        assertXPathValueAndPointer(relative, 
  +            "/integers[2]", 
  +            new Integer(2), 
  +            "/integers[2]");
  +    }
  +
  +    public void testRelativeContextParent() {
  +        JXPathContext relative =
  +            context.getRelativeContext(context.getPointer("nestedBean"));
  +        
  +        assertXPathValueAndPointer(relative, 
  +            "../integers[2]", 
  +            new Integer(2), 
  +            "/integers[2]");
  +    }
   }
  
  
  
  1.6       +17 -4     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.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- BasicTypeConverter.java	7 Feb 2003 00:51:40 -0000	1.5
  +++ BasicTypeConverter.java	19 Feb 2003 00:59:53 -0000	1.6
  @@ -494,8 +494,21 @@
           public Object getNode() {
               return bean;
           }
  +        
  +        public Object getRootNode() {
  +            return bean;
  +        }        
  +        
           public void setValue(Object value) {
               throw new UnsupportedOperationException();
  +        }
  +        
  +        public Object clone(){
  +            return this;
  +        }
  +        
  +        public int compareTo(Object object) {
  +            return 0;
           }
           
           public String asPath() {
  
  
  

---------------------------------------------------------------------
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