1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.jxpath.ri.axes;
17
18 import java.util.Iterator;
19
20 import org.apache.commons.jxpath.ri.EvalContext;
21 import org.apache.commons.jxpath.ri.InfoSetUtil;
22 import org.apache.commons.jxpath.ri.compiler.Expression;
23 import org.apache.commons.jxpath.ri.compiler.NameAttributeTest;
24 import org.apache.commons.jxpath.ri.model.NodePointer;
25 import org.apache.commons.jxpath.ri.model.beans.PropertyOwnerPointer;
26 import org.apache.commons.jxpath.ri.model.beans.PropertyPointer;
27
28 /***
29 * EvalContext that checks predicates.
30 *
31 * @author Dmitri Plotnikov
32 * @version $Revision: 1.22 $ $Date: 2004/02/29 14:17:37 $
33 */
34 public class PredicateContext extends EvalContext {
35 private Expression expression;
36 private boolean done = false;
37 private Expression nameTestExpression;
38 private PropertyPointer dynamicPropertyPointer;
39
40 public PredicateContext(EvalContext parentContext, Expression expression) {
41 super(parentContext);
42 this.expression = expression;
43 if (expression instanceof NameAttributeTest) {
44 nameTestExpression =
45 ((NameAttributeTest) expression).getNameTestExpression();
46 }
47 }
48
49 public boolean nextNode() {
50 if (done) {
51 return false;
52 }
53 while (parentContext.nextNode()) {
54 if (setupDynamicPropertyPointer()) {
55 Object pred = nameTestExpression.computeValue(parentContext);
56 String propertyName = InfoSetUtil.stringValue(pred);
57
58
59
60
61
62
63
64
65
66 boolean ok = false;
67 String names[] = dynamicPropertyPointer.getPropertyNames();
68 for (int i = 0; i < names.length; i++) {
69 if (names[i].equals(propertyName)) {
70 ok = true;
71 break;
72 }
73 }
74 if (ok) {
75 dynamicPropertyPointer.setPropertyName(propertyName);
76 position++;
77 return true;
78 }
79 }
80 else {
81 Object pred = expression.computeValue(parentContext);
82 if (pred instanceof Iterator) {
83 if (!((Iterator) pred).hasNext()) {
84 return false;
85 }
86 pred = ((Iterator) pred).next();
87 }
88
89 if (pred instanceof NodePointer) {
90 pred = ((NodePointer) pred).getNode();
91 }
92
93 if (pred instanceof Number) {
94 int pos = (int) InfoSetUtil.doubleValue(pred);
95 position++;
96 done = true;
97 return parentContext.setPosition(pos);
98 }
99 else if (InfoSetUtil.booleanValue(pred)) {
100 position++;
101 return true;
102 }
103 }
104 }
105 return false;
106 }
107
108 /***
109 * Used for an optimized access to dynamic properties using the
110 * "map[@name = 'name']" syntax
111 */
112 private boolean setupDynamicPropertyPointer() {
113 if (nameTestExpression == null) {
114 return false;
115 }
116
117 NodePointer parent = parentContext.getCurrentNodePointer();
118 if (parent == null) {
119 return false;
120 }
121 parent = parent.getValuePointer();
122 if (!(parent instanceof PropertyOwnerPointer)) {
123 return false;
124 }
125 dynamicPropertyPointer =
126 (PropertyPointer) ((PropertyOwnerPointer) parent)
127 .getPropertyPointer()
128 .clone();
129 return true;
130 }
131
132 public boolean setPosition(int position) {
133 if (nameTestExpression == null) {
134 return setPositionStandard(position);
135 }
136 else {
137 if (dynamicPropertyPointer == null) {
138 if (!setupDynamicPropertyPointer()) {
139 return setPositionStandard(position);
140 }
141 }
142 if (position < 1
143 || position > dynamicPropertyPointer.getLength()) {
144 return false;
145 }
146 dynamicPropertyPointer.setIndex(position - 1);
147 return true;
148 }
149 }
150
151 public NodePointer getCurrentNodePointer() {
152 if (position == 0) {
153 if (!setPosition(1)) {
154 return null;
155 }
156 }
157 if (dynamicPropertyPointer != null) {
158 return dynamicPropertyPointer.getValuePointer();
159 }
160 else {
161 return parentContext.getCurrentNodePointer();
162 }
163 }
164
165 public void reset() {
166 super.reset();
167 done = false;
168 }
169
170 public boolean nextSet() {
171 reset();
172 return parentContext.nextSet();
173 }
174
175 private boolean setPositionStandard(int position) {
176 if (this.position > position) {
177 reset();
178 }
179
180 while (this.position < position) {
181 if (!nextNode()) {
182 return false;
183 }
184 }
185 return true;
186 }
187 }