Merge of XForms code to the trunk. This has some rough edges still, like inputs not being treated as inline elements.

This commit is contained in:
bryner%brianryner.com 2004-10-13 09:51:52 +00:00
Родитель b53073c3c1
Коммит 7dd8608440
37 изменённых файлов: 8261 добавлений и 0 удалений

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

@ -0,0 +1 @@
Makefile

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

@ -0,0 +1,88 @@
#
# ***** 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
# IBM Corporation.
# Portions created by the Initial Developer are Copyright (C) 2004
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Brian Ryner <bryner@brianryner.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either of 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 *****
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = xforms
LIBRARY_NAME = xforms
IS_COMPONENT = 1
EXPORT_LIBRARY = 1
MODULE_NAME = xforms
REQUIRES = \
xpcom \
string \
content \
dom \
widget \
necko \
websrvcs \
xmlextras \
docshell \
mimetype \
$(NULL)
CPPSRCS = \
nsXFormsElementFactory.cpp \
nsXFormsElement.cpp \
nsXFormsControl.cpp \
nsXFormsModelElement.cpp \
nsXFormsInputElement.cpp \
nsXFormsSubmissionElement.cpp \
nsXFormsStubElement.cpp \
nsXFormsInstanceElement.cpp \
nsXFormsAtoms.cpp \
nsXFormsModule.cpp \
nsXFormsMDG.cpp \
nsXFormsMDGEngine.cpp \
nsXFormsMDGSet.cpp \
nsXFormsXPathAnalyzer.cpp \
nsXFormsXPathNode.cpp \
nsXFormsXPathParser.cpp \
nsXFormsXPathScanner.cpp \
nsXFormsXPathXMLUtil.cpp \
$(NULL)
EXTRA_DSO_LDOPTS = $(MOZ_COMPONENT_LIBS)
include $(topsrcdir)/config/rules.mk

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

@ -0,0 +1,72 @@
/* -*- 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):
* Brian Ryner <bryner@brianryner.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 "nsXFormsAtoms.h"
#include "nsMemory.h"
nsIAtom* nsXFormsAtoms::src;
nsIAtom* nsXFormsAtoms::bind;
nsIAtom* nsXFormsAtoms::type;
nsIAtom* nsXFormsAtoms::readonly;
nsIAtom* nsXFormsAtoms::required;
nsIAtom* nsXFormsAtoms::relevant;
nsIAtom* nsXFormsAtoms::calculate;
nsIAtom* nsXFormsAtoms::constraint;
nsIAtom* nsXFormsAtoms::p3ptype;
nsIAtom* nsXFormsAtoms::modelListProperty;
nsIAtom *nsXFormsAtoms::ref;
const nsStaticAtom nsXFormsAtoms::Atoms_info[] = {
{ "src", &nsXFormsAtoms::src },
{ "bind", &nsXFormsAtoms::bind },
{ "type", &nsXFormsAtoms::type },
{ "readonly", &nsXFormsAtoms::readonly },
{ "required", &nsXFormsAtoms::required },
{ "relevant", &nsXFormsAtoms::relevant },
{ "calculate", &nsXFormsAtoms::calculate },
{ "constraint", &nsXFormsAtoms::constraint },
{ "p3ptype", &nsXFormsAtoms::p3ptype },
{ "ModelListProperty", &nsXFormsAtoms::modelListProperty },
{ "ref", &nsXFormsAtoms::ref },
};
void
nsXFormsAtoms::InitAtoms()
{
NS_RegisterStaticAtoms(Atoms_info, NS_ARRAY_LENGTH(Atoms_info));
}

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

@ -0,0 +1,60 @@
/* -*- 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):
* Brian Ryner <bryner@brianryner.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 "nsStaticAtom.h"
class nsXFormsAtoms
{
public:
static NS_HIDDEN_(nsIAtom *) src;
static NS_HIDDEN_(nsIAtom *) bind;
static NS_HIDDEN_(nsIAtom *) type;
static NS_HIDDEN_(nsIAtom *) readonly;
static NS_HIDDEN_(nsIAtom *) required;
static NS_HIDDEN_(nsIAtom *) relevant;
static NS_HIDDEN_(nsIAtom *) calculate;
static NS_HIDDEN_(nsIAtom *) constraint;
static NS_HIDDEN_(nsIAtom *) p3ptype;
static NS_HIDDEN_(nsIAtom *) modelListProperty;
static NS_HIDDEN_(nsIAtom *) ref;
static NS_HIDDEN_(void) InitAtoms();
private:
static NS_HIDDEN_(const nsStaticAtom) Atoms_info[];
};

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

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

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

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

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

@ -0,0 +1,67 @@
/* -*- 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):
* Brian Ryner <bryner@brianryner.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 "nsXFormsElementFactory.h"
#include "nsXFormsModelElement.h"
#include "nsXFormsInstanceElement.h"
#include "nsXFormsSubmissionElement.h"
#include "nsXFormsStubElement.h"
#include "nsString.h"
NS_HIDDEN_(nsresult) NS_NewXFormsInputElement(nsIXTFElement **aElement);
NS_IMPL_ISUPPORTS1(nsXFormsElementFactory, nsIXTFElementFactory)
NS_IMETHODIMP
nsXFormsElementFactory::CreateElement(const nsAString& aTagName,
nsIXTFElement **aElement)
{
if (aTagName.EqualsLiteral("model"))
return NS_NewXFormsModelElement(aElement);
if (aTagName.EqualsLiteral("instance"))
return NS_NewXFormsInstanceElement(aElement);
if (aTagName.EqualsLiteral("bind"))
return NS_NewXFormsStubElement(aElement);
if (aTagName.EqualsLiteral("input"))
return NS_NewXFormsInputElement(aElement);
if (aTagName.EqualsLiteral("submission"))
return NS_NewXFormsSubmissionElement(aElement);
*aElement = nsnull;
return NS_ERROR_FAILURE;
}

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

@ -0,0 +1,49 @@
/* -*- 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):
* Brian Ryner <bryner@brianryner.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 "nsIXTFElementFactory.h"
#define NS_XFORMSELEMENTFACTORY_CID \
{0xc068f682, 0x03b5, 0x4e96, {0x81, 0xe1, 0x60, 0x13, 0xf9, 0x12, 0x88, 0xb2}}
class nsXFormsElementFactory : public nsIXTFElementFactory
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIXTFELEMENTFACTORY
};

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

@ -0,0 +1,401 @@
/* -*- 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):
* Brian Ryner <bryner@brianryner.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 "nsIXTFXMLVisual.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOM3Node.h"
#include "nsIDOMElement.h"
#include "nsMemory.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsIXTFXMLVisualWrapper.h"
#include "nsIDOMDocument.h"
#include "nsXFormsControl.h"
#include "nsISchema.h"
#include "nsXFormsModelElement.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsXFormsAtoms.h"
#include "nsAutoPtr.h"
#include "nsIDOMXPathResult.h"
#include "nsIDOMFocusListener.h"
#include "nsIDOM3EventTarget.h"
#include "nsIDOMEventReceiver.h"
#include "nsIDOMEventGroup.h"
static const nsIID sScriptingIIDs[] = {
NS_IDOMELEMENT_IID,
NS_IDOMEVENTTARGET_IID,
NS_IDOM3NODE_IID
};
class nsXFormsInputElement : public nsXFormsControl,
public nsIXTFXMLVisual,
public nsIDOMFocusListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIXTFXMLVISUAL
NS_DECL_NSIXTFVISUAL
NS_DECL_NSIXTFELEMENT
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent);
// nsIDOMFocusListener
NS_IMETHOD Focus(nsIDOMEvent *aEvent);
NS_IMETHOD Blur(nsIDOMEvent *aEvent);
// nsXFormsControl
virtual NS_HIDDEN_(void) Refresh();
private:
nsCOMPtr<nsIDOMHTMLInputElement> mInput;
};
NS_IMPL_ADDREF(nsXFormsInputElement)
NS_IMPL_RELEASE(nsXFormsInputElement)
NS_INTERFACE_MAP_BEGIN(nsXFormsInputElement)
NS_INTERFACE_MAP_ENTRY(nsIXTFXMLVisual)
NS_INTERFACE_MAP_ENTRY(nsIXTFElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXTFXMLVisual)
NS_INTERFACE_MAP_END
// nsIXTFXMLVisual
NS_IMETHODIMP
nsXFormsInputElement::OnCreated(nsIXTFXMLVisualWrapper *aWrapper)
{
aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_WILL_SET_ATTRIBUTE |
nsIXTFElement::NOTIFY_ATTRIBUTE_SET);
mWrapper = aWrapper;
nsCOMPtr<nsIDOMElement> node;
mWrapper->GetElementNode(getter_AddRefs(node));
nsCOMPtr<nsIDOMDocument> domDoc;
node->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDOMElement> inputElement;
domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML),
NS_LITERAL_STRING("input"),
getter_AddRefs(inputElement));
mInput = do_QueryInterface(inputElement);
NS_ENSURE_TRUE(mInput, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mInput);
nsCOMPtr<nsIDOMEventGroup> group;
receiver->GetSystemEventGroup(getter_AddRefs(group));
nsCOMPtr<nsIDOM3EventTarget> targ = do_QueryInterface(mInput);
targ->AddGroupedEventListener(NS_LITERAL_STRING("blur"), this,
PR_FALSE, group);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::GetVisualContent(nsIDOMElement **aElement)
{
NS_ADDREF(*aElement = mInput);
return NS_OK;
}
// nsIXTFElement
NS_IMETHODIMP
nsXFormsInputElement::OnDestroyed()
{
if (!mInput)
return NS_OK;
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mInput);
nsCOMPtr<nsIDOMEventGroup> group;
receiver->GetSystemEventGroup(getter_AddRefs(group));
nsCOMPtr<nsIDOM3EventTarget> targ = do_QueryInterface(mInput);
targ->RemoveGroupedEventListener(NS_LITERAL_STRING("blur"), this,
PR_FALSE, group);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::GetElementType(PRUint32 *aType)
{
*aType = ELEMENT_TYPE_XML_VISUAL;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::GetIsAttributeHandler(PRBool *aIsHandler)
{
*aIsHandler = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::GetScriptingInterfaces(PRUint32 *aCount, nsIID ***aArray)
{
return CloneScriptingInterfaces(sScriptingIIDs,
NS_ARRAY_LENGTH(sScriptingIIDs),
aCount, aArray);
}
NS_IMETHODIMP
nsXFormsInputElement::WillChangeDocument(nsIDOMDocument *aNewDocument)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::DocumentChanged(nsIDOMDocument *aNewDocument)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::WillChangeParent(nsIDOMElement *aNewParent)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::ParentChanged(nsIDOMElement *aNewParent)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::WillInsertChild(nsIDOMNode *aChild, PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::ChildInserted(nsIDOMNode *aChild, PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::WillAppendChild(nsIDOMNode *aChild)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::ChildAppended(nsIDOMNode *aChild)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::WillRemoveChild(PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::ChildRemoved(PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::WillSetAttribute(nsIAtom *aName, const nsAString &aValue)
{
if (aName == nsXFormsAtoms::bind || aName == nsXFormsAtoms::ref) {
nsCOMPtr<nsIDOMElement> bindElement;
nsXFormsModelElement *model = GetModelAndBind(getter_AddRefs(bindElement));
if (model)
model->RemoveFormControl(this);
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::AttributeSet(nsIAtom *aName, const nsAString &aValue)
{
if (aName == nsXFormsAtoms::bind || aName == nsXFormsAtoms::ref) {
Refresh();
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::WillRemoveAttribute(nsIAtom *aName)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::AttributeRemoved(nsIAtom *aName)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::DoneAddingChildren()
{
return NS_OK;
}
// nsIDOMEventListener
NS_IMETHODIMP
nsXFormsInputElement::HandleEvent(nsIDOMEvent *aEvent)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::Focus(nsIDOMEvent *aEvent)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::Blur(nsIDOMEvent *aEvent)
{
if (!mInput)
return NS_OK;
nsRefPtr<nsXFormsModelElement> model;
nsCOMPtr<nsIDOMElement> bindElement;
nsCOMPtr<nsIDOMXPathResult> result =
EvaluateBinding(nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
getter_AddRefs(model), getter_AddRefs(bindElement));
if (!result)
return NS_OK;
nsCOMPtr<nsIDOMNode> singleNode;
result->GetSingleNodeValue(getter_AddRefs(singleNode));
if (!singleNode)
return NS_OK;
nsAutoString value, type;
mInput->GetType(type);
if (type.EqualsLiteral("checkbox")) {
PRBool checked;
mInput->GetChecked(&checked);
value.AssignASCII(checked ? "1" : "0", 1);
} else {
mInput->GetValue(value);
}
PRUint16 nodeType = 0;
singleNode->GetNodeType(&nodeType);
switch (nodeType) {
case nsIDOMNode::ATTRIBUTE_NODE:
case nsIDOMNode::TEXT_NODE:
singleNode->SetNodeValue(value);
break;
case nsIDOMNode::ELEMENT_NODE:
{
nsCOMPtr<nsIDOM3Node> node = do_QueryInterface(singleNode);
NS_ASSERTION(node, "DOM Nodes must support DOM3 interfaces");
node->SetTextContent(value);
break;
}
}
return NS_OK;
}
// other methods
void
nsXFormsInputElement::Refresh()
{
if (!mInput)
return;
nsRefPtr<nsXFormsModelElement> model;
nsCOMPtr<nsIDOMElement> bindElement;
nsCOMPtr<nsIDOMXPathResult> result =
EvaluateBinding(nsIDOMXPathResult::STRING_TYPE,
getter_AddRefs(model), getter_AddRefs(bindElement));
if (model) {
model->AddFormControl(this);
if (result) {
nsAutoString nodeValue;
result->GetStringValue(nodeValue);
nsCOMPtr<nsISchemaType> type = model->GetTypeForControl(this);
nsCOMPtr<nsISchemaBuiltinType> biType = do_QueryInterface(type);
PRUint16 typeValue = nsISchemaBuiltinType::BUILTIN_TYPE_STRING;
if (biType)
biType->GetBuiltinType(&typeValue);
if (typeValue == nsISchemaBuiltinType::BUILTIN_TYPE_BOOLEAN) {
mInput->SetAttribute(NS_LITERAL_STRING("type"),
NS_LITERAL_STRING("checkbox"));
mInput->SetChecked(nodeValue.EqualsLiteral("true") ||
nodeValue.EqualsLiteral("1"));
} else {
mInput->RemoveAttribute(NS_LITERAL_STRING("type"));
mInput->SetValue(nodeValue);
}
}
}
}
NS_HIDDEN_(nsresult)
NS_NewXFormsInputElement(nsIXTFElement **aResult)
{
*aResult = new nsXFormsInputElement();
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}

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

@ -0,0 +1,431 @@
/* -*- 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):
* Brian Ryner <bryner@brianryner.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 "nsXFormsInstanceElement.h"
#include "nsIDOMElement.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOM3Node.h"
#include "nsMemory.h"
#include "nsXFormsAtoms.h"
#include "nsString.h"
#include "nsIDOMEventReceiver.h"
#include "nsIDOMXMLDocument.h"
#include "nsIDOMDOMImplementation.h"
static const nsIID sScriptingIIDs[] = {
NS_IDOMELEMENT_IID,
NS_IDOMEVENTTARGET_IID,
NS_IDOM3NODE_IID
};
NS_IMPL_ADDREF(nsXFormsInstanceElement)
NS_IMPL_RELEASE(nsXFormsInstanceElement)
NS_INTERFACE_MAP_BEGIN(nsXFormsInstanceElement)
NS_INTERFACE_MAP_ENTRY(nsIXTFGenericElement)
NS_INTERFACE_MAP_ENTRY(nsIXTFElement)
NS_INTERFACE_MAP_ENTRY(nsIXTFPrivate)
NS_INTERFACE_MAP_ENTRY(nsIDOMLoadListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXTFGenericElement)
NS_INTERFACE_MAP_END
NS_IMETHODIMP
nsXFormsInstanceElement::OnDestroyed()
{
nsCOMPtr<nsIDOMEventReceiver> rec = do_QueryInterface(mDocument);
if (rec)
rec->RemoveEventListenerByIID(this, NS_GET_IID(nsIDOMLoadListener));
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::GetElementType(PRUint32 *aElementType)
{
*aElementType = nsIXTFElement::ELEMENT_TYPE_GENERIC_ELEMENT;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::GetIsAttributeHandler(PRBool *aIsAttributeHandler)
{
*aIsAttributeHandler = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::GetScriptingInterfaces(PRUint32 *aCount,
nsIID ***aArray)
{
return CloneScriptingInterfaces(sScriptingIIDs,
NS_ARRAY_LENGTH(sScriptingIIDs),
aCount, aArray);
}
NS_IMETHODIMP
nsXFormsInstanceElement::WillChangeDocument(nsIDOMDocument *aNewDocument)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::DocumentChanged(nsIDOMDocument *aNewDocument)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::WillChangeParent(nsIDOMElement *aNewParent)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::ParentChanged(nsIDOMElement *aNewParent)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::WillInsertChild(nsIDOMNode *aChild, PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::ChildInserted(nsIDOMNode *aChild, PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::WillAppendChild(nsIDOMNode *aChild)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::ChildAppended(nsIDOMNode *aChild)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::WillRemoveChild(PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::ChildRemoved(PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::WillSetAttribute(nsIAtom *aName,
const nsAString &aNewValue)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::AttributeSet(nsIAtom *aName,
const nsAString &aNewValue)
{
if (aName == nsXFormsAtoms::src) {
// Note that this will fail if encountered during document construction,
// because we won't be in the document yet, so CreateInstanceDocument
// won't find a document to work with. That's ok, we'll fix things after
// our children are appended and we're in the document (DoneAddingChildren)
LoadExternalInstance(aNewValue);
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::WillRemoveAttribute(nsIAtom *aName)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::AttributeRemoved(nsIAtom *aName)
{
if (aName == nsXFormsAtoms::src) {
// We no longer have an external instance to use.
// Reset our instance document to whatever inline content we have.
return CloneInlineInstance();
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::DoneAddingChildren()
{
// By the time this is called, we should be inserted in the document
// and have all of our child elements, so this is our first opportunity
// to create the instance document.
nsCOMPtr<nsIDOMElement> element;
mWrapper->GetElementNode(getter_AddRefs(element));
NS_ASSERTION(element, "no wrapper element");
nsAutoString src;
element->GetAttribute(NS_LITERAL_STRING("src"), src);
if (src.IsEmpty()) {
// If we don't have a linked external instance, use our inline data.
CloneInlineInstance();
} else {
LoadExternalInstance(src);
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
{
aWrapper->SetNotificationMask (nsIXTFElement::NOTIFY_PARENT_CHANGED |
nsIXTFElement::NOTIFY_ATTRIBUTE_SET |
nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED |
nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN);
mWrapper = aWrapper;
return NS_OK;
}
// nsIDOMLoadListener
NS_IMETHODIMP
nsXFormsInstanceElement::Load(nsIDOMEvent *aEvent)
{
nsXFormsModelElement *model = GetModel();
if (model)
model->RemovePendingInstance();
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::BeforeUnload(nsIDOMEvent *aEvent)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::Unload(nsIDOMEvent *aEvent)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::Abort(nsIDOMEvent *aEvent)
{
nsXFormsModelElement *model = GetModel();
if (model) {
model->RemovePendingInstance();
model->DispatchEvent(eEvent_LinkException);
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::Error(nsIDOMEvent *aEvent)
{
nsXFormsModelElement *model = GetModel();
if (model) {
model->RemovePendingInstance();
model->DispatchEvent(eEvent_LinkException);
}
return NS_OK;
}
// nsIDOMEventListener
NS_IMETHODIMP
nsXFormsInstanceElement::HandleEvent(nsIDOMEvent *aEvent)
{
return NS_OK;
}
// nsIXTFPrivate
NS_IMETHODIMP
nsXFormsInstanceElement::GetInner(nsISupports **aInner)
{
NS_ENSURE_ARG_POINTER(aInner);
NS_ADDREF(*aInner = NS_STATIC_CAST(nsIXTFGenericElement*, this));
return NS_OK;
}
// private methods
nsresult
nsXFormsInstanceElement::CloneInlineInstance()
{
// Clear out our existing instance data
nsresult rv = CreateInstanceDocument();
if (NS_FAILED(rv))
return rv; // don't warn, we might just not be in the document yet
// look for our first child element (skip over text nodes, etc.)
nsCOMPtr<nsIDOMElement> element;
mWrapper->GetElementNode(getter_AddRefs(element));
nsCOMPtr<nsIDOMNode> child, temp;
element->GetFirstChild(getter_AddRefs(child));
while (child) {
PRUint16 nodeType;
child->GetNodeType(&nodeType);
if (nodeType == nsIDOMNode::ELEMENT_NODE)
break;
temp.swap(child);
temp->GetNextSibling(getter_AddRefs(child));
}
if (child) {
nsCOMPtr<nsIDOMNode> newNode;
rv = mDocument->ImportNode(child, PR_TRUE, getter_AddRefs(newNode));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> nodeReturn;
rv = mDocument->AppendChild(newNode, getter_AddRefs(nodeReturn));
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "failed to append root instance node");
}
return rv;
}
void
nsXFormsInstanceElement::LoadExternalInstance(const nsAString &aSrc)
{
// Clear out our existing instance data
if (NS_FAILED(CreateInstanceDocument()))
return;
nsCOMPtr<nsIDOMEventReceiver> rec = do_QueryInterface(mDocument);
rec->AddEventListenerByIID(this, NS_GET_IID(nsIDOMLoadListener));
nsCOMPtr<nsIDOMXMLDocument> xmlDoc = do_QueryInterface(mDocument);
NS_ASSERTION(xmlDoc, "we created a document but it's not an XMLDocument?");
nsCOMPtr<nsIDOMElement> element;
mWrapper->GetElementNode(getter_AddRefs(element));
PRBool success;
xmlDoc->Load(aSrc, &success);
nsXFormsModelElement *model = GetModel();
if (model) {
if (success)
model->AddPendingInstance();
else
model->DispatchEvent(eEvent_LinkException);
}
}
nsresult
nsXFormsInstanceElement::CreateInstanceDocument()
{
nsCOMPtr<nsIDOMElement> element;
mWrapper->GetElementNode(getter_AddRefs(element));
NS_ASSERTION(element, "no wrapper element");
nsCOMPtr<nsIDOMDocument> doc;
nsresult rv = element->GetOwnerDocument(getter_AddRefs(doc));
NS_ENSURE_SUCCESS(rv, rv);
if (!doc) // could be we just aren't inserted yet, so don't warn
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMDOMImplementation> domImpl;
rv = doc->GetImplementation(getter_AddRefs(domImpl));
NS_ENSURE_SUCCESS(rv, rv);
return domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
getter_AddRefs(mDocument));
}
nsXFormsModelElement*
nsXFormsInstanceElement::GetModel()
{
nsCOMPtr<nsIDOMElement> element;
mWrapper->GetElementNode(getter_AddRefs(element));
NS_ASSERTION(element, "no wrapper element");
nsCOMPtr<nsIDOMNode> parentNode;
element->GetParentNode(getter_AddRefs(parentNode));
nsCOMPtr<nsIXFormsModelElement> modelElt = do_QueryInterface(parentNode);
if (!modelElt)
return nsnull;
nsCOMPtr<nsIXTFPrivate> xtfPriv = do_QueryInterface(modelElt);
NS_ENSURE_TRUE(xtfPriv, nsnull);
nsCOMPtr<nsISupports> modelInner;
xtfPriv->GetInner(getter_AddRefs(modelInner));
NS_ENSURE_TRUE(modelInner, nsnull);
nsISupports *isupp = NS_STATIC_CAST(nsISupports*, modelInner.get());
return NS_STATIC_CAST(nsXFormsModelElement*,
NS_STATIC_CAST(nsIXFormsModelElement*, isupp));
}
nsresult
NS_NewXFormsInstanceElement(nsIXTFElement **aResult)
{
*aResult = new nsXFormsInstanceElement();
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}

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

@ -0,0 +1,93 @@
/* -*- 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):
* Brian Ryner <bryner@brianryner.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 ***** */
/**
* nsXFormsInstanceElement implements the xforms <instance> element.
* It creates an instance document by either cloning the inline instance data
* or loading an external xml document given by the src attribute.
*/
#ifndef nsXFormsInstanceElement_h_
#define nsXFormsInstanceElement_h_
#include "nsIXTFGenericElement.h"
#include "nsIXTFPrivate.h"
#include "nsXFormsElement.h"
#include "nsIDOMDocument.h"
#include "nsCOMPtr.h"
#include "nsIXTFGenericElementWrapper.h"
#include "nsIDOMLoadListener.h"
#include "nsXFormsModelElement.h"
class nsXFormsInstanceElement : public nsXFormsElement,
public nsIXTFGenericElement,
public nsIXTFPrivate,
public nsIDOMLoadListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIXTFELEMENT
NS_DECL_NSIXTFGENERICELEMENT
NS_DECL_NSIXTFPRIVATE
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent);
// nsIDOMLoadListener
NS_IMETHOD Load(nsIDOMEvent *aEvent);
NS_IMETHOD BeforeUnload(nsIDOMEvent *aEvent);
NS_IMETHOD Unload(nsIDOMEvent *aEvent);
NS_IMETHOD Abort(nsIDOMEvent *aEvent);
NS_IMETHOD Error(nsIDOMEvent *aEvent);
NS_HIDDEN_(nsIDOMDocument*) GetDocument() { return mDocument; }
private:
NS_HIDDEN_(nsresult) CloneInlineInstance();
NS_HIDDEN_(void) LoadExternalInstance(const nsAString &aSrc);
NS_HIDDEN_(nsresult) CreateInstanceDocument();
NS_HIDDEN_(nsXFormsModelElement*) GetModel();
nsCOMPtr<nsIDOMDocument> mDocument;
nsCOMPtr<nsIXTFGenericElementWrapper> mWrapper;
};
NS_HIDDEN_(nsresult)
NS_NewXFormsInstanceElement(nsIXTFElement **aResult);
#endif

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

