diff --git a/extensions/transformiix/source/xpath/XFormsFunctionCall.cpp b/extensions/transformiix/source/xpath/XFormsFunctionCall.cpp new file mode 100644 index 000000000000..2dac17e8841d --- /dev/null +++ b/extensions/transformiix/source/xpath/XFormsFunctionCall.cpp @@ -0,0 +1,506 @@ +/* -*- 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 + * + * 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 "FunctionLib.h" +#include "nsAutoPtr.h" +#include "txNodeSet.h" +#include "txAtoms.h" +#include "txIXPathContext.h" +#include "txTokenizer.h" +#include "XFormsFunctions.h" +#include +#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" + +/* + * 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(¶ms); + + switch (mType) { + case AVG: + { + if (!requireParams(1, 1, aContext)) + return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; + + nsRefPtr 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; + + PRInt32 retvalue = -1; + nsAutoString booleanValue; + evaluateToString((Expr*)iter.next(), 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 nodes; + nsresult rv = evaluateToNodeSet((Expr*)iter.next(), aContext, + getter_AddRefs(nodes)); + NS_ENSURE_SUCCESS(rv, rv); + + double res = 0, test = 0; + 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; + + return NS_ERROR_NOT_IMPLEMENTED; + } + case IF: + { + if (!requireParams(3, 3, aContext)) + return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; + + PRBool test; + nsAutoString valueToReturn; + test = evaluateToBoolean((Expr*)iter.next(), aContext); + + // grab 'true' value to return + Expr *getvalue = (Expr*)iter.next(); + + if (!test) { + // grab 'false' value to return + getvalue = (Expr*)iter.next(); + } + evaluateToString(getvalue, 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; + + return NS_ERROR_NOT_IMPLEMENTED; + } + case INSTANCE: + { + nsresult rv; + if (!requireParams(1, 1, aContext)) + return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; + + nsRefPtr resultSet; + rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet)); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString instanceId; + evaluateToString((Expr*)iter.next(), aContext, instanceId); + + // here document is the XForms document + nsCOMPtr document; + rv = mResolverNode->GetOwnerDocument(getter_AddRefs(document)); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(document, NS_ERROR_NULL_POINTER); + + nsCOMPtr 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 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. + nsCOMPtrxformsService = + do_GetService("@mozilla.org/xforms-utility-service;1", &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr 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 instanceRoot; + rv = xformsService->GetInstanceDocumentRoot( + instanceId, + modelInstance, + getter_AddRefs(instanceRoot)); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(instanceRoot, NS_ERROR_NULL_POINTER); + + nsAutoPtr 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 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 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; + + return NS_ERROR_NOT_IMPLEMENTED; + } + 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; + + nsAutoString property; + evaluateToString((Expr*)iter.next(), 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: + { + double dbl=0; + if (!requireParams(1, 1, aContext)) + return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; + + return NS_ERROR_NOT_IMPLEMENTED; + + } + case SECONDSFROMDATETIME: + { + if (!requireParams(1, 1, aContext)) + return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; + + return NS_ERROR_NOT_IMPLEMENTED; + } + } /* switch() */ + + aContext->receiveError(NS_LITERAL_STRING("Internal error"), + NS_ERROR_UNEXPECTED); + return NS_ERROR_UNEXPECTED; +} + +#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::ifFunc; + 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 diff --git a/extensions/transformiix/source/xpath/XFormsFunctions.h b/extensions/transformiix/source/xpath/XFormsFunctions.h new file mode 100644 index 000000000000..6c05a910c009 --- /dev/null +++ b/extensions/transformiix/source/xpath/XFormsFunctions.h @@ -0,0 +1,84 @@ +/* -*- 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 + * + * 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 TRANSFRMX_XFORMS_FUNCTIONS_H +#define TRANSFRMX_XFORMS_FUNCTIONS_H + +#include "Expr.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 { + +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 mResolverNode; +}; + +#endif diff --git a/extensions/transformiix/source/xpath/nsIXFormsUtilityService.h b/extensions/transformiix/source/xpath/nsIXFormsUtilityService.h new file mode 100644 index 000000000000..eda221340b1d --- /dev/null +++ b/extensions/transformiix/source/xpath/nsIXFormsUtilityService.h @@ -0,0 +1,124 @@ +/* -*- 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 + * + * 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 nsIXFormsUtilityService_h +#define nsIXFormsUtilityService_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 nsIXFormsModelElement; /* forward declaration */ + + +/* starting interface: nsIXFormsUtilityService */ +#define NS_IXFORMSUTILITYSERVICE_IID_STR "4a744a59-8771-4065-959d-b8de3dad81da" + +#define NS_IXFORMSUTILITYSERVICE_IID \ + {0x4a744a59, 0x8771, 0x4065, \ + { 0x95, 0x9d, 0xb8, 0xde, 0x3d, 0xad, 0x81, 0xda }} + +#define NS_XFORMS_UTILITY_CONTRACTID "@mozilla.org/xforms-utility-service;1" + +/* Use this macro when declaring classes that implement this interface. */ +#define NS_DECL_NSIXFORMSUTILITYSERVICE \ + NS_IMETHOD GetModelFromNode(nsIDOMNode *node, nsIDOMNode **_retval); \ + NS_IMETHOD IsNodeAssocWithModel(nsIDOMNode *aNode, nsIDOMNode *aModel, PRBool *_retval); \ + NS_IMETHOD GetInstanceDocumentRoot(const nsAString & aID, nsIDOMNode *aModelNode, nsIDOMNode **_retval); \ + NS_IMETHOD ValidateString(const nsAString & aValue, const nsAString & aType, const nsAString & aNamespace, PRBool *_retval); + +/** + * Private interface implemented by the nsXFormsUtilityService in XForms extension. + * Defining it here to prevent XPath requiring XForms extension. + */ +class NS_NO_VTABLE nsIXFormsUtilityService : public nsISupports { + public: + + NS_DEFINE_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 **_retval) = 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 *_retval) = 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 **_retval) = 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 *_retval) = 0; + +}; + +#define NS_ERROR_XFORMS_CALCUATION_EXCEPTION \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_GENERAL, 3001) + +#endif /* nsIXFormsUtilityService_h */ diff --git a/extensions/transformiix/source/xpath/nsIXFormsXPathEvaluator.h b/extensions/transformiix/source/xpath/nsIXFormsXPathEvaluator.h new file mode 100644 index 000000000000..64f3964bc890 --- /dev/null +++ b/extensions/transformiix/source/xpath/nsIXFormsXPathEvaluator.h @@ -0,0 +1,97 @@ +/* -*- 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 + * + * 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 nsIDOMXPathExpression; /* forward declaration */ + +/* starting interface: nsIXFormsXPathEvaluator */ +#define NS_XFORMS_XPATH_EVALUATOR_CONTRACTID "@mozilla.org/dom/xforms-xpath-evaluator;1" +/* a7e127c6-31ff-40b4-8780-15d6938b33d3 */ +#define TRANSFORMIIX_XFORMS_XPATH_EVALUATOR_CID \ +{ 0xa7e127c6, 0x31ff, 0x40b4, { 0x87, 0x80, 0x15, 0xd6, 0x93, 0x8b, 0x33, 0xd3 } } + +/* 60050a4a-4c99-4bad-8c47-3b9b96caf2b4 */ +#define TRANSFORMIIX_XFORMS_XPATH_EVALUATOR_IID \ +{ 0x60050a4a, 0x4c99, 0x4bad, { 0x8c, 0x47, 0x3b, 0x9b, 0x96, 0xca, 0xf2, 0xb4 } } + +/* Use this macro when declaring classes that implement this interface. */ +#define NS_DECL_NSIXFORMXPATHEVALUATOR \ + NS_IMETHOD CreateExpression(const nsAString & aExpression, nsIDOMNode *aResolverNode,nsIDOMXPathExpression **aResult); \ + NS_IMETHOD Evaluate(const nsAString & aExpression, nsIDOMNode *aContextNode, 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_DEFINE_STATIC_IID_ACCESSOR(TRANSFORMIIX_XFORMS_XPATH_EVALUATOR_IID) + + /** + * Function to create a nsIDOMXPathExpression from the provided expression + * string. aResolverNode is the xforms node that the expression is + * associated with. + */ + NS_IMETHOD CreateExpression(const nsAString & aExpression, nsIDOMNode *aResolverNode, nsIDOMXPathExpression **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, nsIDOMNode *aResolverNode, PRUint16 aType, nsISupports *aInResult, nsISupports **aResult) = 0; + +}; + +#endif /* nsIXFormsXPathEvaluator_h */ diff --git a/extensions/transformiix/source/xpath/nsXFormsXPathEvaluator.cpp b/extensions/transformiix/source/xpath/nsXFormsXPathEvaluator.cpp new file mode 100644 index 000000000000..7255734652b7 --- /dev/null +++ b/extensions/transformiix/source/xpath/nsXFormsXPathEvaluator.cpp @@ -0,0 +1,274 @@ +/* -*- 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 + * + * 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 "nsXPathException.h" +#include "nsXPathExpression.h" +#include "nsXPathNSResolver.h" +#include "nsXPathResult.h" +#include "nsContentCID.h" +#include "Expr.h" +#include "ExprParser.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 "XFormsFunctions.h" +#include "nsIDOM3Node.h" + +extern nsINameSpaceManager* gTxNameSpaceManager; + +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, + nsIDOMXPathExpression **aResult) +{ + nsresult rv = NS_OK; + if (!mRecycler) { + nsRefPtr 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 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, + nsIDOMNode *aResolverNode, + PRUint16 aType, + nsISupports *aInResult, + nsISupports **aResult) +{ + // XXX Need to check document of aContextNode if created by + // QI'ing a document. + + nsCOMPtr expression; + nsresult rv = CreateExpression(aExpression, aResolverNode, + getter_AddRefs(expression)); + NS_ENSURE_SUCCESS(rv, rv); + + return expression->Evaluate(aContextNode, 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 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 gTxNameSpaceManager->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::ifFunc) { + aFnCall = new XFormsFunctionCall(XFormsFunctionCall::IF); + } + else if (aName == txXPathAtoms::index) { + aFnCall = new XFormsFunctionCall(XFormsFunctionCall::INDEX); + } + 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; +} + +PRBool nsXFormsXPathEvaluator::XFormsParseContextImpl::fcp() +{ + return PR_FALSE; +} + +void +nsXFormsXPathEvaluator::XFormsParseContextImpl::SetErrorOffset(PRUint32 aOffset) +{ +} diff --git a/extensions/transformiix/source/xpath/nsXFormsXPathEvaluator.h b/extensions/transformiix/source/xpath/nsXFormsXPathEvaluator.h new file mode 100644 index 000000000000..1b9e435bc946 --- /dev/null +++ b/extensions/transformiix/source/xpath/nsXFormsXPathEvaluator.h @@ -0,0 +1,102 @@ +/* -*- 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 + * + * 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 nsXFormsXPathEvaluator_h__ +#define nsXFormsXPathEvaluator_h__ + +#include "nsIXFormsXPathEvaluator.h" +#include "txIXPathContext.h" +#include "nsIXPathEvaluatorInternal.h" +#include "nsIWeakReference.h" +#include "nsAutoPtr.h" +#include "txResultRecycler.h" + + +class nsIDOMDocument; +class nsIDOMXPathExpression; + +/** + * A class for evaluating an XPath expression string + */ +class nsXFormsXPathEvaluator : public nsIXFormsXPathEvaluator +{ +public: + nsXFormsXPathEvaluator(); + virtual ~nsXFormsXPathEvaluator(); + + // nsISupports interface + NS_DECL_ISUPPORTS + + // nsIXFormsXPathEvaluator interface + NS_DECL_NSIXFORMXPATHEVALUATOR + +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(); + PRBool fcp(); + void SetErrorOffset(PRUint32 aOffset); + + private: + nsIDOMNode* mResolverNode; + nsresult mLastError; + }; + + nsRefPtr mRecycler; +}; + +#endif diff --git a/extensions/xforms/nsXFormsUtilityService.cpp b/extensions/xforms/nsXFormsUtilityService.cpp new file mode 100644 index 000000000000..5689136cc5a2 --- /dev/null +++ b/extensions/xforms/nsXFormsUtilityService.cpp @@ -0,0 +1,225 @@ +/* -*- 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 + * + * 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 "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" + +NS_IMPL_ISUPPORTS1(nsXFormsUtilityService, nsIXFormsUtilityService) + +NS_IMETHODIMP +nsXFormsUtilityService::GetModelFromNode(nsIDOMNode *aNode, + nsIDOMNode **aModel) +{ + nsCOMPtr 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 modelPriv = nsXFormsUtils::GetModel(element); + nsCOMPtr 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 element = do_QueryInterface(aNode); + + 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 modelPriv = nsXFormsUtils::GetModel(element); + nsCOMPtr modelNode = do_QueryInterface(modelPriv); + + if (modelNode && (modelNode == aModel)) { + *aModelAssocWithNode = PR_TRUE; + } + else { + *aModelAssocWithNode = PR_FALSE; + } + } + 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 document; + aNode->GetOwnerDocument(getter_AddRefs(document)); + *aModelAssocWithNode = PR_FALSE; + + // Guess that we'd better make sure that it is a model + nsCOMPtr modelEle = do_QueryInterface(aModel); + if (modelEle) { + // OK, we know that this is a model element. So now we have to go + // instance element by instance element and find the associated + // document. If it is equal to the document that contains aNode, + // then aNode is associated with this aModel element and we can return + // true. + nsCOMPtr children; + aModel->GetChildNodes(getter_AddRefs(children)); + + if (!children) + return NS_OK; + + PRUint32 childCount = 0; + children->GetLength(&childCount); + + nsCOMPtr node; + nsCOMPtr instElement; + nsCOMPtr instDocument; + + for (PRUint32 i = 0; i < childCount; ++i) { + children->Item(i, getter_AddRefs(node)); + NS_ASSERTION(node, "incorrect NodeList length?"); + + instElement = do_QueryInterface(node); + if (!instElement) + continue; + + instElement->GetDocument(getter_AddRefs(instDocument)); + if (instDocument) { + if (instDocument == document) { + *aModelAssocWithNode = PR_TRUE; + break; + } + } + } + } + + } + + 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 modelElement = do_QueryInterface(aModelNode); + nsCOMPtr doc; + rv = modelElement->GetInstanceDocument(aID, getter_AddRefs(doc)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr 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) +{ + + // XXX TODO This function needs to call the XForms validator layer from + // bug 274083 when it goes into the build. + +#if 0 + nsresult rv = NS_ERROR_FAILURE; + nsXFormsSchemaValidator *validator = new nsXFormsSchemaValidator(); + *aResult = validator->ValidateString(aValue, aType, aNamespace); + return rv; +#endif + + return NS_ERROR_NOT_IMPLEMENTED; +} diff --git a/extensions/xforms/nsXFormsUtilityService.h b/extensions/xforms/nsXFormsUtilityService.h new file mode 100644 index 000000000000..e8b9c535b392 --- /dev/null +++ b/extensions/xforms/nsXFormsUtilityService.h @@ -0,0 +1,47 @@ +/* -*- 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 + * + * 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 "nsIXFormsUtilityService.h" + +class nsXFormsUtilityService : public nsIXFormsUtilityService +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIXFORMSUTILITYSERVICE + +};