1 package com.icl.saxon.expr; 2 import com.icl.saxon.Context; 3 import com.icl.saxon.om.Axis; 4 import com.icl.saxon.om.NodeInfo; 5 import com.icl.saxon.om.NodeEnumeration; 6 import com.icl.saxon.pattern.AnyNodeTest; 7 import com.icl.saxon.pattern.NameTest; 8 import com.icl.saxon.sort.NodeOrderComparer; 9 import com.icl.saxon.sort.LocalOrderComparer; 10 11 17 18 public class PathExpression extends NodeSetExpression { 19 20 private Expression start; 21 private Step step; 22 int dependencies = -1; 23 24 31 32 public PathExpression(Expression start, Step step) { 33 this.start = start; 34 this.step = step; 35 } 36 37 41 42 public Expression simplify() throws XPathException { 43 44 start = start.simplify(); 45 step = step.simplify(); 46 47 if (start instanceof EmptyNodeSet) { 49 return start; 50 } 51 52 if (step==null) { 54 return new EmptyNodeSet(); 55 } 56 57 byte axis = step.getAxis(); 58 59 61 if (start instanceof RootExpression && axis == Axis.PARENT) { 62 return new EmptyNodeSet(); 63 } 64 65 67 if ( start instanceof ContextNodeExpression && 68 axis == Axis.ATTRIBUTE && 69 step.getNodeTest() instanceof NameTest && 70 step.getNumberOfFilters() == 0) { 71 72 return new AttributeReference(step.getNodeTest().getFingerprint()); 73 } 74 75 78 if ( start instanceof ContextNodeExpression && 79 step.getNumberOfFilters() == 0) { 80 return new AxisExpression(axis, step.getNodeTest()); 81 } 82 83 88 if ( axis == Axis.CHILD && 89 step.getNumberOfFilters() == 0 && 90 start instanceof PathExpression && 91 ((PathExpression)start).step.getAxis() == Axis.DESCENDANT_OR_SELF && 92 ((PathExpression)start).step.getNumberOfFilters() == 0 && 93 ((PathExpression)start).step.getNodeTest() instanceof AnyNodeTest ) 94 { 95 97 100 108 return new PathExpression( 109 ((PathExpression)start).start, 110 new Step(Axis.DESCENDANT, step.getNodeTest())); 111 } 113 114 return this; 115 } 116 117 122 123 public int getDependencies() { 124 if (dependencies==-1) { 125 dependencies = start.getDependencies(); 126 Expression[] filters = step.getFilters(); 127 for (int f=0; f<step.getNumberOfFilters(); f++) { 128 Expression exp = filters[f]; 129 dependencies |= (exp.getDependencies() & Context.XSLT_CONTEXT); 132 } 134 } 135 return dependencies; 136 } 137 138 143 144 public boolean isContextDocumentNodeSet() { 145 return start.isContextDocumentNodeSet(); 146 } 147 148 156 157 public Expression reduce(int dep, Context context) throws XPathException { 158 Expression path = this; 159 if ((dep & getDependencies()) != 0) { 160 Expression newstart = start.reduce(dep, context); 161 Step newstep = new Step(step.getAxis(), step.getNodeTest()); 162 Expression[] filters = step.getFilters(); 163 164 int removedep = dep & Context.XSLT_CONTEXT; 165 if (start.isContextDocumentNodeSet() && 166 ((dep & Context.CONTEXT_DOCUMENT)!=0)) { 167 removedep |= Context.CONTEXT_DOCUMENT; 168 } 169 170 for (int f=0; f<step.getNumberOfFilters(); f++) { 171 Expression exp = filters[f]; 172 Expression newfilter = exp.reduce(removedep, context); 175 newstep.addFilter(newfilter); 176 } 177 path = new PathExpression(newstart, newstep); 178 path.setStaticContext(getStaticContext()); 179 path = path.simplify(); 180 } 181 182 186 if ((path instanceof PathExpression) && 187 ((PathExpression)path).start instanceof NodeSetValue) { 188 return new NodeSetIntent((PathExpression)path, context.getController()); 189 } 190 191 return path; 192 } 193 194 195 200 201 public NodeEnumeration enumerate(Context context, boolean sort) throws XPathException { 202 208 int actualdep = getDependencies(); 209 int removedep = 0; 210 211 if ((actualdep & Context.XSLT_CONTEXT) != 0) { 212 removedep |= Context.XSLT_CONTEXT; 213 } 214 215 if (start.isContextDocumentNodeSet() && 216 ((actualdep & Context.CONTEXT_DOCUMENT) != 0)) { 217 removedep |= Context.CONTEXT_DOCUMENT; 218 } 219 220 if (( removedep & (Context.XSLT_CONTEXT | Context.CONTEXT_DOCUMENT)) != 0) { 221 Expression temp = reduce(removedep, context); 222 return temp.enumerate(context, sort); 223 } 224 225 NodeEnumeration enum = new PathEnumeration(start, context); 226 if (sort && !enum.isSorted()) { 227 NodeOrderComparer comparer; 228 if (start instanceof SingletonNodeSet || start.isContextDocumentNodeSet()) { 229 comparer = LocalOrderComparer.getInstance(); 231 } else { 232 comparer = context.getController(); 233 } 234 NodeSetExtent ns = new NodeSetExtent(enum, comparer); 235 ns.sort(); 236 return ns.enumerate(); 237 } 238 return enum; 239 } 240 241 244 245 public void display(int level) { 246 System.err.println(indent(level) + "path"); 247 start.display(level+1); 248 step.display(level+1); 249 } 250 251 252 255 256 private class PathEnumeration implements NodeEnumeration { 257 258 private Expression thisStart; 259 private NodeEnumeration base=null; 260 private NodeEnumeration thisStep=null; 261 private NodeInfo next=null; 262 private Context context; 263 264 public PathEnumeration(Expression start, Context context) throws XPathException { 265 if (start instanceof SingletonNodeSet) { 266 if (!((SingletonNodeSet)start).isGeneralUseAllowed()) { 267 throw new XPathException("To use a result tree fragment in a path expression, either use exsl:node-set() or specify version='1.1'"); 268 } 269 } 270 thisStart = start; 271 this.context = context.newContext(); 272 base = start.enumerate(this.context, false); 273 next = getNextNode(); 274 } 275 276 public boolean hasMoreElements() { 277 return next!=null; 278 } 279 280 public NodeInfo nextElement() throws XPathException { 281 NodeInfo curr = next; 282 next = getNextNode(); 283 return curr; 284 } 285 286 private NodeInfo getNextNode() throws XPathException { 287 288 291 if (thisStep!=null && thisStep.hasMoreElements()) { 292 return thisStep.nextElement(); 293 } 297 298 while (base.hasMoreElements()) { 299 NodeInfo node = base.nextElement(); 300 thisStep = step.enumerate(node, context); 302 if (thisStep.hasMoreElements()) { 303 return thisStep.nextElement(); 304 } 308 } 309 310 return null; 311 312 } 313 314 319 320 public boolean isSorted() { 321 byte axis = step.getAxis(); 322 return Axis.isForwards[axis] && ( 323 ( (thisStart instanceof SingletonExpression) || 324 (base.isSorted() && base.isPeer() && Axis.isSubtreeAxis[axis]) || 325 (base.isSorted() && (axis==Axis.ATTRIBUTE || axis==Axis.NAMESPACE)) 326 )); 327 } 328 329 333 334 public boolean isReverseSorted() { 335 return thisStart instanceof SingletonExpression && Axis.isReverse[step.getAxis()]; 336 } 337 338 342 343 public boolean isPeer() { 344 return (base.isPeer() && Axis.isPeerAxis[step.getAxis()]); 345 } 346 347 } 349 350 } 351 352 353 354 | Popular Tags |