1
2
3
4
5
6
7
8
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
78 JXPathContext cxt = this.accessJXPathContext();
79 cxt.getVariables().declareVariable("target",target);
80 Pointer p = cxt.getPointer("//*[fn:matchTarget()]");
81
82 cxt.getVariables().undeclareVariable("target");
83
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
124
125
126
127
128
129
130
131
132
133
134