| 1 23 24 package org.xquark.xquery.reconstruction; 25 26 import java.math.BigDecimal ; 27 import java.sql.Timestamp ; 28 import java.util.*; 29 30 import org.w3c.dom.Attr ; 31 import org.w3c.dom.Node ; 32 import org.w3c.dom.Text ; 33 import org.xquark.schema.SchemaException; 34 import org.xquark.schema.SchemaManager; 35 import org.xquark.schema.SimpleType; 36 import org.xquark.schema.validation.ValidationContextProvider; 37 import org.xquark.xml.xdbc.XMLDBCException; 38 import org.xquark.xpath.datamodel.*; 39 import org.xquark.xquery.metadata.DynamicContext; 40 import org.xquark.xquery.parser.*; 41 import org.xquark.xquery.parser.primitivefunctions.fnfunctions.*; 42 import org.xquark.xquery.parser.primitivefunctions.xsfunctions.*; 43 import org.xquark.xquery.parser.util.Constants; 44 import org.xquark.xquery.xdbc.XDBCResultSetInterface; 45 46 51 public class EvaluationVisitor extends DefaultParserVisitor { 52 private static final String RCSRevision = "$Revision: 1.7 $"; 56 private static final String RCSName = "$Name: $"; 57 private XDBCResultSetInterface resultSet = null; 61 62 private boolean verdict = false; 63 64 private ArrayList resnodes = null; 65 private Comparable resvalue = null; 66 67 protected static TypedDocumentImpl docimpl = null; 68 static { 69 docimpl = new TypedDocumentImpl(); 70 } 71 private SchemaManager schemamanager = null; 72 private DynamicContext dc = null; 73 private ValidationContextProvider context = null; 74 75 public static Integer UNKNOWN_TYPE = new Integer (-1); 76 public static Integer BOOLEAN_TYPE = new Integer (0); 77 public static Integer VALUE_TYPE = new Integer (1); 78 public static Integer NODE_TYPE = new Integer (2); 79 public static Integer TUPLE_TYPE = new Integer (3); 80 public static Integer BUFFER_TYPE = new Integer (4); 81 private Stack returnType = new Stack(); 82 83 86 public EvaluationVisitor(XDBCResultSetInterface resultSet, ValidationContextProvider context) { 87 this.schemamanager = new SchemaManager(); 88 this.resultSet = resultSet; 89 this.context = context; 90 } 91 92 95 public EvaluationVisitor(SchemaManager schemamanager, XDBCResultSetInterface resultSet) { 96 this.schemamanager = schemamanager; 97 this.resultSet = resultSet; 98 } 99 100 public void setReturnType(Integer setType) { 101 if (!returnType.isEmpty()) 102 this.returnType.pop(); 103 returnType.push(setType); 104 } 105 106 private void clear() { 107 resnodes = null; 108 resvalue = null; 109 verdict = false; 110 } 111 private void setResnodes(ArrayList nodes) { 112 resnodes = nodes; 113 resvalue = null; 114 verdict = false; 115 } 116 private void setValue(Comparable comp) { 117 resnodes = null; 118 resvalue = comp; 119 verdict = false; 120 } 121 private void setVerdict(boolean bool) { 122 resnodes = null; 123 resvalue = null; 124 verdict = bool; 125 } 126 public void setSchemaManager(SchemaManager schemamanager) { 127 this.schemamanager = schemamanager; 128 } 129 public void setDynamicContext(DynamicContext dc) { 130 this.dc = dc; 131 } 132 public void reset() { 133 clear(); 134 this.resultSet = null; 135 returnType.clear(); 136 } 137 public void reset(XDBCResultSetInterface resultSet) { 138 clear(); 139 this.resultSet = resultSet; 140 returnType.clear(); 141 } 142 public boolean getVerdict() { 143 return verdict; 144 } 145 public Comparable getResValue() { 146 return resvalue; 147 } 148 public ArrayList getResNodes() { 149 return resnodes; 150 } 151 152 public void visit(AttributeValuePair arg) throws XQueryException { 153 if (arg.isXmlns()) { 154 setResnodes(null); 155 return; 156 } 157 if (!(arg.getExpression1() instanceof QName)) { 158 throw new XQueryException("EvaluationVisitor : name of AttributeValuePair is not a QName : " + arg.getExpression1()); 159 } 160 QName attName = (QName) arg.getExpression1(); 161 Object attValue = null; 162 if (!(arg.getExpression2() instanceof Value)) { 163 returnType.push(VALUE_TYPE); 164 arg.getExpression2().accept(this); 165 returnType.pop(); 166 if (resvalue == null) { 167 throw new XQueryException("EvaluationVisitor : value of AttributeValuePair is null : " + arg.getExpression2()); 168 } 169 attValue = resvalue; 170 } else 171 attValue = ((Value) arg.getExpression2()).getObjectValue(); 172 if (attValue != null) { 173 TypedAttributeImpl att = new TypedAttributeImpl(docimpl, ((QName) attName).getNameSpace(), ((QName) attName).getLocalName()); 174 att.setNodeValue(attValue.toString()); 175 att.setTypedValue(attValue); 176 ArrayList tmplist = new ArrayList(1); 177 tmplist.add(att); 178 setResnodes(tmplist); 179 return; 180 } 181 setResnodes(null); 182 } 183 184 public void visit(BinOpANDExpression arg) throws XQueryException { 185 XQueryExpression exp1 = arg.getExpression1(); 186 EvaluationVisitor visitor = new EvaluationVisitor(this.schemamanager, resultSet); 187 visitor.setReturnType(EvaluationVisitor.BOOLEAN_TYPE); 188 exp1.accept(visitor); 189 verdict = visitor.getVerdict(); 190 if (!verdict) { 191 setVerdict(false); 192 return; 193 } 194 XQueryExpression exp2 = arg.getExpression2(); 195 visitor.reset(resultSet); 196 visitor.setReturnType(EvaluationVisitor.BOOLEAN_TYPE); 197 exp2.accept(visitor); 198 verdict &= visitor.getVerdict(); 199 setVerdict(verdict); 200 } 201 202 public void visit(BinOpORExpression arg) throws XQueryException { 203 XQueryExpression exp1 = arg.getExpression1(); 204 EvaluationVisitor visitor = new EvaluationVisitor(this.schemamanager, resultSet); 205 exp1.accept(visitor); 206 verdict = visitor.getVerdict(); 207 if (verdict) { 208 setVerdict(true); 209 return; 210 } 211 XQueryExpression exp2 = arg.getExpression2(); 212 visitor.reset(resultSet); 213 exp2.accept(visitor); 214 verdict = verdict || visitor.getVerdict(); 215 setVerdict(verdict); 216 } 217 218 222 public void visit(Element arg) throws XQueryException { 223 XQueryExpression startTag = arg.getStartTag(); 224 if (!(startTag instanceof QName)) 225 throw new XQueryException("Tag of Element expression is not a QName : " + startTag); 226 Integer rettype = (Integer ) returnType.peek(); 227 QName startTagQName = null; 228 TypedElement element = null; 229 ArrayList tmplist = null; 230 StringBuffer buf = null; 231 if (rettype == NODE_TYPE) { 232 startTagQName = (QName) startTag; 233 element = new TypedElementImpl(docimpl, startTagQName.getNameSpace(), startTagQName.getLocalName()); 234 tmplist = arg.getAttributes(); 235 if (tmplist != null && !tmplist.isEmpty()) { 236 for (int i = 0; i < tmplist.size(); i++) { 237 AttributeValuePair attValPair = (AttributeValuePair) tmplist.get(i); 238 attValPair.accept(this); 239 if (resnodes != null) { 240 TypedAttribute att = (TypedAttribute) resnodes.get(0); 241 element.setAttributeNodeNS((Attr ) att); 242 } 243 } 244 } 245 } else 246 buf = new StringBuffer (); 247 tmplist = arg.getSubExpressions(); 248 if (tmplist != null && !tmplist.isEmpty()) { 249 for (int i = 0; i < tmplist.size(); i++) { 250 XQueryExpression subExpr = (XQueryExpression) tmplist.get(i); 251 subExpr.accept(this); 252 if (rettype == NODE_TYPE && resnodes != null) { 253 for (int j = 0; j < resnodes.size(); j++) { 254 TypedNode resnode = (TypedNode) resnodes.get(j); 255 if (docimpl != resnode.getOwnerDocument()) 256 resnode = (TypedNode) element.getOwnerDocument().importNode(resnode, true); 257 if (resnode instanceof TypedAttributeImpl) { 258 element.setAttributeNodeNS((Attr ) resnode); 259 } else if (resnode instanceof TypedElementImpl) { 260 element.appendChild((Node ) resnode); 261 } else if (resnode instanceof TypedValueImpl) { 262 element.appendChild((Node ) resnode); 263 } else { 264 throw new XQueryException("Could not add child : " + resnode + " to parent."); 265 } 267 } 268 } 269 else if (rettype == VALUE_TYPE && resvalue != null) { 270 buf.append(resvalue.toString()); 271 } 272 } 273 } 274 clear(); 275 if (rettype == VALUE_TYPE) { 276 setValue(buf.toString()); 277 } else { tmplist = new ArrayList(1); 279 tmplist.add(element); 280 setResnodes(tmplist); 281 } 282 } 283 284 public void visit(ITEExpression arg) throws XQueryException { 290 returnType.push(BOOLEAN_TYPE); 291 arg.getIfExpression().accept(this); 292 returnType.pop(); 293 if (verdict) 294 arg.getThenExpression().accept(this); 295 else 296 arg.getElseExpression().accept(this); 297 } 298 299 public void visit(LibraryFunctionCall arg) throws XQueryException { 300 FunctionDeclaration funDecl = arg.getFunctionDefinition(); 301 if (funDecl.getExpressions() != null) { 302 } else { 304 Object [] params = new Object [arg.getArguments().size()]; 305 for (int i=0;i<arg.getArguments().size();i++) { 306 returnType.push(VALUE_TYPE); 307 arg.getArgument(i).accept(this); 308 params[i] = resvalue; 309 returnType.pop(); 310 } 311 Object obj = dc.invoke(arg,params); 312 setValue((Comparable )obj); 313 } 314 } 315 316 318 public void visit(ListOpArithExpression arg) throws XQueryException { 319 XQueryExpression exp1 = arg.getExpression1(); 320 XQueryExpression exp2 = arg.getExpression2(); 321 int operator = arg.getOperator(); 322 323 returnType.push(UNKNOWN_TYPE); 324 exp1.accept(this); 325 ArrayList trees1 = resnodes; 326 Number value1 = (resvalue instanceof Number ) ? (Number ) resvalue : null; 327 exp2.accept(this); 328 ArrayList trees2 = resnodes; 329 Number value2 = (resvalue instanceof Number ) ? (Number ) resvalue : null; 330 returnType.pop(); 331 332 if ((trees1 == null || trees1.isEmpty()) && (trees2 == null || trees2.isEmpty())) { 335 Number res = processOperation(exp1, exp2, null, null, value1, value2, operator); 336 SimpleType st = getSimpleType((Comparable ) res, schemamanager.getDoubleType()); 338 TypedNode text = (TypedNode) docimpl.createTypedValue(res, st); 339 text.setTypedValue(res); 340 text.setType(st); 341 ArrayList tmplist = new ArrayList(1); 342 tmplist.add(text); 343 setResnodes(tmplist); 344 return; 351 } 352 353 if ((trees1 == null || trees1.isEmpty()) && (trees2 != null) && (!trees2.isEmpty())) { 354 ArrayList tmplist = new ArrayList(trees2.size()); 355 for (int j = 0; j < trees2.size(); j++) { 356 TypedNode tree2 = (TypedNode) trees2.get(j); 357 Number res = processOperation(exp1, exp2, null, tree2, value1, value2, operator); 358 SimpleType st = getSimpleType((Comparable ) res, schemamanager.getDoubleType()); 359 TypedNode text = (TypedNode) docimpl.createTypedValue(res, st); 360 text.setTypedValue(res); 361 text.setType(st); 362 tmplist.add(text); 363 } 364 setResnodes(tmplist); 366 return; 370 } 371 372 if ((trees1 != null) && (!trees1.isEmpty()) && (trees2 == null) || (trees2.isEmpty())) { 373 ArrayList tmplist = new ArrayList(trees1.size()); 374 for (int i = 0; i < trees1.size(); i++) { 375 TypedNode tree1 = (TypedNode) trees1.get(i); 376 Number res = processOperation(exp1, exp2, tree1, null, value1, value2, operator); 377 SimpleType st = getSimpleType((Comparable ) res, schemamanager.getDoubleType()); 378 TypedNode text = (TypedNode) docimpl.createTypedValue(res, st); 379 text.setTypedValue(res); 380 text.setType(st); 381 tmplist.add(text); 382 } 383 setResnodes(tmplist); 385 return; 389 } 390 391 ArrayList tmplist = new ArrayList(trees1.size() * trees2.size()); 392 for (int i = 0; i < trees1.size(); i++) { 393 TypedNode tree1 = (TypedNode) trees1.get(i); 394 for (int j = 0; j < trees2.size(); j++) { 395 TypedNode tree2 = (TypedNode) trees2.get(j); 396 Number res = processOperation(exp1, exp2, tree1, tree2, value1, value2, operator); 397 SimpleType st = getSimpleType((Comparable ) res, schemamanager.getDoubleType()); 398 TypedNode text = (TypedNode) docimpl.createTypedValue(res, st); 399 text.setTypedValue(res); 400 text.setType(st); 401 tmplist.add(text); 402 } 403 } 404 setResnodes(tmplist); 406 } 410 411 public void visit(ListOpCompExpression arg) throws XQueryException { 413 XQueryExpression exp1 = arg.getExpression1(); 414 XQueryExpression exp2 = arg.getExpression2(); 415 int operator = arg.getOperator(); 416 417 returnType.push(EvaluationVisitor.NODE_TYPE); 418 resnodes = null; 419 resvalue = null; 420 exp1.accept(this); 421 ArrayList trees1 = resnodes; 423 if (trees1 != null && trees1.isEmpty()) 424 trees1 = null; 425 Comparable value1 = resvalue; 426 resnodes = null; 428 resvalue = null; 429 exp2.accept(this); 430 returnType.pop(); 431 ArrayList trees2 = resnodes; 432 if (trees2 != null && trees2.isEmpty()) 433 trees2 = null; 434 Comparable value2 = resvalue; 435 436 if (value1 != null && value2 != null) { 437 processComparison(null, null, null, null, value1, value2, operator); 438 setVerdict(verdict); 439 return; 440 } 441 442 if (trees1 == null && trees2 == null) { 443 processComparison(exp1, exp2, null, null, value1, value2, operator); 444 return; 445 } 446 447 if (trees1 == null && trees2 != null) { 448 for (int j = 0; j < trees2.size(); j++) { 449 TypedNode tree2 = (TypedNode) trees2.get(j); 450 processComparison(exp1, exp2, null, tree2, value1, value2, operator); 451 if (verdict == true) { 452 setVerdict(true); 453 return; 454 } 455 } 456 setVerdict(false); 457 return; 458 } 459 460 if (trees1 != null && trees2 == null) { 461 for (int i = 0; i < trees1.size(); i++) { 462 TypedNode tree1 = (TypedNode) trees1.get(i); 463 processComparison(exp1, exp2, tree1, null, value1, value2, operator); 464 if (verdict == true) { 465 setVerdict(true); 466 return; 467 } 468 } 469 setVerdict(false); 470 return; 471 } 472 473 for (int i = 0; i < trees1.size(); i++) { 474 TypedNode tree1 = (TypedNode) trees1.get(i); 475 for (int j = 0; j < trees2.size(); j++) { 476 TypedNode tree2 = (TypedNode) trees2.get(j); 477 processComparison(exp1, exp2, tree1, tree2, value1, value2, operator); 478 if (verdict == true) { 479 setVerdict(true); 480 return; 481 } 482 } 483 setVerdict(false); 484 } 485 } 486 487 490 public void visit(ListOpUNIONExpression arg) throws XQueryException { 491 XQueryExpression exp1 = arg.getExpression1(); 492 XQueryExpression exp2 = arg.getExpression2(); 493 494 returnType.push(NODE_TYPE); 495 resnodes = null; 496 exp1.accept(this); 497 ArrayList trees = resnodes; 498 resnodes = null; 499 exp2.accept(this); 500 returnType.pop(); 501 if (resnodes != null) { 502 if (trees == null) 503 trees = resnodes; 504 else 505 trees.addAll(resnodes); 506 } 507 setResnodes(trees); 508 } 509 510 public void visit(LocatedExpression arg) throws XQueryException { 511 ArrayList steps = arg.getSteps(); 512 int nodeAccessor = arg.getNodeAccessor(); 513 boolean hasSpecialStep = false; 514 if (nodeAccessor == Step.NONE) { 515 int lastPosition = steps.size() - 1; 516 Step lastStep = (Step) steps.get(lastPosition); 517 if (lastStep.getStepKind()%16 != 0) { 518 arg.setNodeAccessor(lastStep.getStepKind()); 519 nodeAccessor = arg.getNodeAccessor(); 520 steps.remove(lastPosition); 521 } 522 } 523 clear(); 556 String str = null; 557 try { 558 str = resultSet.fetch(arg.getStringValue(), nodeAccessor); 559 } catch (XMLDBCException xe) { 560 throw new XQueryException(xe.getMessage(), xe); 561 } 562 Integer rettype = returnType.isEmpty() ? UNKNOWN_TYPE : (Integer ) returnType.peek(); 566 if (rettype == NODE_TYPE) { 567 ArrayList nodes = null; 568 if (str != null) { 569 nodes = new ArrayList(1); 570 Text text = docimpl.createTextNode(str); 571 nodes.add(text); 572 } 573 setResnodes(nodes); 574 return; 575 } else { setValue(str); 577 return; 578 } 579 } 580 public void visit(QName arg) throws XQueryException { 584 String str = arg.getStringValue(); 585 Integer rettype = returnType.isEmpty() ? UNKNOWN_TYPE : (Integer ) returnType.peek(); 586 if (rettype == NODE_TYPE) { 587 ArrayList nodes = null; 588 if (str != null) { 589 nodes = new ArrayList(1); 590 Text text = docimpl.createTextNode(str); 591 nodes.add(text); 592 } 593 setResnodes(nodes); 594 return; 595 } else { setValue(str); 597 return; 598 } 599 } 600 607 private Comparable getMinus(Comparable obj) { 608 Comparable retObj = null; 609 if (obj instanceof Number ) { 610 if (obj instanceof Double ) { 612 retObj = new Double (- ((Double ) obj).doubleValue()); 613 } else if (obj instanceof Float ) { 614 retObj = new Float (- ((Float ) obj).floatValue()); 615 } else if (obj instanceof BigDecimal ) { 616 retObj = new BigDecimal (((BigDecimal ) obj).unscaledValue().negate(), ((BigDecimal ) obj).scale()); 617 } else if (obj instanceof Integer ) { 618 retObj = new Integer (- ((Integer ) obj).intValue()); 619 } else if (obj instanceof Long ) { 620 retObj = new Long (- ((Long ) obj).longValue()); 621 } 622 } else if (obj instanceof String ) { 623 try { 624 retObj = new Double (-Double.parseDouble((String ) obj)); 625 } catch (NumberFormatException e) { 626 } 628 } 629 return retObj; 630 } 631 632 public void visit(UnOpMinusExpression arg) throws XQueryException { 633 returnType.push(UNKNOWN_TYPE); 634 arg.getExpression().accept(this); 635 returnType.pop(); 636 Integer rettype = (Integer ) returnType.peek(); 637 if (resvalue != null) { 638 if (!arg.getMinus()) { 639 if (rettype == NODE_TYPE) { 640 ArrayList nodes = new ArrayList(1); 641 TypedValue text = null; 642 if (resvalue instanceof Long ) 643 text = docimpl.createTypedValue(resvalue, this.schemamanager.getIntegerType()); 644 else if (resvalue instanceof BigDecimal ) 645 text = docimpl.createTypedValue(resvalue, this.schemamanager.getDecimalType()); 646 else if (resvalue instanceof Double ) 647 text = docimpl.createTypedValue(resvalue, this.schemamanager.getDoubleType()); 648 else 649 throw new XQueryException("UnOpMinusExpression could not cast resvalue"); 650 nodes.add(text); 651 setResnodes(nodes); 652 return; 653 } else { setValue(resvalue); 655 return; 656 } 657 } 658 Comparable comp = getMinus(resvalue); 659 if (comp != null) { 660 if (rettype == NODE_TYPE) { 661 ArrayList nodes = new ArrayList(1); 662 TypedValue text = null; 663 if (comp instanceof Long ) 664 text = docimpl.createTypedValue(comp, this.schemamanager.getIntegerType()); 665 else if (resvalue instanceof BigDecimal ) 666 text = docimpl.createTypedValue(comp, this.schemamanager.getDecimalType()); 667 else if (comp instanceof Double ) 668 text = docimpl.createTypedValue(comp, this.schemamanager.getDoubleType()); 669 else 670 throw new XQueryException("UnOpMinusExpression could not cast comp"); 671 nodes.add(text); 672 setResnodes(nodes); 673 return; 674 } else { setValue(comp); 676 return; 677 } 678 } else 679 throw new XQueryException("UnOpMinusExpression could not cast operator to Number"); 680 } else if (resnodes != null) { 681 if (rettype == VALUE_TYPE && resnodes.size() != 1) { 682 throw new XQueryException("UnOpMinusExpression could not get value from node list"); 683 } 684 if (!arg.getMinus()) { 685 if (rettype == NODE_TYPE) { 686 ArrayList tmplist = new ArrayList(resnodes.size()); 687 for (int i = 0; i < resnodes.size(); i++) { 688 TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild(); 689 if (tmpnode == null) 690 tmpnode = (TypedNode) resnodes.get(0); 691 tmplist.add(docimpl.createTypedValue((Comparable ) tmpnode.getTypedValue(), (SimpleType) tmpnode.getType())); 692 } 693 setResnodes(tmplist); 694 return; 695 } else { TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild(); 697 if (tmpnode == null) 698 tmpnode = (TypedNode) resnodes.get(0); 699 setValue((Comparable ) tmpnode.getTypedValue()); 700 return; 701 } 702 } 703 ArrayList tmplist = new ArrayList(resnodes.size()); 704 for (int i = 0; i < resnodes.size(); i++) { 705 TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild(); 706 if (tmpnode == null) 707 tmpnode = (TypedNode) resnodes.get(0); 708 Comparable comp = getMinus((Comparable ) tmpnode.getTypedValue()); 709 if (comp != null) { 710 TypedValue text = docimpl.createTypedValue(comp, (SimpleType) tmpnode.getType()); 711 tmplist.add(text); 712 } 713 } 714 if (rettype == NODE_TYPE) { 715 setResnodes(tmplist); 716 return; 717 |