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 }