/** * Copy an expression. This makes a deep copy. * * @return the copy of the original expression */ public Expression copy() { return new VennExpression(operand0.copy(), operator, operand1.copy()); }
/** * 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; }
/** * 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()); } }
/** * 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; }
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; }
/** * 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 = operand0.getSpecialProperties(); final int prop1 = operand1.getSpecialProperties(); int props = StaticProperty.ORDERED_NODESET; if (testContextDocumentNodeSet(prop0, prop1)) { props |= StaticProperty.CONTEXT_DOCUMENT_NODESET; } if (testSubTree(prop0, prop1)) { props |= StaticProperty.SUBTREE_NODESET; } if (!testCreative(prop0, prop1)) { props |= StaticProperty.NON_CREATIVE; } return props; }
Expression lhs = getLhsExpression(); Expression rhs = getRhsExpression(); switch (operator) { case Token.UNION: final VennExpression venn = new VennExpression( path1.getRemainingSteps(), operator, break; case Token.EXCEPT: Expression negate2 = SystemFunction.makeCall("not", getRetainedStaticContext(), exp1.getFilter()); filter = new AndExpression(exp0.getFilter(), negate2); break; if (operandsAreDisjoint(th)) { if (operator == Token.INTERSECT) { return Literal.makeEmptySequence();
getLhs().typeCheck(visitor, contextInfo); getRhs().typeCheck(visitor, contextInfo); if (!(getLhsExpression() instanceof Pattern)) { final RoleDiagnostic role0 = new RoleDiagnostic(RoleDiagnostic.BINARY_EXPR, Token.tokens[operator], 0); setLhsExpression(tc.staticTypeCheck(getLhsExpression(), SequenceType.NODE_SEQUENCE, role0, visitor)); if (!(getRhsExpression() instanceof Pattern)) { final RoleDiagnostic role1 = new RoleDiagnostic(RoleDiagnostic.BINARY_EXPR, Token.tokens[operator], 1); setRhsExpression(tc.staticTypeCheck(getRhsExpression(), SequenceType.NODE_SEQUENCE, role1, visitor)); ItemType t0 = getLhsExpression().getItemType(); ItemType t1 = getRhsExpression().getItemType(); if (th.relationship(t0, t1) == TypeHierarchy.DISJOINT) { if (operator == Token.INTERSECT) { return Literal.makeEmptySequence(); } else { if (getLhsExpression().hasSpecialProperty(StaticProperty.ORDERED_NODESET)) { return getLhsExpression(); } else { return new DocumentSorter(getLhsExpression());
if (v.getOperator() == Token.UNION) { int newop = (operation == EXISTS ? Token.OR : Token.AND); FunctionCall e0 = SystemFunction.makeSystemFunction( getFunctionName().getLocalName(), new Expression[]{v.getOperands()[0]}); FunctionCall e1 = SystemFunction.makeSystemFunction( getFunctionName().getLocalName(), new Expression[]{v.getOperands()[1]}); return new BooleanExpression(e0, newop, e1).optimize(visitor, contextItemType);
/** * 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; }
/** * 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; } }
/** * 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 set) { if (operand0 instanceof VennExpression && ((VennExpression)operand0).operator == operator) { ((VennExpression)operand0).gatherComponents(operator, set); } else { set.add(operand0); } if (operand1 instanceof VennExpression && ((VennExpression)operand1).operator == operator) { ((VennExpression)operand1).gatherComponents(operator, set); } else { set.add(operand1); } }
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; }
/** * 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 = operand0.getSpecialProperties(); final int prop1 = operand1.getSpecialProperties(); int props = StaticProperty.ORDERED_NODESET; if (testContextDocumentNodeSet(prop0, prop1)) { props |= StaticProperty.CONTEXT_DOCUMENT_NODESET; } if (testSubTree(prop0, prop1)) { props |= StaticProperty.SUBTREE_NODESET; } if (!testCreative(prop0, prop1)) { props |= StaticProperty.NON_CREATIVE; } return props; }
Expression lhs = getLhsExpression(); Expression rhs = getRhsExpression(); switch (operator) { case Token.UNION: final VennExpression venn = new VennExpression( path1.getRemainingSteps(), operator, break; case Token.EXCEPT: Expression negate2 = SystemFunction.makeCall("not", getRetainedStaticContext(), exp1.getFilter()); filter = new AndExpression(exp0.getFilter(), negate2); break; if (operandsAreDisjoint(th)) { if (operator == Token.INTERSECT) { return Literal.makeEmptySequence();
getLhs().typeCheck(visitor, contextInfo); getRhs().typeCheck(visitor, contextInfo); if (!(getLhsExpression() instanceof Pattern)) { final RoleDiagnostic role0 = new RoleDiagnostic(RoleDiagnostic.BINARY_EXPR, Token.tokens[operator], 0); setLhsExpression(tc.staticTypeCheck(getLhsExpression(), SequenceType.NODE_SEQUENCE, role0, visitor)); if (!(getRhsExpression() instanceof Pattern)) { final RoleDiagnostic role1 = new RoleDiagnostic(RoleDiagnostic.BINARY_EXPR, Token.tokens[operator], 1); setRhsExpression(tc.staticTypeCheck(getRhsExpression(), SequenceType.NODE_SEQUENCE, role1, visitor)); ItemType t0 = getLhsExpression().getItemType(); ItemType t1 = getRhsExpression().getItemType(); if (th.relationship(t0, t1) == TypeHierarchy.DISJOINT) { if (operator == Token.INTERSECT) { return Literal.makeEmptySequence(); } else { if (getLhsExpression().hasSpecialProperty(StaticProperty.ORDERED_NODESET)) { return getLhsExpression(); } else { return new DocumentSorter(getLhsExpression());
if (v.getOperator() == Token.UNION) { int newop = (operation == EXISTS ? Token.OR : Token.AND); FunctionCall e0 = SystemFunction.makeSystemFunction( getFunctionName().getLocalName(), new Expression[]{v.getOperands()[0]}); FunctionCall e1 = SystemFunction.makeSystemFunction( getFunctionName().getLocalName(), new Expression[]{v.getOperands()[1]}); return new BooleanExpression(e0, newop, e1).optimize(visitor, contextItemType);
/** * 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; }
/** * 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; }
/** * 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; } }