/** * Determine the static cardinality. */ public int computeCardinality() { if (resultWhenEmpty != null) { return StaticProperty.EXACTLY_ONE; } else { return super.computeCardinality(); } }
/** * Diagnostic print of expression structure. The abstract expression tree * is written to the supplied output destination. * * @param out the output destination for the displayed expression tree */ public void export(ExpressionPresenter out) throws XPathException { out.startElement(tag(), this); out.emitAttribute("op", displayOperator()); explainExtraAttributes(out); getLhsExpression().export(out); getRhsExpression().export(out); out.endElement(); }
/** * Create a binary expression identifying the two operands and the operator * * @param p0 the left-hand operand * @param op the operator, as a token returned by the Tokenizer (e.g. Token.AND) * @param p1 the right-hand operand */ public BinaryExpression(Expression p0, int op, Expression p1) { operator = op; // p0.verifyParentPointers(); // p1.verifyParentPointers(); lhs = new Operand(this, p0, getOperandRole(0)); rhs = new Operand(this, p1, getOperandRole(1)); adoptChildExpression(p0); adoptChildExpression(p1); }
@Override public String toShortString() { return parenthesize(getLhsExpression()) + " " + displayOperator() + " " + parenthesize(getRhsExpression()); }
/** * Represent the expression as a string. The resulting string will be a valid XPath 3.0 expression * with no dependencies on namespace bindings other than the binding of the prefix "xs" to the XML Schema * namespace. * * @return the expression as a string in XPath 3.0 syntax */ public String toString() { return ExpressionTool.parenthesize(getLhsExpression()) + " " + displayOperator() + " " + ExpressionTool.parenthesize(getRhsExpression()); }
/** * Is this expression the same as another expression? */ public boolean equals(Object other) { if (other instanceof BinaryExpression && hasCompatibleStaticContext((Expression)other)) { BinaryExpression b = (BinaryExpression) other; Expression lhs1 = getLhsExpression(); Expression rhs1 = getRhsExpression(); Expression lhs2 = b.getLhsExpression(); Expression rhs2 = b.getRhsExpression(); if (operator == b.operator) { if (lhs1.isEqual(lhs2) && rhs1.isEqual(rhs2)) { return true; } if (isCommutative(operator) && lhs1.isEqual(rhs2) && rhs1.isEqual(lhs2)) { return true; } if (isAssociative(operator) && pairwiseEqual(flattenExpression(new ArrayList<>(4)), b.flattenExpression(new ArrayList<>(4)))) { return true; } } return isInverse(operator, b.operator) && lhs1.isEqual(rhs2) && rhs1.isEqual(lhs2); } return false; }
/** * Is this expression the same as another expression? */ public boolean equals(Object other) { if (other instanceof BinaryExpression) { BinaryExpression b = (BinaryExpression)other; if (operator == b.operator) { if (operand0.equals(b.operand0) && operand1.equals(b.operand1)) { return true; } if (isCommutative(operator) && operand0.equals(b.operand1) && operand1.equals(b.operand0)) { return true; } if (isAssociative(operator) && pairwiseEqual(flattenExpression(new ArrayList(4)), b.flattenExpression(new ArrayList(4)))) { return true; } } if (isInverse(operator, b.operator) && operand0.equals(b.operand1) && operand1.equals(b.operand0)) { return true; } } return false; }
/** * Perform optimisation of an expression and its subexpressions. * <p/> * <p>This method is called after all references to functions and variables have been resolved * to the declaration of the function or variable, and after all type checking has been done.</p> * * @param visitor an expression visitor * @param contextItemType the static type of "." at the point where this expression is invoked. * The parameter is set to null if it is known statically that the context item will be undefined. * If the type of the context item is not known statically, the argument is set to * {@link net.sf.saxon.type.Type#ITEM_TYPE} * @return the original expression, rewritten if appropriate to optimize execution * @throws XPathException if an error is discovered during this phase * (typically a type error) */ public Expression optimize(ExpressionVisitor visitor, ItemType contextItemType) throws XPathException { Expression r = super.optimize(visitor, contextItemType); if (r != this) { if (!generateIdEmulation) { if (Literal.isEmptySequence(operand0) || Literal.isEmptySequence(operand1)) { return Literal.makeEmptySequence(); } } } return r; }
public AbstractExpression exprFor (BinaryExpression expr) { Expression [] operands = expr.getOperands(); BinaryOperation.Operator op = operatorFor(expr.getOperator()); if (operands[0] instanceof AtomicSequenceConverter || operands[1] instanceof AtomicSequenceConverter) { // Saxon optimizes some general sequences into atomic sequences in a way that // we can't represent in XQuery directly. So we use a General Comparison in that case // which we *think* will mimic Saxon's behavior op = generalizeOperator (op); } return new BinaryOperation (exprFor(operands[0]), op, exprFor(operands[1])); }
/** * Type-check the expression. Default implementation for binary operators that accept * any kind of operand */ /*@NotNull*/ public Expression typeCheck(ExpressionVisitor visitor, ContextItemStaticInfo contextInfo) throws XPathException { resetLocalStaticProperties(); lhs.typeCheck(visitor, contextInfo); rhs.typeCheck(visitor, contextInfo); // if both operands are known, pre-evaluate the expression try { if ((getLhsExpression() instanceof Literal) && (getRhsExpression() instanceof Literal)) { GroundedValue<?> v = evaluateItem(visitor.getStaticContext().makeEarlyEvaluationContext()).materialize(); return Literal.makeLiteral(v, this); } } catch (XPathException err) { // if early evaluation fails, suppress the error: the value might // not be needed at run-time } return this; }
protected String displayOperator() { return "many-to-many " + super.displayOperator(); }
Expression le = be.getLhsExpression(); Comparison compType = getComparison(be.getOperator()); if (compType == null) { logger.debug("iterateParams; can't get comparison from {}", be); var = le; } else { var = be.getRhsExpression();
if ((getLhsExpression() instanceof Literal) && (getRhsExpression() instanceof Literal)) { Item<?> item = evaluateItem(visitor.getStaticContext().makeEarlyEvaluationContext()); if (item != null) { GroundedValue<?> v = item.materialize();
if (getLhsExpression() instanceof BinaryExpression && ((BinaryExpression) getLhsExpression()).operator == operator) { ((BinaryExpression) getLhsExpression()).flattenExpression(list); } else { int h = getLhsExpression().hashCode(); list.add(getLhsExpression()); int i = list.size() - 1; while (i > 0 && h > list.get(i - 1).hashCode()) { list.set(i, list.get(i - 1)); list.set(i - 1, getLhsExpression()); i--; if (getRhsExpression() instanceof BinaryExpression && ((BinaryExpression) getRhsExpression()).operator == operator) { ((BinaryExpression) getRhsExpression()).flattenExpression(list); } else { int h = getRhsExpression().hashCode(); list.add(getRhsExpression()); int i = list.size() - 1; while (i > 0 && h > list.get(i - 1).hashCode()) { list.set(i, list.get(i - 1)); list.set(i - 1, getRhsExpression()); i--;
/** * Get the effective boolean value. In the case of a union expression, this * is reduced to an OR expression, for efficiency */ public boolean effectiveBooleanValue(final XPathContext context) throws XPathException { if (operator == Token.UNION) { return operand0.effectiveBooleanValue(context) || operand1.effectiveBooleanValue(context); } else { return super.effectiveBooleanValue(context); } }
/** * Type-check the expression. Default implementation for binary operators that accept * any kind of operand */ public Expression typeCheck(ExpressionVisitor visitor, ItemType contextItemType) throws XPathException { operand0 = visitor.typeCheck(operand0, contextItemType); operand1 = visitor.typeCheck(operand1, contextItemType); // if both operands are known, pre-evaluate the expression try { if ((operand0 instanceof Literal) && (operand1 instanceof Literal)) { Value v = Value.asValue(evaluateItem(visitor.getStaticContext().makeEarlyEvaluationContext())); return Literal.makeLiteral(v); } } catch (XPathException err) { // if early evaluation fails, suppress the error: the value might // not be needed at run-time } return this; }
/** * Create a binary expression identifying the two operands and the operator * @param p0 the left-hand operand * @param op the operator, as a token returned by the Tokenizer (e.g. Token.AND) * @param p1 the right-hand operand */ public BinaryExpression(Expression p0, int op, Expression p1) { operator = op; operand0 = p0; operand1 = p1; adoptChildExpression(p0); adoptChildExpression(p1); }
if (operand0 instanceof BinaryExpression && ((BinaryExpression)operand0).operator == operator) { ((BinaryExpression)operand0).flattenExpression(list); } else { int h = operand0.hashCode(); ((BinaryExpression)operand1).flattenExpression(list); } else { int h = operand1.hashCode();
/** * Is this expression the same as another expression? */ public boolean equals(Object other) { if (other instanceof BinaryExpression && hasCompatibleStaticContext((Expression)other)) { BinaryExpression b = (BinaryExpression) other; Expression lhs1 = getLhsExpression(); Expression rhs1 = getRhsExpression(); Expression lhs2 = b.getLhsExpression(); Expression rhs2 = b.getRhsExpression(); if (operator == b.operator) { if (lhs1.isEqual(lhs2) && rhs1.isEqual(rhs2)) { return true; } if (isCommutative(operator) && lhs1.isEqual(rhs2) && rhs1.isEqual(lhs2)) { return true; } if (isAssociative(operator) && pairwiseEqual(flattenExpression(new ArrayList<>(4)), b.flattenExpression(new ArrayList<>(4)))) { return true; } } return isInverse(operator, b.operator) && lhs1.isEqual(rhs2) && rhs1.isEqual(lhs2); } return false; }
/** * Is this expression the same as another expression? */ public boolean equals(Object other) { if (other instanceof BinaryExpression) { BinaryExpression b = (BinaryExpression)other; if (operator == b.operator) { if (operand0.equals(b.operand0) && operand1.equals(b.operand1)) { return true; } if (isCommutative(operator) && operand0.equals(b.operand1) && operand1.equals(b.operand0)) { return true; } if (isAssociative(operator) && pairwiseEqual(flattenExpression(new ArrayList(4)), b.flattenExpression(new ArrayList(4)))) { return true; } } if (isInverse(operator, b.operator) && operand0.equals(b.operand1) && operand1.equals(b.operand0)) { return true; } } return false; }