@ -0,0 +1,329 @@
/* -*- 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
* Novell, Inc.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Allan Beaufour <abeaufour@novell.com>
* David Landwehr <dlandwehr@novell.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 "nsXFormsMDG.h"
#include "nsVoidArray.h"
#include "nsIDOMDocument.h"
#include "nsIDOMText.h"
#include "nsXFormsXPathNode.h"
MOZ_DECL_CTOR_COUNTER(nsXFormsMDG)
nsXFormsMDG::nsXFormsMDG()
: mEngine(this)
{
MOZ_COUNT_CTOR(nsXFormsMDG);
}
nsXFormsMDG::~nsXFormsMDG()
{
MOZ_COUNT_DTOR(nsXFormsMDG);
}
nsresult
nsXFormsMDG::Init()
{
return mEngine.Init();
}
nsresult
nsXFormsMDG::CreateNewChild(nsIDOMNode* aContextNode, const nsAString& aNodeValue,
nsIDOMNode* aBeforeNode)
{
nsresult rv;
nsCOMPtr<nsIDOMDocument> document;
rv = aContextNode->GetOwnerDocument(getter_AddRefs(document));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMText> textNode;
rv = document->CreateTextNode(aNodeValue, getter_AddRefs(textNode));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> newNode;
if (aBeforeNode) {
rv = aContextNode->InsertBefore(textNode, aBeforeNode, getter_AddRefs(newNode));
} else {
rv = aContextNode->AppendChild(textNode, getter_AddRefs(newNode));
}
return rv;
}
nsresult
nsXFormsMDG::AddMIP(ModelItemPropName aType, nsIDOMXPathExpression* aExpression,
nsXFormsMDGSet* aDeps, PRBool aDynFunc, nsIDOMNode* aContextNode,
PRInt32 aContextPos, PRInt32 aContextSize)
{
NS_ENSURE_ARG(aExpression);
NS_ENSURE_ARG(aContextNode);
return mEngine.Insert(aContextNode, aExpression, aDeps, aDynFunc, aContextPos, aContextSize, aType);
}
nsresult
nsXFormsMDG::MarkNodeAsChanged(nsIDOMNode* aContextNode)
{
return mEngine.MarkNode(aContextNode);
}
nsresult
nsXFormsMDG::Recalculate(nsXFormsMDGSet& aChangedNodes)
{
return mEngine.Calculate(aChangedNodes);
}
nsresult
nsXFormsMDG::Rebuild()
{
return mEngine.Rebuild();
}
void
nsXFormsMDG::ClearDispatchFlags()
{
mEngine.ClearDispatchFlags();
}
void
nsXFormsMDG::Clear() {
mEngine.Clear();
}
nsresult
nsXFormsMDG::GetNodeValue(nsIDOMNode* aContextNode, nsAString& aNodeValue)
{
nsresult rv;
nsCOMPtr<nsIDOMNode> childNode;
PRUint16 nodeType;
rv = aContextNode->GetNodeType(&nodeType);
NS_ENSURE_SUCCESS(rv, rv);
switch(nodeType) {
case nsIDOMNode::ATTRIBUTE_NODE:
case nsIDOMNode::TEXT_NODE:
case nsIDOMNode::CDATA_SECTION_NODE:
case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
case nsIDOMNode::COMMENT_NODE:
rv = aContextNode->GetNodeValue(aNodeValue);
NS_ENSURE_SUCCESS(rv, rv);
break;
case nsIDOMNode::ELEMENT_NODE:
rv = aContextNode->GetFirstChild(getter_AddRefs(childNode));
if (NS_FAILED(rv) || !childNode) {
// No child
aNodeValue.Truncate(0);
} else {
PRUint16 childType;
rv = childNode->GetNodeType(&childType);
NS_ENSURE_SUCCESS(rv, rv);
if ( childType == nsIDOMNode::TEXT_NODE
|| childType == nsIDOMNode::CDATA_SECTION_NODE) {
rv = childNode->GetNodeValue(aNodeValue);
NS_ENSURE_SUCCESS(rv, rv);
} else {
// Not a text child
aNodeValue.Truncate(0);
}
}
break;
default:
// Asked for a node which cannot have a text child
// TODO: Should return more specific error?
return NS_ERROR_ILLEGAL_VALUE;
break;
}
return NS_OK;
}
nsresult
nsXFormsMDG::SetNodeValue(nsIDOMNode* aContextNode, nsAString& aNodeValue, PRBool aMarkNode)
{
if (IsReadonly(aContextNode)) {
// TODO: Better feedback for readonly nodes?
return NS_OK;
}
nsresult rv;
nsCOMPtr<nsIDOMNode> childNode;
PRUint16 nodeType;
rv = aContextNode->GetNodeType(&nodeType);
NS_ENSURE_SUCCESS(rv, rv);
switch(nodeType) {
case nsIDOMNode::ATTRIBUTE_NODE:
case nsIDOMNode::TEXT_NODE:
case nsIDOMNode::CDATA_SECTION_NODE:
case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
case nsIDOMNode::COMMENT_NODE:
// TODO: Check existing value, and ignore if same??
rv = aContextNode->SetNodeValue(aNodeValue);
NS_ENSURE_SUCCESS(rv, rv);
break;
case nsIDOMNode::ELEMENT_NODE:
rv = aContextNode->GetFirstChild(getter_AddRefs(childNode));
NS_ENSURE_SUCCESS(rv, rv);
if (!childNode) {
rv = CreateNewChild(aContextNode, aNodeValue);
NS_ENSURE_SUCCESS(rv, rv);
} else {
PRUint16 childType;
rv = childNode->GetNodeType(&childType);
NS_ENSURE_SUCCESS(rv, rv);
if ( childType == nsIDOMNode::TEXT_NODE
|| childType == nsIDOMNode::CDATA_SECTION_NODE) {
rv = childNode->SetNodeValue(aNodeValue);
NS_ENSURE_SUCCESS(rv, rv);
} else {
// Not a text child, create a new one
rv = CreateNewChild(aContextNode, aNodeValue, childNode);
NS_ENSURE_SUCCESS(rv, rv);
}
}
break;
default:
// Unsupported nodeType
// TODO: Should return more specific error?
return NS_ERROR_ILLEGAL_VALUE;
break;
}
// NB: Never reached for Readonly nodes.
if (aMarkNode) {
MarkNodeAsChanged(aContextNode);
}
return NS_OK;
}
/**********************************************/
/* Bit test functions */
/**********************************************/
PRBool
nsXFormsMDG::IsValid(nsIDOMNode* aContextNode)
{
PRBool valid = mEngine.Test(aContextNode, MDG_FLAG_CONSTRAINT);
if (valid) {
// TODO: needs Schema support
// valid = mSchemaHandler->ValidateNode(aContextNode);
}
return valid;
}
PRBool
nsXFormsMDG::IsConstraint(nsIDOMNode* aContextNode)
{
return mEngine.Test(aContextNode, MDG_FLAG_CONSTRAINT);
}
PRBool
nsXFormsMDG::ShouldDispatchValid(nsIDOMNode* aContextNode)
{
return mEngine.Test(aContextNode, MDG_FLAG_DISPATCH_VALID_CHANGED);
}
PRBool
nsXFormsMDG::IsReadonly(nsIDOMNode* aContextNode)
{
PRBool valid;
if ( mEngine.Test(aContextNode, MDG_FLAG_READONLY)
|| mEngine.Test(aContextNode, MDG_FLAG_INHERITED_READONLY)) {
valid = PR_TRUE;
} else {
valid = PR_FALSE;
}
return valid;
}
PRBool
nsXFormsMDG::ShouldDispatchReadonly(nsIDOMNode* aContextNode)
{
return mEngine.Test(aContextNode, MDG_FLAG_DISPATCH_READONLY_CHANGED);
}
PRBool
nsXFormsMDG::IsRelevant(nsIDOMNode* aContextNode)
{
PRBool valid;
if ( mEngine.Test(aContextNode, MDG_FLAG_RELEVANT)
&& mEngine.Test(aContextNode, MDG_FLAG_INHERITED_RELEVANT)) {
valid = PR_TRUE;
} else {
valid = PR_FALSE;
}
return valid;
}
PRBool
nsXFormsMDG::ShouldDispatchRelevant(nsIDOMNode* aContextNode)
{
return mEngine.Test(aContextNode, MDG_FLAG_DISPATCH_RELEVANT_CHANGED);
}
PRBool
nsXFormsMDG::IsRequired(nsIDOMNode* aContextNode)
{
return mEngine.Test(aContextNode, MDG_FLAG_REQUIRED);
}
PRBool
nsXFormsMDG::ShouldDispatchRequired(nsIDOMNode* aContextNode)
{
return mEngine.Test(aContextNode, MDG_FLAG_DISPATCH_REQUIRED_CHANGED);
}
PRBool
nsXFormsMDG::ShouldDispatchValueChanged(nsIDOMNode* aContextNode)
{
return mEngine.Test(aContextNode, MDG_FLAG_DISPATCH_VALUE_CHANGED);
}

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

@ -0,0 +1,155 @@
/* -*- 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
* Novell, Inc.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Allan Beaufour <abeaufour@novell.com>
* David Landwehr <dlandwehr@novell.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 "nsString.h"
#include "nsIDOMNode.h"
#include "nsIDOMXPathExpression.h"
#include "nsXFormsMDGEngine.h"
/**
* Class nsXFormsMDG.
*
* This a wrapper of the more low-level nsXFormsMDGEngine. It handles all the Multi
* Dependency Graph (MDG) functions for the Mozilla XForms implementation.
*/
class nsXFormsMDG {
protected:
/**
* The MDG engine used.
*/
nsXFormsMDGEngine mEngine;
/**
* Inserts a new text child for aContextNode.
*
* @param aContextNode The node to create a child for
* @param aNodeValue The value of the new node
* @param aBeforeNode If non-null, insert new node before this node
*/
nsresult CreateNewChild(nsIDOMNode* aContextNode, const nsAString& aNodeValue, nsIDOMNode* aBeforeNode = nsnull);
public:
/**
* Constructor. Be sure to call Init() before using the object.
*/
nsXFormsMDG();
/**
* Destructor.
*/
~nsXFormsMDG();
/**
* Initializes internal objects. If it fails, the object is unusable.
*/
nsresult Init();
/**
* Insert new MIP (Model Item Property) into graph.
*
* @param aType The type of MIP
* @param aExpression The XPath expression
* @param aDeps Set of nodes expression depends on
* @param aDynFunc True if expression uses dynamic functions
* @param aContextNode The context node for aExpression
* @param aContextPos The context positions of aExpression
* @param aContextSize The context size for aExpression
*/
nsresult AddMIP(ModelItemPropName aType, nsIDOMXPathExpression* aExpression,
nsXFormsMDGSet* aDeps, PRBool aDynFunc,
nsIDOMNode* aContextNode,
PRInt32 aContextPos, PRInt32 aContextSize);
/**
* Recalculate the MDG.
*
* @param aChangedNodes Returns the nodes that was changed during recalculation.
*/
nsresult Recalculate(nsXFormsMDGSet& aChangedNodes);
/**
* Rebuilds the MDG.
*/
nsresult Rebuild();
/**
* Clears all information in the MDG.
*/
void Clear();
/**
* Clears all Dispatch flags.
*/
void ClearDispatchFlags();
/**
* Mark a node as changed.
*
* @param aContextNode The node to be marked.
*/
nsresult MarkNodeAsChanged(nsIDOMNode* aContextNode);
/**
* Set the value of a node. (used by nsXFormsMDG)
* @param aContextNode The node to set the value for
* @param aNodeValue The value
* @param aMarkNode Mark node as changed?
*/
nsresult SetNodeValue(nsIDOMNode* aContextNode, nsAString& aNodeValue, PRBool aMarkNode = PR_FALSE);
/**
* Get the value of a node. (used by nsXFormsMDG)
* @param aContextNode The node to get the value for
* @param aNodeValue The value of the node
*/
nsresult GetNodeValue(nsIDOMNode* aContextNode, nsAString& aNodeValue);
PRBool IsConstraint(nsIDOMNode* aContextNode);
PRBool IsValid(nsIDOMNode* aContextNode);
PRBool ShouldDispatchValid(nsIDOMNode* aContextNode);
PRBool IsReadonly(nsIDOMNode* aContextNode);
PRBool ShouldDispatchReadonly(nsIDOMNode* aContextNode);
PRBool IsRelevant(nsIDOMNode* aContextNode);
PRBool ShouldDispatchRelevant(nsIDOMNode* aContextNode);
PRBool IsRequired(nsIDOMNode* aContextNode);
PRBool ShouldDispatchRequired(nsIDOMNode* aContextNode);
PRBool ShouldDispatchValueChanged(nsIDOMNode* aContextNode);
};

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

