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