1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package com.sun.org.apache.xpath.internal.patterns; 22 23 import com.sun.org.apache.xml.internal.dtm.DTM; 24 import com.sun.org.apache.xml.internal.dtm.DTMFilter; 25 import com.sun.org.apache.xml.internal.utils.QName; 26 import com.sun.org.apache.xpath.internal.Expression; 27 import com.sun.org.apache.xpath.internal.ExpressionOwner; 28 import com.sun.org.apache.xpath.internal.XPath; 29 import com.sun.org.apache.xpath.internal.XPathContext; 30 import com.sun.org.apache.xpath.internal.XPathVisitor; 31 import com.sun.org.apache.xpath.internal.objects.XNumber; 32 import com.sun.org.apache.xpath.internal.objects.XObject; 33 import java.util.ArrayList; 34 import java.util.List; 35 36 /** 37 * This is the basic node test class for both match patterns and location path 38 * steps. 39 * @xsl.usage advanced 40 * @LastModified: Oct 2017 41 */ 42 public class NodeTest extends Expression 43 { 44 static final long serialVersionUID = -5736721866747906182L; 45 46 /** 47 * The namespace or local name for node tests with a wildcard. 48 * @see <a href="http://www.w3.org/TR/xpath#NT-NameTest">the XPath NameTest production.</a> 49 */ 50 public static final String WILD = "*"; 51 52 /** 53 * The URL to pass to the Node#supports method, to see if the 54 * DOM has already been stripped of whitespace nodes. 55 */ 56 public static final String SUPPORTS_PRE_STRIPPING = 57 "http://xml.apache.org/xpath/features/whitespace-pre-stripping"; 58 59 /** 60 * This attribute determines which node types are accepted. 61 * @serial 62 */ 63 protected int m_whatToShow; 64 65 /** 66 * Special bitmap for match patterns starting with a function. 67 * Make sure this does not conflict with {@link org.w3c.dom.traversal.NodeFilter}. 68 */ 69 public static final int SHOW_BYFUNCTION = 0x00010000; 70 71 /** 72 * This attribute determines which node types are accepted. 73 * These constants are defined in the {@link org.w3c.dom.traversal.NodeFilter} 74 * interface. 75 * 76 * @return bitset mainly defined in {@link org.w3c.dom.traversal.NodeFilter}. 77 */ 78 public int getWhatToShow() 79 { 80 return m_whatToShow; 81 } 82 83 /** 84 * This attribute determines which node types are accepted. 85 * These constants are defined in the {@link org.w3c.dom.traversal.NodeFilter} 86 * interface. 87 * 88 * @param what bitset mainly defined in {@link org.w3c.dom.traversal.NodeFilter}. 89 */ 90 public void setWhatToShow(int what) 91 { 92 m_whatToShow = what; 93 } 94 95 /** 96 * The namespace to be tested for, which may be null. 97 * @serial 98 */ 99 String m_namespace; 100 101 /** 102 * Return the namespace to be tested. 103 * 104 * @return The namespace to be tested for, or {@link #WILD}, or null. 105 */ 106 public String getNamespace() 107 { 108 return m_namespace; 109 } 110 111 /** 112 * Set the namespace to be tested. 113 * 114 * @param ns The namespace to be tested for, or {@link #WILD}, or null. 115 */ 116 public void setNamespace(String ns) 117 { 118 m_namespace = ns; 119 } 120 121 /** 122 * The local name to be tested for. 123 * @serial 124 */ 125 protected String m_name; 126 127 /** 128 * Return the local name to be tested. 129 * 130 * @return the local name to be tested, or {@link #WILD}, or an empty string. 131 */ 132 public String getLocalName() 133 { 134 return (null == m_name) ? "" : m_name; 135 } 136 137 /** 138 * Set the local name to be tested. 139 * 140 * @param name the local name to be tested, or {@link #WILD}, or an empty string. 141 */ 142 public void setLocalName(String name) 143 { 144 m_name = name; 145 } 146 147 /** 148 * Statically calculated score for this test. One of 149 * {@link #SCORE_NODETEST}, 150 * {@link #SCORE_NONE}, 151 * {@link #SCORE_NSWILD}, 152 * {@link #SCORE_QNAME}, or 153 * {@link #SCORE_OTHER}. 154 * @serial 155 */ 156 XNumber m_score; 157 158 /** 159 * The match score if the pattern consists of just a NodeTest. 160 * @see <a href="http://www.w3.org/TR/xslt#conflict">XSLT Specification - 5.5 Conflict Resolution for Template Rules</a> 161 */ 162 public static final XNumber SCORE_NODETEST = 163 new XNumber(XPath.MATCH_SCORE_NODETEST); 164 165 /** 166 * The match score if the pattern pattern has the form NCName:*. 167 * @see <a href="http://www.w3.org/TR/xslt#conflict">XSLT Specification - 5.5 Conflict Resolution for Template Rules</a> 168 */ 169 public static final XNumber SCORE_NSWILD = 170 new XNumber(XPath.MATCH_SCORE_NSWILD); 171 172 /** 173 * The match score if the pattern has the form 174 * of a QName optionally preceded by an @ character. 175 * @see <a href="http://www.w3.org/TR/xslt#conflict">XSLT Specification - 5.5 Conflict Resolution for Template Rules</a> 176 */ 177 public static final XNumber SCORE_QNAME = 178 new XNumber(XPath.MATCH_SCORE_QNAME); 179 180 /** 181 * The match score if the pattern consists of something 182 * other than just a NodeTest or just a qname. 183 * @see <a href="http://www.w3.org/TR/xslt#conflict">XSLT Specification - 5.5 Conflict Resolution for Template Rules</a> 184 */ 185 public static final XNumber SCORE_OTHER = 186 new XNumber(XPath.MATCH_SCORE_OTHER); 187 188 /** 189 * The match score if no match is made. 190 * @see <a href="http://www.w3.org/TR/xslt#conflict">XSLT Specification - 5.5 Conflict Resolution for Template Rules</a> 191 */ 192 public static final XNumber SCORE_NONE = 193 new XNumber(XPath.MATCH_SCORE_NONE); 194 195 /** 196 * Construct an NodeTest that tests for namespaces and node names. 197 * 198 * 199 * @param whatToShow Bit set defined mainly by {@link org.w3c.dom.traversal.NodeFilter}. 200 * @param namespace The namespace to be tested. 201 * @param name The local name to be tested. 202 */ 203 public NodeTest(int whatToShow, String namespace, String name) 204 { 205 initNodeTest(whatToShow, namespace, name); 206 } 207 208 /** 209 * Construct an NodeTest that doesn't test for node names. 210 * 211 * 212 * @param whatToShow Bit set defined mainly by {@link org.w3c.dom.traversal.NodeFilter}. 213 */ 214 public NodeTest(int whatToShow) 215 { 216 initNodeTest(whatToShow); 217 } 218 219 /** 220 * @see Expression#deepEquals(Expression) 221 */ 222 public boolean deepEquals(Expression expr) 223 { 224 if(!isSameClass(expr)) 225 return false; 226 227 NodeTest nt = (NodeTest)expr; 228 229 if(null != nt.m_name) 230 { 231 if(null == m_name) 232 return false; 233 else if(!nt.m_name.equals(m_name)) 234 return false; 235 } 236 else if(null != m_name) 237 return false; 238 239 if(null != nt.m_namespace) 240 { 241 if(null == m_namespace) 242 return false; 243 else if(!nt.m_namespace.equals(m_namespace)) 244 return false; 245 } 246 else if(null != m_namespace) 247 return false; 248 249 if(m_whatToShow != nt.m_whatToShow) 250 return false; 251 252 if(m_isTotallyWild != nt.m_isTotallyWild) 253 return false; 254 255 return true; 256 } 257 258 /** 259 * Null argument constructor. 260 */ 261 public NodeTest(){} 262 263 /** 264 * Initialize this node test by setting the whatToShow property, and 265 * calculating the score that this test will return if a test succeeds. 266 * 267 * 268 * @param whatToShow Bit set defined mainly by {@link org.w3c.dom.traversal.NodeFilter}. 269 */ 270 public void initNodeTest(int whatToShow) 271 { 272 273 m_whatToShow = whatToShow; 274 275 calcScore(); 276 } 277 278 /** 279 * Initialize this node test by setting the whatToShow property and the 280 * namespace and local name, and 281 * calculating the score that this test will return if a test succeeds. 282 * 283 * 284 * @param whatToShow Bit set defined mainly by {@link org.w3c.dom.traversal.NodeFilter}. 285 * @param namespace The namespace to be tested. 286 * @param name The local name to be tested. 287 */ 288 public void initNodeTest(int whatToShow, String namespace, String name) 289 { 290 291 m_whatToShow = whatToShow; 292 m_namespace = namespace; 293 m_name = name; 294 295 calcScore(); 296 } 297 298 /** 299 * True if this test has a null namespace and a local name of {@link #WILD}. 300 * @serial 301 */ 302 private boolean m_isTotallyWild; 303 304 /** 305 * Get the static score for this node test. 306 * @return Should be one of the SCORE_XXX constants. 307 */ 308 public XNumber getStaticScore() 309 { 310 return m_score; 311 } 312 313 /** 314 * Set the static score for this node test. 315 * @param score Should be one of the SCORE_XXX constants. 316 */ 317 public void setStaticScore(XNumber score) 318 { 319 m_score = score; 320 } 321 322 /** 323 * Static calc of match score. 324 */ 325 protected void calcScore() 326 { 327 328 if ((m_namespace == null) && (m_name == null)) 329 m_score = SCORE_NODETEST; 330 else if (((m_namespace == WILD) || (m_namespace == null)) 331 && (m_name == WILD)) 332 m_score = SCORE_NODETEST; 333 else if ((m_namespace != WILD) && (m_name == WILD)) 334 m_score = SCORE_NSWILD; 335 else 336 m_score = SCORE_QNAME; 337 338 m_isTotallyWild = (m_namespace == null && m_name == WILD); 339 } 340 341 /** 342 * Get the score that this test will return if a test succeeds. 343 * 344 * 345 * @return the score that this test will return if a test succeeds. 346 */ 347 public double getDefaultScore() 348 { 349 return m_score.num(); 350 } 351 352 /** 353 * Tell what node type to test, if not DTMFilter.SHOW_ALL. 354 * 355 * @param whatToShow Bit set defined mainly by 356 * {@link com.sun.org.apache.xml.internal.dtm.DTMFilter}. 357 * @return the node type for the whatToShow. Since whatToShow can specify 358 * multiple types, it will return the first bit tested that is on, 359 * so the caller of this function should take care that this is 360 * the function they really want to call. If none of the known bits 361 * are set, this function will return zero. 362 */ 363 public static int getNodeTypeTest(int whatToShow) 364 { 365 // %REVIEW% Is there a better way? 366 if (0 != (whatToShow & DTMFilter.SHOW_ELEMENT)) 367 return DTM.ELEMENT_NODE; 368 369 if (0 != (whatToShow & DTMFilter.SHOW_ATTRIBUTE)) 370 return DTM.ATTRIBUTE_NODE; 371 372 if (0 != (whatToShow & DTMFilter.SHOW_TEXT)) 373 return DTM.TEXT_NODE; 374 375 if (0 != (whatToShow & DTMFilter.SHOW_DOCUMENT)) 376 return DTM.DOCUMENT_NODE; 377 378 if (0 != (whatToShow & DTMFilter.SHOW_DOCUMENT_FRAGMENT)) 379 return DTM.DOCUMENT_FRAGMENT_NODE; 380 381 if (0 != (whatToShow & DTMFilter.SHOW_NAMESPACE)) 382 return DTM.NAMESPACE_NODE; 383 384 if (0 != (whatToShow & DTMFilter.SHOW_COMMENT)) 385 return DTM.COMMENT_NODE; 386 387 if (0 != (whatToShow & DTMFilter.SHOW_PROCESSING_INSTRUCTION)) 388 return DTM.PROCESSING_INSTRUCTION_NODE; 389 390 if (0 != (whatToShow & DTMFilter.SHOW_DOCUMENT_TYPE)) 391 return DTM.DOCUMENT_TYPE_NODE; 392 393 if (0 != (whatToShow & DTMFilter.SHOW_ENTITY)) 394 return DTM.ENTITY_NODE; 395 396 if (0 != (whatToShow & DTMFilter.SHOW_ENTITY_REFERENCE)) 397 return DTM.ENTITY_REFERENCE_NODE; 398 399 if (0 != (whatToShow & DTMFilter.SHOW_NOTATION)) 400 return DTM.NOTATION_NODE; 401 402 if (0 != (whatToShow & DTMFilter.SHOW_CDATA_SECTION)) 403 return DTM.CDATA_SECTION_NODE; 404 405 406 return 0; 407 } 408 409 410 /** 411 * Do a diagnostics dump of a whatToShow bit set. 412 * 413 * 414 * @param whatToShow Bit set defined mainly by 415 * {@link com.sun.org.apache.xml.internal.dtm.DTMFilter}. 416 */ 417 public static void debugWhatToShow(int whatToShow) 418 { 419 420 List<String> v = new ArrayList<>(); 421 422 if (0 != (whatToShow & DTMFilter.SHOW_ATTRIBUTE)) 423 v.add("SHOW_ATTRIBUTE"); 424 425 if (0 != (whatToShow & DTMFilter.SHOW_NAMESPACE)) 426 v.add("SHOW_NAMESPACE"); 427 428 if (0 != (whatToShow & DTMFilter.SHOW_CDATA_SECTION)) 429 v.add("SHOW_CDATA_SECTION"); 430 431 if (0 != (whatToShow & DTMFilter.SHOW_COMMENT)) 432 v.add("SHOW_COMMENT"); 433 434 if (0 != (whatToShow & DTMFilter.SHOW_DOCUMENT)) 435 v.add("SHOW_DOCUMENT"); 436 437 if (0 != (whatToShow & DTMFilter.SHOW_DOCUMENT_FRAGMENT)) 438 v.add("SHOW_DOCUMENT_FRAGMENT"); 439 440 if (0 != (whatToShow & DTMFilter.SHOW_DOCUMENT_TYPE)) 441 v.add("SHOW_DOCUMENT_TYPE"); 442 443 if (0 != (whatToShow & DTMFilter.SHOW_ELEMENT)) 444 v.add("SHOW_ELEMENT"); 445 446 if (0 != (whatToShow & DTMFilter.SHOW_ENTITY)) 447 v.add("SHOW_ENTITY"); 448 449 if (0 != (whatToShow & DTMFilter.SHOW_ENTITY_REFERENCE)) 450 v.add("SHOW_ENTITY_REFERENCE"); 451 452 if (0 != (whatToShow & DTMFilter.SHOW_NOTATION)) 453 v.add("SHOW_NOTATION"); 454 455 if (0 != (whatToShow & DTMFilter.SHOW_PROCESSING_INSTRUCTION)) 456 v.add("SHOW_PROCESSING_INSTRUCTION"); 457 458 if (0 != (whatToShow & DTMFilter.SHOW_TEXT)) 459 v.add("SHOW_TEXT"); 460 461 int n = v.size(); 462 463 for (int i = 0; i < n; i++) 464 { 465 if (i > 0) 466 System.out.print(" | "); 467 468 System.out.print(v.get(i)); 469 } 470 471 if (0 == n) 472 System.out.print("empty whatToShow: " + whatToShow); 473 474 System.out.println(); 475 } 476 477 /** 478 * Two names are equal if they and either both are null or 479 * the name t is wild and the name p is non-null, or the two 480 * strings are equal. 481 * 482 * @param p part string from the node. 483 * @param t target string, which may be {@link #WILD}. 484 * 485 * @return true if the strings match according to the rules of this method. 486 */ 487 private static final boolean subPartMatch(String p, String t) 488 { 489 490 // boolean b = (p == t) || ((null != p) && ((t == WILD) || p.equals(t))); 491 // System.out.println("subPartMatch - p: "+p+", t: "+t+", result: "+b); 492 return (p == t) || ((null != p) && ((t == WILD) || p.equals(t))); 493 } 494 495 /** 496 * This is temporary to patch over Xerces issue with representing DOM 497 * namespaces as "". 498 * 499 * @param p part string from the node, which may represent the null namespace 500 * as null or as "". 501 * @param t target string, which may be {@link #WILD}. 502 * 503 * @return true if the strings match according to the rules of this method. 504 */ 505 private static final boolean subPartMatchNS(String p, String t) 506 { 507 508 return (p == t) 509 || ((null != p) 510 && ((p.length() > 0) 511 ? ((t == WILD) || p.equals(t)) : null == t)); 512 } 513 514 /** 515 * Tell what the test score is for the given node. 516 * 517 * 518 * @param xctxt XPath runtime context. 519 * @param context The node being tested. 520 * 521 * @return {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NODETEST}, 522 * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NONE}, 523 * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NSWILD}, 524 * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_QNAME}, or 525 * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_OTHER}. 526 * 527 * @throws javax.xml.transform.TransformerException 528 */ 529 public XObject execute(XPathContext xctxt, int context) 530 throws javax.xml.transform.TransformerException 531 { 532 533 DTM dtm = xctxt.getDTM(context); 534 short nodeType = dtm.getNodeType(context); 535 536 if (m_whatToShow == DTMFilter.SHOW_ALL) 537 return m_score; 538 539 int nodeBit = (m_whatToShow & (0x00000001 << (nodeType - 1))); 540 541 switch (nodeBit) 542 { 543 case DTMFilter.SHOW_DOCUMENT_FRAGMENT : 544 case DTMFilter.SHOW_DOCUMENT : 545 return SCORE_OTHER; 546 case DTMFilter.SHOW_COMMENT : 547 return m_score; 548 case DTMFilter.SHOW_CDATA_SECTION : 549 case DTMFilter.SHOW_TEXT : 550 551 // was: 552 // return (!xctxt.getDOMHelper().shouldStripSourceNode(context)) 553 // ? m_score : SCORE_NONE; 554 return m_score; 555 case DTMFilter.SHOW_PROCESSING_INSTRUCTION : 556 return subPartMatch(dtm.getNodeName(context), m_name) 557 ? m_score : SCORE_NONE; 558 559 // From the draft: "Two expanded names are equal if they 560 // have the same local part, and either both have no URI or 561 // both have the same URI." 562 // "A node test * is true for any node of the principal node type. 563 // For example, child::* will select all element children of the 564 // context node, and attribute::* will select all attributes of 565 // the context node." 566 // "A node test can have the form NCName:*. In this case, the prefix 567 // is expanded in the same way as with a QName using the context 568 // namespace declarations. The node test will be true for any node 569 // of the principal type whose expanded name has the URI to which 570 // the prefix expands, regardless of the local part of the name." 571 case DTMFilter.SHOW_NAMESPACE : 572 { 573 String ns = dtm.getLocalName(context); 574 575 return (subPartMatch(ns, m_name)) ? m_score : SCORE_NONE; 576 } 577 case DTMFilter.SHOW_ATTRIBUTE : 578 case DTMFilter.SHOW_ELEMENT : 579 { 580 return (m_isTotallyWild || (subPartMatchNS(dtm.getNamespaceURI(context), m_namespace) && subPartMatch(dtm.getLocalName(context), m_name))) 581 ? m_score : SCORE_NONE; 582 } 583 default : 584 return SCORE_NONE; 585 } // end switch(testType) 586 } 587 588 /** 589 * Tell what the test score is for the given node. 590 * 591 * 592 * @param xctxt XPath runtime context. 593 * @param context The node being tested. 594 * 595 * @return {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NODETEST}, 596 * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NONE}, 597 * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NSWILD}, 598 * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_QNAME}, or 599 * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_OTHER}. 600 * 601 * @throws javax.xml.transform.TransformerException 602 */ 603 public XObject execute(XPathContext xctxt, int context, 604 DTM dtm, int expType) 605 throws javax.xml.transform.TransformerException 606 { 607 608 if (m_whatToShow == DTMFilter.SHOW_ALL) 609 return m_score; 610 611 int nodeBit = (m_whatToShow & (0x00000001 612 << ((dtm.getNodeType(context)) - 1))); 613 614 switch (nodeBit) 615 { 616 case DTMFilter.SHOW_DOCUMENT_FRAGMENT : 617 case DTMFilter.SHOW_DOCUMENT : 618 return SCORE_OTHER; 619 case DTMFilter.SHOW_COMMENT : 620 return m_score; 621 case DTMFilter.SHOW_CDATA_SECTION : 622 case DTMFilter.SHOW_TEXT : 623 624 // was: 625 // return (!xctxt.getDOMHelper().shouldStripSourceNode(context)) 626 // ? m_score : SCORE_NONE; 627 return m_score; 628 case DTMFilter.SHOW_PROCESSING_INSTRUCTION : 629 return subPartMatch(dtm.getNodeName(context), m_name) 630 ? m_score : SCORE_NONE; 631 632 // From the draft: "Two expanded names are equal if they 633 // have the same local part, and either both have no URI or 634 // both have the same URI." 635 // "A node test * is true for any node of the principal node type. 636 // For example, child::* will select all element children of the 637 // context node, and attribute::* will select all attributes of 638 // the context node." 639 // "A node test can have the form NCName:*. In this case, the prefix 640 // is expanded in the same way as with a QName using the context 641 // namespace declarations. The node test will be true for any node 642 // of the principal type whose expanded name has the URI to which 643 // the prefix expands, regardless of the local part of the name." 644 case DTMFilter.SHOW_NAMESPACE : 645 { 646 String ns = dtm.getLocalName(context); 647 648 return (subPartMatch(ns, m_name)) ? m_score : SCORE_NONE; 649 } 650 case DTMFilter.SHOW_ATTRIBUTE : 651 case DTMFilter.SHOW_ELEMENT : 652 { 653 return (m_isTotallyWild || (subPartMatchNS(dtm.getNamespaceURI(context), m_namespace) && subPartMatch(dtm.getLocalName(context), m_name))) 654 ? m_score : SCORE_NONE; 655 } 656 default : 657 return SCORE_NONE; 658 } // end switch(testType) 659 } 660 661 /** 662 * Test the current node to see if it matches the given node test. 663 * 664 * @param xctxt XPath runtime context. 665 * 666 * @return {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NODETEST}, 667 * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NONE}, 668 * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NSWILD}, 669 * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_QNAME}, or 670 * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_OTHER}. 671 * 672 * @throws javax.xml.transform.TransformerException 673 */ 674 public XObject execute(XPathContext xctxt) 675 throws javax.xml.transform.TransformerException 676 { 677 return execute(xctxt, xctxt.getCurrentNode()); 678 } 679 680 /** 681 * Node tests by themselves do not need to fix up variables. 682 */ 683 public void fixupVariables(List<QName> vars, int globalsSize) 684 { 685 // no-op 686 } 687 688 /** 689 * @see com.sun.org.apache.xpath.internal.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor) 690 */ 691 public void callVisitors(ExpressionOwner owner, XPathVisitor visitor) 692 { 693 assertion(false, "callVisitors should not be called for this object!!!"); 694 } 695 696 }