1 22 23 package org.xquark.xml.xqueryevaluator.eval; 24 25 import java.util.*; 26 27 import org.w3c.dom.Attr ; 28 import org.w3c.dom.Comment ; 29 import org.xml.sax.Attributes ; 30 import org.xml.sax.SAXException ; 31 import org.xml.sax.ext.LexicalHandler ; 32 import org.xml.sax.helpers.DefaultHandler ; 33 import org.xquark.mediator.DOMUtils.BufferTuple; 34 import org.xquark.mediator.DOMUtils.EvaluationVisitor; 35 import org.xquark.mediator.DOMUtils.Tuple; 36 import org.xquark.mediator.plan.DynamicContext; 37 import org.xquark.mediator.runtime.MediatorException; 38 import org.xquark.schema.Type; 39 import org.xquark.schema.validation.ElementPSVInfoset; 40 import org.xquark.schema.validation.PSVInfoset; 41 import org.xquark.schema.validation.SchemaValidationContext; 42 import org.xquark.util.NamespaceContextStack; 43 import org.xquark.util.SAXConstants; 44 import org.xquark.xpath.Axis; 45 import org.xquark.xpath.NodeKind; 46 import org.xquark.xpath.datamodel.*; 47 import org.xquark.xquery.parser.*; 48 import org.xquark.xquery.parser.primitivefunctions.fnfunctions.FunctionDOC; 49 import org.xquark.xquery.parser.util.Constants; 50 51 54 public class SAX2TypedDOM extends DefaultHandler implements LexicalHandler { 55 59 private static final String RCSRevision = "$Revision: 1.11 $"; 60 private static final String RCSName = "$Name: $"; 61 62 private SchemaValidationContext svc = null; 63 private BufferTuple buffer = null; 64 private DynamicContext context = null; 65 private XQueryExpression whereClause = null; 66 private ArrayList computedVars = new ArrayList(); 67 private EvaluationVisitor evaluator = null; 68 private List rootFilters = new ArrayList(); 69 private NamespaceContextStack nsStack = null; 70 71 private ArrayList contexts = new ArrayList(32); 72 private int level = 0; 73 private List bindings = new ArrayList(); 74 75 private TypedDocumentImpl doc = new TypedDocumentImpl(); 76 private TypedNode currentNode = null; 77 private HashSet usedURI = new HashSet(); 78 private HashSet declaredURI = new HashSet(); 79 private StringBuffer charsRead = new StringBuffer (); 80 81 public SAX2TypedDOM(FLWRExpression flwr, BufferTuple buffer, DynamicContext context, ArrayList paths, SchemaValidationContext svc) throws MediatorException { 82 this.buffer = buffer; 83 this.context = context; 84 this.svc = svc; 85 this.nsStack = flwr.getParentModule().getDeclarations(); 86 this.evaluator = new EvaluationVisitor(svc.getSchemaManager()); 87 this.whereClause = flwr.getWhereClause(); 88 List variables = flwr.getVariables(); 89 for (int i = 0; i < variables.size(); i++) { 90 Variable v = (Variable) variables.get(i); 91 List steps = v.getExpression().getSteps(); 92 XQueryExpression rootExpr; 93 List prefix = null; 94 if (steps == null) { 95 rootExpr = v.getExpression(); 96 } else { 97 rootExpr = ((Step) steps.get(0)).getExpression(); 98 } 99 if (rootExpr instanceof FunctionDOC) { 100 if (v.getBindingType() == Constants.FOR_BINDINGTYPE) { 101 XPathExpr[] pathExprs = buildXPath(steps); 102 for (int k = 0; k < pathExprs.length; k++) { 103 VariableFilter rootFilter = new VariableFilter(v.toString(), pathExprs[k]); 104 rootFilters.add(rootFilter); 105 } 106 } else { 107 VariableFilter rootFilter = new VariableFilter("", new XPathExpr()); 108 rootFilters.add(rootFilter); 109 int index = buffer.getPathIndex(v.toString()); 110 if (index != -1) { 111 XPathExpr[] pathExprs = buildXPath(steps); 112 for (int k = 0; k < pathExprs.length; k++) { 113 rootFilter.addSubFilter(index, pathExprs[k]); 114 } 115 } 116 prefix = steps; 117 } 118 for (int j = 0; j < paths.size(); j++) { 119 XQueryExpression expr = (XQueryExpression) paths.get(j); 120 if (expr instanceof LocatedExpression && expr.getSteps().size() > 1) { 122 int index = buffer.getPathIndex(((LocatedExpression) expr).toString()); 123 XPathExpr[] pathExprs = buildXPath(expr.getSteps(), prefix); 124 for (int k = 0; k < pathExprs.length; k++) { 125 for (int l = 0; l < rootFilters.size(); l++) { 126 ((VariableFilter) rootFilters.get(l)).addSubFilter(index, pathExprs[k]); 127 } 128 } 129 } 130 } 131 } else if (steps == null) { 132 computedVars.add(v); 133 } else { 134 throw new RuntimeException ("TODO"); 136 } 137 } 138 } 139 140 private XPathExpr[] buildXPath(List steps, List prefix) throws MediatorException { 141 XPathExpr[] paths = { new XPathExpr()}; 142 if (prefix != null) { 143 for (int i = 1; i < prefix.size(); i++) { 144 paths = addStep(paths, (Step) prefix.get(i)); 145 } 146 } 147 if (steps != null) { 148 for (int i = 1; i < steps.size(); i++) { 149 paths = addStep(paths, (Step) steps.get(i)); 150 } 151 } 152 for (int i = 0; i < paths.length; i++) { 153 paths[i].removeLastSelfNodeStep(); 154 } 155 return paths; 156 } 157 158 private XPathExpr[] buildXPath(List steps) throws MediatorException { 159 return buildXPath(steps, null); 160 } 161 162 private XPathExpr[] addStep(XPathExpr[] paths, Step step) throws MediatorException { 163 QName stepName = null; 164 boolean isSelf = false; 165 boolean isAnyLevel = false; 166 XQueryExpression stepExpr = step.getExpression(); 167 switch (step.getAxis()) { 168 case Axis.DESCENDANT_OR_SELF : 169 isAnyLevel = true; 170 case Axis.SELF : 172 isSelf = true; 173 case Axis.CHILD : 175 if (stepExpr instanceof QName) { 176 stepName = (QName) stepExpr; 177 for (int i = 0; i < paths.length; i++) { 178 XPathExpr pathExpr = paths[i]; 179 pathExpr.addElementStep(stepName.getNameSpace(), stepName.getLocalName(), isAnyLevel, isSelf); 180 } 181 } else if (stepExpr instanceof NodeTest) { 182 switch (((NodeTest) stepExpr).getKind()) { 183 case NodeKind.NODE : 184 for (int i = 0; i < paths.length; i++) { 185 XPathExpr pathExpr = paths[i]; 186 pathExpr.addNodeStep(isAnyLevel, isSelf); 187 } 188 break; 189 case NodeKind.TEXT : 190 for (int i = 0; i < paths.length; i++) { 191 XPathExpr pathExpr = paths[i]; 192 pathExpr.addTextStep(isAnyLevel, isSelf); 193 } 194 break; 195 default : 196 throw new MediatorException("Unsupported XPath expression"); 197 } 198 } else { 199 throw new MediatorException("Unsupported XPath expression"); 200 } 201 break; 202 case Axis.ATTRIBUTE : 203 stepName = (QName) step.getExpression(); 204 for (int i = 0; i < paths.length; i++) { 205 XPathExpr pathExpr = paths[i]; 206 pathExpr.addAttributeStep(stepName.getNameSpace(), stepName.getLocalName(), isAnyLevel); 207 } 208 break; 209 case Axis.NONE : 210 if (stepExpr instanceof ListOpUNIONExpression) { 211 ArrayList steps1 = ((ListOpUNIONExpression) stepExpr).getExpression1().getSteps(); 212 ArrayList steps2 = ((ListOpUNIONExpression) stepExpr).getExpression2().getSteps(); 213 if (steps1 == null || steps2 == null) 214 throw new MediatorException("Unsupported XPath expression"); 215 XPathExpr[] paths1 = paths; 216 XPathExpr[] paths2 = new XPathExpr[paths.length]; 217 for (int i = 0; i < paths.length; i++) { 218 paths2[i] = (XPathExpr) paths[i].clone(); 219 } 220 for (int i = 0; i < steps1.size(); i++) 221 paths1 = addStep(paths1, (Step) steps1.get(i)); 222 for (int i = 0; i < steps2.size(); i++) 223 paths2 = addStep(paths2, (Step) steps2.get(i)); 224 paths = new XPathExpr[paths1.length + paths2.length]; 225 System.arraycopy(paths1, 0, paths, 0, paths1.length); 226 System.arraycopy(paths2, 0, paths, paths1.length, paths1.length); 227 } else { 228 throw new MediatorException("Unsupported XPath expression"); 229 } 230 break; 231 default : 232 throw new MediatorException("Unsupported XPath expression"); 233 } 234 return paths; 235 } 236 237 private void reset() { 238 level = 0; 239 contexts.clear(); 240 bindings.clear(); 241 contexts.add(new FilterContext(rootFilters)); 242 } 243 244 private FilterContext pushContext(String uri, String localName) { 245 FilterContext parent = getCurrentContext(); 246 FilterContext current; 247 level++; 248 if (level == contexts.size()) 249 contexts.add(new FilterContext()); 250 current = getCurrentContext(); 251 current.initialize(uri, localName, parent); 252 return current; 253 } 254 255 private void popContext() throws MediatorException { 256 getCurrentContext().cleanup(); 257 level--; 258 } 259 260 private FilterContext getCurrentContext() { 261 return getContext(level); 262 } 263 264 private FilterContext getContext(int i) { 265 return (FilterContext) contexts.get(i); 266 } 267 268 private void filterTuple(Tuple tuple) throws MediatorException { 269 try { 270 for (int i = 0; i < computedVars.size(); i++) { 271 Variable var = (Variable) computedVars.get(i); 272 int index = buffer.getPathIndex(var.getStringValue()); 273 evaluator.reset(tuple); 274 var.getExpression().accept(evaluator); 275 tuple.addNodesAtIndex(index, evaluator.getResNodes()); 276 } 277 tuple.fillIdentifiers(); 278 if (whereClause != null) { 279 context.addCurrentTuple(tuple); 280 evaluator.reset(context.getCurrentTuples()); 281 evaluator.setReturnType(EvaluationVisitor.BOOLEAN_TYPE); 282 whereClause.accept(evaluator); 283 context.deleteCurrentTuple(tuple); 284 if (evaluator.getVerdict()) 285 buffer.add(tuple); 286 } else 287 buffer.add(tuple); 288 } catch (XQueryException xe) { 289 throw new MediatorException(xe.getMessage(), xe); 290 } 291 } 292 293 private TypedAttribute buildAttribute(PSVInfoset infoset, String value) { 294 TypedAttribute attr = (TypedAttribute) doc.createAttributeNS(infoset.getNamespaceURI(), infoset.getLocalName()); 295 if (infoset.getNormalizedValue() != null) 296 attr.setNodeValue(infoset.getNormalizedValue()); 297 else 298 attr.setNodeValue(value); 299 if (infoset.getActualValue() != null) 300 attr.setTypedValue(infoset.getActualValue()); 301 else 302 attr.setTypedValue(value); 303 if (infoset.getType() != null) 304 attr.setType(infoset.getType()); 305 else 306 attr.setType(svc.getSchemaManager().getAnySimpleType()); 307 attr.setDeclaration(infoset.getDeclaration()); 308 return attr; 309 } 310 311 private TypedValue buildValue(String value, PSVInfoset infoset) { 312 TypedValue tv = (TypedValue) doc.createTextNode(value); 313 Type type = null; 314 if (infoset != null) 315 type = infoset.getType(); 316 if (type != null && type.getValueType() != null) { 317 tv.setType(type.getValueType()); 318 tv.setTypedValue(infoset.getActualValue()); 319 tv.setNodeValue(infoset.getNormalizedValue()); 320 } else { 321 tv.setType(svc.getSchemaManager().getAnySimpleType()); 323 tv.setTypedValue(value); 324 tv.setNodeValue(value); 325 } 326 return tv; 327 } 328 329 private Attr buildPrefixAttribute(String prefix, String uri) { 330 if (prefix == null || prefix.length() == 0) { 331 prefix = "xmlns"; 332 } else { 333 prefix = "xmlns:" + prefix; 334 } 335 Attr attr = doc.createAttributeNS(SAXConstants.XMLNS_URI, prefix); 336 attr.setValue(uri); 337 return attr; 338 } 339 340 private Comment buildComment(char[] chars, int start, int length) { 341 return doc.createComment(new String (chars, start, length)); 342 } 343 344 public void startDocument() throws SAXException { 345 reset(); 346 FilterContext context = getCurrentContext(); 347 if (context.isNodeNeeded()) { 348 context.filterDocument(doc); 349 currentNode = doc; 350 } 351 } 352 353 public void endDocument() throws SAXException { 354 try { 355 popContext(); 356 } catch (MediatorException e) { 357 throw new SAXException (e); 358 } 359 } 360 361 public void startElement(String uri, String local, String raw, Attributes atts) throws SAXException { 362 FilterContext context = getCurrentContext(); 363 if (charsRead.length() > 0) { 364 TypedValue tv = null; 365 String value = charsRead.toString(); 366 charsRead.setLength(0); 367 tv = context.filterValue(null, value); 368 if (currentNode != null) { 369 if (tv == null) { 370 tv = buildValue(value, null); 371 } 372 currentNode.appendChild(tv); 373 } 374 } 375 context = pushContext(uri, local); 376 TypedElement el = null; 377 ElementPSVInfoset epsvis = svc.getCurrentInfoset(); 378 if (currentNode != null || context.isNodeNeeded()) { 379 el = (TypedElement) doc.createElementNS(uri, local); 380 el.setType(epsvis.getType()); 381 el.setDeclaration(epsvis.getDeclaration()); 382 context.filterNode(el); 383 if (currentNode == null) { 385 usedURI.clear(); 387 usedURI.add(uri); 388 declaredURI.clear(); 389 declaredURI.addAll(epsvis.getNamespaceURIs()); 390 } 391 Iterator it = epsvis.getDeclaredPrefixes().iterator(); 392 while (it.hasNext()) { 393 String prefix = (String ) it.next(); 394 String nsURI = epsvis.getNamespaceURI(prefix); 395 if (currentNode == null) 397 declaredURI.remove(nsURI); 398 Collection knownPrefixes = nsStack.getPrefixes(nsURI); 400 if (knownPrefixes.isEmpty()) { 401 el.setAttributeNode(buildPrefixAttribute(prefix, nsURI)); 402 } 403 } 404 } 405 for (int i = 0; i < atts.getLength(); i++) { 406 PSVInfoset infoset = epsvis.getAttributePSVInfoset(i); 407 408 411 String attrValue = atts.getValue(i); 412 TypedAttribute attr = null; 413 attr = context.filterAttribute(infoset, attrValue); 414 if (el != null) { 415 if (attr == null) 416 attr = buildAttribute(infoset, attrValue); 417 el.setAttributeNode(attr); 418 usedURI.add(atts.getURI(i)); 419 } 420 } 421 if (currentNode != null) { 422 currentNode.appendChild(el); 423 } 424 currentNode = el; 425 } 426 427 public void characters(char[] ch, int start, int length) throws SAXException { 428 charsRead.append(ch, start, length); 429 } 430 431 public void endElement(String uri, String local, String raw) throws SAXException { 432 FilterContext context = getCurrentContext(); 433 ElementPSVInfoset epsvis = svc.getCurrentInfoset(); 434 if (charsRead.length() > 0) { 435 TypedValue tv = null; 436 String value = charsRead.toString(); 437 charsRead.setLength(0); 438 tv = context.filterValue(epsvis, value); 439 if (currentNode != null) { 440 if (tv == null) { 441 tv = buildValue(value, epsvis); 442 } 443 currentNode.appendChild(tv); 444 } 445 } 446 if (currentNode != null) { 447 if (currentNode.getParentNode() == null) { 448 Iterator it = usedURI.iterator(); 449 while (it.hasNext()) { 450 String used = (String ) it.next(); 451 if (declaredURI.contains(used) && nsStack.getPrefixes(used).isEmpty()) { 452 String prefix = epsvis.getPrefix(used); 453 ((TypedElement) currentNode).setAttributeNode(buildPrefixAttribute(prefix, used)); 454 } 455 } 456 } 457 currentNode = (TypedNode) currentNode.getParentNode(); 458 } 459 try { 460 popContext(); 461 } catch (MediatorException e) { 462 throw new SAXException (e); 463 } 464 } 465 466 469 public void startDTD(String arg0, String arg1, String arg2) throws SAXException { 470 } 471 472 475 public void endDTD() throws SAXException { 476 } 477 478 481 public void startEntity(String arg0) throws SAXException { 482 } 483 484 487 public void endEntity(String arg0) throws SAXException { 488 } 489 490 493 public void startCDATA() throws SAXException { 494 } 495 496 499 public void endCDATA() throws SAXException { 500 } 501 502 505 public void comment(char[] chars, int start, int length) throws SAXException { 506 FilterContext context = getCurrentContext(); 507 ElementPSVInfoset epsvis = svc.getCurrentInfoset(); 508 if (charsRead.length() > 0) { 509 TypedValue tv = null; 510 String value = charsRead.toString(); 511 charsRead.setLength(0); 512 tv = context.filterValue(epsvis, value); 513 if (currentNode != null) { 514 if (tv == null) { 515 tv = buildValue(value, epsvis); 516 } 517 currentNode.appendChild(tv); 518 } 519 } 520 if (currentNode != null) 521 currentNode.appendChild(buildComment(chars, start, length)); 522 } 523 524 class FilterContext { 525 526 private boolean nodeNeeded = false; 527 private List filters = new ArrayList(); 528 private boolean bindingRoot = false; 529 530 FilterContext(List fList) { 531 Tuple tuple = null; 532 for (int i = 0; i < fList.size(); i++) { 533 VariableFilter xf = (VariableFilter) fList.get(i); 534 filters.add(xf); 535 if (xf.isDone()) { 536 if (xf.isBinding()) { 537 bindingRoot = bindingRoot || bindings.isEmpty(); 538 if (tuple == null) { 539 tuple = buffer.newTuple(); 540 bindings.add(tuple); 541 } 542 xf.setTuple(tuple); 543 } 544 nodeNeeded = nodeNeeded || xf.isNodeNeeded(); 545 List subFilters = xf.getSubFilters(); 546 if (subFilters != null) { 547 Iterator itsub = subFilters.iterator(); 548 while (itsub.hasNext()) { 549 NodeFilter sub = (NodeFilter) itsub.next(); 550 filters.add(sub); 551 if (sub.isDone() || sub.matchSelfNode()) 552 nodeNeeded = nodeNeeded || sub.isNodeNeeded(); 553 } 554 } 555 } 556 } 557 } 558 559 FilterContext() { 560 } 561 562 567 void initialize(String uri, String localName, FilterContext parent) { 568 if (uri != null && uri.length() == 0) 569 uri = null; 570 filters.clear(); 571 nodeNeeded = parent.isNodeNeeded(); 572 Tuple tuple = null; 573 Iterator it = parent.filters.iterator(); 574 while (it.hasNext()) { 575 NodeFilter xf = (NodeFilter) it.next(); 576 if (xf.pushElement(uri, localName)) { 577 filters.add(xf); 578 582 if (xf.matchDescendantOrSelfStep(uri, localName)) { 583 xf = (NodeFilter) xf.fork(uri, localName); 584 filters.add(xf); 585 } 586 if (xf.isDone() || xf.matchSelf(uri, localName)) { 587 if (xf.isBinding()) { 588 bindingRoot = bindingRoot || bindings.isEmpty(); 589 if (tuple == null) { 590 tuple = buffer.newTuple(); 591 bindings.add(tuple); 592 } 593 xf.setTuple(tuple); 594 } 595 nodeNeeded = nodeNeeded || xf.isNodeNeeded(); 596 List subFilters = xf.getSubFilters(); 597 if (subFilters != null) { 598 Iterator itsub = subFilters.iterator(); 599 while (itsub.hasNext()) { 600 NodeFilter sub = (NodeFilter) itsub.next(); 601 sub.skipSelfStep(uri, localName); 602 filters.add(sub); 603 if (sub.isDone() || sub.matchSelf(uri, localName)) 604 nodeNeeded = nodeNeeded || sub.isNodeNeeded(); 605 } 606 } 607 } 608 } 609 } 610 } 611 612 615 public void filterDocument(TypedDocument doc) { 616 Iterator it = filters.iterator(); 617 while (it.hasNext()) { 618 NodeFilter xf = (NodeFilter) it.next(); 619 if (xf.isDone() || xf.matchSelfNode()) { 620 xf.setDOMNode(doc); 621 } 622 } 623 } 624 625 628 public void filterNode(TypedElement node) { 629 Iterator it = filters.iterator(); 630 while (it.hasNext()) { 631 NodeFilter xf = (NodeFilter) it.next(); 632 String uri = node.getNamespaceURI(); 633 if (uri.length() == 0) 634 uri = null; 635 if (xf.isDone() || xf.matchSelf(uri, node.getLocalName())) { 636 xf.setDOMNode(node); 637 } 638 } 639 } 640 641 645 public TypedAttribute filterAttribute(PSVInfoset infoset, String value) { 646 String uri = infoset.getNamespaceURI(); 647 String name = infoset.getLocalName(); 648 TypedAttribute attr = null; 649 if (uri != null && uri.length() == 0) 650 uri = null; 651 Tuple tuple = null; 652 Iterator it = filters.iterator(); 653 while (it.hasNext()) { 654 NodeFilter xf = (NodeFilter) it.next(); 655 if (xf.matchAttribute(uri, name)) { 656 if (attr == null) { 657 attr = buildAttribute(infoset, value); 658 } 659 if (xf.isBinding()) { 660 bindingRoot = bindingRoot || bindings.isEmpty(); 661 if (tuple == null) { 662 tuple = buffer.newTuple(); 663 bindings.add(tuple); 664 } 665 xf = (NodeFilter) xf.clone(); 666 xf.setTuple(tuple); 667 } 668 xf.setDOMNode(attr); 669 } 670 } 671 return attr; 672 } 673 674 public TypedValue filterValue(PSVInfoset infoset, String value) { 675 TypedValue tv = null; 676 Tuple tuple = null; 677 Iterator it = filters.iterator(); 678 while (it.hasNext()) { 679 NodeFilter xf = (NodeFilter) it.next(); 680 if (xf.matchText()) { 681 if (tv == null) { 682 tv = buildValue(value, infoset); 683 } 684 if (xf.isBinding()) { 685 bindingRoot = bindingRoot || bindings.isEmpty(); 686 if (tuple == null) { 687 tuple = buffer.newTuple(); 688 bindings.add(tuple); 689 } 690 xf = (NodeFilter) xf.clone(); 691 xf.setTuple(tuple); 692 } 693 xf.setDOMNode(tv); 694 List subFilters = xf.getSubFilters(); 695 if (subFilters != null) { 696 Iterator itsub = subFilters.iterator(); 697 while (itsub.hasNext()) { 698 NodeFilter sub = (NodeFilter) itsub.next(); 699 if (sub.matchSelfText()) 700 sub.setDOMNode(tv); 701 } 702 } 703 } 704 } 705 return tv; 706 } 707 708 void flushBindings() throws MediatorException { 709 if (bindingRoot) { 710 Iterator it = bindings.iterator(); 711 while (it.hasNext()) { 712 filterTuple((Tuple) it.next()); 713 } 714 bindings.clear(); 715 bindingRoot = false; 716 } 717 } 718 719 722 boolean isNodeNeeded() { 723 return nodeNeeded; 724 } 725 726 void cleanup() throws MediatorException { 727 Iterator it = filters.iterator(); 728 while (it.hasNext()) { 729 NodeFilter xf = (NodeFilter) it.next(); 730 xf.popElement(); 731 xf.setTuple(null); 732 } 733 filters.clear(); 734 flushBindings(); 735 } 736 } 737 738 static abstract class NodeFilter extends XPathFilter { 739 740 protected List subFilters = null; 741 int colIndex; 742 743 746 public NodeFilter(XPathExpr xpath, int colIndex) { 747 super(xpath); 748 this.colIndex = colIndex; 749 } 750 751 List getSubFilters() { 752 return subFilters; 753 } 754 755 NodeFilter addSubFilter(int index, XPathExpr xpath) { 756 SubPathFilter sub = new SubPathFilter(this, index, xpath); 757 if (subFilters == null) 758 subFilters = new ArrayList(); 759 subFilters.add(sub); 760 return sub; 761 } 762 763 abstract boolean isNodeNeeded(); 764 765 768 void setDOMNode(TypedNode node) { 769 if (colIndex != -1) { 770 Tuple t = getTuple(); 771 if (t != null) { 772 List nodes = t.getNodesAtIndex(colIndex); 773 if (nodes == null || node != nodes.get(nodes.size() - 1)) 774 t.addNodeAtIndex(colIndex, node); 775 } 776 } 777 } 778 779 abstract boolean isBinding(); 780 781 abstract void setTuple(Tuple tuple); 782 783 abstract Tuple getTuple(); 784 } 785 786 class VariableFilter extends NodeFilter { 787 788 String name; 789 Tuple tuple = null; 790 791 794 VariableFilter(String name, XPathExpr xpath) { 795 super(xpath, buffer.getPathIndex(name)); 796 } 797 798 protected Object clone() { 799 VariableFilter result = (VariableFilter) super.clone(); 800 result.tuple = null; 801 if (subFilters != null) { 802 result.subFilters = new ArrayList(subFilters.size()); 803 for (int i = 0; i < subFilters.size(); i++) { 804 SubPathFilter sub = (SubPathFilter) subFilters.get(i); 805 result.addSubFilter(sub.colIndex, sub.xpath); 806 } 807 } 808 return result; 809 } 810 811 boolean isNodeNeeded() { 812 return colIndex != -1; 813 } 814 815 boolean isBinding() { 816 return true; 817 } 818 819 Tuple getTuple() { 820 return tuple; 821 } 822 823 void setTuple(Tuple tuple) { 824 this.tuple = tuple; 825 } 826 827 } 828 829 static class SubPathFilter extends NodeFilter { 830 831 NodeFilter parent; 832 833 836 public SubPathFilter(NodeFilter parent, int index, XPathExpr xpath) { 837 super(xpath, index); 838 this.parent = parent; 839 } 840 841 844 boolean isNodeNeeded() { 845 return true; 846 } 847 848 boolean isBinding() { 849 return false; 850 } 851 852 855 856 Tuple getTuple() { 857 return parent.getTuple(); 858 } 859 860 void setTuple(Tuple tuple) { 861 } 862 863 } 864 865 } 866 | Popular Tags |