Back to index

lightning-sunbird  0.9+nobinonly
nsXFormsXPathAnalyzer.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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  * Novell, Inc.
00019  * Portions created by the Initial Developer are Copyright (C) 2004
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *  Allan Beaufour <abeaufour@novell.com>
00024  *  David Landwehr <dlandwehr@novell.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 "nsXFormsXPathAnalyzer.h"
00041 #include "nsIDOMXPathResult.h"
00042 #include "nsXFormsUtils.h"
00043 
00044 #ifdef DEBUG
00045 //#define DEBUG_XF_ANALYZER
00046 #endif
00047 
00048 nsXFormsXPathAnalyzer::nsXFormsXPathAnalyzer(nsIXFormsXPathEvaluator  *aEvaluator,
00049                                              nsIDOMNode               *aResolver,
00050                                              nsIDOMNode               *aOrigCtxt)
00051   : mEvaluator(aEvaluator),
00052     mResolver(aResolver),
00053     mOrigCtxt(aOrigCtxt)
00054 {
00055   MOZ_COUNT_CTOR(nsXFormsXPathAnalyzer);
00056 }
00057 
00058 nsXFormsXPathAnalyzer::~nsXFormsXPathAnalyzer()
00059 {
00060   MOZ_COUNT_DTOR(nsXFormsXPathAnalyzer);
00061 }
00062 
00063 nsresult
00064 nsXFormsXPathAnalyzer::Analyze(nsIDOMNode                *aContextNode,
00065                                const nsXFormsXPathNode   *aNode,
00066                                nsIDOMNSXPathExpression   *aExpression,
00067                                const nsAString           *aExprString,
00068                                nsCOMArray<nsIDOMNode>    *aSet,
00069                                PRUint32                   aPosition,
00070                                PRUint32                   aSize,
00071                                PRBool                     aIncludeRoot)
00072 {
00073   NS_ENSURE_ARG(aContextNode);
00074   NS_ENSURE_ARG(aNode);
00075   NS_ENSURE_ARG(aExpression);
00076   NS_ENSURE_ARG(aExprString);
00077   NS_ENSURE_ARG(aSet);
00078 
00079   mCurExpression = aExpression;
00080   mCurExprString = aExprString;
00081   mCurSet = aSet;
00082   mCurSize = aSize;
00083   mCurPosition = aPosition;
00084 
00085 #ifdef DEBUG_XF_ANALYZER
00086   printf("=====================================\n");
00087   printf("Analyzing: %s\n", NS_ConvertUTF16toUTF8(*mCurExprString).get());
00088   printf("=====================================\n");
00089 #endif
00090 
00091   nsresult rv = AnalyzeRecursively(aContextNode, aNode->mChild, 0,
00092                                    aIncludeRoot);
00093 #ifdef DEBUG_XF_ANALYZER
00094   printf("-------------------------------------\n");
00095 #endif
00096   NS_ENSURE_SUCCESS(rv, rv);
00097 
00098   // Besides making the set a set, it also makes it sorted.
00099   nsXFormsUtils::MakeUniqueAndSort(aSet);
00100 
00101   return NS_OK;
00102 }
00103 
00104 
00105 nsresult
00106 nsXFormsXPathAnalyzer::AnalyzeRecursively(nsIDOMNode              *aContextNode,
00107                                           const nsXFormsXPathNode *aNode,
00108                                           PRUint32                aIndent,
00109                                           PRBool                  aCollect)
00110 {
00111   nsXFormsXPathNode* t;
00112   nsAutoString xp;
00113   nsresult rv;
00114   nsCOMPtr<nsIDOMXPathResult> result;
00115   nsCOMPtr<nsIDOMNode> node;
00116 #ifdef DEBUG_XF_ANALYZER
00117   char strbuf[100];
00118   char* strpos;
00119 #endif
00120 
00121 #ifdef DEBUG_beaufour_xxx
00122   printf("nsXFormsXPathParser::AnalyzeRecursively(%p)\n", (void*) aNode);
00123 #endif
00124   
00125   for (; aNode; aNode = aNode->mSibling) {
00126 #ifdef DEBUG_beaufour_xxx
00127     printf("\tChild: %p, Sibling: %p\n", (void*) aNode->mChild, (void*) aNode->mSibling);
00128     printf("\tIndex: %d - %d\n", aNode->mStartIndex, aNode->mEndIndex);
00129     printf("\tCon: %d, Predicate: %d, Literal: %d\n", aNode->mCon, aNode->mPredicate, aNode->mLiteral);
00130     printf("\tIsIndex: %d\n", aNode->mIsIndex);
00131 #endif
00132 
00133     if (aNode->mEndIndex < 0 || aNode->mStartIndex >= aNode->mEndIndex) {
00134       continue;
00135     }
00136 
00137     PRBool hasContinue = PR_FALSE;
00138     
00139     // hasContinue == whether we have a child with a mCon
00140     t = aNode->mChild;
00141     while (t && !hasContinue) {
00142       hasContinue = t->mCon;
00143       t = t->mSibling;
00144     }
00145 
00146 #ifdef DEBUG_XF_ANALYZER
00147     strpos = strbuf;
00148     *strpos = '\0';
00149     for (PRUint32 j = 0; j < aIndent; ++j) {
00150       strpos += sprintf(strpos, "  ");
00151     }
00152     
00153     strpos += sprintf(strpos, "<%s> ", hasContinue ? "C" : " ");
00154     
00155     if (aNode->mPredicate) {
00156       if (!(aNode->mChild)) {
00157         strpos += sprintf(strpos, "[PredicateVal], ");
00158       } else {
00159         strpos += sprintf(strpos, "[Predicate], ");
00160       }
00161     } else {
00162       if (!(aNode->mChild)) {
00163         strpos += sprintf(strpos, "[AxisStepsVal], ");
00164       } else {
00165         if (!hasContinue) {
00166           strpos += printf(strpos, "[AxisSteps], ");
00167         }
00168       }
00169     }
00170 #endif
00171 
00172     if (aNode->mCon) {
00173       // Remove the leading /
00174       xp = Substring(*mCurExprString, aNode->mStartIndex + 1,
00175                      aNode->mEndIndex - aNode->mStartIndex - 1);
00176     } else {
00177       xp = Substring(*mCurExprString, aNode->mStartIndex,
00178                      aNode->mEndIndex - aNode->mStartIndex);
00179     }
00180     rv = mEvaluator->Evaluate(xp, aContextNode, mCurPosition, mCurSize,
00181                               mResolver, mOrigCtxt, nsIDOMXPathResult::ANY_TYPE,
00182                               nsnull, getter_AddRefs(result));
00183     if (NS_FAILED(rv)) {
00184       const PRUnichar *strings[] = { xp.get() };
00185       nsXFormsUtils::ReportError(NS_LITERAL_STRING("exprEvaluateError"),
00186                                  strings, 1, nsnull, nsnull);
00187       return rv;
00188     }
00189 
00190     PRUint16 type;
00191     rv = result->GetResultType(&type);
00192     NS_ENSURE_SUCCESS(rv, rv);
00193 
00194     if (aNode->mIsIndex) {
00195       // Extract index parameter, xp is "index(parameter)"
00196       const PRUint32 indexSize = sizeof("index(") - 1;
00197       nsDependentSubstring indexExpr = Substring(xp,
00198                                                  indexSize,
00199                                                  xp.Length() - indexSize - 1); // remove final ')' too
00200       nsCOMPtr<nsIDOMXPathResult> stringRes;
00201       rv = mEvaluator->Evaluate(indexExpr, aContextNode, mCurPosition, mCurSize,
00202                                 mResolver, mOrigCtxt,
00203                                 nsIDOMXPathResult::STRING_TYPE,
00204                                 nsnull, getter_AddRefs(stringRes));
00205       NS_ENSURE_SUCCESS(rv, rv);
00206 
00207       nsAutoString indexId;
00208       rv = stringRes->GetStringValue(indexId);
00209       NS_ENSURE_SUCCESS(rv, rv);
00210       mIndexesUsed.AppendString(indexId);
00211     }
00212 
00213     // We are only interested in nodes
00214     if (   type != nsIDOMXPathResult::UNORDERED_NODE_ITERATOR_TYPE
00215         && type != nsIDOMXPathResult::ORDERED_NODE_ITERATOR_TYPE) {
00216       continue;
00217     }
00218 
00219     while (NS_SUCCEEDED(result->IterateNext(getter_AddRefs(node))) && node) {
00220       NS_ENSURE_SUCCESS(rv, rv);
00221 #ifdef DEBUG_XF_ANALYZER
00222       printf(strbuf);
00223 #endif
00224       if (!aCollect && (aNode->mChild || (!aNode->mChild && hasContinue))) {
00225 #ifdef DEBUG_XF_ANALYZER
00226         printf("iterating '%s'\n", NS_ConvertUTF16toUTF8(xp).get());
00227 #endif
00228       } else {
00229 #ifdef DEBUG_XF_ANALYZER
00230         printf("collecting '%s'\n", NS_ConvertUTF16toUTF8(xp).get());
00231 #endif
00232         mCurSet->AppendObject(node);
00233       }
00234       rv = AnalyzeRecursively(node, aNode->mChild, aIndent + 1);
00235     }
00236 
00237     NS_ENSURE_SUCCESS(rv, rv);
00238   }
00239   return NS_OK;
00240 }
00241 
00242 const nsStringArray&
00243 nsXFormsXPathAnalyzer::IndexesUsed() const
00244 {
00245   return mIndexesUsed;
00246 }