1 package net.sf.saxon.instruct; 2 import net.sf.saxon.Controller; 3 import net.sf.saxon.expr.*; 4 import net.sf.saxon.om.*; 5 import net.sf.saxon.style.StandardNames; 6 import net.sf.saxon.trace.InstructionInfo; 7 import net.sf.saxon.trace.Location; 8 import net.sf.saxon.trace.TraceListener; 9 import net.sf.saxon.trans.DynamicError; 10 import net.sf.saxon.trans.Mode; 11 import net.sf.saxon.trans.XPathException; 12 import net.sf.saxon.trans.SaxonErrorCode; 13 import net.sf.saxon.type.ItemType; 14 import net.sf.saxon.type.Type; 15 import net.sf.saxon.value.EmptySequence; 16 import net.sf.saxon.value.Value; 17 18 import java.io.PrintStream ; 19 import java.util.ArrayList ; 20 import java.util.Iterator ; 21 22 25 26 public class ApplyTemplates extends Instruction { 27 28 private Expression select; 29 private WithParam[] actualParams = null; 30 private WithParam[] tunnelParams = null; 31 private boolean useCurrentMode = false; 32 private boolean useTailRecursion = false; 33 private Mode mode; 34 private boolean backwardsCompatible; 35 36 public ApplyTemplates( Expression select, 37 boolean useCurrentMode, 38 boolean useTailRecursion, 39 Mode mode, 40 boolean backwardsCompatible) { 41 this.select = select; 42 this.useCurrentMode = useCurrentMode; 43 this.useTailRecursion = useTailRecursion; 44 this.mode = mode; 45 this.backwardsCompatible = backwardsCompatible; 46 adoptChildExpression(select); 47 } 48 49 52 53 public void setActualParameters( 54 WithParam[] actualParams, 55 WithParam[] tunnelParams ) { 56 this.actualParams = actualParams; 57 this.tunnelParams = tunnelParams; 58 } 59 60 63 64 public int getInstructionNameCode() { 65 return StandardNames.XSL_APPLY_TEMPLATES; 66 } 67 68 72 73 public InstructionInfo getInstructionInfo() { 74 InstructionDetails details = (InstructionDetails)super.getInstructionInfo(); 75 details.setProperty("mode", mode); 76 return details; 77 } 78 79 87 88 public Expression simplify(StaticContext env) throws XPathException { 89 WithParam.simplify(actualParams, env); 90 WithParam.simplify(tunnelParams, env); 91 select = select.simplify(env); 92 return this; 93 } 94 95 public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException { 96 WithParam.typeCheck(actualParams, env, contextItemType); 97 WithParam.typeCheck(tunnelParams, env, contextItemType); 98 select = select.typeCheck(env, contextItemType); 99 adoptChildExpression(select); 100 if (select instanceof EmptySequence) { 101 return EmptySequence.getInstance(); 102 } 103 return this; 104 } 105 106 public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException { 107 WithParam.optimize(opt, actualParams, env, contextItemType); 108 WithParam.optimize(opt, tunnelParams, env, contextItemType); 109 select = select.typeCheck(env, contextItemType); select = select.optimize(opt, env, contextItemType); 111 adoptChildExpression(select); 112 if (select instanceof EmptySequence) { 113 return EmptySequence.getInstance(); 114 } 115 return this; 116 } 117 118 123 124 public final boolean createsNewNodes() { 125 return true; 126 } 127 128 public void process(XPathContext context) throws XPathException { 129 apply(context, false); 130 } 131 132 public TailCall processLeavingTail(XPathContext context) throws XPathException { 133 return apply(context, useTailRecursion); 134 } 135 136 private TailCall apply(XPathContext context, boolean returnTailCall) throws XPathException { 137 Mode thisMode = mode; 138 if (useCurrentMode) { 139 thisMode = context.getCurrentMode(); 140 } 141 142 144 ParameterSet params = assembleParams(context, actualParams); 145 ParameterSet tunnels = assembleTunnelParams(context, tunnelParams); 146 147 if (returnTailCall) { 148 XPathContextMajor c2 = context.newContext(); 149 c2.setOrigin(this); 150 return new ApplyTemplatesPackage( 151 ExpressionTool.lazyEvaluate(select, context, 1), 152 thisMode, params, tunnels, c2, getLocationId()); 153 } 154 155 157 SequenceIterator iter = select.iterate(context); 158 159 161 if (iter instanceof EmptyIterator) { 162 return null; 163 } 164 165 XPathContextMajor c2 = context.newContext(); 167 c2.setOrigin(this); 168 try { 169 TailCall tc = applyTemplates(iter, thisMode, params, tunnels, c2, backwardsCompatible, getLocationId()); 170 while (tc != null) { 171 tc = tc.processLeavingTail(c2); 172 } 173 } catch (StackOverflowError e) { 174 DynamicError err = new DynamicError( 175 "Too many nested apply-templates calls. The stylesheet is probably looping."); 176 err.setErrorCode(SaxonErrorCode.SXLM0001); 177 err.setLocator(this); 178 err.setXPathContext(context); 179 throw err; 180 } 181 return null; 182 183 } 184 185 207 208 public static TailCall applyTemplates(SequenceIterator iterator, 209 Mode mode, 210 ParameterSet parameters, 211 ParameterSet tunnelParameters, 212 XPathContextMajor context, 213 boolean backwardsCompatible, 214 int locationId) 215 throws XPathException { 216 Controller controller = context.getController(); 217 TailCall tc = null; 218 219 XPathContextMajor c2 = context; 220 221 223 if (controller.isTracing()) { 224 225 c2.setCurrentIterator(iterator); 226 c2.setCurrentMode(mode); 227 while(true) { 228 while (tc != null) { 230 tc = tc.processLeavingTail(c2); 231 } 232 233 NodeInfo node = (NodeInfo)iterator.next(); 234 if (node == null) break; 236 237 Template eh = controller.getRuleManager().getTemplateRule(node, mode, c2); 239 240 if (eh==null) { defaultAction(node, parameters, tunnelParameters, c2, backwardsCompatible, locationId); 243 244 } else { 245 TraceListener traceListener = controller.getTraceListener(); 247 c2.setLocalParameters(parameters); 248 c2.setTunnelParameters(tunnelParameters); 249 c2.openStackFrame(eh.getStackFrameMap()); 250 traceListener.startCurrentItem(node); 251 tc = eh.processLeavingTail(c2); 252 traceListener.endCurrentItem(node); 253 } 260 } 261 262 } else { 264 c2.setCurrentIterator(iterator); 265 c2.setCurrentMode(mode); 266 while(true) { 267 268 while (tc != null) { 270 tc = tc.processLeavingTail(c2); 271 } 272 273 NodeInfo node = (NodeInfo)iterator.next(); 274 if (node == null) break; 276 277 279 Template eh = controller.getRuleManager().getTemplateRule(node, mode, c2); 280 281 if (eh==null) { defaultAction(node, parameters, tunnelParameters, c2, backwardsCompatible, locationId); 284 285 } else { 286 c2.openStackFrame(eh.getStackFrameMap()); 288 c2.setLocalParameters(parameters); 289 c2.setTunnelParameters(tunnelParameters); 290 tc = eh.processLeavingTail(c2); 291 } 295 } 296 } 297 return tc; 299 } 300 301 312 313 public static void defaultAction(NodeInfo node, 314 ParameterSet parameters, 315 ParameterSet tunnelParams, 316 XPathContext context, 317 boolean backwardsCompatible, 318 int locationId) throws XPathException { 319 switch(node.getNodeKind()) { 320 case Type.DOCUMENT: 321 case Type.ELEMENT: 322 SequenceIterator iter = node.iterateAxis(Axis.CHILD); 323 XPathContextMajor c2 = context.newContext(); 324 c2.setOrigin(builtInDetails); 325 TailCall tc = applyTemplates( 326 iter, context.getCurrentMode(), parameters, tunnelParams, c2, backwardsCompatible, locationId); 327 while (tc != null) { 328 tc = tc.processLeavingTail(c2); 329 } 330 return; 331 case Type.TEXT: 332 case Type.ATTRIBUTE: 335 context.getReceiver().characters(node.getStringValueCS(), locationId, 0); 336 return; 337 case Type.COMMENT: 338 case Type.PROCESSING_INSTRUCTION: 339 case Type.NAMESPACE: 340 return; 342 } 343 } 344 345 348 349 private static InstructionDetails builtInDetails = new InstructionDetails(); 350 static { 351 builtInDetails.setConstructType(Location.BUILT_IN_TEMPLATE); 352 } 353 354 359 360 public Iterator iterateSubExpressions() { 361 ArrayList list = new ArrayList (10); 362 list.add(select); 363 WithParam.getXPathExpressions(actualParams, list); 364 WithParam.getXPathExpressions(tunnelParams, list); 365 return list.iterator(); 366 } 367 368 373 374 protected void promoteInst(PromotionOffer offer) throws XPathException { 375 select = doPromotion(select, offer); 376 WithParam.promoteParams(actualParams, offer); 377 WithParam.promoteParams(tunnelParams, offer); 378 } 379 380 387 388 public void display(int level, NamePool pool, PrintStream out) { 389 out.println(ExpressionTool.indent(level) + "apply-templates " + "select="); 390 select.display(level+1, pool, out); 391 } 392 393 399 400 private static class ApplyTemplatesPackage implements TailCall { 401 402 private ValueRepresentation selectedNodes; 403 private Mode mode; 404 private ParameterSet params; 405 private ParameterSet tunnelParams; 406 private XPathContextMajor evaluationContext; 407 private int locationId; 408 409 ApplyTemplatesPackage(ValueRepresentation selectedNodes, 410 Mode mode, 411 ParameterSet params, 412 ParameterSet tunnelParams, 413 XPathContextMajor context, 414 int locationId 415 ) { 416 this.selectedNodes = selectedNodes; 417 this.mode = mode; 418 this.params = params; 419 this.tunnelParams = tunnelParams; 420 this.evaluationContext = context; 421 this.locationId = locationId; 422 } 423 424 public TailCall processLeavingTail(XPathContext context) throws XPathException { 425 TailCall tc = applyTemplates( 426 Value.getIterator(selectedNodes), mode, params, tunnelParams, evaluationContext, false, locationId); 427 return tc; 428 } 429 } 430 431 } 432 433 | Popular Tags |