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: #ifndef nsRDFBinding_h__ michael@0: #define nsRDFBinding_h__ michael@0: michael@0: #include "nsAutoPtr.h" michael@0: #include "nsIAtom.h" michael@0: #include "nsIRDFResource.h" michael@0: #include "nsISupportsImpl.h" michael@0: michael@0: class nsXULTemplateResultRDF; michael@0: class nsBindingValues; michael@0: michael@0: /* michael@0: * Classes related to storing bindings for RDF handling. michael@0: */ michael@0: michael@0: /* michael@0: * a descriptors michael@0: */ michael@0: class RDFBinding { michael@0: michael@0: public: michael@0: michael@0: nsCOMPtr mSubjectVariable; michael@0: nsCOMPtr mPredicate; michael@0: nsCOMPtr mTargetVariable; michael@0: michael@0: // indicates whether a binding is dependant on the result from a michael@0: // previous binding michael@0: bool mHasDependency; michael@0: michael@0: RDFBinding* mNext; michael@0: michael@0: private: michael@0: michael@0: friend class RDFBindingSet; michael@0: michael@0: RDFBinding(nsIAtom* aSubjectVariable, michael@0: nsIRDFResource* aPredicate, michael@0: nsIAtom* aTargetVariable) michael@0: : mSubjectVariable(aSubjectVariable), michael@0: mPredicate(aPredicate), michael@0: mTargetVariable(aTargetVariable), michael@0: mHasDependency(false), michael@0: mNext(nullptr) michael@0: { michael@0: MOZ_COUNT_CTOR(RDFBinding); michael@0: } michael@0: michael@0: ~RDFBinding() michael@0: { michael@0: MOZ_COUNT_DTOR(RDFBinding); michael@0: } michael@0: }; michael@0: michael@0: /* michael@0: * a collection of descriptors. This object is refcounted by michael@0: * nsBindingValues objects and the query processor. michael@0: */ michael@0: class RDFBindingSet MOZ_FINAL michael@0: { michael@0: private: michael@0: // Private destructor, to discourage deletion outside of Release(): michael@0: ~RDFBindingSet(); michael@0: michael@0: // the number of bindings michael@0: int32_t mCount; michael@0: michael@0: // pointer to the first binding in a linked list michael@0: RDFBinding* mFirst; michael@0: michael@0: public: michael@0: michael@0: RDFBindingSet() michael@0: : mCount(0), michael@0: mFirst(nullptr) michael@0: { michael@0: MOZ_COUNT_CTOR(RDFBindingSet); michael@0: } michael@0: michael@0: NS_INLINE_DECL_REFCOUNTING(RDFBindingSet) michael@0: michael@0: int32_t Count() const { return mCount; } michael@0: michael@0: /* michael@0: * Add a binding (aRef -> aPredicate -> aVar) to the set michael@0: */ michael@0: nsresult michael@0: AddBinding(nsIAtom* aVar, nsIAtom* aRef, nsIRDFResource* aPredicate); michael@0: michael@0: /* michael@0: * Return true if the binding set contains a binding which would cause michael@0: * the result to need resynchronizing for an RDF triple. The member michael@0: * variable may be supplied as an optimization since bindings most michael@0: * commonly use the member variable as the subject. If aMemberVariable michael@0: * is set, aSubject must be the value of the member variable for the michael@0: * result. The supplied binding values aBindingValues must be values michael@0: * using this binding set (that is aBindingValues->GetBindingSet() == this) michael@0: * michael@0: * @param aSubject subject of the RDF triple michael@0: * @param aPredicate predicate of the RDF triple michael@0: * @param aTarget target of the RDF triple michael@0: * @param aMemberVariable member variable for the query for the binding michael@0: * @param aResult result to synchronize michael@0: * @param aBindingValues the values for the bindings for the result michael@0: */ michael@0: bool michael@0: SyncAssignments(nsIRDFResource* aSubject, michael@0: nsIRDFResource* aPredicate, michael@0: nsIRDFNode* aTarget, michael@0: nsIAtom* aMemberVariable, michael@0: nsXULTemplateResultRDF* aResult, michael@0: nsBindingValues& aBindingValues); michael@0: michael@0: /* michael@0: * The query processor maintains a map of subjects to an array of results. michael@0: * This is used such that when a new assertion is added to the RDF graph, michael@0: * the results associated with the subject of that triple may be checked michael@0: * to see if their bindings have changed. The AddDependencies method adds michael@0: * these subject dependencies to the map. michael@0: */ michael@0: void michael@0: AddDependencies(nsIRDFResource* aSubject, michael@0: nsXULTemplateResultRDF* aResult); michael@0: michael@0: /* michael@0: * Remove the results from the dependencies map when results are deleted. michael@0: */ michael@0: void michael@0: RemoveDependencies(nsIRDFResource* aSubject, michael@0: nsXULTemplateResultRDF* aResult); michael@0: michael@0: /* michael@0: * The nsBindingValues classes stores an array of values, one for each michael@0: * target symbol that could be set by the bindings in the set. michael@0: * LookupTargetIndex determines the index into the array for a given michael@0: * target symbol. michael@0: */ michael@0: int32_t michael@0: LookupTargetIndex(nsIAtom* aTargetVariable, RDFBinding** aBinding); michael@0: }; michael@0: michael@0: /* michael@0: * A set of values of bindings. This object is used once per result. michael@0: * This stores a reference to the binding set and an array of node values. michael@0: * Since the binding set is used once per query and the values are michael@0: * used once per result, we reduce size by only storing the value array's michael@0: * length in the binding set. This is possible since the array is always michael@0: * a fixed length for a particular binding set. michael@0: * michael@0: * XXX ndeakin We may want to revisit this later since it makes the code michael@0: * more complicated. michael@0: */ michael@0: class nsBindingValues michael@0: { michael@0: protected: michael@0: michael@0: // the binding set michael@0: nsRefPtr mBindings; michael@0: michael@0: /* michael@0: * A set of values for variable bindings. To look up a binding value, michael@0: * scan through the binding set in mBindings for the right target atom. michael@0: * Its index will correspond to the index in this array. The size of this michael@0: * array is determined by the RDFBindingSet's Count(). michael@0: */ michael@0: nsCOMPtr* mValues; michael@0: michael@0: public: michael@0: michael@0: nsBindingValues() michael@0: : mBindings(nullptr), michael@0: mValues(nullptr) michael@0: { michael@0: MOZ_COUNT_CTOR(nsBindingValues); michael@0: } michael@0: michael@0: ~nsBindingValues(); michael@0: michael@0: michael@0: /** michael@0: * Clear the binding set, to be called when the nsBindingValues is deleted michael@0: * or a new binding set is being set. michael@0: */ michael@0: void ClearBindingSet(); michael@0: michael@0: RDFBindingSet* GetBindingSet() { return mBindings; } michael@0: michael@0: /** michael@0: * Set the binding set to use. This needs to be called once a rule matches michael@0: * since it is then known which bindings will apply. michael@0: */ michael@0: nsresult SetBindingSet(RDFBindingSet* aBindings); michael@0: michael@0: nsCOMPtr* ValuesArray() { return mValues; } michael@0: michael@0: /* michael@0: * Retrieve the assignment for a particular variable michael@0: */ michael@0: void michael@0: GetAssignmentFor(nsXULTemplateResultRDF* aResult, michael@0: nsIAtom* aVar, michael@0: nsIRDFNode** aValue); michael@0: michael@0: /* michael@0: * Remove depenedencies the bindings have on particular resources michael@0: */ michael@0: void michael@0: RemoveDependencies(nsIRDFResource* aSubject, michael@0: nsXULTemplateResultRDF* aResult); michael@0: }; michael@0: michael@0: #endif // nsRDFBinding_h__