1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is Mozilla XForms support.
17 * The Initial Developer of the Original Code is
19 * Portions created by the Initial Developer are Copyright (C) 2004
20 * the Initial Developer. All Rights Reserved.
23 * Brian Ryner <bryner@brianryner.com>
24 * Allan Beaufour <abeaufour@novell.com>
25 * Darin Fisher <darin@meer.net>
26 * Olli Pettay <Olli.Pettay@helsinki.fi>
28 * Alternatively, the contents of this file may be used under the terms of
29 * either the GNU General Public License Version 2 or later (the "GPL"), or
30 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
40 * ***** END LICENSE BLOCK ***** */
42 #include "nsXFormsModelElement.h"
43 #include "nsIXTFElementWrapper.h"
45 #include "nsIDOMElement.h"
46 #include "nsIDOM3Node.h"
47 #include "nsIDOMNodeList.h"
49 #include "nsIDocument.h"
50 #include "nsXFormsAtoms.h"
51 #include "nsINameSpaceManager.h"
52 #include "nsIServiceManager.h"
53 #include "nsIDOMEvent.h"
54 #include "nsIDOMDOMImplementation.h"
55 #include "nsIDOMXMLDocument.h"
56 #include "nsIDOMEventTarget.h"
57 #include "nsIDOMXPathResult.h"
58 #include "nsIDOMXPathEvaluator.h"
59 #include "nsIXPathEvaluatorInternal.h"
60 #include "nsIDOMXPathExpression.h"
61 #include "nsIDOMXPathNSResolver.h"
62 #include "nsIDOMNSXPathExpression.h"
63 #include "nsIContent.h"
65 #include "nsNetUtil.h"
66 #include "nsIXFormsControl.h"
67 #include "nsXFormsTypes.h"
68 #include "nsXFormsXPathParser.h"
69 #include "nsXFormsXPathAnalyzer.h"
70 #include "nsIInstanceElementPrivate.h"
71 #include "nsXFormsUtils.h"
72 #include "nsXFormsSchemaValidator.h"
73 #include "nsIXFormsUIWidget.h"
74 #include "nsIAttribute.h"
75 #include "nsISchemaLoader.h"
76 #include "nsISchema.h"
77 #include "nsAutoPtr.h"
78 #include "nsIDOMDocumentXBL.h"
79 #include "nsIProgrammingLanguage.h"
80 #include "nsDOMError.h"
81 #include "nsXFormsControlStub.h"
82 #include "nsIPrefService.h"
83 #include "nsIPrefBranch.h"
84 #include "nsIEventStateManager.h"
85 #include "nsStringEnumerator.h"
87 #define XFORMS_LAZY_INSTANCE_BINDING \
88 "chrome://xforms/content/xforms.xml#xforms-lazy-instance"
94 //------------------------------------------------------------------------------
96 // Helper function for using XPath to locate an <xsd:schema> element by
97 // matching its "id" attribute. This is necessary since <xsd:schema> is
98 // treated as an ordinary XML data node without an "ID" attribute.
100 GetSchemaElementById(nsIDOMElement
*contextNode
,
102 nsIDOMElement
**resultNode
)
104 // search for an element with the given "id" attribute, and then verify
105 // that the element is in the XML Schema namespace.
108 expr
.AssignLiteral("//*[@id=\"");
110 expr
.AppendLiteral("\"]");
112 nsCOMPtr
<nsIDOMXPathResult
> xpRes
;
114 nsXFormsUtils::EvaluateXPath(expr
,
117 nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE
,
118 getter_AddRefs(xpRes
));
119 if (NS_SUCCEEDED(rv
) && xpRes
) {
120 nsCOMPtr
<nsIDOMNode
> node
;
121 xpRes
->GetSingleNodeValue(getter_AddRefs(node
));
124 node
->GetNamespaceURI(ns
);
125 if (ns
.EqualsLiteral(NS_NAMESPACE_XML_SCHEMA
))
126 CallQueryInterface(node
, resultNode
);
131 //------------------------------------------------------------------------------
134 DeleteVoidArray(void *aObject
,
135 nsIAtom
*aPropertyName
,
136 void *aPropertyValue
,
139 delete static_cast<nsVoidArray
*>(aPropertyValue
);
143 AddToModelList(nsIDOMDocument
*domDoc
, nsXFormsModelElement
*model
)
145 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(domDoc
);
147 nsVoidArray
*models
=
148 static_cast<nsVoidArray
*>
149 (doc
->GetProperty(nsXFormsAtoms::modelListProperty
));
151 models
= new nsVoidArray(16);
153 return NS_ERROR_OUT_OF_MEMORY
;
154 doc
->SetProperty(nsXFormsAtoms::modelListProperty
, models
, DeleteVoidArray
);
156 models
->AppendElement(model
);
161 RemoveFromModelList(nsIDOMDocument
*domDoc
, nsXFormsModelElement
*model
)
163 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(domDoc
);
165 nsVoidArray
*models
=
166 static_cast<nsVoidArray
*>
167 (doc
->GetProperty(nsXFormsAtoms::modelListProperty
));
169 models
->RemoveElement(model
);
172 static const nsVoidArray
*
173 GetModelList(nsIDOMDocument
*domDoc
)
175 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(domDoc
);
177 return static_cast<nsVoidArray
*>
178 (doc
->GetProperty(nsXFormsAtoms::modelListProperty
));
182 SupportsDtorFunc(void *aObject
, nsIAtom
*aPropertyName
,
183 void *aPropertyValue
, void *aData
)
185 nsISupports
*propertyValue
= static_cast<nsISupports
*>(aPropertyValue
);
186 NS_IF_RELEASE(propertyValue
);
190 //------------------------------------------------------------------------------
191 // --- nsXFormsControlListItem ---
194 nsXFormsControlListItem::iterator::iterator()
199 nsXFormsControlListItem::iterator::iterator(const nsXFormsControlListItem::iterator
& aCopy
)
202 mStack
= aCopy
.mStack
;
205 nsXFormsControlListItem::iterator
206 nsXFormsControlListItem::iterator::operator=(nsXFormsControlListItem
* aCnt
)
213 nsXFormsControlListItem::iterator::operator!=(const nsXFormsControlListItem
* aCnt
)
218 nsXFormsControlListItem::iterator
219 nsXFormsControlListItem::iterator::operator++()
224 if (mCur
->mFirstChild
) {
225 if (!mCur
->mNextSibling
) {
226 mCur
= mCur
->mFirstChild
;
229 mStack
.AppendElement(mCur
->mFirstChild
);
232 if (mCur
->mNextSibling
) {
233 mCur
= mCur
->mNextSibling
;
234 } else if (mStack
.Count()) {
235 mCur
= (nsXFormsControlListItem
*) mStack
[mStack
.Count() - 1];
236 mStack
.RemoveElementAt(mStack
.Count() - 1);
244 nsXFormsControlListItem
*
245 nsXFormsControlListItem::iterator::operator*()
250 nsXFormsControlListItem::nsXFormsControlListItem(
251 nsIXFormsControl
* aControl
,
252 nsRefPtrHashtable
<nsISupportsHashKey
,nsXFormsControlListItem
>* aHashtable
)
254 mNextSibling(nsnull
),
256 mControlListHash(aHashtable
)
261 nsXFormsControlListItem::~nsXFormsControlListItem()
266 nsXFormsControlListItem::nsXFormsControlListItem(const nsXFormsControlListItem
& aCopy
)
269 if (aCopy
.mNextSibling
) {
270 mNextSibling
= new nsXFormsControlListItem(*aCopy
.mNextSibling
);
271 NS_WARN_IF_FALSE(mNextSibling
, "could not new?!");
273 mNextSibling
= nsnull
;
276 if (aCopy
.mFirstChild
) {
277 mFirstChild
= new nsXFormsControlListItem(*aCopy
.mFirstChild
);
278 NS_WARN_IF_FALSE(mFirstChild
, "could not new?!");
280 mFirstChild
= nsnull
;
285 nsXFormsControlListItem::Clear()
288 mFirstChild
->Clear();
289 NS_ASSERTION(!(mFirstChild
->mFirstChild
|| mFirstChild
->mNextSibling
),
290 "child did not clear members!!");
291 mFirstChild
= nsnull
;
294 mNextSibling
->Clear();
295 NS_ASSERTION(!(mNextSibling
->mFirstChild
|| mNextSibling
->mNextSibling
),
296 "sibling did not clear members!!");
297 mNextSibling
= nsnull
;
300 /* we won't bother removing each item one by one from the hashtable. This
301 * approach assumes that we are clearing the whole model's list of controls
302 * due to the model going away. After the model clears this list, it will
303 * clear the hashtable all at once.
305 mControlListHash
= nsnull
;
311 nsXFormsControlListItem::AddControl(nsIXFormsControl
*aControl
,
312 nsIXFormsControl
*aParent
)
314 // Four insertion posibilities:
316 // 1) Delegate to first child from root node
317 if (!mNode
&& mFirstChild
) {
318 return mFirstChild
->AddControl(aControl
, aParent
);
321 // 2) control with no parent
323 nsRefPtr
<nsXFormsControlListItem
> newNode
=
324 new nsXFormsControlListItem(aControl
, mControlListHash
);
325 NS_ENSURE_TRUE(newNode
, NS_ERROR_OUT_OF_MEMORY
);
327 // Empty tree (we have already checked mFirstChild)
329 mFirstChild
= newNode
;
330 nsCOMPtr
<nsIDOMElement
> ele
;
331 aControl
->GetElement(getter_AddRefs(ele
));
332 mControlListHash
->Put(ele
, newNode
);
337 newNode
->mNextSibling
= mNextSibling
;
339 mNextSibling
= newNode
;
340 nsCOMPtr
<nsIDOMElement
> ele
;
341 aControl
->GetElement(getter_AddRefs(ele
));
342 mControlListHash
->Put(ele
, newNode
);
344 nsXFormsControlListItem
* next
= newNode
->mNextSibling
;
346 NS_ASSERTION(aControl
!= next
->mNode
,
347 "Node already in tree!!");
348 next
= next
->mNextSibling
;
356 nsXFormsControlListItem
* parentControl
= FindControl(aParent
);
357 NS_ASSERTION(parentControl
, "Parent not found?!");
359 // 3) parentControl has a first child, insert as sibling to that
360 if (parentControl
->mFirstChild
) {
361 return parentControl
->mFirstChild
->AddControl(aControl
, nsnull
);
364 // 4) first child for parentControl
365 nsRefPtr
<nsXFormsControlListItem
> newNode
=
366 new nsXFormsControlListItem(aControl
, mControlListHash
);
367 NS_ENSURE_TRUE(newNode
, NS_ERROR_OUT_OF_MEMORY
);
369 parentControl
->mFirstChild
= newNode
;
370 nsCOMPtr
<nsIDOMElement
> ele
;
371 aControl
->GetElement(getter_AddRefs(ele
));
372 mControlListHash
->Put(ele
, newNode
);
378 nsXFormsControlListItem::RemoveControl(nsIXFormsControl
*aControl
,
381 nsXFormsControlListItem
* deleteMe
= nsnull
;
386 // The control to remove is our first child
387 if (mFirstChild
->mNode
== aControl
) {
388 deleteMe
= mFirstChild
;
391 if (deleteMe
->mNextSibling
) {
392 mFirstChild
= deleteMe
->mNextSibling
;
393 deleteMe
->mNextSibling
= nsnull
;
395 mFirstChild
= nsnull
;
399 if (deleteMe
->mFirstChild
) {
401 mFirstChild
= deleteMe
->mFirstChild
;
403 nsXFormsControlListItem
*insertPos
= mFirstChild
;
404 while (insertPos
->mNextSibling
) {
405 insertPos
= insertPos
->mNextSibling
;
407 insertPos
->mNextSibling
= deleteMe
->mFirstChild
;
409 deleteMe
->mFirstChild
= nsnull
;
412 // Run through children
413 nsresult rv
= mFirstChild
->RemoveControl(aControl
, aRemoved
);
414 NS_ENSURE_SUCCESS(rv
, rv
);
421 if (!deleteMe
&& mNextSibling
) {
422 if (mNextSibling
->mNode
== aControl
) {
423 deleteMe
= mNextSibling
;
425 if (deleteMe
->mNextSibling
) {
426 mNextSibling
= deleteMe
->mNextSibling
;
427 deleteMe
->mNextSibling
= nsnull
;
429 mNextSibling
= nsnull
;
432 if (deleteMe
->mFirstChild
) {
434 mNextSibling
= deleteMe
->mFirstChild
;
436 nsXFormsControlListItem
*insertPos
= mNextSibling
;
437 while (insertPos
->mNextSibling
) {
438 insertPos
= insertPos
->mNextSibling
;
440 insertPos
->mNextSibling
= deleteMe
->mFirstChild
;
442 deleteMe
->mFirstChild
= nsnull
;
445 // run through siblings
446 return mNextSibling
->RemoveControl(aControl
, aRemoved
);
451 NS_ASSERTION(!(deleteMe
->mNextSibling
),
452 "Deleted control should not have siblings!");
453 NS_ASSERTION(!(deleteMe
->mFirstChild
),
454 "Deleted control should not have children!");
455 nsCOMPtr
<nsIDOMElement
> element
;
456 deleteMe
->mNode
->GetElement(getter_AddRefs(element
));
457 mControlListHash
->Remove(element
);
464 nsXFormsControlListItem
*
465 nsXFormsControlListItem::FindControl(nsIXFormsControl
*aControl
)
470 nsRefPtr
<nsXFormsControlListItem
> listItem
;
471 nsCOMPtr
<nsIDOMElement
> element
;
472 aControl
->GetElement(getter_AddRefs(element
));
473 mControlListHash
->Get(element
, getter_AddRefs(listItem
));
477 already_AddRefed
<nsIXFormsControl
>
478 nsXFormsControlListItem::Control()
480 nsIXFormsControl
* res
= nsnull
;
482 NS_ADDREF(res
= mNode
);
483 NS_WARN_IF_FALSE(res
, "Returning nsnull for a control. Bad sign.");
487 nsXFormsControlListItem
*
488 nsXFormsControlListItem::begin()
497 nsXFormsControlListItem
*
498 nsXFormsControlListItem::end()
504 //------------------------------------------------------------------------------
506 static const nsIID sScriptingIIDs
[] = {
507 NS_IXFORMSMODELELEMENT_IID
,
508 NS_IXFORMSNSMODELELEMENT_IID
511 static nsIAtom
* sModelPropsList
[eModel__count
];
513 // This can be nsVoidArray because elements will remove
514 // themselves from the list if they are deleted during refresh.
515 static nsVoidArray
* sPostRefreshList
= nsnull
;
516 static nsVoidArray
* sContainerPostRefreshList
= nsnull
;
518 static PRInt32 sRefreshing
= 0;
520 nsPostRefresh::nsPostRefresh()
523 printf("nsPostRefresh\n");
528 nsPostRefresh::~nsPostRefresh()
531 printf("~nsPostRefresh\n");
534 if (sRefreshing
!= 1) {
539 if (sPostRefreshList
) {
540 while (sPostRefreshList
->Count()) {
541 // Iterating this way because refresh can lead to
542 // additions/deletions in sPostRefreshList.
543 // Iterating from last to first saves possibly few memcopies,
544 // see nsVoidArray::RemoveElementsAt().
545 PRInt32 last
= sPostRefreshList
->Count() - 1;
546 nsIXFormsControl
* control
=
547 static_cast<nsIXFormsControl
*>(sPostRefreshList
->ElementAt(last
));
548 sPostRefreshList
->RemoveElementAt(last
);
552 if (sRefreshing
== 1) {
553 delete sPostRefreshList
;
554 sPostRefreshList
= nsnull
;
560 // process sContainerPostRefreshList after we've decremented sRefreshing.
561 // container->refresh below could ask for ContainerNeedsPostRefresh which
562 // will add an item to the sContainerPostRefreshList if sRefreshing > 0.
563 // So keeping this under sRefreshing-- will avoid an infinite loop.
564 while (sContainerPostRefreshList
&& sContainerPostRefreshList
->Count()) {
565 PRInt32 last
= sContainerPostRefreshList
->Count() - 1;
566 nsIXFormsControl
* container
=
567 static_cast<nsIXFormsControl
*>(sContainerPostRefreshList
->ElementAt(last
));
568 sContainerPostRefreshList
->RemoveElementAt(last
);
570 container
->Refresh();
573 delete sContainerPostRefreshList
;
574 sContainerPostRefreshList
= nsnull
;
578 nsPostRefresh::PostRefreshList()
580 return sPostRefreshList
;
584 nsXFormsModelElement::NeedsPostRefresh(nsIXFormsControl
* aControl
)
587 if (!sPostRefreshList
) {
588 sPostRefreshList
= new nsVoidArray();
589 NS_ENSURE_TRUE(sPostRefreshList
, NS_ERROR_OUT_OF_MEMORY
);
592 if (sPostRefreshList
->IndexOf(aControl
) < 0) {
593 sPostRefreshList
->AppendElement(aControl
);
596 // We are not refreshing any models, so the control
597 // can be refreshed immediately.
604 nsXFormsModelElement::ContainerNeedsPostRefresh(nsIXFormsControl
* aControl
)
608 if (!sContainerPostRefreshList
) {
609 sContainerPostRefreshList
= new nsVoidArray();
610 if (!sContainerPostRefreshList
) {
615 if (sContainerPostRefreshList
->IndexOf(aControl
) < 0) {
616 sContainerPostRefreshList
->AppendElement(aControl
);
619 // return PR_TRUE to show that the control's refresh will be delayed,
620 // whether as a result of this call or a previous call to this function.
624 // Delaying the refresh doesn't make any sense. But since this
625 // function may be called from inside the control node's refresh already,
626 // we shouldn't just assume that we can call the refresh here. So
627 // we'll just return PR_FALSE to signal that we couldn't delay the refresh.
633 nsXFormsModelElement::CancelPostRefresh(nsIXFormsControl
* aControl
)
635 if (sPostRefreshList
)
636 sPostRefreshList
->RemoveElement(aControl
);
638 if (sContainerPostRefreshList
)
639 sContainerPostRefreshList
->RemoveElement(aControl
);
642 nsXFormsModelElement::nsXFormsModelElement()
644 mFormControls(nsnull
, &mControlListHash
),
647 mPendingInstanceCount(0),
648 mDocumentLoaded(PR_FALSE
),
649 mRebindAllControls(PR_FALSE
),
650 mInstancesInitialized(PR_FALSE
),
651 mReadyHandled(PR_FALSE
),
652 mLazyModel(PR_FALSE
),
653 mConstructDoneHandled(PR_FALSE
),
654 mProcessingUpdateEvent(PR_FALSE
),
656 mInstanceDocuments(nsnull
)
658 mControlListHash
.Init();
661 NS_INTERFACE_MAP_BEGIN(nsXFormsModelElement
)
662 NS_INTERFACE_MAP_ENTRY(nsIXFormsModelElement
)
663 NS_INTERFACE_MAP_ENTRY(nsIXFormsNSModelElement
)
664 NS_INTERFACE_MAP_ENTRY(nsIModelElementPrivate
)
665 NS_INTERFACE_MAP_ENTRY(nsISchemaLoadListener
)
666 NS_INTERFACE_MAP_ENTRY(nsIWebServiceErrorHandler
)
667 NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener
)
668 NS_INTERFACE_MAP_ENTRY(nsIXFormsContextControl
)
669 NS_INTERFACE_MAP_END_INHERITING(nsXFormsStubElement
)
671 NS_IMPL_ADDREF_INHERITED(nsXFormsModelElement
, nsXFormsStubElement
)
672 NS_IMPL_RELEASE_INHERITED(nsXFormsModelElement
, nsXFormsStubElement
)
675 nsXFormsModelElement::OnDestroyed()
679 // Releasing references if the model element is removed from the
680 // document before unload, see bug 375320.
683 if (mInstanceDocuments
)
684 mInstanceDocuments
->DropReferences();
686 mFormControls
.Clear();
687 mControlListHash
.Clear();
693 nsXFormsModelElement::RemoveModelFromDocument()
695 mDocumentLoaded
= PR_FALSE
;
697 nsCOMPtr
<nsIDOMDocument
> domDoc
;
698 mElement
->GetOwnerDocument(getter_AddRefs(domDoc
));
702 RemoveFromModelList(domDoc
, this);
704 nsCOMPtr
<nsIDOMEventTarget
> targ
= do_QueryInterface(domDoc
);
706 targ
->RemoveEventListener(NS_LITERAL_STRING("DOMContentLoaded"), this, PR_TRUE
);
708 nsCOMPtr
<nsIDOMWindowInternal
> window
;
709 nsXFormsUtils::GetWindowFromDocument(domDoc
, getter_AddRefs(window
));
710 targ
= do_QueryInterface(window
);
712 targ
->RemoveEventListener(NS_LITERAL_STRING("unload"), this, PR_TRUE
);
718 nsXFormsModelElement::GetScriptingInterfaces(PRUint32
*aCount
, nsIID
***aArray
)
720 return nsXFormsUtils::CloneScriptingInterfaces(sScriptingIIDs
,
721 NS_ARRAY_LENGTH(sScriptingIIDs
),
726 nsXFormsModelElement::WillChangeDocument(nsIDOMDocument
* aNewDocument
)
728 RemoveModelFromDocument();
733 nsXFormsModelElement::DocumentChanged(nsIDOMDocument
* aNewDocument
)
738 AddToModelList(aNewDocument
, this);
740 nsCOMPtr
<nsIDOMEventTarget
> targ
= do_QueryInterface(aNewDocument
);
742 targ
->AddEventListener(NS_LITERAL_STRING("DOMContentLoaded"), this, PR_TRUE
);
744 nsCOMPtr
<nsIDOMWindowInternal
> window
;
745 nsXFormsUtils::GetWindowFromDocument(aNewDocument
, getter_AddRefs(window
));
746 targ
= do_QueryInterface(window
);
748 targ
->AddEventListener(NS_LITERAL_STRING("unload"), this, PR_TRUE
);
756 nsXFormsModelElement::DoneAddingChildren()
758 return InitializeInstances();
762 nsXFormsModelElement::InitializeInstances()
764 if (mInstancesInitialized
|| !mElement
) {
768 mInstancesInitialized
= PR_TRUE
;
770 nsCOMPtr
<nsIDOMNodeList
> children
;
771 mElement
->GetChildNodes(getter_AddRefs(children
));
773 PRUint32 childCount
= 0;
775 children
->GetLength(&childCount
);
779 for (PRUint32 i
= 0; i
< childCount
; ++i
) {
780 nsCOMPtr
<nsIDOMNode
> child
;
781 children
->Item(i
, getter_AddRefs(child
));
782 if (nsXFormsUtils::IsXFormsElement(child
, NS_LITERAL_STRING("instance"))) {
783 nsCOMPtr
<nsIInstanceElementPrivate
> instance(do_QueryInterface(child
));
784 NS_ENSURE_STATE(instance
);
785 rv
= instance
->Initialize();
786 NS_ENSURE_SUCCESS(rv
, rv
);
791 // 1. load xml schemas
793 nsAutoString schemaList
;
794 mElement
->GetAttribute(NS_LITERAL_STRING("schema"), schemaList
);
796 if (!schemaList
.IsEmpty()) {
797 NS_ENSURE_TRUE(mSchemas
, NS_ERROR_FAILURE
);
798 // Parse the whitespace-separated list.
799 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(mElement
);
800 nsRefPtr
<nsIURI
> baseURI
= content
->GetBaseURI();
801 nsRefPtr
<nsIURI
> docURI
= content
->GetOwnerDoc() ?
802 content
->GetOwnerDoc()->GetDocumentURI() : nsnull
;
804 nsCStringArray schemas
;
805 schemas
.ParseString(NS_ConvertUTF16toUTF8(schemaList
).get(), " \t\r\n");
807 // Increase by 1 to prevent OnLoad from calling FinishConstruction
808 mSchemaTotal
= schemas
.Count();
810 for (PRInt32 i
=0; i
<mSchemaTotal
; ++i
) {
812 nsCOMPtr
<nsIURI
> newURI
;
813 NS_NewURI(getter_AddRefs(newURI
), *schemas
[i
], nsnull
, baseURI
);
814 nsCOMPtr
<nsIURL
> newURL
= do_QueryInterface(newURI
);
816 rv
= NS_ERROR_UNEXPECTED
;
818 // This code is copied from nsXMLEventsManager for extracting an
819 // element ID from an xsd:anyURI link.
822 newURL
->SetRef(EmptyCString());
823 PRBool equals
= PR_FALSE
;
824 newURL
->Equals(docURI
, &equals
);
826 // We will not be able to locate the <xsd:schema> element using the
827 // getElementById function defined on our document when <xsd:schema>
828 // is treated as an ordinary XML data node. So, we employ XPath to
831 NS_ConvertUTF8toUTF16
id(ref
);
833 nsCOMPtr
<nsIDOMElement
> el
;
834 GetSchemaElementById(mElement
, id
, getter_AddRefs(el
));
836 // Perhaps the <xsd:schema> element appears after the <xforms:model>
837 // element in the document, so we'll defer loading it until the
838 // document has finished loading.
839 mPendingInlineSchemas
.AppendString(id
);
841 // We have an inline schema in the model element that was
842 // referenced by the schema attribute. It will be processed
843 // in FinishConstruction so we skip it now to avoid processing
844 // it twice and giving invalid 'duplicate schema' errors.
849 nsCAutoString uriSpec
;
850 newURI
->GetSpec(uriSpec
);
851 rv
= mSchemas
->LoadAsync(NS_ConvertUTF8toUTF16(uriSpec
), this);
855 // this is a fatal error
856 nsXFormsUtils::ReportError(NS_LITERAL_STRING("schemaLoadError"), mElement
);
857 nsXFormsUtils::DispatchEvent(mElement
, eEvent_LinkException
);
863 // If all of the children are added and there aren't any instance elements,
864 // yet, then we need to make sure that one is ready in case the form author
865 // is using lazy authoring.
866 // Lazy <xforms:intance> element is created in anonymous content using XBL.
867 NS_ENSURE_STATE(mInstanceDocuments
);
869 mInstanceDocuments
->GetLength(&instCount
);
872 printf("Creating lazy instance\n");
874 nsCOMPtr
<nsIDOMDocument
> domDoc
;
875 mElement
->GetOwnerDocument(getter_AddRefs(domDoc
));
876 nsCOMPtr
<nsIDOMDocumentXBL
> xblDoc(do_QueryInterface(domDoc
));
879 xblDoc
->AddBinding(mElement
,
880 NS_LITERAL_STRING(XFORMS_LAZY_INSTANCE_BINDING
));
881 NS_ENSURE_SUCCESS(rv
, rv
);
883 mInstanceDocuments
->GetLength(&instCount
);
885 nsCOMPtr
<nsIDOMNodeList
> list
;
886 xblDoc
->GetAnonymousNodes(mElement
, getter_AddRefs(list
));
888 PRUint32 childCount
= 0;
890 list
->GetLength(&childCount
);
893 for (PRUint32 i
= 0; i
< childCount
; ++i
) {
894 nsCOMPtr
<nsIDOMNode
> item
;
895 list
->Item(i
, getter_AddRefs(item
));
896 nsCOMPtr
<nsIInstanceElementPrivate
> instance
=
897 do_QueryInterface(item
);
899 rv
= instance
->Initialize();
900 NS_ENSURE_SUCCESS(rv
, rv
);
902 mLazyModel
= PR_TRUE
;
908 NS_WARN_IF_FALSE(mLazyModel
, "Installing lazy instance didn't succeed!");
911 // (XForms 4.2.1 - cont)
912 // 2. construct an XPath data model from inline or external initial instance
913 // data. This is done by our child instance elements as they are inserted
914 // into the document, and all of the instances will be processed by this
917 // schema and external instance data loads should delay document onload
920 // No need to fire refresh event if we assume that all UI controls
921 // appear later in the document.
922 NS_ASSERTION(!mDocumentLoaded
, "document should not be loaded yet");
923 return FinishConstruction();
930 nsXFormsModelElement::HandleDefault(nsIDOMEvent
*aEvent
, PRBool
*aHandled
)
932 if (!nsXFormsUtils::EventHandlingAllowed(aEvent
, mElement
))
938 aEvent
->GetType(type
);
941 if (type
.EqualsASCII(sXFormsEventsEntries
[eEvent_Refresh
].name
)) {
943 } else if (type
.EqualsASCII(sXFormsEventsEntries
[eEvent_Revalidate
].name
)) {
945 } else if (type
.EqualsASCII(sXFormsEventsEntries
[eEvent_Recalculate
].name
)) {
947 } else if (type
.EqualsASCII(sXFormsEventsEntries
[eEvent_Rebuild
].name
)) {
949 } else if (type
.EqualsASCII(sXFormsEventsEntries
[eEvent_ModelConstructDone
].name
)) {
950 rv
= ConstructDone();
951 mConstructDoneHandled
= PR_TRUE
;
952 } else if (type
.EqualsASCII(sXFormsEventsEntries
[eEvent_Reset
].name
)) {
954 } else if (type
.EqualsASCII(sXFormsEventsEntries
[eEvent_BindingException
].name
)) {
955 // we threw up a popup during the nsXFormsUtils::DispatchEvent that sent
956 // this error to the model
959 *aHandled
= PR_FALSE
;
962 NS_WARN_IF_FALSE(NS_SUCCEEDED(rv
),
963 "nsXFormsModelElement::HandleDefault() failed!\n");
969 nsXFormsModelElement::ConstructDone()
971 nsresult rv
= InitializeControls();
972 NS_ENSURE_SUCCESS(rv
, rv
);
978 nsXFormsModelElement::OnCreated(nsIXTFElementWrapper
*aWrapper
)
980 aWrapper
->SetNotificationMask(nsIXTFElement::NOTIFY_WILL_CHANGE_DOCUMENT
|
981 nsIXTFElement::NOTIFY_DOCUMENT_CHANGED
|
982 nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN
|
983 nsIXTFElement::NOTIFY_HANDLE_DEFAULT
);
985 nsCOMPtr
<nsIDOMElement
> node
;
986 aWrapper
->GetElementNode(getter_AddRefs(node
));
988 // It's ok to keep a weak pointer to mElement. mElement will have an
989 // owning reference to this object, so as long as we null out mElement in
990 // OnDestroyed, it will always be valid.
993 NS_ASSERTION(mElement
, "Wrapper is not an nsIDOMElement, we'll crash soon");
995 nsresult rv
= mMDG
.Init(this);
996 NS_ENSURE_SUCCESS(rv
, rv
);
998 mSchemas
= do_CreateInstance(NS_SCHEMALOADER_CONTRACTID
);
1000 mInstanceDocuments
= new nsXFormsModelInstanceDocuments();
1001 NS_ASSERTION(mInstanceDocuments
, "could not create mInstanceDocuments?!");
1003 // Initialize hash tables
1004 NS_ENSURE_TRUE(mNodeToType
.Init(), NS_ERROR_OUT_OF_MEMORY
);
1005 NS_ENSURE_TRUE(mNodeToP3PType
.Init(), NS_ERROR_OUT_OF_MEMORY
);
1008 // Get eventual user-set loop maximum. Used by RequestUpdateEvent().
1009 nsCOMPtr
<nsIPrefBranch
> pref
= do_GetService(NS_PREFSERVICE_CONTRACTID
, &rv
);
1010 if (NS_SUCCEEDED(rv
) && pref
) {
1012 if (NS_SUCCEEDED(pref
->GetIntPref("xforms.modelLoopMax", &val
)))
1019 // nsIXFormsModelElement
1022 nsXFormsModelElement::GetInstanceDocuments(nsIDOMNodeList
**aDocuments
)
1024 NS_ENSURE_STATE(mInstanceDocuments
);
1025 NS_ENSURE_ARG_POINTER(aDocuments
);
1026 NS_ADDREF(*aDocuments
= mInstanceDocuments
);
1031 nsXFormsModelElement::GetInstanceDocument(const nsAString
& aInstanceID
,
1032 nsIDOMDocument
**aDocument
)
1034 NS_ENSURE_ARG_POINTER(aDocument
);
1036 *aDocument
= FindInstanceDocument(aInstanceID
).get(); // transfer reference
1042 const nsPromiseFlatString
& flat
= PromiseFlatString(aInstanceID
);
1043 const PRUnichar
*strings
[] = { flat
.get() };
1044 nsXFormsUtils::ReportError(aInstanceID
.IsEmpty() ?
1045 NS_LITERAL_STRING("defInstanceNotFound") :
1046 NS_LITERAL_STRING("instanceNotFound"),
1047 strings
, 1, mElement
, nsnull
);
1048 return NS_ERROR_DOM_NOT_FOUND_ERR
;
1052 nsXFormsModelElement::Rebuild()
1055 printf("nsXFormsModelElement::Rebuild()\n");
1061 NS_ENSURE_SUCCESS(rv
, rv
);
1063 // Clear any type information
1064 NS_ENSURE_TRUE(mNodeToType
.IsInitialized() && mNodeToP3PType
.IsInitialized(),
1066 mNodeToType
.Clear();
1067 mNodeToP3PType
.Clear();
1069 // 2. Process bind elements
1070 rv
= ProcessBindElements();
1071 NS_ENSURE_SUCCESS(rv
, rv
);
1073 // 3. If this is not form load, re-attach all elements and validate
1074 // instance documents
1075 if (mReadyHandled
) {
1076 mRebindAllControls
= PR_TRUE
;
1077 ValidateInstanceDocuments();
1081 return mMDG
.Rebuild();
1085 nsXFormsModelElement::Recalculate()
1088 printf("nsXFormsModelElement::Recalculate()\n");
1091 return mMDG
.Recalculate(&mChangedNodes
);
1095 nsXFormsModelElement::SetSingleState(nsIDOMElement
*aElement
,
1097 nsXFormsEvent aOnEvent
)
1099 nsXFormsEvent event
= aState
? aOnEvent
: (nsXFormsEvent
) (aOnEvent
+ 1);
1102 nsXFormsUtils::DispatchEvent(aElement
, event
);
1106 nsXFormsModelElement::SetStates(nsIXFormsControl
*aControl
,
1109 NS_ENSURE_ARG(aControl
);
1111 nsCOMPtr
<nsIDOMElement
> element
;
1112 aControl
->GetElement(getter_AddRefs(element
));
1113 NS_ENSURE_STATE(element
);
1115 nsCOMPtr
<nsIXTFElementWrapper
> xtfWrap(do_QueryInterface(element
));
1116 NS_ENSURE_STATE(xtfWrap
);
1119 const nsXFormsNodeState
* ns
= nsnull
;
1121 ns
= mMDG
.GetNodeState(aNode
);
1122 NS_ENSURE_STATE(ns
);
1123 iState
= ns
->GetIntrinsicState();
1124 nsCOMPtr
<nsIContent
> content(do_QueryInterface(element
));
1125 NS_ENSURE_STATE(content
);
1126 PRInt32 rangeState
= content
->IntrinsicState() &
1127 (NS_EVENT_STATE_INRANGE
| NS_EVENT_STATE_OUTOFRANGE
);
1128 iState
= ns
->GetIntrinsicState() | rangeState
;
1130 aControl
->GetDefaultIntrinsicState(&iState
);
1133 nsresult rv
= xtfWrap
->SetIntrinsicState(iState
);
1134 NS_ENSURE_SUCCESS(rv
, rv
);
1136 // Event dispatching is defined by the bound node, so if there's no bound
1137 // node, there are no events to send. xforms-ready also needs to be handled,
1138 // because these events are not sent before that.
1139 if (!ns
|| !mReadyHandled
)
1142 if (ns
->ShouldDispatchValid()) {
1143 SetSingleState(element
, ns
->IsValid(), eEvent_Valid
);
1145 if (ns
->ShouldDispatchReadonly()) {
1146 SetSingleState(element
, ns
->IsReadonly(), eEvent_Readonly
);
1148 if (ns
->ShouldDispatchRequired()) {
1149 SetSingleState(element
, ns
->IsRequired(), eEvent_Required
);
1151 if (ns
->ShouldDispatchRelevant()) {
1152 SetSingleState(element
, ns
->IsRelevant(), eEvent_Enabled
);
1155 if (ns
->ShouldDispatchValueChanged()) {
1156 nsXFormsUtils::DispatchEvent(element
, eEvent_ValueChanged
);
1163 nsXFormsModelElement::Revalidate()
1166 printf("nsXFormsModelElement::Revalidate()\n");
1170 printf("[%s] Changed nodes:\n", __TIME__
);
1171 for (PRInt32 j
= 0; j
< mChangedNodes
.Count(); ++j
) {
1172 nsCOMPtr
<nsIDOMNode
> node
= mChangedNodes
[j
];
1174 node
->GetNodeName(name
);
1175 printf("\t%s [%p]\n",
1176 NS_ConvertUTF16toUTF8(name
).get(),
1182 mMDG
.Revalidate(&mChangedNodes
);
1188 nsXFormsModelElement::RefreshSubTree(nsXFormsControlListItem
*aCurrent
,
1189 PRBool aForceRebind
)
1192 nsRefPtr
<nsXFormsControlListItem
> current
= aCurrent
;
1194 nsCOMPtr
<nsIXFormsControl
> control(current
->Control());
1195 NS_ASSERTION(control
, "A tree node without a control?!");
1198 nsCOMPtr
<nsIDOMNode
> boundNode
;
1199 control
->GetBoundNode(getter_AddRefs(boundNode
));
1201 PRBool rebind
= aForceRebind
;
1202 PRBool refresh
= PR_FALSE
;
1203 PRBool rebindChildren
= PR_FALSE
;
1206 nsCOMPtr
<nsIDOMElement
> controlElement
;
1207 control
->GetElement(getter_AddRefs(controlElement
));
1208 printf("rebind: %d, mRebindAllControls: %d, aForceRebind: %d\n",
1209 rebind
, mRebindAllControls
, aForceRebind
);
1210 if (controlElement
) {
1211 printf("Checking control: ");
1212 //DBG_TAGINFO(controlElement);
1216 if (mRebindAllControls
|| rebind
) {
1217 refresh
= rebind
= PR_TRUE
;
1219 PRBool usesModelBinding
= PR_FALSE
;
1220 control
->GetUsesModelBinding(&usesModelBinding
);
1223 printf("usesModelBinding: %d\n", usesModelBinding
);
1226 nsCOMArray
<nsIDOMNode
> *deps
= nsnull
;
1227 if (usesModelBinding
) {
1229 PRBool usesSNB
= PR_TRUE
;
1230 control
->GetUsesSingleNodeBinding(&usesSNB
);
1232 // If the control doesn't use single node binding (and can thus be
1233 // bound to many nodes), the above test for boundNode means nothing.
1234 // We'll need to continue on with the work this function does so that
1235 // any controls that this control contains can be tested for whether
1236 // they may need to refresh.
1238 // If a control uses a model binding, but has no bound node a
1239 // rebuild is the only thing that'll (eventually) change it. We
1240 // don't need to worry about contained controls (like a label)
1241 // since the fact that there is no bound node means that this
1242 // control (and contained controls) need to behave as if
1243 // irrelevant per spec.
1244 current
= current
->NextSibling();
1250 control
->GetDependencies(&deps
);
1252 PRUint32 depCount
= deps
? deps
->Count() : 0;
1255 nsAutoString boundName
;
1257 boundNode
->GetNodeName(boundName
);
1258 printf("\tDependencies: %d, Bound to: '%s' [%p]\n",
1260 NS_ConvertUTF16toUTF8(boundName
).get(),
1263 nsAutoString depNodeName
;
1264 for (PRUint32 t
= 0; t
< depCount
; ++t
) {
1265 nsCOMPtr
<nsIDOMNode
> tmpdep
= deps
->ObjectAt(t
);
1267 tmpdep
->GetNodeName(depNodeName
);
1268 printf("\t\t%s [%p]\n",
1269 NS_ConvertUTF16toUTF8(depNodeName
).get(),
1275 nsCOMPtr
<nsIDOM3Node
> curChanged
;
1277 // Iterator over changed nodes. Checking for rebind, too. If it ever
1278 // becomes true due to some condition below, we can stop this testing
1279 // since any control that needs to rebind will also refresh.
1280 for (PRInt32 j
= 0; j
< mChangedNodes
.Count() && !rebind
; ++j
) {
1281 curChanged
= do_QueryInterface(mChangedNodes
[j
]);
1283 // Check whether the bound node is dirty. If so, we need to refresh the
1284 // control (get updated node value from the bound node)
1285 if (!refresh
&& boundNode
) {
1286 curChanged
->IsSameNode(boundNode
, &refresh
);
1288 // Two ways to go here. Keep in mind that controls using model
1289 // binding expressions never needs to have dependencies checked as
1290 // they only rebind on xforms-rebuild
1291 if (refresh
&& usesModelBinding
) {
1292 // 1) If the control needs a refresh, and uses model bindings,
1293 // we can stop checking here
1296 if (refresh
|| usesModelBinding
) {
1297 // 2) If either the control needs a refresh or it uses a model
1298 // binding we can continue to next changed node
1303 // Check whether any dependencies are dirty. If so, we need to rebind
1304 // the control (re-evaluate it's binding expression)
1305 for (PRUint32 k
= 0; k
< depCount
; ++k
) {
1306 /// @note beaufour: I'm not too happy about this ...
1307 /// O(mChangedNodes.Count() * deps->Count()), but using the pointers
1308 /// for sorting and comparing does not work...
1309 curChanged
->IsSameNode(deps
->ObjectAt(k
), &rebind
);
1311 // We need to rebind the control, no need to check any more
1316 printf("\trebind: %d, refresh: %d\n", rebind
, refresh
);
1322 rv
= control
->Bind(&rebindChildren
);
1323 NS_ENSURE_SUCCESS(rv
, rv
);
1326 // Handle refreshing
1327 if (rebind
|| refresh
) {
1329 // XXX: bug 336608: we should really check the return result, but
1330 // f.x. select1 returns error because of no widget...? so we should
1331 // ensure that an error is only returned when there actually is an
1332 // error, and we should report that on the console... possibly we should
1333 // then continue, instead of bailing totally.
1334 // NS_ENSURE_SUCCESS(rv, rv);
1338 rv
= RefreshSubTree(current
->FirstChild(), rebindChildren
);
1339 NS_ENSURE_SUCCESS(rv
, rv
);
1341 current
= current
->NextSibling();
1349 nsXFormsModelElement::Refresh()
1352 printf("nsXFormsModelElement::Refresh()\n");
1355 // XXXbeaufour: Can we somehow suspend redraw / "screen update" while doing
1356 // the refresh? That should save a lot of time, and avoid flickering of
1359 // Using brackets here to provide a scope for the
1360 // nsPostRefresh. We want to make sure that nsPostRefresh's destructor
1361 // runs (and thus processes the postrefresh and containerpostrefresh lists)
1362 // before we clear the dispatch flags
1364 nsPostRefresh postRefresh
= nsPostRefresh();
1366 if (!mDocumentLoaded
) {
1370 // Kick off refreshing on root node
1371 nsresult rv
= RefreshSubTree(mFormControls
.FirstChild(), PR_FALSE
);
1372 NS_ENSURE_SUCCESS(rv
, rv
);
1375 // Clear refresh structures
1376 mChangedNodes
.Clear();
1377 mRebindAllControls
= PR_FALSE
;
1378 mMDG
.ClearDispatchFlags();
1383 // nsISchemaLoadListener
1386 nsXFormsModelElement::OnLoad(nsISchema
* aSchema
)
1390 // If there is no model element, then schema loading finished after
1391 // main page failed to load.
1392 if (IsComplete() && mElement
) {
1393 nsresult rv
= FinishConstruction();
1394 NS_ENSURE_SUCCESS(rv
, rv
);
1396 MaybeNotifyCompletion();
1402 // nsIWebServiceErrorHandler
1405 nsXFormsModelElement::OnError(nsresult aStatus
,
1406 const nsAString
&aStatusMessage
)
1408 nsXFormsUtils::ReportError(NS_LITERAL_STRING("schemaLoadError"), mElement
);
1409 nsXFormsUtils::DispatchEvent(mElement
, eEvent_LinkException
);
1413 // nsIDOMEventListener
1416 nsXFormsModelElement::HandleEvent(nsIDOMEvent
* aEvent
)
1418 if (!nsXFormsUtils::EventHandlingAllowed(aEvent
, mElement
))
1422 aEvent
->GetType(type
);
1424 if (type
.EqualsLiteral("DOMContentLoaded")) {
1425 return HandleLoad(aEvent
);
1426 }else if (type
.EqualsLiteral("unload")) {
1427 return HandleUnload(aEvent
);
1433 // nsIModelElementPrivate
1436 nsXFormsModelElement::AddFormControl(nsIXFormsControl
*aControl
,
1437 nsIXFormsControl
*aParent
)
1440 printf("nsXFormsModelElement::AddFormControl(con: %p, parent: %p)\n",
1441 (void*) aControl
, (void*) aParent
);
1444 NS_ENSURE_ARG(aControl
);
1445 return mFormControls
.AddControl(aControl
, aParent
);
1449 nsXFormsModelElement::RemoveFormControl(nsIXFormsControl
*aControl
)
1452 printf("nsXFormsModelElement::RemoveFormControl(con: %p)\n",
1456 NS_ENSURE_ARG(aControl
);
1458 nsresult rv
= mFormControls
.RemoveControl(aControl
, removed
);
1459 NS_WARN_IF_FALSE(removed
,
1460 "Tried to remove control that was not in the model");
1465 nsXFormsModelElement::GetTypeForControl(nsIXFormsControl
*aControl
,
1466 nsISchemaType
**aType
)
1468 NS_ENSURE_ARG_POINTER(aType
);
1471 nsCOMPtr
<nsIDOMNode
> boundNode
;
1472 aControl
->GetBoundNode(getter_AddRefs(boundNode
));
1474 // if the control isn't bound to instance data, it doesn't make sense to
1475 // return a type. It is perfectly valid for there to be no bound node,
1476 // so no need to use an NS_ENSURE_xxx macro, either.
1477 return NS_ERROR_FAILURE
;
1480 nsAutoString schemaTypeName
, schemaTypeNamespace
;
1481 nsresult rv
= GetTypeAndNSFromNode(boundNode
, schemaTypeName
,
1482 schemaTypeNamespace
);
1483 NS_ENSURE_SUCCESS(rv
, rv
);
1485 nsXFormsSchemaValidator validator
;
1487 nsCOMPtr
<nsISchemaCollection
> schemaColl
= do_QueryInterface(mSchemas
);
1489 nsCOMPtr
<nsISchema
> schema
;
1490 schemaColl
->GetSchema(schemaTypeNamespace
, getter_AddRefs(schema
));
1491 // if no schema found, then we will only handle built-in types.
1493 validator
.LoadSchema(schema
);
1496 PRBool foundType
= validator
.GetType(schemaTypeName
, schemaTypeNamespace
,
1498 return foundType
? NS_OK
: NS_ERROR_FAILURE
;
1501 /* static */ nsresult
1502 nsXFormsModelElement::GetTypeAndNSFromNode(nsIDOMNode
*aInstanceData
,
1503 nsAString
&aType
, nsAString
&aNSUri
)
1505 nsresult rv
= GetTypeFromNode(aInstanceData
, aType
, aNSUri
);
1507 if (rv
== NS_ERROR_NOT_AVAILABLE
) {
1508 // if there is no type assigned, then assume that the type is 'string'
1509 aNSUri
.Assign(NS_LITERAL_STRING(NS_NAMESPACE_XML_SCHEMA
));
1510 aType
.Assign(NS_LITERAL_STRING("string"));
1518 nsXFormsModelElement::InstanceLoadStarted()
1520 ++mPendingInstanceCount
;
1525 nsXFormsModelElement::InstanceLoadFinished(PRBool aSuccess
)
1528 // This will leave mPendingInstanceCount in an invalid state, which is
1529 // exactly what we want, because this is a fatal error, and processing
1530 // should stop. If we decrease mPendingInstanceCount, the model would
1531 // finish construction, which is wrong.
1532 nsXFormsUtils::ReportError(NS_LITERAL_STRING("instanceLoadError"), mElement
);
1533 nsXFormsUtils::DispatchEvent(mElement
, eEvent_LinkException
);
1537 --mPendingInstanceCount
;
1539 nsresult rv
= FinishConstruction();
1540 if (NS_SUCCEEDED(rv
)) {
1541 MaybeNotifyCompletion();
1549 nsXFormsModelElement::FindInstanceElement(const nsAString
&aID
,
1550 nsIInstanceElementPrivate
**aElement
)
1552 NS_ENSURE_STATE(mInstanceDocuments
);
1556 mInstanceDocuments
->GetLength(&instCount
);
1558 nsCOMPtr
<nsIDOMElement
> element
;
1560 for (PRUint32 i
= 0; i
< instCount
; ++i
) {
1561 nsIInstanceElementPrivate
* instEle
= mInstanceDocuments
->GetInstanceAt(i
);
1562 instEle
->GetElement(getter_AddRefs(element
));
1564 if (aID
.IsEmpty()) {
1566 *aElement
= instEle
;
1568 } else if (!element
) {
1569 // this should only happen if the instance on the list is lazy authored
1570 // and as far as I can tell, a lazy authored instance should be the
1571 // first (and only) instance in the model and unable to have an ID.
1572 // But that isn't clear to me reading the spec, so for now
1573 // we'll play it safe in case the WG more clearly defines lazy authoring
1578 element
->GetAttribute(NS_LITERAL_STRING("id"), id
);
1579 if (aID
.Equals(id
)) {
1581 *aElement
= instEle
;
1591 nsXFormsModelElement::SetNodeValue(nsIDOMNode
*aNode
,
1592 const nsAString
&aNodeValue
,
1594 PRBool
*aNodeChanged
)
1596 NS_ENSURE_ARG_POINTER(aNodeChanged
);
1597 nsresult rv
= mMDG
.SetNodeValue(aNode
, aNodeValue
, aNodeChanged
);
1598 NS_ENSURE_SUCCESS(rv
, rv
);
1599 if (*aNodeChanged
&& aDoRefresh
) {
1600 rv
= RequestRecalculate();
1601 NS_ENSURE_SUCCESS(rv
, rv
);
1602 rv
= RequestRevalidate();
1603 NS_ENSURE_SUCCESS(rv
, rv
);
1604 rv
= RequestRefresh();
1605 NS_ENSURE_SUCCESS(rv
, rv
);
1612 nsXFormsModelElement::SetNodeContent(nsIDOMNode
*aNode
,
1613 nsIDOMNode
*aNodeContent
,
1616 nsresult rv
= mMDG
.SetNodeContent(aNode
, aNodeContent
);
1617 NS_ENSURE_SUCCESS(rv
, rv
);
1620 rv
= RequestRebuild();
1621 NS_ENSURE_SUCCESS(rv
, rv
);
1622 rv
= RequestRecalculate();
1623 NS_ENSURE_SUCCESS(rv
, rv
);
1624 rv
= RequestRevalidate();
1625 NS_ENSURE_SUCCESS(rv
, rv
);
1626 rv
= RequestRefresh();
1627 NS_ENSURE_SUCCESS(rv
, rv
);
1634 nsXFormsModelElement::ValidateNode(nsIDOMNode
*aInstanceNode
, PRBool
*aResult
)
1636 NS_ENSURE_ARG_POINTER(aResult
);
1638 nsAutoString schemaTypeName
, schemaTypeNamespace
;
1639 nsresult rv
= GetTypeAndNSFromNode(aInstanceNode
, schemaTypeName
,
1640 schemaTypeNamespace
);
1641 NS_ENSURE_SUCCESS(rv
, rv
);
1643 nsXFormsSchemaValidator validator
;
1644 nsCOMPtr
<nsISchemaCollection
> schemaColl
= do_QueryInterface(mSchemas
);
1646 nsCOMPtr
<nsISchema
> schema
;
1647 schemaColl
->GetSchema(schemaTypeNamespace
, getter_AddRefs(schema
));
1648 // if no schema found, then we will only handle built-in types.
1650 validator
.LoadSchema(schema
);
1653 nsCOMPtr
<nsISchemaType
> type
;
1654 rv
= validator
.GetType(schemaTypeName
, schemaTypeNamespace
,
1655 getter_AddRefs(type
));
1656 NS_ENSURE_SUCCESS(rv
, rv
);
1658 PRUint16 typevalue
= nsISchemaType::SCHEMA_TYPE_SIMPLE
;
1660 rv
= type
->GetSchemaType(&typevalue
);
1661 NS_ENSURE_SUCCESS(rv
, rv
);
1664 PRBool isValid
= PR_FALSE
;
1665 if (typevalue
== nsISchemaType::SCHEMA_TYPE_SIMPLE
) {
1667 nsXFormsUtils::GetNodeValue(aInstanceNode
, value
);
1668 isValid
= validator
.ValidateString(value
, schemaTypeName
,
1669 schemaTypeNamespace
);
1671 isValid
= validator
.Validate(aInstanceNode
);
1678 nsXFormsModelElement::ValidateDocument(nsIDOMDocument
*aInstanceDocument
,
1681 NS_ENSURE_ARG_POINTER(aResult
);
1682 NS_ENSURE_ARG(aInstanceDocument
);
1685 This will process the instance document and check for schema validity. It
1686 will mark nodes in the document with their schema types using nsIProperty
1687 until it hits a structural schema validation error. So if the instance
1688 document's XML structure is invalid, don't expect type properties to be
1691 Note that if the structure is fine but some simple types nodes (nodes
1692 that contain text only) are invalid (say one has a empty nodeValue but
1693 should be a date), the schema validator will continue processing and add
1694 the type properties. Schema validation will return false at the end.
1697 nsCOMPtr
<nsIDOMElement
> element
;
1698 nsresult rv
= aInstanceDocument
->GetDocumentElement(getter_AddRefs(element
));
1699 NS_ENSURE_SUCCESS(rv
, rv
);
1700 NS_ENSURE_STATE(element
);
1702 // get namespace from node
1704 element
->GetNamespaceURI(nsuri
);
1706 nsCOMPtr
<nsISchemaCollection
> schemaColl
= do_QueryInterface(mSchemas
);
1707 NS_ENSURE_STATE(schemaColl
);
1709 nsCOMPtr
<nsISchema
> schema
;
1710 schemaColl
->GetSchema(nsuri
, getter_AddRefs(schema
));
1712 // No schema found, so nothing to validate
1717 nsXFormsSchemaValidator validator
;
1718 validator
.LoadSchema(schema
);
1719 // Validate will validate the node and its subtree, as per the schema
1721 *aResult
= validator
.Validate(element
);
1727 * SUBMIT_SERIALIZE_NODE - node is to be serialized
1728 * SUBMIT_SKIP_NODE - node is not to be serialized
1729 * SUBMIT_ABORT_SUBMISSION - abort submission (invalid node or empty required node)
1732 nsXFormsModelElement::HandleInstanceDataNode(nsIDOMNode
*aInstanceDataNode
,
1733 unsigned short *aResult
)
1736 *aResult
= SUBMIT_ABORT_SUBMISSION
;
1738 const nsXFormsNodeState
* ns
;
1739 ns
= mMDG
.GetNodeState(aInstanceDataNode
);
1740 NS_ENSURE_STATE(ns
);
1742 if (!ns
->IsRelevant()) {
1743 // not relevant, thus skip
1744 *aResult
= SUBMIT_SKIP_NODE
;
1745 } else if (ns
->IsRequired()) {
1746 // required and has a value, continue
1748 nsXFormsUtils::GetNodeValue(aInstanceDataNode
, value
);
1749 if (!value
.IsEmpty() && ns
->IsValid())
1750 *aResult
= SUBMIT_SERIALIZE_NODE
;
1751 } else if (ns
->IsValid()) {
1753 *aResult
= SUBMIT_SERIALIZE_NODE
;
1760 nsXFormsModelElement::GetLazyAuthored(PRBool
*aLazyInstance
)
1762 *aLazyInstance
= mLazyModel
;
1767 nsXFormsModelElement::GetIsReady(PRBool
*aIsReady
)
1769 *aIsReady
= mReadyHandled
;
1774 nsXFormsModelElement::GetTypeFromNode(nsIDOMNode
*aInstanceData
,
1778 // aInstanceData could be an instance data node or it could be an attribute
1779 // on an instance data node (basically the node that a control is bound to).
1781 nsString
*typeVal
= nsnull
;
1783 // Get type stored directly on instance node
1784 nsAutoString typeAttribute
;
1785 nsCOMPtr
<nsIDOMElement
> nodeElem(do_QueryInterface(aInstanceData
));
1787 nodeElem
->GetAttributeNS(NS_LITERAL_STRING(NS_NAMESPACE_XML_SCHEMA_INSTANCE
),
1788 NS_LITERAL_STRING("type"), typeAttribute
);
1789 if (!typeAttribute
.IsEmpty()) {
1790 typeVal
= &typeAttribute
;
1794 // If there was no type information on the node itself, check for a type
1795 // bound to the node via \<xforms:bind\>
1796 if (!typeVal
&& !mNodeToType
.Get(aInstanceData
, &typeVal
)) {
1797 // check if schema validation left us a nsISchemaType*
1798 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(aInstanceData
);
1801 nsISchemaType
*type
;
1802 nsCOMPtr
<nsIAtom
> myAtom
= do_GetAtom("xsdtype");
1804 type
= static_cast<nsISchemaType
*>(content
->GetProperty(myAtom
));
1806 type
->GetName(aType
);
1807 type
->GetTargetNamespace(aNSUri
);
1812 // No type information found
1813 return NS_ERROR_NOT_AVAILABLE
;
1816 // split type (ns:type) into namespace and type.
1817 nsAutoString prefix
;
1818 PRInt32 separator
= typeVal
->FindChar(':');
1819 if ((PRUint32
) separator
== (typeVal
->Length() - 1)) {
1820 const PRUnichar
*strings
[] = { typeVal
->get() };
1821 nsXFormsUtils::ReportError(NS_LITERAL_STRING("missingTypeName"), strings
, 1,
1823 return NS_ERROR_UNEXPECTED
;
1826 if (separator
== kNotFound
) {
1827 // no namespace prefix, which is valid. In this case we should follow
1828 // http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/#src-qname and pick
1829 // up the default namespace. Which will happen by passing an empty string
1830 // as first parameter to LookupNamespaceURI.
1831 prefix
= EmptyString();
1832 aType
.Assign(*typeVal
);
1834 prefix
.Assign(Substring(*typeVal
, 0, separator
));
1835 aType
.Assign(Substring(*typeVal
, ++separator
, typeVal
->Length()));
1837 if (prefix
.IsEmpty()) {
1838 aNSUri
= EmptyString();
1843 // get the namespace url from the prefix using instance data node
1845 nsCOMPtr
<nsIDOM3Node
> domNode3
= do_QueryInterface(aInstanceData
, &rv
);
1846 NS_ENSURE_SUCCESS(rv
, rv
);
1847 rv
= domNode3
->LookupNamespaceURI(prefix
, aNSUri
);
1849 if (DOMStringIsNull(aNSUri
)) {
1850 // if not found using instance data node, use <xf:instance> node
1851 nsCOMPtr
<nsIDOMNode
> instanceNode
;
1852 rv
= nsXFormsUtils::GetInstanceNodeForData(aInstanceData
,
1853 getter_AddRefs(instanceNode
));
1854 NS_ENSURE_SUCCESS(rv
, rv
);
1856 domNode3
= do_QueryInterface(instanceNode
, &rv
);
1857 NS_ENSURE_SUCCESS(rv
, rv
);
1858 rv
= domNode3
->LookupNamespaceURI(prefix
, aNSUri
);
1865 * Poor man's try-catch to make sure that we set mProcessingUpdateEvent to
1866 * when leaving scope. If we actually bail with an error at some time,
1867 * something is pretty rotten, but at least we will not prevent any further
1872 nsXFormsModelElement
* mModel
;
1875 Updating(nsXFormsModelElement
* aModel
)
1876 : mModel(aModel
) { mModel
->mProcessingUpdateEvent
= PR_TRUE
; };
1877 ~Updating() { mModel
->mProcessingUpdateEvent
= PR_FALSE
; };
1881 nsXFormsModelElement::RequestUpdateEvent(nsXFormsEvent aEvent
)
1883 if (mProcessingUpdateEvent
) {
1884 mUpdateEventQueue
.AppendElement(NS_INT32_TO_PTR(aEvent
));
1890 // Send the requested event
1891 nsresult rv
= nsXFormsUtils::DispatchEvent(mElement
, aEvent
);
1892 NS_ENSURE_SUCCESS(rv
, rv
);
1894 // Process queued events
1895 PRInt32 loopCount
= 0;
1896 while (mUpdateEventQueue
.Count()) {
1897 nsXFormsEvent event
=
1898 static_cast<nsXFormsEvent
>(NS_PTR_TO_UINT32(mUpdateEventQueue
[0]));
1899 NS_ENSURE_TRUE(mUpdateEventQueue
.RemoveElementAt(0), NS_ERROR_FAILURE
);
1901 rv
= nsXFormsUtils::DispatchEvent(mElement
, event
);
1902 NS_ENSURE_SUCCESS(rv
, rv
);
1904 if (mLoopMax
&& loopCount
> mLoopMax
) {
1905 // Note: we could also popup a dialog asking the user whether or not to
1907 nsXFormsUtils::ReportError(NS_LITERAL_STRING("modelLoopError"), mElement
);
1908 nsXFormsUtils::HandleFatalError(mElement
, NS_LITERAL_STRING("LoopError"));
1909 return NS_ERROR_FAILURE
;
1918 nsXFormsModelElement::RequestRebuild()
1920 return RequestUpdateEvent(eEvent_Rebuild
);
1924 nsXFormsModelElement::RequestRecalculate()
1926 return RequestUpdateEvent(eEvent_Recalculate
);
1930 nsXFormsModelElement::RequestRevalidate()
1932 return RequestUpdateEvent(eEvent_Revalidate
);
1936 nsXFormsModelElement::RequestRefresh()
1938 return RequestUpdateEvent(eEvent_Refresh
);
1942 // nsIXFormsContextControl
1945 nsXFormsModelElement::SetContext(nsIDOMNode
*aContextNode
,
1946 PRInt32 aContextPosition
,
1947 PRInt32 aContextSize
)
1949 return NS_ERROR_NOT_IMPLEMENTED
;
1953 nsXFormsModelElement::GetContext(nsAString
&aModelID
,
1954 nsIDOMNode
**aContextNode
,
1955 PRInt32
*aContextPosition
,
1956 PRInt32
*aContextSize
)
1958 // Adding the nsIXFormsContextControl interface to model to allow
1959 // submission elements to call our binding evaluation methods, like
1960 // EvaluateNodeBinding. If GetContext can get called outside of the binding
1961 // codepath, then this MIGHT lead to problems.
1963 NS_ENSURE_ARG(aContextSize
);
1964 NS_ENSURE_ARG(aContextPosition
);
1965 *aContextNode
= nsnull
;
1967 // better get the stuff most likely to fail out of the way first. No sense
1968 // changing the other values that we are returning unless this is successful.
1969 nsresult rv
= NS_ERROR_FAILURE
;
1971 // Anybody (like a submission element) asking a model element for its context
1972 // for XPath expressions will want the root node of the default instance
1974 nsCOMPtr
<nsIDOMDocument
> firstInstanceDoc
=
1975 FindInstanceDocument(EmptyString());
1976 NS_ENSURE_TRUE(firstInstanceDoc
, rv
);
1978 nsCOMPtr
<nsIDOMElement
> firstInstanceRoot
;
1979 rv
= firstInstanceDoc
->GetDocumentElement(getter_AddRefs(firstInstanceRoot
));
1980 NS_ENSURE_TRUE(firstInstanceRoot
, rv
);
1982 nsCOMPtr
<nsIDOMNode
>rootNode
= do_QueryInterface(firstInstanceRoot
);
1983 rootNode
.swap(*aContextNode
);
1985 // found the context, so can finish up assinging the rest of the values that
1987 *aContextPosition
= 1;
1991 mElement
->GetAttribute(NS_LITERAL_STRING("id"), id
);
1992 aModelID
.Assign(id
);
1998 nsXFormsModelElement::AddRemoveAbortedControl(nsIXFormsControl
*aControl
,
2001 return NS_ERROR_NOT_IMPLEMENTED
;
2006 already_AddRefed
<nsIDOMDocument
>
2007 nsXFormsModelElement::FindInstanceDocument(const nsAString
&aID
)
2009 nsCOMPtr
<nsIInstanceElementPrivate
> instance
;
2010 nsXFormsModelElement::FindInstanceElement(aID
, getter_AddRefs(instance
));
2012 nsIDOMDocument
*doc
= nsnull
;
2014 instance
->GetInstanceDocument(&doc
); // addrefs
2021 nsXFormsModelElement::ProcessBindElements()
2023 // ProcessBindElements() will go through each xforms:bind element in
2024 // document order and apply all of the Model Item Properties to the
2025 // instance items in the nodeset. This information will also be entered
2026 // in the Master Dependency Graph. Most of this work is done in the
2027 // ProcessBind() method.
2029 nsCOMPtr
<nsIDOMDocument
> firstInstanceDoc
=
2030 FindInstanceDocument(EmptyString());
2031 if (!firstInstanceDoc
)
2034 nsCOMPtr
<nsIDOMElement
> firstInstanceRoot
;
2035 firstInstanceDoc
->GetDocumentElement(getter_AddRefs(firstInstanceRoot
));
2038 nsCOMPtr
<nsIDOMXPathEvaluator
> xpath
= do_QueryInterface(firstInstanceDoc
,
2040 NS_ENSURE_TRUE(xpath
, rv
);
2042 nsCOMPtr
<nsIDOMNodeList
> children
;
2043 mElement
->GetChildNodes(getter_AddRefs(children
));
2045 PRUint32 childCount
= 0;
2047 children
->GetLength(&childCount
);
2049 nsAutoString namespaceURI
, localName
;
2050 for (PRUint32 i
= 0; i
< childCount
; ++i
) {
2051 nsCOMPtr
<nsIDOMNode
> child
;
2052 children
->Item(i
, getter_AddRefs(child
));
2053 NS_ASSERTION(child
, "there can't be null items in the NodeList!");
2055 child
->GetLocalName(localName
);
2056 if (localName
.EqualsLiteral("bind")) {
2057 child
->GetNamespaceURI(namespaceURI
);
2058 if (namespaceURI
.EqualsLiteral(NS_NAMESPACE_XFORMS
)) {
2059 rv
= ProcessBind(xpath
, firstInstanceRoot
, 1, 1,
2060 nsCOMPtr
<nsIDOMElement
>(do_QueryInterface(child
)),
2062 if (NS_FAILED(rv
)) {
2073 nsXFormsModelElement::Reset()
2075 BackupOrRestoreInstanceData(PR_TRUE
);
2076 nsXFormsUtils::DispatchEvent(mElement
, eEvent_Rebuild
);
2077 nsXFormsUtils::DispatchEvent(mElement
, eEvent_Recalculate
);
2078 nsXFormsUtils::DispatchEvent(mElement
, eEvent_Revalidate
);
2079 nsXFormsUtils::DispatchEvent(mElement
, eEvent_Refresh
);
2082 // This function will restore all of the model's instance data to it's original
2083 // state if the supplied boolean is PR_TRUE. If it is PR_FALSE, this function
2084 // will cause this model's instance data to be backed up.
2086 nsXFormsModelElement::BackupOrRestoreInstanceData(PRBool restore
)
2088 if (!mInstanceDocuments
)
2092 mInstanceDocuments
->GetLength(&instCount
);
2094 for (PRUint32 i
= 0; i
< instCount
; ++i
) {
2095 nsIInstanceElementPrivate
*instance
=
2096 mInstanceDocuments
->GetInstanceAt(i
);
2098 // Don't know what to do with error if we get one.
2099 // Restore/BackupOriginalDocument will already output warnings.
2101 instance
->RestoreOriginalDocument();
2104 instance
->BackupOriginalDocument();
2113 nsXFormsModelElement::FinishConstruction()
2115 // Ensure that FinishConstruction isn't called due to some callback
2116 // or event handler after the model has started going through its
2117 // destruction phase
2118 NS_ENSURE_STATE(mElement
);
2120 // process inline schemas that aren't referenced via the schema attribute
2121 nsCOMPtr
<nsIDOMNodeList
> children
;
2122 mElement
->GetChildNodes(getter_AddRefs(children
));
2125 PRUint32 childCount
= 0;
2126 children
->GetLength(&childCount
);
2128 nsCOMPtr
<nsIDOMNode
> node
;
2129 nsCOMPtr
<nsIDOMElement
> element
;
2130 nsAutoString nsURI
, localName
, targetNamespace
;
2132 for (PRUint32 i
= 0; i
< childCount
; ++i
) {
2133 children
->Item(i
, getter_AddRefs(node
));
2135 element
= do_QueryInterface(node
);
2139 node
->GetNamespaceURI(nsURI
);
2140 node
->GetLocalName(localName
);
2141 if (nsURI
.EqualsLiteral(NS_NAMESPACE_XML_SCHEMA
) &&
2142 localName
.EqualsLiteral("schema")) {
2143 if (!IsDuplicateSchema(element
)) {
2144 nsCOMPtr
<nsISchema
> schema
;
2145 nsresult rv
= mSchemas
->ProcessSchemaElement(element
, nsnull
,
2146 getter_AddRefs(schema
));
2147 if (!NS_SUCCEEDED(rv
)) {
2148 nsXFormsUtils::ReportError(NS_LITERAL_STRING("schemaProcessError"),
2156 // (XForms 4.2.1 - cont)
2157 // 3. if applicable, initialize P3P
2159 // 4. construct instance data from initial instance data. apply all
2160 // <bind> elements in document order.
2162 // we get the instance data from our instance child nodes
2164 // We're done initializing this model.
2165 // 5. Perform an xforms-rebuild, xforms-recalculate, and xforms-revalidate in
2166 // sequence, for this model element. (The xforms-refresh is not performed
2167 // since the user interface has not yet been initialized).
2168 nsXFormsUtils::DispatchEvent(mElement
, eEvent_Rebuild
);
2169 nsXFormsUtils::DispatchEvent(mElement
, eEvent_Recalculate
);
2170 nsXFormsUtils::DispatchEvent(mElement
, eEvent_Revalidate
);
2176 nsXFormsModelElement::InitializeControls()
2179 printf("nsXFormsModelElement::InitializeControls()\n");
2181 nsPostRefresh postRefresh
= nsPostRefresh();
2183 nsXFormsControlListItem::iterator it
;
2186 for (it
= mFormControls
.begin(); it
!= mFormControls
.end(); ++it
) {
2188 nsCOMPtr
<nsIXFormsControl
> control
= (*it
)->Control();
2189 NS_ASSERTION(control
, "mFormControls has null control?!");
2192 printf("\tControl (%p): ", (void*) control
);
2193 nsCOMPtr
<nsIDOMElement
> controlElement
;
2194 control
->GetElement(getter_AddRefs(controlElement
));
2195 // DBG_TAGINFO(controlElement);
2198 rv
= control
->Bind(&dummy
);
2199 NS_ENSURE_SUCCESS(rv
, rv
);
2202 rv
= control
->Refresh();
2203 // XXX: Bug 336608, refresh still fails for some controls, for some
2205 // NS_ENSURE_SUCCESS(rv, rv);
2208 mChangedNodes
.Clear();
2214 nsXFormsModelElement::ValidateInstanceDocuments()
2216 if (mInstanceDocuments
) {
2218 mInstanceDocuments
->GetLength(&instCount
);
2220 nsCOMPtr
<nsIDOMDocument
> document
;
2222 for (PRUint32 i
= 0; i
< instCount
; ++i
) {
2223 nsIInstanceElementPrivate
* instEle
=
2224 mInstanceDocuments
->GetInstanceAt(i
);
2225 nsCOMPtr
<nsIXFormsNSInstanceElement
> NSInstEle(instEle
);
2226 NSInstEle
->GetInstanceDocument(getter_AddRefs(document
));
2227 NS_ASSERTION(document
,
2228 "nsIXFormsNSInstanceElement::GetInstanceDocument returned null?!");
2231 PRBool isValid
= PR_FALSE
;
2232 ValidateDocument(document
, &isValid
);
2235 nsCOMPtr
<nsIDOMElement
> instanceElement
;
2236 instEle
->GetElement(getter_AddRefs(instanceElement
));
2238 nsXFormsUtils::ReportError(NS_LITERAL_STRING("instDocumentInvalid"),
2247 // NOTE: This function only runs to completion for _one_ of the models in the
2250 nsXFormsModelElement::MaybeNotifyCompletion()
2252 nsCOMPtr
<nsIDOMDocument
> domDoc
;
2253 mElement
->GetOwnerDocument(getter_AddRefs(domDoc
));
2255 const nsVoidArray
*models
= GetModelList(domDoc
);
2257 NS_NOTREACHED("no model list property");
2263 // Nothing to be done if any model is incomplete or hasn't seen
2264 // DOMContentLoaded.
2265 for (i
= 0; i
< models
->Count(); ++i
) {
2266 nsXFormsModelElement
*model
=
2267 static_cast<nsXFormsModelElement
*>(models
->ElementAt(i
));
2268 if (!model
->mDocumentLoaded
|| !model
->IsComplete())
2271 // Check validity of |functions=| attribute, if it exists. Since we
2272 // don't support ANY extension functions currently, the existance of
2273 // |functions=| with a non-empty value is an error.
2274 nsCOMPtr
<nsIDOMElement
> tElement
= model
->mElement
;
2275 nsAutoString extFunctionAtt
;
2276 tElement
->GetAttribute(NS_LITERAL_STRING("functions"), extFunctionAtt
);
2277 if (!extFunctionAtt
.IsEmpty()) {
2278 nsXFormsUtils::ReportError(NS_LITERAL_STRING("invalidExtFunction"),
2280 nsXFormsUtils::DispatchEvent(tElement
, eEvent_ComputeException
);
2285 // validate the instance documents because we want schemaValidation to add
2286 // schema type properties from the schema file unto our instance document
2288 // XXX: wrong location of this call, @see bug 339674
2289 ValidateInstanceDocuments();
2291 // Register deferred binds with the model. It does not bind the controls,
2292 // only bind them to the model they belong to.
2293 nsXFormsModelElement::ProcessDeferredBinds(domDoc
);
2295 // Okay, dispatch xforms-model-construct-done
2296 for (i
= 0; i
< models
->Count(); ++i
) {
2297 nsXFormsModelElement
*model
=
2298 static_cast<nsXFormsModelElement
*>(models
->ElementAt(i
));
2299 nsXFormsUtils::DispatchEvent(model
->mElement
, eEvent_ModelConstructDone
);
2302 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(domDoc
);
2304 PRUint32 loadingMessages
= NS_PTR_TO_UINT32(
2305 doc
->GetProperty(nsXFormsAtoms::externalMessagesProperty
));
2306 if (loadingMessages
) {
2307 // if we are still waiting for external messages to load, then put off
2308 // the xforms-ready until a model in the document is notified that they
2309 // are finished loading
2315 // Backup instances and fire xforms-ready
2316 for (i
= 0; i
< models
->Count(); ++i
) {
2317 nsXFormsModelElement
*model
=
2318 static_cast<nsXFormsModelElement
*>(models
->ElementAt(i
));
2319 model
->BackupOrRestoreInstanceData(PR_FALSE
);
2320 model
->mReadyHandled
= PR_TRUE
;
2321 nsXFormsUtils::DispatchEvent(model
->mElement
, eEvent_Ready
);
2326 nsXFormsModelElement::ProcessBind(nsIDOMXPathEvaluator
*aEvaluator
,
2327 nsIDOMNode
*aContextNode
,
2328 PRInt32 aContextPosition
,
2329 PRInt32 aContextSize
,
2330 nsIDOMElement
*aBindElement
,
2333 // Get the model item properties specified by this \<bind\>.
2334 nsCOMPtr
<nsIDOMXPathExpression
> props
[eModel__count
];
2335 nsAutoString propStrings
[eModel__count
];
2336 nsAutoString attrStr
;
2338 nsCOMPtr
<nsIDOMXPathNSResolver
> resolver
;
2339 nsresult rv
= aEvaluator
->CreateNSResolver(aBindElement
,
2340 getter_AddRefs(resolver
));
2341 NS_ENSURE_SUCCESS(rv
, rv
);
2343 nsCOMPtr
<nsIXPathEvaluatorInternal
> eval
= do_QueryInterface(aEvaluator
, &rv
);
2344 NS_ENSURE_SUCCESS(rv
, rv
);
2346 for (PRUint32 i
= 0; i
< eModel__count
; ++i
) {
2347 sModelPropsList
[i
]->ToString(attrStr
);
2349 aBindElement
->GetAttribute(attrStr
, propStrings
[i
]);
2352 // Find the nodeset that this bind applies to.
2353 nsCOMPtr
<nsIDOMXPathResult
> result
;
2355 nsAutoString exprString
;
2356 aBindElement
->GetAttribute(NS_LITERAL_STRING("nodeset"), exprString
);
2357 if (exprString
.IsEmpty()) {
2358 exprString
= NS_LITERAL_STRING(".");
2361 nsCOMPtr
<nsIXFormsXPathState
> state
= new nsXFormsXPathState(aBindElement
,
2363 NS_ENSURE_TRUE(state
, NS_ERROR_OUT_OF_MEMORY
);
2364 rv
= nsXFormsUtils::EvaluateXPath(eval
, exprString
, aContextNode
, resolver
,
2366 nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE
,
2367 aContextPosition
, aContextSize
,
2368 nsnull
, getter_AddRefs(result
));
2369 if (NS_FAILED(rv
)) {
2370 if (rv
== NS_ERROR_DOM_INVALID_EXPRESSION_ERR
) {
2371 // the xpath expression isn't valid xpath
2372 const PRUnichar
*strings
[] = { exprString
.get() };
2373 nsXFormsUtils::ReportError(NS_LITERAL_STRING("exprParseError"),
2374 strings
, 1, aBindElement
, nsnull
);
2375 nsXFormsUtils::DispatchEvent(mElement
, eEvent_ComputeException
);
2378 printf("xforms-binding-exception: XPath Evaluation failed\n");
2380 const PRUnichar
*strings
[] = { exprString
.get() };
2381 nsXFormsUtils::ReportError(NS_LITERAL_STRING("nodesetEvaluateError"),
2382 strings
, 1, aBindElement
, aBindElement
);
2383 nsXFormsUtils::DispatchEvent(mElement
, eEvent_BindingException
);
2388 NS_ENSURE_STATE(result
);
2390 // If this is an outer bind, store the nodeset, as controls binding to this
2391 // bind will need this.
2393 nsCOMPtr
<nsIContent
> content(do_QueryInterface(aBindElement
));
2394 NS_ASSERTION(content
, "nsIDOMElement not implementing nsIContent?!");
2395 rv
= content
->SetProperty(nsXFormsAtoms::bind
, result
,
2397 NS_ENSURE_SUCCESS(rv
, rv
);
2399 // addref, circumventing nsDerivedSave
2400 NS_ADDREF(static_cast<nsIDOMXPathResult
*>(result
));
2404 rv
= result
->GetSnapshotLength(&snapLen
);
2405 NS_ENSURE_SUCCESS(rv
, rv
);
2408 // Iterate over resultset
2409 nsCOMArray
<nsIDOMNode
> deps
;
2410 nsCOMPtr
<nsIDOMNode
> node
;
2416 // We rightly assume that all the nodes in the nodeset came from the same
2417 // document. So now we'll get the xpath evaluator from that document. We
2418 // need to ensure that the context node for the evaluation of each MIP
2419 // expression and the evaluator for those expressions came from the same
2420 // document. It is a rule for xpath.
2421 PRUint32 snapItem
= 0;
2423 for (; snapItem
< snapLen
; ++snapItem
) {
2424 rv
= result
->SnapshotItem(snapItem
, getter_AddRefs(node
));
2425 NS_ENSURE_SUCCESS(rv
, rv
);
2430 NS_WARNING("nsXFormsModelElement::ProcessBind(): Empty node in result set.");
2438 nsCOMPtr
<nsIDOMDocument
> nodesetDoc
;
2439 node
->GetOwnerDocument(getter_AddRefs(nodesetDoc
));
2441 nsCOMPtr
<nsIDOMXPathEvaluator
> nodesetEval
= do_QueryInterface(nodesetDoc
);
2442 nsCOMPtr
<nsIXPathEvaluatorInternal
> nodesetEvalInternal
=
2443 do_QueryInterface(nodesetEval
);
2444 NS_ENSURE_STATE(nodesetEval
&& nodesetEvalInternal
);
2446 // Since we've already gotten the first node in the nodeset and verified it is
2447 // good to go, we'll contine on. For this node and each subsequent node in
2448 // the nodeset, we'll evaluate the MIP expressions attached to the bind
2449 // element and add them to the MDG. And also process any binds that this
2450 // bind contains (aka nested binds).
2451 while (node
&& snapItem
< snapLen
) {
2453 // set the context node for the expression that is being analyzed.
2454 nsCOMPtr
<nsIXFormsXPathState
> stateForMIP
=
2455 new nsXFormsXPathState(aBindElement
, node
);
2456 NS_ENSURE_TRUE(stateForMIP
, NS_ERROR_OUT_OF_MEMORY
);
2459 nsXFormsXPathParser parser
;
2460 nsXFormsXPathAnalyzer
analyzer(eval
, resolver
, stateForMIP
);
2461 PRBool multiMIP
= PR_FALSE
;
2462 for (PRUint32 j
= 0; j
< eModel__count
; ++j
) {
2463 if (propStrings
[j
].IsEmpty())
2466 // type and p3ptype are stored as properties on the instance node
2467 if (j
== eModel_type
|| j
== eModel_p3ptype
) {
2468 nsClassHashtable
<nsISupportsHashKey
, nsString
> *table
;
2469 table
= j
== eModel_type
? &mNodeToType
: &mNodeToP3PType
;
2470 NS_ENSURE_TRUE(table
->IsInitialized(), NS_ERROR_FAILURE
);
2472 // Check for existing value
2473 if (table
->Get(node
, nsnull
)) {
2479 nsAutoPtr
<nsString
> newString(new nsString(propStrings
[j
]));
2480 NS_ENSURE_TRUE(newString
, NS_ERROR_OUT_OF_MEMORY
);
2481 NS_ENSURE_TRUE(table
->Put(node
, newString
), NS_ERROR_OUT_OF_MEMORY
);
2483 // string is successfully stored in the table, we should not dealloc it
2486 if (j
== eModel_type
) {
2487 // Inform MDG that it needs to check type. The only arguments
2488 // actually used are |eModel_constraint| and |node|.
2489 rv
= mMDG
.AddMIP(eModel_constraint
, nsnull
, nsnull
, PR_FALSE
, node
,
2491 NS_ENSURE_SUCCESS(rv
, rv
);
2495 rv
= nsXFormsUtils::CreateExpression(nodesetEvalInternal
,
2496 propStrings
[j
], resolver
,
2498 getter_AddRefs(props
[j
]));
2499 if (NS_FAILED(rv
)) {
2500 const PRUnichar
*strings
[] = { propStrings
[j
].get() };
2501 nsXFormsUtils::ReportError(NS_LITERAL_STRING("mipParseError"),
2502 strings
, 1, aBindElement
, aBindElement
);
2503 nsXFormsUtils::DispatchEvent(mElement
, eEvent_ComputeException
);
2507 // the rest of the MIPs are given to the MDG
2508 nsCOMPtr
<nsIDOMNSXPathExpression
> expr
= do_QueryInterface(props
[j
]);
2510 // Get node dependencies
2511 nsAutoPtr
<nsXFormsXPathNode
> xNode(parser
.Parse(propStrings
[j
]));
2513 rv
= analyzer
.Analyze(node
, xNode
, expr
, &propStrings
[j
], &deps
,
2514 snapItem
+ 1, snapLen
, PR_FALSE
);
2515 NS_ENSURE_SUCCESS(rv
, rv
);
2518 rv
= mMDG
.AddMIP((ModelItemPropName
) j
,
2521 parser
.UsesDynamicFunc(),
2526 // if the call results in NS_ERROR_ABORT the page has tried to set a
2527 // MIP twice, break and emit an exception.
2528 if (rv
== NS_ERROR_ABORT
) {
2532 NS_ENSURE_SUCCESS(rv
, rv
);
2536 // If the attribute is already there, the page sets a MIP twice
2537 // which is illegal, and should result in an xforms-binding-exception.
2538 // @see http://www.w3.org/TR/xforms/slice4.html#evt-modelConstruct
2542 printf("xforms-binding-exception: Multiple MIPs on same node!");
2544 nsXFormsUtils::ReportError(NS_LITERAL_STRING("multiMIPError"),
2546 nsXFormsUtils::DispatchEvent(aBindElement
,
2547 eEvent_BindingException
);
2548 return NS_ERROR_FAILURE
;
2551 // Now evaluate any child \<bind\> elements.
2552 nsCOMPtr
<nsIDOMNodeList
> children
;
2553 aBindElement
->GetChildNodes(getter_AddRefs(children
));
2555 PRUint32 childCount
= 0;
2556 children
->GetLength(&childCount
);
2558 nsCOMPtr
<nsIDOMNode
> child
;
2561 for (PRUint32 k
= 0; k
< childCount
; ++k
) {
2562 children
->Item(k
, getter_AddRefs(child
));
2564 child
->GetLocalName(value
);
2565 if (!value
.EqualsLiteral("bind"))
2568 child
->GetNamespaceURI(value
);
2569 if (!value
.EqualsLiteral(NS_NAMESPACE_XFORMS
))
2572 rv
= ProcessBind(aEvaluator
, node
,
2573 snapItem
+ 1, snapLen
,
2574 nsCOMPtr
<nsIDOMElement
>(do_QueryInterface(child
)));
2575 NS_ENSURE_SUCCESS(rv
, rv
);
2581 while (snapItem
< snapLen
) {
2582 rv
= result
->SnapshotItem(snapItem
, getter_AddRefs(node
));
2583 NS_ENSURE_SUCCESS(rv
, rv
);
2589 NS_WARNING("nsXFormsModelElement::ProcessBind(): Empty node in result set.");
2598 nsXFormsModelElement::AddInstanceElement(nsIInstanceElementPrivate
*aInstEle
)
2600 NS_ENSURE_STATE(mInstanceDocuments
);
2601 mInstanceDocuments
->AddInstance(aInstEle
);
2607 nsXFormsModelElement::RemoveInstanceElement(nsIInstanceElementPrivate
*aInstEle
)
2609 NS_ENSURE_STATE(mInstanceDocuments
);
2610 mInstanceDocuments
->RemoveInstance(aInstEle
);
2616 nsXFormsModelElement::MessageLoadFinished()
2618 // This is our signal that all external message links have been tested. If
2619 // we were waiting for this to send out xforms-ready, then now is the time.
2621 // if this document hasn't processed xforms-model-construct-done, yet (which
2622 // must precede xforms-ready), then we'll send out the xforms-ready later
2623 // as part of our normal handling. If we've already become ready, then this
2624 // event was probably generated by a change in the src attribute on the
2625 // message element. Ignore it in that case.
2626 if (!mConstructDoneHandled
|| mReadyHandled
) {
2630 nsCOMPtr
<nsIDOMDocument
> domDoc
;
2631 mElement
->GetOwnerDocument(getter_AddRefs(domDoc
));
2632 const nsVoidArray
*models
= GetModelList(domDoc
);
2633 nsCOMPtr
<nsIDocument
>doc
= do_QueryInterface(domDoc
);
2634 nsCOMArray
<nsIXFormsControl
> *deferredBindList
=
2635 static_cast<nsCOMArray
<nsIXFormsControl
> *>
2636 (doc
->GetProperty(nsXFormsAtoms::deferredBindListProperty
));
2638 // if we've already gotten the xforms-model-construct-done event and not
2639 // yet the xforms-ready, we've hit a window where we may still be
2640 // processing the deferred control binding. If so, we'll leave now and
2641 // leave it to MaybeNotifyCompletion to generate the xforms-ready event.
2642 if (deferredBindList
) {
2647 // if we reached here, then we had to wait on sending out the xforms-ready
2648 // events until the external messages were tested. Now we are finally
2649 // ready to send out xforms-ready to all of the models.
2650 for (int i
= 0; i
< models
->Count(); ++i
) {
2651 nsXFormsModelElement
*model
=
2652 static_cast<nsXFormsModelElement
*>(models
->ElementAt(i
));
2653 model
->mReadyHandled
= PR_TRUE
;
2654 nsXFormsUtils::DispatchEvent(model
->mElement
, eEvent_Ready
);
2661 nsXFormsModelElement::GetHasDOMContentFired(PRBool
*aLoaded
)
2663 NS_ENSURE_ARG_POINTER(aLoaded
);
2665 *aLoaded
= mDocumentLoaded
;
2670 nsXFormsModelElement::ForceRebind(nsIXFormsControl
* aControl
)
2676 nsXFormsControlListItem
* controlItem
= mFormControls
.FindControl(aControl
);
2677 NS_ENSURE_STATE(controlItem
);
2679 PRBool rebindChildren
;
2680 nsresult rv
= aControl
->Bind(&rebindChildren
);
2681 NS_ENSURE_SUCCESS(rv
, rv
);
2683 rv
= aControl
->Refresh();
2684 // XXX: no rv-check, see bug 336608
2687 return RefreshSubTree(controlItem
->FirstChild(), rebindChildren
);
2691 nsXFormsModelElement::GetBuiltinTypeName(PRUint16 aType
,
2695 case nsISchemaBuiltinType::BUILTIN_TYPE_STRING
:
2696 aName
.AssignLiteral("string");
2698 case nsISchemaBuiltinType::BUILTIN_TYPE_BOOLEAN
:
2699 aName
.AssignLiteral("boolean");
2701 case nsISchemaBuiltinType::BUILTIN_TYPE_DECIMAL
:
2702 aName
.AssignLiteral("decimal");
2704 case nsISchemaBuiltinType::BUILTIN_TYPE_FLOAT
:
2705 aName
.AssignLiteral("float");
2707 case nsISchemaBuiltinType::BUILTIN_TYPE_DOUBLE
:
2708 aName
.AssignLiteral("double");
2710 case nsISchemaBuiltinType::BUILTIN_TYPE_DURATION
:
2711 aName
.AssignLiteral("duration");
2713 case nsISchemaBuiltinType::BUILTIN_TYPE_DATETIME
:
2714 aName
.AssignLiteral("dateTime");
2716 case nsISchemaBuiltinType::BUILTIN_TYPE_TIME
:
2717 aName
.AssignLiteral("time");
2719 case nsISchemaBuiltinType::BUILTIN_TYPE_DATE
:
2720 aName
.AssignLiteral("date");
2722 case nsISchemaBuiltinType::BUILTIN_TYPE_GYEARMONTH
:
2723 aName
.AssignLiteral("gYearMonth");
2725 case nsISchemaBuiltinType::BUILTIN_TYPE_GYEAR
:
2726 aName
.AssignLiteral("gYear");
2728 case nsISchemaBuiltinType::BUILTIN_TYPE_GMONTHDAY
:
2729 aName
.AssignLiteral("gMonthDay");
2731 case nsISchemaBuiltinType::BUILTIN_TYPE_GDAY
:
2732 aName
.AssignLiteral("gDay");
2734 case nsISchemaBuiltinType::BUILTIN_TYPE_GMONTH
:
2735 aName
.AssignLiteral("gMonth");
2737 case nsISchemaBuiltinType::BUILTIN_TYPE_HEXBINARY
:
2738 aName
.AssignLiteral("hexBinary");
2740 case nsISchemaBuiltinType::BUILTIN_TYPE_BASE64BINARY
:
2741 aName
.AssignLiteral("base64Binary");
2743 case nsISchemaBuiltinType::BUILTIN_TYPE_ANYURI
:
2744 aName
.AssignLiteral("anyURI");
2746 case nsISchemaBuiltinType::BUILTIN_TYPE_QNAME
:
2747 aName
.AssignLiteral("QName");
2749 case nsISchemaBuiltinType::BUILTIN_TYPE_NOTATION
:
2750 aName
.AssignLiteral("NOTATION");
2752 case nsISchemaBuiltinType::BUILTIN_TYPE_NORMALIZED_STRING
:
2753 aName
.AssignLiteral("normalizedString");
2755 case nsISchemaBuiltinType::BUILTIN_TYPE_TOKEN
:
2756 aName
.AssignLiteral("token");
2758 case nsISchemaBuiltinType::BUILTIN_TYPE_BYTE
:
2759 aName
.AssignLiteral("byte");
2761 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDBYTE
:
2762 aName
.AssignLiteral("unsignedByte");
2764 case nsISchemaBuiltinType::BUILTIN_TYPE_INTEGER
:
2765 aName
.AssignLiteral("integer");
2767 case nsISchemaBuiltinType::BUILTIN_TYPE_NEGATIVEINTEGER
:
2768 aName
.AssignLiteral("negativeInteger");
2770 case nsISchemaBuiltinType::BUILTIN_TYPE_NONPOSITIVEINTEGER
:
2771 aName
.AssignLiteral("nonPositiveInteger");
2773 case nsISchemaBuiltinType::BUILTIN_TYPE_LONG
:
2774 aName
.AssignLiteral("long");
2776 case nsISchemaBuiltinType::BUILTIN_TYPE_NONNEGATIVEINTEGER
:
2777 aName
.AssignLiteral("nonNegativeInteger");
2779 case nsISchemaBuiltinType::BUILTIN_TYPE_INT
:
2780 aName
.AssignLiteral("int");
2782 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDINT
:
2783 aName
.AssignLiteral("unsignedInt");
2785 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDLONG
:
2786 aName
.AssignLiteral("unsignedLong");
2788 case nsISchemaBuiltinType::BUILTIN_TYPE_POSITIVEINTEGER
:
2789 aName
.AssignLiteral("positiveInteger");
2791 case nsISchemaBuiltinType::BUILTIN_TYPE_SHORT
:
2792 aName
.AssignLiteral("short");
2794 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDSHORT
:
2795 aName
.AssignLiteral("unsignedShort");
2797 case nsISchemaBuiltinType::BUILTIN_TYPE_LANGUAGE
:
2798 aName
.AssignLiteral("language");
2800 case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKEN
:
2801 aName
.AssignLiteral("NMTOKEN");
2803 case nsISchemaBuiltinType::BUILTIN_TYPE_NAME
:
2804 aName
.AssignLiteral("Name");
2806 case nsISchemaBuiltinType::BUILTIN_TYPE_NCNAME
:
2807 aName
.AssignLiteral("NCName");
2809 case nsISchemaBuiltinType::BUILTIN_TYPE_ID
:
2810 aName
.AssignLiteral("ID");
2812 case nsISchemaBuiltinType::BUILTIN_TYPE_IDREF
:
2813 aName
.AssignLiteral("IDREF");
2815 case nsISchemaBuiltinType::BUILTIN_TYPE_ENTITY
:
2816 aName
.AssignLiteral("ENTITY");
2818 case nsISchemaBuiltinType::BUILTIN_TYPE_IDREFS
:
2819 aName
.AssignLiteral("IDREFS");
2821 case nsISchemaBuiltinType::BUILTIN_TYPE_ENTITIES
:
2822 aName
.AssignLiteral("ENTITIES");
2824 case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKENS
:
2825 aName
.AssignLiteral("NMTOKENS");
2828 // should never hit here
2829 NS_WARNING("nsXFormsModelElement::GetBuiltinTypeName: Unknown builtin type encountered.");
2830 return NS_ERROR_FAILURE
;
2837 nsXFormsModelElement::GetBuiltinTypesNames(PRUint16 aType
,
2838 nsStringArray
*aNameArray
)
2840 // This function recursively appends aType (and its base types) to
2841 // aNameArray. So it assumes aType isn't in the array already.
2842 nsAutoString typeString
, builtString
;
2843 PRUint16 parentType
= 0;
2845 // We won't append xsd:anyType as the base of every type since that is kinda
2848 nsresult rv
= GetBuiltinTypeName(aType
, typeString
);
2849 NS_ENSURE_SUCCESS(rv
, rv
);
2852 case nsISchemaBuiltinType::BUILTIN_TYPE_NORMALIZED_STRING
:
2853 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_STRING
;
2855 case nsISchemaBuiltinType::BUILTIN_TYPE_TOKEN
:
2856 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_NORMALIZED_STRING
;
2858 case nsISchemaBuiltinType::BUILTIN_TYPE_BYTE
:
2859 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_SHORT
;
2861 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDBYTE
:
2862 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDSHORT
;
2864 case nsISchemaBuiltinType::BUILTIN_TYPE_INTEGER
:
2865 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_DECIMAL
;
2867 case nsISchemaBuiltinType::BUILTIN_TYPE_NEGATIVEINTEGER
:
2868 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_NONPOSITIVEINTEGER
;
2870 case nsISchemaBuiltinType::BUILTIN_TYPE_NONPOSITIVEINTEGER
:
2871 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_INTEGER
;
2873 case nsISchemaBuiltinType::BUILTIN_TYPE_LONG
:
2874 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_INTEGER
;
2876 case nsISchemaBuiltinType::BUILTIN_TYPE_NONNEGATIVEINTEGER
:
2877 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_INTEGER
;
2879 case nsISchemaBuiltinType::BUILTIN_TYPE_INT
:
2880 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_LONG
;
2882 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDINT
:
2883 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDLONG
;
2885 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDLONG
:
2886 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_NONNEGATIVEINTEGER
;
2888 case nsISchemaBuiltinType::BUILTIN_TYPE_POSITIVEINTEGER
:
2889 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_NONNEGATIVEINTEGER
;
2891 case nsISchemaBuiltinType::BUILTIN_TYPE_SHORT
:
2892 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_INT
;
2894 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDSHORT
:
2895 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDINT
;
2897 case nsISchemaBuiltinType::BUILTIN_TYPE_LANGUAGE
:
2898 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_TOKEN
;
2900 case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKEN
:
2901 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_TOKEN
;
2903 case nsISchemaBuiltinType::BUILTIN_TYPE_NAME
:
2904 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_TOKEN
;
2906 case nsISchemaBuiltinType::BUILTIN_TYPE_NCNAME
:
2907 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_NAME
;
2909 case nsISchemaBuiltinType::BUILTIN_TYPE_ID
:
2910 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_NCNAME
;
2912 case nsISchemaBuiltinType::BUILTIN_TYPE_IDREF
:
2913 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_NCNAME
;
2915 case nsISchemaBuiltinType::BUILTIN_TYPE_ENTITY
:
2916 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_NCNAME
;
2918 case nsISchemaBuiltinType::BUILTIN_TYPE_IDREFS
:
2919 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_IDREF
;
2921 case nsISchemaBuiltinType::BUILTIN_TYPE_ENTITIES
:
2922 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_ENTITY
;
2924 case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKENS
:
2925 parentType
= nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKEN
;
2929 builtString
.AppendLiteral(NS_NAMESPACE_XML_SCHEMA
);
2930 builtString
.AppendLiteral("#");
2931 builtString
.Append(typeString
);
2932 aNameArray
->AppendString(builtString
);
2935 return GetBuiltinTypesNames(parentType
, aNameArray
);
2941 nsXFormsModelElement::WalkTypeChainInternal(nsISchemaType
*aType
,
2942 PRBool aFindRootBuiltin
,
2943 PRUint16
*aBuiltinType
,
2944 nsStringArray
*aTypeArray
)
2946 PRUint16 schemaTypeValue
= 0;
2947 aType
->GetSchemaType(&schemaTypeValue
);
2948 NS_ENSURE_STATE(schemaTypeValue
);
2949 nsresult rv
= NS_OK
;
2950 nsCOMPtr
<nsISchemaSimpleType
> simpleType
;
2952 if (schemaTypeValue
== nsISchemaType::SCHEMA_TYPE_SIMPLE
) {
2953 simpleType
= do_QueryInterface(aType
);
2954 NS_ENSURE_STATE(simpleType
);
2955 PRUint16 simpleTypeValue
;
2956 simpleType
->GetSimpleType(&simpleTypeValue
);
2957 NS_ENSURE_STATE(simpleTypeValue
);
2959 switch (simpleTypeValue
) {
2960 case nsISchemaSimpleType::SIMPLE_TYPE_BUILTIN
:
2962 nsCOMPtr
<nsISchemaBuiltinType
> builtinType(do_QueryInterface(aType
));
2963 NS_ENSURE_STATE(builtinType
);
2965 if (aFindRootBuiltin
)
2966 return BuiltinTypeToPrimative(builtinType
, aBuiltinType
);
2968 PRUint16 builtinTypeVal
;
2969 rv
= builtinType
->GetBuiltinType(&builtinTypeVal
);
2970 NS_ENSURE_SUCCESS(rv
, rv
);
2973 *aBuiltinType
= builtinTypeVal
;
2976 return GetBuiltinTypesNames(builtinTypeVal
, aTypeArray
);
2980 case nsISchemaSimpleType::SIMPLE_TYPE_RESTRICTION
:
2982 nsCOMPtr
<nsISchemaRestrictionType
> restType(do_QueryInterface(aType
));
2983 NS_ENSURE_STATE(restType
);
2984 restType
->GetBaseType(getter_AddRefs(simpleType
));
2988 case nsISchemaSimpleType::SIMPLE_TYPE_LIST
:
2990 nsCOMPtr
<nsISchemaListType
> listType(do_QueryInterface(aType
));
2991 NS_ENSURE_STATE(listType
);
2992 listType
->GetListType(getter_AddRefs(simpleType
));
2996 case nsISchemaSimpleType::SIMPLE_TYPE_UNION
:
2998 // For now union types aren't supported. A union means that the type
2999 // could be of any type listed in the union and still be valid. But we
3000 // don't know which path it will take since we'd basically have to
3001 // validate the node value to know. Someday we may have to figure out
3002 // how to properly handle this, though we may never need to if no other
3003 // processor supports it. Strictly interpreting the spec, we don't
3004 // need to handle unions as far as determining whether a control can
3005 // bind to data of a given type. Just the types defined in the spec
3006 // and restrictions of those types.
3007 return NS_ERROR_XFORMS_UNION_TYPE
;
3010 // We only anticipate the 4 types listed above. Definitely an error
3011 // if we get something else.
3012 return NS_ERROR_FAILURE
;
3015 } else if (schemaTypeValue
== nsISchemaType::SCHEMA_TYPE_COMPLEX
) {
3016 nsCOMPtr
<nsISchemaComplexType
> complexType(do_QueryInterface(aType
));
3017 NS_ENSURE_STATE(complexType
);
3018 PRUint16 complexTypeValue
= 0;
3019 complexType
->GetDerivation(&complexTypeValue
);
3020 NS_ENSURE_STATE(complexTypeValue
);
3021 if ((complexTypeValue
==
3022 nsISchemaComplexType::DERIVATION_RESTRICTION_SIMPLE
) ||
3023 (complexTypeValue
==
3024 nsISchemaComplexType::DERIVATION_EXTENSION_SIMPLE
)) {
3025 complexType
->GetSimpleBaseType(getter_AddRefs(simpleType
));
3027 return NS_ERROR_FAILURE
;
3030 return NS_ERROR_FAILURE
;
3033 // For SIMPLE_TYPE_LIST and SIMPLE_TYPE_RESTRICTION we need to go around
3034 // the horn again with the next simpleType. Same with
3035 // DERIVATION_RESTRICTION_SIMPLE and DERIVATION_EXTENSION_SIMPLE. All other
3036 // types should not reach here.
3038 NS_ENSURE_STATE(simpleType
);
3041 nsAutoString builtString
;
3042 rv
= aType
->GetTargetNamespace(builtString
);
3043 NS_ENSURE_SUCCESS(rv
, rv
);
3044 nsAutoString typeName
;
3045 rv
= aType
->GetName(typeName
);
3046 NS_ENSURE_SUCCESS(rv
, rv
);
3047 builtString
.AppendLiteral("#");
3048 builtString
.Append(typeName
);
3049 aTypeArray
->AppendString(builtString
);
3052 return WalkTypeChainInternal(simpleType
, aFindRootBuiltin
, aBuiltinType
,
3058 nsXFormsModelElement::BuiltinTypeToPrimative(nsISchemaBuiltinType
*aSchemaType
,
3059 PRUint16
*aPrimType
)
3061 NS_ENSURE_ARG(aSchemaType
);
3062 NS_ENSURE_ARG_POINTER(aPrimType
);
3064 PRUint16 builtinType
= 0;
3065 nsresult rv
= aSchemaType
->GetBuiltinType(&builtinType
);
3066 NS_ENSURE_SUCCESS(rv
, rv
);
3068 // Note: this won't return BUILTIN_TYPE_ANY since that is the root of all
3071 switch (builtinType
) {
3072 case nsISchemaBuiltinType::BUILTIN_TYPE_STRING
:
3073 case nsISchemaBuiltinType::BUILTIN_TYPE_BOOLEAN
:
3074 case nsISchemaBuiltinType::BUILTIN_TYPE_DECIMAL
:
3075 case nsISchemaBuiltinType::BUILTIN_TYPE_FLOAT
:
3076 case nsISchemaBuiltinType::BUILTIN_TYPE_DOUBLE
:
3077 case nsISchemaBuiltinType::BUILTIN_TYPE_DURATION
:
3078 case nsISchemaBuiltinType::BUILTIN_TYPE_DATETIME
:
3079 case nsISchemaBuiltinType::BUILTIN_TYPE_TIME
:
3080 case nsISchemaBuiltinType::BUILTIN_TYPE_DATE
:
3081 case nsISchemaBuiltinType::BUILTIN_TYPE_GYEARMONTH
:
3082 case nsISchemaBuiltinType::BUILTIN_TYPE_GYEAR
:
3083 case nsISchemaBuiltinType::BUILTIN_TYPE_GMONTHDAY
:
3084 case nsISchemaBuiltinType::BUILTIN_TYPE_GDAY
:
3085 case nsISchemaBuiltinType::BUILTIN_TYPE_GMONTH
:
3086 case nsISchemaBuiltinType::BUILTIN_TYPE_HEXBINARY
:
3087 case nsISchemaBuiltinType::BUILTIN_TYPE_BASE64BINARY
:
3088 case nsISchemaBuiltinType::BUILTIN_TYPE_ANYURI
:
3089 case nsISchemaBuiltinType::BUILTIN_TYPE_QNAME
:
3090 case nsISchemaBuiltinType::BUILTIN_TYPE_NOTATION
:
3091 *aPrimType
= builtinType
;
3094 case nsISchemaBuiltinType::BUILTIN_TYPE_NORMALIZED_STRING
:
3095 case nsISchemaBuiltinType::BUILTIN_TYPE_TOKEN
:
3096 case nsISchemaBuiltinType::BUILTIN_TYPE_LANGUAGE
:
3097 case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKEN
:
3098 case nsISchemaBuiltinType::BUILTIN_TYPE_NAME
:
3099 case nsISchemaBuiltinType::BUILTIN_TYPE_NCNAME
:
3100 case nsISchemaBuiltinType::BUILTIN_TYPE_ID
:
3101 case nsISchemaBuiltinType::BUILTIN_TYPE_IDREF
:
3102 case nsISchemaBuiltinType::BUILTIN_TYPE_ENTITY
:
3103 case nsISchemaBuiltinType::BUILTIN_TYPE_IDREFS
:
3104 case nsISchemaBuiltinType::BUILTIN_TYPE_ENTITIES
:
3105 case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKENS
:
3106 *aPrimType
= nsISchemaBuiltinType::BUILTIN_TYPE_STRING
;
3108 case nsISchemaBuiltinType::BUILTIN_TYPE_BYTE
:
3109 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDBYTE
:
3110 case nsISchemaBuiltinType::BUILTIN_TYPE_INTEGER
:
3111 case nsISchemaBuiltinType::BUILTIN_TYPE_NEGATIVEINTEGER
:
3112 case nsISchemaBuiltinType::BUILTIN_TYPE_NONPOSITIVEINTEGER
:
3113 case nsISchemaBuiltinType::BUILTIN_TYPE_LONG
:
3114 case nsISchemaBuiltinType::BUILTIN_TYPE_NONNEGATIVEINTEGER
:
3115 case nsISchemaBuiltinType::BUILTIN_TYPE_INT
:
3116 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDINT
:
3117 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDLONG
:
3118 case nsISchemaBuiltinType::BUILTIN_TYPE_POSITIVEINTEGER
:
3119 case nsISchemaBuiltinType::BUILTIN_TYPE_SHORT
:
3120 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDSHORT
:
3121 *aPrimType
= nsISchemaBuiltinType::BUILTIN_TYPE_DECIMAL
;
3124 // should never hit here
3125 NS_WARNING("nsXFormsModelElement::BuiltinTypeToPrimative: Unknown builtin type encountered.");
3126 return NS_ERROR_FAILURE
;
3133 nsXFormsModelElement::GetDerivedTypeList(const nsAString
&aType
,
3134 const nsAString
&aNamespace
,
3135 nsAString
&aTypeList
)
3137 nsCOMPtr
<nsISchemaCollection
> schemaColl
= do_QueryInterface(mSchemas
);
3138 NS_ENSURE_STATE(schemaColl
);
3140 nsCOMPtr
<nsISchemaType
> schemaType
;
3141 schemaColl
->GetType(aType
, aNamespace
, getter_AddRefs(schemaType
));
3142 NS_ENSURE_STATE(schemaType
);
3144 nsStringArray typeArray
;
3145 nsresult rv
= WalkTypeChainInternal(schemaType
, PR_FALSE
, nsnull
, &typeArray
);
3146 if (NS_SUCCEEDED(rv
)) {
3147 nsCOMPtr
<nsIStringEnumerator
> stringEnum
;
3148 rv
= NS_NewStringEnumerator(getter_AddRefs(stringEnum
), &typeArray
);
3149 if (NS_SUCCEEDED(rv
)) {
3150 nsAutoString constructorString
;
3151 PRBool hasMore
= PR_FALSE
;
3152 rv
= stringEnum
->HasMore(&hasMore
);
3153 while (NS_SUCCEEDED(rv
) && hasMore
) {
3154 nsAutoString tempString
;
3155 rv
= stringEnum
->GetNext(tempString
);
3156 if (NS_SUCCEEDED(rv
)) {
3157 constructorString
.Append(tempString
);
3158 stringEnum
->HasMore(&hasMore
);
3160 constructorString
.AppendLiteral(" ");
3165 if (NS_SUCCEEDED(rv
)) {
3166 aTypeList
.Assign(constructorString
);
3171 if (NS_FAILED(rv
)) {
3172 aTypeList
.Assign(EmptyString());
3181 nsXFormsModelElement::GetBuiltinTypeNameForControl(nsIXFormsControl
*aControl
,
3182 nsAString
& aTypeName
)
3184 NS_ENSURE_ARG(aControl
);
3186 nsCOMPtr
<nsISchemaType
> schemaType
;
3187 nsresult rv
= GetTypeForControl(aControl
, getter_AddRefs(schemaType
));
3188 NS_ENSURE_SUCCESS(rv
, rv
);
3190 PRUint16 builtinType
;
3191 rv
= WalkTypeChainInternal(schemaType
, PR_FALSE
, &builtinType
);
3192 NS_ENSURE_SUCCESS(rv
, rv
);
3194 return GetBuiltinTypeName(builtinType
, aTypeName
);
3198 nsXFormsModelElement::GetRootBuiltinType(nsISchemaType
*aType
,
3199 PRUint16
*aBuiltinType
)
3201 NS_ENSURE_ARG(aType
);
3202 NS_ENSURE_ARG_POINTER(aBuiltinType
);
3204 return WalkTypeChainInternal(aType
, PR_TRUE
, aBuiltinType
);
3208 nsXFormsModelElement::Startup()
3210 sModelPropsList
[eModel_type
] = nsXFormsAtoms::type
;
3211 sModelPropsList
[eModel_readonly
] = nsXFormsAtoms::readonly
;
3212 sModelPropsList
[eModel_required
] = nsXFormsAtoms::required
;
3213 sModelPropsList
[eModel_relevant
] = nsXFormsAtoms::relevant
;
3214 sModelPropsList
[eModel_calculate
] = nsXFormsAtoms::calculate
;
3215 sModelPropsList
[eModel_constraint
] = nsXFormsAtoms::constraint
;
3216 sModelPropsList
[eModel_p3ptype
] = nsXFormsAtoms::p3ptype
;
3219 already_AddRefed
<nsIDOMElement
>
3220 nsXFormsModelElement::GetDOMElement()
3222 nsIDOMElement
* element
= nsnull
;
3223 NS_IF_ADDREF(element
= mElement
);
3228 DeleteBindList(void *aObject
,
3229 nsIAtom
*aPropertyName
,
3230 void *aPropertyValue
,
3233 delete static_cast<nsCOMArray
<nsIXFormsControl
> *>(aPropertyValue
);
3236 /* static */ nsresult
3237 nsXFormsModelElement::DeferElementBind(nsIXFormsControl
*aControl
)
3239 NS_ENSURE_ARG_POINTER(aControl
);
3240 nsCOMPtr
<nsIDOMElement
> element
;
3241 nsresult rv
= aControl
->GetElement(getter_AddRefs(element
));
3242 NS_ENSURE_SUCCESS(rv
, rv
);
3244 nsCOMPtr
<nsIContent
> content(do_QueryInterface(element
));
3245 NS_ASSERTION(content
, "nsIDOMElement not implementing nsIContent?!");
3247 nsCOMPtr
<nsIDocument
> doc
= content
->GetCurrentDoc();
3249 // We do not care about elements without a document. If they get added to
3250 // a document at some point in time, they'll try to bind again.
3254 // We are using a PRBool on each control to mark whether the control is on the
3255 // deferredBindList. We are running into too many scenarios where a control
3256 // could be added more than once which will lead to inefficiencies because
3257 // calling bind and refresh on some controls is getting pretty expensive.
3258 // We need to keep the document order of the controls AND don't want
3259 // to walk the deferredBindList every time we want to check about adding a
3261 PRBool onList
= PR_FALSE
;
3262 aControl
->GetOnDeferredBindList(&onList
);
3267 nsCOMArray
<nsIXFormsControl
> *deferredBindList
=
3268 static_cast<nsCOMArray
<nsIXFormsControl
> *>
3269 (doc
->GetProperty(nsXFormsAtoms::deferredBindListProperty
));
3271 if (!deferredBindList
) {
3272 deferredBindList
= new nsCOMArray
<nsIXFormsControl
>(16);
3273 NS_ENSURE_TRUE(deferredBindList
, NS_ERROR_OUT_OF_MEMORY
);
3275 doc
->SetProperty(nsXFormsAtoms::deferredBindListProperty
, deferredBindList
,
3279 // always append to the end of the list. We need to keep the elements in
3280 // document order when we process the binds later. Otherwise we have trouble
3281 // when an element is trying to bind and should use its parent as a context
3282 // for the xpath evaluation but the parent isn't bound yet.
3283 deferredBindList
->AppendObject(aControl
);
3284 aControl
->SetOnDeferredBindList(PR_TRUE
);
3290 nsXFormsModelElement::ProcessDeferredBinds(nsIDOMDocument
*aDoc
)
3293 printf("nsXFormsModelElement::ProcessDeferredBinds()\n");
3296 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(aDoc
);
3302 nsPostRefresh postRefresh
= nsPostRefresh();
3304 doc
->SetProperty(nsXFormsAtoms::readyForBindProperty
, doc
);
3306 nsCOMArray
<nsIXFormsControl
> *deferredBindList
=
3307 static_cast<nsCOMArray
<nsIXFormsControl
> *>
3308 (doc
->GetProperty(nsXFormsAtoms::deferredBindListProperty
));
3310 if (deferredBindList
) {
3311 for (PRInt32 i
= 0; i
< deferredBindList
->Count(); ++i
) {
3312 nsIXFormsControl
*control
= deferredBindList
->ObjectAt(i
);
3314 control
->BindToModel(PR_FALSE
);
3315 control
->SetOnDeferredBindList(PR_FALSE
);
3319 doc
->DeleteProperty(nsXFormsAtoms::deferredBindListProperty
);
3324 nsXFormsModelElement::HandleLoad(nsIDOMEvent
* aEvent
)
3326 if (!mInstancesInitialized
) {
3327 // XXX This is for Bug 308106. In Gecko 1.8 DoneAddingChildren is not
3328 // called in XUL if the element doesn't have any child nodes.
3329 InitializeInstances();
3332 mDocumentLoaded
= PR_TRUE
;
3334 nsCOMPtr
<nsIDOMDocument
> document
;
3335 mElement
->GetOwnerDocument(getter_AddRefs(document
));
3336 NS_ENSURE_STATE(document
);
3337 nsXFormsUtils::DispatchDeferredEvents(document
);
3339 // dispatch xforms-model-construct, xforms-rebuild, xforms-recalculate,
3340 // xforms-revalidate
3342 // We wait until DOMContentLoaded to dispatch xforms-model-construct,
3343 // since the model may have an action handler for this event and Mozilla
3344 // doesn't register XML Event listeners until the document is loaded.
3346 // xforms-model-construct is not cancellable, so always proceed.
3348 nsXFormsUtils::DispatchEvent(mElement
, eEvent_ModelConstruct
);
3350 if (mPendingInlineSchemas
.Count() > 0) {
3351 nsCOMPtr
<nsIDOMElement
> el
;
3352 nsresult rv
= NS_OK
;
3353 for (PRInt32 i
=0; i
<mPendingInlineSchemas
.Count(); ++i
) {
3354 GetSchemaElementById(mElement
, *mPendingInlineSchemas
[i
],
3355 getter_AddRefs(el
));
3357 rv
= NS_ERROR_UNEXPECTED
;
3359 // According to section 3.3.1 of the spec, more than one schema per
3360 // namespace isn't allowed, but it also doesn't spell out very well
3361 // what this means a processor should do about it. Since most
3362 // processors ignore this rule and it isn't specifically a fatal error,
3363 // we won't make this a failure here.
3364 if (!IsDuplicateSchema(el
)) {
3365 nsCOMPtr
<nsISchema
> schema
;
3366 // no need to observe errors via the callback. instead, rely on
3367 // this method returning a failure code when it encounters errors.
3368 rv
= mSchemas
->ProcessSchemaElement(el
, nsnull
,
3369 getter_AddRefs(schema
));
3370 if (NS_SUCCEEDED(rv
))
3374 if (NS_FAILED(rv
)) {
3375 // this is a fatal error
3376 nsXFormsUtils::ReportError(NS_LITERAL_STRING("schemaLoadError"), mElement
);
3377 nsXFormsUtils::DispatchEvent(mElement
, eEvent_LinkException
);
3382 rv
= FinishConstruction();
3383 NS_ENSURE_SUCCESS(rv
, rv
);
3385 mPendingInlineSchemas
.Clear();
3388 // We may still be waiting on external documents to load.
3389 MaybeNotifyCompletion();
3395 nsXFormsModelElement::HandleUnload(nsIDOMEvent
* aEvent
)
3397 // due to fastback changes, had to move this notification out from under
3398 // model's WillChangeDocument override.
3399 nsXFormsUtils::DispatchEvent(mElement
, eEvent_ModelDestruct
);
3401 // Releasing references as early as possible, see bug 375320.
3404 if (mInstanceDocuments
)
3405 mInstanceDocuments
->DropReferences();
3407 mFormControls
.Clear();
3408 mControlListHash
.Clear();
3413 nsXFormsModelElement::IsDuplicateSchema(nsIDOMElement
*aSchemaElement
)
3415 nsCOMPtr
<nsISchemaCollection
> schemaColl
= do_QueryInterface(mSchemas
);
3419 const nsAFlatString
& empty
= EmptyString();
3420 nsAutoString targetNamespace
;
3421 aSchemaElement
->GetAttributeNS(empty
,
3422 NS_LITERAL_STRING("targetNamespace"),
3424 targetNamespace
.Trim(" \r\n\t");
3426 nsCOMPtr
<nsISchema
> schema
;
3427 schemaColl
->GetSchema(targetNamespace
, getter_AddRefs(schema
));
3431 // A schema with the same target namespace already exists in the
3432 // schema collection and the first instance has already been processed.
3433 // Report an error to the JS console and dispatch the LinkError event,
3434 // but do not consider it a fatal error.
3435 const nsPromiseFlatString
& flat
= PromiseFlatString(targetNamespace
);
3436 const PRUnichar
*strings
[] = { flat
.get() };
3437 nsXFormsUtils::ReportError(NS_LITERAL_STRING("duplicateSchema"),
3438 strings
, 1, aSchemaElement
, aSchemaElement
,
3440 nsXFormsUtils::DispatchEvent(mElement
, eEvent_LinkError
);
3445 NS_NewXFormsModelElement(nsIXTFElement
**aResult
)
3447 *aResult
= new nsXFormsModelElement();
3449 return NS_ERROR_OUT_OF_MEMORY
;
3451 NS_ADDREF(*aResult
);
3456 // ---------------------------- //
3458 // nsXFormsModelInstanceDocuments
3460 NS_IMPL_ISUPPORTS2(nsXFormsModelInstanceDocuments
, nsIDOMNodeList
, nsIClassInfo
)
3462 nsXFormsModelInstanceDocuments::nsXFormsModelInstanceDocuments()
3468 nsXFormsModelInstanceDocuments::GetLength(PRUint32
* aLength
)
3470 *aLength
= mInstanceList
.Count();
3476 nsXFormsModelInstanceDocuments::Item(PRUint32 aIndex
, nsIDOMNode
** aReturn
)
3479 nsIInstanceElementPrivate
* instance
= mInstanceList
.SafeObjectAt(aIndex
);
3481 nsCOMPtr
<nsIDOMDocument
> doc
;
3482 if (NS_SUCCEEDED(instance
->GetInstanceDocument(getter_AddRefs(doc
))) && doc
) {
3483 NS_ADDREF(*aReturn
= doc
);
3490 nsIInstanceElementPrivate
*
3491 nsXFormsModelInstanceDocuments::GetInstanceAt(PRUint32 aIndex
)
3493 return mInstanceList
.ObjectAt(aIndex
);
3497 nsXFormsModelInstanceDocuments::AddInstance(nsIInstanceElementPrivate
*aInst
)
3499 // always append to the end of the list. We need to keep the elements in
3500 // document order since the first instance element is the default instance
3501 // document for the model.
3502 mInstanceList
.AppendObject(aInst
);
3506 nsXFormsModelInstanceDocuments::RemoveInstance(nsIInstanceElementPrivate
*aInst
)
3508 mInstanceList
.RemoveObject(aInst
);
3512 nsXFormsModelInstanceDocuments::DropReferences()
3514 mInstanceList
.Clear();
3517 // nsIClassInfo implementation
3519 static const nsIID sInstScriptingIIDs
[] = {
3524 nsXFormsModelInstanceDocuments::GetInterfaces(PRUint32
*aCount
,
3528 nsXFormsUtils::CloneScriptingInterfaces(sInstScriptingIIDs
,
3529 NS_ARRAY_LENGTH(sInstScriptingIIDs
),
3534 nsXFormsModelInstanceDocuments::GetHelperForLanguage(PRUint32 language
,
3535 nsISupports
**_retval
)
3542 nsXFormsModelInstanceDocuments::GetContractID(char * *aContractID
)
3544 *aContractID
= nsnull
;
3549 nsXFormsModelInstanceDocuments::GetClassDescription(char * *aClassDescription
)
3551 *aClassDescription
= nsnull
;
3556 nsXFormsModelInstanceDocuments::GetClassID(nsCID
* *aClassID
)
3563 nsXFormsModelInstanceDocuments::GetImplementationLanguage(PRUint32
*aLang
)
3565 *aLang
= nsIProgrammingLanguage::CPLUSPLUS
;
3570 nsXFormsModelInstanceDocuments::GetFlags(PRUint32
*aFlags
)
3572 *aFlags
= nsIClassInfo::DOM_OBJECT
;
3577 nsXFormsModelInstanceDocuments::GetClassIDNoAlloc(nsCID
*aClassIDNoAlloc
)
3579 return NS_ERROR_NOT_AVAILABLE
;