123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862 |
- /* -*- 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/. */
- /*
- A rule discrimination network implementation based on ideas from
- RETE and TREAT.
- RETE is described in Charles Forgy, "Rete: A Fast Algorithm for the
- Many Patterns/Many Objects Match Problem", Artificial Intelligence
- 19(1): pp. 17-37, 1982.
- TREAT is described in Daniel P. Miranker, "TREAT: A Better Match
- Algorithm for AI Production System Matching", AAAI 1987: pp. 42-47.
- --
- TO DO:
- . nsAssignmentSet::List objects are allocated by the gallon. We
- should make it so that these are always allocated from a pool,
- maybe owned by the nsRuleNetwork?
- */
- #ifndef nsRuleNetwork_h__
- #define nsRuleNetwork_h__
- #include "mozilla/Attributes.h"
- #include "nsCOMPtr.h"
- #include "nsCOMArray.h"
- #include "nsIAtom.h"
- #include "nsIDOMNode.h"
- #include "plhash.h"
- #include "PLDHashTable.h"
- #include "nsIRDFNode.h"
- class nsXULTemplateResultSetRDF;
- //----------------------------------------------------------------------
- /**
- * A memory element that supports an instantiation. A memory element holds a
- * set of nodes involved in an RDF test such as <member> or <triple> test. A
- * memory element is created when a specific test matches. The query processor
- * maintains a map between the memory elements and the results they eventually
- * matched. When an assertion is removed from the graph, this map is consulted
- * to determine which results will no longer match.
- */
- class MemoryElement {
- protected:
- MemoryElement() { MOZ_COUNT_CTOR(MemoryElement); }
- public:
- virtual ~MemoryElement() { MOZ_COUNT_DTOR(MemoryElement); }
- virtual const char* Type() const = 0;
- virtual PLHashNumber Hash() const = 0;
- virtual bool Equals(const MemoryElement& aElement) const = 0;
- bool operator==(const MemoryElement& aMemoryElement) const {
- return Equals(aMemoryElement);
- }
- bool operator!=(const MemoryElement& aMemoryElement) const {
- return !Equals(aMemoryElement);
- }
- };
- //----------------------------------------------------------------------
- /**
- * A collection of memory elements
- */
- class MemoryElementSet {
- public:
- class ConstIterator;
- friend class ConstIterator;
- protected:
- class List {
- public:
- List() { MOZ_COUNT_CTOR(MemoryElementSet::List); }
- protected:
- ~List() {
- MOZ_COUNT_DTOR(MemoryElementSet::List);
- delete mElement;
- NS_IF_RELEASE(mNext); }
- public:
- int32_t AddRef() { return ++mRefCnt; }
- int32_t Release() {
- int32_t refcnt = --mRefCnt;
- if (refcnt == 0) delete this;
- return refcnt; }
- MemoryElement* mElement;
- int32_t mRefCnt;
- List* mNext;
- };
- List* mElements;
- public:
- MemoryElementSet() : mElements(nullptr) {
- MOZ_COUNT_CTOR(MemoryElementSet); }
- MemoryElementSet(const MemoryElementSet& aSet) : mElements(aSet.mElements) {
- MOZ_COUNT_CTOR(MemoryElementSet);
- NS_IF_ADDREF(mElements); }
- MemoryElementSet& operator=(const MemoryElementSet& aSet) {
- NS_IF_RELEASE(mElements);
- mElements = aSet.mElements;
- NS_IF_ADDREF(mElements);
- return *this; }
-
- ~MemoryElementSet() {
- MOZ_COUNT_DTOR(MemoryElementSet);
- NS_IF_RELEASE(mElements); }
- public:
- class ConstIterator {
- public:
- explicit ConstIterator(List* aElementList) : mCurrent(aElementList) {
- NS_IF_ADDREF(mCurrent); }
- ConstIterator(const ConstIterator& aConstIterator)
- : mCurrent(aConstIterator.mCurrent) {
- NS_IF_ADDREF(mCurrent); }
- ConstIterator& operator=(const ConstIterator& aConstIterator) {
- NS_IF_RELEASE(mCurrent);
- mCurrent = aConstIterator.mCurrent;
- NS_IF_ADDREF(mCurrent);
- return *this; }
- ~ConstIterator() { NS_IF_RELEASE(mCurrent); }
- ConstIterator& operator++() {
- List* next = mCurrent->mNext;
- NS_RELEASE(mCurrent);
- mCurrent = next;
- NS_IF_ADDREF(mCurrent);
- return *this; }
- ConstIterator operator++(int) {
- ConstIterator result(*this);
- List* next = mCurrent->mNext;
- NS_RELEASE(mCurrent);
- mCurrent = next;
- NS_IF_ADDREF(mCurrent);
- return result; }
- const MemoryElement& operator*() const {
- return *mCurrent->mElement; }
- const MemoryElement* operator->() const {
- return mCurrent->mElement; }
- bool operator==(const ConstIterator& aConstIterator) const {
- return mCurrent == aConstIterator.mCurrent; }
- bool operator!=(const ConstIterator& aConstIterator) const {
- return mCurrent != aConstIterator.mCurrent; }
- protected:
- List* mCurrent;
- };
- ConstIterator First() const { return ConstIterator(mElements); }
- ConstIterator Last() const { return ConstIterator(nullptr); }
- // N.B. that the set assumes ownership of the element
- nsresult Add(MemoryElement* aElement);
- };
- //----------------------------------------------------------------------
- /**
- * An assignment of a value to a variable
- */
- class nsAssignment {
- public:
- const nsCOMPtr<nsIAtom> mVariable;
- nsCOMPtr<nsIRDFNode> mValue;
- nsAssignment(nsIAtom* aVariable, nsIRDFNode* aValue)
- : mVariable(aVariable),
- mValue(aValue)
- { MOZ_COUNT_CTOR(nsAssignment); }
- nsAssignment(const nsAssignment& aAssignment)
- : mVariable(aAssignment.mVariable),
- mValue(aAssignment.mValue)
- { MOZ_COUNT_CTOR(nsAssignment); }
- ~nsAssignment() { MOZ_COUNT_DTOR(nsAssignment); }
- bool operator==(const nsAssignment& aAssignment) const {
- return mVariable == aAssignment.mVariable && mValue == aAssignment.mValue; }
- bool operator!=(const nsAssignment& aAssignment) const {
- return mVariable != aAssignment.mVariable || mValue != aAssignment.mValue; }
- PLHashNumber Hash() const {
- // XXX I have no idea if this hashing function is good or not // XXX change this
- PLHashNumber temp = PLHashNumber(NS_PTR_TO_INT32(mValue.get())) >> 2; // strip alignment bits
- return (temp & 0xffff) | NS_PTR_TO_INT32(mVariable.get()); }
- };
- //----------------------------------------------------------------------
- /**
- * A collection of value-to-variable assignments that minimizes
- * copying by sharing subsets when possible.
- */
- class nsAssignmentSet {
- public:
- class ConstIterator;
- friend class ConstIterator;
- protected:
- class List {
- public:
- explicit List(const nsAssignment& aAssignment) : mAssignment(aAssignment) {
- MOZ_COUNT_CTOR(nsAssignmentSet::List); }
- protected:
- ~List() {
- MOZ_COUNT_DTOR(nsAssignmentSet::List);
- NS_IF_RELEASE(mNext); }
- public:
- int32_t AddRef() { return ++mRefCnt; }
- int32_t Release() {
- int32_t refcnt = --mRefCnt;
- if (refcnt == 0) delete this;
- return refcnt; }
- nsAssignment mAssignment;
- int32_t mRefCnt;
- List* mNext;
- };
- List* mAssignments;
- public:
- nsAssignmentSet()
- : mAssignments(nullptr)
- { MOZ_COUNT_CTOR(nsAssignmentSet); }
- nsAssignmentSet(const nsAssignmentSet& aSet)
- : mAssignments(aSet.mAssignments) {
- MOZ_COUNT_CTOR(nsAssignmentSet);
- NS_IF_ADDREF(mAssignments); }
- nsAssignmentSet& operator=(const nsAssignmentSet& aSet) {
- NS_IF_RELEASE(mAssignments);
- mAssignments = aSet.mAssignments;
- NS_IF_ADDREF(mAssignments);
- return *this; }
- ~nsAssignmentSet() {
- MOZ_COUNT_DTOR(nsAssignmentSet);
- NS_IF_RELEASE(mAssignments); }
- public:
- class ConstIterator {
- public:
- explicit ConstIterator(List* aAssignmentList) : mCurrent(aAssignmentList) {
- NS_IF_ADDREF(mCurrent); }
- ConstIterator(const ConstIterator& aConstIterator)
- : mCurrent(aConstIterator.mCurrent) {
- NS_IF_ADDREF(mCurrent); }
- ConstIterator& operator=(const ConstIterator& aConstIterator) {
- NS_IF_RELEASE(mCurrent);
- mCurrent = aConstIterator.mCurrent;
- NS_IF_ADDREF(mCurrent);
- return *this; }
- ~ConstIterator() { NS_IF_RELEASE(mCurrent); }
- ConstIterator& operator++() {
- List* next = mCurrent->mNext;
- NS_RELEASE(mCurrent);
- mCurrent = next;
- NS_IF_ADDREF(mCurrent);
- return *this; }
- ConstIterator operator++(int) {
- ConstIterator result(*this);
- List* next = mCurrent->mNext;
- NS_RELEASE(mCurrent);
- mCurrent = next;
- NS_IF_ADDREF(mCurrent);
- return result; }
- const nsAssignment& operator*() const {
- return mCurrent->mAssignment; }
- const nsAssignment* operator->() const {
- return &mCurrent->mAssignment; }
- bool operator==(const ConstIterator& aConstIterator) const {
- return mCurrent == aConstIterator.mCurrent; }
- bool operator!=(const ConstIterator& aConstIterator) const {
- return mCurrent != aConstIterator.mCurrent; }
- protected:
- List* mCurrent;
- };
- ConstIterator First() const { return ConstIterator(mAssignments); }
- ConstIterator Last() const { return ConstIterator(nullptr); }
- public:
- /**
- * Add an assignment to the set
- * @param aElement the assigment to add
- * @return NS_OK if all is well, NS_ERROR_OUT_OF_MEMORY if memory
- * could not be allocated for the addition.
- */
- nsresult Add(const nsAssignment& aElement);
- /**
- * Determine if the assignment set contains the specified variable
- * to value assignment.
- * @param aVariable the variable for which to lookup the binding
- * @param aValue the value to query
- * @return true if aVariable is bound to aValue; false otherwise.
- */
- bool HasAssignment(nsIAtom* aVariable, nsIRDFNode* aValue) const;
- /**
- * Determine if the assignment set contains the specified assignment
- * @param aAssignment the assignment to search for
- * @return true if the set contains the assignment, false otherwise.
- */
- bool HasAssignment(const nsAssignment& aAssignment) const {
- return HasAssignment(aAssignment.mVariable, aAssignment.mValue); }
- /**
- * Determine whether the assignment set has an assignment for the
- * specified variable.
- * @param aVariable the variable to query
- * @return true if the assignment set has an assignment for the variable,
- * false otherwise.
- */
- bool HasAssignmentFor(nsIAtom* aVariable) const;
- /**
- * Retrieve the assignment for the specified variable
- * @param aVariable the variable to query
- * @param aValue an out parameter that will receive the value assigned
- * to the variable, if any.
- * @return true if the variable has an assignment, false
- * if there was no assignment for the variable.
- */
- bool GetAssignmentFor(nsIAtom* aVariable, nsIRDFNode** aValue) const;
- /**
- * Count the number of assignments in the set
- * @return the number of assignments in the set
- */
- int32_t Count() const;
- /**
- * Determine if the set is empty
- * @return true if the assignment set is empty, false otherwise.
- */
- bool IsEmpty() const { return mAssignments == nullptr; }
- bool Equals(const nsAssignmentSet& aSet) const;
- bool operator==(const nsAssignmentSet& aSet) const { return Equals(aSet); }
- bool operator!=(const nsAssignmentSet& aSet) const { return !Equals(aSet); }
- };
- //----------------------------------------------------------------------
- /**
- * A collection of variable-to-value bindings, with the memory elements
- * that support those bindings. Essentially, an instantiation is the
- * collection of variables and values assigned to those variables for a single
- * result. For each RDF rule in the rule network, each instantiation is
- * examined and either extended with additional bindings specified by the RDF
- * rule, or removed if the rule doesn't apply (for instance if a node has no
- * children). When an instantiation gets to the last node of the rule network,
- * which is always an nsInstantiationNode, a result is created for it.
- *
- * An instantiation object is typically created by "extending" another
- * instantiation object. That is, using the copy constructor, and
- * adding bindings and support to the instantiation.
- */
- class Instantiation
- {
- public:
- /**
- * The variable-to-value bindings
- */
- nsAssignmentSet mAssignments;
- /**
- * The memory elements that support the bindings.
- */
- MemoryElementSet mSupport;
- Instantiation() { MOZ_COUNT_CTOR(Instantiation); }
- Instantiation(const Instantiation& aInstantiation)
- : mAssignments(aInstantiation.mAssignments),
- mSupport(aInstantiation.mSupport) {
- MOZ_COUNT_CTOR(Instantiation); }
- Instantiation& operator=(const Instantiation& aInstantiation) {
- mAssignments = aInstantiation.mAssignments;
- mSupport = aInstantiation.mSupport;
- return *this; }
- ~Instantiation() { MOZ_COUNT_DTOR(Instantiation); }
- /**
- * Add the specified variable-to-value assignment to the instantiation's
- * set of assignments.
- * @param aVariable the variable to which is being assigned
- * @param aValue the value that is being assigned
- * @return NS_OK if no errors, NS_ERROR_OUT_OF_MEMORY if there
- * is not enough memory to perform the operation
- */
- nsresult AddAssignment(nsIAtom* aVariable, nsIRDFNode* aValue) {
- mAssignments.Add(nsAssignment(aVariable, aValue));
- return NS_OK; }
- /**
- * Add a memory element to the set of memory elements that are
- * supporting the instantiation
- * @param aMemoryElement the memory element to add to the
- * instantiation's set of support
- * @return NS_OK if no errors occurred, NS_ERROR_OUT_OF_MEMORY
- * if there is not enough memory to perform the operation.
- */
- nsresult AddSupportingElement(MemoryElement* aMemoryElement) {
- mSupport.Add(aMemoryElement);
- return NS_OK; }
- bool Equals(const Instantiation& aInstantiation) const {
- return mAssignments == aInstantiation.mAssignments; }
- bool operator==(const Instantiation& aInstantiation) const {
- return Equals(aInstantiation); }
- bool operator!=(const Instantiation& aInstantiation) const {
- return !Equals(aInstantiation); }
- static PLHashNumber Hash(const void* aKey);
- static int Compare(const void* aLeft, const void* aRight);
- };
- //----------------------------------------------------------------------
- /**
- * A collection of intantiations
- */
- class InstantiationSet
- {
- public:
- InstantiationSet();
- InstantiationSet(const InstantiationSet& aInstantiationSet);
- InstantiationSet& operator=(const InstantiationSet& aInstantiationSet);
- ~InstantiationSet() {
- MOZ_COUNT_DTOR(InstantiationSet);
- Clear(); }
- class ConstIterator;
- friend class ConstIterator;
- class Iterator;
- friend class Iterator;
- friend class nsXULTemplateResultSetRDF; // so it can get to the List
- protected:
- class List {
- public:
- Instantiation mInstantiation;
- List* mNext;
- List* mPrev;
- List() { MOZ_COUNT_CTOR(InstantiationSet::List); }
- ~List() { MOZ_COUNT_DTOR(InstantiationSet::List); }
- };
- List mHead;
- public:
- class ConstIterator {
- protected:
- friend class Iterator; // XXXwaterson so broken.
- List* mCurrent;
- public:
- explicit ConstIterator(List* aList) : mCurrent(aList) {}
- ConstIterator(const ConstIterator& aConstIterator)
- : mCurrent(aConstIterator.mCurrent) {}
- ConstIterator& operator=(const ConstIterator& aConstIterator) {
- mCurrent = aConstIterator.mCurrent;
- return *this; }
- ConstIterator& operator++() {
- mCurrent = mCurrent->mNext;
- return *this; }
- ConstIterator operator++(int) {
- ConstIterator result(*this);
- mCurrent = mCurrent->mNext;
- return result; }
- ConstIterator& operator--() {
- mCurrent = mCurrent->mPrev;
- return *this; }
- ConstIterator operator--(int) {
- ConstIterator result(*this);
- mCurrent = mCurrent->mPrev;
- return result; }
- const Instantiation& operator*() const {
- return mCurrent->mInstantiation; }
- const Instantiation* operator->() const {
- return &mCurrent->mInstantiation; }
- bool operator==(const ConstIterator& aConstIterator) const {
- return mCurrent == aConstIterator.mCurrent; }
- bool operator!=(const ConstIterator& aConstIterator) const {
- return mCurrent != aConstIterator.mCurrent; }
- };
- ConstIterator First() const { return ConstIterator(mHead.mNext); }
- ConstIterator Last() const { return ConstIterator(const_cast<List*>(&mHead)); }
- class Iterator : public ConstIterator {
- public:
- explicit Iterator(List* aList) : ConstIterator(aList) {}
- Iterator& operator++() {
- mCurrent = mCurrent->mNext;
- return *this; }
- Iterator operator++(int) {
- Iterator result(*this);
- mCurrent = mCurrent->mNext;
- return result; }
- Iterator& operator--() {
- mCurrent = mCurrent->mPrev;
- return *this; }
- Iterator operator--(int) {
- Iterator result(*this);
- mCurrent = mCurrent->mPrev;
- return result; }
- Instantiation& operator*() const {
- return mCurrent->mInstantiation; }
- Instantiation* operator->() const {
- return &mCurrent->mInstantiation; }
- bool operator==(const ConstIterator& aConstIterator) const {
- return mCurrent == aConstIterator.mCurrent; }
- bool operator!=(const ConstIterator& aConstIterator) const {
- return mCurrent != aConstIterator.mCurrent; }
- friend class InstantiationSet;
- };
- Iterator First() { return Iterator(mHead.mNext); }
- Iterator Last() { return Iterator(&mHead); }
- bool Empty() const { return First() == Last(); }
- Iterator Append(const Instantiation& aInstantiation) {
- return Insert(Last(), aInstantiation); }
- Iterator Insert(Iterator aBefore, const Instantiation& aInstantiation);
- Iterator Erase(Iterator aElement);
- void Clear();
- bool HasAssignmentFor(nsIAtom* aVariable) const;
- };
- //----------------------------------------------------------------------
- /**
- * A abstract base class for all nodes in the rule network
- */
- class ReteNode
- {
- public:
- ReteNode() {}
- virtual ~ReteNode() {}
- /**
- * Propagate a set of instantiations "down" through the
- * network. Each instantiation is a partial set of
- * variable-to-value assignments, along with the memory elements
- * that support it.
- *
- * The node must evaluate each instantiation, and either 1)
- * extend it with additional assignments and memory-element
- * support, or 2) remove it from the set because it is
- * inconsistent with the constraints that this node applies.
- *
- * The node must then pass the resulting instantiation set along
- * to any of its children in the network. (In other words, the
- * node must recursively call Propagate() on its children. We
- * should fix this to make the algorithm interruptable.)
- *
- * See TestNode::Propagate for details about instantiation set ownership
- *
- * @param aInstantiations the set of instantiations to propagate
- * down through the network.
- * @param aIsUpdate true if updating, false for first generation
- * @param aTakenInstantiations true if the ownership over aInstantiations
- * has been taken from the caller. If false,
- * the caller owns it.
- * @return NS_OK if no errors occurred.
- */
- virtual nsresult Propagate(InstantiationSet& aInstantiations,
- bool aIsUpdate, bool& aTakenInstantiations) = 0;
- };
- //----------------------------------------------------------------------
- /**
- * A collection of nodes in the rule network
- */
- class ReteNodeSet
- {
- public:
- ReteNodeSet();
- ~ReteNodeSet();
- nsresult Add(ReteNode* aNode);
- nsresult Clear();
- class Iterator;
- class ConstIterator {
- public:
- explicit ConstIterator(ReteNode** aNode) : mCurrent(aNode) {}
- ConstIterator(const ConstIterator& aConstIterator)
- : mCurrent(aConstIterator.mCurrent) {}
- ConstIterator& operator=(const ConstIterator& aConstIterator) {
- mCurrent = aConstIterator.mCurrent;
- return *this; }
- ConstIterator& operator++() {
- ++mCurrent;
- return *this; }
- ConstIterator operator++(int) {
- ConstIterator result(*this);
- ++mCurrent;
- return result; }
- const ReteNode* operator*() const {
- return *mCurrent; }
- const ReteNode* operator->() const {
- return *mCurrent; }
- bool operator==(const ConstIterator& aConstIterator) const {
- return mCurrent == aConstIterator.mCurrent; }
- bool operator!=(const ConstIterator& aConstIterator) const {
- return mCurrent != aConstIterator.mCurrent; }
- protected:
- friend class Iterator; // XXXwaterson this is so wrong!
- ReteNode** mCurrent;
- };
- ConstIterator First() const { return ConstIterator(mNodes); }
- ConstIterator Last() const { return ConstIterator(mNodes + mCount); }
- class Iterator : public ConstIterator {
- public:
- explicit Iterator(ReteNode** aNode) : ConstIterator(aNode) {}
- Iterator& operator++() {
- ++mCurrent;
- return *this; }
- Iterator operator++(int) {
- Iterator result(*this);
- ++mCurrent;
- return result; }
- ReteNode* operator*() const {
- return *mCurrent; }
- ReteNode* operator->() const {
- return *mCurrent; }
- bool operator==(const ConstIterator& aConstIterator) const {
- return mCurrent == aConstIterator.mCurrent; }
- bool operator!=(const ConstIterator& aConstIterator) const {
- return mCurrent != aConstIterator.mCurrent; }
- };
- Iterator First() { return Iterator(mNodes); }
- Iterator Last() { return Iterator(mNodes + mCount); }
- int32_t Count() const { return mCount; }
- protected:
- ReteNode** mNodes;
- int32_t mCount;
- int32_t mCapacity;
- };
- //----------------------------------------------------------------------
- /**
- * A node that applies a test condition to a set of instantiations.
- *
- * This class provides implementations of Propagate() and Constrain()
- * in terms of one simple operation, FilterInstantiations(). A node
- * that is a "simple test node" in a rule network should derive from
- * this class, and need only implement FilterInstantiations().
- */
- class TestNode : public ReteNode
- {
- public:
- explicit TestNode(TestNode* aParent);
- /**
- * Retrieve the test node's parent
- * @return the test node's parent
- */
- TestNode* GetParent() const { return mParent; }
- /**
- * Calls FilterInstantiations() on the instantiation set, and if
- * the resulting set isn't empty, propagates the new set down to
- * each of the test node's children.
- *
- * Note that the caller of Propagate is responsible for deleting
- * aInstantiations if necessary as described below.
- *
- * Propagate may be called in update or non-update mode as indicated
- * by the aIsUpdate argument. Non-update mode is used when initially
- * generating results, whereas update mode is used when the datasource
- * changes and new results might be available.
- *
- * The last node in a chain of TestNodes is always an nsInstantiationNode.
- * In non-update mode, this nsInstantiationNode will cache the results
- * in the query using the SetCachedResults method. The query processor
- * takes these cached results and creates a nsXULTemplateResultSetRDF
- * which is the enumeration returned to the template builder. This
- * nsXULTemplateResultSetRDF owns the instantiations and they will be
- * deleted when the nsXULTemplateResultSetRDF goes away.
- *
- * In update mode, the nsInstantiationNode node will iterate over the
- * instantiations itself and callback to the builder to update any matches
- * and generated content. If no instantiations match, then the builder
- * will never be called.
- *
- * Thus, the difference between update and non-update modes is that in
- * update mode, the results and instantiations have been already handled
- * whereas in non-update mode they are expected to be returned in an
- * nsXULTemplateResultSetRDF for further processing by the builder.
- *
- * Regardless, aTakenInstantiations will be set to true if the
- * ownership over aInstantiations has been transferred to a result set.
- * If set to false, the caller is still responsible for aInstantiations.
- * aTakenInstantiations will be set properly even if an error occurs.
- */
- virtual nsresult Propagate(InstantiationSet& aInstantiations,
- bool aIsUpdate, bool& aTakenInstantiations) override;
- /**
- * This is called by a child node on its parent to allow the
- * parent's constraints to apply to the set of instantiations.
- *
- * A node must iterate through the set of instantiations, and for
- * each instantiation, either 1) extend the instantiation by
- * adding variable-to-value assignments and memory element support
- * for those assignments, or 2) remove the instantiation because
- * it is inconsistent.
- *
- * The node must then pass the resulting set of instantiations up
- * to its parent (by recursive call; we should make this iterative
- * & interruptable at some point.)
- *
- * @param aInstantiations the set of instantiations that must
- * be constrained
- * @return NS_OK if no errors occurred
- */
- virtual nsresult Constrain(InstantiationSet& aInstantiations);
- /**
- * Given a set of instantiations, filter out any that are
- * inconsistent with the test node's test, and append
- * variable-to-value assignments and memory element support for
- * those which do pass the test node's test.
- *
- * @param aInstantiations the set of instantiations to be
- * filtered
- * @param aCantHandleYet [out] true if the instantiations do not contain
- * enough information to constrain the data. May be null if this
- * isn't important to the caller.
- * @return NS_OK if no errors occurred.
- */
- virtual nsresult FilterInstantiations(InstantiationSet& aInstantiations,
- bool* aCantHandleYet) const = 0;
- //XXX probably better named "ApplyConstraints" or "Discrminiate" or something
- /**
- * Add another node as a child of this node.
- * @param aNode the node to add.
- * @return NS_OK if no errors occur.
- */
- nsresult AddChild(ReteNode* aNode) { return mKids.Add(aNode); }
- /**
- * Remove all the children of this node
- * @return NS_OK if no errors occur.
- */
- nsresult RemoveAllChildren() { return mKids.Clear(); }
- protected:
- TestNode* mParent;
- ReteNodeSet mKids;
- };
- #endif // nsRuleNetwork_h__
|