/** * Gather the component operands of a union or intersect expression * * @param operator union or intersect * @param set the set into which the components are to be gathered. If the operator * is union, this follows the tree gathering all operands of union expressions. Ditto, * mutatis mutandis, for intersect expressions. */ public void gatherComponents(int operator, Set<Expression> set) { if (getLhsExpression() instanceof VennExpression && ((VennExpression) getLhsExpression()).operator == operator) { ((VennExpression) getLhsExpression()).gatherComponents(operator, set); } else { set.add(getLhsExpression()); } if (getRhsExpression() instanceof VennExpression && ((VennExpression) getRhsExpression()).operator == operator) { ((VennExpression) getRhsExpression()).gatherComponents(operator, set); } else { set.add(getRhsExpression()); } }
public int computeHashCode() { return getLhsExpression().hashCode() ^ getRhsExpression().hashCode(); }
public int computeHashCode() { return getLhsExpression().hashCode() ^ getRhsExpression().hashCode(); }
/** * 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) { // NOTE: this optimization was probably already done statically return getLhsExpression().effectiveBooleanValue(context) || getRhsExpression().effectiveBooleanValue(context); } else { return super.effectiveBooleanValue(context); } }
/** * 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) { // NOTE: this optimization was probably already done statically return getLhsExpression().effectiveBooleanValue(context) || getRhsExpression().effectiveBooleanValue(context); } else { return super.effectiveBooleanValue(context); } }
private boolean operandsAreDisjoint(TypeHierarchy th) { return th.relationship(getLhsExpression().getItemType(), getRhsExpression().getItemType()) == TypeHierarchy.DISJOINT; }
private boolean operandsAreDisjoint(TypeHierarchy th) { return th.relationship(getLhsExpression().getItemType(), getRhsExpression().getItemType()) == TypeHierarchy.DISJOINT; }
/** * Copy an expression. This makes a deep copy. * * @return the copy of the original expression * @param rebindings variables that need to be rebound */ /*@NotNull*/ public Expression copy(RebindingMap rebindings) { VennExpression exp = new VennExpression(getLhsExpression().copy(rebindings), operator, getRhsExpression().copy(rebindings)); ExpressionTool.copyLocationInfo(this, exp); return exp; }
/** * Copy an expression. This makes a deep copy. * * @return the copy of the original expression * @param rebindings variables that need to be rebound */ /*@NotNull*/ public Expression copy(RebindingMap rebindings) { VennExpression exp = new VennExpression(getLhsExpression().copy(rebindings), operator, getRhsExpression().copy(rebindings)); ExpressionTool.copyLocationInfo(this, exp); return exp; }
private void checkNoPredicatePattern(Expression exp) throws XPathException { if (exp instanceof ContextItemExpression) { grumble("A predicatePattern can appear only at the outermost level (union operator not allowed)"); } if (exp instanceof FilterExpression) { checkNoPredicatePattern(((FilterExpression) exp).getBase()); } if (exp instanceof VennExpression) { checkNoPredicatePattern(((VennExpression) exp).getLhsExpression()); checkNoPredicatePattern(((VennExpression) exp).getRhsExpression()); } }
private void checkNoPredicatePattern(Expression exp) throws XPathException { if (exp instanceof ContextItemExpression) { grumble("A predicatePattern can appear only at the outermost level (union operator not allowed)"); } if (exp instanceof FilterExpression) { checkNoPredicatePattern(((FilterExpression) exp).getBase()); } if (exp instanceof VennExpression) { checkNoPredicatePattern(((VennExpression) exp).getLhsExpression()); checkNoPredicatePattern(((VennExpression) exp).getRhsExpression()); } }
/** * Get the static type of the expression as a UType, following precisely the type * inference rules defined in the XSLT 3.0 specification. * * @return the static item type of the expression according to the XSLT 3.0 defined rules * @param contextItemType the static type of the context item */ @Override public UType getStaticUType(UType contextItemType) { switch (operator) { case Token.UNION: return getLhsExpression().getStaticUType(contextItemType).union(getRhsExpression().getStaticUType(contextItemType)); case Token.INTERSECT: return getLhsExpression().getStaticUType(contextItemType).intersection(getRhsExpression().getStaticUType(contextItemType)); case Token.EXCEPT: default: return getLhsExpression().getStaticUType(contextItemType); } }
/** * Get the static type of the expression as a UType, following precisely the type * inference rules defined in the XSLT 3.0 specification. * * @return the static item type of the expression according to the XSLT 3.0 defined rules * @param contextItemType the static type of the context item */ @Override public UType getStaticUType(UType contextItemType) { switch (operator) { case Token.UNION: return getLhsExpression().getStaticUType(contextItemType).union(getRhsExpression().getStaticUType(contextItemType)); case Token.INTERSECT: return getLhsExpression().getStaticUType(contextItemType).intersection(getRhsExpression().getStaticUType(contextItemType)); case Token.EXCEPT: default: return getLhsExpression().getStaticUType(contextItemType); } }
/** * Determine the data type of the items returned by this expression * * @return the data type */ /*@NotNull*/ public final ItemType getItemType() { final ItemType t1 = getLhsExpression().getItemType(); if (operator == Token.UNION) { ItemType t2 = getRhsExpression().getItemType(); TypeHierarchy th = getConfiguration().getTypeHierarchy(); return Type.getCommonSuperType(t1, t2, th); } else { return t1; } }
/** * Determine the data type of the items returned by this expression * * @return the data type */ /*@NotNull*/ public final ItemType getItemType() { final ItemType t1 = getLhsExpression().getItemType(); if (operator == Token.UNION) { ItemType t2 = getRhsExpression().getItemType(); TypeHierarchy th = getConfiguration().getTypeHierarchy(); return Type.getCommonSuperType(t1, t2, th); } else { return t1; } }
/** * Get the static properties of this expression (other than its type). The result is * bit-signficant. These properties are used for optimizations. In general, if * property bit is set, it is true, but if it is unset, the value is unknown. */ public int computeSpecialProperties() { final int prop0 = getLhsExpression().getSpecialProperties(); final int prop1 = getRhsExpression().getSpecialProperties(); int props = StaticProperty.ORDERED_NODESET; if (testContextDocumentNodeSet(prop0, prop1)) { props |= StaticProperty.CONTEXT_DOCUMENT_NODESET; } if (testSubTree(prop0, prop1)) { props |= StaticProperty.SUBTREE_NODESET; } if (createsNoNewNodes(prop0, prop1)) { props |= StaticProperty.NO_NODES_NEWLY_CREATED; } return props; }
/** * Replace this expression by an expression that returns the same result but without * regard to order * * @param retainAllNodes true if all nodes in the result must be retained; false * if duplicates can be eliminated * @param forStreaming set to true if optimizing for streaming */ @Override public Expression unordered(boolean retainAllNodes, boolean forStreaming) { if (operator == Token.UNION && !forStreaming && operandsAreDisjoint(getConfiguration().getTypeHierarchy())) { // replace union operator by comma operator to avoid cost of sorting into document order. See XMark q7 Block block = new Block(new Expression[]{getLhsExpression(), getRhsExpression()}); ExpressionTool.copyLocationInfo(this, block); return block; } return this; }
/** * Get the static properties of this expression (other than its type). The result is * bit-signficant. These properties are used for optimizations. In general, if * property bit is set, it is true, but if it is unset, the value is unknown. */ public int computeSpecialProperties() { final int prop0 = getLhsExpression().getSpecialProperties(); final int prop1 = getRhsExpression().getSpecialProperties(); int props = StaticProperty.ORDERED_NODESET; if (testContextDocumentNodeSet(prop0, prop1)) { props |= StaticProperty.CONTEXT_DOCUMENT_NODESET; } if (testSubTree(prop0, prop1)) { props |= StaticProperty.SUBTREE_NODESET; } if (createsNoNewNodes(prop0, prop1)) { props |= StaticProperty.NO_NODES_NEWLY_CREATED; } return props; }
/** * Replace this expression by an expression that returns the same result but without * regard to order * * @param retainAllNodes true if all nodes in the result must be retained; false * if duplicates can be eliminated * @param forStreaming set to true if optimizing for streaming */ @Override public Expression unordered(boolean retainAllNodes, boolean forStreaming) { if (operator == Token.UNION && !forStreaming && operandsAreDisjoint(getConfiguration().getTypeHierarchy())) { // replace union operator by comma operator to avoid cost of sorting into document order. See XMark q7 Block block = new Block(new Expression[]{getLhsExpression(), getRhsExpression()}); ExpressionTool.copyLocationInfo(this, block); return block; } return this; }
public Expression makeOptimizedFunctionCall( ExpressionVisitor visitor, ContextItemStaticInfo contextInfo, final Expression... arguments) throws XPathException { // See if we can deduce the answer from the cardinality int c = arguments[0].getCardinality(); if (c == StaticProperty.ALLOWS_ONE_OR_MORE) { return Literal.makeLiteral(BooleanValue.FALSE, arguments[0]); } else if (c == StaticProperty.ALLOWS_ZERO) { return Literal.makeLiteral(BooleanValue.TRUE, arguments[0]); } // Rewrite // empty(A|B) => empty(A) and empty(B) if (arguments[0] instanceof VennExpression && !visitor.isOptimizeForStreaming()) { VennExpression v = (VennExpression) arguments[0]; if (v.getOperator() == Token.UNION) { Expression e0 = SystemFunction.makeCall("empty", getRetainedStaticContext(), v.getLhsExpression()); Expression e1 = SystemFunction.makeCall("empty", getRetainedStaticContext(), v.getRhsExpression()); return new AndExpression(e0, e1).optimize(visitor, contextInfo); } } return null; }