зеркало из https://github.com/mozilla/gecko-dev.git
272 строки
7.4 KiB
C++
272 строки
7.4 KiB
C++
/* -*- 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 "nsXULTemplateQueryProcessorRDF.h"
|
|
#include "nsXULTemplateResultRDF.h"
|
|
#include "nsRDFBinding.h"
|
|
|
|
#ifdef DEBUG
|
|
#include "nsXULContentUtils.h"
|
|
#endif
|
|
|
|
RDFBindingSet::~RDFBindingSet()
|
|
{
|
|
while (mFirst) {
|
|
RDFBinding* doomed = mFirst;
|
|
mFirst = mFirst->mNext;
|
|
delete doomed;
|
|
}
|
|
|
|
MOZ_COUNT_DTOR(RDFBindingSet);
|
|
}
|
|
|
|
nsresult
|
|
RDFBindingSet::AddBinding(nsIAtom* aVar, nsIAtom* aRef, nsIRDFResource* aPredicate)
|
|
{
|
|
RDFBinding* newbinding = new RDFBinding(aRef, aPredicate, aVar);
|
|
if (! newbinding)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
if (mFirst) {
|
|
RDFBinding* binding = mFirst;
|
|
|
|
while (binding) {
|
|
// the binding is dependant on the calculation of a previous binding
|
|
if (binding->mSubjectVariable == aVar)
|
|
newbinding->mHasDependency = true;
|
|
|
|
// if the target variable is already used in a binding, ignore it
|
|
// since it won't be useful for anything
|
|
if (binding->mTargetVariable == aVar) {
|
|
delete newbinding;
|
|
return NS_OK;
|
|
}
|
|
|
|
// add the binding at the end of the list
|
|
if (! binding->mNext) {
|
|
binding->mNext = newbinding;
|
|
break;
|
|
}
|
|
|
|
binding = binding->mNext;
|
|
}
|
|
}
|
|
else {
|
|
mFirst = newbinding;
|
|
}
|
|
|
|
mCount++;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
bool
|
|
RDFBindingSet::SyncAssignments(nsIRDFResource* aSubject,
|
|
nsIRDFResource* aPredicate,
|
|
nsIRDFNode* aTarget,
|
|
nsIAtom* aMemberVariable,
|
|
nsXULTemplateResultRDF* aResult,
|
|
nsBindingValues& aBindingValues)
|
|
{
|
|
NS_ASSERTION(aBindingValues.GetBindingSet() == this,
|
|
"nsBindingValues not for this RDFBindingSet");
|
|
NS_PRECONDITION(aResult, "Must have result");
|
|
|
|
bool needSync = false;
|
|
nsCOMPtr<nsIRDFNode>* valuesArray = aBindingValues.ValuesArray();
|
|
if (!valuesArray)
|
|
return false;
|
|
|
|
RDFBinding* binding = mFirst;
|
|
int32_t count = 0;
|
|
|
|
// QI for proper comparisons just to be safe
|
|
nsCOMPtr<nsIRDFNode> subjectnode = do_QueryInterface(aSubject);
|
|
|
|
// iterate through the bindings looking for ones that would match the RDF
|
|
// nodes that were involved in a change
|
|
nsCOMPtr<nsIRDFNode> value;
|
|
while (binding) {
|
|
if (aPredicate == binding->mPredicate) {
|
|
// if the source of the binding is the member variable, optimize
|
|
if (binding->mSubjectVariable == aMemberVariable) {
|
|
valuesArray[count] = aTarget;
|
|
needSync = true;
|
|
}
|
|
else {
|
|
aResult->GetAssignment(binding->mSubjectVariable, getter_AddRefs(value));
|
|
if (value == subjectnode) {
|
|
valuesArray[count] = aTarget;
|
|
needSync = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
binding = binding->mNext;
|
|
count++;
|
|
}
|
|
|
|
return needSync;
|
|
}
|
|
|
|
void
|
|
RDFBindingSet::AddDependencies(nsIRDFResource* aSubject,
|
|
nsXULTemplateResultRDF* aResult)
|
|
{
|
|
NS_PRECONDITION(aResult, "Must have result");
|
|
|
|
// iterate through the bindings and add binding dependencies to the
|
|
// processor
|
|
|
|
nsXULTemplateQueryProcessorRDF* processor = aResult->GetProcessor();
|
|
if (! processor)
|
|
return;
|
|
|
|
nsCOMPtr<nsIRDFNode> value;
|
|
|
|
RDFBinding* binding = mFirst;
|
|
while (binding) {
|
|
aResult->GetAssignment(binding->mSubjectVariable, getter_AddRefs(value));
|
|
|
|
nsCOMPtr<nsIRDFResource> valueres = do_QueryInterface(value);
|
|
if (valueres)
|
|
processor->AddBindingDependency(aResult, valueres);
|
|
|
|
binding = binding->mNext;
|
|
}
|
|
}
|
|
|
|
void
|
|
RDFBindingSet::RemoveDependencies(nsIRDFResource* aSubject,
|
|
nsXULTemplateResultRDF* aResult)
|
|
{
|
|
NS_PRECONDITION(aResult, "Must have result");
|
|
|
|
// iterate through the bindings and remove binding dependencies from the
|
|
// processor
|
|
|
|
nsXULTemplateQueryProcessorRDF* processor = aResult->GetProcessor();
|
|
if (! processor)
|
|
return;
|
|
|
|
nsCOMPtr<nsIRDFNode> value;
|
|
|
|
RDFBinding* binding = mFirst;
|
|
while (binding) {
|
|
aResult->GetAssignment(binding->mSubjectVariable, getter_AddRefs(value));
|
|
|
|
nsCOMPtr<nsIRDFResource> valueres = do_QueryInterface(value);
|
|
if (valueres)
|
|
processor->RemoveBindingDependency(aResult, valueres);
|
|
|
|
binding = binding->mNext;
|
|
}
|
|
}
|
|
|
|
int32_t
|
|
RDFBindingSet::LookupTargetIndex(nsIAtom* aTargetVariable, RDFBinding** aBinding)
|
|
{
|
|
int32_t idx = 0;
|
|
RDFBinding* binding = mFirst;
|
|
|
|
while (binding) {
|
|
if (binding->mTargetVariable == aTargetVariable) {
|
|
*aBinding = binding;
|
|
return idx;
|
|
}
|
|
idx++;
|
|
binding = binding->mNext;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
nsBindingValues::~nsBindingValues()
|
|
{
|
|
ClearBindingSet();
|
|
MOZ_COUNT_DTOR(nsBindingValues);
|
|
}
|
|
|
|
void
|
|
nsBindingValues::ClearBindingSet()
|
|
{
|
|
if (mBindings && mValues) {
|
|
delete [] mValues;
|
|
mValues = nullptr;
|
|
}
|
|
|
|
mBindings = nullptr;
|
|
}
|
|
|
|
nsresult
|
|
nsBindingValues::SetBindingSet(RDFBindingSet* aBindings)
|
|
{
|
|
ClearBindingSet();
|
|
|
|
int32_t count = aBindings->Count();
|
|
if (count) {
|
|
mValues = new nsCOMPtr<nsIRDFNode>[count];
|
|
if (!mValues)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
mBindings = aBindings;
|
|
}
|
|
else {
|
|
mValues = nullptr;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsBindingValues::GetAssignmentFor(nsXULTemplateResultRDF* aResult,
|
|
nsIAtom* aVar,
|
|
nsIRDFNode** aValue)
|
|
{
|
|
*aValue = nullptr;
|
|
|
|
// assignments are calculated lazily when asked for. The only issue is
|
|
// when a binding has no value in the RDF graph, it will be checked again
|
|
// every time.
|
|
|
|
if (mBindings && mValues) {
|
|
RDFBinding* binding;
|
|
int32_t idx = mBindings->LookupTargetIndex(aVar, &binding);
|
|
if (idx >= 0) {
|
|
*aValue = mValues[idx];
|
|
if (*aValue) {
|
|
NS_ADDREF(*aValue);
|
|
}
|
|
else {
|
|
nsXULTemplateQueryProcessorRDF* processor = aResult->GetProcessor();
|
|
if (! processor)
|
|
return;
|
|
|
|
nsIRDFDataSource* ds = processor->GetDataSource();
|
|
if (! ds)
|
|
return;
|
|
|
|
nsCOMPtr<nsIRDFNode> subjectValue;
|
|
aResult->GetAssignment(binding->mSubjectVariable,
|
|
getter_AddRefs(subjectValue));
|
|
if (subjectValue) {
|
|
nsCOMPtr<nsIRDFResource> subject = do_QueryInterface(subjectValue);
|
|
ds->GetTarget(subject, binding->mPredicate, true, aValue);
|
|
if (*aValue)
|
|
mValues[idx] = *aValue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
nsBindingValues::RemoveDependencies(nsIRDFResource* aSubject,
|
|
nsXULTemplateResultRDF* aResult)
|
|
{
|
|
if (mBindings)
|
|
mBindings->RemoveDependencies(aSubject, aResult);
|
|
}
|