1 package com.icl.saxon.expr; 2 import com.icl.saxon.*; 3 import com.icl.saxon.om.*; 4 import com.icl.saxon.sort.LocalOrderComparer; 5 6 import java.util.*; 7 import org.w3c.dom.*; 8 9 15 16 public abstract class NodeSetValue extends Value { 17 18 private Hashtable stringValues = null; 20 24 25 public int getDataType() { 26 return Value.NODESET; 27 } 28 29 33 34 public Value evaluate(Context context) throws XPathException { 35 sort(); 36 return this; 37 } 38 39 44 45 public NodeSetValue evaluateAsNodeSet(Context context) throws XPathException { 46 sort(); 47 return this; 48 } 49 50 54 55 public abstract NodeEnumeration enumerate() throws XPathException; 56 57 63 64 public NodeEnumeration enumerate(Context c, boolean sorted) throws XPathException { 65 if (sorted) sort(); 66 return enumerate(); 67 } 68 69 75 76 public abstract void setSorted(boolean isSorted); 77 78 83 84 public abstract boolean isSorted() throws XPathException; 85 86 91 92 public abstract String asString() throws XPathException; 93 94 98 99 public double asNumber() throws XPathException { 100 return (new StringValue(asString())).asNumber(); 101 } 102 103 107 108 public abstract boolean asBoolean() throws XPathException; 109 110 114 115 public abstract int getCount() throws XPathException; 116 117 125 126 public abstract NodeSetValue sort() throws XPathException; 127 128 132 133 public abstract NodeInfo getFirst() throws XPathException; 134 135 138 139 private Hashtable getStringValues() throws XPathException { 140 if (stringValues==null) { 141 stringValues = new Hashtable(); 142 NodeEnumeration e1 = this.enumerate(); 143 while (e1.hasMoreElements()) { 144 stringValues.put(e1.nextElement().getStringValue(), "x"); 145 } 146 } 147 return stringValues; 148 } 149 150 153 154 public boolean equals(Value other) throws XPathException { 155 156 if (other instanceof ObjectValue) { 157 return false; 158 159 } else if (other instanceof SingletonNodeSet) { 160 if (other.asBoolean()) { 161 return equals(new StringValue(other.asString())); 162 } else { 163 return false; 164 } 165 166 } else if (other instanceof NodeSetValue) { 167 168 170 Hashtable table = getStringValues(); 171 172 NodeEnumeration e2 = ((NodeSetValue)other).enumerate(); 173 while (e2.hasMoreElements()) { 174 if (table.get(e2.nextElement().getStringValue())!=null) return true; 175 } 176 return false; 177 178 } else if (other instanceof NumericValue) { 179 NodeEnumeration e1 = this.enumerate(); 180 while (e1.hasMoreElements()) { 181 NodeInfo node = e1.nextElement(); 182 if (Value.stringToNumber(node.getStringValue())==other.asNumber()) return true; 183 } 184 return false; 185 186 } else if (other instanceof StringValue) { 187 if (stringValues==null) { 188 NodeEnumeration e1 = this.enumerate(); 189 while (e1.hasMoreElements()) { 190 NodeInfo node = e1.nextElement(); 191 if (node.getStringValue().equals(other.asString())) return true; 192 } 193 return false; 194 } else { 195 return stringValues.get(other.asString()) != null; 196 } 197 198 } else if (other instanceof BooleanValue) { 199 return (asBoolean()==other.asBoolean()); 201 202 } else { 203 throw new InternalSaxonError("Unknown data type in a relational expression"); 204 } 206 207 } 208 209 212 213 public boolean notEquals(Value other) throws XPathException { 214 215 if (other instanceof ObjectValue) { 216 return false; 217 218 } else if (other instanceof SingletonNodeSet) { 219 if (other.asBoolean()) { 220 return notEquals(new StringValue(other.asString())); 221 } else { 222 return false; 223 } 224 225 } else if (other instanceof NodeSetValue) { 226 227 230 NodeEnumeration e1 = this.enumerate(); 231 while (e1.hasMoreElements()) { 232 String s1 = e1.nextElement().getStringValue(); 233 NodeEnumeration e2 = ((NodeSetValue)other).enumerate(); 234 while (e2.hasMoreElements()) { 235 String s2 = e2.nextElement().getStringValue(); 236 if (!s1.equals(s2)) return true; 237 } 238 } 239 return false; 240 241 } else if (other instanceof NumericValue) { 242 NodeEnumeration e1 = this.enumerate(); 243 while (e1.hasMoreElements()) { 244 NodeInfo node = e1.nextElement(); 245 if (Value.stringToNumber(node.getStringValue())!=other.asNumber()) return true; 246 } 247 return false; 248 249 } else if (other instanceof StringValue) { 250 NodeEnumeration e1 = this.enumerate(); 251 while (e1.hasMoreElements()) { 252 NodeInfo node = e1.nextElement(); 253 if (!(node.getStringValue().equals(other.asString()))) return true; 254 } 255 return false; 256 257 } else if (other instanceof BooleanValue) { 258 return (asBoolean()!=other.asBoolean()); 260 261 } else { 262 throw new InternalSaxonError("Unknown data type in a relational expression"); 263 } 264 265 } 266 267 272 273 public boolean compare(int operator, Value other) throws XPathException { 274 if (other instanceof ObjectValue) { 275 return false; 276 277 } 278 if (other instanceof SingletonNodeSet) { 279 if (other.asBoolean()) { 280 other = new StringValue(other.asString()); 281 } else { 282 return false; 283 } 284 } 285 286 if (operator==Tokenizer.EQUALS) return equals(other); 287 if (operator==Tokenizer.NE) return notEquals(other); 288 289 if (other instanceof NodeSetValue) { 290 291 293 double thismax = Double.NEGATIVE_INFINITY; 294 double thismin = Double.POSITIVE_INFINITY; 295 boolean thisIsEmpty = true; 296 297 NodeEnumeration e1 = enumerate(); 298 while (e1.hasMoreElements()) { 299 double val = Value.stringToNumber(e1.nextElement().getStringValue()); 300 if (val<thismin) thismin = val; 301 if (val>thismax) thismax = val; 302 thisIsEmpty = false; 303 } 304 305 if (thisIsEmpty) return false; 306 307 309 double othermax = Double.NEGATIVE_INFINITY; 310 double othermin = Double.POSITIVE_INFINITY; 311 boolean otherIsEmpty = true; 312 313 NodeEnumeration e2 = ((NodeSetValue)other).enumerate(); 314 while (e2.hasMoreElements()) { 315 double val = Value.stringToNumber(e2.nextElement().getStringValue()); 316 if (val<othermin) othermin = val; 317 if (val>othermax) othermax = val; 318 otherIsEmpty = false; 319 } 320 321 if (otherIsEmpty) return false; 322 323 switch(operator) { 324 case Tokenizer.LT: 325 return thismin < othermax; 326 case Tokenizer.LE: 327 return thismin <= othermax; 328 case Tokenizer.GT: 329 return thismax > othermin; 330 case Tokenizer.GE: 331 return thismax >= othermin; 332 default: 333 return false; 334 } 335 336 } else { 337 if (other instanceof NumericValue || other instanceof StringValue) { 338 NodeEnumeration e1 = enumerate(); 339 while (e1.hasMoreElements()) { 340 NodeInfo node = e1.nextElement(); 341 if (numericCompare(operator, 342 Value.stringToNumber(node.getStringValue()), 343 other.asNumber())) 344 return true; 345 } 346 return false; 347 } else if (other instanceof BooleanValue) { 348 return numericCompare(operator, 349 new BooleanValue(this.asBoolean()).asNumber(), 350 new BooleanValue(other.asBoolean()).asNumber()); 351 } else { 352 throw new InternalSaxonError("Unknown data type in a relational expression"); 353 } 354 } 355 356 } 357 358 361 362 public void display(int level) { 363 System.err.println(indent(level) + "** node set value (class " + getClass() + ") **"); 364 } 365 366 370 371 public int conversionPreference(Class required) { 372 373 if (required.isAssignableFrom(NodeSetValue.class)) return 0; 374 375 if (required==NodeList.class) return 0; 376 if (required==boolean.class) return 8; 377 if (required==Boolean .class) return 9; 378 if (required==byte.class) return 6; 379 if (required==Byte .class) return 7; 380 if (required==char.class) return 4; 381 if (required==Character .class) return 5; 382 if (required==double.class) return 6; 383 if (required==Double .class) return 7; 384 if (required==float.class) return 6; 385 if (required==Float .class) return 7; 386 if (required==int.class) return 6; 387 if (required==Integer .class) return 7; 388 if (required==long.class) return 6; 389 if (required==Long .class) return 7; 390 if (required==short.class) return 6; 391 if (required==Short .class) return 7; 392 if (required==String .class) return 2; 393 if (required==Object .class) return 3; 394 if (required==Node.class) return 1; 395 if (required==Element.class) return 1; 396 if (required==Document.class) return 1; 397 if (required==DocumentFragment.class) return 1; 398 if (required==Attr.class) return 1; 399 if (required==Comment.class) return 1; 400 if (required==Text.class) return 1; 401 if (required==CharacterData.class) return 1; 402 if (required==ProcessingInstruction.class) return 1; 403 return Integer.MAX_VALUE; 404 } 405 406 409 410 public Object convertToJava(Class target) throws XPathException { 411 412 if (target.isAssignableFrom(getClass())) { 413 return this; 414 } else if (target==NodeEnumeration.class) { 415 return this.enumerate(); 416 417 } else if (target==boolean.class) { 418 return new Boolean (asBoolean()); 419 } else if (target==Boolean .class) { 420 return new Boolean (asBoolean()); 421 422 } else if (target==Object .class || target==NodeList.class) { 423 if (this instanceof NodeList) { 424 return this; 425 } else { 426 return new NodeSetExtent(this.enumerate(), new LocalOrderComparer()); 428 } 429 430 } else if (target==Node.class) { 431 NodeInfo node = getFirst(); 432 return node; 433 434 } else if (target==Attr.class) { 435 NodeInfo node = getFirst(); 436 if (node==null) return null; 437 if (node.getNodeType() == NodeInfo.ATTRIBUTE) return node; 438 throw new XPathException("Node is of wrong type"); 439 440 } else if (target==CharacterData.class || target==Text.class) { 441 NodeInfo node = getFirst(); 442 if (node==null) return null; 443 if (node.getNodeType() == NodeInfo.TEXT) return node; 444 throw new XPathException("Node is of wrong type"); 445 446 } else if (target==Comment.class) { 447 NodeInfo node = getFirst(); 448 if (node==null) return null; 449 if (node.getNodeType() == NodeInfo.COMMENT) return node; 450 throw new XPathException("Node is of wrong type"); 451 452 } else if (target==Document.class) { 453 NodeInfo node = getFirst(); 454 if (node==null) return null; 455 if (node.getNodeType() == NodeInfo.ROOT) return node; 456 throw new XPathException("Node is of wrong type"); 457 458 } else if (target==Element.class) { 459 NodeInfo node = getFirst(); 460 if (node==null) return null; 461 if (node.getNodeType() == NodeInfo.ELEMENT) return node; 462 throw new XPathException("Node is of wrong type"); 463 464 } else if (target==ProcessingInstruction.class) { 465 NodeInfo node = getFirst(); 466 if (node==null) return null; 467 if (node.getNodeType() == NodeInfo.PI) return node; 468 throw new XPathException("Node is of wrong type"); 469 470 } else if (target==String .class) { 471 return asString(); 472 } else if (target==double.class) { 473 return new Double (asNumber()); 474 } else if (target==Double .class) { 475 return new Double (asNumber()); 476 } else if (target==float.class) { 477 return new Float (asNumber()); 478 } else if (target==Float .class) { 479 return new Float (asNumber()); 480 } else if (target==long.class) { 481 return new Long ((long)asNumber()); 482 } else if (target==Long .class) { 483 return new Long ((long)asNumber()); 484 } else if (target==int.class) { 485 return new Integer ((int)asNumber()); 486 } else if (target==Integer .class) { 487 return new Integer ((int)asNumber()); 488 } else if (target==short.class) { 489 return new Short ((short)asNumber()); 490 } else if (target==Short .class) { 491 return new Short ((short)asNumber()); 492 } else if (target==byte.class) { 493 return new Byte ((byte)asNumber()); 494 } else if (target==Byte .class) { 495 return new Byte ((byte)asNumber()); 496 } else if (target==char.class || target==Character .class) { 497 String s = asString(); 498 if (s.length()==1) { 499 return new Character (s.charAt(0)); 500 } else { 501 throw new XPathException("Cannot convert string to Java char unless length is 1"); 502 } 503 } else { 504 throw new XPathException("Conversion of node-set to " + target.getName() + 505 " is not supported"); 506 } 507 } 508 509 510 511 } 512 513 532 | Popular Tags |