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.trans.DynamicError; 8 import net.sf.saxon.trans.XPathException; 9 import net.sf.saxon.type.ItemType; 10 11 import java.io.PrintStream ; 12 import java.util.ArrayList ; 13 import java.util.Iterator ; 14 15 18 19 public class CallTemplate extends Instruction { 20 21 private Template template = null; 22 private WithParam[] actualParams = null; 23 private WithParam[] tunnelParams = null; 24 private boolean useTailRecursion = false; 25 private Expression calledTemplateExpression; private NamespaceResolver nsContext; 28 38 39 public CallTemplate ( Template template, 40 boolean useTailRecursion, 41 Expression calledTemplateExpression, 42 NamespaceResolver nsContext ) { 43 44 this.template = template; 45 this.useTailRecursion = useTailRecursion; 46 this.calledTemplateExpression = calledTemplateExpression; 47 this.nsContext = nsContext; 48 adoptChildExpression(calledTemplateExpression); 49 } 50 51 54 55 public void setActualParameters( 56 WithParam[] actualParams, 57 WithParam[] tunnelParams ) { 58 this.actualParams = actualParams; 59 this.tunnelParams = tunnelParams; 60 for (int i=0; i<actualParams.length; i++) { 61 adoptChildExpression(actualParams[i]); 62 } 63 for (int i=0; i<tunnelParams.length; i++) { 64 adoptChildExpression(tunnelParams[i]); 65 } 66 } 67 68 71 72 public int getInstructionNameCode() { 73 return StandardNames.XSL_CALL_TEMPLATE; 74 } 75 76 80 81 public InstructionInfo getInstructionInfo() { 82 InstructionDetails details = (InstructionDetails)super.getInstructionInfo(); 83 if (template != null) { 84 details.setProperty("template", template); 85 } 86 return details; 87 } 88 89 97 98 public Expression simplify(StaticContext env) throws XPathException { 99 WithParam.simplify(actualParams, env); 100 WithParam.simplify(tunnelParams, env); 101 if (calledTemplateExpression != null) { 102 calledTemplateExpression = calledTemplateExpression.simplify(env); 103 } 104 return this; 105 } 106 107 public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException { 108 WithParam.typeCheck(actualParams, env, contextItemType); 109 WithParam.typeCheck(tunnelParams, env, contextItemType); 110 if (calledTemplateExpression != null) { 111 calledTemplateExpression = calledTemplateExpression.typeCheck(env, contextItemType); 112 adoptChildExpression(calledTemplateExpression); 113 } 114 return this; 115 } 116 117 public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException { 118 WithParam.optimize(opt, actualParams, env, contextItemType); 119 WithParam.optimize(opt, tunnelParams, env, contextItemType); 120 if (calledTemplateExpression != null) { 121 calledTemplateExpression = calledTemplateExpression.optimize(opt, env, contextItemType); 122 adoptChildExpression(calledTemplateExpression); 123 } 124 return this; 125 } 126 127 public int getIntrinsicDependencies() { 128 return StaticProperty.DEPENDS_ON_XSLT_CONTEXT | 131 StaticProperty.DEPENDS_ON_FOCUS; 132 } 133 134 138 139 public final boolean createsNewNodes() { 140 return true; 141 } 142 143 148 149 public Iterator iterateSubExpressions() { 150 ArrayList list = new ArrayList (10); 151 if (calledTemplateExpression != null) { 152 list.add(calledTemplateExpression); 153 } 154 WithParam.getXPathExpressions(actualParams, list); 155 WithParam.getXPathExpressions(tunnelParams, list); 156 return list.iterator(); 157 } 158 159 164 165 protected void promoteInst(PromotionOffer offer) throws XPathException { 166 if (calledTemplateExpression != null) { 167 calledTemplateExpression = doPromotion(calledTemplateExpression, offer); 168 } 169 WithParam.promoteParams(actualParams, offer); 170 WithParam.promoteParams(tunnelParams, offer); 171 } 172 173 178 179 public void process(XPathContext context) throws XPathException { 180 181 Template t = getTargetTemplate(context); 182 XPathContextMajor c2 = context.newContext(); 183 c2.setOrigin(this); 184 c2.openStackFrame(t.getStackFrameMap()); 185 c2.setLocalParameters(assembleParams(context, actualParams)); 186 c2.setTunnelParameters(assembleTunnelParams(context, tunnelParams)); 187 188 try { 189 TailCall tc = t.expand(c2); 190 while (tc != null) { 191 tc = tc.processLeavingTail(c2); 192 } 193 } catch (StackOverflowError e) { 194 DynamicError err = new DynamicError( 195 "Too many nested template or function calls. The stylesheet is probably looping."); 196 err.setLocator(this); 197 err.setXPathContext(context); 198 throw err; 199 } 200 } 201 202 210 211 public TailCall processLeavingTail(XPathContext context) throws XPathException 212 { 213 if (!useTailRecursion) { 214 process(context); 215 return null; 216 } 217 218 220 Template target = getTargetTemplate(context); 221 222 224 ParameterSet params = assembleParams(context, actualParams); 225 ParameterSet tunnels = assembleTunnelParams(context, tunnelParams); 226 227 230 if (params==null) { params = ParameterSet.EMPTY_PARAMETER_SET; 233 } 234 235 StackFrame frame = context.getStackFrame(); 237 ValueRepresentation[] vars = frame.getStackFrameValues(); 238 for (int i=0; i<vars.length; i++) { 239 vars[i] = null; 240 } 241 242 return new CallTemplatePackage(target, params, tunnels, context); 243 } 244 245 253 254 public Template getTargetTemplate(XPathContext context) throws XPathException { 255 if (calledTemplateExpression != null) { 256 Controller controller = context.getController(); 257 String qname = calledTemplateExpression.evaluateAsString(context); 258 259 String prefix; 260 String localName; 261 try { 262 String [] parts = Name.getQNameParts(qname); 263 prefix = parts[0]; 264 localName = parts[1]; 265 } catch (QNameException err) { 266 throw dynamicError("Invalid template name. " + err.getMessage(), controller); 267 } 268 String uri = nsContext.getURIForPrefix(prefix, false); 269 if (uri==null) { 270 throw dynamicError("Namespace prefix " + prefix + " has not been declared", controller); 271 } 272 int fprint = controller.getNamePool().getFingerprint(uri, localName); 273 Template target = controller.getExecutable().getNamedTemplate(fprint); 274 if (target==null) { 275 throw dynamicError("Template " + qname + " has not been defined", controller); 276 } 277 return target; 278 } else { 279 return template; 280 } 281 } 282 283 290 291 public void display(int level, NamePool pool, PrintStream out) { 292 out.println(ExpressionTool.indent(level) + "call-template"); 293 } 294 295 301 302 private class CallTemplatePackage implements TailCall { 303 304 private Template target; 305 private ParameterSet params; 306 private ParameterSet tunnelParams; 307 private XPathContext evaluationContext; 308 309 317 318 public CallTemplatePackage(Template template, 319 ParameterSet params, 320 ParameterSet tunnelParams, 321 XPathContext evaluationContext) { 322 this.target = template; 323 this.params = params; 324 this.tunnelParams = tunnelParams; 325 this.evaluationContext = evaluationContext; 326 } 327 328 337 338 public TailCall processLeavingTail(XPathContext context) throws XPathException { 339 XPathContextMajor c2 = evaluationContext.newContext(); 344 c2.setOrigin(CallTemplate.this); 345 c2.setLocalParameters(params); 346 c2.setTunnelParameters(tunnelParams); 347 c2.openStackFrame(target.getStackFrameMap()); 348 349 351 TailCall tc = target.expand(c2); 352 return tc; 353 } 354 } 355 356 } 357 358 | Popular Tags |