summaryrefslogtreecommitdiffstats
path: root/dom/xul/templates/nsXULTemplateQueryProcessorRDF.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/xul/templates/nsXULTemplateQueryProcessorRDF.h')
-rw-r--r--dom/xul/templates/nsXULTemplateQueryProcessorRDF.h349
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__