diff options
Diffstat (limited to 'dom/xul/templates/nsXULTemplateQueryProcessorRDF.h')
-rw-r--r-- | dom/xul/templates/nsXULTemplateQueryProcessorRDF.h | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/dom/xul/templates/nsXULTemplateQueryProcessorRDF.h b/dom/xul/templates/nsXULTemplateQueryProcessorRDF.h new file mode 100644 index 000000000..30ac34d23 --- /dev/null +++ b/dom/xul/templates/nsXULTemplateQueryProcessorRDF.h @@ -0,0 +1,349 @@ +/* -*- 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/. */ + + +#ifndef nsXULTemplateQueryProcessorRDF_h__ +#define nsXULTemplateQueryProcessorRDF_h__ + +#include "nsIRDFContainer.h" +#include "nsIRDFContainerUtils.h" +#include "nsIRDFDataSource.h" +#include "nsIRDFObserver.h" +#include "nsIRDFService.h" +#include "nsIXULTemplateBuilder.h" +#include "nsIXULTemplateQueryProcessor.h" +#include "nsCollationCID.h" + +#include "nsResourceSet.h" +#include "nsRuleNetwork.h" +#include "nsRDFQuery.h" +#include "nsRDFBinding.h" +#include "nsXULTemplateResultSetRDF.h" +#include "nsCOMArray.h" +#include "nsString.h" +#include "nsClassHashtable.h" +#include "nsRefPtrHashtable.h" +#include "nsCycleCollectionParticipant.h" +#include "mozilla/Attributes.h" + +#include "mozilla/Logging.h" +extern mozilla::LazyLogModule gXULTemplateLog; + +class nsIContent; +class nsXULTemplateResultRDF; + +/** + * An object that generates results from a query on an RDF graph + */ +class nsXULTemplateQueryProcessorRDF final : public nsIXULTemplateQueryProcessor, + public nsIRDFObserver +{ +public: + typedef nsTArray<RefPtr<nsXULTemplateResultRDF> > ResultArray; + + nsXULTemplateQueryProcessorRDF(); + + nsresult InitGlobals(); + + // nsISupports interface + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULTemplateQueryProcessorRDF, + nsIXULTemplateQueryProcessor) + + // nsIXULTemplateQueryProcessor interface + NS_DECL_NSIXULTEMPLATEQUERYPROCESSOR + + // nsIRDFObserver interface + NS_DECL_NSIRDFOBSERVER + + /* + * Propagate all changes through the rule network when an assertion is + * added to the graph, adding any new results. + */ + nsresult + Propagate(nsIRDFResource* aSource, + nsIRDFResource* aProperty, + nsIRDFNode* aTarget); + + /* + * Retract all changes through the rule network when an assertion is + * removed from the graph, removing any results that no longer match. + */ + nsresult + Retract(nsIRDFResource* aSource, + nsIRDFResource* aProperty, + nsIRDFNode* aTarget); + + /* + * Synchronize results when the graph changes, updating their bindings. + */ + nsresult + SynchronizeAll(nsIRDFResource* aSource, + nsIRDFResource* aProperty, + nsIRDFNode* aOldTarget, + nsIRDFNode* aNewTarget); + + /* + * Return true if a resource is a container + */ + nsresult + CheckContainer(nsIRDFResource* aTargetResource, + bool* aIsContainer); + + /* + * Check if a resource does not have any children + */ + nsresult + CheckEmpty(nsIRDFResource* aTargetResource, + bool* aIsEmpty); + + /** + * Check if a resource is a separator + */ + nsresult + CheckIsSeparator(nsIRDFResource* aResource, bool* aIsSeparator); + + /* + * Compute the containment properties which are additional arcs which + * indicate that a node is a container, in additional to the RDF container + * tests. The computed list is stored in mContainmentProperties + */ + nsresult + ComputeContainmentProperties(nsIDOMNode* aRootNode); + + /** + * Compile a query that uses the extended template syntax. The last + * compiled node of the query is returned as aLastNode. This node will + * have been added to mAllTests which owns the node. + */ + nsresult + CompileExtendedQuery(nsRDFQuery* aQuery, + nsIContent* aConditions, + TestNode** aLastNode); + + /** + * Compile a single query child and return the compiled node in aResult. + * This node will have been added to mAllTests which owns the node and + * set as a child of aParentNode. + */ + virtual nsresult + CompileQueryChild(nsIAtom* aTag, + nsRDFQuery* aQuery, + nsIContent* aConditions, + TestNode* aParentNode, + TestNode** aResult); + + /** + * Parse the value of a property test assertion for a condition or a simple + * rule based on the parseType attribute into the appropriate literal type. + */ + nsresult ParseLiteral(const nsString& aParseType, + const nsString& aValue, + nsIRDFNode** aResult); + + /** + * Compile a <triple> condition and return the compiled node in aResult. + * This node will have been added to mAllTests which owns the node and + * set as a child of aParentNode. + */ + nsresult + CompileTripleCondition(nsRDFQuery* aQuery, + nsIContent* aCondition, + TestNode* aParentNode, + TestNode** aResult); + + /** + * Compile a <member> condition and return the compiled node in aResult. + * This node will have been added to mAllTests which owns the node and + * set as a child of aParentNode. + */ + nsresult + CompileMemberCondition(nsRDFQuery* aQuery, + nsIContent* aCondition, + TestNode* aParentNode, + TestNode** aResult); + + /** + * Add the default rules shared by all simple queries. This creates + * the content start node followed by a member test. The member TestNode + * is returned in aChildNode. Both nodes will have been added to mAllTests + * which owns the nodes. + */ + nsresult + AddDefaultSimpleRules(nsRDFQuery* aQuery, + TestNode** aChildNode); + + /** + * Compile a query that's specified using the simple template + * syntax. Each TestNode is created in a chain, the last compiled node + * is returned as aLastNode. All nodes will have been added to mAllTests + * which owns the nodes. + */ + nsresult + CompileSimpleQuery(nsRDFQuery* aQuery, + nsIContent* aQueryElement, + TestNode** aLastNode); + + RDFBindingSet* + GetBindingsForRule(nsIDOMNode* aRule); + + /* + * Indicate that a result is dependant on a particular resource. When an + * assertion is added to or removed from the graph involving that + * resource, that result must be recalculated. + */ + void + AddBindingDependency(nsXULTemplateResultRDF* aResult, + nsIRDFResource* aResource); + + /** + * Remove a dependency a result has on a particular resource. + */ + void + RemoveBindingDependency(nsXULTemplateResultRDF* aResult, + nsIRDFResource* aResource); + + /** + * A memory element is a hash of an RDF triple. One exists for each triple + * that was involved in generating a result. This function adds this to a + * map, keyed by memory element, when the value is a list of results that + * depend on that memory element. When an RDF triple is removed from the + * datasource, RetractElement is called, and this map is examined to + * determine which results are no longer valid. + */ + nsresult + AddMemoryElements(const Instantiation& aInst, + nsXULTemplateResultRDF* aResult); + + /** + * Remove the memory elements associated with a result when the result is + * no longer being used. + */ + nsresult + RemoveMemoryElements(const Instantiation& aInst, + nsXULTemplateResultRDF* aResult); + + /** + * Remove the results associated with a memory element since the + * RDF triple the memory element is a hash of has been removed. + */ + void RetractElement(const MemoryElement& aMemoryElement); + + /** + * Return the index of a result's resource in its RDF container + */ + int32_t + GetContainerIndexOf(nsIXULTemplateResult* aResult); + + /** + * Given a result and a predicate to sort on, get the target value of + * the triple to use for sorting. The sort predicate is the predicate + * with '?sort=true' appended. + */ + nsresult + GetSortValue(nsIXULTemplateResult* aResult, + nsIRDFResource* aPredicate, + nsIRDFResource* aSortPredicate, + nsISupports** aResultNode); + + nsIRDFDataSource* GetDataSource() { return mDB; } + + nsIXULTemplateBuilder* GetBuilder() { return mBuilder; } + + nsResourceSet& ContainmentProperties() { return mContainmentProperties; } + + nsresult + Log(const char* aOperation, + nsIRDFResource* aSource, + nsIRDFResource* aProperty, + nsIRDFNode* aTarget); + +#define LOG(_op, _src, _prop, _targ) \ + Log(_op, _src, _prop, _targ) + +protected: + ~nsXULTemplateQueryProcessorRDF(); + + // We are an observer of the composite datasource. The cycle is + // broken when the document is destroyed. + nsCOMPtr<nsIRDFDataSource> mDB; + + // weak reference to the builder, cleared when the document is destroyed + nsIXULTemplateBuilder* mBuilder; + + // true if the query processor has been initialized + bool mQueryProcessorRDFInited; + + // true if results have been generated. Once set, bindings can no longer + // be added. If they were, the binding value arrays for results that have + // already been generated would be the wrong size + bool mGenerationStarted; + + // nesting level for RDF batch notifications + int32_t mUpdateBatchNest; + + // containment properties that are checked to determine if a resource is + // a container + nsResourceSet mContainmentProperties; + + // the end node of the default simple node hierarchy + TestNode* mSimpleRuleMemberTest; + + // the reference variable + nsCOMPtr<nsIAtom> mRefVariable; + + // the last ref that was calculated, used for simple rules + nsCOMPtr<nsIXULTemplateResult> mLastRef; + + /** + * A map between nsIRDFNodes that form the left-hand side (the subject) of + * a <binding> and an array of nsIXULTemplateResults. When a new assertion + * is added to the graph involving a particular rdf node, it is looked up + * in this binding map. If it exists, the corresponding results must then + * be synchronized. + */ + nsClassHashtable<nsISupportsHashKey, ResultArray> mBindingDependencies; + + /** + * A map between memory elements and an array of nsIXULTemplateResults. + * When a triple is unasserted from the graph, the corresponding results + * no longer match so they must be removed. + */ + nsClassHashtable<nsUint32HashKey, + nsCOMArray<nsXULTemplateResultRDF> > mMemoryElementToResultMap; + + // map of the rules to the bindings for those rules. + // XXXndeakin this might be better just as an array since there is usually + // ten or fewer rules + nsRefPtrHashtable<nsISupportsHashKey, RDFBindingSet> mRuleToBindingsMap; + + /** + * The queries + */ + nsTArray<nsCOMPtr<nsITemplateRDFQuery> > mQueries; + + /** + * All of the RDF tests in the rule network, which are checked when a new + * assertion is added to the graph. This is a subset of mAllTests, which + * also includes non-RDF tests. + */ + ReteNodeSet mRDFTests; + + /** + * All of the tests in the rule network, owned by this list + */ + ReteNodeSet mAllTests; + + // pseudo-constants + static nsrefcnt gRefCnt; + +public: + static nsIRDFService* gRDFService; + static nsIRDFContainerUtils* gRDFContainerUtils; + static nsIRDFResource* kNC_BookmarkSeparator; + static nsIRDFResource* kRDF_type; +}; + +#endif // nsXULTemplateQueryProcessorRDF_h__ |