001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 /*
019 * $Id: XPathExpressionImpl.java 1225426 2011-12-29 04:13:08Z mrglavas $
020 */
021
022
023 package org.apache.xpath.domapi;
024
025 import javax.xml.transform.TransformerException;
026
027 import org.apache.xpath.XPath;
028 import org.apache.xpath.XPathContext;
029 import org.apache.xpath.objects.XObject;
030 import org.apache.xpath.res.XPATHErrorResources;
031 import org.apache.xpath.res.XPATHMessages;
032 import org.w3c.dom.DOMException;
033 import org.w3c.dom.Document;
034 import org.w3c.dom.Node;
035 import org.w3c.dom.xpath.XPathException;
036 import org.w3c.dom.xpath.XPathExpression;
037 import org.w3c.dom.xpath.XPathNamespace;
038
039 /**
040 *
041 * The class provides an implementation of XPathExpression according
042 * to the DOM L3 XPath Specification, Working Group Note 26 February 2004.
043 *
044 * <p>See also the <a href='http://www.w3.org/TR/2004/NOTE-DOM-Level-3-XPath-20040226'>Document Object Model (DOM) Level 3 XPath Specification</a>.</p>
045 *
046 * <p>The <code>XPathExpression</code> interface represents a parsed and resolved
047 * XPath expression.</p>
048 *
049 * @see org.w3c.dom.xpath.XPathExpression
050 *
051 * @xsl.usage internal
052 */
053 class XPathExpressionImpl implements XPathExpression {
054
055 /**
056 * The xpath object that this expression wraps
057 */
058 final private XPath m_xpath;
059
060 /**
061 * The document to be searched to parallel the case where the XPathEvaluator
062 * is obtained by casting a Document.
063 */
064 final private Document m_doc;
065
066 /**
067 * Constructor for XPathExpressionImpl.
068 *
069 * @param xpath The wrapped XPath object.
070 * @param doc The document to be searched, to parallel the case where''
071 * the XPathEvaluator is obtained by casting the document.
072 */
073 XPathExpressionImpl(XPath xpath, Document doc) {
074 m_xpath = xpath;
075 m_doc = doc;
076 }
077
078 /**
079 *
080 * This method provides an implementation XPathResult.evaluate according
081 * to the DOM L3 XPath Specification, Working Group Note 26 February 2004.
082 *
083 * <p>See also the <a href='http://www.w3.org/TR/2004/NOTE-DOM-Level-3-XPath-20040226'>Document Object Model (DOM) Level 3 XPath Specification</a>.</p>
084 *
085 * <p>Evaluates this XPath expression and returns a result.</p>
086 * @param contextNode The <code>context</code> is context node for the
087 * evaluation of this XPath expression.If the XPathEvaluator was
088 * obtained by casting the <code>Document</code> then this must be
089 * owned by the same document and must be a <code>Document</code>,
090 * <code>Element</code>, <code>Attribute</code>, <code>Text</code>,
091 * <code>CDATASection</code>, <code>Comment</code>,
092 * <code>ProcessingInstruction</code>, or <code>XPathNamespace</code>
093 * node.If the context node is a <code>Text</code> or a
094 * <code>CDATASection</code>, then the context is interpreted as the
095 * whole logical text node as seen by XPath, unless the node is empty
096 * in which case it may not serve as the XPath context.
097 * @param type If a specific <code>type</code> is specified, then the
098 * result will be coerced to return the specified type relying on
099 * XPath conversions and fail if the desired coercion is not possible.
100 * This must be one of the type codes of <code>XPathResult</code>.
101 * @param result The <code>result</code> specifies a specific result
102 * object which may be reused and returned by this method. If this is
103 * specified as <code>null</code>or the implementation does not reuse
104 * the specified result, a new result object will be constructed and
105 * returned.For XPath 1.0 results, this object will be of type
106 * <code>XPathResult</code>.
107 * @return The result of the evaluation of the XPath expression.For XPath
108 * 1.0 results, this object will be of type <code>XPathResult</code>.
109 * @exception XPathException
110 * TYPE_ERR: Raised if the result cannot be converted to return the
111 * specified type.
112 * @exception DOMException
113 * WRONG_DOCUMENT_ERR: The Node is from a document that is not supported
114 * by the XPathEvaluator that created this
115 * <code>XPathExpression</code>.
116 * <br>NOT_SUPPORTED_ERR: The Node is not a type permitted as an XPath
117 * context node.
118 *
119 * @see org.w3c.dom.xpath.XPathExpression#evaluate(Node, short, XPathResult)
120 * @xsl.usage internal
121 */
122 public Object evaluate(
123 Node contextNode,
124 short type,
125 Object result)
126 throws XPathException, DOMException {
127
128 // If the XPathEvaluator was determined by "casting" the document
129 if (m_doc != null) {
130
131 // Check that the context node is owned by the same document
132 if ((contextNode != m_doc) && (!contextNode.getOwnerDocument().equals(m_doc))) {
133 String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_WRONG_DOCUMENT, null);
134 throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, fmsg);
135 }
136
137 // Check that the context node is an acceptable node type
138 short nodeType = contextNode.getNodeType();
139 if ((nodeType != Document.DOCUMENT_NODE) &&
140 (nodeType != Document.ELEMENT_NODE) &&
141 (nodeType != Document.ATTRIBUTE_NODE) &&
142 (nodeType != Document.TEXT_NODE) &&
143 (nodeType != Document.CDATA_SECTION_NODE) &&
144 (nodeType != Document.COMMENT_NODE) &&
145 (nodeType != Document.PROCESSING_INSTRUCTION_NODE) &&
146 (nodeType != XPathNamespace.XPATH_NAMESPACE_NODE)) {
147 String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_WRONG_NODETYPE, null);
148 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, fmsg);
149 }
150 }
151
152 //
153 // If the type is not a supported type, throw an exception and be
154 // done with it!
155 if (!XPathResultImpl.isValidType(type)) {
156 String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_INVALID_XPATH_TYPE, new Object[] {new Integer(type)});
157 throw new XPathException(XPathException.TYPE_ERR,fmsg); // Invalid XPath type argument: {0}
158 }
159
160 // Create an XPathContext that doesn't support pushing and popping of
161 // variable resolution scopes. Sufficient for simple XPath 1.0
162 // expressions.
163 // Cache xpath context?
164 XPathContext xpathSupport = new XPathContext(false);
165
166 // if m_document is not null, build the DTM from the document
167 if (null != m_doc) {
168 xpathSupport.getDTMHandleFromNode(m_doc);
169 }
170
171 XObject xobj = null;
172 try {
173 xobj = m_xpath.execute(xpathSupport, contextNode, null);
174 } catch (TransformerException te) {
175 // What should we do here?
176 throw new XPathException(XPathException.INVALID_EXPRESSION_ERR,te.getMessageAndLocation());
177 }
178
179 // Create a new XPathResult object
180 // Reuse result object passed in?
181 // The constructor will check the compatibility of type and xobj and
182 // throw an exception if they are not compatible.
183 return new XPathResultImpl(type,xobj,contextNode, m_xpath);
184 }
185
186 }