1 package net.sf.saxon.style; 2 import net.sf.saxon.Err; 3 import net.sf.saxon.expr.Expression; 4 import net.sf.saxon.expr.ExpressionTool; 5 import net.sf.saxon.instruct.CallTemplate; 6 import net.sf.saxon.instruct.Executable; 7 import net.sf.saxon.instruct.Template; 8 import net.sf.saxon.om.*; 9 import net.sf.saxon.trans.XPathException; 10 import net.sf.saxon.type.AnyItemType; 11 import net.sf.saxon.type.ItemType; 12 import net.sf.saxon.type.Type; 13 import net.sf.saxon.value.SequenceType; 14 import net.sf.saxon.value.Whitespace; 15 16 import java.util.List ; 17 18 21 22 public class XSLCallTemplate extends StyleElement { 23 24 private int calledTemplateFingerprint = -1; private XSLTemplate template = null; 26 private boolean useTailRecursion = false; 27 private String calledTemplateName = null; private Expression calledTemplateExpression; 30 33 34 protected boolean allowAVT() { 35 return false; 36 } 37 38 42 43 public boolean isInstruction() { 44 return true; 45 } 46 47 52 53 protected ItemType getReturnedItemType() { 54 if (template==null) { 55 return AnyItemType.getInstance(); 56 } else { 57 return template.getReturnedItemType(); 58 } 59 } 60 61 public void prepareAttributes() throws XPathException { 62 63 AttributeCollection atts = getAttributeList(); 64 65 String nameAttribute = null; 66 67 for (int a=0; a<atts.getLength(); a++) { 68 int nc = atts.getNameCode(a); 69 String f = getNamePool().getClarkName(nc); 70 if (f==StandardNames.NAME) { 71 nameAttribute = atts.getValue(a).trim(); 72 } else { 73 checkUnknownAttribute(nc); 74 } 75 } 76 77 if (nameAttribute==null) { 78 reportAbsence("name"); 79 return; 80 } 81 82 if (allowAVT() && nameAttribute.indexOf('{')>=0) { 83 calledTemplateExpression = makeAttributeValueTemplate(nameAttribute); 84 } else { 85 calledTemplateName = nameAttribute; 86 try { 87 calledTemplateFingerprint = 88 makeNameCode(nameAttribute.trim()) & 0xfffff; 89 } catch (NamespaceException err) { 90 compileError(err.getMessage(), "XTSE0280"); 91 } catch (XPathException err) { 92 compileError(err.getMessage(), "XTSE0280"); 93 } 94 } 95 } 96 97 public void validate() throws XPathException { 98 checkWithinTemplate(); 99 100 AxisIterator kids = iterateAxis(Axis.CHILD); 101 while (true) { 102 NodeInfo child = (NodeInfo)kids.next(); 103 if (child == null) { 104 break; 105 } 106 if (child instanceof XSLWithParam) { 107 } else if (child instanceof XSLFallback && mayContainFallback()) { 109 } else if (child.getNodeKind() == Type.TEXT) { 111 if (!Whitespace.isWhite(child.getStringValueCS())) { 113 compileError("No character data is allowed within xsl:call-template", "XTSE0010"); 114 } 115 } else { 116 compileError("Child element " + Err.wrap(child.getDisplayName(), Err.ELEMENT) + 117 " is not allowed within xsl:call-template", "XTSE0010"); 118 } 119 } 120 if (calledTemplateExpression==null) { 121 template = findTemplate(calledTemplateFingerprint); 122 if (template==null) { 123 return; 124 } 125 } 126 calledTemplateExpression = typeCheck("name", calledTemplateExpression); 127 } 128 129 public void postValidate() throws XPathException { 130 133 if (template != null) { 134 AxisIterator declaredParams = template.iterateAxis(Axis.CHILD); 135 while(true) { 136 NodeInfo param = (NodeInfo)declaredParams.next(); 137 if (param == null) { 138 break; 139 } 140 if (param instanceof XSLParam && ((XSLParam)param).isRequiredParam() 141 && !((XSLParam)param).isTunnelParam()) { 142 AxisIterator actualParams = iterateAxis(Axis.CHILD); 143 boolean ok = false; 144 while(true) { 145 NodeInfo withParam = (NodeInfo)actualParams.next(); 146 if (withParam == null) { 147 break; 148 } 149 if (withParam instanceof XSLWithParam && 150 ((XSLWithParam)withParam).getVariableFingerprint() == 151 ((XSLParam)param).getVariableFingerprint()) { 152 ok = true; 153 break; 154 } 155 } 156 if (!ok) { 157 compileError("No value supplied for required parameter " + 158 Err.wrap(((XSLParam)param).getVariableName(), Err.VARIABLE), "XTSE0690"); 159 } 160 } 161 } 162 163 164 167 AxisIterator actualParams = iterateAxis(Axis.CHILD); 168 while(true) { 169 NodeInfo w = (NodeInfo)actualParams.next(); 170 if (w == null) { 171 break; 172 } 173 if (w instanceof XSLWithParam && !((XSLWithParam)w).isTunnelParam()) { 174 XSLWithParam withParam = (XSLWithParam)w; 175 AxisIterator formalParams = template.iterateAxis(Axis.CHILD); 176 boolean ok = false; 177 while(true) { 178 NodeInfo param = (NodeInfo)formalParams.next(); 179 if (param == null) { 180 break; 181 } 182 if (param instanceof XSLParam && 183 ((XSLParam)param).getVariableFingerprint() == 184 withParam.getVariableFingerprint()) { 185 ok = true; 186 SequenceType required = ((XSLParam)param).getRequiredType(); 187 withParam.checkAgainstRequiredType(required); 188 break; 189 } 190 } 191 if (!ok) { 192 if (!backwardsCompatibleModeIsEnabled()) { 193 compileError("Parameter " + 194 withParam.getVariableName() + 195 " is not declared in the called template", "XTSE0680"); 196 } 197 } 198 } 199 } 200 } 201 } 202 203 private XSLTemplate findTemplate(int fingerprint) 204 throws XPathException { 205 206 XSLStylesheet stylesheet = getPrincipalStylesheet(); 207 List toplevel = stylesheet.getTopLevel(); 208 209 212 for (int i=toplevel.size()-1; i>=0; i--) { 213 if (toplevel.get(i) instanceof XSLTemplate) { 214 XSLTemplate t = (XSLTemplate)toplevel.get(i); 215 if (t.getTemplateFingerprint() == fingerprint) { 216 return t; 217 } 218 } 219 } 220 compileError("No template exists named " + calledTemplateName, "XTSE0650"); 221 return null; 222 } 223 224 228 229 public void markTailCalls() { 230 useTailRecursion = true; 231 } 232 233 234 public Expression compile(Executable exec) throws XPathException { 235 Template target = null; 236 NamespaceResolver nsContext = null; 237 238 if (calledTemplateExpression==null) { 239 if (template==null) { 240 return null; } 242 target = template.getCompiledTemplate(); 243 } else { 244 nsContext = makeNamespaceContext(); 246 } 247 248 CallTemplate call = new CallTemplate ( 249 target, 250 useTailRecursion, 251 calledTemplateExpression, 252 nsContext ); 253 call.setActualParameters(getWithParamInstructions(exec, false, call), 254 getWithParamInstructions(exec, true, call)); 255 ExpressionTool.makeParentReferences(call); 256 return call; 257 } 258 259 } 260 261 | Popular Tags |