Back to index

lightning-sunbird  0.9+nobinonly
nsXPathExpression.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is TransforMiiX XSLT processor code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2001
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Peter Van der Beken <peterv@propagandism.org>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsXPathExpression.h"
00040 #include "Expr.h"
00041 #include "ExprResult.h"
00042 #include "nsDOMError.h"
00043 #include "nsIDOMCharacterData.h"
00044 #include "nsIDOMClassInfo.h"
00045 #include "nsIDOMDocument.h"
00046 #include "nsIDOMXPathNamespace.h"
00047 #include "nsXPathResult.h"
00048 #include "nsDOMError.h"
00049 #include "txURIUtils.h"
00050 #include "txXPathTreeWalker.h"
00051 
00052 NS_IMPL_ADDREF(nsXPathExpression)
00053 NS_IMPL_RELEASE(nsXPathExpression)
00054 NS_INTERFACE_MAP_BEGIN(nsXPathExpression)
00055   NS_INTERFACE_MAP_ENTRY(nsIDOMXPathExpression)
00056   NS_INTERFACE_MAP_ENTRY(nsIDOMNSXPathExpression)
00057   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMXPathExpression)
00058   NS_INTERFACE_MAP_ENTRY_EXTERNAL_DOM_CLASSINFO(XPathExpression)
00059 NS_INTERFACE_MAP_END
00060 
00061 nsXPathExpression::nsXPathExpression(nsAutoPtr<Expr>& aExpression,
00062                                      txResultRecycler* aRecycler)
00063     : mExpression(aExpression),
00064       mRecycler(aRecycler)
00065 {
00066 }
00067 
00068 nsXPathExpression::~nsXPathExpression()
00069 {
00070 }
00071 
00072 NS_IMETHODIMP
00073 nsXPathExpression::Evaluate(nsIDOMNode *aContextNode,
00074                             PRUint16 aType,
00075                             nsISupports *aInResult,
00076                             nsISupports **aResult)
00077 {
00078     return EvaluateWithContext(aContextNode, 1, 1, aType, aInResult, aResult);
00079 }
00080 
00081 NS_IMETHODIMP
00082 nsXPathExpression::EvaluateWithContext(nsIDOMNode *aContextNode,
00083                                        PRUint32 aContextPosition,
00084                                        PRUint32 aContextSize,
00085                                        PRUint16 aType,
00086                                        nsISupports *aInResult,
00087                                        nsISupports **aResult)
00088 {
00089     NS_ENSURE_ARG(aContextNode);
00090 
00091     if (aContextPosition > aContextSize)
00092         return NS_ERROR_FAILURE;
00093 
00094     if (!URIUtils::CanCallerAccess(aContextNode))
00095         return NS_ERROR_DOM_SECURITY_ERR;
00096 
00097     nsresult rv;
00098     PRUint16 nodeType;
00099     rv = aContextNode->GetNodeType(&nodeType);
00100     NS_ENSURE_SUCCESS(rv, rv);
00101 
00102     if (nodeType == nsIDOMNode::TEXT_NODE ||
00103         nodeType == nsIDOMNode::CDATA_SECTION_NODE) {
00104         nsCOMPtr<nsIDOMCharacterData> textNode = do_QueryInterface(aContextNode);
00105         NS_ENSURE_TRUE(textNode, NS_ERROR_FAILURE);
00106 
00107         if (textNode) {
00108             PRUint32 textLength;
00109             textNode->GetLength(&textLength);
00110             if (textLength == 0)
00111                 return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
00112         }
00113 
00114         // XXX Need to get logical XPath text node for CDATASection
00115         //     and Text nodes.
00116     }
00117     else if (nodeType != nsIDOMNode::DOCUMENT_NODE &&
00118              nodeType != nsIDOMNode::ELEMENT_NODE &&
00119              nodeType != nsIDOMNode::ATTRIBUTE_NODE &&
00120              nodeType != nsIDOMNode::COMMENT_NODE &&
00121              nodeType != nsIDOMNode::PROCESSING_INSTRUCTION_NODE &&
00122              nodeType != nsIDOMXPathNamespace::XPATH_NAMESPACE_NODE) {
00123         return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
00124     }
00125 
00126     NS_ENSURE_ARG(aResult);
00127     *aResult = nsnull;
00128 
00129     nsAutoPtr<txXPathNode> contextNode(txXPathNativeNode::createXPathNode(aContextNode));
00130     if (!contextNode) {
00131         return NS_ERROR_OUT_OF_MEMORY;
00132     }
00133 
00134     EvalContextImpl eContext(*contextNode, aContextPosition, aContextSize,
00135                              mRecycler);
00136     nsRefPtr<txAExprResult> exprResult;
00137     rv = mExpression->evaluate(&eContext, getter_AddRefs(exprResult));
00138     NS_ENSURE_SUCCESS(rv, rv);
00139 
00140     PRUint16 resultType = aType;
00141     if (aType == nsIDOMXPathResult::ANY_TYPE) {
00142         short exprResultType = exprResult->getResultType();
00143         switch (exprResultType) {
00144             case txAExprResult::NUMBER:
00145                 resultType = nsIDOMXPathResult::NUMBER_TYPE;
00146                 break;
00147             case txAExprResult::STRING:
00148                 resultType = nsIDOMXPathResult::STRING_TYPE;
00149                 break;
00150             case txAExprResult::BOOLEAN:
00151                 resultType = nsIDOMXPathResult::BOOLEAN_TYPE;
00152                 break;
00153             case txAExprResult::NODESET:
00154                 resultType = nsIDOMXPathResult::UNORDERED_NODE_ITERATOR_TYPE;
00155                 break;
00156             case txAExprResult::RESULT_TREE_FRAGMENT:
00157                 NS_ERROR("Can't return a tree fragment!");
00158                 return NS_ERROR_FAILURE;
00159         }
00160     }
00161 
00162     // We need a result object and it must be our implementation.
00163     nsCOMPtr<nsIXPathResult> xpathResult = do_QueryInterface(aInResult);
00164     if (!xpathResult) {
00165         // Either no aInResult or not one of ours.
00166         xpathResult = new nsXPathResult();
00167         NS_ENSURE_TRUE(xpathResult, NS_ERROR_OUT_OF_MEMORY);
00168     }
00169     rv = xpathResult->SetExprResult(exprResult, resultType);
00170     NS_ENSURE_SUCCESS(rv, rv);
00171 
00172     return CallQueryInterface(xpathResult, aResult);
00173 }
00174 
00175 /*
00176  * Implementation of the txIEvalContext private to nsXPathExpression
00177  * EvalContextImpl bases on only one context node and no variables
00178  */
00179 
00180 nsresult
00181 nsXPathExpression::EvalContextImpl::getVariable(PRInt32 aNamespace,
00182                                                 nsIAtom* aLName,
00183                                                 txAExprResult*& aResult)
00184 {
00185     aResult = 0;
00186     return NS_ERROR_INVALID_ARG;
00187 }
00188 
00189 MBool nsXPathExpression::EvalContextImpl::isStripSpaceAllowed(const txXPathNode& aNode)
00190 {
00191     return MB_FALSE;
00192 }
00193 
00194 void* nsXPathExpression::EvalContextImpl::getPrivateContext()
00195 {
00196     // we don't have a private context here.
00197     return nsnull;
00198 }
00199 
00200 txResultRecycler* nsXPathExpression::EvalContextImpl::recycler()
00201 {
00202     return mRecycler;
00203 }
00204 
00205 void nsXPathExpression::EvalContextImpl::receiveError(const nsAString& aMsg,
00206                                                       nsresult aRes)
00207 {
00208     mLastError = aRes;
00209     // forward aMsg to console service?
00210 }
00211 
00212 const txXPathNode& nsXPathExpression::EvalContextImpl::getContextNode()
00213 {
00214     return mContextNode;
00215 }
00216 
00217 PRUint32 nsXPathExpression::EvalContextImpl::size()
00218 {
00219     return mContextSize;
00220 }
00221 
00222 PRUint32 nsXPathExpression::EvalContextImpl::position()
00223 {
00224     return mContextPosition;
00225 }