Back to index

lightning-sunbird  0.9+nobinonly
NodeSetFunctionCall.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  * The MITRE Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Keith Visco <kvisco@ziplink.net> (Original Author)
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 /*
00040  * NodeSetFunctionCall
00041  * A representation of the XPath NodeSet funtions
00042  */
00043 
00044 #include "FunctionLib.h"
00045 #include "nsAutoPtr.h"
00046 #include "txNodeSet.h"
00047 #include "txAtoms.h"
00048 #include "txIXPathContext.h"
00049 #include "txTokenizer.h"
00050 
00051 /*
00052  * Creates a NodeSetFunctionCall of the given type
00053  */
00054 NodeSetFunctionCall::NodeSetFunctionCall(NodeSetFunctions aType)
00055     : mType(aType)
00056 {
00057 }
00058 
00059 /*
00060  * Evaluates this Expr based on the given context node and processor state
00061  * @param context the context node for evaluation of this Expr
00062  * @param ps the ContextState containing the stack information needed
00063  * for evaluation
00064  * @return the result of the evaluation
00065  */
00066 nsresult
00067 NodeSetFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
00068 {
00069     *aResult = nsnull;
00070     nsresult rv = NS_OK;
00071     txListIterator iter(&params);
00072 
00073     switch (mType) {
00074         case COUNT:
00075         {
00076             if (!requireParams(1, 1, aContext))
00077                 return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
00078 
00079             nsRefPtr<txNodeSet> nodes;
00080             rv = evaluateToNodeSet((Expr*)iter.next(), aContext,
00081                                    getter_AddRefs(nodes));
00082             NS_ENSURE_SUCCESS(rv, rv);
00083 
00084             return aContext->recycler()->getNumberResult(nodes->size(),
00085                                                          aResult);
00086         }
00087         case ID:
00088         {
00089             if (!requireParams(1, 1, aContext))
00090                 return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
00091 
00092             nsRefPtr<txAExprResult> exprResult;
00093             rv = ((Expr*)iter.next())->evaluate(aContext,
00094                                                 getter_AddRefs(exprResult));
00095             NS_ENSURE_SUCCESS(rv, rv);
00096 
00097             nsRefPtr<txNodeSet> resultSet;
00098             rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet));
00099             NS_ENSURE_SUCCESS(rv, rv);
00100 
00101             txXPathTreeWalker walker(aContext->getContextNode());
00102             
00103             if (exprResult->getResultType() == txAExprResult::NODESET) {
00104                 txNodeSet* nodes = NS_STATIC_CAST(txNodeSet*,
00105                                                   NS_STATIC_CAST(txAExprResult*,
00106                                                                  exprResult));
00107                 PRInt32 i;
00108                 for (i = 0; i < nodes->size(); ++i) {
00109                     nsAutoString idList;
00110                     txXPathNodeUtils::appendNodeValue(nodes->get(i), idList);
00111                     txTokenizer tokenizer(idList);
00112                     while (tokenizer.hasMoreTokens()) {
00113                         if (walker.moveToElementById(tokenizer.nextToken())) {
00114                             resultSet->add(walker.getCurrentPosition());
00115                         }
00116                     }
00117                 }
00118             }
00119             else {
00120                 nsAutoString idList;
00121                 exprResult->stringValue(idList);
00122                 txTokenizer tokenizer(idList);
00123                 while (tokenizer.hasMoreTokens()) {
00124                     if (walker.moveToElementById(tokenizer.nextToken())) {
00125                         resultSet->add(walker.getCurrentPosition());
00126                     }
00127                 }
00128             }
00129 
00130             *aResult = resultSet;
00131             NS_ADDREF(*aResult);
00132 
00133             return NS_OK;
00134         }
00135         case LAST:
00136         {
00137             if (!requireParams(0, 0, aContext))
00138                 return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
00139 
00140             return aContext->recycler()->getNumberResult(aContext->size(),
00141                                                          aResult);
00142         }
00143         case LOCAL_NAME:
00144         case NAME:
00145         case NAMESPACE_URI:
00146         {
00147             if (!requireParams(0, 1, aContext)) {
00148                 return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
00149             }
00150 
00151             // Check for optional arg
00152             nsRefPtr<txNodeSet> nodes;
00153             if (iter.hasNext()) {
00154                 rv = evaluateToNodeSet((Expr*)iter.next(), aContext,
00155                                        getter_AddRefs(nodes));
00156                 NS_ENSURE_SUCCESS(rv, rv);
00157 
00158                 if (nodes->isEmpty()) {
00159                     aContext->recycler()->getEmptyStringResult(aResult);
00160 
00161                     return NS_OK;
00162                 }
00163             }
00164 
00165             const txXPathNode& node = nodes ? nodes->get(0) :
00166                                               aContext->getContextNode();
00167             switch (mType) {
00168                 case LOCAL_NAME:
00169                 {
00170                     StringResult* strRes = nsnull;
00171                     rv = aContext->recycler()->getStringResult(&strRes);
00172                     NS_ENSURE_SUCCESS(rv, rv);
00173 
00174                     *aResult = strRes;
00175                     txXPathNodeUtils::getLocalName(node, strRes->mValue);
00176 
00177                     return NS_OK;
00178                 }
00179                 case NAMESPACE_URI:
00180                 {
00181                     StringResult* strRes = nsnull;
00182                     rv = aContext->recycler()->getStringResult(&strRes);
00183                     NS_ENSURE_SUCCESS(rv, rv);
00184 
00185                     *aResult = strRes;
00186                     txXPathNodeUtils::getNamespaceURI(node, strRes->mValue);
00187 
00188                     return NS_OK;
00189                 }
00190                 case NAME:
00191                 {
00192                     // XXX Namespace: namespaces have a name
00193                     if (txXPathNodeUtils::isAttribute(node) ||
00194                         txXPathNodeUtils::isElement(node) ||
00195                         txXPathNodeUtils::isProcessingInstruction(node)) {
00196                         StringResult* strRes = nsnull;
00197                         rv = aContext->recycler()->getStringResult(&strRes);
00198                         NS_ENSURE_SUCCESS(rv, rv);
00199 
00200                         *aResult = strRes;
00201                         txXPathNodeUtils::getNodeName(node, strRes->mValue);
00202                     }
00203                     else {
00204                         aContext->recycler()->getEmptyStringResult(aResult);
00205                     }
00206 
00207                     return NS_OK;
00208                 }
00209                 default:
00210                 {
00211                     break;
00212                 }
00213             }
00214         }
00215         case POSITION:
00216         {
00217             if (!requireParams(0, 0, aContext))
00218                 return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
00219 
00220             return aContext->recycler()->getNumberResult(aContext->position(),
00221                                                          aResult);
00222         }
00223     }
00224 
00225     aContext->receiveError(NS_LITERAL_STRING("Internal error"),
00226                            NS_ERROR_UNEXPECTED);
00227     return NS_ERROR_UNEXPECTED;
00228 }
00229 
00230 #ifdef TX_TO_STRING
00231 nsresult
00232 NodeSetFunctionCall::getNameAtom(nsIAtom** aAtom)
00233 {
00234     switch (mType) {
00235         case COUNT:
00236         {
00237             *aAtom = txXPathAtoms::count;
00238             break;
00239         }
00240         case ID:
00241         {
00242             *aAtom = txXPathAtoms::id;
00243             break;
00244         }
00245         case LAST:
00246         {
00247             *aAtom = txXPathAtoms::last;
00248             break;
00249         }
00250         case LOCAL_NAME:
00251         {
00252             *aAtom = txXPathAtoms::localName;
00253             break;
00254         }
00255         case NAME:
00256         {
00257             *aAtom = txXPathAtoms::name;
00258             break;
00259         }
00260         case NAMESPACE_URI:
00261         {
00262             *aAtom = txXPathAtoms::namespaceUri;
00263             break;
00264         }
00265         case POSITION:
00266         {
00267             *aAtom = txXPathAtoms::position;
00268             break;
00269         }
00270         default:
00271         {
00272             *aAtom = 0;
00273             return NS_ERROR_FAILURE;
00274         }
00275     }
00276     NS_ADDREF(*aAtom);
00277     return NS_OK;
00278 }
00279 #endif