Fix for bug 278981 (Extension mechanism for XPath extension functions). r=sicking, sr=jst.

This commit is contained in:
peterv%propagandism.org 2006-07-13 14:21:53 +00:00
Родитель 74b982040d
Коммит a9c63c4a75
33 изменённых файлов: 2229 добавлений и 1833 удалений

Просмотреть файл

@ -47,14 +47,11 @@
#define NS_NO_VTABLE
#endif
class nsIDOMNode; /* forward declaration */
/* nsIXFormsUtilityService */
#define NS_IXFORMSUTILITYSERVICE_IID_STR "4a744a59-8771-4065-959d-b8de3dad81da"
#define NS_IXFORMSUTILITYSERVICE_IID_STR "f7276415-bb3e-4170-b746-aa57f68d7006"
#define NS_IXFORMSUTILITYSERVICE_IID \
{0x4a744a59, 0x8771, 0x4065, \
{ 0x95, 0x9d, 0xb8, 0xde, 0x3d, 0xad, 0x81, 0xda }}
{ 0xf7276415, 0xbb3e, 0x4170, \
{ 0xb7, 0x46, 0xaa, 0x57, 0xf6, 0x8d, 0x70, 0x06 } }
/**
* Private interface implemented by the nsXFormsUtilityService in XForms
@ -64,87 +61,6 @@ class NS_NO_VTABLE nsIXFormsUtilityService : public nsISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXFORMSUTILITYSERVICE_IID)
/**
* Function to get the corresponding model element from a xforms node or
* a xforms instance data node.
*/
/* nsIDOMNode getModelFromNode (in nsIDOMNode node); */
NS_IMETHOD GetModelFromNode(nsIDOMNode *node, nsIDOMNode **aModel) = 0;
/**
* Function to see if the given node is associated with the given model.
* Right now this function is only called by XPath in the case of the
* instance() function.
* The provided node can be an instance node from an instance
* document and thus be associated to the model in that way (model elements
* contain instance elements). Otherwise the node will be an XForms element
* that was used as the context node of the XPath expression (i.e the
* XForms control has an attribute that contains an XPath expression).
* Form controls are associated with model elements either explicitly through
* single-node binding or implicitly (if model cannot by calculated, it
* will use the first model element encountered in the document). The model
* can also be inherited from a containing element like xforms:group or
* xforms:repeat.
*/
/* PRBool isNodeAssocWithModel (in nsIDOMNode aNode, in nsIDOMNode aModel); */
NS_IMETHOD IsNodeAssocWithModel(nsIDOMNode *aNode, nsIDOMNode *aModel,
PRBool *aModelAssocWithNode) = 0;
/**
* Function to get the instance document root for the instance element with
* the given id. The instance element must be associated with the given
* model.
*/
/* nsIDOMNode getInstanceDocumentRoot(in DOMString aID,
in nsIDOMNode aModelNode); */
NS_IMETHOD GetInstanceDocumentRoot(const nsAString& aID,
nsIDOMNode *aModelNode,
nsIDOMNode **aInstanceRoot) = 0;
/**
* Function to ensure that aValue is of the schema type aType. Will basically
* be a forwarder to the nsISchemaValidator function of the same name.
*/
/* boolean validateString (in AString aValue, in AString aType,
in AString aNamespace); */
NS_IMETHOD ValidateString(const nsAString& aValue, const nsAString& aType,
const nsAString & aNamespace, PRBool *aResult) = 0;
/**
* Function to retrieve the index from the given repeat element.
*/
/* long getRepeatIndex (in nsIDOMNode aRepeat); */
NS_IMETHOD GetRepeatIndex(nsIDOMNode *aRepeat, PRInt32 *aIndex) = 0;
/**
* Function to retrieve the number of months represented by the
* xsd:duration provided in aValue
*/
/* long getMonths (in DOMString aValue); */
NS_IMETHOD GetMonths(const nsAString& aValue, PRInt32 *aMonths) = 0;
/**
* Function to retrieve the number of seconds represented by the
* xsd:duration provided in aValue
*/
/* double getSeconds (in DOMString aValue); */
NS_IMETHOD GetSeconds(const nsAString& aValue, double *aSeconds) = 0;
/**
* Function to retrieve the number of seconds represented by the
* xsd:dateTime provided in aValue
*/
/* double getSecondsFromDateTime (in DOMString aValue); */
NS_IMETHOD GetSecondsFromDateTime(const nsAString& aValue,
double *aSeconds) = 0;
/**
* Function to retrieve the number of days represented by the
* xsd:dateTime provided in aValue
*/
/* long getDaysFromDateTime (in DOMString aValue); */
NS_IMETHOD GetDaysFromDateTime(const nsAString& aValue, PRInt32 *aDays) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIXFormsUtilityService,

Просмотреть файл

@ -39,9 +39,11 @@
#ifndef nsIXPathEvaluatorInternal_h__
#define nsIXPathEvaluatorInternal_h__
#include "nsISupports.h"
#include "nsCOMArray.h"
class nsIDOMDocument;
class nsIDOMXPathExpression;
class nsIDOMXPathNSResolver;
#define NS_IXPATHEVALUATORINTERNAL_IID \
{0xb4b72daa, 0x65d6, 0x440f, \
@ -57,6 +59,13 @@ public:
* Sets the document this evaluator corresponds to
*/
NS_IMETHOD SetDocument(nsIDOMDocument* aDocument) = 0;
NS_IMETHOD CreateExpression(const nsAString &aExpression,
nsIDOMXPathNSResolver *aResolver,
nsStringArray *aNamespaceURIs,
nsCStringArray *aContractIDs,
nsCOMArray<nsISupports> *aState,
nsIDOMXPathExpression **aResult) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIXPathEvaluatorInternal,

Просмотреть файл

@ -47,6 +47,7 @@ XPIDL_MODULE = content_xslt
EXPORTS = \
nsIDocumentTransformer.h \
txDouble.h \
$(NULL)
XPIDLSRCS = \
@ -54,6 +55,8 @@ XPIDLSRCS = \
nsIXSLTProcessor.idl \
nsIXSLTProcessorObsolete.idl \
nsIXSLTProcessorPrivate.idl \
txIFunctionEvaluationContext.idl \
txINodeSet.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,128 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Peter Van der Beken.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@propagandism.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __txdouble_h__
#define __txdouble_h__
//A trick to handle IEEE floating point exceptions on FreeBSD - E.D.
#ifdef __FreeBSD__
#include <ieeefp.h>
#ifdef __alpha__
fp_except_t allmask = FP_X_INV|FP_X_OFL|FP_X_UFL|FP_X_DZ|FP_X_IMP;
#else
fp_except_t allmask = FP_X_INV|FP_X_OFL|FP_X_UFL|FP_X_DZ|FP_X_IMP|FP_X_DNML;
#endif
fp_except_t oldmask = fpsetmask(~allmask);
#endif
/**
* Macros to workaround math-bugs bugs in various platforms
*/
/**
* Stefan Hanske <sh990154@mail.uni-greifswald.de> reports:
* ARM is a little endian architecture but 64 bit double words are stored
* differently: the 32 bit words are in little endian byte order, the two words
* are stored in big endian`s way.
*/
#if defined(__arm) || defined(__arm32__) || defined(__arm26__) || defined(__arm__)
#define CPU_IS_ARM
#endif
#if (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || __GNUC__ > 2
/**
* This version of the macros is safe for the alias optimizations
* that gcc does, but uses gcc-specific extensions.
*/
typedef union txdpun {
PRFloat64 d;
struct {
#if defined(IS_LITTLE_ENDIAN) && !defined(CPU_IS_ARM)
PRUint32 lo, hi;
#else
PRUint32 hi, lo;
#endif
} s;
} txdpun;
#define TX_DOUBLE_HI32(x) (__extension__ ({ txdpun u; u.d = (x); u.s.hi; }))
#define TX_DOUBLE_LO32(x) (__extension__ ({ txdpun u; u.d = (x); u.s.lo; }))
#else // __GNUC__
/* We don't know of any non-gcc compilers that perform alias optimization,
* so this code should work.
*/
#if defined(IS_LITTLE_ENDIAN) && !defined(CPU_IS_ARM)
#define TX_DOUBLE_HI32(x) (((PRUint32 *)&(x))[1])
#define TX_DOUBLE_LO32(x) (((PRUint32 *)&(x))[0])
#else
#define TX_DOUBLE_HI32(x) (((PRUint32 *)&(x))[0])
#define TX_DOUBLE_LO32(x) (((PRUint32 *)&(x))[1])
#endif
#endif // __GNUC__
#define TX_DOUBLE_HI32_SIGNBIT 0x80000000
#define TX_DOUBLE_HI32_EXPMASK 0x7ff00000
#define TX_DOUBLE_HI32_MANTMASK 0x000fffff
#define TX_DOUBLE_IS_NaN(x) \
((TX_DOUBLE_HI32(x) & TX_DOUBLE_HI32_EXPMASK) == TX_DOUBLE_HI32_EXPMASK && \
(TX_DOUBLE_LO32(x) || (TX_DOUBLE_HI32(x) & TX_DOUBLE_HI32_MANTMASK)))
#ifdef IS_BIG_ENDIAN
#define TX_DOUBLE_NaN {TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_MANTMASK, \
0xffffffff}
#else
#define TX_DOUBLE_NaN {0xffffffff, \
TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_MANTMASK}
#endif
#if defined(XP_WIN)
#define TX_DOUBLE_COMPARE(LVAL, OP, RVAL) \
(!TX_DOUBLE_IS_NaN(LVAL) && !TX_DOUBLE_IS_NaN(RVAL) && (LVAL) OP (RVAL))
#else
#define TX_DOUBLE_COMPARE(LVAL, OP, RVAL) ((LVAL) OP (RVAL))
#endif
#endif /* __txdouble_h__ */

Просмотреть файл

@ -0,0 +1,51 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Peter Van der Beken.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@propagandism.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "domstubs.idl"
interface txINodeSet;
[scriptable, uuid(0ecbb00c-6a78-11d9-9791-000a95dc234c)]
interface txIFunctionEvaluationContext : nsISupports
{
readonly attribute PRUint32 position;
readonly attribute PRUint32 size;
readonly attribute nsIDOMNode contextNode;
readonly attribute nsISupports state;
};

Просмотреть файл

@ -0,0 +1,57 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Peter Van der Beken.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@propagandism.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "domstubs.idl"
%{ C++
class txAExprResult;
%}
[ptr] native txAExprResultPtr(txAExprResult);
[scriptable, uuid(15d424c0-6b47-11d9-9791-000a95dc234c)]
interface txINodeSet : nsISupports
{
nsIDOMNode item(in unsigned long index);
double itemAsNumber(in unsigned long index);
DOMString itemAsString(in unsigned long index);
readonly attribute unsigned long length;
void add(in nsIDOMNode node);
[noscript, notxpcom] txAExprResultPtr getTxNodeSet();
};

Просмотреть файл

@ -42,6 +42,7 @@
#include "nscore.h"
#include "nsDebug.h"
#include "prtypes.h"
#include "txDouble.h"
class nsAString;

Просмотреть файл

@ -49,81 +49,12 @@
* Utility class for doubles
*/
//A trick to handle IEEE floating point exceptions on FreeBSD - E.D.
#ifdef __FreeBSD__
#include <ieeefp.h>
#ifdef __alpha__
fp_except_t allmask = FP_X_INV|FP_X_OFL|FP_X_UFL|FP_X_DZ|FP_X_IMP;
#else
fp_except_t allmask = FP_X_INV|FP_X_OFL|FP_X_UFL|FP_X_DZ|FP_X_IMP|FP_X_DNML;
#endif
fp_except_t oldmask = fpsetmask(~allmask);
#endif
/**
* Macros to workaround math-bugs bugs in various platforms
*/
/**
* Stefan Hanske <sh990154@mail.uni-greifswald.de> reports:
* ARM is a little endian architecture but 64 bit double words are stored
* differently: the 32 bit words are in little endian byte order, the two words
* are stored in big endian`s way.
*/
#if defined(__arm) || defined(__arm32__) || defined(_arm26__) || defined(__arm__)
#define CPU_IS_ARM
#endif
#if (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || __GNUC__ > 2
/**
* This version of the macros is safe for the alias optimizations
* that gcc does, but uses gcc-specific extensions.
*/
typedef union txdpun {
PRFloat64 d;
struct {
#if defined(IS_LITTLE_ENDIAN) && !defined(CPU_IS_ARM)
PRUint32 lo, hi;
#else
PRUint32 hi, lo;
#endif
} s;
} txdpun;
#define TX_DOUBLE_HI32(x) (__extension__ ({ txdpun u; u.d = (x); u.s.hi; }))
#define TX_DOUBLE_LO32(x) (__extension__ ({ txdpun u; u.d = (x); u.s.lo; }))
#else // __GNUC__
/* We don't know of any non-gcc compilers that perform alias optimization,
* so this code should work.
*/
#if defined(IS_LITTLE_ENDIAN) && !defined(CPU_IS_ARM)
#define TX_DOUBLE_HI32(x) (((PRUint32 *)&(x))[1])
#define TX_DOUBLE_LO32(x) (((PRUint32 *)&(x))[0])
#else
#define TX_DOUBLE_HI32(x) (((PRUint32 *)&(x))[0])
#define TX_DOUBLE_LO32(x) (((PRUint32 *)&(x))[1])
#endif
#endif // __GNUC__
#define TX_DOUBLE_HI32_SIGNBIT 0x80000000
#define TX_DOUBLE_HI32_EXPMASK 0x7ff00000
#define TX_DOUBLE_HI32_MANTMASK 0x000fffff
//-- Initialize Double related constants
const PRUint32 nanMask[2] = TX_DOUBLE_NaN;
#ifdef IS_BIG_ENDIAN
const PRUint32 nanMask[2] = {TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_MANTMASK,
0xffffffff};
const PRUint32 infMask[2] = {TX_DOUBLE_HI32_EXPMASK, 0};
const PRUint32 negInfMask[2] = {TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_SIGNBIT, 0};
#else
const PRUint32 nanMask[2] = {0xffffffff,
TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_MANTMASK};
const PRUint32 infMask[2] = {0, TX_DOUBLE_HI32_EXPMASK};
const PRUint32 negInfMask[2] = {0, TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_SIGNBIT};
#endif
@ -147,8 +78,7 @@ MBool Double::isInfinite(double aDbl)
*/
MBool Double::isNaN(double aDbl)
{
return ((TX_DOUBLE_HI32(aDbl) & TX_DOUBLE_HI32_EXPMASK) == TX_DOUBLE_HI32_EXPMASK &&
(TX_DOUBLE_LO32(aDbl) || (TX_DOUBLE_HI32(aDbl) & TX_DOUBLE_HI32_MANTMASK)));
return TX_DOUBLE_IS_NaN(aDbl);
}
/*

Просмотреть файл

@ -101,20 +101,13 @@ CPPSRCS += nsXPathEvaluator.cpp \
nsXPathNSResolver.cpp \
nsXPathResult.cpp \
nsXPath1Scheme.cpp \
txMozillaXPathTreeWalker.cpp
txMozillaXPathTreeWalker.cpp \
txNodeSetAdaptor.cpp \
txXPCOMExtensionFunction.cpp
else
CPPSRCS += txStandaloneXPathTreeWalker.cpp
endif
ifndef DISABLE_XFORMS_HOOKS # Dummy var, nobody sets it!
ifndef MOZ_XSLT_STANDALONE
EXPORTS = nsIXFormsXPathEvaluator.h
CPPSRCS += nsXFormsXPathEvaluator.cpp \
txXFormsFunctionCall.cpp
endif
endif
# we don't want the shared lib, but we want to force the creation of a
# static lib.
FORCE_STATIC_LIB = 1

Просмотреть файл

@ -1,102 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
*
* The Initial Developer of the Original Code is
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Aaron Reed <aaronr@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsIXFormsXPathEvaluator_h
#define nsIXFormsXPathEvaluator_h
#include "nsISupports.h"
/* For IDL files that don't want to include root IDL files. */
#ifndef NS_NO_VTABLE
#define NS_NO_VTABLE
#endif
class nsIDOMNode; /* forward declaration */
class nsIDOMNSXPathExpression; /* forward declaration */
/* starting interface: nsIXFormsXPathEvaluator */
#define NS_XFORMS_XPATH_EVALUATOR_CONTRACTID "@mozilla.org/dom/xforms-xpath-evaluator;1"
/* 4cdd884f-f949-4d82-bb78-b8edd9f1420c */
#define TRANSFORMIIX_XFORMS_XPATH_EVALUATOR_CID \
{ 0x4cdd884f, 0xf949, 0x4d82, \
{0xbb, 0x78, 0xb8, 0xed, 0xd9, 0xf1, 0x42, 0x0c} }
/* 61e5a446-73f7-432e-a2d6-d94d4a51aed8 */
#define TRANSFORMIIX_XFORMS_XPATH_EVALUATOR_IID \
{ 0x61e5a446, 0x73f7, 0x432e, \
{0xa2, 0xd6, 0xd9, 0x4d, 0x4a, 0x51, 0xae, 0xd8} }
/* Use this macro when declaring classes that implement this interface. */
#define NS_DECL_NSIXFORMXPATHEVALUATOR \
NS_IMETHOD CreateExpression(const nsAString & aExpression, nsIDOMNode *aResolverNode, nsIDOMNSXPathExpression **aResult); \
NS_IMETHOD Evaluate(const nsAString & aExpression, nsIDOMNode *aContextNode, PRUint32 aContextPosition, PRUint32 aContextSize, nsIDOMNode *aResolverNode, PRUint16 aType, nsISupports *aInResult, nsISupports **aResult);
/**
* Private interface implemented by the nsXFormsXPathEvaluator in Transformiix
* and will move to the XForms extension when XPath is made extensible. We
* are using this interface instead of nsIDOMXPathEvaluator since we can
* don't really need all of that overhead. For example, this interface uses
* a resolver node from the xforms document rather than forcing XForms to
* create a namespace resolver node prior to creating the expression or
* running an evaluation.
*/
class NS_NO_VTABLE nsIXFormsXPathEvaluator : public nsISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(TRANSFORMIIX_XFORMS_XPATH_EVALUATOR_IID)
/**
* Function to create a nsIDOMNSXPathExpression from the provided expression
* string. aResolverNode is the xforms node that the expression is
* associated with.
*/
NS_IMETHOD CreateExpression(const nsAString & aExpression, nsIDOMNode *aResolverNode, nsIDOMNSXPathExpression **aResult) = 0;
/**
* Function to evaluate the given expression. aResolverNode is the xforms
* node that the expression is associated with. The other parameters are as
* required by DOM's XPathEvaluator.
*/
NS_IMETHOD Evaluate(const nsAString & aExpression, nsIDOMNode *aContextNode, PRUint32 aContextPosition, PRUint32 aContextSize, nsIDOMNode *aResolverNode, PRUint16 aType, nsISupports *aInResult, nsISupports **aResult) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIXFormsXPathEvaluator,
TRANSFORMIIX_XFORMS_XPATH_EVALUATOR_IID)
#endif /* nsIXFormsXPathEvaluator_h */