@ -0,0 +1,781 @@
/* -*- 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
* Novell, Inc.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Allan Beaufour <abeaufour@novell.com>
* David Landwehr <dlandwehr@novell.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 "nsXFormsMDGEngine.h"
#include "nsXFormsMDG.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMXPathExpression.h"
#include "nsIDOMXPathResult.h"
#include "nsDeque.h"
#ifdef DEBUG
// #define DEBUG_XF_MDG
#endif
/* ------------------------------------ */
/* --------- nsXFormsMDGNode ---------- */
/* ------------------------------------ */
MOZ_DECL_CTOR_COUNTER(nsXFormsMDGNode)
nsXFormsMDGNode::nsXFormsMDGNode(nsIDOMNode* aNode, const ModelItemPropName aType)
: mDirty (PR_TRUE), mHasExpr(PR_FALSE), mContextNode(aNode), mCount(0), mType(aType),
mContextSize(0), mContextPosition(0), mDynFunc(PR_FALSE), mNext(nsnull)
{
MOZ_COUNT_CTOR(nsXFormsMDGNode);
}
nsXFormsMDGNode::~nsXFormsMDGNode()
{
MOZ_COUNT_DTOR(nsXFormsMDGNode);
}
void
nsXFormsMDGNode::SetExpression(nsIDOMXPathExpression* aExpression, PRBool aDynFunc,
PRInt32 aContextPosition, PRInt32 aContextSize)
{
mHasExpr = PR_TRUE;
mDynFunc = aDynFunc;
mExpression = aExpression;
mContextPosition = aContextPosition;
mContextSize = aContextSize;
}
PRBool
nsXFormsMDGNode::HasExpr() const
{
return mHasExpr;
}
PRBool
nsXFormsMDGNode::IsDirty() const
{
// A node is always dirty, if it depends on a dynamic function.
return mDirty || mDynFunc;
}
void
nsXFormsMDGNode::MarkDirty()
{
mDirty = PR_TRUE;
}
void
nsXFormsMDGNode::MarkClean()
{
mDirty = PR_FALSE;
}
/* ------------------------------------ */
/* -------- nsXFormsMDGEngine --------- */
/* ------------------------------------ */
MOZ_DECL_CTOR_COUNTER(nsXFormsMDGEngine)
nsXFormsMDGEngine::nsXFormsMDGEngine(nsXFormsMDG* aOwner)
: mNodesInGraph(0), mOwner(aOwner)
{
MOZ_COUNT_CTOR(nsXFormsMDGEngine);
}
nsXFormsMDGEngine::~nsXFormsMDGEngine()
{
mNodeToMDG.Enumerate(DeleteLinkedNodes, nsnull);
MOZ_COUNT_DTOR(nsXFormsMDGEngine);
}
PLDHashOperator
nsXFormsMDGEngine::DeleteLinkedNodes(nsISupports *aKey, nsAutoPtr<nsXFormsMDGNode>& aNode, void* aArg)
{
if (!aNode) {
NS_WARNING("nsXFormsMDGEngine::DeleteLinkedNodes() called with aNode == nsnull!");
return PL_DHASH_STOP;
}
nsXFormsMDGNode* temp;
nsXFormsMDGNode* next = aNode->mNext;
while (next) {
temp = next;
next = next->mNext;
delete temp;
}
return PL_DHASH_NEXT;
}
nsresult
nsXFormsMDGEngine::Init()
{
nsresult rv = NS_ERROR_FAILURE;
if (mNodeToFlag.Init() && mNodeToMDG.Init()) {
rv = NS_OK;
}
return rv;
}
nsXFormsMDGNode*
nsXFormsMDGEngine::GetNode(nsIDOMNode* aDomNode, ModelItemPropName aType, PRBool aCreate)
{
nsIDOMNode* nodeKey = aDomNode;
nsXFormsMDGNode* nd = nsnull;
#ifdef DEBUG_XF_MDG
printf("nsXFormsMDGEngine::GetNode(aDomNode=%p, aType=%d, aCreate=%d)\n", (void*) nodeKey, aType, aCreate);
#endif
// Find correct type
if (mNodeToMDG.Get(nodeKey, &nd)) {
while (nd && nd->mType != aType) {
nd = nd->mNext;
}
}
// Eventually create node
if (!nd && aCreate){
nd = new nsXFormsMDGNode(nodeKey, aType);
if (!nd) {
NS_ERROR("Could not allocate room for new nsXFormsMDGNode");
return nsnull;
}
#ifdef DEBUG_XF_MDG
printf("\tNode not found, create new MDGNode '%p'\n", (void*) nd);
#endif
// Link to existing node
nsXFormsMDGNode* nd_exists;
if (mNodeToMDG.Get(nodeKey, &nd_exists)) {
while (nd_exists->mNext) {
nd_exists = nd_exists->mNext;
}
#ifdef DEBUG_XF_MDG
printf("\tLinking to existing MDGNode '%p'\n", (void*) nd_exists);
#endif
nd_exists->mNext = nd;
} else {
nodeKey->AddRef();
if (!mNodeToMDG.Put(nodeKey, nd)) {
delete nd;
NS_ERROR("Could not insert new node in HashTable!");
return nsnull;
}
}
mNodesInGraph++;
}
return nd;
}
nsresult
nsXFormsMDGEngine::Insert(nsIDOMNode* aContextNode, nsIDOMXPathExpression* aExpression,
const nsXFormsMDGSet* aDependencies, PRBool aDynFunc,
PRInt32 aContextPos, PRInt32 aContextSize,
ModelItemPropName aType, ModelItemPropName aDepType)
{
NS_ENSURE_ARG(aContextNode);
NS_ENSURE_ARG(aExpression);
#ifdef DEBUG_XF_MDG
nsAutoString nodename;
aContextNode->GetNodeName(nodename);
printf("nsXFormsMDGEngine::Insert(aContextNode=%s, aExpression=n/a, aDependencies=|%d|,\n",
NS_ConvertUCS2toUTF8(nodename).get(),
aDependencies->Count());
printf(" aContextPos=%d, aContextSize=%d, aType=%d, aDepType=%d,\n",
aContextPos, aContextSize, aType, aDepType);
printf(" aDynFunc=%d)\n",
aDynFunc);
#endif
nsXFormsMDGNode* newnode = GetNode(aContextNode, aType);
if (!newnode) {
return NS_ERROR_OUT_OF_MEMORY;
}
if (newnode->HasExpr()) {
// MIP already in the graph. That is. there is already a MIP of the same
// type for this node, which is illegal.
// Example: <bind nodeset="x" required="true()" required="false()"/>
return NS_ERROR_ABORT;
}
newnode->SetExpression(aExpression, aDynFunc, aContextPos, aContextSize);
// Add dependencies
if (aDependencies) {
nsCOMPtr<nsIDOMNode> dep_domnode;
nsXFormsMDGNode* dep_gnode;
for (PRInt32 i = 0; i < aDependencies->Count(); ++i) {
dep_domnode = aDependencies->GetNode(i);
if (!dep_domnode) {
return NS_ERROR_NULL_POINTER;
}
dep_gnode = GetNode(dep_domnode, aDepType);
if (!dep_gnode) {
return NS_ERROR_OUT_OF_MEMORY;
}
if (aType == aDepType && dep_gnode->mContextNode == aContextNode) {
// Reference to itself, ignore
continue;
}
dep_gnode->mSuc.AppendElement(newnode);
newnode->mCount++;
}
}
return NS_OK;
}
PLDHashOperator
nsXFormsMDGEngine::AddStartNodes(nsISupports *aKey, nsXFormsMDGNode* aNode, void* aDeque)
{
#ifdef DEBUG_XF_MDG
printf("nsXFormsMDGEngine::AddStartNodes(aKey=n/a, aNode=%p, aDeque=%p)\n", (void*) aNode, aDeque);
#endif
nsDeque* deque = NS_STATIC_CAST(nsDeque*, aDeque);
if (!deque) {
NS_ERROR("nsXFormsMDGEngine::AddStartNodes called with NULL aDeque");
return PL_DHASH_STOP;
}
while (aNode) {
if (aNode->mCount == 0) {
// Is it not possible to check error condition?
deque->Push(aNode);
}
aNode = aNode->mNext;
}
return PL_DHASH_NEXT;
}
nsresult
nsXFormsMDGEngine::Rebuild()
{
#ifdef DEBUG_XF_MDG
printf("nsXFormsMDGEngine::Rebuild()\n");
#endif
nsresult rv = NS_OK;
mJustRebuilt = PR_TRUE;
mFirstCalculate = PR_FALSE;
mGraph.Clear();
mNodeToFlag.Clear();
nsDeque sortedNodes(nsnull);
#ifdef DEBUG_XF_MDG
printf("\tmNodesInGraph: %d\n", mNodesInGraph);
printf("\tmNodeToMDG: %d\n", mNodeToMDG.Count());
printf("\tmNodeToFlag: %d\n", mNodeToFlag.Count());
#endif
// Initial scan for nsXFormsMDGNodes with no dependencies (count == 0)
PRUint32 entries = mNodeToMDG.EnumerateRead(AddStartNodes, &sortedNodes);
if (entries != mNodeToMDG.Count()) {
return NS_ERROR_OUT_OF_MEMORY;
}
#ifdef DEBUG_XF_MDG
printf("\tStartNodes: %d\n", sortedNodes.GetSize());
#endif
nsXFormsMDGNode* node;
while ((node = NS_STATIC_CAST(nsXFormsMDGNode*, sortedNodes.Pop()))) {
for (PRInt32 i = 0; i < node->mSuc.Count(); ++i) {
nsXFormsMDGNode* sucNode = NS_STATIC_CAST(nsXFormsMDGNode*, node->mSuc[i]);
NS_ASSERTION(sucNode, "XForms: NULL successor node");
sucNode->mCount--;
if (sucNode->mCount == 0) {
sortedNodes.Push(sucNode);
}
}
node->MarkDirty();
if (!mGraph.AppendElement(node)) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
if (mGraph.Count() != mNodesInGraph) {
NS_WARNING("XForms: There are loops in the MDG\n");
rv = NS_ERROR_ABORT;
}
mNodesInGraph = 0;
return rv;
}
void
nsXFormsMDGEngine::Clear() {
#ifdef DEBUG_XF_MDG
printf("nsXFormsMDGEngine::Clear()\n");
#endif
mNodeToMDG.Enumerate(DeleteLinkedNodes, nsnull);
mNodeToMDG.Clear();
mNodeToFlag.Clear();
mGraph.Clear();
mNodesInGraph = 0;
}
PLDHashOperator
nsXFormsMDGEngine::AndFlag(nsISupports *aKey, PRUint16& aFlag, void* aMask)
{
PRUint16* andMask = NS_STATIC_CAST(PRUint16*, aMask);
if (!andMask) {
return PL_DHASH_STOP;
}
aFlag &= *andMask;
return PL_DHASH_NEXT;
}
PRBool
nsXFormsMDGEngine::AndFlags(PRUint16 aAndMask)
{
PRUint32 entries = mNodeToFlag.Enumerate(AndFlag, &aAndMask);
return (entries == mNodeToFlag.Count()) ? PR_TRUE : PR_FALSE;
}
PRUint16
nsXFormsMDGEngine::GetFlag(nsIDOMNode* aDomNode)
{
PRUint16 flag = MDG_FLAG_DEFAULT | (mJustRebuilt && mFirstCalculate ? MDG_FLAG_INITIAL_DISPATCH : 0);
// If node is found, flag is modified, if not flag is untouched
mNodeToFlag.Get(aDomNode, &flag);
return flag;
}
void
nsXFormsMDGEngine::SetFlag(nsIDOMNode* aDomNode, PRUint16 aFlag)
{
nsIDOMNode *nodeKey = aDomNode;
nodeKey->AddRef();
mNodeToFlag.Put(nodeKey, aFlag);
}
void
nsXFormsMDGEngine::OrFlag(nsIDOMNode* aDomNode, PRInt16 aFlag)
{
PRUint16 fl = GetFlag(aDomNode);
fl |= aFlag;
SetFlag(aDomNode, fl);
}
void
nsXFormsMDGEngine::SetFlagBits(nsIDOMNode* aDomNode, PRUint16 aBits, PRBool aOn)
{
PRUint32 fl = GetFlag(aDomNode);
if (aOn) {
fl |= aBits;
} else {
fl &= ~aBits;
}
SetFlag(aDomNode, fl);
}
nsresult
nsXFormsMDGEngine::BooleanExpression(nsXFormsMDGNode* aNode, PRBool& state)
{
NS_ENSURE_ARG_POINTER(aNode);
// TODO: Use aNode->contextPosition and aNode->contextSize!
nsISupports* retval;
nsresult rv;
rv = aNode->mExpression->Evaluate(aNode->mContextNode, nsIDOMXPathResult::BOOLEAN_TYPE, nsnull, &retval);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMXPathResult> xpath_res = do_QueryInterface(retval);
NS_ENSURE_TRUE(xpath_res, NS_ERROR_FAILURE);
rv = xpath_res->GetBooleanValue(&state);
return rv;
}
nsresult
nsXFormsMDGEngine::ComputeMIP(PRUint16 aStateFlag, PRUint16 aDispatchFlag, nsXFormsMDGNode* aNode, PRBool& aDidChange)
{
NS_ENSURE_ARG_POINTER(aNode);
PRUint32 word = GetFlag(aNode->mContextNode);
PRBool state;
nsresult rv = BooleanExpression(aNode, state);
NS_ENSURE_SUCCESS(rv, rv);
PRBool cstate = ((word & aStateFlag) != 0) ? PR_TRUE : PR_FALSE;
if (state) {
word |= aStateFlag;
} else {
word &= ~aStateFlag;
}
aDidChange = (state != cstate) ? PR_TRUE : PR_FALSE;
if (aDidChange) {
word |= aDispatchFlag;
}
SetFlag(aNode->mContextNode, word);
return NS_OK;
}
nsresult
nsXFormsMDGEngine::ComputeMIPWithInheritance(PRUint16 aStateFlag, PRUint16 aDispatchFlag, PRUint16 aInheritanceFlag, nsXFormsMDGNode* aNode, nsXFormsMDGSet& aSet)
{
nsresult rv;
PRBool didChange;
rv = ComputeMIP(aStateFlag, aDispatchFlag, aNode, didChange);
NS_ENSURE_SUCCESS(rv, rv);
if (didChange) {
PRUint16 flag = GetFlag(aNode->mContextNode);
PRBool state = (flag & aStateFlag != 0) ? PR_TRUE : PR_FALSE;
if ( (aStateFlag == MDG_FLAG_READONLY && (flag & aInheritanceFlag) == 0)
|| (aStateFlag == MDG_FLAG_RELEVANT && (flag & aInheritanceFlag) > 0) )
{
NS_ENSURE_TRUE(aSet.AddNode(aNode->mContextNode), NS_ERROR_FAILURE);
rv = AttachInheritance(aSet, aNode->mContextNode, state, aStateFlag);
}
}
return NS_OK;
}
nsresult
nsXFormsMDGEngine::AttachInheritance(nsXFormsMDGSet& aSet, nsIDOMNode* aSrc, PRBool aState, PRUint16 aStateFlag)
{
NS_ENSURE_ARG(aSrc);
nsCOMPtr<nsIDOMNode> node;
PRUint32 flag;
PRBool cstate;
nsresult rv;
PRBool updateNode = PR_FALSE;
nsCOMPtr<nsIDOMNodeList> childList;
rv = aSrc->GetChildNodes(getter_AddRefs(childList));
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 childCount;
rv = childList->GetLength(&childCount);
NS_ENSURE_SUCCESS(rv, rv);
for (PRUint32 i = 0; i < childCount; i++) {
rv = childList->Item(i, getter_AddRefs(node));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
flag = GetFlag(node);
cstate = ((flag & aStateFlag) != 0) ? PR_TRUE : PR_FALSE;
if (aStateFlag == MDG_FLAG_RELEVANT) {
if (aState == PR_FALSE) { // The nodes are getting irrelevant
if ((flag & MDG_FLAG_INHERITED_RELEVANT) != 0 && cstate) {
flag &= ~MDG_FLAG_INHERITED_RELEVANT;
flag |= MDG_FLAG_DISPATCH_RELEVANT_CHANGED;
updateNode = PR_TRUE;
}
} else { // The nodes are becoming relevant
if (cstate) {
flag |= MDG_FLAG_DISPATCH_RELEVANT_CHANGED; // Relevant has changed from inheritance
flag |= MDG_FLAG_INHERITED_RELEVANT; // Clear the flag for inheritance
updateNode = PR_TRUE;
}
}
} else if (aStateFlag == MDG_FLAG_READONLY) {
if (aState) { // The nodes are getting readonly
if ((flag & MDG_FLAG_INHERITED_READONLY) == 0 && cstate == PR_FALSE) {
flag |= MDG_FLAG_INHERITED_READONLY | MDG_FLAG_DISPATCH_READONLY_CHANGED;
updateNode = PR_TRUE;
}
} else { // The nodes are getting readwrite
if (cstate) {
flag |= MDG_FLAG_DISPATCH_READONLY_CHANGED;
flag &= ~MDG_FLAG_INHERITED_READONLY;
updateNode = PR_TRUE;
}
}
}
if (updateNode) {
SetFlag(node, flag);
rv = AttachInheritance(aSet, node, aState, aStateFlag);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(aSet.AddNode(node), NS_ERROR_FAILURE);
updateNode = PR_FALSE;
}
}
return NS_OK;
}
nsresult
nsXFormsMDGEngine::Calculate(nsXFormsMDGSet& aValueChanged)
{
#ifdef DEBUG_XF_MDG
printf("nsXFormsMDGEngine::Calculcate(aValueChanged=|%d|)\n", aValueChanged.Count());
#endif
NS_ENSURE_TRUE(aValueChanged.AddSet(mMarkedNodes), NS_ERROR_OUT_OF_MEMORY);
mMarkedNodes.Clear();
PRBool res = PR_TRUE;
mFirstCalculate = mJustRebuilt;
#ifdef DEBUG_XF_MDG
printf("\taValueChanged: %d\n", aValueChanged.Count());
printf("\tmNodeToMDG: %d\n", mNodeToFlag.Count());
printf("\tmNodeToFlag: %d\n", mNodeToFlag.Count());
printf("\tGraph nodes: %d\n", mGraph.Count());
#endif
// Go through all dirty nodes in the graph
nsresult rv;
nsXFormsMDGNode* g;
for (PRInt32 i = 0; i < mGraph.Count(); ++i) {
g = NS_STATIC_CAST(nsXFormsMDGNode*, mGraph[i]);
if (!g) {
NS_WARNING("nsXFormsMDGEngine::Calculcate(): Empty node in graph!!!");
continue;
}
#ifdef DEBUG_XF_MDG
nsAutoString domNodeName;
g->mContextNode->GetNodeName(domNodeName);
printf("\tNode #%d: This=%p, Dirty=%d, DynFunc=%d, Type=%d, Count=%d, Suc=%d, CSize=%d, CPos=%d, Next=%p, domnode=%s\n",
i, (void*) g, g->IsDirty(), g->mDynFunc, g->mType, g->mCount, g->mSuc.Count(),
g->mContextSize, g->mContextPosition, (void*) g->mNext, NS_ConvertUCS2toUTF8(domNodeName).get());
#endif
// Ignore node if it is not dirty
if (!g->IsDirty()) {
continue;
}
PRBool constraint = PR_TRUE;
// Find MIP-type and handle it accordingly
switch (g->mType) {
case eModel_calculate:
if (g->HasExpr()) {
nsISupports* retval;
rv = g->mExpression->Evaluate(g->mContextNode, nsIDOMXPathResult::STRING_TYPE, nsnull, &retval);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMXPathResult> xpath_res = do_QueryInterface(retval);
NS_ENSURE_TRUE(xpath_res, NS_ERROR_OUT_OF_MEMORY);
nsAutoString nodeval;
rv = xpath_res->GetStringValue(nodeval);
NS_ENSURE_SUCCESS(rv, rv);
rv = mOwner->SetNodeValue(g->mContextNode, nodeval);
if (NS_SUCCEEDED(rv)) {
NS_ENSURE_TRUE(aValueChanged.AddNode(g->mContextNode), NS_ERROR_FAILURE);
}
}
OrFlag(g->mContextNode, MDG_FLAG_DISPATCH_VALUE_CHANGED);// | MDG_FLAG_DISPATCH_READONLY_CHANGED | MDG_FLAG_DISPATCH_VALID_CHANGED | MDG_FLAG_DISPATCH_RELEVANT_CHANGED);
break;
case eModel_constraint:
if (g->HasExpr()) {
rv = BooleanExpression(g, constraint);
NS_ENSURE_SUCCESS(rv, rv);
}
// TODO: Schema validity should be checked here
if ((GetFlag(g->mContextNode) & MDG_FLAG_CONSTRAINT) > 0 != constraint) {
SetFlagBits(g->mContextNode, MDG_FLAG_CONSTRAINT, constraint);
SetFlagBits(g->mContextNode, MDG_FLAG_DISPATCH_VALID_CHANGED, PR_TRUE);
NS_ENSURE_TRUE(aValueChanged.AddNode(g->mContextNode), NS_ERROR_FAILURE);
}
break;
case eModel_readonly:
if (g->HasExpr()) {
rv = ComputeMIPWithInheritance(MDG_FLAG_READONLY, MDG_FLAG_DISPATCH_READONLY_CHANGED, MDG_FLAG_INHERITED_READONLY, g, aValueChanged);
NS_ENSURE_SUCCESS(rv, rv);
}
break;
case eModel_relevant:
if (g->HasExpr()) {
rv = ComputeMIPWithInheritance(MDG_FLAG_RELEVANT, MDG_FLAG_DISPATCH_RELEVANT_CHANGED, MDG_FLAG_INHERITED_RELEVANT, g, aValueChanged);
NS_ENSURE_SUCCESS(rv, rv);
}
break;
case eModel_required:
PRBool didChange;
rv = ComputeMIP(MDG_FLAG_REQUIRED, MDG_FLAG_DISPATCH_REQUIRED_CHANGED, g, didChange);
NS_ENSURE_SUCCESS(rv, rv);
if (g->HasExpr() && didChange) {
NS_ENSURE_TRUE(aValueChanged.AddNode(g->mContextNode), NS_ERROR_FAILURE);
}
break;
default:
NS_ERROR("There was no expression which matched\n");
res = PR_FALSE;
break;
}
// Mark successors dirty
nsXFormsMDGNode* sucnode;
for (PRInt32 j = 0; j < g->mSuc.Count(); ++j) {
sucnode = NS_STATIC_CAST(nsXFormsMDGNode*, g->mSuc[j]);
if (!sucnode) {
NS_ERROR("nsXFormsMDGEngine::Calculate(): Node has NULL successor!");
return NS_ERROR_FAILURE;
}
sucnode->MarkDirty();
}
g->MarkClean();
}
aValueChanged.MakeUnique();
#ifdef DEBUG_XF_MDG
printf("\taValueChanged: %d\n", aValueChanged.Count());
printf("\tmNodeToMDG: %d\n", mNodeToFlag.Count());
printf("\tmNodeToFlag: %d\n", mNodeToFlag.Count());
printf("\tGraph nodes: %d\n", mGraph.Count());
#endif
return res;
}
// TODO: This function needs to be called
nsresult
nsXFormsMDGEngine::MarkNode(nsIDOMNode* aDomNode)
{
SetFlagBits(aDomNode, MDG_FLAG_ALL_DISPATCH, PR_TRUE);
nsXFormsMDGNode* n = GetNode(aDomNode, eModel_calculate);
if (n) {
n->MarkDirty();
}
// Add constraint to trigger validation of node
n = GetNode(aDomNode, eModel_constraint, PR_FALSE);
if (!n) {
n = GetNode(aDomNode, eModel_constraint, PR_TRUE);
if (!n) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ENSURE_TRUE(mGraph.AppendElement(n), NS_ERROR_OUT_OF_MEMORY);
}
n->MarkDirty();
NS_ENSURE_TRUE(mMarkedNodes.AddNode(aDomNode), NS_ERROR_FAILURE);
return NS_OK;
}
PRBool
nsXFormsMDGEngine::ClearDispatchFlags()
{
mJustRebuilt = PR_FALSE;
return AndFlags(MDG_FLAGMASK_NOT_DISPATCH);
}
nsresult
nsXFormsMDGEngine::Invalidate()
{
nsXFormsMDGNode* g;
for (PRInt32 i = 0; i < mGraph.Count(); ++i) {
g = NS_STATIC_CAST(nsXFormsMDGNode*, mGraph[i]);
NS_ENSURE_TRUE(g, NS_ERROR_FAILURE);
g->MarkDirty();
}
return NS_OK;
}
PRBool
nsXFormsMDGEngine::TestAndClear(nsIDOMNode* aDomNode, PRUint16 aFlag)
{
PRUint16 fl = GetFlag(aDomNode);
PRUint16 test = fl & aFlag;
fl &= ~aFlag;
SetFlag(aDomNode, fl);
return (test != 0) ? PR_TRUE : PR_FALSE;
}
PRBool
nsXFormsMDGEngine::TestAndSet(nsIDOMNode* aDomNode, PRUint16 aFlag)
{
PRUint16 fl = GetFlag(aDomNode);
PRUint16 test = fl & aFlag;
fl |= aFlag;
SetFlag(aDomNode, fl);
return (test != 0) ? PR_TRUE : PR_FALSE;
}
PRBool
nsXFormsMDGEngine::Test(nsIDOMNode* aDomNode, PRUint16 aFlag)
{
PRUint16 fl = GetFlag(aDomNode);
PRUint16 test = fl & aFlag;
return (test != 0) ? PR_TRUE : PR_FALSE;
}

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

@ -0,0 +1,430 @@
/* -*- 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
* Novell, Inc.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Allan Beaufour <abeaufour@novell.com>
* David Landwehr <dlandwehr@novell.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 __NSXFORMSMDGENGINE__
#define __NSXFORMSMDGENGINE__
#include "nscore.h"
#include "nsCOMPtr.h"
#include "nsVoidArray.h"
#include "nsClassHashtable.h"
#include "nsDataHashtable.h"
#include "nsIDOMNode.h"
#include "nsXFormsTypes.h"
#include "nsXFormsMDGSet.h"
class nsIDOMXPathExpression;
class nsXFormsMDG;
/**
* Flags, etc.
*
* TODO: Convert to enum?
*/
const PRUint16 MDG_FLAG_READONLY = 1 << 1;
const PRUint16 MDG_FLAG_CONSTRAINT = 1 << 2;
const PRUint16 MDG_FLAG_RELEVANT = 1 << 3;
const PRUint16 MDG_FLAG_REQUIRED = 1 << 4;
const PRUint16 MDG_FLAG_SCHEMA_VALID = 1 << 5;
const PRUint16 MDG_FLAG_VALID = 1 << 6;
const PRUint16 MDG_FLAG_INHERITED_RELEVANT = 1 << 7;
const PRUint16 MDG_FLAG_INHERITED_READONLY = 1 << 8;
const PRUint16 MDG_FLAG_DISPATCH_VALUE_CHANGED = 1 << 9;
const PRUint16 MDG_FLAG_DISPATCH_READONLY_CHANGED = 1 << 10;
const PRUint16 MDG_FLAG_DISPATCH_VALID_CHANGED = 1 << 11;
const PRUint16 MDG_FLAG_DISPATCH_RELEVANT_CHANGED = 1 << 12;
const PRUint16 MDG_FLAG_DISPATCH_REQUIRED_CHANGED = 1 << 13;
const PRUint16 MDG_FLAG_DISPATCH_CONSTRAINT_CHANGED = 1 << 14;
const PRUint16 MDG_FLAGMASK_NOT_DISPATCH = ~(MDG_FLAG_DISPATCH_VALUE_CHANGED | \
MDG_FLAG_DISPATCH_READONLY_CHANGED |\
MDG_FLAG_DISPATCH_VALID_CHANGED |\
MDG_FLAG_DISPATCH_RELEVANT_CHANGED |\
MDG_FLAG_DISPATCH_REQUIRED_CHANGED |\
MDG_FLAG_DISPATCH_CONSTRAINT_CHANGED);
const PRUint16 MDG_FLAG_DEFAULT = MDG_FLAG_CONSTRAINT | \
MDG_FLAG_RELEVANT |\
MDG_FLAG_INHERITED_RELEVANT;
const PRUint16 MDG_FLAG_INITIAL_DISPATCH = MDG_FLAG_DISPATCH_READONLY_CHANGED |\
MDG_FLAG_DISPATCH_VALID_CHANGED |\
MDG_FLAG_DISPATCH_RELEVANT_CHANGED |\
MDG_FLAG_DISPATCH_REQUIRED_CHANGED;
const PRUint16 MDG_FLAG_ALL_DISPATCH = MDG_FLAG_DISPATCH_READONLY_CHANGED |\
MDG_FLAG_DISPATCH_VALID_CHANGED |\
MDG_FLAG_DISPATCH_RELEVANT_CHANGED |\
MDG_FLAG_DISPATCH_REQUIRED_CHANGED |\
MDG_FLAG_DISPATCH_VALUE_CHANGED |\
MDG_FLAG_DISPATCH_CONSTRAINT_CHANGED;
/**
* Data structure for nodes in the graph.
*
* There is one node per type (calculate, readonly, etc) for each nsIDOMNode.
* All nsXFormsMDGNodes for same nsIDOMNode are linked together via 'next'.
*/
class nsXFormsMDGNode {
private:
/** Dirty flag */
PRBool mDirty;
/** Does this node have an XPath expression attached to it */
PRBool mHasExpr;
public:
/** Pointer to the nsIDOMNode */
nsCOMPtr<nsIDOMNode> mContextNode;
/** The XPath expression for this node */
nsCOMPtr<nsIDOMXPathExpression> mExpression;
/** List of nodes that depend on this node */
nsVoidArray mSuc;
/** Number of nodes that this node depends on */
unsigned int mCount;
/** The type */
ModelItemPropName mType;
/** (XPath) Context size for this node */
int mContextSize;
/** (XPath) Position for this node */
int mContextPosition;
/** Does expression use dynamic functions */
PRBool mDynFunc;
/** Pointer to next nsXFormsMDGNode with same nsIDOMNode, but different type */
nsXFormsMDGNode* mNext;
/**
* Constructor.
*
* @param aNode The context node
* @param aType The type of node (calculate, readonly, etc.)
*/
nsXFormsMDGNode(nsIDOMNode* aNode, const ModelItemPropName aType);
/** Destructor */
~nsXFormsMDGNode();
/**
* Sets the XPath expression for the node.
*
* @param aExpression The XPath expression
* @param aDynFunc Whether expression uses dynamic functions
* @param aContextPosition The context position for the expression
* @param aContextSize The context size for the expression
*/
void SetExpression(nsIDOMXPathExpression* aExpression, PRBool aDynFunc,
PRInt32 aContextPosition, PRInt32 aContextSize);
/** Does node have an expression? */
PRBool HasExpr() const;
/** Is node dirty? */
PRBool IsDirty() const;
/* Mark node clean */
void MarkClean();
/* Mark node dirty */
void MarkDirty();
};
/**
* The Multi Dependency Graph (MDG) Engine.
*
* This class handles all the necessary logic to create and maintain the MDG,
* and update the instance data accordingly.
*
* A bit about the graph:
* As specified in the spec., one node (nsXFormsMDGNode) is created in the graph for
* each of the attributes (readonly, calculate, etc.) for a nsIDOMNode. These graph
* nodes are owned by the mNodeToMDG hash table, which maps from a nsIDOMNode to
* the first node in a single-linked list (mNext) of nodes for the same nsIDOMNode.
*/
class nsXFormsMDGEngine {
protected:
/**
* Maps from nsIDOMNode to nsXFormsMDGNode(s)
*/
nsClassHashtable<nsISupportsHashKey, nsXFormsMDGNode> mNodeToMDG;
/**
* Maps from nsIDOMNode to flag (MDG_FLAG_*)
*/
nsDataHashtable<nsISupportsHashKey, PRUint16> mNodeToFlag;
/**
* True when Rebuild() has been run, but not ClearDispatchFlags()
*/
PRBool mJustRebuilt;
/**
* True when last Calculate() was run when mJustRebuilded was true.
*/
PRBool mFirstCalculate;
/** The actual MDG */
nsVoidArray mGraph;
/** Set of nodes that are marked as changed, and should be included in recalculation */
nsXFormsMDGSet mMarkedNodes;
/** Number of nodes in the graph */
PRInt32 mNodesInGraph;
/** Hidden copy constructor */
nsXFormsMDGEngine(nsXFormsMDGEngine&) {}
/**
* Used by Clear() and ~ to delete the linked nodes in mNodeToMDG, the hash table
* itself handles the main nodes.
*/
static PLDHashOperator PR_CALLBACK DeleteLinkedNodes(nsISupports *aKey, nsAutoPtr<nsXFormsMDGNode>& aNode, void* aArg);
/**
* Used by Rebuild() to find the start nodes for mGraph, that is nodes
* where mCount == 0.
*/
static PLDHashOperator PR_CALLBACK AddStartNodes(nsISupports *aKey, nsXFormsMDGNode* aNode, void* aDeque);
/**
* Used by AndFlags() to boolean AND all flags with aMask.
*/
static PLDHashOperator PR_CALLBACK AndFlag(nsISupports *aKey, PRUint16& aFlag, void* aMask);
/**
* Retrieve a node from the graph.
*
* @param aDomNode The DOM node to retrieve
* @param aType The type to retrieve (readonly, calculate, etc)
* @param aCreate Create the node and insert it into the graph if it does not exist?
* @return The node, nsnull if not found and aCreate != PR_TRUE
*/
nsXFormsMDGNode* GetNode(nsIDOMNode* aDomNode, ModelItemPropName aType, PRBool aCreate = PR_TRUE);
/**
* Sets the flag for a node.
*
* @param aDomNode The node
* @param aFlag The flag
*/
void SetFlag(nsIDOMNode* aDomNode, PRUint16 aFlag);
/**
* Boolean OR the existing flag on the node with a new flag
*
* @param aDomNode The node
* @param aFlag The new flag
*/
void OrFlag(nsIDOMNode* aDomNode, PRInt16 aFlag);
/**
* Retrieve the flag for a node.
*
* @param aDomNode The node
* @return The flag
*/
PRUint16 GetFlag(nsIDOMNode* aDomNode);
/**
* Sets a bit in the flag for a node
*
* @param aDomNode The node
* @param aBit The bit position to set
* @param aOn The bit value
*/
void SetFlagBits(nsIDOMNode* aDomNode, PRUint16 aBit, PRBool aOn);
/**
* Boolean AND all flags with a mask.
*
* @param aAndMask The mask
* @return Did operation succeed?
*/
PRBool AndFlags(PRUint16 aAndMask);
/**
* Evaluates the expression for the given node and returns the boolean result.
*
* @param aNode The node to evaluate
* @param res The result of the evaluation
*/
nsresult BooleanExpression(nsXFormsMDGNode* aNode, PRBool& res);
/**
* Compute MIP value for node types with boolean result (all except calculate)
*
* @param aStateFlag The flag for the type of MIP
* @param aDispatchFlag The dispatch flag
* @param aNode The context node
* @param aDidChange Was the node changed?
*/
nsresult ComputeMIP(PRUint16 aStateFlag, PRUint16 aDispatchFlag, nsXFormsMDGNode* aNode, PRBool& aDidChange);
/**
* Same as ComputeMIP(), but also handles any inheritance of attributes.
*
* @param aStateFlag The flag for the type of MIP
* @param aDispatchFlag The dispatch flag
* @param aInheritanceFlag The inheritance flag for the type of MIP
* @param aNode The context node
* @param aSet Set of the nodes influenced by operation
*/
nsresult ComputeMIPWithInheritance(PRUint16 aStateFlag, PRUint16 aDispatchFlag, PRUint16 aInheritanceFlag, nsXFormsMDGNode* aNode, nsXFormsMDGSet& aSet);
/**
* Attaches inheritance to all children of a given node
*
* @param aSet Set of the nodes influenced by operation
* @param aSrc The node
* @param aState The state of the flag
* @param aStateFlag The flag
*/
nsresult AttachInheritance(nsXFormsMDGSet& aSet, nsIDOMNode* aSrc, PRBool aState, PRUint16 aStateFlag);
/** A pointer to the owner, used to access Get- and SetNodeValue() */
nsXFormsMDG* mOwner;
public:
/**
* Constructor
*
* @param aOwner Pointer to the owner
*/
nsXFormsMDGEngine(nsXFormsMDG* aOwner);
/**
* Destructor
*/
~nsXFormsMDGEngine();
/**
* Initializes the hash tables. Needs to be called before class is used!
*/
nsresult Init();
/**
* Inserts a MIP into the graph
*/
nsresult Insert(nsIDOMNode* aContextNode, nsIDOMXPathExpression* aExpression,
const nsXFormsMDGSet* aDependencies,
PRBool aDynFunc,
PRInt32 aContextPos, PRInt32 aContextSize,
ModelItemPropName aType = eModel_calculate,
ModelItemPropName aDeptype = eModel_calculate);
/**
* Rebuilds the MDG.
*
* Does this by doing a topological sort of all nodes in mNodeToMDG, and storing
* the result in mGraph.
*
* @note This has to be called before Calculate().
*/
nsresult Rebuild();
/**
* Removes all node information from engine
*/
void Clear();
/**
* Perform a calculation on all dirty nodes
*
* @param aValueChanged The nodes which were changed by operation.
*/
nsresult Calculate(nsXFormsMDGSet& aValueChanged);
/**
* Invalidate the information, ie. mark all nodes as dirty.
*/
nsresult Invalidate();
/**
* Get flag value for node and clear flag.
*
* @param aDomNode The node
* @param aFlag The flag
* @return The flag value
*/
PRBool TestAndClear(nsIDOMNode* aDomNode, PRUint16 aFlag);
/**
* Get flag value for node and set flag.
*
* @param aDomNode The node
* @param aFlag The flag
* @return The flag value
*/
PRBool TestAndSet(nsIDOMNode* aDomNode, PRUint16 aFlag);
/**
* Get flag value for node
*
* @param aDomNode The node
* @param aFlag The flag
* @return The flag value
*/
PRBool Test(nsIDOMNode* aDomNode, PRUint16 aFlag);
/**
* Clear dispatch flags for all nodes
*
* @return Did operation succeed?
*/
PRBool ClearDispatchFlags();
/**
* Make a node as changed, ie. include in next Calculate
*
* @param aDomNode The node
*/
nsresult MarkNode(nsIDOMNode* aDomNode);
};
#endif

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

@ -0,0 +1,97 @@
#include "nsXFormsMDGSet.h"
MOZ_DECL_CTOR_COUNTER(nsXFormsMDGSet)
nsXFormsMDGSet::nsXFormsMDGSet()
{
MOZ_COUNT_CTOR(nsXFormsMDGSet);
}
nsXFormsMDGSet::~nsXFormsMDGSet() {
Clear();
MOZ_COUNT_DTOR(nsXFormsMDGSet);
}
int
nsXFormsMDGSet::sortFunc(const void* aElement1, const void* aElement2, void* aData)
{
int res = 0;
if (aElement1 < aElement2)
res = -1;
if (aElement1 > aElement2)
res = 1;
return res;
}
void
nsXFormsMDGSet::Clear()
{
// Remove reference counters
nsISupports* node;
for (PRInt32 i = 0; i < array.Count(); ++i) {
node = NS_STATIC_CAST(nsISupports*, array[i]);
node->Release();
}
// Clear array
array.Clear();
}
void
nsXFormsMDGSet::MakeUnique()
{
array.Sort(sortFunc, nsnull);
// TODO: Assuming that moving element x, will delete x, and move list "one to the left",
// ie. x = x+1, x+1=x+2, ... etc.
// Is that correct?
PRInt32 pos = 0;
nsIDOMNode* node;
while (pos + 1 < array.Count()) {
if (array[pos] == array[pos + 1]) {
node = NS_STATIC_CAST(nsIDOMNode*, array[pos + 1]);
node->Release();
array.RemoveElementAt(pos + 1);
} else {
++pos;
}
}
}
PRInt32
nsXFormsMDGSet::Count() const
{
return array.Count();
}
PRBool
nsXFormsMDGSet::AddNode(nsIDOMNode* aDomNode)
{
if (!aDomNode) {
return PR_FALSE;
}
aDomNode->AddRef();
return array.AppendElement(aDomNode);
}
PRBool
nsXFormsMDGSet::AddSet(nsXFormsMDGSet& aSet)
{
nsIDOMNode* node;
for (PRInt32 i = 0; i < aSet.array.Count(); ++i) {
node = NS_STATIC_CAST(nsIDOMNode*, aSet.array[i]);
if (!AddNode(node)) {
return PR_FALSE;
}
}
return PR_TRUE;
}
nsIDOMNode*
nsXFormsMDGSet::GetNode(const PRInt32 aIndex) const {
return NS_STATIC_CAST(nsIDOMNode*, array[aIndex]);
}

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

@ -0,0 +1,110 @@
/* -*- 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
* Novell, Inc.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Allan Beaufour <abeaufour@novell.com>
* David Landwehr <dlandwehr@novell.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 __NSXFORMSMDGSET_H__
#define __NSXFORMSMDGSET_H__
#include "nsVoidArray.h"
#include "nsIDOMNode.h"
/**
* A simple "set" implementation. For now it is just a wrapper for nsVoidArray,
* but nsVoidArray can be changed if a more suitable structure is found.
*
* It is not a set, in that no two same nodes can exist. You need to call
* MakeUnique() manually for that to be true.
*
* The class owns the nsIDOMNodes that it stores, and manages the reference
* counters automatically.
*/
class nsXFormsMDGSet {
private:
/** The data structure */
nsVoidArray array;
/** The sorting function used by MakeUnique() */
static int sortFunc(const void* aElement1, const void* aElement2, void* aData);
public:
/** Constructor */
nsXFormsMDGSet();
/** Destructor */
~nsXFormsMDGSet();
/** Clears the struture (removes all stored data) */
void Clear();
/**
* Delete any duplicates (ie. make the set a set...).
*
* As a side effect, it also sorts the data structure by the data pointer in
* ascending order.
*/
void MakeUnique();
/** Returns the number of members */
PRInt32 Count() const;
/**
* Adds a node to the set.
*
* @param aDomNode The node to add.
* @return Did the storage succeed?
*/
PRBool AddNode(nsIDOMNode* aDomNode);
/**
* Adds all nodes from another set to this set
*
* @param aSet The set to add nodes from
* @return Did the operation succeed?
*/
PRBool AddSet(nsXFormsMDGSet& aSet);
/**
* Get a specific node from the set
*
* @param aIndex The position of the node to get
* @return The node
*/
nsIDOMNode* GetNode(const PRInt32 aIndex) const;
};
#endif

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

@ -0,0 +1,944 @@
/* -*- 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):
* Brian Ryner <bryner@brianryner.com>
* Allan Beaufour <abeaufour@novell.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 "nsXFormsModelElement.h"
#include "nsIXTFGenericElementWrapper.h"
#include "nsMemory.h"
#include "nsIDOMDocumentEvent.h"
#include "nsIDOMEvent.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMElement.h"
#include "nsIDOM3Node.h"
#include "nsIDOMNodeList.h"
#include "nsString.h"
#include "nsIDocument.h"
#include "nsXFormsAtoms.h"
#include "nsINameSpaceManager.h"
#include "nsIServiceManager.h"
#include "nsINodeInfo.h"
#include "nsIDOMDOMImplementation.h"
#include "nsIDOMXMLDocument.h"
#include "nsIDOMEventReceiver.h"
#include "nsIDOMXPathResult.h"
#include "nsIDOMXPathEvaluator.h"
#include "nsIDOMXPathNSResolver.h"
#include "nsIDOMXPathExpression.h"
#include "nsIDOM3EventTarget.h"
#include "nsIDOMEventGroup.h"
#include "nsIDOMNSUIEvent.h"
#include "nsIScriptGlobalObject.h"
#include "nsIContent.h"
#include "nsNetUtil.h"
#include "nsXFormsControl.h"
#include "nsXFormsTypes.h"
#include "nsXFormsXPathParser.h"
#include "nsXFormsXPathAnalyzer.h"
#include "nsXFormsInstanceElement.h"
#include "nsISchemaLoader.h"
#include "nsAutoPtr.h"
#ifdef DEBUG_beaufour
#include "nsIDOMSerializer.h"
#endif
static const nsIID sScriptingIIDs[] = {
NS_IDOMELEMENT_IID,
NS_IDOMEVENTTARGET_IID,
NS_IDOM3NODE_IID,
NS_IXFORMSMODELELEMENT_IID
};
struct EventData
{
const char *name;
PRBool canCancel;
PRBool canBubble;
};
static const EventData sModelEvents[] = {
{ "xforms-model-construct", PR_FALSE, PR_TRUE },
{ "xforms-model-construct-done", PR_FALSE, PR_TRUE },
{ "xforms-ready", PR_FALSE, PR_TRUE },
{ "xforms-model-destruct", PR_FALSE, PR_TRUE },
{ "xforms-rebuild", PR_TRUE, PR_TRUE },
{ "xforms-refresh", PR_TRUE, PR_TRUE },
{ "xforms-revalidate", PR_TRUE, PR_TRUE },
{ "xforms-recalculate", PR_TRUE, PR_TRUE },
{ "xforms-reset", PR_TRUE, PR_TRUE },
{ "xforms-binding-exception", PR_FALSE, PR_TRUE },
{ "xforms-link-exception", PR_FALSE, PR_TRUE },
{ "xforms-link-error", PR_FALSE, PR_TRUE },
{ "xforms-compute-exception", PR_FALSE, PR_TRUE }
};
static nsIAtom* sModelPropsList[eModel__count];
struct nsXFormsModelElement::ModelItemProperties
{
nsCOMPtr<nsIDOMXPathExpression> properties[eModel__count];
};
nsXFormsModelElement::nsXFormsModelElement()
: mElement(nsnull),
mSchemaCount(0)
{
}
NS_IMPL_ADDREF(nsXFormsModelElement)
NS_IMPL_RELEASE(nsXFormsModelElement)
NS_INTERFACE_MAP_BEGIN(nsXFormsModelElement)
NS_INTERFACE_MAP_ENTRY(nsIXTFElement)
NS_INTERFACE_MAP_ENTRY(nsIXTFGenericElement)
NS_INTERFACE_MAP_ENTRY(nsIXTFPrivate)
NS_INTERFACE_MAP_ENTRY(nsIXFormsModelElement)
NS_INTERFACE_MAP_ENTRY(nsISchemaLoadListener)
NS_INTERFACE_MAP_ENTRY(nsIWebServiceErrorHandler)
NS_INTERFACE_MAP_ENTRY(nsIDOMLoadListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXTFElement)
NS_INTERFACE_MAP_END
NS_IMETHODIMP
nsXFormsModelElement::OnDestroyed()
{
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mElement);
NS_ASSERTION(receiver, "xml elements must be event receivers");
nsCOMPtr<nsIDOMEventGroup> systemGroup;
receiver->GetSystemEventGroup(getter_AddRefs(systemGroup));
NS_ASSERTION(systemGroup, "system event group must exist");
nsCOMPtr<nsIDOM3EventTarget> targ = do_QueryInterface(mElement);
for (unsigned int i = 0; i < NS_ARRAY_LENGTH(sModelEvents); ++i) {
targ->RemoveGroupedEventListener(NS_ConvertUTF8toUTF16(sModelEvents[i].name),
this, PR_FALSE, systemGroup);
}
RemoveModelFromDocument();
mElement = nsnull;
return NS_OK;
}
void
nsXFormsModelElement::RemoveModelFromDocument()
{
// Find out if we are handling the model-construct-done for this document.
nsCOMPtr<nsIDOMDocument> domDoc;
mElement->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
nsIScriptGlobalObject *window = nsnull;
if (doc)
window = doc->GetScriptGlobalObject();
nsCOMPtr<nsIDOMEventTarget> targ = do_QueryInterface(window);
if (targ) {
nsVoidArray *models = NS_STATIC_CAST(nsVoidArray*,
doc->GetProperty(nsXFormsAtoms::modelListProperty));
if (models) {
if (models->SafeElementAt(0) == this) {
nsXFormsModelElement *next =
NS_STATIC_CAST(nsXFormsModelElement*, models->SafeElementAt(1));
if (next) {
targ->AddEventListener(NS_LITERAL_STRING("load"), next, PR_TRUE);
}
targ->RemoveEventListener(NS_LITERAL_STRING("load"), this, PR_TRUE);
}
models->RemoveElement(this);
}
}
}
NS_IMETHODIMP
nsXFormsModelElement::GetElementType(PRUint32 *aType)
{
*aType = ELEMENT_TYPE_GENERIC_ELEMENT;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::GetIsAttributeHandler(PRBool *aIsHandler)
{
*aIsHandler = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::GetScriptingInterfaces(PRUint32 *aCount, nsIID ***aArray)
{
return CloneScriptingInterfaces(sScriptingIIDs,
NS_ARRAY_LENGTH(sScriptingIIDs),
aCount, aArray);
}
NS_IMETHODIMP
nsXFormsModelElement::WillChangeDocument(nsIDOMDocument* aNewDocument)
{
RemoveModelFromDocument();
return NS_OK;
}
static void
DeleteVoidArray(void *aObject,
nsIAtom *aPropertyName,
void *aPropertyValue,
void *aData)
{
delete NS_STATIC_CAST(nsVoidArray*, aPropertyValue);
}
NS_IMETHODIMP
nsXFormsModelElement::DocumentChanged(nsIDOMDocument* aNewDocument)
{
// Add this model to the document's model list. If this is the first
// model to be created, register an onload handler so that we can
// do model-construct-done notifications.
if (!aNewDocument)
return NS_OK;
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aNewDocument);
nsVoidArray *models = NS_STATIC_CAST(nsVoidArray*,
doc->GetProperty(nsXFormsAtoms::modelListProperty));
if (!models) {
models = new nsVoidArray(16);
doc->SetProperty(nsXFormsAtoms::modelListProperty,
models, DeleteVoidArray);
nsIScriptGlobalObject *window = doc->GetScriptGlobalObject();
nsCOMPtr<nsIDOMEventTarget> targ = do_QueryInterface(window);
targ->AddEventListener(NS_LITERAL_STRING("load"), this, PR_TRUE);
}
models->AppendElement(this);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::WillChangeParent(nsIDOMElement* aNewParent)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::ParentChanged(nsIDOMElement* aNewParent)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::WillInsertChild(nsIDOMNode* aChild, PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::ChildInserted(nsIDOMNode* aChild, PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::WillAppendChild(nsIDOMNode* aChild)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::ChildAppended(nsIDOMNode* aChild)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::WillRemoveChild(PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::ChildRemoved(PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::WillSetAttribute(nsIAtom *aName,
const nsAString &aNewValue)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::AttributeSet(nsIAtom *aName, const nsAString &aNewValue)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::WillRemoveAttribute(nsIAtom *aName)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::AttributeRemoved(nsIAtom *aName)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::DoneAddingChildren()
{
// We wait until all children are added to dispatch xforms-model-construct,
// since the model may have an action handler for this event.
nsresult rv = DispatchEvent(eEvent_ModelConstruct);
NS_ENSURE_SUCCESS(rv, rv);
// xforms-model-construct is not cancellable, so always proceed.
// We continue here rather than doing this in HandleEvent since we know
// it only makes sense to perform this default action once.
// (XForms 4.2.1)
// 1. load xml schemas
nsAutoString schemaList;
mElement->GetAttribute(NS_LITERAL_STRING("schema"), schemaList);
if (!schemaList.IsEmpty()) {
nsCOMPtr<nsISchemaLoader> loader = do_GetService(NS_SCHEMALOADER_CONTRACTID);
NS_ENSURE_TRUE(loader, NS_ERROR_FAILURE);
// Parse the space-separated list.
PRUint32 offset = 0;
nsCOMPtr<nsIContent> content = do_QueryInterface(mElement);
nsRefPtr<nsIURI> baseURI = content->GetBaseURI();
while (1) {
++mSchemaCount;
PRInt32 index = schemaList.FindChar(PRUnichar(' '), offset);
nsCOMPtr<nsIURI> newURI;
NS_NewURI(getter_AddRefs(newURI),
Substring(schemaList, offset, index - offset),
nsnull, baseURI);
if (!newURI) {
DispatchEvent(eEvent_LinkException); // this is a fatal error
return NS_OK;
}
nsCAutoString uriSpec;
newURI->GetSpec(uriSpec);
rv = loader->LoadAsync(NS_ConvertUTF8toUTF16(uriSpec), this);
if (NS_FAILED(rv)) {
DispatchEvent(eEvent_LinkException); // this is a fatal error
return NS_OK;
}
if (index == -1)
break;
offset = index + 1;
}
}
// 2. construct an XPath data model from inline or external initial instance
// data. This is done by our child instance elements as they are inserted
// into the document, and all of the instances will be processed by this
// point.
// XXX schema and external instance data loads should delay document onload
if (IsComplete()) {
return FinishConstruction();
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
{
aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_WILL_CHANGE_DOCUMENT |
nsIXTFElement::NOTIFY_DOCUMENT_CHANGED |
nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN);
nsCOMPtr<nsIDOMElement> node;
aWrapper->GetElementNode(getter_AddRefs(node));
// It's ok to keep a weak pointer to mElement. mElement will have an
// owning reference to this object, so as long as we null out mElement in
// OnDestroyed, it will always be valid.
mElement = node;
NS_ASSERTION(mElement, "Wrapper is not an nsIDOMElement, we'll crash soon");
nsresult rv = mMDG.Init();
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
// nsIXTFPrivate
NS_IMETHODIMP
nsXFormsModelElement::GetInner(nsISupports **aInner)
{
NS_ENSURE_ARG_POINTER(aInner);
NS_ADDREF(*aInner = NS_STATIC_CAST(nsIXFormsModelElement*, this));
return NS_OK;
}
// nsIXFormsModelElement
NS_IMETHODIMP
nsXFormsModelElement::GetInstanceDocument(const nsAString& aInstanceID,
nsIDOMDocument **aDocument)
{
NS_ENSURE_ARG_POINTER(aDocument);
NS_IF_ADDREF(*aDocument = FindInstanceDocument(aInstanceID));
return *aDocument ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsXFormsModelElement::Rebuild()
{
#ifdef DEBUG
printf("nsXFormsModelElement::Rebuild()\n");
#endif
// TODO: Clear graph and re-attach elements
// 1 . Clear graph
// mMDG.Clear();
// 2. Re-attach all elements
// 3. Rebuild graph
return mMDG.Rebuild();
}
NS_IMETHODIMP
nsXFormsModelElement::Recalculate()
{
#ifdef DEBUG
printf("nsXFormsModelElement::Recalculate()\n");
#endif
nsXFormsMDGSet changedNodes;
// TODO: Handle changed nodes. That is, dispatch events, etc.
return mMDG.Recalculate(changedNodes);
}
NS_IMETHODIMP
nsXFormsModelElement::Revalidate()
{
#ifdef DEBUG
printf("nsXFormsModelElement::Revalidate()\n");
#endif
#ifdef DEBUG_beaufour
// Dump instance document to stdout
nsresult rv;
nsCOMPtr<nsIDOMSerializer> serializer(do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
// TODO: Should use SerializeToStream and write directly to stdout...
nsAutoString instanceString;
rv = serializer->SerializeToString(mInstanceDocument, instanceString);
NS_ENSURE_SUCCESS(rv, rv);
printf("Instance data:\n%s\n", NS_ConvertUCS2toUTF8(instanceString).get());
#endif
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::Refresh()
{
#ifdef DEBUG
printf("nsXFormsModelElement::Refresh()\n");
#endif
return NS_OK;
}
// nsISchemaLoadListener
NS_IMETHODIMP
nsXFormsModelElement::OnLoad(nsISchema* aSchema)
{
mSchemas.AppendObject(aSchema);
if (IsComplete()) {
nsresult rv = FinishConstruction();
NS_ENSURE_SUCCESS(rv, rv);
DispatchEvent(eEvent_Refresh);
}
return NS_OK;
}
// nsIWebServiceErrorHandler
NS_IMETHODIMP
nsXFormsModelElement::OnError(nsresult aStatus,
const nsAString &aStatusMessage)
{
DispatchEvent(eEvent_LinkException);
return NS_OK;
}
// nsIDOMEventListener
NS_IMETHODIMP
nsXFormsModelElement::HandleEvent(nsIDOMEvent* aEvent)
{
nsCOMPtr<nsIDOMNSUIEvent> evt = do_QueryInterface(aEvent);
NS_ASSERTION(evt, "event should implement nsIDOMNSUIEvent");
PRBool defaultPrevented;
evt->GetPreventDefault(&defaultPrevented);
if (defaultPrevented)
return NS_OK;
nsAutoString type;
aEvent->GetType(type);
if (type.EqualsLiteral("xforms-refresh")) {
// refresh all of our form controls
PRInt32 controlCount = mFormControls.Count();
for (PRInt32 i = 0; i < controlCount; ++i) {
NS_STATIC_CAST(nsXFormsControl*, mFormControls[i])->Refresh();
}
} else if (type.EqualsLiteral("xforms-revalidate")) {
Revalidate();
} else if (type.EqualsLiteral("xforms-recalculate")) {
Recalculate();
} else if (type.EqualsLiteral("xforms-rebuild")) {
Rebuild();
} else if (type.EqualsLiteral("xforms-reset")) {
#ifdef DEBUG
printf("nsXFormsModelElement::Reset()\n");
#endif
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::Load(nsIDOMEvent* aEvent)
{
nsCOMPtr<nsIDOMEventTarget> target;
aEvent->GetTarget(getter_AddRefs(target));
nsCOMPtr<nsIDocument> document = do_QueryInterface(target);
if (document) {
// The document has finished loading; that means that all of the models
// in it are initialized. Fire the model-construct-done event to each
// model.
nsVoidArray *models = NS_STATIC_CAST(nsVoidArray*,
document->GetProperty(nsXFormsAtoms::modelListProperty));
NS_ASSERTION(models, "models list is empty!");
for (PRInt32 i = 0; i < models->Count(); ++i) {
NS_STATIC_CAST(nsXFormsModelElement*, models->ElementAt(i))
->DispatchEvent(eEvent_ModelConstructDone);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::BeforeUnload(nsIDOMEvent* aEvent)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::Unload(nsIDOMEvent* aEvent)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::Abort(nsIDOMEvent* aEvent)
{
DispatchEvent(eEvent_LinkException);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::Error(nsIDOMEvent* aEvent)
{
DispatchEvent(eEvent_LinkException);
return NS_OK;
}
// internal methods
nsIDOMDocument*
nsXFormsModelElement::FindInstanceDocument(const nsAString &aID)
{
nsCOMPtr<nsIDOMNodeList> children;
mElement->GetChildNodes(getter_AddRefs(children));
if (!children)
return nsnull;
PRUint32 childCount = 0;
children->GetLength(&childCount);
nsCOMPtr<nsIDOMNode> node;
nsCOMPtr<nsIDOMElement> element;
nsAutoString id;
for (PRUint32 i = 0; i < childCount; ++i) {
children->Item(i, getter_AddRefs(node));
NS_ASSERTION(node, "incorrect NodeList length?");
element = do_QueryInterface(node);
if (!element)
continue;
element->GetAttribute(NS_LITERAL_STRING("id"), id);
if (aID.IsEmpty() || aID.Equals(id)) {
// make sure this is an xforms instance element
nsAutoString namespaceURI, localName;
element->GetNamespaceURI(namespaceURI);
element->GetLocalName(localName);
if (localName.EqualsLiteral("instance") &&
namespaceURI.EqualsLiteral(NS_NAMESPACE_XFORMS)) {
// This is the requested instance, so get its document.
nsCOMPtr<nsIXTFPrivate> xtfPriv = do_QueryInterface(element);
NS_ENSURE_TRUE(xtfPriv, nsnull);
nsCOMPtr<nsISupports> instanceInner;
xtfPriv->GetInner(getter_AddRefs(instanceInner));
NS_ENSURE_TRUE(instanceInner, nsnull);
nsISupports *isupp = NS_STATIC_CAST(nsISupports*, instanceInner.get());
nsXFormsInstanceElement *instance =
NS_STATIC_CAST(nsXFormsInstanceElement*,
NS_STATIC_CAST(nsIXTFGenericElement*, isupp));
return instance->GetDocument();
}
}
}
return nsnull;
}
nsresult
nsXFormsModelElement::FinishConstruction()
{
// 3. if applicable, initialize P3P
// 4. construct instance data from initial instance data. apply all
// <bind> elements in document order.
// we get the instance data from our instance child nodes
nsIDOMDocument *firstInstanceDoc = FindInstanceDocument(EmptyString());
if (!firstInstanceDoc)
return NS_OK;
nsCOMPtr<nsIDOMElement> firstInstanceRoot;
firstInstanceDoc->GetDocumentElement(getter_AddRefs(firstInstanceRoot));
nsCOMPtr<nsIDOMXPathEvaluator> xpath = do_QueryInterface(firstInstanceDoc);
nsCOMPtr<nsIDOMNodeList> children;
mElement->GetChildNodes(getter_AddRefs(children));
PRUint32 childCount = 0;
if (children)
children->GetLength(&childCount);
nsAutoString namespaceURI, localName;
for (PRUint32 i = 0; i < childCount; ++i) {
nsCOMPtr<nsIDOMNode> child;
children->Item(i, getter_AddRefs(child));
NS_ASSERTION(child, "there can't be null items in the NodeList!");
child->GetLocalName(localName);
if (localName.EqualsLiteral("bind")) {
child->GetNamespaceURI(namespaceURI);
if (namespaceURI.EqualsLiteral(NS_NAMESPACE_XFORMS)) {
if (!ProcessBind(xpath, firstInstanceRoot,
nsCOMPtr<nsIDOMElement>(do_QueryInterface(child)))) {
DispatchEvent(eEvent_BindingException);
return NS_OK;
}
}
}
}
// 5. dispatch xforms-rebuild, xforms-recalculate, xforms-revalidate
// First hook up our event listener so we invoke the default action for
// these events. We listen on the system event group so that we can check
// whether preventDefault() was called by any content listeners.
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mElement);
NS_ASSERTION(receiver, "xml elements must be event receivers");
nsCOMPtr<nsIDOMEventGroup> systemGroup;
receiver->GetSystemEventGroup(getter_AddRefs(systemGroup));
NS_ASSERTION(systemGroup, "system event group must exist");
nsCOMPtr<nsIDOM3EventTarget> targ = do_QueryInterface(mElement);
for (unsigned int j = 0; j < NS_ARRAY_LENGTH(sModelEvents); ++j) {
targ->AddGroupedEventListener(NS_ConvertUTF8toUTF16(sModelEvents[j].name),
this, PR_FALSE, systemGroup);
}
DispatchEvent(eEvent_Rebuild);
DispatchEvent(eEvent_Recalculate);
DispatchEvent(eEvent_Revalidate);
// We're done initializing this model.
return NS_OK;
}
static void
ReleaseExpr(void *aElement,
nsIAtom *aPropertyName,
void *aPropertyValue,
void *aData)
{
nsIDOMXPathExpression *expr = NS_STATIC_CAST(nsIDOMXPathExpression*,
aPropertyValue);
NS_RELEASE(expr);
}
PRBool
nsXFormsModelElement::ProcessBind(nsIDOMXPathEvaluator *aEvaluator,
nsIDOMNode *aContextNode,
nsIDOMElement *aBindElement)
{
// Get the expression for the nodes that this <bind> applies to.
nsAutoString expr;
aBindElement->GetAttribute(NS_LITERAL_STRING("nodeset"), expr);
if (expr.IsEmpty())
return PR_TRUE;
nsCOMPtr<nsIDOMXPathNSResolver> resolver;
aEvaluator->CreateNSResolver(aBindElement, getter_AddRefs(resolver));
// Get the model item properties specified by this <bind>.
nsCOMPtr<nsIDOMXPathExpression> props[eModel__count];
nsAutoString exprStrings[eModel__count];
PRInt32 propCount = 0;
nsresult rv = NS_OK;
nsAutoString attrStr;
for (int i = 0; i < eModel__count; ++i) {
sModelPropsList[i]->ToString(attrStr);
aBindElement->GetAttribute(attrStr, exprStrings[i]);
if (!exprStrings[i].IsEmpty()) {
rv = aEvaluator->CreateExpression(exprStrings[i], resolver,
getter_AddRefs(props[i]));
if (NS_FAILED(rv))
return PR_FALSE;
++propCount;
}
}
if (propCount == 0)
return PR_TRUE; // successful, but nothing to do
nsCOMPtr<nsIDOMXPathResult> result;
rv = aEvaluator->Evaluate(expr, aContextNode, resolver,
nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
nsnull, getter_AddRefs(result));
if (NS_FAILED(rv))
return PR_FALSE;
PRUint32 snapLen;
rv = result->GetSnapshotLength(&snapLen);
NS_ENSURE_SUCCESS(rv, rv);
nsXFormsMDGSet set;
nsCOMPtr<nsIDOMNode> node;
PRInt32 contextPosition = 1;
for (PRUint32 snapItem = 0; snapItem < snapLen; ++snapItem) {
rv = result->SnapshotItem(snapItem, getter_AddRefs(node));
NS_ENSURE_SUCCESS(rv, rv);
if (!node) {
NS_WARNING("nsXFormsModelElement::ProcessBind(): Empty node in result set.");
continue;
}
nsXFormsXPathParser parser;
nsXFormsXPathAnalyzer analyzer(aEvaluator, resolver);
// We must check whether the properties already exist on the node.
for (int j = 0; j < eModel__count; ++j) {
if (props[j]) {
nsCOMPtr<nsIContent> content = do_QueryInterface(node, &rv);
if (NS_FAILED(rv)) {
NS_WARNING("nsXFormsModelElement::ProcessBind(): Node is not IContent!\n");
continue;
}
nsIDOMXPathExpression *expr = props[j];
NS_ADDREF(expr);
// Set property
rv = content->SetProperty(sModelPropsList[j], expr, ReleaseExpr);
if (rv == NS_PROPTABLE_PROP_OVERWRITTEN) {
return PR_FALSE;
}
// Get node dependencies
nsAutoPtr<nsXFormsXPathNode> xNode(parser.Parse(exprStrings[j]));
set.Clear();
rv = analyzer.Analyze(node, xNode, expr, &exprStrings[j], &set);
NS_ENSURE_SUCCESS(rv, rv);
// Insert into MDG
rv = mMDG.AddMIP((ModelItemPropName) j, expr, &set, parser.UsesDynamicFunc(),
node, contextPosition++, snapLen);
NS_ENSURE_SUCCESS(rv, rv);
}
}
}
return PR_TRUE;
}
nsresult
nsXFormsModelElement::DispatchEvent(nsXFormsModelEvent aEvent)
{
nsCOMPtr<nsIDOMDocument> domDoc;
mElement->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDOMDocumentEvent> doc = do_QueryInterface(domDoc);
nsCOMPtr<nsIDOMEvent> event;
doc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
const EventData *data = &sModelEvents[aEvent];
event->InitEvent(NS_ConvertUTF8toUTF16(data->name),
data->canBubble, data->canCancel);
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mElement);
PRBool cancelled;
return target->DispatchEvent(event, &cancelled);
}
already_AddRefed<nsISchemaType>
nsXFormsModelElement::GetTypeForControl(nsXFormsControl *aControl)
{
return nsnull;
}
void
nsXFormsModelElement::AddFormControl(nsXFormsControl *aControl)
{
if (mFormControls.IndexOf(aControl) == -1)
mFormControls.AppendElement(aControl);
}
void
nsXFormsModelElement::RemoveFormControl(nsXFormsControl *aControl)
{
mFormControls.RemoveElement(aControl);
}
void
nsXFormsModelElement::RemovePendingInstance()
{
--mPendingInstanceCount;
if (IsComplete()) {
nsresult rv = FinishConstruction();
if (NS_SUCCEEDED(rv))
DispatchEvent(eEvent_Refresh);
}
}
/* static */ void
nsXFormsModelElement::Startup()
{
sModelPropsList[eModel_type] = nsXFormsAtoms::type;
sModelPropsList[eModel_readonly] = nsXFormsAtoms::readonly;
sModelPropsList[eModel_required] = nsXFormsAtoms::required;
sModelPropsList[eModel_relevant] = nsXFormsAtoms::relevant;
sModelPropsList[eModel_calculate] = nsXFormsAtoms::calculate;
sModelPropsList[eModel_constraint] = nsXFormsAtoms::constraint;
sModelPropsList[eModel_p3ptype] = nsXFormsAtoms::p3ptype;
}
nsresult
NS_NewXFormsModelElement(nsIXTFElement **aResult)
{
*aResult = new nsXFormsModelElement();
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}

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

@ -0,0 +1,146 @@
/* -*- 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):
* Brian Ryner <bryner@brianryner.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 nsXFormsModelElement_h_
#define nsXFormsModelElement_h_
#include "nsIXTFGenericElement.h"
#include "nsIXTFPrivate.h"
#include "nsIXFormsModelElement.h"
#include "nsISchema.h"
#include "nsCOMArray.h"
#include "nsVoidArray.h"
#include "nsCOMPtr.h"
#include "nsIDOMLoadListener.h"
#include "nsIDOMDocument.h"
#include "nsXFormsMDG.h"
#include "nsXFormsElement.h"
#include "nsISchemaLoader.h"
#include "nsISchema.h"
class nsIDOMElement;
class nsIDOMNode;
class nsIDOMXPathEvaluator;
class nsXFormsControl;
class nsXFormsInstanceElement;
enum nsXFormsModelEvent {
eEvent_ModelConstruct,
eEvent_ModelConstructDone,
eEvent_Ready,
eEvent_ModelDestruct,
eEvent_Rebuild,
eEvent_Refresh,
eEvent_Revalidate,
eEvent_Recalculate,
eEvent_Reset,
eEvent_BindingException,
eEvent_LinkException,
eEvent_LinkError,
eEvent_ComputeExeception
};
class nsXFormsModelElement : public nsXFormsElement,
public nsIXTFGenericElement,
public nsIXTFPrivate,
public nsIXFormsModelElement,
public nsISchemaLoadListener,
public nsIDOMLoadListener
{
public:
nsXFormsModelElement() NS_HIDDEN;
NS_DECL_ISUPPORTS
NS_DECL_NSIXTFELEMENT
NS_DECL_NSIXTFGENERICELEMENT
NS_DECL_NSIXTFPRIVATE
NS_DECL_NSIXFORMSMODELELEMENT
NS_DECL_NSISCHEMALOADLISTENER
NS_DECL_NSIWEBSERVICEERRORHANDLER
NS_DECL_NSIDOMEVENTLISTENER
// nsIDOMLoadListener
NS_IMETHOD Load(nsIDOMEvent* aEvent);
NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent);
NS_IMETHOD Unload(nsIDOMEvent* aEvent);
NS_IMETHOD Abort(nsIDOMEvent* aEvent);
NS_IMETHOD Error(nsIDOMEvent* aEvent);
NS_HIDDEN_(nsresult) DispatchEvent(nsXFormsModelEvent aEvent);
NS_HIDDEN_(already_AddRefed<nsISchemaType>)
GetTypeForControl(nsXFormsControl *aControl);
NS_HIDDEN_(void) AddFormControl(nsXFormsControl *aControl);
NS_HIDDEN_(void) RemoveFormControl(nsXFormsControl *aControl);
NS_HIDDEN_(void) AddPendingInstance() { ++mPendingInstanceCount; }
NS_HIDDEN_(void) RemovePendingInstance();
NS_HIDDEN_(nsIDOMDocument*) FindInstanceDocument(const nsAString &aID);
// Called after nsXFormsAtoms is registered
static NS_HIDDEN_(void) Startup();
private:
class ModelItemProperties;
NS_HIDDEN_(nsresult) FinishConstruction();
NS_HIDDEN_(PRBool) ProcessBind(nsIDOMXPathEvaluator *aEvaluator,
nsIDOMNode *aContextNode,
nsIDOMElement *aBindElement);
NS_HIDDEN_(void) RemoveModelFromDocument();
PRBool IsComplete() const { return (mSchemas.Count() == mSchemaCount
&& mPendingInstanceCount == 0); }
nsIDOMElement *mElement;
nsCOMArray<nsISchema> mSchemas;
nsVoidArray mFormControls;
PRInt32 mSchemaCount;
PRInt32 mPendingInstanceCount;
nsXFormsMDG mMDG;
};
NS_HIDDEN_(nsresult) NS_NewXFormsModelElement(nsIXTFElement **aResult);
#endif

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

@ -0,0 +1,61 @@
/* -*- 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):
* Brian Ryner <bryner@brianryner.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 "nsIGenericFactory.h"
#include "nsXFormsElementFactory.h"
#include "nsXFormsAtoms.h"
#include "nsXFormsModelElement.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsXFormsElementFactory)
static const nsModuleComponentInfo components[] = {
{ "XForms element factory",
NS_XFORMSELEMENTFACTORY_CID,
NS_XTF_ELEMENT_FACTORY_CONTRACTID_PREFIX NS_NAMESPACE_XFORMS,
nsXFormsElementFactoryConstructor }
};
PR_STATIC_CALLBACK(nsresult)
XFormsModuleCtor(nsIModule* aSelf)
{
nsXFormsAtoms::InitAtoms();
nsXFormsModelElement::Startup();
return NS_OK;
}
NS_IMPL_NSGETMODULE_WITH_CTOR(xforms, components, XFormsModuleCtor)

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

@ -0,0 +1,187 @@
/* -*- 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):
* Brian Ryner <bryner@brianryner.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 "nsXFormsStubElement.h"
#include "nsIDOMElement.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOM3Node.h"
#include "nsMemory.h"
static const nsIID sScriptingIIDs[] = {
NS_IDOMELEMENT_IID,
NS_IDOMEVENTTARGET_IID,
NS_IDOM3NODE_IID
};
NS_IMPL_ISUPPORTS2(nsXFormsStubElement, nsIXTFElement, nsIXTFGenericElement)
NS_IMETHODIMP
nsXFormsStubElement::OnDestroyed()
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::GetElementType(PRUint32 *aElementType)
{
*aElementType = nsIXTFElement::ELEMENT_TYPE_GENERIC_ELEMENT;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::GetIsAttributeHandler(PRBool *aIsAttributeHandler)
{
*aIsAttributeHandler = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::GetScriptingInterfaces(PRUint32 *aCount, nsIID ***aArray)
{
return CloneScriptingInterfaces(sScriptingIIDs,
NS_ARRAY_LENGTH(sScriptingIIDs),
aCount, aArray);
}
NS_IMETHODIMP
nsXFormsStubElement::WillChangeDocument(nsIDOMDocument *aNewDocument)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::DocumentChanged(nsIDOMDocument *aNewDocument)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::WillChangeParent(nsIDOMElement *aNewParent)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::ParentChanged(nsIDOMElement *aNewParent)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::WillInsertChild(nsIDOMNode *aChild, PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::ChildInserted(nsIDOMNode *aChild, PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::WillAppendChild(nsIDOMNode *aChild)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::ChildAppended(nsIDOMNode *aChild)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::WillRemoveChild(PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::ChildRemoved(PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::WillSetAttribute(nsIAtom *aName,
const nsAString &aNewValue)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::AttributeSet(nsIAtom *aName, const nsAString &aNewValue)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::WillRemoveAttribute(nsIAtom *aName)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::AttributeRemoved(nsIAtom *aName)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::DoneAddingChildren()
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsStubElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
{
return NS_OK;
}
nsresult
NS_NewXFormsStubElement(nsIXTFElement **aResult)
{
*aResult = new nsXFormsStubElement();
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}

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

@ -0,0 +1,56 @@
/* -*- 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):
* Brian Ryner <bryner@brianryner.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 nsXFormsStubElement_h_
#define nsXFormsStubElement_h_
#include "nsIXTFGenericElement.h"
#include "nsXFormsElement.h"
class nsXFormsStubElement : public nsXFormsElement,
public nsIXTFGenericElement
{
NS_DECL_ISUPPORTS
NS_DECL_NSIXTFELEMENT
NS_DECL_NSIXTFGENERICELEMENT
};
NS_HIDDEN_(nsresult)
NS_NewXFormsStubElement(nsIXTFElement **aResult);
#endif

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -0,0 +1,95 @@
/* -*- 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):
* Darin Fisher <darin@meer.net>
*
* 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 nsXFormsSubmissionElement_h_
#define nsXFormsSubmissionElement_h_
#include "nsIXTFGenericElement.h"
#include "nsIDOMEventListener.h"
#include "nsXFormsElement.h"
class nsIMultiplexInputStream;
class nsIInputStream;
class nsIDOMElement;
class nsIFile;
class nsCString;
class nsString;
class SubmissionAttachmentArray;
class nsXFormsSubmissionElement : public nsXFormsElement,
public nsIXTFGenericElement,
public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIXTFELEMENT
NS_DECL_NSIXTFGENERICELEMENT
NS_DECL_NSIDOMEVENTLISTENER
nsXFormsSubmissionElement()
: mElement(nsnull)
{}
NS_HIDDEN_(void) Submit();
NS_HIDDEN_(nsresult) SubmitEnd(PRBool succeeded);
NS_HIDDEN_(PRBool) GetBooleanAttr(const nsAString &attrName, PRBool defaultVal = PR_FALSE);
NS_HIDDEN_(void) GetDefaultInstanceData(nsIDOMNode **result);
NS_HIDDEN_(nsresult) GetSelectedInstanceData(nsIDOMNode **result);
NS_HIDDEN_(nsresult) SerializeData(nsIDOMNode *data, PRUint32 format, nsCString &uri, nsIInputStream **, nsCString &contentType);
NS_HIDDEN_(nsresult) SerializeDataXML(nsIDOMNode *data, PRUint32 format, nsIInputStream **, nsCString &contentType, SubmissionAttachmentArray *);
NS_HIDDEN_(nsresult) CreateSubmissionDoc(nsIDOMDocument *source, const nsString &encoding, SubmissionAttachmentArray *, nsIDOMDocument **result);
NS_HIDDEN_(nsresult) CopyChildren(nsIDOMNode *source, nsIDOMNode *dest, nsIDOMDocument *destDoc, SubmissionAttachmentArray *, const nsString &cdataElements, PRBool indent, PRUint32 depth);
NS_HIDDEN_(nsresult) SerializeDataURLEncoded(nsIDOMNode *data, PRUint32 format, nsCString &uri, nsIInputStream **, nsCString &contentType);
NS_HIDDEN_(void) AppendURLEncodedData(nsIDOMNode *data, const nsCString &sep, nsCString &buf);
NS_HIDDEN_(nsresult) SerializeDataMultipartRelated(nsIDOMNode *data, PRUint32 format, nsIInputStream **, nsCString &contentType);
NS_HIDDEN_(nsresult) SerializeDataMultipartFormData(nsIDOMNode *data, PRUint32 format, nsIInputStream **, nsCString &contentType);
NS_HIDDEN_(nsresult) AppendMultipartFormData(nsIDOMNode *data, const nsCString &boundary, nsCString &buf, nsIMultiplexInputStream *);
NS_HIDDEN_(nsresult) AppendPostDataChunk(nsCString &postDataChunk, nsIMultiplexInputStream *multiStream);
NS_HIDDEN_(nsresult) GetElementEncodingType(nsIDOMNode *data, PRUint32 *encType);
NS_HIDDEN_(nsresult) CreateFileStream(const nsString &absURI, nsIFile **file, nsIInputStream **stream);
NS_HIDDEN_(nsresult) SendData(PRUint32 format, const nsCString &uri, nsIInputStream *stream, const nsCString &contentType);
private:
nsIDOMElement *mElement;
};
NS_HIDDEN_(nsresult)
NS_NewXFormsSubmissionElement(nsIXTFElement **aResult);
#endif

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

@ -0,0 +1,54 @@
/* -*- 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):
* Brian Ryner <bryner@brianryner.com>
* Allan Beaufour <abeaufour@novell.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 __NSXFORMSTYPES_H__
#define __NSXFORMSTYPES_H__
enum ModelItemPropName
{
eModel_type,
eModel_readonly,
eModel_required,
eModel_relevant,
eModel_calculate,
eModel_constraint,
eModel_p3ptype,
eModel__count
};
#endif

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

@ -0,0 +1,198 @@
/* -*- 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
* Novell, Inc.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Allan Beaufour <abeaufour@novell.com>
* David Landwehr <dlandwehr@novell.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 "nsXFormsXPathAnalyzer.h"
#include "nsIDOMXPathResult.h"
#ifdef DEBUG
// #define DEBUG_XF_ANALYZER
#endif
MOZ_DECL_CTOR_COUNTER(nsXFormsXPathAnalyzer)
nsXFormsXPathAnalyzer::nsXFormsXPathAnalyzer(nsIDOMXPathEvaluator* aEvaluator, nsIDOMXPathNSResolver* aResolver)
: mEvaluator(aEvaluator), mResolver(aResolver)
{
MOZ_COUNT_CTOR(nsXFormsXPathAnalyzer);
}
nsXFormsXPathAnalyzer::~nsXFormsXPathAnalyzer()
{
MOZ_COUNT_DTOR(nsXFormsXPathAnalyzer);
}
nsresult
nsXFormsXPathAnalyzer::Analyze(nsIDOMNode* aContextNode, const nsXFormsXPathNode* aNode,
nsIDOMXPathExpression* aExpression, const nsAString* aExprString,
nsXFormsMDGSet* aSet)
{
NS_ENSURE_TRUE(aContextNode, NS_ERROR_INVALID_ARG);
NS_ENSURE_TRUE(aNode, NS_ERROR_INVALID_ARG);
NS_ENSURE_TRUE(aExpression, NS_ERROR_INVALID_ARG);
NS_ENSURE_TRUE(aExprString, NS_ERROR_INVALID_ARG);
NS_ENSURE_TRUE(aSet, NS_ERROR_INVALID_ARG);
mCurExpression = aExpression;
mCurExprString = aExprString;
mCurSet = aSet;
#ifdef DEBUG_XF_ANALYZER
printf("=====================================\n");
printf("Analyzing: %s\n", NS_ConvertUCS2toUTF8(*mCurExprString).get());
printf("=====================================\n");
#endif
nsresult rv = AnalyzeRecursively(aContextNode, aNode->mChild, 0);
#ifdef DEBUG_XF_ANALYZER
printf("-------------------------------------\n");
#endif
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult
nsXFormsXPathAnalyzer::AnalyzeRecursively(nsIDOMNode* aContextNode, const nsXFormsXPathNode* aNode,
PRUint32 aIndent)
{
nsXFormsXPathNode* t;
nsAutoString xp;
nsresult rv;
nsCOMPtr<nsIDOMXPathResult> result;
nsCOMPtr<nsIDOMNode> node;
char strbuf[100];
char* strpos;
#ifdef DEBUG_beaufour_xxx
printf("nsXFormsXPathParser::AnalyzeRecursively(%p)\n", (void*) aNode);
#endif
for (; aNode; aNode = aNode->mSibling) {
#ifdef DEBUG_beaufour_xxx
printf("\tChild: %p, Sibling: %p\n", (void*) aNode->mChild, (void*) aNode->mSibling);
printf("\tIndex: %d - %d\n", aNode->mStartIndex, aNode->mEndIndex);
printf("\tCon: %d, Predicate: %d, Literal: %d\n", aNode->mCon, aNode->mPredicate, aNode->mLiteral);
#endif
if ( aNode->mEndIndex < 0
|| aNode->mStartIndex >= aNode->mEndIndex
|| ((PRUint32) aNode->mEndIndex == mCurExprString->Length() && aNode->mStartIndex == 0)) {
continue;
}
PRBool hasContinue = PR_FALSE;
strpos = strbuf;
*strpos = '\0';
// hasContinue == whether we have a child with a mCon
t = aNode->mChild;
while (t && !hasContinue) {
hasContinue = t->mCon;
t = t->mSibling;
}
#ifdef DEBUG_XF_ANALYZER
for (PRUint32 j = 0; j < aIndent; ++j) {
strpos += sprintf(strpos, " ");
}
strpos += sprintf(strpos, "<%s> ", hasContinue ? "C" : " ");
if (aNode->mPredicate) {
if (!(aNode->mChild)) {
strpos += sprintf(strpos, "[PredicateVal], ");
} else {
strpos += sprintf(strpos, "[Predicate], ");
}
} else {
if (!(aNode->mChild)) {
strpos += sprintf(strpos, "[AxisStepsVal], ");
} else {
if (!hasContinue) {
strpos += printf(strpos, "[AxisSteps], ");
}
}
}
#endif
if (aNode->mCon) {
// Remove the leading /
xp = Substring(*mCurExprString, aNode->mStartIndex + 1, aNode->mEndIndex - aNode->mStartIndex + 1);
} else {
xp = Substring(*mCurExprString, aNode->mStartIndex, aNode->mEndIndex - aNode->mStartIndex);
}
rv = mEvaluator->Evaluate(xp, aContextNode, mResolver,
nsIDOMXPathResult::ANY_TYPE,
nsnull, getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
PRUint16 type;
rv = result->GetResultType(&type);
NS_ENSURE_SUCCESS(rv, rv);
// We are only interested in nodes
if ( type != nsIDOMXPathResult::UNORDERED_NODE_ITERATOR_TYPE
&& type != nsIDOMXPathResult::ORDERED_NODE_ITERATOR_TYPE) {
continue;
}
while (NS_SUCCEEDED(result->IterateNext(getter_AddRefs(node))) && node) {
NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG_XF_ANALYZER
printf(strbuf);
#endif
if (aNode->mChild || (!aNode->mChild && hasContinue)) {
#ifdef DEBUG_XF_ANALYZER
printf("iterating '%s'\n", NS_ConvertUCS2toUTF8(xp).get());
#endif
} else {
#ifdef DEBUG_XF_ANALYZER
printf("collecting '%s'\n", NS_ConvertUCS2toUTF8(xp).get());
#endif
mCurSet->AddNode(node);
}
rv = AnalyzeRecursively(node, aNode->mChild, aIndent + 1);
}
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}

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

@ -0,0 +1,77 @@
/* -*- 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
* Novell, Inc.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Allan Beaufour <abeaufour@novell.com>
* David Landwehr <dlandwehr@novell.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 "nscore.h"
#include "nsCOMPtr.h"
#include "nsXFormsXPathNode.h"
#include "nsIDOMXPathExpression.h"
#include "nsIDOMXPathEvaluator.h"
#include "nsIDOMXPathNSResolver.h"
#include "nsXFormsMDGSet.h"
#include "nsIDOMNode.h"
#include "nsCOMPtr.h"
#include "nsString.h"
/**
* This class analyzes an XPath Expression parse tree (nsXFormsXPathNode), and
* returns all the nodes that the expression depends on.
*
* @note Should be reimplemented and moved to Transformiix
* @note This class is not thread safe (mCur.*)
*/
class nsXFormsXPathAnalyzer {
private:
nsCOMPtr<nsIDOMXPathEvaluator> mEvaluator;
nsCOMPtr<nsIDOMXPathNSResolver> mResolver;
nsXFormsMDGSet* mCurSet;
nsCOMPtr<nsIDOMXPathExpression> mCurExpression;
const nsAString* mCurExprString;
nsresult AnalyzeRecursively(nsIDOMNode* aContextNode, const nsXFormsXPathNode* aNode,
PRUint32 aIndent);
public:
nsXFormsXPathAnalyzer(nsIDOMXPathEvaluator* aEvaluator, nsIDOMXPathNSResolver* aResolver);
~nsXFormsXPathAnalyzer();
nsresult Analyze(nsIDOMNode* aContextNode, const nsXFormsXPathNode* aNode,
nsIDOMXPathExpression* aExpression, const nsAString* aExprString,
nsXFormsMDGSet* aSet);
};

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

@ -0,0 +1,64 @@
/* -*- 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
* Novell, Inc.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Allan Beaufour <abeaufour@novell.com>
* David Landwehr <dlandwehr@novell.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 "nsXFormsXPathNode.h"
#include "nsCOMPtr.h"
MOZ_DECL_CTOR_COUNTER(nsXFormsXPathNode)
nsXFormsXPathNode::nsXFormsXPathNode(nsXFormsXPathNode* aParent, PRBool aContinue)
: mChild(nsnull), mEndIndex(-100), mCon(aContinue)
{
MOZ_COUNT_CTOR(nsXFormsXPathNode);
if (aParent) {
mSibling = aParent->mChild;
aParent->mChild = this;
} else {
mSibling = nsnull;
}
}
nsXFormsXPathNode::~nsXFormsXPathNode()
{
delete mChild;
delete mSibling;
MOZ_COUNT_DTOR(nsXFormsXPathNode);
}

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

@ -0,0 +1,64 @@
/* -*- 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
* Novell, Inc.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Allan Beaufour <abeaufour@novell.com>
* David Landwehr <dlandwehr@novell.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 __NSXFORMSXPATHNODE_H__
#define __NSXFORMSXPATHNODE_H__
#include "nscore.h"
/**
* The node type of the XPath Expression parse tree that nsXFormsXPathParser
* creates.
*
* @note Should be reimplemented and moved to Transformiix
*/
class nsXFormsXPathNode {
public:
nsXFormsXPathNode* mChild;
nsXFormsXPathNode* mSibling;
PRInt32 mStartIndex;
PRInt32 mEndIndex;
PRBool mCon;
PRBool mPredicate;
PRBool mLiteral;
nsXFormsXPathNode(nsXFormsXPathNode* aParent, PRBool aContinue = PR_FALSE);
~nsXFormsXPathNode();
};
#endif

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

@ -0,0 +1,911 @@
/* -*- 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
* Novell, Inc.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Allan Beaufour <abeaufour@novell.com>
* David Landwehr <dlandwehr@novell.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 "nsXFormsXPathParser.h"
#include "nscore.h"
/*
* (TODO) GIANT hack. Without exceptions everything had to be rewritten, and
* that was to overdo it a bit, when the code probably does not survive...
*/
void
XPathCompilerException(const char* aMsg, nsAString& aExpression, PRInt32 aOffset = -1, PRInt32 aLength = -1) {
printf("XPathCompilerException: %s, %s [o: %d, l: %d]\n",
aMsg,
NS_ConvertUCS2toUTF8(aExpression).get(), aOffset, aLength);
printf("WARNING: Houston we have a problem, and unlike Apollo 13, we're not going to make it!\n");
NS_ABORT();
}
MOZ_DECL_CTOR_COUNTER(nsXFormsXPathParser)
nsXFormsXPathParser::nsXFormsXPathParser()
: mUsesDynamicFunc(PR_FALSE), mHead(nsnull), mAnalyzeStackPointer(nsnull)
{
MOZ_COUNT_CTOR(nsXFormsXPathParser);
}
nsXFormsXPathParser::~nsXFormsXPathParser()
{
MOZ_COUNT_DTOR(nsXFormsXPathParser);
}
void
nsXFormsXPathParser::PushContext(PRInt32 aStartIndex)
{
mHead = new nsXFormsXPathNode(mHead);
if (aStartIndex == -100) {
mHead->mStartIndex = mScanner.Offset() + 1;
} else {
mHead->mStartIndex = aStartIndex;
}
mStack[++mAnalyzeStackPointer] = mHead;
mHead->mPredicate = mPredicateLevel != 0;
mHead->mLiteral = PR_FALSE;
}
void
nsXFormsXPathParser::PushContext(nsXFormsXPathNode* aNode)
{
mStack[++mAnalyzeStackPointer] = aNode;
mHead = aNode;
}
void
nsXFormsXPathParser::EndContext()
{
if (mHead) {
mHead->mEndIndex = mScanner.Offset() + 1;
}
}
void
nsXFormsXPathParser::RestartContext()
{
nsXFormsXPathNode* temp = new nsXFormsXPathNode(nsnull, PR_TRUE);
temp->mStartIndex = mScanner.Offset() + 1;
temp->mSibling = mHead->mChild;
temp->mPredicate = mPredicateLevel != 0;
mHead->mChild = temp;
mHead = temp;
mStack[mAnalyzeStackPointer] = mHead;
}
nsXFormsXPathNode*
nsXFormsXPathParser::JustContext()
{
nsXFormsXPathNode* t = mStack[mAnalyzeStackPointer];
mHead = mStack[--mAnalyzeStackPointer];
return t;
}
nsXFormsXPathNode*
nsXFormsXPathParser::PopContext()
{
if (mHead->mEndIndex == -100) {
mHead->mEndIndex = mScanner.Offset() + 1;
}
NS_ASSERTION(mHead->mStartIndex <= mHead->mEndIndex, "");
NS_ASSERTION(mAnalyzeStackPointer - 1 >= 0, "");
mHead = mStack[--mAnalyzeStackPointer];
return mHead;
}
void
nsXFormsXPathParser::AbbreviatedStep()
{
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::DOT:
PopToken();
break;
case nsXFormsXPathScanner::DOTDOT:
PopToken();
break;
default:
XPathCompilerException("Expected . or ..", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
break;
}
}
void
nsXFormsXPathParser::AbsoluteLocationPath()
{
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
nsXFormsXPathScanner::XPATHTOKEN r;
switch (t) {
case nsXFormsXPathScanner::SLASH:
PopToken();
r = PeekToken();
switch (r) {
case nsXFormsXPathScanner::ANCESTOR:
case nsXFormsXPathScanner::ANCESTOR_OR_SELF:
case nsXFormsXPathScanner::ATTRIBUTE:
case nsXFormsXPathScanner::CHILD:
case nsXFormsXPathScanner::DESCENDANT:
case nsXFormsXPathScanner::DESCENDANT_OR_SELF:
case nsXFormsXPathScanner::FOLLOWING:
case nsXFormsXPathScanner::FOLLOWING_SIBLING:
case nsXFormsXPathScanner::NAMESPACE:
case nsXFormsXPathScanner::PARENT:
case nsXFormsXPathScanner::PRECEDING:
case nsXFormsXPathScanner::PRECEDING_SIBLING:
case nsXFormsXPathScanner::SELF:
case nsXFormsXPathScanner::AT:
case nsXFormsXPathScanner::STAR:
case nsXFormsXPathScanner::NCNAME:
case nsXFormsXPathScanner::QNAME:
case nsXFormsXPathScanner::COMMENT:
case nsXFormsXPathScanner::TEXT:
case nsXFormsXPathScanner::PI:
case nsXFormsXPathScanner::NODE:
case nsXFormsXPathScanner::DOT:
case nsXFormsXPathScanner::DOTDOT:
RelativeLocationPath();
break;
default:
break;
}
break;
case nsXFormsXPathScanner::SLASHSLASH:
PopToken();
if (DoRelative()) {
RelativeLocationPath();
}
break;
default:
XPathCompilerException("Not an absolute location path", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
}
}
void
nsXFormsXPathParser::AdditiveExpression()
{
PRBool con = PR_TRUE;
MultiplicationExpr();
while (con) {
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::PLUS:
PopToken();
MultiplicationExpr();
break;
case nsXFormsXPathScanner::MINUS:
PopToken();
MultiplicationExpr();
break;
default:
con = PR_FALSE;
}
}
}
void
nsXFormsXPathParser::AndExpr()
{
EqualityExpr();
if (PeekToken() == nsXFormsXPathScanner::AND) {
PopToken();
AndExpr();
}
}
void
nsXFormsXPathParser::AxisSpecifier()
{
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::ANCESTOR:
case nsXFormsXPathScanner::ANCESTOR_OR_SELF:
case nsXFormsXPathScanner::ATTRIBUTE:
case nsXFormsXPathScanner::CHILD:
case nsXFormsXPathScanner::DESCENDANT:
case nsXFormsXPathScanner::DESCENDANT_OR_SELF:
case nsXFormsXPathScanner::FOLLOWING:
case nsXFormsXPathScanner::FOLLOWING_SIBLING:
case nsXFormsXPathScanner::NAMESPACE:
case nsXFormsXPathScanner::PARENT:
case nsXFormsXPathScanner::PRECEDING:
case nsXFormsXPathScanner::PRECEDING_SIBLING:
case nsXFormsXPathScanner::SELF:
PopToken();
case nsXFormsXPathScanner::AT:
PopToken();
break;
default:
XPathCompilerException("Not a axis specifier", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
break;
}
}
PRBool
nsXFormsXPathParser::DoRelative()
{
PRBool ret = PR_FALSE;
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::ANCESTOR:
case nsXFormsXPathScanner::ANCESTOR_OR_SELF:
case nsXFormsXPathScanner::ATTRIBUTE:
case nsXFormsXPathScanner::CHILD:
case nsXFormsXPathScanner::DESCENDANT:
case nsXFormsXPathScanner::DESCENDANT_OR_SELF:
case nsXFormsXPathScanner::FOLLOWING:
case nsXFormsXPathScanner::FOLLOWING_SIBLING:
case nsXFormsXPathScanner::NAMESPACE:
case nsXFormsXPathScanner::PARENT:
case nsXFormsXPathScanner::PRECEDING:
case nsXFormsXPathScanner::PRECEDING_SIBLING:
case nsXFormsXPathScanner::SELF:
case nsXFormsXPathScanner::AT:
case nsXFormsXPathScanner::STAR:
case nsXFormsXPathScanner::NCNAME:
case nsXFormsXPathScanner::QNAME:
case nsXFormsXPathScanner::COMMENT:
case nsXFormsXPathScanner::TEXT:
case nsXFormsXPathScanner::PI:
case nsXFormsXPathScanner::NODE:
case nsXFormsXPathScanner::DOT:
case nsXFormsXPathScanner::DOTDOT:
ret = PR_TRUE;
break;
default:
break;
}
return ret;
}
void
nsXFormsXPathParser::EqualityExpr()
{
RelationalExpression();
PRBool con = PR_TRUE;
while (con) {
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::EQUAL:
PopToken();
RelationalExpression();
break;
case nsXFormsXPathScanner::NOTEQUAL:
PopToken();
RelationalExpression();
break;
default:
con = PR_FALSE;
}
}
}
void
nsXFormsXPathParser::Expr()
{
OrExpr();
}
void
nsXFormsXPathParser::FilterExpr()
{
if (PrimaryExpr() && PeekToken() == nsXFormsXPathScanner::LBRACK) {
Predicate();
}
}
void
nsXFormsXPathParser::FunctionCall()
{
if (!mUsesDynamicFunc) {
nsDependentSubstring fname = Substring(mScanner.Expression(), mScanner.Offset() + 1, mScanner.Offset() + mScanner.Length() + 1);
if (fname.Equals(NS_LITERAL_STRING("now"))) {
mUsesDynamicFunc = PR_TRUE;
}
}
PopToken();
PopToken();
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
PRBool con = t == nsXFormsXPathScanner::RPARAN ? PR_FALSE : PR_TRUE;
while (con) {
if (t == nsXFormsXPathScanner::XPATHEOF) {
XPathCompilerException("Expected ) got EOF", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
}
nsXFormsXPathNode* c = JustContext();
Expr();
PushContext(c);
t = PeekToken();
if (t == nsXFormsXPathScanner::COMMA) {
PopToken(); // Another Argument
con = PR_TRUE;
} else {
con = PR_FALSE;
}
}
if (t != nsXFormsXPathScanner::RPARAN) {
XPathCompilerException("Expected )", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
}
PopToken();
}
void
nsXFormsXPathParser::LocationPath()
{
if (DoRelative()) {
PushContext();
RelativeLocationPath();
PopContext();
} else {
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::SLASH:
case nsXFormsXPathScanner::SLASHSLASH:
PushContext();
AbsoluteLocationPath();
PopContext();
break;
default:
XPathCompilerException("Not a location path", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
}
}
}
void
nsXFormsXPathParser::MultiplicationExpr()
{
UnaryExpr();
PRBool con = PR_TRUE;
while (con) {
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::MULTIPLYOPERATOR:
case nsXFormsXPathScanner::DIV:
case nsXFormsXPathScanner::MOD:
PopToken();
UnaryExpr();
break;
default:
con = PR_FALSE;
}
}
}
void
nsXFormsXPathParser::NameTest()
{
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::STAR:
case nsXFormsXPathScanner::NCNAME:
case nsXFormsXPathScanner::QNAME:
PopToken();
break;
default:
XPathCompilerException("NodeTest error", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
}
}
void
nsXFormsXPathParser::NodeTest()
{
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::STAR:
case nsXFormsXPathScanner::NCNAME:
case nsXFormsXPathScanner::QNAME:
NameTest();
break;
case nsXFormsXPathScanner::COMMENT:
case nsXFormsXPathScanner::TEXT:
case nsXFormsXPathScanner::PI:
case nsXFormsXPathScanner::NODE:
NodeType();
break;
default:
XPathCompilerException("Not a node test", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
}
}
void
nsXFormsXPathParser::NodeType()
{
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::COMMENT:
PopToken();
PopToken();
PopToken();
break;
case nsXFormsXPathScanner::TEXT:
PopToken();
PopToken();
PopToken();
break;
case nsXFormsXPathScanner::PI:
PopToken();
if ((t = PeekToken()) == nsXFormsXPathScanner::LPARAN) {
PopToken();
PopToken();
PopToken();
}
break;
case nsXFormsXPathScanner::NODE:
PopToken();
PopToken();
PopToken();
break;
default:
XPathCompilerException("Not a valid NodeType", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
}
}
void
nsXFormsXPathParser::OrExpr()
{
AndExpr();
if (PeekToken() == nsXFormsXPathScanner::OR) {
PopToken();
OrExpr();
}
}
void
nsXFormsXPathParser::PathExpr()
{
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::ANCESTOR:
case nsXFormsXPathScanner::ANCESTOR_OR_SELF:
case nsXFormsXPathScanner::ATTRIBUTE:
case nsXFormsXPathScanner::CHILD:
case nsXFormsXPathScanner::DESCENDANT:
case nsXFormsXPathScanner::DESCENDANT_OR_SELF:
case nsXFormsXPathScanner::FOLLOWING:
case nsXFormsXPathScanner::FOLLOWING_SIBLING:
case nsXFormsXPathScanner::NAMESPACE:
case nsXFormsXPathScanner::PARENT:
case nsXFormsXPathScanner::PRECEDING:
case nsXFormsXPathScanner::PRECEDING_SIBLING:
case nsXFormsXPathScanner::SELF:
case nsXFormsXPathScanner::AT:
case nsXFormsXPathScanner::STAR:
case nsXFormsXPathScanner::NCNAME:
case nsXFormsXPathScanner::QNAME:
case nsXFormsXPathScanner::COMMENT:
case nsXFormsXPathScanner::TEXT:
case nsXFormsXPathScanner::PI:
case nsXFormsXPathScanner::NODE:
case nsXFormsXPathScanner::DOT:
case nsXFormsXPathScanner::DOTDOT:
case nsXFormsXPathScanner::SLASH:
case nsXFormsXPathScanner::SLASHSLASH:
LocationPath();
break;
default:
PushContext();
FilterExpr();
t = PeekToken();
if (t == nsXFormsXPathScanner::SLASH || t == nsXFormsXPathScanner::SLASHSLASH) {
PopToken();
if (DoRelative()) {
RelativeLocationPath();
} else {
nsAutoString nullstr;
XPathCompilerException("After / in a filter expression it is required to have a reletive path expression", nullstr);
}
}
PopContext();
}
}
nsXFormsXPathScanner::XPATHTOKEN
nsXFormsXPathParser::PeekToken()
{
return mPeek;
}
nsXFormsXPathScanner::XPATHTOKEN
nsXFormsXPathParser::PopToken()
{
nsXFormsXPathScanner::XPATHTOKEN temp = mPeek;
mPeek = mScanner.NextToken();
if (mPeek == nsXFormsXPathScanner::WHITESPACE) { // Skip whitespaces
mPeek = mScanner.NextToken();
}
return temp;
}
void
nsXFormsXPathParser::Predicate()
{
EndContext();
mPredicateLevel++;
while (PeekToken() == nsXFormsXPathScanner::LBRACK) {
PopToken();
Expr();
nsXFormsXPathScanner::XPATHTOKEN t = PopToken();
if (t != nsXFormsXPathScanner::RBRACK) {
XPathCompilerException("Expected ]", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
}
}
mPredicateLevel--;
RestartContext();
}
PRBool
nsXFormsXPathParser::PrimaryExpr()
{
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::VARIABLE:
PopToken();
break;
case nsXFormsXPathScanner::LPARAN: {
PopToken();
nsXFormsXPathNode* c = JustContext();
Expr();
PushContext(c);
if (PeekToken() == nsXFormsXPathScanner::RPARAN) {
PopToken();
} else {
XPathCompilerException("Expected )", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
}
}
break;
case nsXFormsXPathScanner::LITERAL:
mHead->mLiteral = PR_TRUE;
PopToken();
break;
case nsXFormsXPathScanner::NUMBER:
mHead->mLiteral = PR_TRUE;
PopToken();
break;
case nsXFormsXPathScanner::FUNCTIONNAME:
FunctionCall();
return PeekToken() == nsXFormsXPathScanner::SLASH || PeekToken() == nsXFormsXPathScanner::SLASHSLASH || PeekToken() == nsXFormsXPathScanner::LBRACK;
break;
default:
XPathCompilerException("Not a primary expression", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
}
return PR_FALSE;
}
void
nsXFormsXPathParser::RelationalExpression()
{
AdditiveExpression();
PRBool con = PR_TRUE;
while (con) {
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::LESS:
PopToken();
AdditiveExpression();
break;
case nsXFormsXPathScanner::LEQUAL:
PopToken();
AdditiveExpression();
break;
case nsXFormsXPathScanner::GREATER:
PopToken();
AdditiveExpression();
break;
case nsXFormsXPathScanner::GEQUAL:
PopToken();
AdditiveExpression();
break;
default:
con = PR_FALSE;
}
}
}
void
nsXFormsXPathParser::RelativeLocationPath()
{
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::ANCESTOR:
case nsXFormsXPathScanner::ANCESTOR_OR_SELF:
case nsXFormsXPathScanner::ATTRIBUTE:
case nsXFormsXPathScanner::CHILD:
case nsXFormsXPathScanner::DESCENDANT:
case nsXFormsXPathScanner::DESCENDANT_OR_SELF:
case nsXFormsXPathScanner::FOLLOWING:
case nsXFormsXPathScanner::FOLLOWING_SIBLING:
case nsXFormsXPathScanner::NAMESPACE:
case nsXFormsXPathScanner::PARENT:
case nsXFormsXPathScanner::PRECEDING:
case nsXFormsXPathScanner::PRECEDING_SIBLING:
case nsXFormsXPathScanner::SELF:
case nsXFormsXPathScanner::AT:
case nsXFormsXPathScanner::STAR:
case nsXFormsXPathScanner::NCNAME:
case nsXFormsXPathScanner::QNAME:
case nsXFormsXPathScanner::COMMENT:
case nsXFormsXPathScanner::TEXT:
case nsXFormsXPathScanner::PI:
case nsXFormsXPathScanner::NODE:
Step();
break;
case nsXFormsXPathScanner::DOT:
case nsXFormsXPathScanner::DOTDOT:
AbbreviatedStep();
break;
default:
XPathCompilerException("Not a relative location path ", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
}
t = PeekToken();
if (t == nsXFormsXPathScanner::SLASH || t == nsXFormsXPathScanner::SLASHSLASH) {
PopToken();
if (DoRelative()) {
RelativeLocationPath();
}
}
}
void
nsXFormsXPathParser::Step()
{
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::ANCESTOR:
case nsXFormsXPathScanner::ANCESTOR_OR_SELF:
case nsXFormsXPathScanner::ATTRIBUTE:
case nsXFormsXPathScanner::CHILD:
case nsXFormsXPathScanner::DESCENDANT:
case nsXFormsXPathScanner::DESCENDANT_OR_SELF:
case nsXFormsXPathScanner::FOLLOWING:
case nsXFormsXPathScanner::FOLLOWING_SIBLING:
case nsXFormsXPathScanner::NAMESPACE:
case nsXFormsXPathScanner::PARENT:
case nsXFormsXPathScanner::PRECEDING:
case nsXFormsXPathScanner::PRECEDING_SIBLING:
case nsXFormsXPathScanner::SELF:
case nsXFormsXPathScanner::AT:
AxisSpecifier();
break;
default:
break;
}
t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::STAR:
case nsXFormsXPathScanner::NCNAME:
case nsXFormsXPathScanner::QNAME:
case nsXFormsXPathScanner::COMMENT:
case nsXFormsXPathScanner::TEXT:
case nsXFormsXPathScanner::PI:
case nsXFormsXPathScanner::NODE:
NodeTest();
break;
default:
XPathCompilerException("Expected a NodeTest expression", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
}
t = PeekToken();
if (t == nsXFormsXPathScanner::LBRACK) {
Predicate(); // set the predicates
}
}
void
nsXFormsXPathParser::UnaryExpr()
{
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::MINUS:
PopToken();
UnaryExpr();
break;
default:
UnionExpr();
}
}
void
nsXFormsXPathParser::UnionExpr()
{
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
switch (t) {
case nsXFormsXPathScanner::ANCESTOR:
case nsXFormsXPathScanner::ANCESTOR_OR_SELF:
case nsXFormsXPathScanner::ATTRIBUTE:
case nsXFormsXPathScanner::CHILD:
case nsXFormsXPathScanner::DESCENDANT:
case nsXFormsXPathScanner::DESCENDANT_OR_SELF:
case nsXFormsXPathScanner::FOLLOWING:
case nsXFormsXPathScanner::FOLLOWING_SIBLING:
case nsXFormsXPathScanner::NAMESPACE:
case nsXFormsXPathScanner::PARENT:
case nsXFormsXPathScanner::PRECEDING:
case nsXFormsXPathScanner::PRECEDING_SIBLING:
case nsXFormsXPathScanner::SELF:
case nsXFormsXPathScanner::AT:
case nsXFormsXPathScanner::STAR:
case nsXFormsXPathScanner::NCNAME:
case nsXFormsXPathScanner::QNAME:
case nsXFormsXPathScanner::COMMENT:
case nsXFormsXPathScanner::TEXT:
case nsXFormsXPathScanner::PI:
case nsXFormsXPathScanner::NODE:
case nsXFormsXPathScanner::DOT:
case nsXFormsXPathScanner::DOTDOT:
case nsXFormsXPathScanner::SLASH:
case nsXFormsXPathScanner::SLASHSLASH:
PathExpr();
t = PeekToken();
if (t == nsXFormsXPathScanner::UNION) {
PopToken();
UnionExpr();
}
break;
case nsXFormsXPathScanner::VARIABLE:
case nsXFormsXPathScanner::LPARAN:
case nsXFormsXPathScanner::LITERAL:
case nsXFormsXPathScanner::NUMBER:
case nsXFormsXPathScanner::FUNCTIONNAME:
PathExpr();
t = PeekToken();
if (t == nsXFormsXPathScanner::UNION) {
PopToken();
UnionExpr();
}
break;
default:
XPathCompilerException("Unexpected union token", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
}
}
nsXFormsXPathNode*
nsXFormsXPathParser::Parse(const nsAString& aExpression)
{
#ifdef DEBUG_XF_PARSER
printf("=====================================\n");
printf("Parsing: %s\n", NS_ConvertUCS2toUTF8(aExpression).get());
printf("=====================================\n");
#endif
mScanner.Init(aExpression);
mAnalyzeStackPointer = 0;
mPredicateLevel = 0;
mHead = nsnull;
PopToken();
PushContext();
nsXFormsXPathNode* root = mHead;
Expr();
PopContext();
#ifdef DEBUG_XF_PARSER
Dump(root);
printf("-------------------------------------\n");
#endif
return root;
}
PRBool
nsXFormsXPathParser::UsesDynamicFunc() const {
return mUsesDynamicFunc;
}
#ifdef DEBUG_XF_PARSER
void
nsXFormsXPathParser::Dump(nsXFormsXPathNode* aNode)
{
DumpWithLevel(aNode->mChild, 0);
}
void
nsXFormsXPathParser::DumpWithLevel(nsXFormsXPathNode* aNode, PRInt32 aLevel)
{
while (aNode) {
if (aNode->mStartIndex < aNode->mEndIndex) {
for (int i = 0; i < aLevel; i++) {
printf(" ");
}
if (aNode->mCon) {
printf("(+)");
} else {
printf("(|)");
}
OutputSubExpression(aNode->mStartIndex, aNode->mEndIndex);
}
DumpWithLevel(aNode->mChild, aLevel + 2);
aNode = aNode->mSibling;
}
}
void
nsXFormsXPathParser::OutputSubExpression(PRInt32 aOffset, PRInt32 aEndOffset)
{
const nsDependentSubstring expr = Substring(mScanner.Expression(), aOffset, aEndOffset - aOffset);
printf("%s\n", NS_ConvertUCS2toUTF8(expr).get());
}
#endif

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

@ -0,0 +1,112 @@
/* -*- 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
* Novell, Inc.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Allan Beaufour <abeaufour@novell.com>
* David Landwehr <dlandwehr@novell.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 "nsXFormsXPathScanner.h"
#include "nsXFormsXPathNode.h"
#define ANALYZE_STACK_SIZE 120
/**
* The XPath Expression parser. Uses nsXFormsXPathScanner to scan the expression
* and builds a parse tree of nsXFormsXPathNode's.
*
* @note Should be reimplemented and moved to Transformiix
*
*/
class nsXFormsXPathParser {
private:
nsXFormsXPathScanner mScanner;
nsXFormsXPathScanner::XPATHTOKEN mPeek;
PRBool mUsesDynamicFunc;
nsXFormsXPathNode* mHead;
int mAnalyzeStackPointer;
int mPredicateLevel;
nsXFormsXPathNode* mStack[ANALYZE_STACK_SIZE];
nsXFormsXPathScanner::XPATHTOKEN PeekToken();
nsXFormsXPathScanner::XPATHTOKEN PopToken();
void PushContext(PRInt32 aStartIndex = -100);
void PushContext(nsXFormsXPathNode* mAnalyze);
void EndContext();
void RestartContext();
nsXFormsXPathNode* JustContext();
nsXFormsXPathNode* PopContext();
PRBool DoRelative();
void AbbreviatedStep();
void AbsoluteLocationPath();
void AdditiveExpression();
void AndExpr();
void AxisSpecifier();
void EqualityExpr();
void Expr();
void FilterExpr();
void FunctionCall();
void LocationPath();
void MultiplicationExpr();
void NameTest();
void NodeTest();
void NodeType();
void OrExpr();
void PathExpr();
void Predicate();
PRBool PrimaryExpr();
void RelationalExpression();
void RelativeLocationPath();
void Step();
void UnaryExpr();
void UnionExpr();
#ifdef DEBUG_XF_PARSER
void Dump(nsXFormsXPathNode* aNode);
void DumpWithLevel(nsXFormsXPathNode* aNode, PRInt32 aLevel);
void OutputSubExpression(PRInt32 aOffset, PRInt32 aEndOffset);
#endif
public:
nsXFormsXPathParser();
~nsXFormsXPathParser();
nsXFormsXPathNode* Parse(const nsAString& aExpression);
PRBool UsesDynamicFunc() const;
};

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

@ -0,0 +1,441 @@
/* -*- 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
* Novell, Inc.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Allan Beaufour <abeaufour@novell.com>
* David Landwehr <dlandwehr@novell.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 "nsXFormsXPathScanner.h"
#include "nsXFormsXPathXMLUtil.h"
MOZ_DECL_CTOR_COUNTER(nsXFormsXPathScanner)
nsXFormsXPathScanner::nsXFormsXPathScanner()
{
MOZ_COUNT_CTOR(nsXFormsXPathScanner);
}
nsXFormsXPathScanner::nsXFormsXPathScanner(const nsAString& aExpression)
{
MOZ_COUNT_CTOR(nsXFormsXPathScanner);
Init(aExpression);
}
nsXFormsXPathScanner::~nsXFormsXPathScanner()
{
MOZ_COUNT_DTOR(nsXFormsXPathScanner);
}
void
nsXFormsXPathScanner::Init(const nsAString& aExpression)
{
mExpression = aExpression;
mSize = mExpression.Length();
mLength = 0;
mOffset = -1;
mLast = NONE;
mState = NONE;
}
PRInt32
nsXFormsXPathScanner::Length()
{
return mLength;
}
PRInt32
nsXFormsXPathScanner::Offset()
{
return mOffset;
}
nsAString&
nsXFormsXPathScanner::Expression()
{
return mExpression;
}
PRUnichar
nsXFormsXPathScanner::PopChar()
{
PRUnichar c = '\0';
mLength++;
if (mOffset + mLength < mSize) {
c = mExpression[mOffset + mLength];
}
return c;
}
PRUnichar
nsXFormsXPathScanner::PeekChar()
{
return PeekChar(mOffset + mLength + 1);
}
PRUnichar
nsXFormsXPathScanner::PeekChar(PRInt32 aOffset)
{
if (mSize > aOffset)
return mExpression[aOffset];
return '\0';
}
PRUnichar
nsXFormsXPathScanner::NextNonWhite()
{
return PeekChar(GetOffsetForNonWhite());
}
int
nsXFormsXPathScanner::GetOffsetForNonWhite()
{
PRInt32 co = mOffset + mLength + 1;
while (nsXFormsXPathXMLUtil::IsWhitespace(PeekChar(co)))
co++;
return co;
}
PRBool
nsXFormsXPathScanner::HasMoreTokens()
{
return mState != XPATHEOF;
}
nsXFormsXPathScanner::XPATHTOKEN
nsXFormsXPathScanner::NextToken()
{
if (mState != WHITESPACE)
mLast = mState;
mOffset = mOffset + mLength;
mLength = 0;
PRUnichar c = PeekChar();
if (c == '\0') {
mState = XPATHEOF;
} else if (nsXFormsXPathXMLUtil::IsDigit(c)) {
mState = ScanNumber();
} else if (c == '_' || nsXFormsXPathXMLUtil::IsLetter(c)) {
mState = ScanQName();
} else if (c == '"' || c == '\'') {
mState = ScanLiteral();
} else {
switch (c) {
case '(':
mState = LPARAN;
PopChar();
break;
case ')':
mState = RPARAN;
PopChar();
break;
case '[':
mState = LBRACK;
PopChar();
break;
case ']':
mState = RBRACK;
PopChar();
break;
case '@':
mState = AT;
PopChar();
break;
case ',':
mState = COMMA;
PopChar();
break;
case ':':
PopChar();
if (PeekChar() == ':') {
mState = COLONCOLON;
PopChar();
} else
mState = ERRORXPATHTOKEN;
break;
case '.':
PopChar();
if (PeekChar() == '.') {
mState = DOTDOT;
PopChar();
} else if (nsXFormsXPathXMLUtil::IsDigit(PeekChar()))
mState = ScanNumber();
else
mState = DOT;
break;
case '$':
mState = ScanVariable();
break;
case '/':
PopChar();
if (PeekChar() == '/') {
mState = SLASHSLASH;
PopChar();
} else
mState = SLASH;
break;
case '|':
PopChar();
mState = UNION;
break;
case '+':
PopChar();
mState = PLUS;
break;
case '-':
PopChar();
mState = MINUS;
break;
case '=':
PopChar();
mState = EQUAL;
break;
case '!':
PopChar();
if (PeekChar() == '=') {
mState = NOTEQUAL;
PopChar();
} else
mState = ERRORXPATHTOKEN;
break;
case '<':
PopChar();
if (PeekChar() == '=') {
mState = LEQUAL;
PopChar();
} else
mState = LESS;
break;
case '>':
PopChar();
if (PeekChar() == '=') {
mState = GEQUAL;
PopChar();
} else
mState = GREATER;
break;
case '*':
PopChar();
mState = SolveStar();
break;
case '\r':
case '\n':
case '\t':
case ' ':
mState = ScanWhitespace();
break;
default:
PopChar();
mState = ERRORXPATHTOKEN;
}
}
return mState;
}
PRBool
nsXFormsXPathScanner::SolveDiambiguate()
{
return mLast != NONE && (mLast != AT && mLast != COLONCOLON && mLast != LPARAN && mLast != LBRACK &&
mLast != AND && mLast != OR && mLast != DIV && mLast != MOD && mLast != SLASH && mLast != MULTIPLYOPERATOR &&
mLast != SLASHSLASH && mLast != UNION && mLast != PLUS && mLast != MINUS && mLast != NOTEQUAL && mLast != EQUAL && mLast != LESS &&
mLast != LEQUAL && mLast != GEQUAL && mLast != GREATER && mLast != COMMA);
}
nsXFormsXPathScanner::XPATHTOKEN
nsXFormsXPathScanner::SolveStar()
{
if (SolveDiambiguate())
return MULTIPLYOPERATOR;
return STAR;
}
nsXFormsXPathScanner::XPATHTOKEN
nsXFormsXPathScanner::ScanNumber()
{
PRUnichar c = PopChar();
PRBool decimal = (c == '.');
while (c != '\0') {
c = PeekChar();
if (!decimal && c == '.') {
decimal = PR_TRUE;
} else if (!nsXFormsXPathXMLUtil::IsDigit(c)) {
return NUMBER;
}
PopChar();
}
return NUMBER;
}
nsXFormsXPathScanner::XPATHTOKEN
nsXFormsXPathScanner::ScanVariable()
{
PopChar();
if (ScanQName() != ERRORXPATHTOKEN)
return VARIABLE;
return ERRORXPATHTOKEN;
}
nsXFormsXPathScanner::XPATHTOKEN
nsXFormsXPathScanner::ScanWhitespace()
{
PRUnichar c;
do {
PopChar();
c = PeekChar();
} while (nsXFormsXPathXMLUtil::IsWhitespace(c));
return WHITESPACE;
}
nsXFormsXPathScanner::XPATHTOKEN
nsXFormsXPathScanner::ScanLiteral()
{
PRUnichar c = PopChar();
PRUnichar p;
while ((p = PeekChar()) != c && p != '\0')
PopChar();
if (p == '\0')
return ERRORXPATHTOKEN;
PopChar();
return LITERAL;
}
nsXFormsXPathScanner::XPATHTOKEN
nsXFormsXPathScanner::ScanQName()
{
XPATHTOKEN second = NONE;
ScanNCName();
if (PeekChar() == ':' && PeekChar(mOffset + mLength + 2) != ':') {
PopChar();
second = ScanNCName();
}
// TODO: nsSubString and .Equals() ?
nsDependentSubstring image = Substring(mExpression, Offset());
if (SolveDiambiguate()) {
if (image.EqualsASCII("and", 3))
return AND;
else if (image.EqualsASCII("or", 2))
return OR;
else if (image.EqualsASCII("mod", 3))
return MOD;
else if (image.EqualsASCII("div", 3))
return DIV;
return ERRORXPATHTOKEN;
}
PRUnichar c = NextNonWhite();
if (c == '(') {
if (image.EqualsASCII("comment", 7))
return COMMENT;
else if (image.EqualsASCII("text", 4))
return TEXT;
else if (image.EqualsASCII("processing-instruction", 22))
return PI;
else if (image.EqualsASCII("node", 4))
return NODE;
return FUNCTIONNAME;
}
PRInt32 of = GetOffsetForNonWhite();
if (PeekChar(of) == ':' && PeekChar(of + 1) == ':') {
if (image.EqualsASCII("ancestor", 8))
return ANCESTOR;
else if (image.EqualsASCII("ancestor-or-self", 16))
return ANCESTOR_OR_SELF;
else if (image.EqualsASCII("attribute", 9))
return ATTRIBUTE;
else if (image.EqualsASCII("child", 5))
return CHILD;
else if (image.EqualsASCII("descendant", 10))
return DESCENDANT;
else if (image.EqualsASCII("descendant-or-self", 18))
return DESCENDANT_OR_SELF;
else if (image.EqualsASCII("following", 9))
return FOLLOWING;
else if (image.EqualsASCII("following-sibling", 17))
return FOLLOWING_SIBLING;
else if (image.EqualsASCII("namespace", 9))
return NAMESPACE;
else if (image.EqualsASCII("parent", 6))
return PARENT;
else if (image.EqualsASCII("preceding", 9))
return PRECEDING;
else if (image.EqualsASCII("preceding-sibling", 17))
return PRECEDING_SIBLING;
else if (image.EqualsASCII("self", 4))
return SELF;
return ERRORXPATHTOKEN;
}
return second != NONE ? QNAME : NCNAME;
}
nsXFormsXPathScanner::XPATHTOKEN
nsXFormsXPathScanner::ScanNCName()
{
PRUnichar c = PopChar();
if (c != '_' && !nsXFormsXPathXMLUtil::IsLetter(c)) {
return ERRORXPATHTOKEN;
}
while (nsXFormsXPathXMLUtil::IsNCNameChar(PeekChar())) {
PopChar();
}
return NCNAME;
}

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

@ -0,0 +1,101 @@
/* -*- 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
* Novell, Inc.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Allan Beaufour <abeaufour@novell.com>
* David Landwehr <dlandwehr@novell.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 __NSXFORMSXPATHSCANNER_H__
#define __NSXFORMSXPATHSCANNER_H__
#include "nsString.h"
/**
* The XPath Expression scanner, used by nsXFormsXPathParser.
*
* @note Should be reimplemented and moved to Transformiix
*
*/
class nsXFormsXPathScanner
{
public:
enum XPATHTOKEN {
LPARAN, RPARAN, LBRACK, RBRACK, AT, COMMA,
COLONCOLON, DOT, DOTDOT, SLASH, SLASHSLASH, UNION,
PLUS, MINUS, EQUAL, NOTEQUAL, LEQUAL, LESS, GEQUAL,
GREATER, MULTIPLYOPERATOR, WHITESPACE, NUMBER,
LITERAL, AND, OR, MOD, DIV, NODE, PI, TEXT, COMMENT,
FUNCTIONNAME, NCNAME, QNAME, VARIABLE, STAR, ANCESTOR,
ANCESTOR_OR_SELF, ATTRIBUTE, CHILD, DESCENDANT,
DESCENDANT_OR_SELF, FOLLOWING, FOLLOWING_SIBLING, NAMESPACE,
PARENT, PRECEDING, PRECEDING_SIBLING, SELF, XPATHEOF, ERRORXPATHTOKEN, NONE
};
private:
XPATHTOKEN mState, mLast;
nsAutoString mExpression;
PRInt32 mOffset, mLength, mSize;
PRUnichar PopChar();
PRUnichar PeekChar();
PRUnichar PeekChar(PRInt32 offset);
PRUnichar NextNonWhite();
PRInt32 GetOffsetForNonWhite();
PRBool SolveDiambiguate();
XPATHTOKEN SolveStar();
XPATHTOKEN ScanNumber();
XPATHTOKEN ScanVariable();
XPATHTOKEN ScanWhitespace();
XPATHTOKEN ScanLiteral();
XPATHTOKEN ScanQName();
XPATHTOKEN ScanNCName();
public:
nsXFormsXPathScanner();
nsXFormsXPathScanner(const nsAString& aExpression);
~nsXFormsXPathScanner();
void Init(const nsAString& aExpression);
XPATHTOKEN NextToken();
PRInt32 Offset();
PRInt32 Length();
void Image(PRInt32& aOffset, PRInt32& aLength);
PRBool HasMoreTokens();
nsAString& Expression();
};
#endif

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

@ -0,0 +1,137 @@
/* -*- 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
* Novell, Inc.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Allan Beaufour <abeaufour@novell.com>
* David Landwehr <dlandwehr@novell.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 "nsXFormsXPathXMLUtil.h"
static const PRUint32 BASECHAR_RANGE_LENGTH = 404;
static const PRUnichar BASECHAR_RANGE[] = {
L'\x0041',L'\x005a',L'\x0061',L'\x007a',L'\x00c0',L'\x00d6',L'\x00d8',L'\x00f6',L'\x00f8',L'\x00ff',L'\x0100',L'\x0131',L'\x0134',L'\x013e',L'\x0141',L'\x0148',L'\x014a',L'\x017e',L'\x0180',L'\x01c3',L'\x01cd',L'\x01f0',L'\x01f4',L'\x01f5',L'\x01fa',L'\x0217',L'\x0250',L'\x02a8',L'\x02bb',L'\x02c1',L'\x0386',L'\x0386',L'\x0388',L'\x038a',L'\x038c',L'\x038c',L'\x038e',L'\x03a1',L'\x03a3',L'\x03ce'
,L'\x03d0',L'\x03d6',L'\x03da',L'\x03da',L'\x03dc',L'\x03dc',L'\x03de',L'\x03de',L'\x03e0',L'\x03e0',L'\x03e2',L'\x03f3',L'\x0401',L'\x040c',L'\x040e',L'\x044f',L'\x0451',L'\x045c',L'\x045e',L'\x0481',L'\x0490',L'\x04c4',L'\x04c7',L'\x04c8',L'\x04cb',L'\x04cc',L'\x04d0',L'\x04eb',L'\x04ee',L'\x04f5',L'\x04f8',L'\x04f9',L'\x0531',L'\x0556',L'\x0559',L'\x0559',L'\x0561',L'\x0586',L'\x05d0',L'\x05ea'
,L'\x05f0',L'\x05f2',L'\x0621',L'\x063a',L'\x0641',L'\x064a',L'\x0671',L'\x06b7',L'\x06ba',L'\x06be',L'\x06c0',L'\x06ce',L'\x06d0',L'\x06d3',L'\x06d5',L'\x06d5',L'\x06e5',L'\x06e6',L'\x0905',L'\x0939',L'\x093d',L'\x093d',L'\x0958',L'\x0961',L'\x0985',L'\x098c',L'\x098f',L'\x0990',L'\x0993',L'\x09a8',L'\x09aa',L'\x09b0',L'\x09b2',L'\x09b2',L'\x09b6',L'\x09b9',L'\x09dc',L'\x09dd',L'\x09df',L'\x09e1'
,L'\x09f0',L'\x09f1',L'\x0a05',L'\x0a0a',L'\x0a0f',L'\x0a10',L'\x0a13',L'\x0a28',L'\x0a2a',L'\x0a30',L'\x0a32',L'\x0a33',L'\x0a35',L'\x0a36',L'\x0a38',L'\x0a39',L'\x0a59',L'\x0a5c',L'\x0a5e',L'\x0a5e',L'\x0a72',L'\x0a74',L'\x0a85',L'\x0a8b',L'\x0a8d',L'\x0a8d',L'\x0a8f',L'\x0a91',L'\x0a93',L'\x0aa8',L'\x0aaa',L'\x0ab0',L'\x0ab2',L'\x0ab3',L'\x0ab5',L'\x0ab9',L'\x0abd',L'\x0abd',L'\x0ae0',L'\x0ae0'
,L'\x0b05',L'\x0b0c',L'\x0b0f',L'\x0b10',L'\x0b13',L'\x0b28',L'\x0b2a',L'\x0b30',L'\x0b32',L'\x0b33',L'\x0b36',L'\x0b39',L'\x0b3d',L'\x0b3d',L'\x0b5c',L'\x0b5d',L'\x0b5f',L'\x0b61',L'\x0b85',L'\x0b8a',L'\x0b8e',L'\x0b90',L'\x0b92',L'\x0b95',L'\x0b99',L'\x0b9a',L'\x0b9c',L'\x0b9c',L'\x0b9e',L'\x0b9f',L'\x0ba3',L'\x0ba4',L'\x0ba8',L'\x0baa',L'\x0bae',L'\x0bb5',L'\x0bb7',L'\x0bb9',L'\x0c05',L'\x0c0c'
,L'\x0c0e',L'\x0c10',L'\x0c12',L'\x0c28',L'\x0c2a',L'\x0c33',L'\x0c35',L'\x0c39',L'\x0c60',L'\x0c61',L'\x0c85',L'\x0c8c',L'\x0c8e',L'\x0c90',L'\x0c92',L'\x0ca8',L'\x0caa',L'\x0cb3',L'\x0cb5',L'\x0cb9',L'\x0cde',L'\x0cde',L'\x0ce0',L'\x0ce1',L'\x0d05',L'\x0d0c',L'\x0d0e',L'\x0d10',L'\x0d12',L'\x0d28',L'\x0d2a',L'\x0d39',L'\x0d60',L'\x0d61',L'\x0e01',L'\x0e2e',L'\x0e30',L'\x0e30',L'\x0e32',L'\x0e33'
,L'\x0e40',L'\x0e45',L'\x0e81',L'\x0e82',L'\x0e84',L'\x0e84',L'\x0e87',L'\x0e88',L'\x0e8a',L'\x0e8a',L'\x0e8d',L'\x0e8d',L'\x0e94',L'\x0e97',L'\x0e99',L'\x0e9f',L'\x0ea1',L'\x0ea3',L'\x0ea5',L'\x0ea5',L'\x0ea7',L'\x0ea7',L'\x0eaa',L'\x0eab',L'\x0ead',L'\x0eae',L'\x0eb0',L'\x0eb0',L'\x0eb2',L'\x0eb3',L'\x0ebd',L'\x0ebd',L'\x0ec0',L'\x0ec4',L'\x0f40',L'\x0f47',L'\x0f49',L'\x0f69',L'\x10a0',L'\x10c5'
,L'\x10d0',L'\x10f6',L'\x1100',L'\x1100',L'\x1102',L'\x1103',L'\x1105',L'\x1107',L'\x1109',L'\x1109',L'\x110b',L'\x110c',L'\x110e',L'\x1112',L'\x113c',L'\x113c',L'\x113e',L'\x113e',L'\x1140',L'\x1140',L'\x114c',L'\x114c',L'\x114e',L'\x114e',L'\x1150',L'\x1150',L'\x1154',L'\x1155',L'\x1159',L'\x1159',L'\x115f',L'\x1161',L'\x1163',L'\x1163',L'\x1165',L'\x1165',L'\x1167',L'\x1167',L'\x1169',L'\x1169'
,L'\x116d',L'\x116e',L'\x1172',L'\x1173',L'\x1175',L'\x1175',L'\x119e',L'\x119e',L'\x11a8',L'\x11a8',L'\x11ab',L'\x11ab',L'\x11ae',L'\x11af',L'\x11b7',L'\x11b8',L'\x11ba',L'\x11ba',L'\x11bc',L'\x11c2',L'\x11eb',L'\x11eb',L'\x11f0',L'\x11f0',L'\x11f9',L'\x11f9',L'\x1e00',L'\x1e9b',L'\x1ea0',L'\x1ef9',L'\x1f00',L'\x1f15',L'\x1f18',L'\x1f1d',L'\x1f20',L'\x1f45',L'\x1f48',L'\x1f4d',L'\x1f50',L'\x1f57'
,L'\x1f59',L'\x1f59',L'\x1f5b',L'\x1f5b',L'\x1f5d',L'\x1f5d',L'\x1f5f',L'\x1f7d',L'\x1f80',L'\x1fb4',L'\x1fb6',L'\x1fbc',L'\x1fbe',L'\x1fbe',L'\x1fc2',L'\x1fc4',L'\x1fc6',L'\x1fcc',L'\x1fd0',L'\x1fd3',L'\x1fd6',L'\x1fdb',L'\x1fe0',L'\x1fec',L'\x1ff2',L'\x1ff4',L'\x1ff6',L'\x1ffc',L'\x2126',L'\x2126',L'\x212a',L'\x212b',L'\x212e',L'\x212e',L'\x2180',L'\x2182',L'\x3041',L'\x3094',L'\x30a1',L'\x30fa'
,L'\x3105',L'\x312c',L'\xac00',L'\xd7a3'};
static const PRUint32 IDEOGRAPHIC_RANGE_LENGTH = 6;
static const PRUnichar IDEOGRAPHIC_RANGE[] = {
L'\x4e00',L'\x9fa5',L'\x3007',L'\x3007',L'\x3021',L'\x3029'
};
static const PRUint32 COMBINING_CHAR_RANGE_LENGTH = 190;
static const PRUnichar COMBINING_CHAR_RANGE[] = {
L'\x0300',L'\x0345',L'\x0360',L'\x0361',L'\x0483',L'\x0486',L'\x0591',L'\x05a1',L'\x05a3',L'\x05b9',L'\x05bb',L'\x05bd',L'\x05bf',L'\x05bf',L'\x05c1',L'\x05c2',L'\x05c4',L'\x05c4',L'\x064b',L'\x0652',L'\x0670',L'\x0670',L'\x06d6',L'\x06dc',L'\x06dd',L'\x06df',L'\x06e0',L'\x06e4',L'\x06e7',L'\x06e8',L'\x06ea',L'\x06ed',L'\x0901',L'\x0903',L'\x093c',L'\x093c',L'\x093e',L'\x094c',L'\x094d',L'\x094d'
,L'\x0951',L'\x0954',L'\x0962',L'\x0963',L'\x0981',L'\x0983',L'\x09bc',L'\x09bc',L'\x09be',L'\x09be',L'\x09bf',L'\x09bf',L'\x09c0',L'\x09c4',L'\x09c7',L'\x09c8',L'\x09cb',L'\x09cd',L'\x09d7',L'\x09d7',L'\x09e2',L'\x09e3',L'\x0a02',L'\x0a02',L'\x0a3c',L'\x0a3c',L'\x0a3e',L'\x0a3e',L'\x0a3f',L'\x0a3f',L'\x0a40',L'\x0a42',L'\x0a47',L'\x0a48',L'\x0a4b',L'\x0a4d',L'\x0a70',L'\x0a71',L'\x0a81',L'\x0a83'
,L'\x0abc',L'\x0abc',L'\x0abe',L'\x0ac5',L'\x0ac7',L'\x0ac9',L'\x0acb',L'\x0acd',L'\x0b01',L'\x0b03',L'\x0b3c',L'\x0b3c',L'\x0b3e',L'\x0b43',L'\x0b47',L'\x0b48',L'\x0b4b',L'\x0b4d',L'\x0b56',L'\x0b57',L'\x0b82',L'\x0b83',L'\x0bbe',L'\x0bc2',L'\x0bc6',L'\x0bc8',L'\x0bca',L'\x0bcd',L'\x0bd7',L'\x0bd7',L'\x0c01',L'\x0c03',L'\x0c3e',L'\x0c44',L'\x0c46',L'\x0c48',L'\x0c4a',L'\x0c4d',L'\x0c55',L'\x0c56'
,L'\x0c82',L'\x0c83',L'\x0cbe',L'\x0cc4',L'\x0cc6',L'\x0cc8',L'\x0cca',L'\x0ccd',L'\x0cd5',L'\x0cd6',L'\x0d02',L'\x0d03',L'\x0d3e',L'\x0d43',L'\x0d46',L'\x0d48',L'\x0d4a',L'\x0d4d',L'\x0d57',L'\x0d57',L'\x0e31',L'\x0e31',L'\x0e34',L'\x0e3a',L'\x0e47',L'\x0e4e',L'\x0eb1',L'\x0eb1',L'\x0eb4',L'\x0eb9',L'\x0ebb',L'\x0ebc',L'\x0ec8',L'\x0ecd',L'\x0f18',L'\x0f19',L'\x0f35',L'\x0f35',L'\x0f37',L'\x0f37'
,L'\x0f39',L'\x0f39',L'\x0f3e',L'\x0f3e',L'\x0f3f',L'\x0f3f',L'\x0f71',L'\x0f84',L'\x0f86',L'\x0f8b',L'\x0f90',L'\x0f95',L'\x0f97',L'\x0f97',L'\x0f99',L'\x0fad',L'\x0fb1',L'\x0fb7',L'\x0fb9',L'\x0fb9',L'\x20d0',L'\x20dc',L'\x20e1',L'\x20e1',L'\x302a',L'\x302f',L'\x3099',L'\x3099',L'\x309a',L'\x309a'
};
static const PRUint32 DIGIT_RANGE_LENGTH = 30;
static const PRUnichar DIGIT_RANGE[] = {
L'\x0030',L'\x0039',L'\x0660',L'\x0669',L'\x06f0',L'\x06f9',L'\x0966',L'\x096f',L'\x09e6',L'\x09ef',L'\x0a66',L'\x0a6f',L'\x0ae6',L'\x0aef',L'\x0b66',L'\x0b6f',L'\x0be7',L'\x0bef',L'\x0c66',L'\x0c6f',L'\x0ce6',L'\x0cef',L'\x0d66',L'\x0d6f',L'\x0e50',L'\x0e59',L'\x0ed0',L'\x0ed9',L'\x0f20',L'\x0f29'
};
static const PRUint32 EXTENDER_RANGE_LENGTH = 22;
static const PRUnichar EXTENDER_RANGE[] = {
L'\x00b7',L'\x00b7',L'\x02d0',L'\x02d0',L'\x02d1',L'\x02d1',L'\x0387',L'\x0387',L'\x0640',L'\x0640',L'\x0e46',L'\x0e46',L'\x0ec6',L'\x0ec6',L'\x3005',L'\x3005',L'\x3031',L'\x3035',L'\x309d',L'\x309e',L'\x30fc',L'\x30fe'
};
PRBool
nsXFormsXPathXMLUtil::IsInRange(const PRUnichar* range, const PRUint32 range_length, const PRUnichar c)
{
PRBool inrange = false;
for (PRUint32 i = 0; !inrange && c >= range[i] && i < range_length; i += 2) {
inrange = c >= range[i] && c <= range[i + 1];
}
return inrange;
}
PRBool
nsXFormsXPathXMLUtil::IsWhitespace(const PRUnichar c)
{
return (c == L'\r' || c == L' ' || c == L'\n' || c == L'\t');
}
PRBool
nsXFormsXPathXMLUtil::IsDigit(const PRUnichar c)
{
return IsInRange(DIGIT_RANGE, DIGIT_RANGE_LENGTH, c);
}
PRBool
nsXFormsXPathXMLUtil::IsIdeographic(const PRUnichar c)
{
return IsInRange(IDEOGRAPHIC_RANGE, IDEOGRAPHIC_RANGE_LENGTH, c);
}
PRBool
nsXFormsXPathXMLUtil::IsLetter(const PRUnichar c)
{
return IsBaseChar(c) || IsIdeographic(c);
}
PRBool
nsXFormsXPathXMLUtil::IsBaseChar(const PRUnichar c)
{
return IsInRange(BASECHAR_RANGE, BASECHAR_RANGE_LENGTH, c);
}
PRBool
nsXFormsXPathXMLUtil::IsNCNameChar(const PRUnichar c)
{
return IsLetter(c) || IsDigit(c) || c == L'.' || c == L'-' || c == L'_' || IsCombiningChar(c) || IsExtender(c);
}
PRBool
nsXFormsXPathXMLUtil::IsCombiningChar(const PRUnichar c)
{
return IsInRange(COMBINING_CHAR_RANGE, COMBINING_CHAR_RANGE_LENGTH, c);
}
PRBool
nsXFormsXPathXMLUtil::IsExtender(const PRUnichar c)
{
return IsInRange(EXTENDER_RANGE, EXTENDER_RANGE_LENGTH, c);
}

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

@ -0,0 +1,78 @@
/* -*- 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
* Novell, Inc.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Allan Beaufour <abeaufour@novell.com>
* David Landwehr <dlandwehr@novell.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 "nsString.h"
/**
* Misc. utility functions for determining the class of a character, used by
* nsXFormsXPathScanner.
*
* @note Should be reimplemented and moved to Transformiix
*
*/
class nsXFormsXPathXMLUtil {
private:
/** Helper function for public functions */
static PRBool IsInRange(const PRUnichar* range, const PRUint32 range_length, const PRUnichar c);
public:
/** Checks if a char is a whitespace */
static PRBool IsWhitespace(const PRUnichar c);
/** Checks of a char is a digit */
static PRBool IsDigit(const PRUnichar c);
/** Checks if a char is an ideographic */
static PRBool IsIdeographic(const PRUnichar c);
/** Checks if a char is a letter */
static PRBool IsLetter(const PRUnichar c);
/** Checks if a char is a base char */
static PRBool IsBaseChar(const PRUnichar c);
/** Check is a char matches the first rule of a NCName */
static PRBool IsNCNameChar(const PRUnichar c);
/** Check if a char is a combining char */
static PRBool IsCombiningChar(const PRUnichar c);
/** Check if a char is an extender */
static PRBool IsExtender(const PRUnichar c);
};