diff options
Diffstat (limited to 'dom/xul/templates/nsRDFPropertyTestNode.cpp')
-rw-r--r-- | dom/xul/templates/nsRDFPropertyTestNode.cpp | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/dom/xul/templates/nsRDFPropertyTestNode.cpp b/dom/xul/templates/nsRDFPropertyTestNode.cpp new file mode 100644 index 000000000..2fa08f2b8 --- /dev/null +++ b/dom/xul/templates/nsRDFPropertyTestNode.cpp @@ -0,0 +1,362 @@ +/* -*- 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 "nsRDFPropertyTestNode.h" +#include "nsString.h" +#include "nsXULContentUtils.h" + +#include "mozilla/Logging.h" + +using mozilla::LogLevel; + +extern mozilla::LazyLogModule gXULTemplateLog; +#include "nsIRDFLiteral.h" + +nsRDFPropertyTestNode::nsRDFPropertyTestNode(TestNode* aParent, + nsXULTemplateQueryProcessorRDF* aProcessor, + nsIAtom* aSourceVariable, + nsIRDFResource* aProperty, + nsIAtom* aTargetVariable) + : nsRDFTestNode(aParent), + mProcessor(aProcessor), + mSourceVariable(aSourceVariable), + mSource(nullptr), + mProperty(aProperty), + mTargetVariable(aTargetVariable), + mTarget(nullptr) +{ + if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) { + const char* prop = "(null)"; + if (aProperty) + aProperty->GetValueConst(&prop); + + nsAutoString svar(NS_LITERAL_STRING("(none)")); + if (mSourceVariable) + mSourceVariable->ToString(svar); + + nsAutoString tvar(NS_LITERAL_STRING("(none)")); + if (mTargetVariable) + mTargetVariable->ToString(tvar); + + MOZ_LOG(gXULTemplateLog, LogLevel::Debug, + ("nsRDFPropertyTestNode[%p]: parent=%p source=%s property=%s target=%s", + this, aParent, NS_ConvertUTF16toUTF8(svar).get(), prop, NS_ConvertUTF16toUTF8(tvar).get())); + } +} + + +nsRDFPropertyTestNode::nsRDFPropertyTestNode(TestNode* aParent, + nsXULTemplateQueryProcessorRDF* aProcessor, + nsIRDFResource* aSource, + nsIRDFResource* aProperty, + nsIAtom* aTargetVariable) + : nsRDFTestNode(aParent), + mProcessor(aProcessor), + mSourceVariable(nullptr), + mSource(aSource), + mProperty(aProperty), + mTargetVariable(aTargetVariable), + mTarget(nullptr) +{ + if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) { + const char* source = "(null)"; + if (aSource) + aSource->GetValueConst(&source); + + const char* prop = "(null)"; + if (aProperty) + aProperty->GetValueConst(&prop); + + nsAutoString tvar(NS_LITERAL_STRING("(none)")); + if (mTargetVariable) + mTargetVariable->ToString(tvar); + + MOZ_LOG(gXULTemplateLog, LogLevel::Debug, + ("nsRDFPropertyTestNode[%p]: parent=%p source=%s property=%s target=%s", + this, aParent, source, prop, NS_ConvertUTF16toUTF8(tvar).get())); + } +} + + +nsRDFPropertyTestNode::nsRDFPropertyTestNode(TestNode* aParent, + nsXULTemplateQueryProcessorRDF* aProcessor, + nsIAtom* aSourceVariable, + nsIRDFResource* aProperty, + nsIRDFNode* aTarget) + : nsRDFTestNode(aParent), + mProcessor(aProcessor), + mSourceVariable(aSourceVariable), + mSource(nullptr), + mProperty(aProperty), + mTargetVariable(nullptr), + mTarget(aTarget) +{ + if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) { + nsAutoString svar(NS_LITERAL_STRING("(none)")); + if (mSourceVariable) + mSourceVariable->ToString(svar); + + const char* prop = "(null)"; + if (aProperty) + aProperty->GetValueConst(&prop); + + nsAutoString target; + nsXULContentUtils::GetTextForNode(aTarget, target); + + MOZ_LOG(gXULTemplateLog, LogLevel::Debug, + ("nsRDFPropertyTestNode[%p]: parent=%p source=%s property=%s target=%s", + this, aParent, NS_ConvertUTF16toUTF8(svar).get(), prop, NS_ConvertUTF16toUTF8(target).get())); + } +} + + +nsresult +nsRDFPropertyTestNode::FilterInstantiations(InstantiationSet& aInstantiations, + bool* aCantHandleYet) const +{ + nsresult rv; + + if (aCantHandleYet) + *aCantHandleYet = false; + + nsIRDFDataSource* ds = mProcessor->GetDataSource(); + + InstantiationSet::Iterator last = aInstantiations.Last(); + for (InstantiationSet::Iterator inst = aInstantiations.First(); inst != last; ++inst) { + bool hasSourceBinding; + nsCOMPtr<nsIRDFResource> sourceRes; + + if (mSource) { + hasSourceBinding = true; + sourceRes = mSource; + } + else { + nsCOMPtr<nsIRDFNode> sourceValue; + hasSourceBinding = inst->mAssignments.GetAssignmentFor(mSourceVariable, + getter_AddRefs(sourceValue)); + sourceRes = do_QueryInterface(sourceValue); + } + + bool hasTargetBinding; + nsCOMPtr<nsIRDFNode> targetValue; + + if (mTarget) { + hasTargetBinding = true; + targetValue = mTarget; + } + else { + hasTargetBinding = inst->mAssignments.GetAssignmentFor(mTargetVariable, + getter_AddRefs(targetValue)); + } + + if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) { + const char* source = "(unbound)"; + if (hasSourceBinding) + sourceRes->GetValueConst(&source); + + nsAutoString target(NS_LITERAL_STRING("(unbound)")); + if (hasTargetBinding) + nsXULContentUtils::GetTextForNode(targetValue, target); + + MOZ_LOG(gXULTemplateLog, LogLevel::Debug, + ("nsRDFPropertyTestNode[%p]: FilterInstantiations() source=[%s] target=[%s]", + this, source, NS_ConvertUTF16toUTF8(target).get())); + } + + if (hasSourceBinding && hasTargetBinding) { + // it's a consistency check. see if we have a assignment that is consistent + bool hasAssertion; + rv = ds->HasAssertion(sourceRes, mProperty, targetValue, + true, &hasAssertion); + if (NS_FAILED(rv)) return rv; + + MOZ_LOG(gXULTemplateLog, LogLevel::Debug, + (" consistency check => %s", hasAssertion ? "passed" : "failed")); + + if (hasAssertion) { + // it's consistent. + Element* element = + new nsRDFPropertyTestNode::Element(sourceRes, mProperty, + targetValue); + inst->AddSupportingElement(element); + } + else { + // it's inconsistent. remove it. + aInstantiations.Erase(inst--); + } + } + else if ((hasSourceBinding && ! hasTargetBinding) || + (! hasSourceBinding && hasTargetBinding)) { + // it's an open ended query on the source or + // target. figure out what matches and add as a + // cross-product. + nsCOMPtr<nsISimpleEnumerator> results; + if (hasSourceBinding) { + rv = ds->GetTargets(sourceRes, + mProperty, + true, + getter_AddRefs(results)); + } + else { + rv = ds->GetSources(mProperty, + targetValue, + true, + getter_AddRefs(results)); + if (NS_FAILED(rv)) return rv; + } + + while (1) { + bool hasMore; + rv = results->HasMoreElements(&hasMore); + if (NS_FAILED(rv)) return rv; + + if (! hasMore) + break; + + nsCOMPtr<nsISupports> isupports; + rv = results->GetNext(getter_AddRefs(isupports)); + if (NS_FAILED(rv)) return rv; + + nsIAtom* variable; + nsCOMPtr<nsIRDFNode> value; + + if (hasSourceBinding) { + variable = mTargetVariable; + + value = do_QueryInterface(isupports); + NS_ASSERTION(value != nullptr, "target is not an nsIRDFNode"); + + if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) { + nsAutoString s(NS_LITERAL_STRING("(none found)")); + if (value) + nsXULContentUtils::GetTextForNode(value, s); + + MOZ_LOG(gXULTemplateLog, LogLevel::Debug, + (" target => %s", NS_ConvertUTF16toUTF8(s).get())); + } + + if (! value) continue; + + targetValue = value; + } + else { + variable = mSourceVariable; + + nsCOMPtr<nsIRDFResource> source = do_QueryInterface(isupports); + NS_ASSERTION(source != nullptr, "source is not an nsIRDFResource"); + + if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) { + const char* s = "(none found)"; + if (source) + source->GetValueConst(&s); + + MOZ_LOG(gXULTemplateLog, LogLevel::Debug, + (" source => %s", s)); + } + + if (! source) continue; + + value = sourceRes = source; + } + + // Copy the original instantiation, and add it to the + // instantiation set with the new assignment that we've + // introduced. Ownership will be transferred to the + Instantiation newinst = *inst; + newinst.AddAssignment(variable, value); + + Element* element = + new nsRDFPropertyTestNode::Element(sourceRes, mProperty, + targetValue); + newinst.AddSupportingElement(element); + + aInstantiations.Insert(inst, newinst); + } + + // finally, remove the "under specified" instantiation. + aInstantiations.Erase(inst--); + } + else { + if (!aCantHandleYet) { + nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_TRIPLE_UNBOUND); + // Neither source nor target assignment! + return NS_ERROR_UNEXPECTED; + } + + *aCantHandleYet = true; + return NS_OK; + } + } + + return NS_OK; +} + +bool +nsRDFPropertyTestNode::CanPropagate(nsIRDFResource* aSource, + nsIRDFResource* aProperty, + nsIRDFNode* aTarget, + Instantiation& aInitialBindings) const +{ + bool result; + + if ((mProperty.get() != aProperty) || + (mSource && mSource.get() != aSource) || + (mTarget && mTarget.get() != aTarget)) { + result = false; + } + else { + if (mSourceVariable) + aInitialBindings.AddAssignment(mSourceVariable, aSource); + + if (mTargetVariable) + aInitialBindings.AddAssignment(mTargetVariable, aTarget); + + result = true; + } + + 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, + ("nsRDFPropertyTestNode[%p]: CanPropagate([%s]==[%s]=>[%s]) => %s", + this, source, property, NS_ConvertUTF16toUTF8(target).get(), + result ? "true" : "false")); + } + + return result; +} + +void +nsRDFPropertyTestNode::Retract(nsIRDFResource* aSource, + nsIRDFResource* aProperty, + nsIRDFNode* aTarget) const +{ + if (aProperty == mProperty.get()) { + 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, + ("nsRDFPropertyTestNode[%p]: Retract([%s]==[%s]=>[%s])", + this, source, property, NS_ConvertUTF16toUTF8(target).get())); + } + + mProcessor->RetractElement(Element(aSource, aProperty, aTarget)); + } +} + |