| 1 23 24 package org.xquark.xquery.normalize; 25 26 import java.util.*; 28 29 import org.xml.sax.SAXException ; 30 import org.xquark.schema.Schema; 31 import org.xquark.xpath.Axis; 32 import org.xquark.xpath.NodeKind; 33 import org.xquark.xquery.parser.*; 34 import org.xquark.xquery.parser.primitivefunctions.fnfunctions.*; 35 import org.xquark.xquery.parser.primitivefunctions.xsfunctions.FunctionSTRING; 36 import org.xquark.xquery.parser.util.Constants; 37 import org.xquark.xquery.typing.QType; 38 import org.xquark.xquery.typing.TypeException; 39 import org.xquark.xquery.typing.TypeVisitor; 40 41 48 49 52 53 public class ExpressionNormalizationVisitor extends org.xquark.xquery.parser.DefaultParserVisitor { 54 55 56 private static final String RCSRevision = "$Revision: 1.12 $"; 57 58 59 private static final String RCSName = "$Name: $"; 60 61 66 67 68 69 private final boolean reType = true; 70 71 72 protected TypeVisitor typeVisitor = null; 73 74 75 protected XQueryExpression expr = null; 76 77 78 protected VisitorContext context = null; 79 80 81 protected int depth = -1; 82 83 84 protected boolean normalized; 85 86 87 protected HashMap variablesDeclarations = null; 88 89 private AtomizeVisitor atomizeVisitor = new AtomizeVisitor(typeVisitor); 90 91 private String sourceName = null; 92 93 94 95 96 protected final String DEFAULT_XML_PREFIX = "xml"; 97 98 99 protected final String DEFAULT_XML_URL = "http://www.w3.org/XML/1998/namespace"; 100 101 102 protected final String DEFAULT_SCHEMA_PREFIX = "xs"; 103 104 105 protected final String DEFAULT_SCHEMA_URL = "http://www.w3.org/2001/XMLSchema"; 106 107 108 protected final String DEFAULT_SCHEMA_INSTANCE_PREFIX = "xsi"; 109 110 111 protected final String DEFAULT_SCHEMA_INSTANCE_URL = "http://www.w3.org/2001/XMLSchema-instance"; 112 113 114 protected final String DEFAULT_FUNCTION_PREFIX = "xf"; 115 116 117 protected final String DEFAULT_FUNCTION_URL = "http://www.w3.org/2002/08/xquery-functions"; 118 119 120 protected final String DEFAULT_OPERATOR_PREFIX = "op"; 121 122 123 protected final String DEFAULT_OPERATOR_URL = "http://www.w3.org/2002/08/xquery-operators"; 124 125 126 127 132 142 public ExpressionNormalizationVisitor(TypeVisitor typeVisitor, String sourceName) throws NormalizeException { 143 this(new VisitorContext(), -1, typeVisitor, sourceName); 144 } 145 146 153 165 protected ExpressionNormalizationVisitor(int depth, TypeVisitor typeVisitor, String sourceName) throws NormalizeException { 166 this(new VisitorContext(), depth, typeVisitor, sourceName); 167 } 168 169 180 protected ExpressionNormalizationVisitor(VisitorContext ctx, int depth, TypeVisitor typeVisitor, String sourceName) throws NormalizeException { 181 this.context = ctx; 182 this.expr = null; 183 this.depth = depth + 1; 184 this.normalized = false; 185 this.typeVisitor = typeVisitor; 186 this.sourceName = sourceName; 187 } 188 189 190 191 private FLWRExpression createDummyFLWR(XQueryExpression whereClause, XQueryExpression returnClause) throws XQueryException, TypeException { 192 Variable var = typeVisitor.getStaticContext().createVariable(Constants.FOR_BINDINGTYPE, new ValueInteger("1", returnClause.getParentModule()), Variable.NORM_CREATOR); 193 ArrayList vars = new ArrayList(1); 194 vars.add(var); 195 XQueryModule unit = returnClause.getParentModule(); 196 FLWRExpression flwr = new FLWRExpression(vars, null, whereClause, returnClause, returnClause.getParentModule()); 197 flwr.setParentModule(unit); 198 return flwr; 199 } 200 201 206 protected VisitorContext getContext() { 207 return this.context; 208 } 209 210 216 protected void setContext(VisitorContext ctx) { 217 this.context = ctx; 218 } 219 220 225 protected int getDepth() { 226 return this.depth; 227 } 228 229 230 231 236 public void reInit() throws NormalizeException { 237 this.context = new VisitorContext(); 238 this.expr = null; 239 this.depth = 0; 240 this.normalized = false; 241 } 242 243 248 public XQueryExpression getExpr() { 249 return this.expr; 250 } 251 252 257 public boolean wasNormalized() { 258 return this.normalized; 259 } 260 261 262 263 264 265 272 public void visit(XQueryModule arg) throws NormalizeException { 273 typeVisitor.setNoForce(false); 275 try { 277 ExpressionNormalizationVisitor recurseVisitor = new ExpressionNormalizationVisitor(this.depth, typeVisitor, sourceName); 278 int pass = 0; 279 boolean removed = false; 281 do { 283 normalized = false; 284 pass++; 285 289 293 ArrayList expressions = arg.getExpressions(); 295 if (expressions != null) { 296 int exprLen = expressions.size(); 297 for (int i = exprLen - 1; i >= 0; i--) { 298 recurseVisitor.reInit(); 299 XQueryExpression expri = (XQueryExpression) expressions.get(i); 300 expri.accept(recurseVisitor); 301 XQueryExpression newExpr = recurseVisitor.getExpr(); 302 if (newExpr == null) { 303 expressions.remove(i); 304 removed = true; 305 } else { 306 newExpr.setParentModule(arg); 308 expressions.set(i, newExpr); 309 } 310 this.normalized = this.normalized | recurseVisitor.wasNormalized(); 312 } 313 } 314 if (pass > 32) 315 throw new NormalizeException(0, "Infinite loop on normalization of " + arg + "<==\n"); 316 } while (this.normalized && !removed); 317 318 } catch (XQueryException e) { 319 throw new NormalizeException(0, e.getMessage()); 320 } 321 typeVisitor.setNoForce(true); 323 } 325 326 332 public void visit(XQueryExpression arg) throws NormalizeException { 333 this.expr = arg; 334 } 335 336 337 338 351 352 364 public void visit(UnOpMinusExpression arg) throws NormalizeException { 365 try { 366 ExpressionNormalizationVisitor recurseVisitor = new ExpressionNormalizationVisitor(this.depth, typeVisitor, sourceName); 367 VisitorContext localCtx = new VisitorContext(); 368 localCtx.merge(this.context, false); 369 localCtx.filter(this.depth); 371 recurseVisitor.setContext(localCtx); 372 XQueryExpression anExpr = arg.getExpression(); 374 anExpr.accept(recurseVisitor); 375 localCtx.update(recurseVisitor.getContext()); 376 anExpr = recurseVisitor.getExpr(); 377 this.normalized = recurseVisitor.wasNormalized(); 379 if (this.normalized) { 381 if (anExpr != null) { 382 arg.setExpression(anExpr); 384 if (reType) { 386 arg.accept(typeVisitor); 387 } 388 } else { 389 arg = null; 390 } 391 } 392 this.expr = arg; 393 this.context.update(localCtx); 395 } catch (XQueryException e) { 396 throw new NormalizeException(0, e); 397 } 398 } 399 400 414 public void visit(BinOpANDExpression arg) throws NormalizeException { 415 try { 416 ExpressionNormalizationVisitor recurseVisitor = new ExpressionNormalizationVisitor(this.depth, typeVisitor, sourceName); 417 VisitorContext localCtx = new VisitorContext(); 418 localCtx.merge(this.context, false); 419 localCtx.filter(this.depth); 421 recurseVisitor.setContext(localCtx); 422 localCtx.setMemo((this.depth + 1), VisitorContext._MULTIVALUED_NEEDEXISTSFUNCTION, null, true); 424 XQueryExpression expr1 = arg.getExpression1(); 426 expr1.accept(recurseVisitor); 427 localCtx.update(recurseVisitor.getContext()); 428 expr1 = recurseVisitor.getExpr(); 429 this.normalized = recurseVisitor.wasNormalized(); 431 if (this.normalized) { 433 if (expr1 != null) { 434 arg.setExpression1(expr1); 436 } else { 437 arg = null; 438 } 439 } 440 XQueryExpression expr2 = null; 442 if (arg != null) { 443 expr2 = arg.getExpression2(); 444 expr2.accept(recurseVisitor); 445 localCtx.update(recurseVisitor.getContext()); 446 expr2 = recurseVisitor.getExpr(); 447 this.normalized = this.normalized | recurseVisitor.wasNormalized(); 449 if (recurseVisitor.wasNormalized()) { 451 if (expr2 != null) { 452 arg.setExpression2(expr2); 454 } else { 455 arg = null; 456 } 457 } 458 } 459 localCtx.removeMemo((this.depth + 1), VisitorContext._MULTIVALUED_NEEDEXISTSFUNCTION); 461 if (arg == null) { 463 this.expr = new FunctionFALSE(null, arg.getParentModule()); 465 this.normalized = true; 466 } else if ((expr1 instanceof FunctionFALSE) || (expr2 instanceof FunctionFALSE)) { 467 this.expr = new FunctionFALSE(null, arg.getParentModule()); 469 this.normalized = true; 470 } else if ((expr1 instanceof FunctionTRUE) && (expr2 instanceof FunctionTRUE)) { 471 this.expr = new FunctionTRUE(null, arg.getParentModule()); 473 this.normalized = true; 474 } else if (expr1 instanceof FunctionTRUE) { 475 this.expr = expr2; 476 this.normalized = true; 477 } else if (expr2 instanceof FunctionTRUE) { 478 this.expr = expr1; 479 this.normalized = true; 480 } else { 481 this.expr = arg; 482 } 483 if (reType && this.normalized && (this.expr != null)) { 485 this.expr.accept(typeVisitor); 486 } 487 this.context.update(localCtx); 489 } catch (XQueryException e) { 490 throw new NormalizeException(0, e); 491 } 492 } 493 494 508 public void visit(BinOpORExpression arg) throws NormalizeException { 509 try { 510 ExpressionNormalizationVisitor recurseVisitor = new ExpressionNormalizationVisitor(this.depth, typeVisitor, sourceName); 511 VisitorContext localCtx = new VisitorContext(); 512 localCtx.merge(this.context, false); 513 localCtx.filter(this.depth); 515 recurseVisitor.setContext(localCtx); 516 localCtx.setMemo((this.depth + 1), VisitorContext._MULTIVALUED_NEEDEXISTSFUNCTION, null, true); 518 XQueryExpression expr1 = arg.getExpression1(); 520 expr1.accept(recurseVisitor); 521 localCtx.update(recurseVisitor.getContext()); 522 expr1 = recurseVisitor.getExpr(); 523 this.normalized = recurseVisitor.wasNormalized(); 525 if ((this.normalized) && (expr1 != null)) { 526 arg.setExpression1(expr1); 527 } 528 XQueryExpression expr2 = arg.getExpression2(); 530 expr2.accept(recurseVisitor); 531 localCtx.update(recurseVisitor.getContext()); 532 expr2 = recurseVisitor.getExpr(); 533 this.normalized = this.normalized | recurseVisitor.wasNormalized(); 535 if ((recurseVisitor.wasNormalized()) && (expr2 != null)) { 536 arg.setExpression2(expr2); 537 } 538 localCtx.removeMemo((this.depth + 1), VisitorContext._MULTIVALUED_NEEDEXISTSFUNCTION); 540 if (expr1 == null) { 542 this.normalized = true; 543 if (expr2 == null) { 544 this.expr = new FunctionFALSE(null, arg.getParentModule()); 545 } else if (expr2 instanceof FunctionFALSE) { 546 this.expr = new FunctionFALSE(null, arg.getParentModule()); 547 } else if (expr2 instanceof FunctionTRUE) { 548 this.expr = new FunctionTRUE(null, arg.getParentModule()); 549 } else { 550 this.expr = expr2; 551 } 552 } else if (expr1 instanceof FunctionFALSE) { 553 this.normalized = true; 554 if (expr2 == null) { 555 this.expr = new FunctionFALSE(null, arg.getParentModule()); 556 } else if (expr2 instanceof FunctionFALSE) { 557 this.expr = new FunctionFALSE(null, arg.getParentModule()); 558 } else if (expr2 instanceof FunctionTRUE) { 559 this.expr = new FunctionTRUE(null, arg.getParentModule()); 560 } else { 561 this.expr = expr2; 562 } 563 } else if (expr1 instanceof FunctionTRUE) { 564 this.normalized = true; 565 this.expr = new FunctionTRUE(null, arg.getParentModule()); 566 } else { 567 if (expr2 == null) { 568 this.expr = expr1; 569 this.normalized = true; 570 } else if (expr2 instanceof FunctionFALSE) { 571 this.expr = expr1; 572 this.normalized = true; 573 } else if (expr2 instanceof FunctionTRUE) { 574 this.expr = new FunctionTRUE(null, arg.getParentModule()); 575 this.normalized = true; 576 } else { 577 this.expr = arg; 578 } 579 } 580 if (reType && this.normalized && this.expr != null) { 582 this.expr.accept(typeVisitor); 583 } 584 this.context.update(localCtx); 586 } catch (XQueryException e) { 587 throw new NormalizeException(0, e); 588 } 589 } 590 591 605 public void visit(ListOpArithExpression arg) throws NormalizeException { 606 try { 607 ExpressionNormalizationVisitor recurseVisitor = new ExpressionNormalizationVisitor(this.depth, typeVisitor, sourceName); 608 VisitorContext localCtx = new VisitorContext(); 609 localCtx.merge(this.context, false); 610 localCtx.filter(this.depth); 612 recurseVisitor.setContext(localCtx); 613 XQueryExpression expr1 = arg.getExpression1(); 615 expr1.accept(recurseVisitor); 616 localCtx.update(recurseVisitor.getContext()); 617 expr1 = recurseVisitor.getExpr(); 618 expr1.accept(atomizeVisitor); 619 expr1 = atomizeVisitor.getExpression(); 620 this.normalized = recurseVisitor.wasNormalized(); 622 if (this.normalized) { 623 if (expr1 != null) { 624 arg.setExpression1(expr1); 625 } else { 626 arg = null; 627 } 628 } 629 XQueryExpression expr2 = null; 631 if (arg != null) { 632 expr2 = arg.getExpression2(); 633 expr2.accept(recurseVisitor); 634 localCtx.update(recurseVisitor.getContext()); 635 expr2 = recurseVisitor.getExpr(); 636 expr2.accept(atomizeVisitor); 637 expr2 = atomizeVisitor.getExpression(); 638 this.normalized = this.normalized | recurseVisitor.wasNormalized(); 640 if (recurseVisitor.wasNormalized()) { 641 if (expr2 != null) { 642 arg.setExpression2(expr2); 643 } else { 644 arg = null; 645 } 646 } 647 } 648 this.expr = arg; 649 if (reType && this.normalized && this.expr != null) { 651 this.expr.accept(typeVisitor); 652 } 653 this.context.update(localCtx); 655 } catch (XQueryException e) { 656 throw new NormalizeException(0, e); 657 } 658 } 659 660 674 675 public void visit(ListOpCompExpression arg) throws NormalizeException { 676 try { 677 ExpressionNormalizationVisitor recurseVisitor = new ExpressionNormalizationVisitor(this.depth, typeVisitor, sourceName); 678 VisitorContext localCtx = new VisitorContext(); 679 localCtx.merge(this.context, false); 680 localCtx.filter(this.depth); 682 recurseVisitor.setContext(localCtx); 683 XQueryExpression expr1 = arg.getExpression1(); 685 expr1.accept(recurseVisitor); 686 localCtx.update(recurseVisitor.getContext()); 687 expr1 = recurseVisitor.getExpr(); 688 expr1.accept(atomizeVisitor); 689 expr1 = atomizeVisitor.getExpression(); 690 this.normalized = this.normalized | recurseVisitor.wasNormalized(); 692 if (this.normalized) { 693 if (expr1 != null) { 694 arg.setExpression1(expr1); 695 } else { 696 arg = null; 697 } 698 } 699 XQueryExpression expr2 = null; 701 if (arg != null) { 702 expr2 = arg.getExpression2(); 703 expr2.accept(recurseVisitor); 704 localCtx.update(recurseVisitor.getContext()); 705 expr2 = recurseVisitor.getExpr(); 706 expr2.accept(atomizeVisitor); 707 expr2 = atomizeVisitor.getExpression(); 708 this.normalized = this.normalized | recurseVisitor.wasNormalized(); 710 if (recurseVisitor.wasNormalized()) { 711 if (expr2 != null) { 712 arg.setExpression2(expr2); 713 } else { 714 arg = null; 715 } 716 } 717 } 718 this.expr = arg; 719 if (reType && this.normalized && this.expr != null) { 721 this.expr.accept(typeVisitor); 722 } 723 this.context.update(localCtx); 725 } catch (XQueryException e) { 747 throw new NormalizeException(0, e); 748 } 749 } 750 751 765 public void visit(ListOpUNIONExpression arg) throws NormalizeException { 767 try { 768 ExpressionNormalizationVisitor recurseVisitor = new ExpressionNormalizationVisitor(this.depth, typeVisitor, sourceName); 769 VisitorContext localCtx = new VisitorContext(); 770 localCtx.merge(this.context, false); 771 localCtx.filter(this.depth); 773 recurseVisitor.setContext(localCtx); 774 XQueryExpression expr1 = arg.getExpression1(); 776 expr1.accept(recurseVisitor); 777 localCtx.update(recurseVisitor.getContext()); 778 expr1 = recurseVisitor.getExpr(); 779 this.normalized = recurseVisitor.wasNormalized(); 781 if ((this.normalized) && (expr1 != null)) { 782 arg.setExpression1(expr1); 783 } 784 XQueryExpression expr2 = arg.getExpression2(); 786 expr2.accept(recurseVisitor); 787 |