1 package net.sf.saxon.style; 2 import net.sf.saxon.expr.*; 3 import net.sf.saxon.instruct.*; 4 import net.sf.saxon.om.*; 5 import net.sf.saxon.pattern.NodeKindTest; 6 import net.sf.saxon.trans.XPathException; 7 import net.sf.saxon.type.ItemType; 8 import net.sf.saxon.type.Type; 9 import net.sf.saxon.value.Cardinality; 10 import net.sf.saxon.value.EmptySequence; 11 import net.sf.saxon.value.SequenceType; 12 import net.sf.saxon.value.StringValue; 13 14 17 18 public abstract class XSLGeneralVariable extends StyleElement { 19 20 protected Expression select = null; 21 protected SequenceType requiredType = null; 22 protected String constantText = null; 23 protected boolean global; 24 protected SlotManager slotManager = null; protected boolean assignable = false; 26 protected boolean redundant = false; 27 protected boolean requiredParam = false; 28 protected boolean tunnel = false; 29 private boolean textonly; 30 31 38 39 protected ItemType getReturnedItemType() { 40 return null; 41 } 42 46 47 public boolean mayContainSequenceConstructor() { 48 return true; 49 } 50 51 protected boolean allowsAsAttribute() { 52 return true; 53 } 54 55 protected boolean allowsTunnelAttribute() { 56 return false; 57 } 58 59 protected boolean allowsValue() { 60 return true; 61 } 62 63 protected boolean allowsRequired() { 64 return false; 65 } 66 67 72 73 public boolean isAssignable() { 74 return assignable; 75 } 76 77 public boolean isTunnelParam() { 78 return tunnel; 79 } 80 81 public boolean isRequiredParam() { 82 return requiredParam; 83 } 84 85 public boolean isGlobal() { 86 return isTopLevel(); 87 } 89 90 93 94 public String getVariableName() { 95 return getAttributeValue(StandardNames.NAME); 96 } 97 98 101 102 public void setRedundant() { 103 redundant = true; 104 } 105 106 109 110 public int getVariableFingerprint() { 111 112 117 if (getObjectNameCode()==-1) { 118 String nameAttribute = getAttributeValue(StandardNames.NAME); 119 if (nameAttribute==null) { 120 return -1; } 122 try { 123 setObjectNameCode(makeNameCode(nameAttribute.trim())); 124 } catch (NamespaceException err) { 125 setObjectNameCode(-1); 126 } catch (XPathException err) { 127 setObjectNameCode(-1); 128 } 129 } 130 return getObjectFingerprint(); 131 } 132 133 public void prepareAttributes() throws XPathException { 134 135 getVariableFingerprint(); 136 137 AttributeCollection atts = getAttributeList(); 138 139 String selectAtt = null; 140 String assignAtt = null; 141 String nameAtt = null; 142 String asAtt = null; 143 String requiredAtt = null; 144 String tunnelAtt = null; 145 146 for (int a=0; a<atts.getLength(); a++) { 147 int nc = atts.getNameCode(a); 148 String f = getNamePool().getClarkName(nc); 149 if (f==StandardNames.NAME) { 150 nameAtt = atts.getValue(a).trim(); 151 } else if (f==StandardNames.SELECT) { 152 selectAtt = atts.getValue(a); 153 } else if (f==StandardNames.AS && allowsAsAttribute()) { 154 asAtt = atts.getValue(a); 155 } else if (f==StandardNames.REQUIRED && allowsRequired()) { 156 requiredAtt = atts.getValue(a).trim(); 157 } else if (f==StandardNames.TUNNEL && allowsTunnelAttribute()) { 158 tunnelAtt = atts.getValue(a).trim(); 159 } else if (f==StandardNames.SAXON_ASSIGNABLE && this instanceof XSLVariableDeclaration) { 160 assignAtt = atts.getValue(a).trim(); 161 } else { 162 checkUnknownAttribute(nc); 163 } 164 } 165 166 if (nameAtt==null) { 167 reportAbsence("name"); 168 } else { 169 try { 170 setObjectNameCode(makeNameCode(nameAtt.trim())); 171 } catch (NamespaceException err) { 172 compileError(err.getMessage()); 173 } catch (XPathException err) { 174 compileError(err); 175 } 176 } 177 178 if (selectAtt!=null) { 179 if (!allowsValue()) { 180 compileError("Function parameters cannot have a default value", "XTSE0760"); 181 } 182 select = makeExpression(selectAtt); 183 } 184 185 if (assignAtt!=null && assignAtt.equals("yes")) { 186 assignable=true; 187 } 188 189 if (requiredAtt!=null) { 190 if (requiredAtt.equals("yes")) { 191 requiredParam = true; 192 } else if (requiredAtt.equals("no")) { 193 requiredParam = false; 194 } else { 195 compileError("The attribute 'required' must be set to 'yes' or 'no'", "XTSE0020"); 196 } 197 } 198 199 if (tunnelAtt!=null) { 200 if (tunnelAtt.equals("yes")) { 201 tunnel = true; 202 } else if (tunnelAtt.equals("no")) { 203 tunnel = false; 204 } else { 205 compileError("The attribute 'tunnel' must be set to 'yes' or 'no'", "XTSE0020"); 206 } 207 } 208 209 if (asAtt!=null) { 210 requiredType = makeSequenceType(asAtt); 211 } 212 } 213 214 public void validate() throws XPathException { 215 global = isTopLevel(); 216 217 if (global) { 218 slotManager = getConfiguration().makeSlotManager(); 219 } 220 if (select!=null && hasChildNodes()) { 221 compileError("An " + getDisplayName() + " element with a select attribute must be empty", "XTSE0620"); 222 } 223 224 if (assignable && !global) { 225 compileError("saxon:assignable='yes' is no longer permitted for local variables"); 226 } 227 228 checkAgainstRequiredType(requiredType); 229 230 if (select==null && allowsValue()) { 231 textonly = true; 232 AxisIterator kids = iterateAxis(Axis.CHILD); 233 NodeInfo first = (NodeInfo)kids.next(); 234 if (first == null) { 235 if (requiredType == null) { 236 select = StringValue.EMPTY_STRING; 237 } else { 238 if (this instanceof XSLParam) { 239 if (!requiredParam) { 240 if (Cardinality.allowsZero(requiredType.getCardinality())) { 241 select = EmptySequence.getInstance(); 242 } else { 243 requiredParam = true; 246 } 247 } 248 } else { 249 if (Cardinality.allowsZero(requiredType.getCardinality())) { 250 select = EmptySequence.getInstance(); 251 } else { 252 compileError("The implicit value () is not valid for the declared type", "XTTE0570"); 253 } 254 } 255 } 256 } else { 257 if (kids.next() == null) { 258 if (first.getNodeKind() == Type.TEXT) { 260 constantText = first.getStringValue(); 262 } 263 } 264 265 textonly = (getCommonChildItemType() == NodeKindTest.TEXT); 267 } 268 } 269 select = typeCheck("select", select); 270 } 271 272 277 278 protected void checkAgainstRequiredType(SequenceType required) 279 throws XPathException { 280 try { 281 282 if (required!=null) { 283 if (select != null) { 285 RoleLocator role = new RoleLocator(RoleLocator.VARIABLE, getVariableName(), 0, null); 286 role.setSourceLocator(new ExpressionLocation(this)); 287 role.setErrorCode("XTTE0570"); 288 select = TypeChecker.staticTypeCheck(select, required, false, role, getStaticContext()); 289 } else { 290 } 292 } 293 } catch (XPathException err) { 294 err.setLocator(this); compileError(err); 296 select = new ErrorExpression(err); 297 } 298 } 299 300 303 304 protected void initializeInstruction(Executable exec, GeneralVariable var) 305 throws XPathException { 306 307 var.init(select, getObjectNameCode()); 308 var.setAssignable(assignable); 309 var.setRequiredParam(requiredParam); 310 var.setRequiredType(requiredType); 311 var.setTunnel(tunnel); 312 313 if (hasChildNodes()) { 316 if (requiredType==null) { 317 DocumentInstr doc = new DocumentInstr(textonly, constantText, getBaseURI()); 318 doc.setParentExpression(var); 319 Expression b = compileSequenceConstructor(exec, iterateAxis(Axis.CHILD), true); 320 if (b == null) { 321 b = EmptySequence.getInstance(); 322 } 323 doc.setContentExpression(b); 324 select = doc; 325 var.setSelectExpression(doc); 326 } else { 327 select = compileSequenceConstructor(exec, iterateAxis(Axis.CHILD), true); 328 if (select == null) { 329 select = EmptySequence.getInstance(); 330 } 331 try { 332 if (requiredType != null) { 333 RoleLocator role = 334 new RoleLocator(RoleLocator.VARIABLE, getVariableName(), 0, null); 335 role.setErrorCode("XTTE0570"); 336 role.setSourceLocator(new ExpressionLocation(this)); 337 select = select.simplify(getStaticContext()); 338 select = TypeChecker.staticTypeCheck(select, requiredType, false, role, getStaticContext()); 339 } 340 } catch (XPathException err) { 341 err.setLocator(this); 342 compileError(err); 343 select = new ErrorExpression(err); 344 } 345 var.setSelectExpression(select); 346 } 347 } 348 if (global) { 349 Expression exp2 = select; 350 if (exp2 != null) { 351 try { 352 exp2 = select.simplify(staticContext).typeCheck(staticContext, Type.NODE_TYPE); 353 exp2 = exp2.optimize(getConfiguration().getOptimizer(), staticContext, Type.NODE_TYPE); 354 } catch (XPathException err) { 355 compileError(err); 356 } 357 358 if (getConfiguration().getTraceListener() != null) { 359 TraceWrapper trace = new TraceInstruction(exp2, this); 360 trace.setLocationId(allocateLocationId(getSystemId(), getLineNumber())); 361 exp2 = trace; 362 } 363 364 allocateSlots(exp2); 365 } 366 if (slotManager != null && slotManager.getNumberOfVariables() > 0) { 367 ((GlobalVariable)var).setContainsLocals(slotManager); 368 } 369 exec.registerGlobalVariable(var); 370 if (exp2 != select) { 371 var.setSelectExpression(exp2); 372 } 373 } 374 } 375 376 381 382 public int getConstructType() { 383 return StandardNames.XSL_VARIABLE; 384 } 385 386 } 387 388 | Popular Tags |