1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.jxpath.ri.compiler;
17
18 import org.apache.commons.jxpath.ri.EvalContext;
19 import org.apache.commons.jxpath.ri.axes.InitialContext;
20 import org.apache.commons.jxpath.ri.axes.NodeSetContext;
21 import org.apache.commons.jxpath.ri.axes.PredicateContext;
22 import org.apache.commons.jxpath.ri.axes.SimplePathInterpreter;
23 import org.apache.commons.jxpath.ri.axes.UnionContext;
24 import org.apache.commons.jxpath.ri.model.NodePointer;
25
26 /***
27 * An element of the parse tree that represents an expression path, which is a
28 * path that starts with an expression like a function call: <code>getFoo(.)
29 * /bar</code>.
30 *
31 * @author Dmitri Plotnikov
32 * @version $Revision: 1.11 $ $Date: 2004/02/29 14:17:39 $
33 */
34 public class ExpressionPath extends Path {
35
36 private Expression expression;
37 private Expression predicates[];
38
39 private boolean basicKnown = false;
40 private boolean basic;
41
42 public ExpressionPath(
43 Expression expression,
44 Expression[] predicates,
45 Step[] steps)
46 {
47 super(steps);
48 this.expression = expression;
49 this.predicates = predicates;
50 }
51
52 public Expression getExpression() {
53 return expression;
54 }
55
56 /***
57 * Predicates are the expressions in brackets that may follow
58 * the root expression of the path.
59 */
60 public Expression[] getPredicates() {
61 return predicates;
62 }
63
64 /***
65 * Returns true if the root expression or any of the
66 * predicates or the path steps are context dependent.
67 */
68 public boolean computeContextDependent() {
69 if (expression.isContextDependent()) {
70 return true;
71 }
72 if (predicates != null) {
73 for (int i = 0; i < predicates.length; i++) {
74 if (predicates[i].isContextDependent()) {
75 return true;
76 }
77 }
78 }
79 return super.computeContextDependent();
80 }
81
82 /***
83 * Recognized paths formatted as <code>$x[3]/foo[2]</code>. The
84 * evaluation of such "simple" paths is optimized and streamlined.
85 */
86 public boolean isSimpleExpressionPath() {
87 if (!basicKnown) {
88 basicKnown = true;
89 basic = isSimplePath() && areBasicPredicates(getPredicates());
90 }
91 return basic;
92 }
93
94 public String toString() {
95 StringBuffer buffer = new StringBuffer();
96 if (expression instanceof CoreOperation
97 || expression instanceof ExpressionPath
98 || expression instanceof LocationPath) {
99 buffer.append('(');
100 buffer.append(expression);
101 buffer.append(')');
102 }
103 else {
104 buffer.append(expression);
105 }
106 if (predicates != null) {
107 for (int i = 0; i < predicates.length; i++) {
108 buffer.append('[');
109 buffer.append(predicates[i]);
110 buffer.append(']');
111 }
112 }
113
114 Step steps[] = getSteps();
115 if (steps != null) {
116 for (int i = 0; i < steps.length; i++) {
117 buffer.append("/");
118 buffer.append(steps[i]);
119 }
120 }
121 return buffer.toString();
122 }
123
124 public Object compute(EvalContext context) {
125 return expressionPath(context, false);
126 }
127
128 public Object computeValue(EvalContext context) {
129 return expressionPath(context, true);
130 }
131
132 /***
133 * Walks an expression path (a path that starts with an expression)
134 */
135 protected Object expressionPath(
136 EvalContext evalContext,
137 boolean firstMatch)
138 {
139 Object value = expression.compute(evalContext);
140 EvalContext context;
141 if (value instanceof InitialContext) {
142
143
144 context = (InitialContext) value;
145 }
146 else if (value instanceof EvalContext) {
147
148
149 context =
150 new UnionContext(
151 evalContext,
152 new EvalContext[] {(EvalContext) value });
153 }
154 else {
155 context = evalContext.getRootContext().getConstantContext(value);
156 }
157
158 if (firstMatch
159 && isSimpleExpressionPath()
160 && !(context instanceof NodeSetContext)) {
161 EvalContext ctx = context;
162 NodePointer ptr = (NodePointer) ctx.getSingleNodePointer();
163 if (ptr != null
164 && (ptr.getIndex() == NodePointer.WHOLE_COLLECTION
165 || predicates == null
166 || predicates.length == 0)) {
167 return SimplePathInterpreter.interpretSimpleExpressionPath(
168 evalContext,
169 ptr,
170 predicates,
171 getSteps());
172 }
173 }
174 if (predicates != null) {
175 for (int j = 0; j < predicates.length; j++) {
176 context = new PredicateContext(context, predicates[j]);
177 }
178 }
179 if (firstMatch) {
180 return getSingleNodePointerForSteps(context);
181 }
182 else {
183 return evalSteps(context);
184 }
185 }
186 }