Просмотреть файл

@ -1,272 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
*
* The Initial Developer of the Original Code is
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Aaron Reed <aaronr@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsXFormsXPathEvaluator.h"
#include "nsCOMPtr.h"
#include "nsIAtom.h"
#include "nsIDOMClassInfo.h"
#include "nsXPathExpression.h"
#include "nsXPathNSResolver.h"
#include "nsXPathResult.h"
#include "nsContentCID.h"
#include "txExpr.h"
#include "txExprParser.h"
#include "nsDOMError.h"
#include "txURIUtils.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsDOMString.h"
#include "nsINameSpaceManager.h"
#include "txError.h"
#include "txAtoms.h"
#include "txXFormsFunctions.h"
#include "nsIDOM3Node.h"
#include "nsContentUtils.h"
NS_IMPL_ADDREF(nsXFormsXPathEvaluator)
NS_IMPL_RELEASE(nsXFormsXPathEvaluator)
NS_INTERFACE_MAP_BEGIN(nsXFormsXPathEvaluator)
NS_INTERFACE_MAP_ENTRY(nsIXFormsXPathEvaluator)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXFormsXPathEvaluator)
NS_INTERFACE_MAP_END
nsXFormsXPathEvaluator::nsXFormsXPathEvaluator()
{
}
nsXFormsXPathEvaluator::~nsXFormsXPathEvaluator()
{
}
NS_IMETHODIMP
nsXFormsXPathEvaluator::CreateExpression(const nsAString & aExpression,
nsIDOMNode *aResolverNode,
nsIDOMNSXPathExpression **aResult)
{
nsresult rv = NS_OK;
if (!mRecycler) {
nsRefPtr<txResultRecycler> recycler = new txResultRecycler;
NS_ENSURE_TRUE(recycler, NS_ERROR_OUT_OF_MEMORY);
rv = recycler->init();
NS_ENSURE_SUCCESS(rv, rv);
mRecycler = recycler;
}
XFormsParseContextImpl pContext(aResolverNode);
nsAutoPtr<Expr> expression;
rv = txExprParser::createExpr(PromiseFlatString(aExpression), &pContext,
getter_Transfers(expression));
if (NS_FAILED(rv)) {
if (rv == NS_ERROR_DOM_NAMESPACE_ERR) {
return NS_ERROR_DOM_NAMESPACE_ERR;
}
return NS_ERROR_DOM_INVALID_EXPRESSION_ERR;
}
*aResult = new nsXPathExpression(expression, mRecycler);
if (!*aResult) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsXPathEvaluator::Evaluate(const nsAString & aExpression,
nsIDOMNode *aContextNode,
PRUint32 aPosition,
PRUint32 aSize,
nsIDOMNode *aResolverNode,
PRUint16 aType,
nsISupports *aInResult,
nsISupports **aResult)
{
// XXX Need to check document of aContextNode if created by
// QI'ing a document.
nsCOMPtr<nsIDOMNSXPathExpression> expression;
nsresult rv = CreateExpression(aExpression, aResolverNode,
getter_AddRefs(expression));
NS_ENSURE_SUCCESS(rv, rv);
return expression->EvaluateWithContext(aContextNode, aPosition, aSize,
aType, aInResult, aResult);
}
/*
* Implementation of txIParseContext private to nsXFormsXPathEvaluator
* XFormsParseContextImpl bases on a nsIDOMXPathNSResolver
*/
nsresult nsXFormsXPathEvaluator::XFormsParseContextImpl::resolveNamespacePrefix
(nsIAtom* aPrefix, PRInt32& aID)
{
aID = kNameSpaceID_Unknown;
if (!mResolverNode) {
return NS_ERROR_DOM_NAMESPACE_ERR;
}
nsAutoString prefix;
if (aPrefix) {
aPrefix->ToString(prefix);
}
nsVoidableString ns;
nsresult rv;
// begin - taken directly from nsXPathNSResolver::LookupNamespaceURI
if (prefix.EqualsLiteral("xml")) {
ns.AssignLiteral("http://www.w3.org/XML/1998/namespace");
rv = NS_OK;
}
else {
nsCOMPtr<nsIDOM3Node> dom3Node = do_QueryInterface(mResolverNode);
NS_ASSERTION(dom3Node, "Need a node to resolve namespaces.");
if( dom3Node ) {
rv = dom3Node->LookupNamespaceURI(prefix, ns);
}
else {
SetDOMStringToNull(ns);
rv = NS_OK;
}
}
// end - taken directly from nsXPathNSResolver::LookupNamespaceURI
NS_ENSURE_SUCCESS(rv, rv);
if (DOMStringIsNull(ns)) {
return NS_ERROR_DOM_NAMESPACE_ERR;
}
if (ns.IsEmpty()) {
aID = kNameSpaceID_None;
return NS_OK;
}
// get the namespaceID for the URI
return nsContentUtils::NameSpaceManager()->RegisterNameSpace(ns, aID);
}
nsresult
nsXFormsXPathEvaluator::XFormsParseContextImpl::resolveFunctionCall(
nsIAtom* aName,
PRInt32 aNamespaceID,
FunctionCall*& aFnCall)
{
if (aNamespaceID == kNameSpaceID_None) {
PRBool isOutOfMem = PR_TRUE;
if (aName == txXPathAtoms::avg) {
aFnCall = new XFormsFunctionCall(XFormsFunctionCall::AVG);
}
else if (aName == txXPathAtoms::booleanFromString) {
aFnCall = new XFormsFunctionCall(XFormsFunctionCall::BOOLEANFROMSTRING);
}
else if (aName == txXPathAtoms::countNonEmpty) {
aFnCall = new XFormsFunctionCall(XFormsFunctionCall::COUNTNONEMPTY);
}
else if (aName == txXPathAtoms::daysFromDate) {
aFnCall = new XFormsFunctionCall(XFormsFunctionCall::DAYSFROMDATE);
}
else if (aName == txXPathAtoms::_if) {
aFnCall = new XFormsFunctionCall(XFormsFunctionCall::IF);
}
else if (aName == txXPathAtoms::index) {
NS_ENSURE_TRUE(mResolverNode, NS_ERROR_FAILURE);
aFnCall = new XFormsFunctionCall(XFormsFunctionCall::INDEX,
mResolverNode);
}
else if (aName == txXPathAtoms::instance) {
NS_ENSURE_TRUE(mResolverNode, NS_ERROR_FAILURE);
aFnCall = new XFormsFunctionCall(XFormsFunctionCall::INSTANCE,
mResolverNode);
}
else if (aName == txXPathAtoms::max) {
aFnCall = new XFormsFunctionCall(XFormsFunctionCall::MAX);
}
else if (aName == txXPathAtoms::min) {
aFnCall = new XFormsFunctionCall(XFormsFunctionCall::MIN);
}
else if (aName == txXPathAtoms::months) {
aFnCall = new XFormsFunctionCall(XFormsFunctionCall::MONTHS);
}
else if (aName == txXPathAtoms::now) {
aFnCall = new XFormsFunctionCall(XFormsFunctionCall::NOW);
}
else if (aName == txXPathAtoms::property) {
aFnCall = new XFormsFunctionCall(XFormsFunctionCall::PROPERTY);
}
else if (aName == txXPathAtoms::seconds) {
aFnCall = new XFormsFunctionCall(XFormsFunctionCall::SECONDS);
}
else if (aName == txXPathAtoms::secondsFromDateTime) {
aFnCall = new XFormsFunctionCall(XFormsFunctionCall::SECONDSFROMDATETIME);
}
else {
// didn't find functioncall here, aFnCall should be null
isOutOfMem = PR_FALSE;
}
if (aFnCall)
{
return NS_OK;
}
else if (isOutOfMem) {
NS_ERROR("XPath FunctionLib failed on out-of-memory");
return NS_ERROR_OUT_OF_MEMORY;
}
}
return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
}
PRBool nsXFormsXPathEvaluator::XFormsParseContextImpl::caseInsensitiveNameTests()
{
// This will always be false since this handles XForms, which is XML-based,
// so case sensitive.
return PR_FALSE;
}
void
nsXFormsXPathEvaluator::XFormsParseContextImpl::SetErrorOffset(PRUint32 aOffset)
{
}

Просмотреть файл

@ -59,16 +59,23 @@
class nsXPathEvaluatorParseContext : public txIParseContext
{
public:
nsXPathEvaluatorParseContext(nsIDOMXPathNSResolver *aResolver,
nsXPathEvaluatorParseContext(nsXPathEvaluator &aEvaluator,
nsIDOMXPathNSResolver* aResolver,
nsTArray<PRInt32> *aNamespaceIDs,
nsCStringArray *aContractIDs,
nsCOMArray<nsISupports> *aState,
PRBool aIsCaseSensitive)
: mResolver(aResolver),
: mEvaluator(aEvaluator),
mResolver(aResolver),
mNamespaceIDs(aNamespaceIDs),
mContractIDs(aContractIDs),
mState(aState),
mLastError(NS_OK),
mIsCaseSensitive(aIsCaseSensitive)
{
}
~nsXPathEvaluatorParseContext()
{
NS_ASSERTION(mContractIDs ||
(!mNamespaceIDs || mNamespaceIDs->Length() == 0),
"Need contract IDs if there are namespaces.");
}
nsresult getError()
@ -83,7 +90,11 @@ public:
void SetErrorOffset(PRUint32 aOffset);
private:
nsXPathEvaluator &mEvaluator;
nsIDOMXPathNSResolver* mResolver;
nsTArray<PRInt32> *mNamespaceIDs;
nsCStringArray *mContractIDs;
nsCOMArray<nsISupports> *mState;
nsresult mLastError;
PRBool mIsCaseSensitive;
};
@ -113,38 +124,8 @@ nsXPathEvaluator::CreateExpression(const nsAString & aExpression,
nsIDOMXPathNSResolver *aResolver,
nsIDOMXPathExpression **aResult)
{
nsresult rv = NS_OK;
if (!mRecycler) {
nsRefPtr<txResultRecycler> recycler = new txResultRecycler;
NS_ENSURE_TRUE(recycler, NS_ERROR_OUT_OF_MEMORY);
rv = recycler->init();
NS_ENSURE_SUCCESS(rv, rv);
mRecycler = recycler;
}
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
nsXPathEvaluatorParseContext pContext(aResolver,
!doc || doc->IsCaseSensitive());
nsAutoPtr<Expr> expression;
rv = txExprParser::createExpr(PromiseFlatString(aExpression), &pContext,
getter_Transfers(expression));
if (NS_FAILED(rv)) {
if (rv == NS_ERROR_DOM_NAMESPACE_ERR) {
return NS_ERROR_DOM_NAMESPACE_ERR;
}
return NS_ERROR_DOM_INVALID_EXPRESSION_ERR;
}
*aResult = new nsXPathExpression(expression, mRecycler);
if (!*aResult) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*aResult);
return NS_OK;
return CreateExpression(aExpression, aResolver, (nsTArray<PRInt32>*)nsnull,
nsnull, nsnull, aResult);
}
NS_IMETHODIMP
@ -172,7 +153,6 @@ nsXPathEvaluator::Evaluate(const nsAString & aExpression,
{
// XXX Need to check document of aContextNode if created by
// QI'ing a document.
nsCOMPtr<nsIDOMXPathExpression> expression;
nsresult rv = CreateExpression(aExpression, aResolver,
getter_AddRefs(expression));
@ -189,6 +169,85 @@ nsXPathEvaluator::SetDocument(nsIDOMDocument* aDocument)
return NS_OK;
}
NS_IMETHODIMP
nsXPathEvaluator::CreateExpression(const nsAString & aExpression,
nsIDOMXPathNSResolver *aResolver,
nsStringArray *aNamespaceURIs,
nsCStringArray *aContractIDs,
nsCOMArray<nsISupports> *aState,
nsIDOMXPathExpression **aResult)
{
nsTArray<PRInt32> namespaceIDs;
if (aNamespaceURIs) {
PRInt32 count = aNamespaceURIs->Count();
if (!aContractIDs || aContractIDs->Count() != count) {
return NS_ERROR_FAILURE;
}
if (!namespaceIDs.SetLength(count)) {
return NS_ERROR_OUT_OF_MEMORY;
}
PRInt32 i;
for (i = 0; i < count; ++i) {
if (aContractIDs->CStringAt(i)->IsEmpty()) {
return NS_ERROR_FAILURE;
}
nsContentUtils::NameSpaceManager()->RegisterNameSpace(*aNamespaceURIs->StringAt(i), namespaceIDs[i]);
}
}
return CreateExpression(aExpression, aResolver, &namespaceIDs, aContractIDs,
aState, aResult);
}
nsresult
nsXPathEvaluator::CreateExpression(const nsAString & aExpression,
nsIDOMXPathNSResolver *aResolver,
nsTArray<PRInt32> *aNamespaceIDs,
nsCStringArray *aContractIDs,
nsCOMArray<nsISupports> *aState,
nsIDOMXPathExpression **aResult)
{
nsresult rv;
if (!mRecycler) {
nsRefPtr<txResultRecycler> recycler = new txResultRecycler;
NS_ENSURE_TRUE(recycler, NS_ERROR_OUT_OF_MEMORY);
rv = recycler->init();
NS_ENSURE_SUCCESS(rv, rv);
mRecycler = recycler;
}
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
nsXPathEvaluatorParseContext pContext(*this, aResolver, aNamespaceIDs,
aContractIDs, aState,
!doc || doc->IsCaseSensitive());
nsAutoPtr<Expr> expression;
rv = txExprParser::createExpr(PromiseFlatString(aExpression), &pContext,
getter_Transfers(expression));
if (NS_FAILED(rv)) {
if (rv == NS_ERROR_DOM_NAMESPACE_ERR) {
return NS_ERROR_DOM_NAMESPACE_ERR;
}
return NS_ERROR_DOM_INVALID_EXPRESSION_ERR;
}
*aResult = new nsXPathExpression(expression, mRecycler);
if (!*aResult) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*aResult);
return NS_OK;
}
/*
* Implementation of txIParseContext private to nsXPathEvaluator, based on a
* nsIDOMXPathNSResolver
@ -226,12 +285,31 @@ nsresult nsXPathEvaluatorParseContext::resolveNamespacePrefix
return nsContentUtils::NameSpaceManager()->RegisterNameSpace(ns, aID);
}
extern nsresult
TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, PRInt32 aNamespaceID,
nsIAtom *aName, nsISupports *aState,
FunctionCall *&aFunction);
nsresult
nsXPathEvaluatorParseContext::resolveFunctionCall(nsIAtom* aName,
PRInt32 aID,
FunctionCall*& aFn)
{
return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
nsresult rv = NS_ERROR_XPATH_UNKNOWN_FUNCTION;
PRUint32 i, count = mNamespaceIDs ? mNamespaceIDs->Length() : 0;
for (i = 0; i < count; ++i) {
if (mNamespaceIDs->ElementAt(i) == aID) {
nsISupports *state = mState ? mState->SafeObjectAt(i) : nsnull;
rv = TX_ResolveFunctionCallXPCOM(*mContractIDs->CStringAt(i), aID,
aName, state, aFn);
if (NS_SUCCEEDED(rv)) {
break;
}
}
}
return rv;
}
PRBool nsXPathEvaluatorParseContext::caseInsensitiveNameTests()

Просмотреть файл

@ -43,8 +43,10 @@
#include "nsIXPathEvaluatorInternal.h"
#include "nsIWeakReference.h"
#include "nsAutoPtr.h"
#include "nsString.h"
#include "txResultRecycler.h"
#include "nsAgg.h"
#include "nsTArray.h"
/**
* A class for evaluating an XPath expression string
@ -68,8 +70,21 @@ public:
// nsIXPathEvaluatorInternal interface
NS_IMETHOD SetDocument(nsIDOMDocument* aDocument);
NS_IMETHOD CreateExpression(const nsAString &aExpression,
nsIDOMXPathNSResolver *aResolver,
nsStringArray *aNamespaceURIs,
nsCStringArray *aContractIDs,
nsCOMArray<nsISupports> *aState,
nsIDOMXPathExpression **aResult);
private:
nsresult CreateExpression(const nsAString & aExpression,
nsIDOMXPathNSResolver *aResolver,
nsTArray<PRInt32> *aNamespaceIDs,
nsCStringArray *aContractIDs,
nsCOMArray<nsISupports> *aState,
nsIDOMXPathExpression **aResult);
nsWeakPtr mDocument;
nsRefPtr<txResultRecycler> mRecycler;
};

Просмотреть файл

@ -0,0 +1,129 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Peter Van der Beken.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@propagandism.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "txNodeSetAdaptor.h"
#include "txXPathTreeWalker.h"
txNodeSetAdaptor::txNodeSetAdaptor()
: mWritable(PR_TRUE)
{
}
txNodeSetAdaptor::txNodeSetAdaptor(txNodeSet *aNodeSet)
: mNodeSet(aNodeSet),
mWritable(PR_FALSE)
{
NS_ASSERTION(aNodeSet,
"Don't create an adaptor if you don't have a txNodeSet");
}
NS_IMPL_ISUPPORTS1(txNodeSetAdaptor, txINodeSet)
nsresult
txNodeSetAdaptor::Init()
{
if (!mNodeSet) {
mNodeSet = new txNodeSet(nsnull);
}
return mNodeSet ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
NS_IMETHODIMP
txNodeSetAdaptor::Item(PRUint32 aIndex, nsIDOMNode **aResult)
{
*aResult = nsnull;
if (aIndex > (PRUint32)mNodeSet->size()) {
return NS_ERROR_ILLEGAL_VALUE;
}
return txXPathNativeNode::getNode(mNodeSet->get(aIndex), aResult);
}
NS_IMETHODIMP
txNodeSetAdaptor::ItemAsNumber(PRUint32 aIndex, double *aResult)
{
if (aIndex > (PRUint32)mNodeSet->size()) {
return NS_ERROR_ILLEGAL_VALUE;
}
nsAutoString result;
txXPathNodeUtils::appendNodeValue(mNodeSet->get(aIndex), result);
*aResult = Double::toDouble(result);
return NS_OK;
}
NS_IMETHODIMP
txNodeSetAdaptor::ItemAsString(PRUint32 aIndex, nsAString &aResult)
{
if (aIndex > (PRUint32)mNodeSet->size()) {
return NS_ERROR_ILLEGAL_VALUE;
}
txXPathNodeUtils::appendNodeValue(mNodeSet->get(aIndex), aResult);
return NS_OK;
}
NS_IMETHODIMP
txNodeSetAdaptor::GetLength(PRUint32 *aLength)
{
*aLength = (PRUint32)mNodeSet->size();
return NS_OK;
}
NS_IMETHODIMP
txNodeSetAdaptor::Add(nsIDOMNode *aNode)
{
NS_ENSURE_TRUE(mWritable, NS_ERROR_FAILURE);
nsAutoPtr<txXPathNode> node(txXPathNativeNode::createXPathNode(aNode));
return node ? mNodeSet->add(*node) : NS_ERROR_OUT_OF_MEMORY;
}
txAExprResult*
txNodeSetAdaptor::GetTxNodeSet()
{
return mNodeSet;
}

Просмотреть файл

@ -12,15 +12,16 @@
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2004
* Peter Van der Beken.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Aaron Reed <aaronr@us.ibm.com>
* Peter Van der Beken <peterv@propagandism.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -36,66 +37,30 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsXFormsXPathEvaluator_h__
#define nsXFormsXPathEvaluator_h__
#ifndef txNodeSetAdaptor_h__
#define txNodeSetAdaptor_h__
#include "nsIXFormsXPathEvaluator.h"
#include "txIXPathContext.h"
#include "nsIXPathEvaluatorInternal.h"
#include "nsIWeakReference.h"
#include "nsAutoPtr.h"
#include "txResultRecycler.h"
class nsIDOMDocument;
class nsIDOMXPathExpression;
#include "txINodeSet.h"
#include "txNodeSet.h"
/**
* A class for evaluating an XPath expression string
* Implements an XPCOM wrapper around an XPath NodeSet.
*/
class nsXFormsXPathEvaluator : public nsIXFormsXPathEvaluator
class txNodeSetAdaptor : public txINodeSet
{
public:
nsXFormsXPathEvaluator();
virtual ~nsXFormsXPathEvaluator();
txNodeSetAdaptor();
txNodeSetAdaptor(txNodeSet *aNodeSet);
nsresult Init();
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIXFormsXPathEvaluator interface
NS_DECL_NSIXFORMXPATHEVALUATOR
NS_DECL_TXINODESET
private:
// txIParseContext implementation
class XFormsParseContextImpl : public txIParseContext
{
public:
XFormsParseContextImpl(nsIDOMNode* aResolverNode)
: mResolverNode(aResolverNode), mLastError(NS_OK)
{
}
~XFormsParseContextImpl()
{
}
nsresult getError()
{
return mLastError;
}
nsresult resolveNamespacePrefix(nsIAtom* aPrefix, PRInt32& aID);
nsresult resolveFunctionCall(nsIAtom* aName, PRInt32 aID,
FunctionCall*& aFunction);
PRBool caseInsensitiveNameTests();
void SetErrorOffset(PRUint32 aOffset);
private:
nsIDOMNode* mResolverNode;
nsresult mLastError;
};
nsRefPtr<txResultRecycler> mRecycler;
nsRefPtr<txNodeSet> mNodeSet;
PRBool mWritable;
};
#endif
#endif // txNodeSetAdaptor_h__

Просмотреть файл

@ -37,6 +37,7 @@
* ***** END LICENSE BLOCK ***** */
#include "txExpr.h"
#include "txDouble.h"
#include "txNodeSet.h"
#include "txIXPathContext.h"
#include "txXPathTreeWalker.h"
@ -118,14 +119,7 @@ RelationalExpr::compareResults(txIEvalContext* aContext, txAExprResult* aLeft,
rtype == txAExprResult::NUMBER) {
double lval = aLeft->numberValue();
double rval = aRight->numberValue();
#if defined(XP_WIN)
if (Double::isNaN(lval) || Double::isNaN(rval))
result = PR_FALSE;
else
result = lval == rval;
#else
result = lval == rval;
#endif
result = TX_DOUBLE_COMPARE(lval, ==, rval);
}
// Otherwise compare as strings. Try to use the stringobject in
@ -157,27 +151,22 @@ RelationalExpr::compareResults(txIEvalContext* aContext, txAExprResult* aLeft,
double leftDbl = aLeft->numberValue();
double rightDbl = aRight->numberValue();
#if defined(XP_WIN)
if (Double::isNaN(leftDbl) || Double::isNaN(rightDbl))
return PR_FALSE;
#endif
switch (mOp) {
case LESS_THAN:
{
return leftDbl < rightDbl;
return TX_DOUBLE_COMPARE(leftDbl, <, rightDbl);
}
case LESS_OR_EQUAL:
{
return leftDbl <= rightDbl;
return TX_DOUBLE_COMPARE(leftDbl, <=, rightDbl);
}
case GREATER_THAN:
{
return leftDbl > rightDbl;
return TX_DOUBLE_COMPARE(leftDbl, >, rightDbl);
}
case GREATER_OR_EQUAL:
{
return leftDbl >= rightDbl;
return TX_DOUBLE_COMPARE(leftDbl, >=, rightDbl);
}
default:
{

Просмотреть файл

@ -1,647 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
*
* The Initial Developer of the Original Code is
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Aaron Reed <aaronr@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* XFormsFunctionCall
* A representation of the XPath NodeSet funtions
*/
#include "txExpr.h"
#include "nsAutoPtr.h"
#include "txNodeSet.h"
#include "txAtoms.h"
#include "txIXPathContext.h"
#include "txTokenizer.h"
#include "txXFormsFunctions.h"
#include <math.h>
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentEvent.h"
#include "nsIDOMEvent.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMElement.h"
#include "nsIXFormsUtilityService.h"
#include "nsServiceManagerUtils.h" // needed for do_GetService?
#include "prprf.h"
#include "txXPathTreeWalker.h"
/*
* Creates a XFormsFunctionCall of the given type
*/
XFormsFunctionCall::XFormsFunctionCall(XFormsFunctions aType, nsIDOMNode *aResolverNode)
: mType(aType)
, mResolverNode(aResolverNode)
{
}
/*
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
*/
nsresult
XFormsFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
*aResult = nsnull;
nsresult rv = NS_OK;
txListIterator iter(&params);
switch (mType) {
case AVG:
{
if (!requireParams(1, 1, aContext))
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
nsRefPtr<txNodeSet> nodes;
nsresult rv = evaluateToNodeSet((Expr*)iter.next(), aContext,
getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, rv);
double res = 0;
PRInt32 i;
for (i = 0; i < nodes->size(); ++i) {
nsAutoString resultStr;
txXPathNodeUtils::appendNodeValue(nodes->get(i), resultStr);
res += Double::toDouble(resultStr);
}
if (i > 0) {
res = (res/i);
}
else {
res = Double::NaN;
}
return aContext->recycler()->getNumberResult(res, aResult);
}
case BOOLEANFROMSTRING:
{
if (!requireParams(1, 1, aContext))
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
Expr *expr1 = NS_STATIC_CAST(Expr*, iter.next());
nsAutoString booleanValue;
expr1->evaluateToString(aContext, booleanValue);
aContext->recycler()->getBoolResult(
booleanValue.EqualsLiteral("1") ||
booleanValue.LowerCaseEqualsLiteral("true"),
aResult);
return NS_OK;
}
case COUNTNONEMPTY:
{
if (!requireParams(1, 1, aContext))
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
nsRefPtr<txNodeSet> nodes;
nsresult rv = evaluateToNodeSet((Expr*)iter.next(), aContext,
getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 i, count=0;
for (i = 0; i < nodes->size(); ++i) {
nsAutoString resultStr;
txXPathNodeUtils::appendNodeValue(nodes->get(i), resultStr);
if (!resultStr.IsEmpty()) {
count++;
}
}
return aContext->recycler()->getNumberResult(count, aResult);
}
case DAYSFROMDATE:
{
if (!requireParams(1, 1, aContext))
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
Expr *expr1 = NS_STATIC_CAST(Expr*, iter.next());
nsAutoString date;
expr1->evaluateToString(aContext, date);
nsCOMPtr<nsIXFormsUtilityService>xformsService =
do_GetService("@mozilla.org/xforms-utility-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 result = 0;
double res = Double::NaN;
nsresult rv = xformsService->GetDaysFromDateTime(date, &result);
if (NS_SUCCEEDED(rv)) {
res = result;
}
else if (rv != NS_ERROR_ILLEGAL_VALUE) {
// if we failed for a reason other than the parameter value, pass that
// up the chain
return rv;
}
return aContext->recycler()->getNumberResult(res, aResult);
}
case IF:
{
if (!requireParams(3, 3, aContext))
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
Expr *expr1 = NS_STATIC_CAST(Expr*, iter.next());
PRBool test;
nsAutoString valueToReturn;
expr1->evaluateToBool(aContext, test);
// grab 'true' value to return
Expr *getvalue = NS_STATIC_CAST(Expr*, iter.next());
if (!test) {
// grab 'false' value to return
getvalue = NS_STATIC_CAST(Expr*, iter.next());
}
getvalue->evaluateToString(aContext, valueToReturn);
return aContext->recycler()->getStringResult(valueToReturn, aResult);
}
case INDEX:
{
// Given an element's id as the parameter, need to query the element and
// make sure that it is a xforms:repeat node. Given that, must query
// its index.
if (!requireParams(1, 1, aContext))
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
Expr *expr1 = NS_STATIC_CAST(Expr*, iter.next());
nsAutoString indexId;
expr1->evaluateToString(aContext, indexId);
// here document is the XForms document
nsCOMPtr<nsIDOMDocument> document;
rv = mResolverNode->GetOwnerDocument(getter_AddRefs(document));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(document, NS_ERROR_NULL_POINTER);
// indexId should be the id of a nsIXFormsRepeatElement
nsCOMPtr<nsIDOMElement> repeatEle;
rv = document->GetElementById(indexId, getter_AddRefs(repeatEle));
NS_ENSURE_SUCCESS(rv, rv);
// now get the index value from the xforms:repeat. Need to use the
// service to do this work so that we don't have dependencies in
// transformiix on XForms.
nsCOMPtr<nsIXFormsUtilityService>xformsService =
do_GetService("@mozilla.org/xforms-utility-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 index = 0;
double res = Double::NaN;
rv = xformsService->GetRepeatIndex(repeatEle, &index);
NS_ENSURE_SUCCESS(rv, rv);
if (index >= 0) {
// repeat's index is 1-based. If it is 0, then that is still ok since
// repeat's index can be 0 if uninitialized or if the nodeset that it
// is bound to is empty (either initially or due to delete remove all
// of the instance nodes). If index == -1, then repeatEle isn't an
// XForms repeat element, so we need to return NaN per spec.
res = index;
}
return aContext->recycler()->getNumberResult(res, aResult);
}
case INSTANCE:
{
nsresult rv;
if (!requireParams(1, 1, aContext))
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
nsRefPtr<txNodeSet> resultSet;
rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet));
NS_ENSURE_SUCCESS(rv, rv);
Expr *expr1 = NS_STATIC_CAST(Expr*, iter.next());
nsAutoString instanceId;
expr1->evaluateToString(aContext, instanceId);
// here document is the XForms document
nsCOMPtr<nsIDOMDocument> document;
rv = mResolverNode->GetOwnerDocument(getter_AddRefs(document));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(document, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIDOMElement> instEle;
rv = document->GetElementById(instanceId, getter_AddRefs(instEle));
PRBool foundInstance = PR_FALSE;
nsAutoString localname, namespaceURI;
if (instEle) {
instEle->GetLocalName(localname);
instEle->GetNamespaceURI(namespaceURI);
if (localname.EqualsLiteral("instance") &&
namespaceURI.EqualsLiteral(NS_NAMESPACE_XFORMS)) {
foundInstance = PR_TRUE;
}
}
if (!foundInstance) {
// We didn't find an instance element with the given id. Return the
// empty result set.
*aResult = resultSet;
NS_ADDREF(*aResult);
return NS_OK;
}
// Make sure that this element is contained in the same
// model as the context node of the expression as per
// the XForms 1.0 spec.
// first step is to get the contextNode passed in to
// the evaluation
nsCOMPtr<nsIDOMNode> xfContextNode;
rv = txXPathNativeNode::getNode(aContext->getContextNode(),
getter_AddRefs(xfContextNode));
NS_ENSURE_SUCCESS(rv, rv);
// now see if the node we found (instEle) and the
// context node for the evaluation (xfContextNode) link
// back to the same model.
nsCOMPtr<nsIXFormsUtilityService>xformsService =
do_GetService("@mozilla.org/xforms-utility-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> instNode, modelInstance;
instNode = do_QueryInterface(instEle);
rv = xformsService->GetModelFromNode(instNode,
getter_AddRefs(modelInstance));
NS_ENSURE_SUCCESS(rv, rv);
PRBool modelContainsNode = PR_FALSE;
rv = xformsService->IsNodeAssocWithModel(xfContextNode,
modelInstance,
&modelContainsNode);
NS_ENSURE_SUCCESS(rv, rv);
if (modelContainsNode) {
// ok, we've found an instance node with the proper id
// that fulfills the requirement of being from the
// same model as the context node. Now we need to
// return a 'node-set containing just the root
// element node of the referenced instance data'.
// Wonderful.
nsCOMPtr<nsIDOMNode> instanceRoot;
rv = xformsService->GetInstanceDocumentRoot(
instanceId,
modelInstance,
getter_AddRefs(instanceRoot));
NS_ENSURE_SUCCESS(rv, rv);
if (instanceRoot) {
nsAutoPtr<txXPathNode> txNode(txXPathNativeNode::createXPathNode(instanceRoot));
if (txNode) {
resultSet->add(*txNode);
}
}
}
// XXX where we need to do the work
// if (walker.moveToElementById(instanceId)) {
// resultSet->add(walker.getCurrentPosition());
// }
*aResult = resultSet;
NS_ADDREF(*aResult);
return NS_OK;
}
case MAX:
{
if (!requireParams(1, 1, aContext))
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
nsRefPtr<txNodeSet> nodes;
nsresult rv = evaluateToNodeSet((Expr*)iter.next(), aContext,
getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, rv);
double res = Double::NaN;
PRInt32 i;
for (i = 0; i < nodes->size(); ++i) {
double test;
nsAutoString resultStr;
txXPathNodeUtils::appendNodeValue(nodes->get(i), resultStr);
test = Double::toDouble(resultStr);
if (Double::isNaN(test)) {
res = Double::NaN;
break;
}
if (test > res || i == 0) {
res = test;
}
}
return aContext->recycler()->getNumberResult(res, aResult);
}
case MIN:
{
if (!requireParams(1, 1, aContext))
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
nsRefPtr<txNodeSet> nodes;
nsresult rv = evaluateToNodeSet((Expr*)iter.next(), aContext,
getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, rv);
double res = Double::NaN;
PRInt32 i;
for (i = 0; i < nodes->size(); ++i) {
double test;
nsAutoString resultStr;
txXPathNodeUtils::appendNodeValue(nodes->get(i), resultStr);
test = Double::toDouble(resultStr);
if (Double::isNaN(test)) {
res = Double::NaN;
break;
}
if ((test < res) || (i==0)) {
res = test;
}
}
return aContext->recycler()->getNumberResult(res, aResult);
}
case MONTHS:
{
if (!requireParams(1, 1, aContext))
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
Expr *expr1 = NS_STATIC_CAST(Expr*, iter.next());
nsAutoString duration;
expr1->evaluateToString(aContext, duration);
nsCOMPtr<nsIXFormsUtilityService>xformsService =
do_GetService("@mozilla.org/xforms-utility-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 result = 0;
double res = Double::NaN;
nsresult rv = xformsService->GetMonths(duration, &result);
if (NS_SUCCEEDED(rv)) {
res = result;
}
else if (rv != NS_ERROR_ILLEGAL_VALUE) {
// if we failed for a reason other than the parameter value, pass that
// up the chain
return rv;
}
return aContext->recycler()->getNumberResult(res, aResult);
}
case NOW:
{
if (!requireParams(0, 0, aContext))
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
PRExplodedTime time;
char ctime[60];
PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &time);
int gmtoffsethour = time.tm_params.tp_gmt_offset < 0 ?
-1*time.tm_params.tp_gmt_offset / 3600 :
time.tm_params.tp_gmt_offset / 3600;
int remainder = time.tm_params.tp_gmt_offset%3600;
int gmtoffsetminute = remainder ? remainder/60 : 00;
char zone_location[40];
const int zoneBufSize = sizeof(zone_location);
PR_snprintf(zone_location, zoneBufSize, "%c%02d:%02d\0",
time.tm_params.tp_gmt_offset < 0 ? '-' : '+',
gmtoffsethour, gmtoffsetminute);
PR_FormatTime(ctime, sizeof(ctime), "%Y-%m-%dT%H:%M:%S\0", &time);
nsString sTime = NS_ConvertASCIItoUTF16(ctime) + NS_ConvertASCIItoUTF16(zone_location);
return aContext->recycler()->getStringResult(sTime, aResult);
}
case PROPERTY:
{
if (!requireParams(1, 1, aContext))
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
Expr *expr1 = NS_STATIC_CAST(Expr*, iter.next());
nsAutoString property;
expr1->evaluateToString(aContext, property);
// This function can handle "version" and "conformance-level"
// which is all that the XForms 1.0 spec is worried about
if (property.Equals(NS_LITERAL_STRING("version")))
property.Assign(NS_LITERAL_STRING("1.0"));
else if (property.Equals(NS_LITERAL_STRING("conformance-level")))
property.Assign(NS_LITERAL_STRING("basic"));
return aContext->recycler()->getStringResult(property, aResult);
}
case SECONDS:
{
if (!requireParams(1, 1, aContext))
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
Expr *expr1 = NS_STATIC_CAST(Expr*, iter.next());
nsAutoString duration;
expr1->evaluateToString(aContext, duration);
nsCOMPtr<nsIXFormsUtilityService>xformsService =
do_GetService("@mozilla.org/xforms-utility-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
double res;
nsresult rv = xformsService->GetSeconds(duration, &res);
if (NS_FAILED(rv)) {
if (rv != NS_ERROR_ILLEGAL_VALUE) {
// if we failed for a reason other than the parameter value, pass that
// up the chain
return rv;
}
res = Double::NaN;
}
return aContext->recycler()->getNumberResult(res, aResult);
}
case SECONDSFROMDATETIME:
{
if (!requireParams(1, 1, aContext))
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
Expr *expr1 = NS_STATIC_CAST(Expr*, iter.next());
nsAutoString dateTime;
expr1->evaluateToString(aContext, dateTime);
nsCOMPtr<nsIXFormsUtilityService>xformsService =
do_GetService("@mozilla.org/xforms-utility-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
double res;
nsresult rv = xformsService->GetSecondsFromDateTime(dateTime, &res);
if (NS_FAILED(rv)) {
if (rv != NS_ERROR_ILLEGAL_VALUE) {
// if we failed for a reason other than the parameter value, pass that
// up the chain
return rv;
}
res = Double::NaN;
}
return aContext->recycler()->getNumberResult(res, aResult);
}
} /* switch() */
aContext->receiveError(NS_LITERAL_STRING("Internal error"),
NS_ERROR_UNEXPECTED);
return NS_ERROR_UNEXPECTED;
}
Expr::ResultType
XFormsFunctionCall::getReturnType()
{
// It doesn't really matter what we return here, but it might
// be a good idea to try to keep this as unoptimizable as possible
return ANY_RESULT;
}
PRBool
XFormsFunctionCall::isSensitiveTo(ContextSensitivity aContext)
{
// It doesn't really matter what we return here, but it might
// be a good idea to try to keep this as unoptimizable as possible
return PR_TRUE;
}
#ifdef TX_TO_STRING
nsresult
XFormsFunctionCall::getNameAtom(nsIAtom** aAtom)
{
switch (mType) {
case AVG:
{
*aAtom = txXPathAtoms::avg;
break;
}
case BOOLEANFROMSTRING:
{
*aAtom = txXPathAtoms::booleanFromString;
break;
}
case COUNTNONEMPTY:
{
*aAtom = txXPathAtoms::countNonEmpty;
break;
}
case DAYSFROMDATE:
{
*aAtom = txXPathAtoms::daysFromDate;
break;
}
case IF:
{
*aAtom = txXPathAtoms::_if;
break;
}
case INDEX:
{
*aAtom = txXPathAtoms::index;
break;
}
case INSTANCE:
{
*aAtom = txXPathAtoms::instance;
break;
}
case MAX:
{
*aAtom = txXPathAtoms::max;
break;
}
case MIN:
{
*aAtom = txXPathAtoms::min;
break;
}
case MONTHS:
{
*aAtom = txXPathAtoms::months;
break;
}
case NOW:
{
*aAtom = txXPathAtoms::now;
break;
}
case PROPERTY:
{
*aAtom = txXPathAtoms::property;
break;
}
case SECONDS:
{
*aAtom = txXPathAtoms::seconds;
break;
}
case SECONDSFROMDATETIME:
{
*aAtom = txXPathAtoms::secondsFromDateTime;
break;
}
default:
{
*aAtom = 0;
return NS_ERROR_FAILURE;
}
}
NS_ADDREF(*aAtom);
return NS_OK;
}
#endif

Просмотреть файл

@ -0,0 +1,587 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Peter Van der Beken.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@propagandism.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsAutoPtr.h"
#include "nsComponentManagerUtils.h"
#include "nsDependentString.h"
#include "nsIAtom.h"
#include "nsIInterfaceInfoManager.h"
#include "nsServiceManagerUtils.h"
#include "txExpr.h"
#include "txIFunctionEvaluationContext.h"
#include "txIXPathContext.h"
#include "txNodeSetAdaptor.h"
#include "txXPathTreeWalker.h"
#include "xptcall.h"
class txFunctionEvaluationContext : public txIFunctionEvaluationContext
{
public:
txFunctionEvaluationContext(txIEvalContext *aContext, nsISupports *aState);
NS_DECL_ISUPPORTS
NS_DECL_TXIFUNCTIONEVALUATIONCONTEXT
void ClearContext()
{
mContext = nsnull;
}
private:
txIEvalContext *mContext;
nsCOMPtr<nsISupports> mState;
};
txFunctionEvaluationContext::txFunctionEvaluationContext(txIEvalContext *aContext,
nsISupports *aState)
: mContext(aContext),
mState(aState)
{
}
NS_IMPL_ISUPPORTS1(txFunctionEvaluationContext, txIFunctionEvaluationContext)
NS_IMETHODIMP
txFunctionEvaluationContext::GetPosition(PRUint32 *aPosition)
{
NS_ENSURE_TRUE(mContext, NS_ERROR_FAILURE);
*aPosition = mContext->position();
return NS_OK;
}
NS_IMETHODIMP
txFunctionEvaluationContext::GetSize(PRUint32 *aSize)
{
NS_ENSURE_TRUE(mContext, NS_ERROR_FAILURE);
*aSize = mContext->size();
return NS_OK;
}
NS_IMETHODIMP
txFunctionEvaluationContext::GetContextNode(nsIDOMNode **aNode)
{
NS_ENSURE_TRUE(mContext, NS_ERROR_FAILURE);
return txXPathNativeNode::getNode(mContext->getContextNode(), aNode);
}
NS_IMETHODIMP
txFunctionEvaluationContext::GetState(nsISupports **aState)
{
NS_IF_ADDREF(*aState = mState);
return NS_OK;
}
enum txArgumentType {
BOOLEAN = nsXPTType::T_BOOL,
NUMBER = nsXPTType::T_DOUBLE,
STRING = nsXPTType::T_DOMSTRING,
NODESET,
CONTEXT,
UNKNOWN
};
class txXPCOMExtensionFunctionCall : public FunctionCall
{
public:
txXPCOMExtensionFunctionCall(nsISupports *aHelper, const nsIID &aIID,
PRUint16 aMethodIndex,
#ifdef TX_TO_STRING
PRInt32 aNamespaceID, nsIAtom *aName,
#endif
nsISupports *aState);
TX_DECL_FUNCTION;
private:
txArgumentType GetParamType(const nsXPTParamInfo &aParam,
nsIInterfaceInfo *aInfo);
nsCOMPtr<nsISupports> mHelper;
nsIID mIID;
PRUint16 mMethodIndex;
#ifdef TX_TO_STRING
PRInt32 mNamespaceID;
nsCOMPtr<nsIAtom> mName;
#endif
nsCOMPtr<nsISupports> mState;
};
txXPCOMExtensionFunctionCall::txXPCOMExtensionFunctionCall(nsISupports *aHelper,
const nsIID &aIID,
PRUint16 aMethodIndex,
#ifdef TX_TO_STRING
PRInt32 aNamespaceID,
nsIAtom *aName,
#endif
nsISupports *aState)
: mHelper(aHelper),
mIID(aIID),
mMethodIndex(aMethodIndex),
#ifdef TX_TO_STRING
mNamespaceID(aNamespaceID),
mName(aName),
#endif
mState(aState)
{
}
class txInterfacesArrayHolder
{
public:
txInterfacesArrayHolder(nsIID **aArray, PRUint32 aCount) : mArray(aArray),
mCount(aCount)
{
}
~txInterfacesArrayHolder()
{
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(mCount, mArray);
}
private:
nsIID **mArray;
PRUint32 mCount;
};
static nsresult
LookupFunction(const char *aContractID, nsIAtom* aName, nsIID &aIID,
PRUint16 &aMethodIndex)
{
nsresult rv;
nsCOMPtr<nsIClassInfo> classInfo = do_GetClassObject(aContractID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIInterfaceInfoManager> iim =
do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(iim, NS_ERROR_FAILURE);
nsIID** iidArray = nsnull;
PRUint32 iidCount = 0;
rv = classInfo->GetInterfaces(&iidCount, &iidArray);
NS_ENSURE_SUCCESS(rv, rv);
txInterfacesArrayHolder holder(iidArray, iidCount);
// Remove any minus signs and uppercase the following letter (so
// foo-bar becomes fooBar). Note that if there are any names that already
// have uppercase letters they might cause false matches (both fooBar and
// foo-bar matching fooBar).
const char *name;
aName->GetUTF8String(&name);
nsCAutoString methodName;
char letter;
PRBool upperNext = PR_FALSE;
while ((letter = *name)) {
if (letter == '-') {
upperNext = PR_TRUE;
}
else {
methodName.Append(upperNext ? nsCRT::ToUpper(letter) : letter);
upperNext = PR_FALSE;
}
++name;
}
PRUint32 i;
for (i = 0; i < iidCount; ++i) {
nsIID *iid = iidArray[i];
nsCOMPtr<nsIInterfaceInfo> info;
rv = iim->GetInfoForIID(iid, getter_AddRefs(info));
NS_ENSURE_SUCCESS(rv, rv);
PRUint16 methodIndex;
const nsXPTMethodInfo *methodInfo;
rv = info->GetMethodInfoForName(methodName.get(), &methodIndex,
&methodInfo);
if (NS_SUCCEEDED(rv)) {
// Exclude notxpcom and hidden. Also check that we have at least a
// return value (the xpidl compiler ensures that that return value
// is the last argument).
PRUint8 paramCount = methodInfo->GetParamCount();
if (methodInfo->IsNotXPCOM() || methodInfo->IsHidden() ||
paramCount == 0 ||
!methodInfo->GetParam(paramCount - 1).IsRetval()) {
return NS_ERROR_FAILURE;
}
aIID = *iid;
aMethodIndex = methodIndex;
return NS_OK;
}
}
return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
}
/* static */
nsresult
TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, PRInt32 aNamespaceID,
nsIAtom* aName, nsISupports *aState,
FunctionCall *&aFunction)
{
nsIID iid;
PRUint16 methodIndex;
nsresult rv = LookupFunction(aContractID.get(), aName, iid, methodIndex);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupports> helper;
rv = CallGetService(aContractID.get(), iid, getter_AddRefs(helper));
NS_ENSURE_SUCCESS(rv, rv);
aFunction = new txXPCOMExtensionFunctionCall(helper, iid, methodIndex,
#ifdef TX_TO_STRING
aNamespaceID, aName,
#endif
aState);
return aFunction ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
txArgumentType
txXPCOMExtensionFunctionCall::GetParamType(const nsXPTParamInfo &aParam,
nsIInterfaceInfo *aInfo)
{
PRUint8 tag = aParam.GetType().TagPart();
switch (tag) {
case nsXPTType::T_BOOL:
case nsXPTType::T_DOUBLE:
case nsXPTType::T_DOMSTRING:
{
return txArgumentType(tag);
}
case nsXPTType::T_INTERFACE:
case nsXPTType::T_INTERFACE_IS:
{
nsIID iid;
aInfo->GetIIDForParamNoAlloc(mMethodIndex, &aParam, &iid);
if (iid.Equals(NS_GET_IID(txINodeSet))) {
return NODESET;
}
if (iid.Equals(NS_GET_IID(txIFunctionEvaluationContext))) {
return CONTEXT;
}
}
default:
{
// XXX Error!
return UNKNOWN;
}
}
}
class txParamArrayHolder
{
public:
txParamArrayHolder()
: mCount(0)
{
}
~txParamArrayHolder();
PRBool Init(PRUint8 aCount);
operator nsXPTCVariant*() const
{
return mArray;
}
private:
nsAutoArrayPtr<nsXPTCVariant> mArray;
PRUint8 mCount;
};
txParamArrayHolder::~txParamArrayHolder()
{
PRUint8 i;
for (i = 0; i < mCount; ++i) {
nsXPTCVariant &variant = mArray[i];
if (variant.IsValInterface()) {
NS_STATIC_CAST(nsISupports*, variant.val.p)->Release();
}
else if (variant.IsValDOMString()) {
delete (nsAString*)variant.val.p;
}
}
}
PRBool
txParamArrayHolder::Init(PRUint8 aCount)
{
mCount = aCount;
mArray = new nsXPTCVariant[mCount];
if (!mArray) {
return PR_FALSE;
}
memset(mArray, 0, mCount * sizeof(nsXPTCVariant));
return PR_TRUE;
}
nsresult
txXPCOMExtensionFunctionCall::evaluate(txIEvalContext* aContext,
txAExprResult** aResult)
{
nsCOMPtr<nsIInterfaceInfoManager> iim =
do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(iim, NS_ERROR_FAILURE);
nsCOMPtr<nsIInterfaceInfo> info;
nsresult rv = iim->GetInfoForIID(&mIID, getter_AddRefs(info));
NS_ENSURE_SUCCESS(rv, rv);
const nsXPTMethodInfo *methodInfo;
rv = info->GetMethodInfo(mMethodIndex, &methodInfo);
NS_ENSURE_SUCCESS(rv, rv);
PRUint8 paramCount = methodInfo->GetParamCount();
PRUint8 inArgs = paramCount - 1;
txParamArrayHolder invokeParams;
if (!invokeParams.Init(paramCount)) {
return NS_ERROR_OUT_OF_MEMORY;
}
const nsXPTParamInfo &paramInfo = methodInfo->GetParam(0);
txArgumentType type = GetParamType(paramInfo, info);
if (type == UNKNOWN) {
return NS_ERROR_FAILURE;
}
txFunctionEvaluationContext *context;
PRUint8 i = 0;
if (type == CONTEXT) {
if (paramInfo.IsOut()) {
// We don't support out values.
return NS_ERROR_FAILURE;
}
// Create context wrapper.
context = new txFunctionEvaluationContext(aContext, mState);
if (!context) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsXPTCVariant &invokeParam = invokeParams[0];
invokeParam.type = paramInfo.GetType();
invokeParam.SetValIsInterface();
NS_ADDREF((txIFunctionEvaluationContext*&)invokeParam.val.p = context);
// Skip first argument, since it's the context.
++i;
}
else {
context = nsnull;
}
// XXX varargs
if (!requireParams(inArgs - i, inArgs - i, aContext)) {
return NS_ERROR_FAILURE;
}
txListIterator iter(&params);
for (; i < inArgs; ++i) {
Expr* expr = NS_STATIC_CAST(Expr*, iter.next());
const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
txArgumentType type = GetParamType(paramInfo, info);
if (type == UNKNOWN) {
return NS_ERROR_FAILURE;
}
nsXPTCVariant &invokeParam = invokeParams[i];
if (paramInfo.IsOut()) {
// We don't support out values.
return NS_ERROR_FAILURE;
}
invokeParam.type = paramInfo.GetType();
switch (type) {
case NODESET:
{
nsRefPtr<txNodeSet> nodes;
rv = evaluateToNodeSet(expr, aContext, getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, rv);
txNodeSetAdaptor *adaptor = new txNodeSetAdaptor(nodes);
if (!adaptor) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMPtr<txINodeSet> nodeSet = adaptor;
rv = adaptor->Init();
NS_ENSURE_SUCCESS(rv, rv);
invokeParam.SetValIsInterface();
nodeSet.swap((txINodeSet*&)invokeParam.val.p);
break;
}
case BOOLEAN:
{
rv = expr->evaluateToBool(aContext, invokeParam.val.b);
NS_ENSURE_SUCCESS(rv, rv);
break;
}
case NUMBER:
{
invokeParam.val.d = evaluateToNumber(expr, aContext);
break;
}
case STRING:
{
nsString *value = new nsString();
if (!value) {
return NS_ERROR_OUT_OF_MEMORY;
}
rv = expr->evaluateToString(aContext, *value);
NS_ENSURE_SUCCESS(rv, rv);
invokeParam.SetValIsDOMString();
invokeParam.val.p = value;
break;
}
case CONTEXT:
case UNKNOWN:
{
// We only support passing the context as the *first* argument.
return NS_ERROR_FAILURE;
}
}
}
const nsXPTParamInfo &returnInfo = methodInfo->GetParam(inArgs);
txArgumentType returnType = GetParamType(returnInfo, info);
if (returnType == UNKNOWN) {
return NS_ERROR_FAILURE;
}
nsXPTCVariant &returnParam = invokeParams[inArgs];
returnParam.type = returnInfo.GetType();
if (returnType == STRING) {
nsString *value = new nsString();
if (!value) {
return NS_ERROR_FAILURE;
}
returnParam.SetValIsDOMString();
returnParam.val.p = value;
}
else {
returnParam.SetPtrIsData();
returnParam.ptr = &returnParam.val;
}
rv = XPTC_InvokeByIndex(mHelper, mMethodIndex, paramCount, invokeParams);
// In case someone is holding on to the txFunctionEvaluationContext which
// could thus stay alive longer than this function.
if (context) {
context->ClearContext();
}
NS_ENSURE_SUCCESS(rv, rv);
switch (returnType) {
case NODESET:
{
txINodeSet *nodeSet = NS_STATIC_CAST(txINodeSet*,
returnParam.val.p);
NS_ADDREF(*aResult = nodeSet->GetTxNodeSet());
return NS_OK;
}
case BOOLEAN:
{
aContext->recycler()->getBoolResult(returnParam.val.b, aResult);
return NS_OK;
}
case NUMBER:
{
return aContext->recycler()->getNumberResult(returnParam.val.d,
aResult);
}
case STRING:
{
nsString *returned = NS_STATIC_CAST(nsString*,
returnParam.val.p);
return aContext->recycler()->getStringResult(*returned, aResult);
}
default:
{
// Huh?
return NS_ERROR_FAILURE;
}
}
}
Expr::ResultType
txXPCOMExtensionFunctionCall::getReturnType()
{
// It doesn't really matter what we return here, but it might
// be a good idea to try to keep this as unoptimizable as possible
return ANY_RESULT;
}
PRBool
txXPCOMExtensionFunctionCall::isSensitiveTo(ContextSensitivity aContext)
{
// It doesn't really matter what we return here, but it might
// be a good idea to try to keep this as unoptimizable as possible
return PR_TRUE;
}
#ifdef TX_TO_STRING
nsresult
txXPCOMExtensionFunctionCall::getNameAtom(nsIAtom** aAtom)
{
NS_ADDREF(*aAtom = mName);
return NS_OK;
}
#endif

Просмотреть файл

@ -148,6 +148,7 @@ XPIDLSRCS = \
nsIXFormsCopyElement.idl \
nsIXFormsEphemeralMessageUI.idl \
nsIXFormsRangeConditionAccessors.idl \
nsIXFormsXPathFunctions.idl \
$(NULL)
# XForms source files
@ -208,6 +209,7 @@ CPPSRCS = \
nsXFormsRangeAccessors.cpp \
nsXFormsCopyElement.cpp \
nsXFormsRangeConditionAccessors.cpp \
nsXFormsXPathFunctions.cpp \
$(NULL)
# Standard Mozilla make rules

Просмотреть файл

@ -0,0 +1,60 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Peter Van der Beken.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@propagandism.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "txIFunctionEvaluationContext.idl"
[scriptable, uuid(cc846954-69a0-11d9-9791-000a95dc234c)]
interface nsIXFormsXPathFunctions : nsISupports
{
double avg(in txINodeSet aNodeSet);
boolean booleanFromString(in DOMString aString);
double countNonEmpty(in txINodeSet aNodeSet);
double daysFromDate(in DOMString aDateTime);
DOMString if(in boolean aValue, in DOMString aIfString, in DOMString aElseString);
double index(in txIFunctionEvaluationContext aContext, in DOMString aId);
txINodeSet instance(in txIFunctionEvaluationContext aContext, in DOMString aString);
double max(in txINodeSet aNodeSet);
double min(in txINodeSet aNodeSet);
double months(in DOMString aDuration);
DOMString now();
DOMString property(in DOMString aProperty);
double seconds(in DOMString aDuration);
double secondsFromDateTime(in DOMString aDateTime);
};

Просмотреть файл

@ -380,14 +380,16 @@ nsXFormsMDGEngine::Recalculate(nsCOMArray<nsIDOMNode> *aChangedNodes)
switch (g->mType) {
case eModel_calculate:
if (g->HasExpr()) {
nsCOMPtr<nsIDOMXPathResult> xpath_res;
nsCOMPtr<nsISupports> result;
rv = g->mExpression->EvaluateWithContext(g->mContextNode,
g->mContextPosition,
g->mContextSize,
nsIDOMXPathResult::STRING_TYPE,
nsnull,
getter_AddRefs(xpath_res));
getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMXPathResult> xpath_res = do_QueryInterface(result);
NS_ENSURE_STATE(xpath_res);
nsAutoString nodeval;
@ -1039,7 +1041,7 @@ nsXFormsMDGEngine::BooleanExpression(nsXFormsMDGNode* aNode, PRBool& state)
NS_ENSURE_ARG_POINTER(aNode);
NS_ENSURE_TRUE(aNode->mExpression, NS_ERROR_FAILURE);
nsISupports* retval;
nsCOMPtr<nsISupports> retval;
nsresult rv;
rv = aNode->mExpression->EvaluateWithContext(aNode->mContextNode,
@ -1047,7 +1049,7 @@ nsXFormsMDGEngine::BooleanExpression(nsXFormsMDGNode* aNode, PRBool& state)
aNode->mContextSize,
nsIDOMXPathResult::BOOLEAN_TYPE,
nsnull,
&retval);
getter_AddRefs(retval));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMXPathResult> xpath_res = do_QueryInterface(retval);

Просмотреть файл

@ -55,7 +55,9 @@
#include "nsIDOMXMLDocument.h"
#include "nsIDOMEventReceiver.h"
#include "nsIDOMXPathResult.h"
#include "nsIXFormsXPathEvaluator.h"
#include "nsIDOMXPathEvaluator.h"
#include "nsIXPathEvaluatorInternal.h"
#include "nsIDOMXPathExpression.h"
#include "nsIDOMXPathNSResolver.h"
#include "nsIDOMNSXPathExpression.h"
#include "nsIContent.h"
@ -1983,10 +1985,10 @@ nsXFormsModelElement::ProcessBindElements()
firstInstanceDoc->GetDocumentElement(getter_AddRefs(firstInstanceRoot));
nsresult rv;
nsCOMPtr<nsIXFormsXPathEvaluator> xpath =
do_CreateInstance("@mozilla.org/dom/xforms-xpath-evaluator;1", &rv);
NS_ENSURE_TRUE(xpath, rv);
nsCOMPtr<nsIDOMXPathEvaluator> xpath = do_QueryInterface(firstInstanceDoc,
&rv);
NS_ENSURE_TRUE(rv, rv);
nsCOMPtr<nsIDOMNodeList> children;
mElement->GetChildNodes(getter_AddRefs(children));
@ -2266,19 +2268,26 @@ nsXFormsModelElement::MaybeNotifyCompletion()
}
nsresult
nsXFormsModelElement::ProcessBind(nsIXFormsXPathEvaluator *aEvaluator,
nsIDOMNode *aContextNode,
PRInt32 aContextPosition,
PRInt32 aContextSize,
nsIDOMElement *aBindElement,
PRBool aIsOuter)
nsXFormsModelElement::ProcessBind(nsIDOMXPathEvaluator *aEvaluator,
nsIDOMNode *aContextNode,
PRInt32 aContextPosition,
PRInt32 aContextSize,
nsIDOMElement *aBindElement,
PRBool aIsOuter)
{
// Get the model item properties specified by this \<bind\>.
nsCOMPtr<nsIDOMNSXPathExpression> props[eModel__count];
nsCOMPtr<nsIDOMXPathExpression> props[eModel__count];
nsAutoString propStrings[eModel__count];
nsresult rv;
nsAutoString attrStr;
nsCOMPtr<nsIDOMXPathNSResolver> resolver;
nsresult rv = aEvaluator->CreateNSResolver(aBindElement,
getter_AddRefs(resolver));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXPathEvaluatorInternal> eval = do_QueryInterface(aEvaluator, &rv);
NS_ENSURE_SUCCESS(rv, rv);
for (PRUint32 i = 0; i < eModel__count; ++i) {
sModelPropsList[i]->ToString(attrStr);
@ -2286,8 +2295,9 @@ nsXFormsModelElement::ProcessBind(nsIXFormsXPathEvaluator *aEvaluator,
if (!propStrings[i].IsEmpty() &&
i != eModel_type &&
i != eModel_p3ptype) {
rv = aEvaluator->CreateExpression(propStrings[i], aBindElement,
getter_AddRefs(props[i]));
rv = nsXFormsUtils::CreateExpression(eval, propStrings[i], resolver,
aBindElement,
getter_AddRefs(props[i]));
if (NS_FAILED(rv)) {
const PRUnichar *strings[] = { propStrings[i].get() };
nsXFormsUtils::ReportError(NS_LITERAL_STRING("mipParseError"),
@ -2301,21 +2311,21 @@ nsXFormsModelElement::ProcessBind(nsIXFormsXPathEvaluator *aEvaluator,
// Find the nodeset that this bind applies to.
nsCOMPtr<nsIDOMXPathResult> result;
nsAutoString expr;
aBindElement->GetAttribute(NS_LITERAL_STRING("nodeset"), expr);
if (expr.IsEmpty()) {
expr = NS_LITERAL_STRING(".");
nsAutoString exprString;
aBindElement->GetAttribute(NS_LITERAL_STRING("nodeset"), exprString);
if (exprString.IsEmpty()) {
exprString = NS_LITERAL_STRING(".");
}
rv = aEvaluator->Evaluate(expr, aContextNode, aContextPosition, aContextSize,
aBindElement,
nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
nsnull, getter_AddRefs(result));
rv = nsXFormsUtils::EvaluateXPath(eval, exprString, aContextNode, resolver,
aBindElement,
nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
aContextPosition, aContextSize,
nsnull, getter_AddRefs(result));
if (NS_FAILED(rv)) {
if (rv == NS_ERROR_DOM_INVALID_EXPRESSION_ERR) {
// the xpath expression isn't valid xpath
const nsPromiseFlatString& flat = PromiseFlatString(expr);
const PRUnichar *strings[] = { flat.get() };
const PRUnichar *strings[] = { exprString.get() };
nsXFormsUtils::ReportError(NS_LITERAL_STRING("exprParseError"),
strings, 1, aBindElement, nsnull);
nsXFormsUtils::DispatchEvent(mElement, eEvent_ComputeException);
@ -2323,7 +2333,7 @@ nsXFormsModelElement::ProcessBind(nsIXFormsXPathEvaluator *aEvaluator,
#ifdef DEBUG
printf("xforms-binding-exception: XPath Evaluation failed\n");
#endif
const PRUnichar *strings[] = { expr.get() };
const PRUnichar *strings[] = { exprString.get() };
nsXFormsUtils::ReportError(NS_LITERAL_STRING("nodesetEvaluateError"),
strings, 1, aBindElement, aBindElement);
nsXFormsUtils::DispatchEvent(mElement, eEvent_BindingException);
@ -2367,7 +2377,7 @@ nsXFormsModelElement::ProcessBind(nsIXFormsXPathEvaluator *aEvaluator,
// Apply MIPs
nsXFormsXPathParser parser;
nsXFormsXPathAnalyzer analyzer(aEvaluator, aBindElement);
nsXFormsXPathAnalyzer analyzer(eval, resolver, aBindElement);
PRBool multiMIP = PR_FALSE;
for (PRUint32 j = 0; j < eModel__count; ++j) {
if (propStrings[j].IsEmpty())
@ -2402,7 +2412,7 @@ nsXFormsModelElement::ProcessBind(nsIXFormsXPathEvaluator *aEvaluator,
}
} else {
// the rest of the MIPs are given to the MDG
nsCOMPtr<nsIDOMNSXPathExpression> expr = props[j];
nsCOMPtr<nsIDOMNSXPathExpression> expr = do_QueryInterface(props[j]);
// Get node dependencies
nsAutoPtr<nsXFormsXPathNode> xNode(parser.Parse(propStrings[j]));

Просмотреть файл

@ -60,7 +60,7 @@
class nsIDOMElement;
class nsIDOMNode;
class nsIXFormsXPathEvaluator;
class nsIDOMXPathEvaluator;
class nsIDOMXPathResult;
class nsXFormsControl;
class nsXFormsModelInstanceDocuments;
@ -310,12 +310,12 @@ private:
NS_HIDDEN_(nsresult) ConstructDone();
NS_HIDDEN_(void) MaybeNotifyCompletion();
NS_HIDDEN_(nsresult) ProcessBind(nsIXFormsXPathEvaluator *aEvaluator,
nsIDOMNode *aContextNode,
PRInt32 aContextPosition,
PRInt32 aContextSize,
nsIDOMElement *aBindElement,
PRBool aIsOuter = PR_FALSE);
NS_HIDDEN_(nsresult) ProcessBind(nsIDOMXPathEvaluator *aEvaluator,
nsIDOMNode *aContextNode,
PRInt32 aContextPosition,
PRInt32 aContextSize,
nsIDOMElement *aBindElement,
PRBool aIsOuter = PR_FALSE);
NS_HIDDEN_(void) RemoveModelFromDocument();

Просмотреть файл

@ -44,6 +44,8 @@
#include "nsXFormsUtils.h"
#include "nsICategoryManager.h"
#include "nsIServiceManager.h"
#include "nsIClassInfoImpl.h"
#include "nsXFormsXPathFunctions.h"
// bb0d9c8b-3096-4b66-92a0-6c1ddf80e65f
#define NS_XFORMSUTILITYSERVICE_CID \
@ -52,9 +54,15 @@
#define NS_XFORMSUTILITYSERVICE_CONTRACTID \
"@mozilla.org/xforms-utility-service;1"
#define XFORMSXPATHFUNCTIONS_CID \
{ 0x8edc8cf1, 0x69a3, 0x11d9, { 0x97, 0x91, 0x00, 0x0a, 0x95, 0xdc, 0x23, 0x4c } }
#define XFORMSXPATHFUNCTIONS_CONTRACTID \
"@mozilla.org/xforms-xpath-functions;1"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsXFormsElementFactory)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsXFormsUtilityService)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsXFormsXPathFunctions)
NS_DECL_CLASSINFO(nsXFormsXPathFunctions)
static NS_IMETHODIMP
RegisterXFormsModule(nsIComponentManager *aCompMgr,
@ -132,6 +140,15 @@ static const nsModuleComponentInfo components[] = {
NS_XFORMSUTILITYSERVICE_CID,
NS_XFORMSUTILITYSERVICE_CONTRACTID,
nsXFormsUtilityServiceConstructor
},
{ "XForms XPath extension functions",
XFORMSXPATHFUNCTIONS_CID,
XFORMSXPATHFUNCTIONS_CONTRACTID,
nsXFormsXPathFunctionsConstructor,
nsnull, nsnull, nsnull,
NS_CI_INTERFACE_GETTER_NAME(nsXFormsXPathFunctions),
nsnull,
&NS_CLASSINFO_NAME(nsXFormsXPathFunctions)
}
};

Просмотреть файл

@ -36,389 +36,6 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsIServiceManager.h"
#include "nsXFormsUtilityService.h"
#include "nsXFormsUtils.h"
#include "nsIXTFElement.h"
#include "nsIDOMNode.h"
#include "nsIDOMElement.h"
#include "nsString.h"
#include "nsIDOMDocument.h"
#include "nsIXFormsModelElement.h"
#include "nsIDOMNodeList.h"
#include "nsIInstanceElementPrivate.h"
#include "nsIXFormsRepeatElement.h"
#include "nsISchemaValidator.h"
#include "nsISchemaDuration.h"
#include "nsXFormsSchemaValidator.h"
#include "prdtoa.h"
NS_IMPL_ISUPPORTS1(nsXFormsUtilityService, nsIXFormsUtilityService)
/* I don't know why Doron didn't put this in the .idl so that it could be added
* to the generated .h file. Put it here for now
*/
#define NS_SCHEMAVALIDATOR_CONTRACTID "@mozilla.org/schemavalidator;1"
NS_IMETHODIMP
nsXFormsUtilityService::GetModelFromNode(nsIDOMNode *aNode,
nsIDOMNode **aModel)
{
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
NS_ASSERTION(aModel, "no return buffer, we'll crash soon");
*aModel = nsnull;
nsAutoString namespaceURI;
aNode->GetNamespaceURI(namespaceURI);
// If the node is in the XForms namespace and XTF based, then it should
// be able to be handled by GetModel. Otherwise it is probably an instance
// node in a instance document.
if (!namespaceURI.EqualsLiteral(NS_NAMESPACE_XFORMS)) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIModelElementPrivate> modelPriv = nsXFormsUtils::GetModel(element);
nsCOMPtr<nsIDOMNode> modelElement = do_QueryInterface(modelPriv);
if( modelElement ) {
NS_IF_ADDREF(*aModel = modelElement);
}
// No model found
NS_ENSURE_TRUE(*aModel, NS_ERROR_FAILURE);
return NS_OK;
}
/**
* Function to see if the given node is associated with the given model.
* Right now this function is only called by XPath in the case of the
* instance() function.
* The provided node can be an instance node from an instance
* document and thus be associated to the model in that way (model elements
* contain instance elements). Otherwise the node will be an XForms element
* that was used as the context node of the XPath expression (i.e the
* XForms control has an attribute that contains an XPath expression).
* Form controls are associated with model elements either explicitly through
* single-node binding or implicitly (if model cannot by calculated, it
* will use the first model element encountered in the document). The model
* can also be inherited from a containing element like xforms:group or
* xforms:repeat.
*/
NS_IMETHODIMP
nsXFormsUtilityService::IsNodeAssocWithModel( nsIDOMNode *aNode,
nsIDOMNode *aModel,
PRBool *aModelAssocWithNode)
{
nsCOMPtr<nsIDOMNode> modelNode;
nsAutoString namespaceURI;
aNode->GetNamespaceURI(namespaceURI);
// If the node is in the XForms namespace and XTF based, then it should
// be able to be handled by GetModel. Otherwise it is probably an instance
// node in a instance document.
if (namespaceURI.EqualsLiteral(NS_NAMESPACE_XFORMS)) {
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
nsCOMPtr<nsIModelElementPrivate> modelPriv = nsXFormsUtils::GetModel(element);
modelNode = do_QueryInterface(modelPriv);
} else {
// We are assuming that if the node coming in isn't a proper XForms element,
// then it is an instance element in an instance doc. Now we just have
// to determine if the given model contains this instance document.
nsCOMPtr<nsIDOMNode> instNode;
nsresult rv =
nsXFormsUtils::GetInstanceNodeForData(aNode, getter_AddRefs(instNode));
if (NS_SUCCEEDED(rv) && instNode) {
instNode->GetParentNode(getter_AddRefs(modelNode));
}
}
if (modelNode && (modelNode == aModel)) {
*aModelAssocWithNode = PR_TRUE;
} else {
*aModelAssocWithNode = PR_FALSE;
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsUtilityService::GetInstanceDocumentRoot(const nsAString& aID,
nsIDOMNode *aModelNode,
nsIDOMNode **aInstanceRoot)
{
nsresult rv = NS_ERROR_FAILURE;
NS_ASSERTION(aInstanceRoot, "no return buffer, we'll crash soon");
*aInstanceRoot = nsnull;
if (aID.IsEmpty()) {
return rv;
}
nsCOMPtr<nsIXFormsModelElement> modelElement = do_QueryInterface(aModelNode);
nsCOMPtr<nsIDOMDocument> doc;
rv = modelElement->GetInstanceDocument(aID, getter_AddRefs(doc));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMElement> element;
rv = doc->GetDocumentElement(getter_AddRefs(element));
NS_ENSURE_SUCCESS(rv, rv);
if (element) {
NS_IF_ADDREF(*aInstanceRoot = element);
}
return rv;
}
/* Gotta do this via the service since we don't want transformiix to require
* any of the new extensions, like schema-validation
*/
NS_IMETHODIMP
nsXFormsUtilityService::ValidateString(const nsAString & aValue,
const nsAString & aType,
const nsAString & aNamespace,
PRBool *aResult)
{
NS_ASSERTION(aResult, "no return buffer for result so we'll crash soon");
*aResult = PR_FALSE;
nsXFormsSchemaValidator *validator = new nsXFormsSchemaValidator();
if (validator) {
*aResult = validator->ValidateString(aValue, aType, aNamespace);
delete validator;
}
return *aResult ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsXFormsUtilityService::GetRepeatIndex(nsIDOMNode *aRepeat, PRInt32 *aIndex)
{
NS_ASSERTION(aIndex, "no return buffer for index, we'll crash soon");
*aIndex = 0;
nsCOMPtr<nsIXFormsRepeatElement> repeatEle = do_QueryInterface(aRepeat);
if (!repeatEle) {
// if aRepeat isn't a repeat element, then setting aIndex to -1 to tell
// XPath to return NaN. Per 7.8.5 in the spec (1.0, 2nd edition)
*aIndex = -1;
} else {
PRUint32 retIndex = 0;
nsresult rv = repeatEle->GetIndex(&retIndex);
NS_ENSURE_SUCCESS(rv, rv);
*aIndex = retIndex;
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsUtilityService::GetMonths(const nsAString & aValue,
PRInt32 * aMonths)
{
NS_ASSERTION(aMonths, "no return buffer for months, we'll crash soon");
*aMonths = 0;
nsCOMPtr<nsISchemaDuration> duration;
nsCOMPtr<nsISchemaValidator> schemaValidator =
do_CreateInstance(NS_SCHEMAVALIDATOR_CONTRACTID);
NS_ENSURE_TRUE(schemaValidator, NS_ERROR_FAILURE);
nsresult rv = schemaValidator->ValidateBuiltinTypeDuration(aValue,
getter_AddRefs(duration));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 sumMonths;
PRUint32 years;
PRUint32 months;
duration->GetYears(&years);
duration->GetMonths(&months);
sumMonths = months + years*12;
PRBool negative;
duration->GetNegative(&negative);
if (negative) {
// according to the spec, "the sign of the result will match the sign
// of the duration"
sumMonths *= -1;
}
*aMonths = sumMonths;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsUtilityService::GetSeconds(const nsAString & aValue,
double * aSeconds)
{
nsCOMPtr<nsISchemaDuration> duration;
nsCOMPtr<nsISchemaValidator> schemaValidator =
do_CreateInstance(NS_SCHEMAVALIDATOR_CONTRACTID);
NS_ENSURE_TRUE(schemaValidator, NS_ERROR_FAILURE);
nsresult rv = schemaValidator->ValidateBuiltinTypeDuration(aValue,
getter_AddRefs(duration));
NS_ENSURE_SUCCESS(rv, rv);
double sumSeconds;
PRUint32 days;
PRUint32 hours;
PRUint32 minutes;
PRUint32 seconds;
double fractSecs;
duration->GetDays(&days);
duration->GetHours(&hours);
duration->GetMinutes(&minutes);
duration->GetSeconds(&seconds);
duration->GetFractionSeconds(&fractSecs);
sumSeconds = seconds + minutes*60 + hours*3600 + days*24*3600 + fractSecs;
PRBool negative;
duration->GetNegative(&negative);
if (negative) {
// according to the spec, "the sign of the result will match the sign
// of the duration"
sumSeconds *= -1;
}
*aSeconds = sumSeconds;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsUtilityService::GetSecondsFromDateTime(const nsAString & aValue,
double * aSeconds)
{
PRTime dateTime;
nsCOMPtr<nsISchemaValidator> schemaValidator =
do_CreateInstance(NS_SCHEMAVALIDATOR_CONTRACTID);
NS_ENSURE_TRUE(schemaValidator, NS_ERROR_FAILURE);
nsresult rv = schemaValidator->ValidateBuiltinTypeDateTime(aValue, &dateTime);
NS_ENSURE_SUCCESS(rv, rv);
PRTime secs64 = dateTime, remain64;
PRInt64 usecPerSec;
PRInt32 secs32, remain32;
// convert from PRTime (microseconds from epoch) to seconds.
LL_I2L(usecPerSec, PR_USEC_PER_SEC);
LL_MOD(remain64, secs64, usecPerSec); /* remainder after conversion */
LL_DIV(secs64, secs64, usecPerSec); /* Conversion in whole seconds */
// convert whole seconds and remainder to PRInt32
LL_L2I(secs32, secs64);
LL_L2I(remain32, remain64);
// ready the result to send back to transformiix land now in case there are
// no fractional seconds or we end up having a problem parsing them out. If
// we do, we'll just ignore the fractional seconds.
double totalSeconds = secs32;
*aSeconds = totalSeconds;
// We're not getting fractional seconds back in the PRTime we get from
// the schemaValidator. We'll have to figure out the fractions from
// the original value. Since ValidateBuiltinTypeDateTime returned
// successful for us to get this far, we know that the value is in
// the proper format.
int findFractionalSeconds = aValue.FindChar('.');
if (findFractionalSeconds < 0) {
// no fractions of seconds, so we are good to go as we are
return NS_OK;
}
const nsAString& fraction = Substring(aValue, findFractionalSeconds+1,
aValue.Length());
PRBool done = PR_FALSE;
PRUnichar currentChar;
nsCAutoString fractionResult;
nsAString::const_iterator start, end, buffStart;
fraction.BeginReading(start);
fraction.BeginReading(buffStart);
fraction.EndReading(end);
while ((start != end) && !done) {
currentChar = *start++;
// Time is usually terminated with Z or followed by a time zone
// (i.e. -05:00). Time can also be terminated by the end of the string, so
// test for that as well. All of this specified at:
// http://www.w3.org/TR/xmlschema-2/#dateTime
if ((currentChar == 'Z') || (currentChar == '+') || (currentChar == '-') ||
(start == end)) {
fractionResult.AssignLiteral("0.");
AppendUTF16toUTF8(Substring(buffStart.get(), start.get()-1),
fractionResult);
} else if ((currentChar > '9') || (currentChar < '0')) {
// has to be a numerical character or else abort. This should have been
// caught by the schemavalidator, but it is worth double checking.
done = PR_TRUE;
}
}
if (fractionResult.IsEmpty()) {
// couldn't successfully parse the fractional seconds, so we'll just return
// without them.
return NS_OK;
}
// convert the result string that we have to a double and add it to the total
totalSeconds += PR_strtod(fractionResult.get(), nsnull);
*aSeconds = totalSeconds;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsUtilityService::GetDaysFromDateTime(const nsAString & aValue,
PRInt32 * aDays)
{
NS_ASSERTION(aDays, "no return buffer for days, we'll crash soon");
*aDays = 0;
PRTime date;
nsCOMPtr<nsISchemaValidator> schemaValidator =
do_CreateInstance(NS_SCHEMAVALIDATOR_CONTRACTID);
NS_ENSURE_TRUE(schemaValidator, NS_ERROR_FAILURE);
// aValue could be a xsd:date or a xsd:dateTime. If it is a dateTime, we
// should ignore the hours, minutes, and seconds according to 7.10.2 in
// the spec. So search for such things now. If they are there, strip 'em.
int findTime = aValue.FindChar('T');
nsAutoString dateString;
dateString.Assign(aValue);
if (findTime >= 0) {
dateString.Assign(Substring(dateString, 0, findTime));
}
nsresult rv = schemaValidator->ValidateBuiltinTypeDate(dateString, &date);
NS_ENSURE_SUCCESS(rv, rv);
PRTime secs64 = date;
PRInt64 usecPerSec;
PRInt32 secs32;
// convert from PRTime (microseconds from epoch) to seconds. Shouldn't
// have to worry about remainders since input is a date. Smallest value
// is in whole days.
LL_I2L(usecPerSec, PR_USEC_PER_SEC);
LL_DIV(secs64, secs64, usecPerSec);
// convert whole seconds to PRInt32
LL_L2I(secs32, secs64);
// convert whole seconds to days. 86400 seconds in a day.
*aDays = secs32/86400;
return NS_OK;
}

Просмотреть файл

@ -42,24 +42,4 @@ class nsXFormsUtilityService : public nsIXFormsUtilityService
{
public:
NS_DECL_ISUPPORTS
// nsIXFormsUtilityService
NS_IMETHOD GetModelFromNode(nsIDOMNode *node, nsIDOMNode **aModel);
NS_IMETHOD IsNodeAssocWithModel(nsIDOMNode *aNode, nsIDOMNode *aModel,
PRBool *aModelAssocWithNode);
NS_IMETHOD GetInstanceDocumentRoot(const nsAString& aID,
nsIDOMNode *aModelNode,
nsIDOMNode **aInstanceRoot);
NS_IMETHOD ValidateString(const nsAString& aValue, const nsAString & aType,
const nsAString& aNamespace, PRBool *aResult);
NS_IMETHOD GetRepeatIndex(nsIDOMNode *aRepeat, PRInt32 *aIndex);
NS_IMETHOD GetMonths(const nsAString& aValue, PRInt32 *aMonths);
NS_IMETHOD GetSeconds(const nsAString& aValue, double *aSeconds);
NS_IMETHOD GetSecondsFromDateTime(const nsAString& aValue, double *aSeconds);
NS_IMETHOD GetDaysFromDateTime(const nsAString& aValue, PRInt32 *aDays);
};

Просмотреть файл

@ -45,9 +45,11 @@
#include "nsIDocument.h"
#include "nsINameSpaceManager.h"
#include "nsIDOMNodeList.h"
#include "nsIXFormsXPathEvaluator.h"
#include "nsIDOMXPathEvaluator.h"
#include "nsIDOMXPathExpression.h"
#include "nsIDOMXPathResult.h"
#include "nsIDOMXPathNSResolver.h"
#include "nsIXPathEvaluatorInternal.h"
#include "nsIDOMDocument.h"
#include "nsIDOMText.h"
#include "nsIModelElementPrivate.h"
@ -79,16 +81,20 @@
#include "nsIScriptSecurityManager.h"
#include "nsIPermissionManager.h"
#include "nsServiceManagerUtils.h"
#include "nsIXFormsUtilityService.h"
#include "nsIDOMAttr.h"
#include "nsIDOM3Node.h"
#include "nsIConsoleService.h"
#include "nsIStringBundle.h"
#include "nsIXFormsRepeatElement.h"
#include "nsIDOMNSEvent.h"
#include "nsIURI.h"
#include "nsIPrivateDOMEvent.h"
#include "nsIDOMNamedNodeMap.h"
#include "nsIParserService.h"
#include "nsISchemaValidator.h"
#include "nsISchemaDuration.h"
#include "nsXFormsSchemaValidator.h"
#include "prdtoa.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
@ -418,6 +424,26 @@ nsXFormsUtils::GetModel(nsIDOMElement *aElement,
return result;
}
/* static */ nsresult
nsXFormsUtils::CreateExpression(nsIXPathEvaluatorInternal *aEvaluator,
const nsAString &aExpression,
nsIDOMXPathNSResolver *aResolver,
nsISupports *aState,
nsIDOMXPathExpression **aResult)
{
nsStringArray ns;
nsCStringArray contractid;
nsCOMArray<nsISupports> state;
ns.AppendString(EmptyString());
contractid.AppendCString(NS_LITERAL_CSTRING("@mozilla.org/xforms-xpath-functions;1"));
state.AppendObject(aState);
nsCOMPtr<nsIDOMXPathExpression> expression;
return aEvaluator->CreateExpression(aExpression, aResolver, &ns, &contractid,
&state, aResult);
}
/* static */ nsresult
nsXFormsUtils::EvaluateXPath(const nsAString &aExpression,
nsIDOMNode *aContextNode,
@ -432,13 +458,21 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression,
NS_ENSURE_ARG_POINTER(aResult);
*aResult = nsnull;
nsCOMPtr<nsIXFormsXPathEvaluator> eval =
do_CreateInstance("@mozilla.org/dom/xforms-xpath-evaluator;1");
NS_ENSURE_STATE(eval);
nsCOMPtr<nsIDOMDocument> doc;
aContextNode->GetOwnerDocument(getter_AddRefs(doc));
nsCOMPtr<nsIDOMXPathEvaluator> eval = do_QueryInterface(doc);
nsCOMPtr<nsIXPathEvaluatorInternal> evalInternal = do_QueryInterface(eval);
NS_ENSURE_STATE(eval && evalInternal);
nsCOMPtr<nsIDOMXPathNSResolver> resolver;
nsresult rv = eval->CreateNSResolver(aResolverNode, getter_AddRefs(resolver));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMXPathExpression> expression;
rv = CreateExpression(evalInternal, aExpression, resolver, aResolverNode,
getter_AddRefs(expression));
nsCOMPtr<nsIDOMNSXPathExpression> expression;
nsresult rv = eval->CreateExpression(aExpression, aResolverNode,
getter_AddRefs(expression));
PRBool throwException = PR_FALSE;
if (!expression) {
const nsPromiseFlatString& flat = PromiseFlatString(aExpression);
@ -447,13 +481,17 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression,
strings, 1, aContextNode, nsnull);
throwException = PR_TRUE;
} else {
nsCOMPtr<nsIDOMNSXPathExpression> nsExpr =
do_QueryInterface(expression, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupports> supResult;
rv = expression->EvaluateWithContext(aContextNode,
aContextPosition,
aContextSize,
aResultType,
nsnull,
getter_AddRefs(supResult));
rv = nsExpr->EvaluateWithContext(aContextNode,
aContextPosition,
aContextSize,
aResultType,
nsnull,
getter_AddRefs(supResult));
if (NS_SUCCEEDED(rv) && supResult) {
/// @todo beaufour: This is somewhat "hackish". Hopefully, this will
@ -461,11 +499,11 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression,
/// @see http://bugzilla.mozilla.org/show_bug.cgi?id=265212
if (aSet) {
nsXFormsXPathParser parser;
nsXFormsXPathAnalyzer analyzer(eval, aResolverNode);
nsXFormsXPathAnalyzer analyzer(evalInternal, resolver, aResolverNode);
nsAutoPtr<nsXFormsXPathNode> xNode(parser.Parse(aExpression));
rv = analyzer.Analyze(aContextNode,
xNode,
expression,
nsExpr,
&aExpression,
aSet,
aContextPosition,
@ -481,7 +519,7 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression,
return NS_OK;
}
if (rv == NS_ERROR_XFORMS_CALCUATION_EXCEPTION) {
if (rv == NS_ERROR_XFORMS_CALCULATION_EXCEPTION) {
const nsPromiseFlatString& flat = PromiseFlatString(aExpression);
const PRUnichar *strings[] = { flat.get() };
nsXFormsUtils::ReportError(NS_LITERAL_STRING("exprEvaluateError"),
@ -493,7 +531,8 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression,
// Throw xforms-compute-exception
if (throwException) {
nsCOMPtr<nsIDOMElement> resolverElement = do_QueryInterface(aResolverNode);
nsCOMPtr<nsIModelElementPrivate> modelPriv = nsXFormsUtils::GetModel(resolverElement);
nsCOMPtr<nsIModelElementPrivate> modelPriv =
nsXFormsUtils::GetModel(resolverElement);
nsCOMPtr<nsIDOMNode> model = do_QueryInterface(modelPriv);
DispatchEvent(model, eEvent_ComputeException, nsnull, resolverElement);
}
@ -501,6 +540,36 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression,
return rv;
}
/* static */ nsresult
nsXFormsUtils::EvaluateXPath(nsIXPathEvaluatorInternal *aEvaluator,
const nsAString &aExpression,
nsIDOMNode *aContextNode,
nsIDOMXPathNSResolver *aResolver,
nsISupports *aState,
PRUint16 aResultType,
PRInt32 aContextPosition,
PRInt32 aContextSize,
nsIDOMXPathResult *aInResult,
nsIDOMXPathResult **aResult)
{
nsCOMPtr<nsIDOMXPathExpression> expression;
nsresult rv = CreateExpression(aEvaluator, aExpression, aResolver, aState,
getter_AddRefs(expression));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNSXPathExpression> nsExpression =
do_QueryInterface(expression, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupports> supResult;
rv = nsExpression->EvaluateWithContext(aContextNode, aContextPosition,
aContextSize, aResultType,
aInResult, getter_AddRefs(supResult));
NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(supResult, aResult);
}
/* static */ nsresult
nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement,
PRUint32 aElementFlags,
@ -2233,3 +2302,326 @@ nsXFormsUtils::GetWindowFromDocument(nsIDOMDocument *aDoc,
NS_ADDREF(*aWindow = internal);
return NS_OK;
}
/* static */ nsresult
nsXFormsUtils::GetModelFromNode(nsIDOMNode *aNode, nsIDOMNode **aModel)
{
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
NS_ASSERTION(aModel, "no return buffer, we'll crash soon");
*aModel = nsnull;
nsAutoString namespaceURI;
aNode->GetNamespaceURI(namespaceURI);
// If the node is in the XForms namespace and XTF based, then it should
// be able to be handled by GetModel. Otherwise it is probably an instance
// node in a instance document.
if (!namespaceURI.EqualsLiteral(NS_NAMESPACE_XFORMS)) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIModelElementPrivate> modelPriv = nsXFormsUtils::GetModel(element);
nsCOMPtr<nsIDOMNode> modelElement = do_QueryInterface(modelPriv);
if( modelElement ) {
NS_IF_ADDREF(*aModel = modelElement);
}
// No model found
NS_ENSURE_TRUE(*aModel, NS_ERROR_FAILURE);
return NS_OK;
}
/* static */ PRBool
nsXFormsUtils::IsNodeAssocWithModel(nsIDOMNode *aNode, nsIDOMNode *aModel)
{
nsCOMPtr<nsIDOMNode> modelNode;
nsAutoString namespaceURI;
aNode->GetNamespaceURI(namespaceURI);
// If the node is in the XForms namespace and XTF based, then it should
// be able to be handled by GetModel. Otherwise it is probably an instance
// node in a instance document.
if (namespaceURI.EqualsLiteral(NS_NAMESPACE_XFORMS)) {
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
nsCOMPtr<nsIModelElementPrivate> modelPriv = GetModel(element);
modelNode = do_QueryInterface(modelPriv);
} else {
// We are assuming that if the node coming in isn't a proper XForms element,
// then it is an instance element in an instance doc. Now we just have
// to determine if the given model contains this instance document.
nsCOMPtr<nsIDOMNode> instNode;
nsresult rv =
nsXFormsUtils::GetInstanceNodeForData(aNode, getter_AddRefs(instNode));
if (NS_SUCCEEDED(rv) && instNode) {
instNode->GetParentNode(getter_AddRefs(modelNode));
}
}
return modelNode && (modelNode == aModel);
}
/* static */ nsresult
nsXFormsUtils::GetInstanceDocumentRoot(const nsAString &aID,
nsIDOMNode *aModelNode,
nsIDOMNode **aInstanceRoot)
{
nsresult rv = NS_ERROR_FAILURE;
NS_ASSERTION(aInstanceRoot, "no return buffer, we'll crash soon");
*aInstanceRoot = nsnull;
if (aID.IsEmpty()) {
return rv;
}
nsCOMPtr<nsIXFormsModelElement> modelElement = do_QueryInterface(aModelNode);
nsCOMPtr<nsIDOMDocument> doc;
rv = modelElement->GetInstanceDocument(aID, getter_AddRefs(doc));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMElement> element;
rv = doc->GetDocumentElement(getter_AddRefs(element));
NS_ENSURE_SUCCESS(rv, rv);
NS_IF_ADDREF(*aInstanceRoot = element);
return NS_OK;
}
/* static */ PRBool
nsXFormsUtils::ValidateString(const nsAString &aValue, const nsAString & aType,
const nsAString & aNamespace)
{
nsXFormsSchemaValidator validator;
return validator.ValidateString(aValue, aType, aNamespace);
}
/* static */ nsresult
nsXFormsUtils::GetRepeatIndex(nsIDOMNode *aRepeat, PRInt32 *aIndex)
{
NS_ASSERTION(aIndex, "no return buffer for index, we'll crash soon");
*aIndex = 0;
nsCOMPtr<nsIXFormsRepeatElement> repeatEle = do_QueryInterface(aRepeat);
if (!repeatEle) {
// if aRepeat isn't a repeat element, then setting aIndex to -1 to tell
// XPath to return NaN. Per 7.8.5 in the spec (1.0, 2nd edition)
*aIndex = -1;
} else {
PRUint32 retIndex = 0;
nsresult rv = repeatEle->GetIndex(&retIndex);
NS_ENSURE_SUCCESS(rv, rv);
*aIndex = retIndex;
}
return NS_OK;
}
/* static */ nsresult
nsXFormsUtils::GetMonths(const nsAString & aValue, PRInt32 * aMonths)
{
NS_ASSERTION(aMonths, "no return buffer for months, we'll crash soon");
*aMonths = 0;
nsCOMPtr<nsISchemaDuration> duration;
nsCOMPtr<nsISchemaValidator> schemaValidator =
do_CreateInstance("@mozilla.org/schemavalidator;1");
NS_ENSURE_TRUE(schemaValidator, NS_ERROR_FAILURE);
nsresult rv = schemaValidator->ValidateBuiltinTypeDuration(aValue,
getter_AddRefs(duration));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 sumMonths;
PRUint32 years;
PRUint32 months;
duration->GetYears(&years);
duration->GetMonths(&months);
sumMonths = months + years*12;
PRBool negative;
duration->GetNegative(&negative);
if (negative) {
// according to the spec, "the sign of the result will match the sign
// of the duration"
sumMonths *= -1;
}
*aMonths = sumMonths;
return NS_OK;
}
/* static */ nsresult
nsXFormsUtils::GetSeconds(const nsAString & aValue, double * aSeconds)
{
nsCOMPtr<nsISchemaDuration> duration;
nsCOMPtr<nsISchemaValidator> schemaValidator =
do_CreateInstance("@mozilla.org/schemavalidator;1");
NS_ENSURE_TRUE(schemaValidator, NS_ERROR_FAILURE);
nsresult rv = schemaValidator->ValidateBuiltinTypeDuration(aValue,
getter_AddRefs(duration));
NS_ENSURE_SUCCESS(rv, rv);
double sumSeconds;
PRUint32 days;
PRUint32 hours;
PRUint32 minutes;
PRUint32 seconds;
double fractSecs;
duration->GetDays(&days);
duration->GetHours(&hours);
duration->GetMinutes(&minutes);
duration->GetSeconds(&seconds);
duration->GetFractionSeconds(&fractSecs);
sumSeconds = seconds + minutes*60 + hours*3600 + days*24*3600 + fractSecs;
PRBool negative;
duration->GetNegative(&negative);
if (negative) {
// according to the spec, "the sign of the result will match the sign
// of the duration"
sumSeconds *= -1;
}
*aSeconds = sumSeconds;
return NS_OK;
}
/* static */ nsresult
nsXFormsUtils::GetSecondsFromDateTime(const nsAString & aValue,
double * aSeconds)
{
PRTime dateTime;
nsCOMPtr<nsISchemaValidator> schemaValidator =
do_CreateInstance("@mozilla.org/schemavalidator;1");
NS_ENSURE_TRUE(schemaValidator, NS_ERROR_FAILURE);
nsresult rv = schemaValidator->ValidateBuiltinTypeDateTime(aValue, &dateTime);
NS_ENSURE_SUCCESS(rv, rv);
PRTime secs64 = dateTime, remain64;
PRInt64 usecPerSec;
PRInt32 secs32, remain32;
// convert from PRTime (microseconds from epoch) to seconds.
LL_I2L(usecPerSec, PR_USEC_PER_SEC);
LL_MOD(remain64, secs64, usecPerSec); /* remainder after conversion */
LL_DIV(secs64, secs64, usecPerSec); /* Conversion in whole seconds */
// convert whole seconds and remainder to PRInt32
LL_L2I(secs32, secs64);
LL_L2I(remain32, remain64);
// ready the result to send back to transformiix land now in case there are
// no fractional seconds or we end up having a problem parsing them out. If
// we do, we'll just ignore the fractional seconds.
double totalSeconds = secs32;
*aSeconds = totalSeconds;
// We're not getting fractional seconds back in the PRTime we get from
// the schemaValidator. We'll have to figure out the fractions from
// the original value. Since ValidateBuiltinTypeDateTime returned
// successful for us to get this far, we know that the value is in
// the proper format.
int findFractionalSeconds = aValue.FindChar('.');
if (findFractionalSeconds < 0) {
// no fractions of seconds, so we are good to go as we are
return NS_OK;
}
const nsAString& fraction = Substring(aValue, findFractionalSeconds+1,
aValue.Length());
PRBool done = PR_FALSE;
PRUnichar currentChar;
nsCAutoString fractionResult;
nsAString::const_iterator start, end, buffStart;
fraction.BeginReading(start);
fraction.BeginReading(buffStart);
fraction.EndReading(end);
while ((start != end) && !done) {
currentChar = *start++;
// Time is usually terminated with Z or followed by a time zone
// (i.e. -05:00). Time can also be terminated by the end of the string, so
// test for that as well. All of this specified at:
// http://www.w3.org/TR/xmlschema-2/#dateTime
if ((currentChar == 'Z') || (currentChar == '+') || (currentChar == '-') ||
(start == end)) {
fractionResult.AssignLiteral("0.");
AppendUTF16toUTF8(Substring(buffStart.get(), start.get()-1),
fractionResult);
} else if ((currentChar > '9') || (currentChar < '0')) {
// has to be a numerical character or else abort. This should have been
// caught by the schemavalidator, but it is worth double checking.
done = PR_TRUE;
}
}
if (fractionResult.IsEmpty()) {
// couldn't successfully parse the fractional seconds, so we'll just return
// without them.
return NS_OK;
}
// convert the result string that we have to a double and add it to the total
totalSeconds += PR_strtod(fractionResult.get(), nsnull);
*aSeconds = totalSeconds;
return NS_OK;
}
/* static */ nsresult
nsXFormsUtils::GetDaysFromDateTime(const nsAString & aValue, PRInt32 * aDays)
{
NS_ASSERTION(aDays, "no return buffer for days, we'll crash soon");
*aDays = 0;
PRTime date;
nsCOMPtr<nsISchemaValidator> schemaValidator =
do_CreateInstance("@mozilla.org/schemavalidator;1");
NS_ENSURE_TRUE(schemaValidator, NS_ERROR_FAILURE);
// aValue could be a xsd:date or a xsd:dateTime. If it is a dateTime, we
// should ignore the hours, minutes, and seconds according to 7.10.2 in
// the spec. So search for such things now. If they are there, strip 'em.
PRInt32 findTime = aValue.FindChar('T');
nsAutoString dateString;
dateString.Assign(aValue);
if (findTime >= 0) {
dateString.Assign(Substring(dateString, 0, findTime));
}
nsresult rv = schemaValidator->ValidateBuiltinTypeDate(dateString, &date);
NS_ENSURE_SUCCESS(rv, rv);
PRTime secs64 = date;
PRInt64 usecPerSec;
PRInt32 secs32;
// convert from PRTime (microseconds from epoch) to seconds. Shouldn't
// have to worry about remainders since input is a date. Smallest value
// is in whole days.
LL_I2L(usecPerSec, PR_USEC_PER_SEC);
LL_DIV(secs64, secs64, usecPerSec);
// convert whole seconds to PRInt32
LL_L2I(secs32, secs64);
// convert whole seconds to days. 86400 seconds in a day.
*aDays = secs32/86400;
return NS_OK;
}

Просмотреть файл

@ -57,6 +57,10 @@ class nsIURI;
class nsString;
class nsIMutableArray;
class nsIDOMEvent;
class nsIDOMXPathEvaluator;
class nsIDOMXPathExpression;
class nsIDOMXPathNSResolver;
class nsIXPathEvaluatorInternal;
#define NS_NAMESPACE_XFORMS "http://www.w3.org/2002/xforms"
#define NS_NAMESPACE_XHTML "http://www.w3.org/1999/xhtml"
@ -66,6 +70,9 @@ class nsIDOMEvent;
#define NS_NAMESPACE_SOAP_ENVELOPE "http://schemas.xmlsoap.org/soap/envelope/"
#define NS_NAMESPACE_MOZ_XFORMS_LAZY "http://www.mozilla.org/projects/xforms/2005/lazy"
#define NS_ERROR_XFORMS_CALCULATION_EXCEPTION \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_GENERAL, 3001)
/**
* Error codes
*/
@ -236,7 +243,7 @@ public:
* and returned (addrefed) in |aModel|
*
* The return value is an XPathResult as returned from
* nsIXFormsXPathEvaluator::Evaluate().
* nsIDOMXPathEvaluator::Evaluate().
*/
static NS_HIDDEN_(nsresult)
EvaluateNodeBinding(nsIDOMElement *aElement,
@ -251,10 +258,17 @@ public:
nsCOMArray<nsIDOMNode> *aDeps = nsnull,
nsStringArray *aIndexesUsed = nsnull);
static NS_HIDDEN_(nsresult)
CreateExpression(nsIXPathEvaluatorInternal *aEvaluator,
const nsAString &aExpression,
nsIDOMXPathNSResolver *aResolver,
nsISupports *aState,
nsIDOMXPathExpression **aResult);
/**
* Convenience method for doing XPath evaluations. This gets a
* nsIXFormsXPathEvaluator from |aContextNode|'s ownerDocument, and calls
* nsIXFormsXPathEvaluator::Evalute using the given expression, context node,
* nsIDOMXPathEvaluator from |aContextNode|'s ownerDocument, and calls
* nsIDOMXPathEvaluator::Evaluate using the given expression, context node,
* namespace resolver, and result type.
*/
static NS_HIDDEN_(nsresult)
@ -268,6 +282,18 @@ public:
nsCOMArray<nsIDOMNode> *aSet = nsnull,
nsStringArray *aIndexesUsed = nsnull);
static NS_HIDDEN_(nsresult)
EvaluateXPath(nsIXPathEvaluatorInternal *aEvaluator,
const nsAString &aExpression,
nsIDOMNode *aContextNode,
nsIDOMXPathNSResolver *aResolver,
nsISupports *aState,
PRUint16 aResultType,
PRInt32 aContextPosition,
PRInt32 aContextSize,
nsIDOMXPathResult *aInResult,
nsIDOMXPathResult **aResult);
/**
* Given a node in the instance data, get its string value according
* to section 8.1.1 of the XForms specification.
@ -552,6 +578,63 @@ public:
static NS_HIDDEN_(nsresult) GetWindowFromDocument(nsIDOMDocument *aDoc,
nsIDOMWindowInternal **aWindow);
/**
* Function to get the corresponding model element from a xforms node or
* a xforms instance data node.
*/
static NS_HIDDEN_(nsresult) GetModelFromNode(nsIDOMNode *aNode,
nsIDOMNode **aResult);
/**
* Function to see if the given node is associated with the given model.
* Right now this function is only called by XPath in the case of the
* instance() function.
* The provided node can be an instance node from an instance
* document and thus be associated to the model in that way (model elements
* contain instance elements). Otherwise the node will be an XForms element
* that was used as the context node of the XPath expression (i.e the
* XForms control has an attribute that contains an XPath expression).
* Form controls are associated with model elements either explicitly through
* single-node binding or implicitly (if model cannot by calculated, it
* will use the first model element encountered in the document). The model
* can also be inherited from a containing element like xforms:group or
* xforms:repeat.
*/
static NS_HIDDEN_(PRBool) IsNodeAssocWithModel(nsIDOMNode *aNode,
nsIDOMNode *aModel);
/**
* Function to get the instance document root for the instance element with
* the given id. The instance element must be associated with the given
* model.
*/
static NS_HIDDEN_(nsresult) GetInstanceDocumentRoot(const nsAString &aID,
nsIDOMNode *aModelNode,
nsIDOMNode **aResult);
/**
* Function to ensure that aValue is of the schema type aType. Will basically
* be a forwarder to the nsISchemaValidator function of the same name.
*/
static NS_HIDDEN_(PRBool) ValidateString(const nsAString &aValue,
const nsAString & aType,
const nsAString & aNamespace);
static NS_HIDDEN_(nsresult) GetRepeatIndex(nsIDOMNode *aRepeat,
PRInt32 *aIndex);
static NS_HIDDEN_(nsresult) GetMonths(const nsAString & aValue,
PRInt32 * aMonths);
static NS_HIDDEN_(nsresult) GetSeconds(const nsAString & aValue,
double * aSeconds);
static NS_HIDDEN_(nsresult) GetSecondsFromDateTime(const nsAString & aValue,
double * aSeconds);
static NS_HIDDEN_(nsresult) GetDaysFromDateTime(const nsAString & aValue,
PRInt32 * aDays);
private:
/**
* Do same origin checks on aBaseDocument and aTestURI. Hosts can be

Просмотреть файл

@ -45,9 +45,12 @@
//#define DEBUG_XF_ANALYZER
#endif
nsXFormsXPathAnalyzer::nsXFormsXPathAnalyzer(nsIXFormsXPathEvaluator *aEvaluator,
nsIDOMNode *aResolver)
: mEvaluator(aEvaluator), mResolver(aResolver)
nsXFormsXPathAnalyzer::nsXFormsXPathAnalyzer(nsIXPathEvaluatorInternal *aEvaluator,
nsIDOMXPathNSResolver *aResolver,
nsISupports *aState)
: mEvaluator(aEvaluator),
mResolver(aResolver),
mState(aState)
{
MOZ_COUNT_CTOR(nsXFormsXPathAnalyzer);
}
@ -174,9 +177,10 @@ nsXFormsXPathAnalyzer::AnalyzeRecursively(nsIDOMNode *aContextNode,
xp = Substring(*mCurExprString, aNode->mStartIndex,
aNode->mEndIndex - aNode->mStartIndex);
}
rv = mEvaluator->Evaluate(xp, aContextNode, mCurPosition, mCurSize,
mResolver, nsIDOMXPathResult::ANY_TYPE,
nsnull, getter_AddRefs(result));
rv = nsXFormsUtils::EvaluateXPath(mEvaluator, xp, aContextNode, mResolver,
mState, nsIDOMXPathResult::ANY_TYPE,
mCurPosition, mCurSize, nsnull,
getter_AddRefs(result));
if (NS_FAILED(rv)) {
const PRUnichar *strings[] = { xp.get() };
nsXFormsUtils::ReportError(NS_LITERAL_STRING("exprEvaluateError"),
@ -194,10 +198,13 @@ nsXFormsXPathAnalyzer::AnalyzeRecursively(nsIDOMNode *aContextNode,
nsDependentSubstring indexExpr = Substring(xp,
indexSize,
xp.Length() - indexSize - 1); // remove final ')' too
nsCOMPtr<nsIDOMXPathResult> stringRes;
rv = mEvaluator->Evaluate(indexExpr, aContextNode, mCurPosition, mCurSize,
mResolver, nsIDOMXPathResult::STRING_TYPE,
nsnull, getter_AddRefs(stringRes));
rv = nsXFormsUtils::EvaluateXPath(mEvaluator, indexExpr, aContextNode,
mResolver, mState,
nsIDOMXPathResult::STRING_TYPE,
mCurPosition, mCurSize, nsnull,
getter_AddRefs(stringRes));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString indexId;

Просмотреть файл

@ -42,7 +42,7 @@
#include "nsCOMArray.h"
#include "nsXFormsXPathNode.h"
#include "nsIDOMNSXPathExpression.h"
#include "nsIXFormsXPathEvaluator.h"
#include "nsIXPathEvaluatorInternal.h"
#include "nsIDOMXPathNSResolver.h"
#include "nsIDOMNode.h"
#include "nsCOMPtr.h"
@ -58,8 +58,9 @@
*/
class nsXFormsXPathAnalyzer {
private:
nsCOMPtr<nsIXFormsXPathEvaluator> mEvaluator;
nsCOMPtr<nsIDOMNode> mResolver;
nsCOMPtr<nsIXPathEvaluatorInternal> mEvaluator;
nsCOMPtr<nsIDOMXPathNSResolver> mResolver;
nsCOMPtr<nsISupports> mState;
nsCOMArray<nsIDOMNode> *mCurSet;
nsCOMPtr<nsIDOMNSXPathExpression> mCurExpression;
@ -74,8 +75,9 @@ private:
PRBool aCollect = PR_FALSE);
public:
nsXFormsXPathAnalyzer(nsIXFormsXPathEvaluator *aEvaluator,
nsIDOMNode *aResolver);
nsXFormsXPathAnalyzer(nsIXPathEvaluatorInternal *aEvaluator,
nsIDOMXPathNSResolver *aResolver,
nsISupports *aState);
~nsXFormsXPathAnalyzer();
nsresult Analyze(nsIDOMNode *aContextNode,

Просмотреть файл

@ -0,0 +1,426 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
*
* The Initial Developer of the Original Code is
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Aaron Reed <aaronr@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsXFormsXPathFunctions.h"
#include "nsAutoPtr.h"
#include "nsComponentManagerUtils.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
#include "nsString.h"
#include "nsXFormsUtils.h"
#include "prprf.h"
#include "txDouble.h"
#include "txIFunctionEvaluationContext.h"
#include "txINodeSet.h"
#include "nsIClassInfoImpl.h"
#define NS_NAMESPACE_XFORMS "http://www.w3.org/2002/xforms"
static const PRUint32 nanMask[2] = TX_DOUBLE_NaN;
#define kNaN *((double*)nanMask)
NS_IMPL_ISUPPORTS1_CI(nsXFormsXPathFunctions, nsIXFormsXPathFunctions)
NS_IMETHODIMP
nsXFormsXPathFunctions::Avg(txINodeSet *aNodeSet, double *aResult)
{
PRUint32 length;
nsresult rv = aNodeSet->GetLength(&length);
NS_ENSURE_SUCCESS(rv, rv);
double total = 0;
PRUint32 i;
for (i = 0; i < length; ++i) {
double item;
rv = aNodeSet->ItemAsNumber(i, &item);
NS_ENSURE_SUCCESS(rv, rv);
if (TX_DOUBLE_IS_NaN(item)) {
// This will make aResult be set to kNaN below.
i = 0;
break;
}
total += item;
}
*aResult = (i > 0) ? (total / i) : kNaN;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsXPathFunctions::BooleanFromString(const nsAString & aString,
PRBool *aResult)
{
*aResult = aString.EqualsLiteral("1") ||
aString.LowerCaseEqualsLiteral("true");
return NS_OK;
}
NS_IMETHODIMP
nsXFormsXPathFunctions::CountNonEmpty(txINodeSet *aNodeSet, double *aResult)
{
PRUint32 length;
nsresult rv = aNodeSet->GetLength(&length);
NS_ENSURE_SUCCESS(rv, rv);
double result = 0;
PRUint32 i;
for (i = 0; i < length; ++i) {
nsAutoString item;
rv = aNodeSet->ItemAsString(i, item);
NS_ENSURE_SUCCESS(rv, rv);
if (!item.IsEmpty()) {
++result;
}
}
*aResult = result;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsXPathFunctions::DaysFromDate(const nsAString &aDateTime,
double *aResult)
{
PRInt32 result = 0;
nsresult rv = nsXFormsUtils::GetDaysFromDateTime(aDateTime, &result);
if (rv == NS_ERROR_ILLEGAL_VALUE) {
*aResult = kNaN;
rv = NS_OK;
}
else {
*aResult = result;
}
return rv;
}
NS_IMETHODIMP
nsXFormsXPathFunctions::If(PRBool aValue, const nsAString &aIfString,
const nsAString &aElseString, nsAString &aResult)
{
// XXX Avoid evaluating aIfString and aElseString until after checking
// aValue. Probably needs vararg support.
aResult = aValue ? aIfString : aElseString;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsXPathFunctions::Index(txIFunctionEvaluationContext *aContext,
const nsAString &aID, double *aResult)
{
// Given an element's id as the parameter, need to query the element and
// make sure that it is a xforms:repeat node. Given that, must query
// its index.
nsCOMPtr<nsISupports> state;
aContext->GetState(getter_AddRefs(state));
nsCOMPtr<nsIDOMNode> resolverNode = do_QueryInterface(state);
NS_ENSURE_TRUE(resolverNode, NS_ERROR_FAILURE);
// here document is the XForms document
nsCOMPtr<nsIDOMDocument> document;
resolverNode->GetOwnerDocument(getter_AddRefs(document));
NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
// aID should be the id of a nsIXFormsRepeatElement
nsCOMPtr<nsIDOMElement> repeatEle;
nsresult rv = document->GetElementById(aID, getter_AddRefs(repeatEle));
NS_ENSURE_SUCCESS(rv, rv);
// now get the index value from the xforms:repeat.
PRInt32 index;
rv = nsXFormsUtils::GetRepeatIndex(repeatEle, &index);
NS_ENSURE_SUCCESS(rv, rv);
// repeat's index is 1-based. If it is 0, then that is still ok since
// repeat's index can be 0 if uninitialized or if the nodeset that it
// is bound to is empty (either initially or due to delete remove all
// of the instance nodes). If index == -1, then repeatEle isn't an
// XForms repeat element, so we need to return NaN per spec.
*aResult = index >= 0 ? index : kNaN;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsXPathFunctions::Instance(txIFunctionEvaluationContext *aContext,
const nsAString &aInstanceId,
txINodeSet **aResult)
{
*aResult = nsnull;
// The state is the node in the XForms document that contained
// the expression we are evaluating. We'll use this to get the
// document. If this isn't here, then something is wrong. Bail.
nsCOMPtr<nsISupports> state;
aContext->GetState(getter_AddRefs(state));
nsCOMPtr<nsIDOMNode> resolverNode = do_QueryInterface(state);
NS_ENSURE_TRUE(resolverNode, NS_ERROR_FAILURE);
// here document is the XForms document
nsCOMPtr<nsIDOMDocument> document;
resolverNode->GetOwnerDocument(getter_AddRefs(document));
NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMElement> instEle;
nsresult rv = document->GetElementById(aInstanceId,
getter_AddRefs(instEle));
NS_ENSURE_SUCCESS(rv, rv);
PRBool foundInstance = PR_FALSE;
if (instEle) {
nsAutoString localname, namespaceURI;
instEle->GetLocalName(localname);
instEle->GetNamespaceURI(namespaceURI);
foundInstance = localname.EqualsLiteral("instance") &&
namespaceURI.EqualsLiteral(NS_NAMESPACE_XFORMS);
}
nsCOMPtr<txINodeSet> result =
do_CreateInstance("@mozilla.org/transformiix-nodeset;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
if (!foundInstance) {
// We didn't find an instance element with the given id. Return the
// empty result set.
result.swap(*aResult);
return NS_OK;
}
// Make sure that this element is contained in the same
// model as the context node of the expression as per
// the XForms 1.0 spec.
// first step is to get the contextNode passed in to
// the evaluation
nsCOMPtr<nsIDOMNode> xfContextNode;
rv = aContext->GetContextNode(getter_AddRefs(xfContextNode));
NS_ENSURE_SUCCESS(rv, rv);
// now see if the node we found (instEle) and the
// context node for the evaluation (xfContextNode) link
// back to the same model.
nsCOMPtr<nsIDOMNode> instNode, modelInstance;
instNode = do_QueryInterface(instEle);
rv = nsXFormsUtils::GetModelFromNode(instNode,
getter_AddRefs(modelInstance));
NS_ENSURE_SUCCESS(rv, rv);
PRBool modelContainsNode =
nsXFormsUtils::IsNodeAssocWithModel(xfContextNode, modelInstance);
if (modelContainsNode) {
// ok, we've found an instance node with the proper id
// that fulfills the requirement of being from the
// same model as the context node. Now we need to
// return a 'node-set containing just the root
// element node of the referenced instance data'.
// Wonderful.
nsCOMPtr<nsIDOMNode> root;
rv = nsXFormsUtils::GetInstanceDocumentRoot(aInstanceId,
modelInstance,
getter_AddRefs(root));
NS_ENSURE_SUCCESS(rv, rv);
if (root) {
result->Add(root);
}
result.swap(*aResult);
return NS_OK;
}
// XXX where we need to do the work
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXFormsXPathFunctions::Max(txINodeSet *aNodeSet, double *aResult)
{
PRUint32 length;
nsresult rv = aNodeSet->GetLength(&length);
NS_ENSURE_SUCCESS(rv, rv);
double result = kNaN;
PRUint32 i;
for (i = 0; i < length; ++i) {
double item;
rv = aNodeSet->ItemAsNumber(i, &item);
NS_ENSURE_SUCCESS(rv, rv);
if (!TX_DOUBLE_COMPARE(item, <=, result)) {
result = item;
}
if (TX_DOUBLE_IS_NaN(result)) {
break;
}
}
*aResult = result;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsXPathFunctions::Min(txINodeSet *aNodeSet, double *aResult)
{
PRUint32 length;
nsresult rv = aNodeSet->GetLength(&length);
NS_ENSURE_SUCCESS(rv, rv);
double result = kNaN;
PRUint32 i;
for (i = 0; i < length; ++i) {
double item;
rv = aNodeSet->ItemAsNumber(i, &item);
NS_ENSURE_SUCCESS(rv, rv);
if (!TX_DOUBLE_COMPARE(item, >=, result)) {
result = item;
}
if (TX_DOUBLE_IS_NaN(result)) {
break;
}
}
*aResult = result;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsXPathFunctions::Months(const nsAString & aDuration, double *aResult)
{
PRInt32 result = 0;
nsresult rv = nsXFormsUtils::GetMonths(aDuration, &result);
if (rv == NS_ERROR_ILLEGAL_VALUE) {
*aResult = kNaN;
return NS_OK;
}
*aResult = result;
return rv;
}
NS_IMETHODIMP
nsXFormsXPathFunctions::Now(nsAString & aResult)
{
PRExplodedTime time;
char ctime[60];
PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &time);
int gmtoffsethour = time.tm_params.tp_gmt_offset < 0 ?
-1*time.tm_params.tp_gmt_offset / 3600 :
time.tm_params.tp_gmt_offset / 3600;
int remainder = time.tm_params.tp_gmt_offset%3600;
int gmtoffsetminute = remainder ? remainder/60 : 00;
char zone_location[40];
const int zoneBufSize = sizeof(zone_location);
PR_snprintf(zone_location, zoneBufSize, "%c%02d:%02d\0",
time.tm_params.tp_gmt_offset < 0 ? '-' : '+',
gmtoffsethour, gmtoffsetminute);
PR_FormatTime(ctime, sizeof(ctime), "%Y-%m-%dT%H:%M:%S\0", &time);
aResult.AssignASCII(ctime);
AppendASCIItoUTF16(zone_location, aResult);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsXPathFunctions::Property(const nsAString &aProperty,
nsAString &aResult)
{
// This function can handle "version" and "conformance-level"
// which is all that the XForms 1.0 spec is worried about
if (aProperty.EqualsLiteral("version")) {
aResult.AssignLiteral("1.0");
}
else if (aProperty.EqualsLiteral("conformance-level")) {
aResult.AssignLiteral("basic");
}
else {
aResult.Truncate();
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsXPathFunctions::Seconds(const nsAString &aDuration, double *aResult)
{
nsresult rv = nsXFormsUtils::GetSeconds(aDuration, aResult);
if (rv == NS_ERROR_ILLEGAL_VALUE) {
*aResult = kNaN;
rv = NS_OK;
}
return rv;
}
NS_IMETHODIMP
nsXFormsXPathFunctions::SecondsFromDateTime(const nsAString &aDateTime,
double *aResult)
{
nsresult rv = nsXFormsUtils::GetSecondsFromDateTime(aDateTime, aResult);
if (rv == NS_ERROR_ILLEGAL_VALUE) {
*aResult = kNaN;
rv = NS_OK;
}
return rv;
}

Просмотреть файл

@ -36,49 +36,11 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef TRANSFRMX_XFORMS_FUNCTIONS_H
#define TRANSFRMX_XFORMS_FUNCTIONS_H
#include "txExpr.h"
#include "nsIDOMNode.h"
#define NS_NAMESPACE_XFORMS "http://www.w3.org/2002/xforms"
#define NS_NAMESPACE_SCHEMA "http://www.w3.org/1999/XMLSchema"
/*
* Represents the XPath XForms Function Calls
*/
class XFormsFunctionCall : public FunctionCall {
#include "nsIXFormsXPathFunctions.h"
class nsXFormsXPathFunctions : public nsIXFormsXPathFunctions
{
public:
enum XFormsFunctions {
AVG, // avg()
BOOLEANFROMSTRING, // boolean-from-string()
COUNTNONEMPTY, // count-non-empty()
DAYSFROMDATE, // days-from-date()
IF, // if()
INDEX, // index()
INSTANCE, // instance()
MAX, // max()
MIN, // min()
MONTHS, // months()
NOW, // now()
PROPERTY, // property()
SECONDS, // seconds()
SECONDSFROMDATETIME // seconds-from-dateTime()
};
/*
* Creates a Number function of the given type
*/
XFormsFunctionCall(XFormsFunctions aType, nsIDOMNode *resolverNode=nsnull);
TX_DECL_FUNCTION;
private:
XFormsFunctions mType;
nsCOMPtr<nsIDOMNode> mResolverNode;
NS_DECL_ISUPPORTS
NS_DECL_NSIXFORMSXPATHFUNCTIONS
};
#endif

Просмотреть файл

@ -108,10 +108,9 @@
// Transformiix stuff
#include "nsXPathEvaluator.h"
#include "txMozillaXSLTProcessor.h"
#include "txNodeSetAdaptor.h"
#include "txXSLTProcessor.h"
#include "nsXPath1Scheme.h"
#include "nsXFormsXPathEvaluator.h"
#include "txXSLTProcessor.h"
#include "nsDOMParser.h"
#include "nsDOMSerializer.h"
@ -200,12 +199,19 @@ static void Shutdown();
#define TRANSFORMIIX_XPATH1_SCHEME_CID \
{ 0xc351177, 0x159, 0x4500, { 0x86, 0xb0, 0xa2, 0x19, 0xdf, 0xde, 0x42, 0x58 } }
/* 5d5d92cd-6bf8-11d9-bf4a-000a95dc234c */
#define TRANSFORMIIX_NODESET_CID \
{ 0x5d5d92cd, 0x6bf8, 0x11d9, { 0xbf, 0x4a, 0x0, 0x0a, 0x95, 0xdc, 0x23, 0x4c } }
#define TRANSFORMIIX_NODESET_CONTRACTID \
"@mozilla.org/transformiix-nodeset;1"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsXPath1SchemeProcessor)
// Factory Constructor
NS_GENERIC_FACTORY_CONSTRUCTOR(txMozillaXSLTProcessor)
NS_GENERIC_AGGREGATED_CONSTRUCTOR_INIT(nsXPathEvaluator, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsXFormsXPathEvaluator)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(txNodeSetAdaptor, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMSerializer)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsXMLHttpRequest)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMParser)
@ -1253,16 +1259,16 @@ static const nsModuleComponentInfo gComponents[] = {
NS_XPATH_EVALUATOR_CONTRACTID,
nsXPathEvaluatorConstructor },
{ "XFormsXPathEvaluator",
TRANSFORMIIX_XFORMS_XPATH_EVALUATOR_CID,
NS_XFORMS_XPATH_EVALUATOR_CONTRACTID,
nsXFormsXPathEvaluatorConstructor },
{ "XPath1 XPointer Scheme Processor",
TRANSFORMIIX_XPATH1_SCHEME_CID,
NS_XPOINTER_SCHEME_PROCESSOR_BASE "xpath1",
nsXPath1SchemeProcessorConstructor },
{ "Transformiix NodeSet",
TRANSFORMIIX_NODESET_CID,
TRANSFORMIIX_NODESET_CONTRACTID,
txNodeSetAdaptorConstructor },
{ "XML Serializer",
NS_XMLSERIALIZER_CID,
NS_XMLSERIALIZER_CONTRACTID,