1 package net.sf.saxon.expr; 2 3 import net.sf.saxon.Configuration; 4 import net.sf.saxon.Controller; 5 import net.sf.saxon.event.SequenceOutputter; 6 import net.sf.saxon.instruct.*; 7 import net.sf.saxon.om.*; 8 import net.sf.saxon.sort.SortExpression; 9 import net.sf.saxon.trace.InstructionInfoProvider; 10 import net.sf.saxon.trans.DynamicError; 11 import net.sf.saxon.trans.XPathException; 12 import net.sf.saxon.type.AnyItemType; 13 import net.sf.saxon.value.*; 14 15 import javax.xml.transform.SourceLocator ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 19 24 25 public class ExpressionTool 26 { 27 private ExpressionTool() {} 28 29 44 45 public static Expression make(String expression, StaticContext env, 46 int start, int terminator, int lineNumber) throws XPathException { 47 ExpressionParser parser = new ExpressionParser(); 48 if (terminator == -1) { 49 terminator = Token.EOF; 50 } 51 Expression exp = parser.parse(expression, start, terminator, lineNumber, env); 52 exp = exp.simplify(env); 53 makeParentReferences(exp); 54 return exp; 55 } 56 57 61 62 public static void copyLocationInfo(Expression from, Expression to) { 63 if (from instanceof ComputedExpression && to instanceof ComputedExpression) { 64 ((ComputedExpression)to).setLocationId(((ComputedExpression)from).getLocationId()); 65 } 66 } 67 68 72 73 public static void makeParentReferences(Expression top) { 74 } 87 88 91 92 public static SourceLocator getLocator(Expression exp) { 93 if (exp instanceof ComputedExpression) { 94 return (ComputedExpression)exp; 95 } else { 96 return null; 97 } 98 } 99 100 105 106 public static boolean isRepeatedSubexpression(Expression parent, Expression child) { 107 if (parent instanceof PathExpression) { 108 return child == ((PathExpression)parent).getStepExpression(); 109 } 110 if (parent instanceof FilterExpression) { 111 return child == ((FilterExpression)parent).getFilter(); 112 } 113 if (parent instanceof ForExpression) { 114 return child == ((ForExpression)parent).getAction(); 115 } 116 if (parent instanceof QuantifiedExpression) { 117 return child == ((QuantifiedExpression)parent).getAction(); 118 } 119 if (parent instanceof SimpleMappingExpression) { 120 return child == ((SimpleMappingExpression)parent).getStepExpression(); 121 } 122 if (parent instanceof SortExpression) { 123 return ((SortExpression)parent).isSortKey(child); 124 } 125 if (parent instanceof AnalyzeString) { 129 return child == ((AnalyzeString)parent).getMatchingExpression() || 130 child == ((AnalyzeString)parent).getNonMatchingExpression(); 131 } 132 if (parent instanceof ForEach) { 133 return child == ((ForEach)parent).getActionExpression(); 134 } 135 if (parent instanceof ForEachGroup) { 136 return child == ((ForEachGroup)parent).getActionExpression(); 137 } 138 if (parent instanceof While) { 139 return child == ((While)parent).getActionExpression(); 140 } 141 if (parent instanceof GeneralComparison) { 142 return child == ((GeneralComparison)parent).getOperands()[1]; 143 } 144 if (parent instanceof GeneralComparison10) { 145 Expression[] ops = ((GeneralComparison10)parent).getOperands(); 146 return child == ops[0] || child == ops[1]; 147 } 148 return false; 149 } 150 153 154 public static Expression unsorted(Optimizer opt, Expression exp, boolean eliminateDuplicates) 155 throws XPathException { 156 if (exp instanceof Value) return exp; PromotionOffer offer = new PromotionOffer(opt); 158 offer.action = PromotionOffer.UNORDERED; 159 offer.mustEliminateDuplicates = eliminateDuplicates; 160 Expression exp2 = exp.promote(offer); 161 if (exp2 != exp) { 162 if (exp2 instanceof ComputedExpression) { 163 ((ComputedExpression)exp2).setParentExpression(exp.getParentExpression()); 164 } 165 return exp2; 166 } 167 return exp; 168 } 169 170 177 178 public static Expression unsortedIfHomogeneous(Optimizer opt, Expression exp, boolean eliminateDuplicates) 179 throws XPathException { 180 if (exp instanceof Value) { 181 return exp; } 183 if (exp.getItemType() instanceof AnyItemType) { 184 return exp; 185 } else { 186 PromotionOffer offer = new PromotionOffer(opt); 187 offer.action = PromotionOffer.UNORDERED; 188 offer.mustEliminateDuplicates = eliminateDuplicates; 189 return exp.promote(offer); 190 } 191 } 192 193 194 213 214 public static ValueRepresentation lazyEvaluate(Expression exp, XPathContext context, int ref) throws XPathException { 215 if (exp instanceof Value) { 218 return (Value)exp; 219 220 } else if (exp instanceof VariableReference) { 221 return ((VariableReference)exp).evaluateVariable(context); 222 223 } else if ((exp.getDependencies() & 224 ( StaticProperty.DEPENDS_ON_POSITION | 225 StaticProperty.DEPENDS_ON_LAST | 226 StaticProperty.DEPENDS_ON_CURRENT_ITEM | 227 StaticProperty.DEPENDS_ON_CURRENT_GROUP | 228 StaticProperty.DEPENDS_ON_REGEX_GROUP )) != 0) { 229 return eagerEvaluate(exp, context); 232 233 } else if (exp instanceof LazyExpression) { 234 return Closure.make((LazyExpression)exp, context, (ref==1 ? 10 : ref)); 237 238 } else if (!Cardinality.allowsMany(exp.getCardinality())) { 239 return eagerEvaluate(exp, context); 241 242 } else { 243 return Closure.make((ComputedExpression)exp, context, ref); 245 } 246 247 } 248 249 257 258 public static Value eagerEvaluate(Expression exp, XPathContext context) throws XPathException { 259 if (exp instanceof Value && !(exp instanceof Closure)) { 260 return (Value)exp; 261 } 262 if (exp instanceof VariableReference) { 263 ValueRepresentation v = ((VariableReference)exp).evaluateVariable(context); 264 if (v instanceof Closure) { 265 return SequenceExtent.makeSequenceExtent(((Closure)v).iterate(null)); 266 } else if (v instanceof Value) { 267 return (Value)v; 268 } else if (v instanceof NodeInfo) { 269 return new SingletonNode((NodeInfo)v); 270 } 271 } 272 int m = exp.getImplementationMethod(); 273 if ((m & Expression.ITERATE_METHOD) != 0) { 274 SequenceIterator iterator = exp.iterate(context); 275 if (iterator instanceof EmptyIterator) { 276 return EmptySequence.getInstance(); 277 } else if (iterator instanceof SingletonIterator) { 278 Item item = ((SingletonIterator)iterator).getValue(); 279 return Value.asValue(item); 280 } 281 Value extent = SequenceExtent.makeSequenceExtent(iterator); 282 int len = extent.getLength(); 283 if (len==0) { 284 return EmptySequence.getInstance(); 285 } else if (len==1) { 286 return Value.asValue(extent.itemAt(0)); 287 } else { 288 return extent; 289 } 290 291 } else if ((m & Expression.EVALUATE_METHOD) != 0) { 292 Item item = exp.evaluateItem(context); 293 return Value.asValue(item); 294 295 } else { 296 Controller controller = context.getController(); 298 XPathContext c2 = context.newMinorContext(); 299 c2.setOrigin((InstructionInfoProvider)exp); 300 SequenceOutputter seq = new SequenceOutputter(); 301 seq.setPipelineConfiguration(controller.makePipelineConfiguration()); 302 c2.setTemporaryReceiver(seq); 303 seq.open(); 304 exp.process(c2); 305 seq.close(); 306 return Value.asValue(seq.getSequence()); 307 } 308 } 309 310 public static boolean markTailFunctionCalls(Expression exp) { 311 if (exp instanceof ComputedExpression) { 312 return ((ComputedExpression)exp).markTailFunctionCalls(); 313 } else { 314 return false; 315 } 316 } 317 318 324 325 public static String indent(int level) { 326 String s = ""; 327 for (int i=0; i<level; i++) { 328 s += " "; 329 } 330 return s; 331 } 332 333 341 342 public static int allocateSlots(Expression exp, int nextFree, SlotManager frame) { 343 if (exp instanceof Assignation) { 344 ((Assignation)exp).setSlotNumber(nextFree); 345 int count = ((Assignation)exp).getRequiredSlots(); 346 nextFree += count; 347 if (frame != null) { 348 for (int i=0; i<count; i++) { 349 frame.allocateSlotNumber(((Assignation)exp).getVariableFingerprint()); 350 } 351 } 352 } 353 for (Iterator children = exp.iterateSubExpressions(); children.hasNext();) { 354 Expression child = (Expression)children.next(); 355 nextFree = allocateSlots(child, nextFree, frame); 356 } 357 return nextFree; 358 359 } 363 364 370 public static boolean effectiveBooleanValue(SequenceIterator iterator) throws XPathException { 371 Item first = iterator.next(); 372 if (first == null) { 373 return false; 374 } 375 if (first instanceof NodeInfo) { 376 return true; 377 } else { 378 if (first instanceof BooleanValue) { 379 if (iterator.next() != null) { 380 ebvError("sequence of two or more items starting with an atomic value"); 381 } 382 return ((BooleanValue)first).getBooleanValue(); 383 } else if (first instanceof StringValue) { 384 if (iterator.next() != null) { 385 ebvError("sequence of two or more items starting with an atomic value"); 386 } 387 return (first.getStringValueCS().length()!=0); 388 } else if (first instanceof NumericValue) { 389 if (iterator.next() != null) { 390 ebvError("sequence of two or more items starting with an atomic value"); 391 } 392 return (!(first.equals(DoubleValue.ZERO)) && first.equals(first)); 394 } else { 395 ebvError("sequence starting with an atomic value other than a boolean, number, or string"); 396 return false; 397 } 398 } 399 } 400 401 public static void ebvError(String reason) throws XPathException { 402 DynamicError err = new DynamicError("Effective boolean value is not defined for a " + reason); 403 err.setIsTypeError(true); 404 throw err; 405 } 406 407 408 414 415 public static boolean dependsOnVariable(Expression e, Binding[] bindingList) { 416 if (e instanceof VariableReference) { 417 for (int i=0; i<bindingList.length; i++) { 418 if (((VariableReference)e).getBinding() == bindingList[i]) { 419 return true; 420 } 421 } 422 return false; 423 } else { 424 for (Iterator children = e.iterateSubExpressions(); children.hasNext();) { 425 Expression child = (Expression)children.next(); 426 if (dependsOnVariable(child, bindingList)) { 427 return true; 428 } 429 } 430 return false; 431 } 432 } 433 434 440 441 public static void gatherReferencedVariables(Expression e, List list) { 442 if (e instanceof VariableReference) { 443 Binding binding = ((VariableReference)e).getBinding(); 444 if (!list.contains(binding)) { 445 list.add(binding); 446 } 447 } else { 448 for (Iterator children = e.iterateSubExpressions(); children.hasNext();) { 449 Expression child = (Expression)children.next(); 450 gatherReferencedVariables(child, list); 451 } 452 } 453 } 454 455 461 462 public static boolean callsFunction(Expression exp, int fp) { 463 if (exp instanceof FunctionCall && (((FunctionCall)exp).getFunctionNameCode() & NamePool.FP_MASK) == fp) { 464 return true; 465 } 466 Iterator iter = exp.iterateSubExpressions(); 467 while (iter.hasNext()) { 468 Expression e = (Expression)iter.next(); 469 if (callsFunction(e, fp)) { 470 return true; 471 } 472 } 473 return false; 474 } 475 476 482 483 public static void gatherCalledFunctions(Expression e, List list) { 484 if (e instanceof UserFunctionCall) { 485 UserFunction function = ((UserFunctionCall)e).getFunction(); 486 if (!list.contains(function)) { 487 list.add(function); 488 } 489 } else { 490 for (Iterator children = e.iterateSubExpressions(); children.hasNext();) { 491 Expression child = (Expression)children.next(); 492 gatherCalledFunctions(child, list); 493 } 494 } 495 } 496 497 500 501 public static Expression resolveCallsToCurrentFunction(Expression exp, Configuration config) throws XPathException { 502 int current = config.getNamePool().getFingerprint(NamespaceConstant.FN, "current"); 503 if (current == -1) { 504 return exp; 505 } 507 if (callsFunction(exp, current)) { 508 RangeVariableDeclaration decl = new RangeVariableDeclaration(); 509 decl.setNameCode(config.getNamePool().allocate("saxon", NamespaceConstant.SAXON, "current" + exp.hashCode())); 510 decl.setVariableName("saxon:current"); 511 decl.setRequiredType(SequenceType.SINGLE_ITEM); 512 LetExpression let = new LetExpression(); 513 let.setSequence(new ContextItemExpression()); 514 let.setVariableDeclaration(decl); 515 PromotionOffer offer = new PromotionOffer(config.getOptimizer()); 516 offer.action = PromotionOffer.REPLACE_CURRENT; 517 offer.containingExpression = let; 518 exp = exp.promote(offer); 519 let.setAction(exp); 520 return let; 521 } else { 522 return exp; 523 } 524 } 525 526 531 532 public static boolean isVariableReplaceableByDot(Expression exp, Binding[] binding) { 533 if (exp instanceof ComputedExpression) { 534 if (exp instanceof FilterExpression) { 535 Expression start = ((FilterExpression)exp).getBaseExpression(); 536 Expression filter = ((FilterExpression)exp).getFilter(); 537 return isVariableReplaceableByDot(start, binding) && 538 !dependsOnVariable(filter, binding); 539 } else if (exp instanceof PathExpression) { 540 Expression start = ((PathExpression)exp).getFirstStep(); 541 Expression rest = ((PathExpression)exp).getRemainingSteps(); 542 return isVariableReplaceableByDot(start, binding) && 543 !dependsOnVariable(rest, binding); 544 } else { 545 Iterator iter = exp.iterateSubExpressions(); 546 while (iter.hasNext()) { 547 Expression sub = (Expression)iter.next(); 548 if (!isVariableReplaceableByDot(sub, binding)) { 549 return false; 550 } 551 } 552 return true; 553 } 554 } else { 555 return true; 556 } 557 } 558 } 559 560 | Popular Tags |