1 package net.sf.saxon.expr; 2 import net.sf.saxon.functions.SystemFunction; 3 import net.sf.saxon.om.SequenceIterator; 4 import net.sf.saxon.pattern.CombinedNodeTest; 5 import net.sf.saxon.sort.DocumentOrderIterator; 6 import net.sf.saxon.sort.GlobalOrderComparer; 7 import net.sf.saxon.trans.XPathException; 8 import net.sf.saxon.type.ItemType; 9 import net.sf.saxon.type.Type; 10 import net.sf.saxon.value.EmptySequence; 11 import net.sf.saxon.value.SequenceType; 12 13 14 18 19 public class VennExpression extends BinaryExpression { 20 21 27 28 public VennExpression(final Expression p1, final int op, final Expression p2) { 29 super(p1, op, p2); 30 } 31 32 36 37 public final ItemType getItemType() { 38 final ItemType t1 = operand0.getItemType(); 39 final ItemType t2 = operand1.getItemType(); 40 return Type.getCommonSuperType(t1, t2); 41 } 42 43 46 47 public final int computeCardinality() { 48 final int c1 = operand0.getCardinality(); 49 final int c2 = operand1.getCardinality(); 50 switch (operator) { 51 case Token.UNION: 52 if (operand0 instanceof EmptySequence) return c2; 53 if (operand1 instanceof EmptySequence) return c1; 54 return c1 | c2 | StaticProperty.ALLOWS_ONE | StaticProperty.ALLOWS_MANY; 55 case Token.INTERSECT: 57 if (operand0 instanceof EmptySequence) return StaticProperty.EMPTY; 58 if (operand1 instanceof EmptySequence) return StaticProperty.EMPTY; 59 return (c1 & c2) | StaticProperty.ALLOWS_ZERO | StaticProperty.ALLOWS_ONE; 60 case Token.EXCEPT: 62 if (operand0 instanceof EmptySequence) return StaticProperty.EMPTY; 63 if (operand1 instanceof EmptySequence) return c1; 64 return c1 | StaticProperty.ALLOWS_ZERO | StaticProperty.ALLOWS_ONE; 65 } 67 return StaticProperty.ALLOWS_ZERO_OR_MORE; 68 } 69 70 75 76 public int computeSpecialProperties() { 77 final int prop0 = operand0.getSpecialProperties(); 78 final int prop1 = operand1.getSpecialProperties(); 79 int props = StaticProperty.ORDERED_NODESET; 80 if (testContextDocumentNodeSet(prop0, prop1)) { 81 props |= StaticProperty.CONTEXT_DOCUMENT_NODESET; 82 } 83 if (testSubTree(prop0, prop1)) { 84 props |= StaticProperty.SUBTREE_NODESET; 85 } 86 if (!testCreative(prop0, prop1)) { 87 props |= StaticProperty.NON_CREATIVE; 88 } 89 return props; 90 } 91 92 96 97 private boolean testContextDocumentNodeSet(final int prop0, final int prop1) { 98 switch (operator) { 99 case Token.UNION: 100 return (prop0 & prop1 & StaticProperty.CONTEXT_DOCUMENT_NODESET) != 0; 101 case Token.INTERSECT: 102 return ((prop0 | prop1) & StaticProperty.CONTEXT_DOCUMENT_NODESET) != 0; 103 case Token.EXCEPT: 104 return (prop0 & StaticProperty.CONTEXT_DOCUMENT_NODESET) != 0; 105 } 106 return false; 107 } 108 109 113 114 private boolean testSubTree(final int prop0, final int prop1) { 115 switch (operator) { 116 case Token.UNION: 117 return (prop0 & prop1 & StaticProperty.SUBTREE_NODESET) != 0; 118 case Token.INTERSECT: 119 return ((prop0 | prop1) & StaticProperty.SUBTREE_NODESET) != 0; 120 case Token.EXCEPT: 121 return (prop0 & StaticProperty.SUBTREE_NODESET) != 0; 122 } 123 return false; 124 } 125 126 129 130 private boolean testCreative(final int prop0, final int prop1) { 131 return !(((prop0 & StaticProperty.NON_CREATIVE) == 1) && 132 ((prop1 & StaticProperty.NON_CREATIVE) == 1)); 133 } 134 135 136 139 140 public Expression simplify(final StaticContext env) throws XPathException { 141 operand0 = operand0.simplify(env); 142 operand1 = operand1.simplify(env); 143 144 148 switch (operator) { 149 case Token.UNION: 150 if (operand0 instanceof EmptySequence && 151 (operand1.getSpecialProperties() & StaticProperty.ORDERED_NODESET) != 0) return operand1; 152 if (operand1 instanceof EmptySequence && 153 (operand0.getSpecialProperties() & StaticProperty.ORDERED_NODESET) != 0) return operand0; 154 break; 155 case Token.INTERSECT: 156 if (operand0 instanceof EmptySequence) return operand0; 157 if (operand1 instanceof EmptySequence) return operand1; 158 break; 159 case Token.EXCEPT: 160 if (operand0 instanceof EmptySequence) return operand0; 161 if (operand1 instanceof EmptySequence && 162 (operand0.getSpecialProperties() & StaticProperty.ORDERED_NODESET) != 0) return operand0; 163 break; 164 } 165 166 167 168 171 if (operand0 instanceof AxisExpression && operand1 instanceof AxisExpression) { 172 final AxisExpression a1 = (AxisExpression)operand0; 173 final AxisExpression a2 = (AxisExpression)operand1; 174 if (a1.getAxis() == a2.getAxis()) { 175 return new AxisExpression(a1.getAxis(), 176 new CombinedNodeTest(a1.getNodeTest(), 177 operator, 178 a2.getNodeTest())); 179 } 180 } 181 182 186 191 if (operand0 instanceof PathExpression && operand1 instanceof PathExpression && operator==Token.UNION) { 192 final PathExpression path1 = (PathExpression)operand0; 193 final PathExpression path2 = (PathExpression)operand1; 194 195 if (path1.getFirstStep().equals(path2.getFirstStep())) { 196 final Expression path = new PathExpression( 197 path1.getFirstStep(), 198 new VennExpression( 199 path1.getRemainingSteps(), 200 operator, 201 path2.getRemainingSteps())).simplify(env); 202 ExpressionTool.copyLocationInfo(this, path); 203 return path; 204 } 205 } 206 207 210 if (operand0 instanceof FilterExpression && operand1 instanceof FilterExpression) { 211 final FilterExpression exp0 = (FilterExpression)operand0; 212 final FilterExpression exp1 = (FilterExpression)operand1; 213 214 if (!exp0.isPositional() && 215 !exp1.isPositional() && 216 exp0.getBaseExpression().equals(exp1.getBaseExpression())) { 217 final Expression filter; 218 switch (operator) { 219 case Token.UNION: 220 filter = new BooleanExpression(exp0.getFilter(), 221 Token.OR, 222 exp1.getFilter()); 223 break; 224 case Token.INTERSECT: 225 filter = new BooleanExpression(exp0.getFilter(), 226 Token.AND, 227 exp1.getFilter()); 228 break; 229 case Token.EXCEPT: 230 final FunctionCall negate2 = SystemFunction.makeSystemFunction("not", 1, env.getNamePool()); 231 final Expression[] args = new Expression[1]; 232 args[0] = exp1.getFilter(); 233 negate2.setArguments(args); 234 filter = new BooleanExpression(exp0.getFilter(), 235 Token.AND, 236 negate2); 237 break; 238 default: 239 throw new AssertionError ("Unknown operator " + operator); 240 } 241 final Expression f = new FilterExpression( 242 exp0.getBaseExpression(), 243 filter, env).simplify(env); 244 ExpressionTool.copyLocationInfo(this, filter); 245 ExpressionTool.copyLocationInfo(this, f); 246 return f; 247 } 248 } 249 return this; 250 } 251 252 255 256 public Expression typeCheck(final StaticContext env, final ItemType contextItemType) throws XPathException { 257 258 operand0 = operand0.typeCheck(env, contextItemType); 259 operand1 = operand1.typeCheck(env, contextItemType); 260 261 final RoleLocator role0 = new RoleLocator(RoleLocator.BINARY_EXPR, Token.tokens[operator], 0, null); 262 role0.setSourceLocator(this); 263 operand0 = TypeChecker.staticTypeCheck(operand0, SequenceType.NODE_SEQUENCE, false, role0, env); 264 265 final RoleLocator role1 = new RoleLocator(RoleLocator.BINARY_EXPR, Token.tokens[operator], 1, null); 266 role1.setSourceLocator(this); 267 operand1 = TypeChecker.staticTypeCheck(operand1, SequenceType.NODE_SEQUENCE, false, role1, env); 268 return this; 269 } 270 271 272 275 276 295 public int hashCode() { 296 return operand0.hashCode() ^ operand1.hashCode(); 297 } 298 299 305 306 public SequenceIterator iterate(final XPathContext c) throws XPathException { 307 SequenceIterator i1 = operand0.iterate(c); 308 if (!((operand0.getSpecialProperties() & StaticProperty.ORDERED_NODESET) != 0)) { 311 i1 = new DocumentOrderIterator(i1, GlobalOrderComparer.getInstance()); 312 } 313 SequenceIterator i2 = operand1.iterate(c); 314 if (!((operand1.getSpecialProperties() & StaticProperty.ORDERED_NODESET) != 0)) { 317 i2 = new DocumentOrderIterator(i2, GlobalOrderComparer.getInstance()); 318 } 319 switch (operator) { 320 case Token.UNION: 321 return new UnionEnumeration(i1, i2, 322 GlobalOrderComparer.getInstance()); 323 case Token.INTERSECT: 324 return new IntersectionEnumeration(i1, i2, 325 GlobalOrderComparer.getInstance()); 326 case Token.EXCEPT: 327 return new DifferenceEnumeration(i1, i2, 328 GlobalOrderComparer.getInstance()); 329 } 330 throw new UnsupportedOperationException ("Unknown operator in Set Expression"); 331 } 332 333 337 338 public boolean effectiveBooleanValue(final XPathContext context) throws XPathException { 339 if (operator == Token.UNION) { 340 return operand0.effectiveBooleanValue(context) || operand1.effectiveBooleanValue(context); 341 } else { 342 return super.effectiveBooleanValue(context); 343 } 344 } 345 346 347 } 348 349 | Popular Tags |