Back to index

lightning-sunbird  0.9+nobinonly
nsXFormsXPathEvaluator.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 Mozilla XForms support.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * IBM Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2004
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *  Aaron Reed <aaronr@us.ibm.com>
00024  *  Merle Sterling <msterlin@us.ibm.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "nsXFormsXPathEvaluator.h"
00041 #include "nsCOMPtr.h"
00042 #include "nsIAtom.h"
00043 #include "nsIDOMClassInfo.h"
00044 #include "nsXPathException.h"
00045 #include "nsXPathExpression.h"
00046 #include "nsXPathNSResolver.h"
00047 #include "nsXPathResult.h"
00048 #include "nsContentCID.h"
00049 #include "Expr.h"
00050 #include "ExprParser.h"
00051 #include "nsDOMError.h"
00052 #include "txURIUtils.h"
00053 #include "nsIDocument.h"
00054 #include "nsIDOMDocument.h"
00055 #include "nsDOMString.h"
00056 #include "nsINameSpaceManager.h"
00057 #include "txError.h"
00058 #include "txAtoms.h"
00059 #include "XFormsFunctions.h"
00060 #include "nsIDOM3Node.h"
00061 
00062 extern nsINameSpaceManager* gTxNameSpaceManager;
00063 
00064 NS_IMPL_ADDREF(nsXFormsXPathEvaluator)
00065 NS_IMPL_RELEASE(nsXFormsXPathEvaluator)
00066 NS_INTERFACE_MAP_BEGIN(nsXFormsXPathEvaluator)
00067   NS_INTERFACE_MAP_ENTRY(nsIXFormsXPathEvaluator)
00068   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXFormsXPathEvaluator)
00069 NS_INTERFACE_MAP_END
00070 
00071 nsXFormsXPathEvaluator::nsXFormsXPathEvaluator()
00072 {
00073 }
00074 
00075 nsXFormsXPathEvaluator::~nsXFormsXPathEvaluator()
00076 {
00077 }
00078 
00079 NS_IMETHODIMP
00080 nsXFormsXPathEvaluator::CreateExpression(const nsAString & aExpression, 
00081                                          nsIDOMNode *aResolverNode,
00082                                          nsIDOMNode *aOrigCtxt,
00083                                          nsIDOMNSXPathExpression **aResult)
00084 {
00085   nsresult rv = NS_OK;
00086   if (!mRecycler) {
00087     nsRefPtr<txResultRecycler> recycler = new txResultRecycler;
00088     NS_ENSURE_TRUE(recycler, NS_ERROR_OUT_OF_MEMORY);
00089     
00090     rv = recycler->init();
00091     NS_ENSURE_SUCCESS(rv, rv);
00092     
00093     mRecycler = recycler;
00094   }
00095 
00096   XFormsParseContextImpl pContext(aResolverNode, aOrigCtxt);
00097                                   
00098   nsAutoPtr<Expr> expression;
00099   rv = txExprParser::createExpr(PromiseFlatString(aExpression), &pContext,
00100                                 getter_Transfers(expression));
00101   if (NS_FAILED(rv)) {
00102     if (rv == NS_ERROR_DOM_NAMESPACE_ERR) {
00103       return NS_ERROR_DOM_NAMESPACE_ERR;
00104     }
00105 
00106     return NS_ERROR_DOM_INVALID_EXPRESSION_ERR;
00107   }
00108 
00109   *aResult = new nsXPathExpression(expression, mRecycler);
00110   if (!*aResult) {
00111     return NS_ERROR_OUT_OF_MEMORY;
00112   }
00113 
00114   NS_ADDREF(*aResult);
00115   return NS_OK;
00116 }
00117 
00118 NS_IMETHODIMP
00119 nsXFormsXPathEvaluator::Evaluate(const nsAString & aExpression,
00120                                  nsIDOMNode *aContextNode,
00121                                  PRUint32 aPosition,
00122                                  PRUint32 aSize,
00123                                  nsIDOMNode *aResolverNode,
00124                                  nsIDOMNode *aOrigCtxt,
00125                                  PRUint16 aType,
00126                                  nsISupports *aInResult,
00127                                  nsISupports **aResult)
00128 {
00129   // XXX Need to check document of aContextNode if created by
00130   //   QI'ing a document.
00131 
00132   nsCOMPtr<nsIDOMNSXPathExpression> expression;
00133   nsresult rv = CreateExpression(aExpression, aResolverNode, aOrigCtxt,
00134                                  getter_AddRefs(expression));
00135   NS_ENSURE_SUCCESS(rv, rv);
00136 
00137   return expression->EvaluateWithContext(aContextNode, aPosition, aSize,
00138                                          aType, aInResult, aResult);
00139 }
00140 
00141 
00142 /*
00143  * Implementation of txIParseContext private to nsXFormsXPathEvaluator
00144  * XFormsParseContextImpl bases on a nsIDOMXPathNSResolver
00145  */
00146 
00147 nsresult nsXFormsXPathEvaluator::XFormsParseContextImpl::resolveNamespacePrefix
00148     (nsIAtom* aPrefix, PRInt32& aID)
00149 {
00150   aID = kNameSpaceID_Unknown;
00151 
00152   if (!mResolverNode) {
00153     return NS_ERROR_DOM_NAMESPACE_ERR;
00154   }
00155 
00156   nsAutoString prefix;
00157   if (aPrefix) {
00158     aPrefix->ToString(prefix);
00159   }
00160 
00161   nsVoidableString ns;
00162   nsresult rv;
00163   // begin - taken directly from nsXPathNSResolver::LookupNamespaceURI
00164   if (prefix.EqualsLiteral("xml")) {
00165       ns.AssignLiteral("http://www.w3.org/XML/1998/namespace");
00166       rv = NS_OK;
00167   }
00168   else {
00169     nsCOMPtr<nsIDOM3Node> dom3Node = do_QueryInterface(mResolverNode);
00170     NS_ASSERTION(dom3Node, "Need a node to resolve namespaces.");
00171     if( dom3Node ) {
00172       rv = dom3Node->LookupNamespaceURI(prefix, ns);
00173     }
00174     else {
00175       SetDOMStringToNull(ns);
00176       rv = NS_OK;
00177     }
00178   }
00179   // end - taken directly from nsXPathNSResolver::LookupNamespaceURI
00180   NS_ENSURE_SUCCESS(rv, rv);
00181 
00182   if (DOMStringIsNull(ns)) {
00183     return NS_ERROR_DOM_NAMESPACE_ERR;
00184   }
00185 
00186   if (ns.IsEmpty()) {
00187     aID = kNameSpaceID_None;
00188     return NS_OK;
00189   }
00190 
00191   // get the namespaceID for the URI
00192   return gTxNameSpaceManager->RegisterNameSpace(ns, aID);
00193 }
00194 
00195 nsresult
00196 nsXFormsXPathEvaluator::XFormsParseContextImpl::resolveFunctionCall(
00197                                                     nsIAtom* aName,
00198                                                     PRInt32 aNamespaceID,
00199                                                     FunctionCall*& aFnCall)
00200 {
00201   if (aNamespaceID == kNameSpaceID_None) {
00202     PRBool isOutOfMem = PR_TRUE;
00203 
00204     if (aName == txXPathAtoms::avg) {
00205       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::AVG);
00206     }
00207     else if (aName == txXPathAtoms::booleanFromString) {
00208       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::BOOLEANFROMSTRING);
00209     }
00210     else if (aName == txXPathAtoms::countNonEmpty) {
00211       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::COUNTNONEMPTY);
00212     }
00213     else if (aName == txXPathAtoms::daysFromDate) {
00214       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::DAYSFROMDATE);
00215     }
00216     else if (aName == txXPathAtoms::ifFunc) {
00217       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::IF);
00218     }
00219     else if (aName == txXPathAtoms::index) {
00220       NS_ENSURE_TRUE(mResolverNode, NS_ERROR_FAILURE);
00221       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::INDEX,
00222                                        mResolverNode); 
00223     }
00224     else if (aName == txXPathAtoms::instance) {
00225       NS_ENSURE_TRUE(mResolverNode, NS_ERROR_FAILURE);
00226       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::INSTANCE, 
00227                                        mResolverNode);
00228     }
00229     else if (aName == txXPathAtoms::max) {
00230       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::MAX);
00231     }
00232     else if (aName == txXPathAtoms::min) {
00233       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::MIN);
00234     }
00235     else if (aName == txXPathAtoms::months) {
00236       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::MONTHS);
00237     }
00238     else if (aName == txXPathAtoms::now) {
00239       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::NOW);
00240     }
00241     else if (aName == txXPathAtoms::localDateTime) {
00242       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::LOCALDATETIME);
00243     }
00244     else if (aName == txXPathAtoms::localDate) {
00245       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::LOCALDATE);
00246     }
00247     else if (aName == txXPathAtoms::property) {
00248       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::PROPERTY);
00249     }
00250     else if (aName == txXPathAtoms::seconds) {
00251       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::SECONDS);
00252     }
00253     else if (aName == txXPathAtoms::secondsFromDateTime) {
00254       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::SECONDSFROMDATETIME);
00255     }
00256     else if (aName == txXPathAtoms::current) {
00257       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::CURRENT,
00258                                        mOriginalContext);
00259     }
00260     else if (aName == txXPathAtoms::event) {
00261       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::EVENT,
00262                                        mResolverNode);
00263     }
00264     else if (aName == txXPathAtoms::power) {
00265       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::POWER);
00266     }
00267     else if (aName == txXPathAtoms::random) {
00268       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::RANDOM);
00269     }
00270     else if (aName == txXPathAtoms::compare) {
00271       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::COMPARE);
00272     }
00273     else if (aName == txXPathAtoms::context) {
00274       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::CONTEXT,
00275                                        mResolverNode);
00276     }
00277     else if (aName == txXPathAtoms::daysToDate) {
00278       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::DAYSTODATE);
00279     }
00280     else if (aName == txXPathAtoms::secondsToDateTime) {
00281       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::SECONDSTODATETIME);
00282     }
00283     else if (aName == txXPathAtoms::isCardNumber) {
00284       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::ISCARDNUMBER);
00285     }
00286     else if (aName == txXPathAtoms::digest) {
00287       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::DIGEST,
00288                                        mResolverNode);
00289     }
00290     else if (aName == txXPathAtoms::adjustDateTimeToTimezone) {
00291       aFnCall = new XFormsFunctionCall(XFormsFunctionCall::ADJUSTDATETIMETOTIMEZONE);
00292     }
00293     else {
00294       // didn't find functioncall here, aFnCall should be null
00295       isOutOfMem = PR_FALSE;
00296     }
00297 
00298     if (aFnCall)
00299     {
00300       return NS_OK;
00301     }
00302     else if (isOutOfMem) {
00303       NS_ERROR("XPath FunctionLib failed on out-of-memory");
00304       return NS_ERROR_OUT_OF_MEMORY;
00305     }
00306   }
00307   return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
00308 }
00309 
00310 PRBool nsXFormsXPathEvaluator::XFormsParseContextImpl::caseInsensitiveNameTests()
00311 {
00312   // This will always be false since this handles XForms, which is XML-based,
00313   //   so case sensitive.
00314   return PR_FALSE;
00315 }
00316 
00317 void
00318 nsXFormsXPathEvaluator::XFormsParseContextImpl::SetErrorOffset(PRUint32 aOffset)
00319 {
00320 }