|
|
|
|
|
*/ |
|
/* |
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
* contributor license agreements. See the NOTICE file distributed with |
|
* this work for additional information regarding copyright ownership. |
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
* (the "License"); you may not use this file except in compliance with |
|
* the License. You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
package com.sun.org.apache.xpath.internal.patterns; |
|
|
|
import com.sun.org.apache.xml.internal.dtm.DTM; |
|
import com.sun.org.apache.xml.internal.dtm.DTMFilter; |
|
import com.sun.org.apache.xml.internal.utils.QName; |
|
import com.sun.org.apache.xpath.internal.Expression; |
|
import com.sun.org.apache.xpath.internal.ExpressionOwner; |
|
import com.sun.org.apache.xpath.internal.XPath; |
|
import com.sun.org.apache.xpath.internal.XPathContext; |
|
import com.sun.org.apache.xpath.internal.XPathVisitor; |
|
import com.sun.org.apache.xpath.internal.objects.XNumber; |
|
import com.sun.org.apache.xpath.internal.objects.XObject; |
|
import java.util.ArrayList; |
|
import java.util.List; |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public class NodeTest extends Expression |
|
{ |
|
static final long serialVersionUID = -5736721866747906182L; |
|
|
|
|
|
|
|
|
|
*/ |
|
public static final String WILD = "*"; |
|
|
|
|
|
|
|
|
|
*/ |
|
public static final String SUPPORTS_PRE_STRIPPING = |
|
"http://xml.apache.org/xpath/features/whitespace-pre-stripping"; |
|
|
|
|
|
|
|
|
|
*/ |
|
protected int m_whatToShow; |
|
|
|
|
|
|
|
|
|
*/ |
|
public static final int SHOW_BYFUNCTION = 0x00010000; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public int getWhatToShow() |
|
{ |
|
return m_whatToShow; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setWhatToShow(int what) |
|
{ |
|
m_whatToShow = what; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
String m_namespace; |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public String getNamespace() |
|
{ |
|
return m_namespace; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setNamespace(String ns) |
|
{ |
|
m_namespace = ns; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
protected String m_name; |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public String getLocalName() |
|
{ |
|
return (null == m_name) ? "" : m_name; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setLocalName(String name) |
|
{ |
|
m_name = name; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
XNumber m_score; |
|
|
|
|
|
|
|
|
|
*/ |
|
public static final XNumber SCORE_NODETEST = |
|
new XNumber(XPath.MATCH_SCORE_NODETEST); |
|
|
|
|
|
|
|
|
|
*/ |
|
public static final XNumber SCORE_NSWILD = |
|
new XNumber(XPath.MATCH_SCORE_NSWILD); |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static final XNumber SCORE_QNAME = |
|
new XNumber(XPath.MATCH_SCORE_QNAME); |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static final XNumber SCORE_OTHER = |
|
new XNumber(XPath.MATCH_SCORE_OTHER); |
|
|
|
|
|
|
|
|
|
*/ |
|
public static final XNumber SCORE_NONE = |
|
new XNumber(XPath.MATCH_SCORE_NONE); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public NodeTest(int whatToShow, String namespace, String name) |
|
{ |
|
initNodeTest(whatToShow, namespace, name); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public NodeTest(int whatToShow) |
|
{ |
|
initNodeTest(whatToShow); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public boolean deepEquals(Expression expr) |
|
{ |
|
if(!isSameClass(expr)) |
|
return false; |
|
|
|
NodeTest nt = (NodeTest)expr; |
|
|
|
if(null != nt.m_name) |
|
{ |
|
if(null == m_name) |
|
return false; |
|
else if(!nt.m_name.equals(m_name)) |
|
return false; |
|
} |
|
else if(null != m_name) |
|
return false; |
|
|
|
if(null != nt.m_namespace) |
|
{ |
|
if(null == m_namespace) |
|
return false; |
|
else if(!nt.m_namespace.equals(m_namespace)) |
|
return false; |
|
} |
|
else if(null != m_namespace) |
|
return false; |
|
|
|
if(m_whatToShow != nt.m_whatToShow) |
|
return false; |
|
|
|
if(m_isTotallyWild != nt.m_isTotallyWild) |
|
return false; |
|
|
|
return true; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public NodeTest(){} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void initNodeTest(int whatToShow) |
|
{ |
|
|
|
m_whatToShow = whatToShow; |
|
|
|
calcScore(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void initNodeTest(int whatToShow, String namespace, String name) |
|
{ |
|
|
|
m_whatToShow = whatToShow; |
|
m_namespace = namespace; |
|
m_name = name; |
|
|
|
calcScore(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
private boolean m_isTotallyWild; |
|
|
|
|
|
|
|
|
|
*/ |
|
public XNumber getStaticScore() |
|
{ |
|
return m_score; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public void setStaticScore(XNumber score) |
|
{ |
|
m_score = score; |
|
} |
|
|
|
|
|
|
|
*/ |
|
protected void calcScore() |
|
{ |
|
|
|
if ((m_namespace == null) && (m_name == null)) |
|
m_score = SCORE_NODETEST; |
|
else if (((m_namespace == WILD) || (m_namespace == null)) |
|
&& (m_name == WILD)) |
|
m_score = SCORE_NODETEST; |
|
else if ((m_namespace != WILD) && (m_name == WILD)) |
|
m_score = SCORE_NSWILD; |
|
else |
|
m_score = SCORE_QNAME; |
|
|
|
m_isTotallyWild = (m_namespace == null && m_name == WILD); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public double getDefaultScore() |
|
{ |
|
return m_score.num(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static int getNodeTypeTest(int whatToShow) |
|
{ |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_ELEMENT)) |
|
return DTM.ELEMENT_NODE; |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_ATTRIBUTE)) |
|
return DTM.ATTRIBUTE_NODE; |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_TEXT)) |
|
return DTM.TEXT_NODE; |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_DOCUMENT)) |
|
return DTM.DOCUMENT_NODE; |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_DOCUMENT_FRAGMENT)) |
|
return DTM.DOCUMENT_FRAGMENT_NODE; |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_NAMESPACE)) |
|
return DTM.NAMESPACE_NODE; |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_COMMENT)) |
|
return DTM.COMMENT_NODE; |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_PROCESSING_INSTRUCTION)) |
|
return DTM.PROCESSING_INSTRUCTION_NODE; |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_DOCUMENT_TYPE)) |
|
return DTM.DOCUMENT_TYPE_NODE; |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_ENTITY)) |
|
return DTM.ENTITY_NODE; |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_ENTITY_REFERENCE)) |
|
return DTM.ENTITY_REFERENCE_NODE; |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_NOTATION)) |
|
return DTM.NOTATION_NODE; |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_CDATA_SECTION)) |
|
return DTM.CDATA_SECTION_NODE; |
|
|
|
|
|
return 0; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static void debugWhatToShow(int whatToShow) |
|
{ |
|
|
|
List<String> v = new ArrayList<>(); |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_ATTRIBUTE)) |
|
v.add("SHOW_ATTRIBUTE"); |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_NAMESPACE)) |
|
v.add("SHOW_NAMESPACE"); |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_CDATA_SECTION)) |
|
v.add("SHOW_CDATA_SECTION"); |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_COMMENT)) |
|
v.add("SHOW_COMMENT"); |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_DOCUMENT)) |
|
v.add("SHOW_DOCUMENT"); |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_DOCUMENT_FRAGMENT)) |
|
v.add("SHOW_DOCUMENT_FRAGMENT"); |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_DOCUMENT_TYPE)) |
|
v.add("SHOW_DOCUMENT_TYPE"); |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_ELEMENT)) |
|
v.add("SHOW_ELEMENT"); |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_ENTITY)) |
|
v.add("SHOW_ENTITY"); |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_ENTITY_REFERENCE)) |
|
v.add("SHOW_ENTITY_REFERENCE"); |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_NOTATION)) |
|
v.add("SHOW_NOTATION"); |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_PROCESSING_INSTRUCTION)) |
|
v.add("SHOW_PROCESSING_INSTRUCTION"); |
|
|
|
if (0 != (whatToShow & DTMFilter.SHOW_TEXT)) |
|
v.add("SHOW_TEXT"); |
|
|
|
int n = v.size(); |
|
|
|
for (int i = 0; i < n; i++) |
|
{ |
|
if (i > 0) |
|
System.out.print(" | "); |
|
|
|
System.out.print(v.get(i)); |
|
} |
|
|
|
if (0 == n) |
|
System.out.print("empty whatToShow: " + whatToShow); |
|
|
|
System.out.println(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static final boolean subPartMatch(String p, String t) |
|
{ |
|
|
|
// boolean b = (p == t) || ((null != p) && ((t == WILD) || p.equals(t))); |
|
|
|
return (p == t) || ((null != p) && ((t == WILD) || p.equals(t))); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static final boolean subPartMatchNS(String p, String t) |
|
{ |
|
|
|
return (p == t) |
|
|| ((null != p) |
|
&& ((p.length() > 0) |
|
? ((t == WILD) || p.equals(t)) : null == t)); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public XObject execute(XPathContext xctxt, int context) |
|
throws javax.xml.transform.TransformerException |
|
{ |
|
|
|
DTM dtm = xctxt.getDTM(context); |
|
short nodeType = dtm.getNodeType(context); |
|
|
|
if (m_whatToShow == DTMFilter.SHOW_ALL) |
|
return m_score; |
|
|
|
int nodeBit = (m_whatToShow & (0x00000001 << (nodeType - 1))); |
|
|
|
switch (nodeBit) |
|
{ |
|
case DTMFilter.SHOW_DOCUMENT_FRAGMENT : |
|
case DTMFilter.SHOW_DOCUMENT : |
|
return SCORE_OTHER; |
|
case DTMFilter.SHOW_COMMENT : |
|
return m_score; |
|
case DTMFilter.SHOW_CDATA_SECTION : |
|
case DTMFilter.SHOW_TEXT : |
|
|
|
// was: |
|
// return (!xctxt.getDOMHelper().shouldStripSourceNode(context)) |
|
|
|
return m_score; |
|
case DTMFilter.SHOW_PROCESSING_INSTRUCTION : |
|
return subPartMatch(dtm.getNodeName(context), m_name) |
|
? m_score : SCORE_NONE; |
|
|
|
// From the draft: "Two expanded names are equal if they |
|
// have the same local part, and either both have no URI or |
|
// both have the same URI." |
|
// "A node test * is true for any node of the principal node type. |
|
// For example, child::* will select all element children of the |
|
// context node, and attribute::* will select all attributes of |
|
// the context node." |
|
// "A node test can have the form NCName:*. In this case, the prefix |
|
// is expanded in the same way as with a QName using the context |
|
// namespace declarations. The node test will be true for any node |
|
// of the principal type whose expanded name has the URI to which |
|
|
|
case DTMFilter.SHOW_NAMESPACE : |
|
{ |
|
String ns = dtm.getLocalName(context); |
|
|
|
return (subPartMatch(ns, m_name)) ? m_score : SCORE_NONE; |
|
} |
|
case DTMFilter.SHOW_ATTRIBUTE : |
|
case DTMFilter.SHOW_ELEMENT : |
|
{ |
|
return (m_isTotallyWild || (subPartMatchNS(dtm.getNamespaceURI(context), m_namespace) && subPartMatch(dtm.getLocalName(context), m_name))) |
|
? m_score : SCORE_NONE; |
|
} |
|
default : |
|
return SCORE_NONE; |
|
} // end switch(testType) |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public XObject execute(XPathContext xctxt, int context, |
|
DTM dtm, int expType) |
|
throws javax.xml.transform.TransformerException |
|
{ |
|
|
|
if (m_whatToShow == DTMFilter.SHOW_ALL) |
|
return m_score; |
|
|
|
int nodeBit = (m_whatToShow & (0x00000001 |
|
<< ((dtm.getNodeType(context)) - 1))); |
|
|
|
switch (nodeBit) |
|
{ |
|
case DTMFilter.SHOW_DOCUMENT_FRAGMENT : |
|
case DTMFilter.SHOW_DOCUMENT : |
|
return SCORE_OTHER; |
|
case DTMFilter.SHOW_COMMENT : |
|
return m_score; |
|
case DTMFilter.SHOW_CDATA_SECTION : |
|
case DTMFilter.SHOW_TEXT : |
|
|
|
// was: |
|
// return (!xctxt.getDOMHelper().shouldStripSourceNode(context)) |
|
|
|
return m_score; |
|
case DTMFilter.SHOW_PROCESSING_INSTRUCTION : |
|
return subPartMatch(dtm.getNodeName(context), m_name) |
|
? m_score : SCORE_NONE; |
|
|
|
// From the draft: "Two expanded names are equal if they |
|
// have the same local part, and either both have no URI or |
|
// both have the same URI." |
|
// "A node test * is true for any node of the principal node type. |
|
// For example, child::* will select all element children of the |
|
// context node, and attribute::* will select all attributes of |
|
// the context node." |
|
// "A node test can have the form NCName:*. In this case, the prefix |
|
// is expanded in the same way as with a QName using the context |
|
// namespace declarations. The node test will be true for any node |
|
// of the principal type whose expanded name has the URI to which |
|
|
|
case DTMFilter.SHOW_NAMESPACE : |
|
{ |
|
String ns = dtm.getLocalName(context); |
|
|
|
return (subPartMatch(ns, m_name)) ? m_score : SCORE_NONE; |
|
} |
|
case DTMFilter.SHOW_ATTRIBUTE : |
|
case DTMFilter.SHOW_ELEMENT : |
|
{ |
|
return (m_isTotallyWild || (subPartMatchNS(dtm.getNamespaceURI(context), m_namespace) && subPartMatch(dtm.getLocalName(context), m_name))) |
|
? m_score : SCORE_NONE; |
|
} |
|
default : |
|
return SCORE_NONE; |
|
} // end switch(testType) |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public XObject execute(XPathContext xctxt) |
|
throws javax.xml.transform.TransformerException |
|
{ |
|
return execute(xctxt, xctxt.getCurrentNode()); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void fixupVariables(List<QName> vars, int globalsSize) |
|
{ |
|
// no-op |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void callVisitors(ExpressionOwner owner, XPathVisitor visitor) |
|
{ |
|
assertion(false, "callVisitors should not be called for this object!!!"); |
|
} |
|
|
|
} |