View Javadoc

1   /*$Id: BaseBean.java,v 1.3 2004/03/05 11:05:08 nw Exp $
2    * Created on 10-Feb-2004
3    *
4    * Copyright (C) AstroGrid. All rights reserved.
5    *
6    * This software is published under the terms of the AstroGrid 
7    * Software License version 1.2, a copy of which has been included 
8    * with this distribution in the LICENSE.txt file.  
9    *
10  **/
11  package org.astrogrid.common.bean;
12  
13  import org.apache.commons.jxpath.ClassFunctions;
14  import org.apache.commons.jxpath.ExpressionContext;
15  import org.apache.commons.jxpath.FunctionLibrary;
16  import org.apache.commons.jxpath.Functions;
17  import org.apache.commons.jxpath.JXPathContext;
18  import org.apache.commons.jxpath.Pointer;
19  
20  import java.util.Iterator;
21  
22  /*** Base class for generated object-model beans.
23   * @author Noel Winstanley nw@jb.man.ac.uk 10-Feb-2004
24   * @see http://jakarta.apache.org/commons/jxpath/apidocs/org/apache/commons/jxpath/JXPathContext.html
25   * @see BaseBeanTest
26   */
27  public abstract class BaseBean {
28      /*** Construct a new BaseBean
29       * 
30       */
31      public BaseBean() {
32          super();
33      }
34      
35      private transient JXPathContext cxt;
36      /*** access the jxpath context object for this object (lazily initialized)
37       * @modified NWW - renamed, to avoid using 'get*' naming convention - otherwise
38       * is accessed when traversing the tree, which leads to recursion and out of memory errors.*/
39      public final synchronized JXPathContext accessJXPathContext() {
40          if (cxt == null) {
41                      this.cxt = JXPathContext.newContext(this);
42                      this.cxt.setLenient(true);
43                      FunctionLibrary lib = new FunctionLibrary();
44                      this.cxt.setFunctions(lib);                    
45                      lib.addFunctions(new ClassFunctions(BaseBean.Fns.class,"fn"));         
46          }
47          return cxt;
48      } 
49      /*** add a new funciton library to the xpath interpreter */
50      public final void addFunctions(Functions fn) {
51          ((FunctionLibrary)accessJXPathContext().getFunctions()).addFunctions(fn);
52      }
53      /*** execute an xpath query, using thiis object as the root of an object graph
54       * 
55       * @param xpath query to execute
56       * @return object found, or null
57       */
58      public final Object findXPathValue(String xpath) {
59          return this.accessJXPathContext().getValue(xpath);
60      }
61      /*** execute an expath query, using this object as the root of an object graph
62       * 
63       * @param xpath query to execute
64       * @return iterator containing series of objects that match this query
65       */
66      public final Iterator findXPathIterator(String xpath) {
67          return this.accessJXPathContext().iterate(xpath);
68      }
69      
70      /*** return the xpath for a particular object.
71       * 
72       * @param target object to return xpath for. must be in object tree (or a similar object equivalent under equals())
73       * @return xpath for that object, or null
74       *
75       */
76      public final String getXPathFor(Object target) {
77          // add variable we're looking for.
78          JXPathContext cxt = this.accessJXPathContext();
79          cxt.getVariables().declareVariable("target",target);
80          Pointer p  = cxt.getPointer("//*[fn:matchTarget()]");
81          // tidyup  
82          cxt.getVariables().undeclareVariable("target");
83          // sanity check..
84          return p != null && p.getNode() != null ? p.asPath() : null;        
85      }
86  
87      /*** class of functions added to jxpath context
88       * <p>has to be public, else lib is not callable from jxpath */
89      public static class Fns {
90          /*** returns true if context node is equal to variable target.
91           * i.e. $target.equals(.)
92           * @param ctxt
93           * @return
94           */ 
95          public static boolean matchTarget(ExpressionContext ctxt) {
96              Object candidate = ctxt.getContextNodePointer().getValue();
97              Object target = ctxt.getJXPathContext().getVariables().getVariable("target");
98              return target.equals(candidate);
99          }
100         
101         /*** access the name of the class of the context node - useful for finding nodes by class 
102          * e.g. //*[functions:type() = 'org.astrogrid.Blob'] 
103          *  */
104         public static String type(ExpressionContext ctxt) {
105             Pointer ptr = ctxt.getContextNodePointer();
106             if (ptr == null) {
107                 return "null";
108             }
109             Object candidate = ctxt.getContextNodePointer().getValue();
110             if (candidate == null) {
111                 return "null";
112             }
113             return candidate.getClass().getName();
114         }
115 
116     }    
117 
118     
119 }
120 
121 
122 /* 
123 $Log: BaseBean.java,v $
124 Revision 1.3  2004/03/05 11:05:08  nw
125 added ability to plug in new xpath function sets
126 
127 Revision 1.2  2004/03/01 01:26:12  nw
128 added method to find xpath for a given object in the tree
129 - can be used to implement activity keys
130 
131 Revision 1.1  2004/02/10 17:30:57  nw
132 added base class for castor-generated object models that provides xpath querying
133  
134 */