1 16 package org.apache.commons.jxpath.ri.compiler; 17 18 import org.apache.commons.jxpath.Pointer; 19 import org.apache.commons.jxpath.ri.Compiler; 20 import org.apache.commons.jxpath.ri.EvalContext; 21 import org.apache.commons.jxpath.ri.QName; 22 import org.apache.commons.jxpath.ri.axes.AncestorContext; 23 import org.apache.commons.jxpath.ri.axes.AttributeContext; 24 import org.apache.commons.jxpath.ri.axes.ChildContext; 25 import org.apache.commons.jxpath.ri.axes.DescendantContext; 26 import org.apache.commons.jxpath.ri.axes.InitialContext; 27 import org.apache.commons.jxpath.ri.axes.NamespaceContext; 28 import org.apache.commons.jxpath.ri.axes.ParentContext; 29 import org.apache.commons.jxpath.ri.axes.PrecedingOrFollowingContext; 30 import org.apache.commons.jxpath.ri.axes.PredicateContext; 31 import org.apache.commons.jxpath.ri.axes.SelfContext; 32 import org.apache.commons.jxpath.ri.axes.SimplePathInterpreter; 33 import org.apache.commons.jxpath.ri.model.NodePointer; 34 35 39 public abstract class Path extends Expression { 40 41 private Step[] steps; 42 private boolean basicKnown = false; 43 private boolean basic; 44 45 public Path(Step[] steps) { 46 this.steps = steps; 47 } 48 49 public Step[] getSteps() { 50 return steps; 51 } 52 53 public boolean computeContextDependent() { 54 if (steps != null) { 55 for (int i = 0; i < steps.length; i++) { 56 if (steps[i].isContextDependent()) { 57 return true; 58 } 59 } 60 } 61 62 return false; 63 } 64 65 70 public boolean isSimplePath() { 71 if (!basicKnown) { 72 basicKnown = true; 73 basic = true; 74 Step[] steps = getSteps(); 75 for (int i = 0; i < steps.length; i++) { 76 if (!isSimpleStep(steps[i])){ 77 basic = false; 78 break; 79 } 80 } 81 } 82 return basic; 83 } 84 85 90 protected boolean isSimpleStep(Step step) { 91 if (step.getAxis() == Compiler.AXIS_SELF) { 92 NodeTest nodeTest = step.getNodeTest(); 93 if (!(nodeTest instanceof NodeTypeTest)) { 94 return false; 95 } 96 int nodeType = ((NodeTypeTest) nodeTest).getNodeType(); 97 if (nodeType != Compiler.NODE_TYPE_NODE) { 98 return false; 99 } 100 return areBasicPredicates(step.getPredicates()); 101 } 102 else if (step.getAxis() == Compiler.AXIS_CHILD 103 || step.getAxis() == Compiler.AXIS_ATTRIBUTE) { 104 NodeTest nodeTest = step.getNodeTest(); 105 if (!(nodeTest instanceof NodeNameTest)){ 106 return false; 107 } 108 109 if (((NodeNameTest) nodeTest).isWildcard()) { 110 return false; 111 } 112 return areBasicPredicates(step.getPredicates()); 113 } 114 return false; 115 } 116 117 protected boolean areBasicPredicates(Expression predicates[]) { 118 if (predicates != null && predicates.length != 0) { 119 boolean firstIndex = true; 120 for (int i = 0; i < predicates.length; i++) { 121 if (predicates[i] instanceof NameAttributeTest) { 122 if (((NameAttributeTest) predicates[i]) 123 .getNameTestExpression() 124 .isContextDependent()) { 125 return false; 126 } 127 } 128 else if (predicates[i].isContextDependent()) { 129 return false; 130 } 131 else { 132 if (!firstIndex) { 133 return false; 134 } 135 firstIndex = false; 136 } 137 } 138 } 139 return true; 140 } 141 142 146 protected Pointer getSingleNodePointerForSteps(EvalContext context) { 147 if (steps.length == 0) { 148 return context.getSingleNodePointer(); 149 } 150 151 if (isSimplePath()) { 152 NodePointer ptr = (NodePointer) context.getSingleNodePointer(); 153 return SimplePathInterpreter.interpretSimpleLocationPath( 154 context, 155 ptr, 156 steps); 157 } 158 else { 159 return searchForPath(context); 160 } 161 } 162 163 181 private Pointer searchForPath(EvalContext context) { 182 EvalContext ctx = buildContextChain(context, steps.length, true); 183 Pointer pointer = ctx.getSingleNodePointer(); 184 185 if (pointer != null) { 186 return pointer; 187 } 188 189 for (int i = steps.length; --i > 0;) { 190 if (!isSimpleStep(steps[i])) { 191 return null; 192 } 193 ctx = buildContextChain(context, i, true); 194 if (ctx.hasNext()) { 195 Pointer partial = (Pointer) ctx.next(); 196 if (ctx.hasNext()) { 197 return null; 200 } 201 if (partial instanceof NodePointer) { 202 return SimplePathInterpreter.createNullPointer( 203 context, 204 (NodePointer) partial, 205 steps, 206 i); 207 } 208 } 209 } 210 return null; 211 } 212 213 217 protected EvalContext evalSteps(EvalContext context) { 218 return buildContextChain(context, steps.length, false); 219 } 220 221 private EvalContext buildContextChain( 222 EvalContext context, 223 int stepCount, 224 boolean createInitialContext) 225 { 226 if (createInitialContext) { 227 context = new InitialContext(context); 228 } 229 if (steps.length == 0) { 230 return context; 231 } 232 for (int i = 0; i < stepCount; i++) { 233 context = 234 createContextForStep( 235 context, 236 steps[i].getAxis(), 237 steps[i].getNodeTest()); 238 Expression predicates[] = steps[i].getPredicates(); 239 if (predicates != null) { 240 for (int j = 0; j < predicates.length; j++) { 241 context = new PredicateContext(context, predicates[j]); 242 } 243 } 244 } 245 return context; 246 } 247 248 252 protected EvalContext createContextForStep( 253 EvalContext context, 254 int axis, 255 NodeTest nodeTest) 256 { 257 if (nodeTest instanceof NodeNameTest) { 258 QName qname = ((NodeNameTest) nodeTest).getNodeName(); 259 String prefix = qname.getPrefix(); 260 if (prefix != null) { 261 String namespaceURI = context.getJXPathContext() 262 .getNamespaceURI(prefix); 263 nodeTest = new NodeNameTest(qname, namespaceURI); 264 } 265 } 266 267 switch (axis) { 268 case Compiler.AXIS_ANCESTOR : 269 return new AncestorContext(context, false, nodeTest); 270 case Compiler.AXIS_ANCESTOR_OR_SELF : 271 return new AncestorContext(context, true, nodeTest); 272 case Compiler.AXIS_ATTRIBUTE : 273 return new AttributeContext(context, nodeTest); 274 case Compiler.AXIS_CHILD : 275 return new ChildContext(context, nodeTest, false, false); 276 case Compiler.AXIS_DESCENDANT : 277 return new DescendantContext(context, false, nodeTest); 278 case Compiler.AXIS_DESCENDANT_OR_SELF : 279 return new DescendantContext(context, true, nodeTest); 280 case Compiler.AXIS_FOLLOWING : 281 return new PrecedingOrFollowingContext(context, nodeTest, false); 282 case Compiler.AXIS_FOLLOWING_SIBLING : 283 return new ChildContext(context, nodeTest, true, false); 284 case Compiler.AXIS_NAMESPACE : 285 return new NamespaceContext(context, nodeTest); 286 case Compiler.AXIS_PARENT : 287 return new ParentContext(context, nodeTest); 288 case Compiler.AXIS_PRECEDING : 289 return new PrecedingOrFollowingContext(context, nodeTest, true); 290 case Compiler.AXIS_PRECEDING_SIBLING : 291 return new ChildContext(context, nodeTest, true, true); 292 case Compiler.AXIS_SELF : 293 return new SelfContext(context, nodeTest); 294 } 295 return null; } 297 } | Popular Tags |