123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "nsIComponentManager.h"
- #include "nsIRDFContainer.h"
- #include "nsIRDFContainerUtils.h"
- #include "nsIServiceManager.h"
- #include "nsRDFCID.h"
- #include "nsRDFConInstanceTestNode.h"
- #include "nsResourceSet.h"
- #include "mozilla/Logging.h"
- #include "nsXULContentUtils.h"
- using mozilla::LogLevel;
- extern mozilla::LazyLogModule gXULTemplateLog;
- static const char*
- TestToString(nsRDFConInstanceTestNode::Test aTest) {
- switch (aTest) {
- case nsRDFConInstanceTestNode::eFalse: return "false";
- case nsRDFConInstanceTestNode::eTrue: return "true";
- case nsRDFConInstanceTestNode::eDontCare: return "dontcare";
- }
- return "?";
- }
- nsRDFConInstanceTestNode::nsRDFConInstanceTestNode(TestNode* aParent,
- nsXULTemplateQueryProcessorRDF* aProcessor,
- nsIAtom* aContainerVariable,
- Test aContainer,
- Test aEmpty)
- : nsRDFTestNode(aParent),
- mProcessor(aProcessor),
- mContainerVariable(aContainerVariable),
- mContainer(aContainer),
- mEmpty(aEmpty)
- {
- if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
- nsAutoCString props;
- nsResourceSet& containmentProps = aProcessor->ContainmentProperties();
- nsResourceSet::ConstIterator last = containmentProps.Last();
- nsResourceSet::ConstIterator first = containmentProps.First();
- nsResourceSet::ConstIterator iter;
- for (iter = first; iter != last; ++iter) {
- if (iter != first)
- props += " ";
- const char* str;
- iter->GetValueConst(&str);
- props += str;
- }
- nsAutoString cvar(NS_LITERAL_STRING("(none)"));
- if (mContainerVariable)
- mContainerVariable->ToString(cvar);
- MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
- ("nsRDFConInstanceTestNode[%p]: parent=%p member-props=(%s) container-var=%s container=%s empty=%s",
- this,
- aParent,
- props.get(),
- NS_ConvertUTF16toUTF8(cvar).get(),
- TestToString(aContainer),
- TestToString(aEmpty)));
- }
- }
- nsresult
- nsRDFConInstanceTestNode::FilterInstantiations(InstantiationSet& aInstantiations,
- bool* aCantHandleYet) const
- {
- nsresult rv;
- if (aCantHandleYet)
- *aCantHandleYet = false;
- nsCOMPtr<nsIRDFContainerUtils> rdfc
- = do_GetService("@mozilla.org/rdf/container-utils;1");
- if (! rdfc)
- return NS_ERROR_FAILURE;
- nsIRDFDataSource* ds = mProcessor->GetDataSource();
- InstantiationSet::Iterator last = aInstantiations.Last();
- for (InstantiationSet::Iterator inst = aInstantiations.First(); inst != last; ++inst) {
- nsCOMPtr<nsIRDFNode> value;
- if (! inst->mAssignments.GetAssignmentFor(mContainerVariable, getter_AddRefs(value))) {
- NS_ERROR("can't do unbounded container testing");
- return NS_ERROR_UNEXPECTED;
- }
- nsCOMPtr<nsIRDFResource> valueres = do_QueryInterface(value);
- if (! valueres) {
- aInstantiations.Erase(inst--);
- continue;
- }
- if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
- const char* container = "(unbound)";
- valueres->GetValueConst(&container);
- MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
- ("nsRDFConInstanceTestNode[%p]::FilterInstantiations() container=[%s]",
- this, container));
- }
- nsCOMPtr<nsIRDFContainer> rdfcontainer;
- bool isRDFContainer;
- rv = rdfc->IsContainer(ds, valueres, &isRDFContainer);
- if (NS_FAILED(rv)) return rv;
- if (mEmpty != eDontCare || mContainer != eDontCare) {
- Test empty = eDontCare;
- Test container = eDontCare;
- if (isRDFContainer) {
- // It's an RDF container. Use the container utilities
- // to deduce what's in it.
- container = eTrue;
- // XXX should cache the factory
- rdfcontainer = do_CreateInstance("@mozilla.org/rdf/container;1", &rv);
- if (NS_FAILED(rv)) return rv;
- rv = rdfcontainer->Init(ds, valueres);
- if (NS_FAILED(rv)) return rv;
- int32_t count;
- rv = rdfcontainer->GetCount(&count);
- if (NS_FAILED(rv)) return rv;
- empty = (count == 0) ? eTrue : eFalse;
- } else {
- empty = eTrue;
- container = eFalse;
- // First do the simple check of finding some outward
- // arcs; there should be only a few containment arcs, so this can
- // save us time from dealing with an iterator later on
- nsResourceSet& containmentProps = mProcessor->ContainmentProperties();
- for (nsResourceSet::ConstIterator property = containmentProps.First();
- property != containmentProps.Last();
- ++property) {
- nsCOMPtr<nsIRDFNode> target;
- rv = ds->GetTarget(valueres, *property, true, getter_AddRefs(target));
- if (NS_FAILED(rv)) return rv;
- if (target != nullptr) {
- // bingo. we found one.
- empty = eFalse;
- container = eTrue;
- break;
- }
- }
- // if we still don't think its a container, but we
- // want to know for sure whether it is or not, we need
- // to check ArcLabelsOut for potential container arcs.
- if (container == eFalse && mContainer != eDontCare) {
- nsCOMPtr<nsISimpleEnumerator> arcsout;
- rv = ds->ArcLabelsOut(valueres, getter_AddRefs(arcsout));
- if (NS_FAILED(rv)) return rv;
- while (1) {
- bool hasmore;
- rv = arcsout->HasMoreElements(&hasmore);
- if (NS_FAILED(rv)) return rv;
- if (! hasmore)
- break;
- nsCOMPtr<nsISupports> isupports;
- rv = arcsout->GetNext(getter_AddRefs(isupports));
- if (NS_FAILED(rv)) return rv;
- nsCOMPtr<nsIRDFResource> property = do_QueryInterface(isupports);
- NS_ASSERTION(property != nullptr, "not a property");
- if (! property)
- return NS_ERROR_UNEXPECTED;
- if (mProcessor->ContainmentProperties().Contains(property)) {
- container = eTrue;
- break;
- }
- }
- }
- }
- MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
- (" empty => %s",
- (empty == mEmpty) ? "consistent" : "inconsistent"));
- MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
- (" container => %s",
- (container == mContainer) ? "consistent" : "inconsistent"));
- if (((mEmpty == empty) && (mContainer == container)) ||
- ((mEmpty == eDontCare) && (mContainer == container)) ||
- ((mContainer == eDontCare) && (mEmpty == empty)))
- {
- Element* element =
- new nsRDFConInstanceTestNode::Element(valueres, container, empty);
- inst->AddSupportingElement(element);
- }
- else {
- aInstantiations.Erase(inst--);
- }
- }
- }
- return NS_OK;
- }
- bool
- nsRDFConInstanceTestNode::CanPropagate(nsIRDFResource* aSource,
- nsIRDFResource* aProperty,
- nsIRDFNode* aTarget,
- Instantiation& aInitialBindings) const
- {
- nsresult rv;
- bool canpropagate = false;
- nsCOMPtr<nsIRDFContainerUtils> rdfc
- = do_GetService("@mozilla.org/rdf/container-utils;1");
- if (! rdfc)
- return false;
- // We can certainly propagate ordinal properties
- rv = rdfc->IsOrdinalProperty(aProperty, &canpropagate);
- if (NS_FAILED(rv)) return false;
- if (! canpropagate) {
- canpropagate = mProcessor->ContainmentProperties().Contains(aProperty);
- }
- if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
- const char* source;
- aSource->GetValueConst(&source);
- const char* property;
- aProperty->GetValueConst(&property);
- nsAutoString target;
- nsXULContentUtils::GetTextForNode(aTarget, target);
- MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
- ("nsRDFConInstanceTestNode[%p]: CanPropagate([%s]==[%s]=>[%s]) => %s",
- this, source, property, NS_ConvertUTF16toUTF8(target).get(),
- canpropagate ? "true" : "false"));
- }
- if (canpropagate) {
- aInitialBindings.AddAssignment(mContainerVariable, aSource);
- return true;
- }
- return false;
- }
- void
- nsRDFConInstanceTestNode::Retract(nsIRDFResource* aSource,
- nsIRDFResource* aProperty,
- nsIRDFNode* aTarget) const
- {
- // XXXwaterson oof. complicated. figure this out.
- if (0) {
- mProcessor->RetractElement(Element(aSource, mContainer, mEmpty));
- }
- }
|