michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsInstantiationNode.h" michael@0: #include "nsTemplateRule.h" michael@0: #include "nsXULTemplateQueryProcessorRDF.h" michael@0: michael@0: #include "prlog.h" michael@0: #ifdef PR_LOGGING michael@0: extern PRLogModuleInfo* gXULTemplateLog; michael@0: #endif michael@0: michael@0: nsInstantiationNode::nsInstantiationNode(nsXULTemplateQueryProcessorRDF* aProcessor, michael@0: nsRDFQuery* aQuery) michael@0: : mProcessor(aProcessor), michael@0: mQuery(aQuery) michael@0: { michael@0: #ifdef PR_LOGGING michael@0: PR_LOG(gXULTemplateLog, PR_LOG_DEBUG, michael@0: ("nsInstantiationNode[%p] query=%p", this, aQuery)); michael@0: #endif michael@0: michael@0: MOZ_COUNT_CTOR(nsInstantiationNode); michael@0: } michael@0: michael@0: michael@0: nsInstantiationNode::~nsInstantiationNode() michael@0: { michael@0: MOZ_COUNT_DTOR(nsInstantiationNode); michael@0: } michael@0: michael@0: nsresult michael@0: nsInstantiationNode::Propagate(InstantiationSet& aInstantiations, michael@0: bool aIsUpdate, bool& aTakenInstantiations) michael@0: { michael@0: // In update mode, iterate through the results and call the template michael@0: // builder to update them. In non-update mode, cache them in the processor michael@0: // to be used during processing. The results are cached in the processor michael@0: // so that the simple rules are only computed once. In this situation, all michael@0: // data for all queries are calculated at once. michael@0: nsresult rv = NS_OK; michael@0: michael@0: aTakenInstantiations = false; michael@0: michael@0: if (aIsUpdate) { michael@0: // Iterate through newly added keys to determine which rules fired. michael@0: // michael@0: // XXXwaterson Unfortunately, this could also lead to retractions; michael@0: // e.g., (container ?a ^empty false) could become "unmatched". How michael@0: // to track those? michael@0: nsCOMPtr querynode; michael@0: mQuery->GetQueryNode(getter_AddRefs(querynode)); michael@0: michael@0: InstantiationSet::ConstIterator last = aInstantiations.Last(); michael@0: for (InstantiationSet::ConstIterator inst = aInstantiations.First(); inst != last; ++inst) { michael@0: nsAssignmentSet assignments = inst->mAssignments; michael@0: michael@0: nsCOMPtr node; michael@0: assignments.GetAssignmentFor(mQuery->mMemberVariable, michael@0: getter_AddRefs(node)); michael@0: if (node) { michael@0: nsCOMPtr resource = do_QueryInterface(node); michael@0: if (resource) { michael@0: nsRefPtr nextresult = michael@0: new nsXULTemplateResultRDF(mQuery, *inst, resource); michael@0: if (! nextresult) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: rv = mProcessor->AddMemoryElements(*inst, nextresult); michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: michael@0: mProcessor->GetBuilder()->AddResult(nextresult, querynode); michael@0: } michael@0: } michael@0: } michael@0: } michael@0: else { michael@0: nsresult rv = mQuery->SetCachedResults(mProcessor, aInstantiations); michael@0: if (NS_SUCCEEDED(rv)) michael@0: aTakenInstantiations = true; michael@0: } michael@0: michael@0: return rv; michael@0: }