1 package net.sf.saxon.expr; 2 3 import net.sf.saxon.event.LocationProvider; 4 import net.sf.saxon.instruct.Executable; 5 import net.sf.saxon.instruct.Instruction; 6 import net.sf.saxon.instruct.InstructionDetails; 7 import net.sf.saxon.om.Item; 8 import net.sf.saxon.om.SequenceIterator; 9 import net.sf.saxon.om.SingletonIterator; 10 import net.sf.saxon.trace.InstructionInfo; 11 import net.sf.saxon.trace.InstructionInfoProvider; 12 import net.sf.saxon.trace.Location; 13 import net.sf.saxon.trans.DynamicError; 14 import net.sf.saxon.trans.XPathException; 15 import net.sf.saxon.type.SchemaType; 16 import net.sf.saxon.value.AtomicValue; 17 import net.sf.saxon.value.Cardinality; 18 import net.sf.saxon.value.StringValue; 19 20 import javax.xml.transform.SourceLocator ; 21 import java.io.Serializable ; 22 import java.util.*; 23 24 44 45 public abstract class ComputedExpression 46 implements Serializable , Expression, InstructionInfoProvider, Container { 47 48 protected int staticProperties = -1; 49 protected int locationId = -1; 50 private Container parentExpression; 51 52 55 private int[] slotsUsed; 56 57 65 66 public Container getParentExpression() { 67 return parentExpression; 68 } 69 70 public void setParentExpression(Container parent) { 71 if (this == parent) { 72 throw new AssertionError ("Incestuous relationship!"); 73 } 74 parentExpression = parent; 75 } 76 77 public void adoptChildExpression(Expression child) { 78 if (child instanceof ComputedExpression) { 79 ComputedExpression cc = (ComputedExpression)child; 80 if (cc.getParentExpression() == this) { 81 return; 82 } 83 cc.setParentExpression(this); 84 if (this.locationId == -1) { 85 ExpressionTool.copyLocationInfo(child, this); 86 } else if (((ComputedExpression)child).locationId == -1) { 87 ExpressionTool.copyLocationInfo(this, child); 88 } 89 } 90 if (staticProperties != -1) { 91 resetStaticProperties(); 92 } 93 } 94 95 99 100 public int getImplementationMethod() { 101 if (Cardinality.allowsMany(getCardinality())) { 102 return ITERATE_METHOD; 103 } else { 104 return EVALUATE_METHOD; 105 } 106 } 107 108 111 112 public void setLocationId(int id) { 113 locationId = id; 114 } 115 116 119 120 public final int getLocationId() { 121 return locationId; 122 } 123 124 127 128 public int getLineNumber() { 129 if (locationId == -1) { 130 if (parentExpression != null) { 131 return parentExpression.getLineNumber(); 132 } else { 133 return -1; 134 } 135 } 136 return locationId & 0xfffff; 137 } 138 139 142 143 public int getColumnNumber() { 144 return -1; 145 } 146 147 150 151 public String getSystemId() { 152 if (locationId == -1) { 153 if (parentExpression != null) { 154 return parentExpression.getSystemId(); 155 } else { 156 return null; 157 } 158 } 159 Executable exec = getExecutable(); 160 if (exec == null) { 161 if (parentExpression == null) { 162 return null; 163 } 164 if (parentExpression instanceof LocationProvider) { 165 return ((LocationProvider)parentExpression).getSystemId(locationId); 166 } 167 return parentExpression.getSystemId(); 168 } 169 return exec.getLocationMap().getSystemId(locationId); 170 } 171 172 175 176 public final String getPublicId() { 177 return null; 178 } 179 180 183 184 public Executable getExecutable() { 185 Container container = getParentExpression(); 186 if (container == null) { 187 return null; 188 } if (container == this) { 189 throw new IllegalStateException ("Expression cannot contain itself"); 190 } else { 191 return container.getExecutable(); 192 } 193 } 194 195 198 199 public LocationProvider getLocationProvider() { 200 Executable exec = getExecutable(); 201 if (exec != null) { 202 return exec.getLocationMap(); 203 } else if (getParentExpression() instanceof LocationProvider) { 204 return ((LocationProvider)getParentExpression()); 205 } else { 206 return null; 207 } 208 } 209 210 218 219 public Expression simplify(StaticContext env) throws XPathException { 220 return this; 221 } 222 223 238 239 public Expression promote(PromotionOffer offer) throws XPathException { 240 return this; 246 } 247 248 252 253 public final Expression doPromotion(Expression subexpression, PromotionOffer offer) throws XPathException { 254 Expression e = subexpression.promote(offer); 255 if (e != subexpression) { 256 adoptChildExpression(e); 257 resetStaticProperties(); 258 } 259 return e; 260 } 261 262 269 270 public final int getSpecialProperties() { 271 if (staticProperties == -1) { 272 computeStaticProperties(); 273 } 274 return staticProperties & StaticProperty.SPECIAL_PROPERTY_MASK; 275 } 276 277 281 282 public final void computeStaticProperties() { 283 staticProperties = 284 computeDependencies() | 285 computeCardinality() | 286 computeSpecialProperties(); 287 } 288 289 293 294 public final void resetStaticProperties() { 295 staticProperties = -1; 296 if (parentExpression instanceof ComputedExpression) { 297 ((ComputedExpression)parentExpression).resetStaticProperties(); 298 } 299 } 300 301 protected abstract int computeCardinality(); 302 303 public int computeSpecialProperties() { 304 return 0; 305 } 306 307 318 319 public int getCardinality() { 320 if (staticProperties == -1) { 321 computeStaticProperties(); 322 } 323 return staticProperties & StaticProperty.CARDINALITY_MASK; 324 } 325 326 327 339 340 public int getDependencies() { 341 if (staticProperties == -1) { 344 computeStaticProperties(); 345 } 346 return staticProperties & StaticProperty.DEPENDENCY_MASK; 347 } 348 349 357 358 public int computeDependencies() { 359 int dependencies = (short) getIntrinsicDependencies(); 360 for (Iterator children = iterateSubExpressions(); children.hasNext();) { 361 dependencies |= (short) ((Expression)children.next()).getDependencies(); 362 } 363 return dependencies; 364 } 365 366 375 376 public int getIntrinsicDependencies() { 377 return 0; 378 } 379 380 381 387 388 public Iterator iterateSubExpressions() { 389 return Collections.EMPTY_LIST.iterator(); 390 } 391 392 399 400 public void checkPermittedContents(SchemaType parentType, StaticContext env, boolean whole) throws XPathException { 401 return; 402 } 403 404 410 411 public boolean markTailFunctionCalls() { 412 return false; 413 } 414 415 419 420 public int[] getSlotsUsed() { 421 if (slotsUsed != null) { 422 return slotsUsed; 423 } 424 Set slots = new HashSet(10); 425 gatherSlotsUsed(this, slots); 426 slotsUsed = new int[slots.size()]; 427 int i=0; 428 Iterator iter = slots.iterator(); 429 while (iter.hasNext()) { 430 Integer islot = (Integer )iter.next(); 431 slotsUsed[i++] = islot.intValue(); 432 } 433 Arrays.sort(slotsUsed); 434 return slotsUsed; 435 } 436 437 private static void gatherSlotsUsed(Expression exp, Set slots) { 438 if (exp instanceof VariableReference) { 439 Binding binding = ((VariableReference)exp).getBinding(); 440 if (!binding.isGlobal()) { 441 int slot = binding.getLocalSlotNumber(); 442 if (slot != -1) { 443 Integer islot = new Integer (slot); 444 if (!slots.contains(islot)) { 445 slots.add(islot); 446 } 447 } 448 } 449 } else { 450 Iterator iter = exp.iterateSubExpressions(); 451 while (iter.hasNext()) { 452 Expression sub = (Expression)iter.next(); 453 gatherSlotsUsed(sub, slots); 454 } 455 } 456 } 457 458 472 473 public Item evaluateItem(XPathContext context) throws XPathException { 474 return iterate(context).next(); 475 } 476 477 493 494 public String evaluateAsString(XPathContext context) throws XPathException { 495 Item o = evaluateItem(context); 496 if (o instanceof AtomicValue && !((AtomicValue)o).hasBuiltInType()) { 497 o = ((AtomicValue) o).getPrimitiveValue(); 498 } 499 StringValue value = (StringValue) o; if (value == null) return ""; 501 return value.getStringValue(); 502 } 503 504 517 518 public SequenceIterator iterate(XPathContext context) throws XPathException { 519 Item value = evaluateItem(context); 520 return SingletonIterator.makeIterator(value); 521 } 522 523 524 534 535 public boolean effectiveBooleanValue(XPathContext context) throws XPathException { 536 return ExpressionTool.effectiveBooleanValue(iterate(context)); 537 } 538 539 544 545 public void process(XPathContext context) throws XPathException { 546 int m = getImplementationMethod(); 547 548 if ((m & EVALUATE_METHOD) != 0) { 549 Item item = evaluateItem(context); 550 Instruction.appendItem(item, context.getReceiver(), locationId); 552 553 } else if ((m & ITERATE_METHOD) != 0) { 554 555 SequenceIterator iter = iterate(context); 556 try { 557 while (true) { 558 Item it = iter.next(); 559 if (it == null) break; 560 Instruction.appendItem(it, context.getReceiver(), locationId); 562 } 563 } catch (XPathException e) { 564 if (e.getLocator() == null) { 565 e.setLocator(this); 566 } 567 throw e; 568 } 569 570 } else { 571 dynamicError("process() is not implemented in the subclass " + this.getClass(), context); 572 } 573 } 574 575 576 579 580 protected void dynamicError(String message, XPathContext context) throws DynamicError { 581 DynamicError err = new DynamicError(message, getSourceLocator()); 582 err.setXPathContext(context); 583 throw err; 584 } 585 586 589 590 protected void dynamicError(String message, String code, XPathContext context) throws DynamicError { 591 DynamicError err = new DynamicError(message, getSourceLocator()); 592 err.setXPathContext(context); 593 err.setErrorCode(code); 594 throw err; 595 } 596 597 600 601 protected void typeError(String message, XPathContext context) throws DynamicError { 602 DynamicError e = new DynamicError(message, getSourceLocator()); 603 e.setIsTypeError(true); 604 e.setXPathContext(context); 605 throw e; 606 } 607 608 611 612 protected void typeError(String message, String errorCode, XPathContext context) throws DynamicError { 613 DynamicError e = new DynamicError(message, getSourceLocator()); 614 e.setIsTypeError(true); 615 e.setErrorCode(errorCode); 616 e.setXPathContext(context); 617 throw e; 618 } 619 620 623 624 private SourceLocator getSourceLocator() { 625 return ExpressionTool.getLocator(this); 626 } 627 628 631 632 public InstructionInfo getInstructionInfo() { 633 InstructionDetails details = new InstructionDetails(); 634 details.setConstructType(getConstructType()); 635 details.setProperty("expression", this); 636 details.setSystemId(getSystemId()); 637 details.setLineNumber(getLineNumber()); 638 details.setColumnNumber(getColumnNumber()); 639 if (this instanceof Assignation) { 640 details.setObjectNameCode(((Assignation)this).getVariableNameCode()); 641 } 642 return details; 643 } 644 645 649 650 protected int getConstructType() { 651 return Location.XPATH_EXPRESSION; 652 } 653 654 657 658 public boolean hasBadParentPointer() { 659 Iterator iter = iterateSubExpressions(); 660 while (iter.hasNext()) { 661 Expression exp = (Expression)iter.next(); 662 if (exp instanceof ComputedExpression) { 663 if (this != exp.getParentExpression()) { 664 System.err.println("Bad parent pointer to " + exp.getParentExpression() + " found in " + exp); 665 return true; 666 } 667 if (((ComputedExpression)exp).hasBadParentPointer()) { 668 System.err.println("Found in "+ exp); 669 return true; 670 } 671 } 672 } 673 return false; 674 } 675 676 } 677 678 | Popular Tags |