1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,357 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 + 1.10 +#ifndef nsXULTemplateQueryProcessorRDF_h__ 1.11 +#define nsXULTemplateQueryProcessorRDF_h__ 1.12 + 1.13 +#include "nsIRDFContainer.h" 1.14 +#include "nsIRDFContainerUtils.h" 1.15 +#include "nsIRDFDataSource.h" 1.16 +#include "nsIRDFObserver.h" 1.17 +#include "nsIRDFService.h" 1.18 +#include "nsIXULTemplateBuilder.h" 1.19 +#include "nsIXULTemplateQueryProcessor.h" 1.20 +#include "nsCollationCID.h" 1.21 + 1.22 +#include "nsResourceSet.h" 1.23 +#include "nsRuleNetwork.h" 1.24 +#include "nsRDFQuery.h" 1.25 +#include "nsRDFBinding.h" 1.26 +#include "nsXULTemplateResultSetRDF.h" 1.27 +#include "nsCOMArray.h" 1.28 +#include "nsString.h" 1.29 +#include "nsClassHashtable.h" 1.30 +#include "nsRefPtrHashtable.h" 1.31 +#include "nsCycleCollectionParticipant.h" 1.32 +#include "mozilla/Attributes.h" 1.33 + 1.34 +#include "prlog.h" 1.35 +#ifdef PR_LOGGING 1.36 +extern PRLogModuleInfo* gXULTemplateLog; 1.37 +#endif 1.38 + 1.39 +class nsIContent; 1.40 +class nsIRDFCompositeDataSource; 1.41 +class nsXULTemplateResultRDF; 1.42 + 1.43 +/** 1.44 + * An object that generates results from a query on an RDF graph 1.45 + */ 1.46 +class nsXULTemplateQueryProcessorRDF MOZ_FINAL : public nsIXULTemplateQueryProcessor, 1.47 + public nsIRDFObserver 1.48 +{ 1.49 +public: 1.50 + typedef nsTArray<nsRefPtr<nsXULTemplateResultRDF> > ResultArray; 1.51 + 1.52 + nsXULTemplateQueryProcessorRDF(); 1.53 + 1.54 + ~nsXULTemplateQueryProcessorRDF(); 1.55 + 1.56 + nsresult InitGlobals(); 1.57 + 1.58 + // nsISupports interface 1.59 + NS_DECL_CYCLE_COLLECTING_ISUPPORTS 1.60 + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULTemplateQueryProcessorRDF, 1.61 + nsIXULTemplateQueryProcessor) 1.62 + 1.63 + // nsIXULTemplateQueryProcessor interface 1.64 + NS_DECL_NSIXULTEMPLATEQUERYPROCESSOR 1.65 + 1.66 + // nsIRDFObserver interface 1.67 + NS_DECL_NSIRDFOBSERVER 1.68 + 1.69 + /* 1.70 + * Propagate all changes through the rule network when an assertion is 1.71 + * added to the graph, adding any new results. 1.72 + */ 1.73 + nsresult 1.74 + Propagate(nsIRDFResource* aSource, 1.75 + nsIRDFResource* aProperty, 1.76 + nsIRDFNode* aTarget); 1.77 + 1.78 + /* 1.79 + * Retract all changes through the rule network when an assertion is 1.80 + * removed from the graph, removing any results that no longer match. 1.81 + */ 1.82 + nsresult 1.83 + Retract(nsIRDFResource* aSource, 1.84 + nsIRDFResource* aProperty, 1.85 + nsIRDFNode* aTarget); 1.86 + 1.87 + /* 1.88 + * Synchronize results when the graph changes, updating their bindings. 1.89 + */ 1.90 + nsresult 1.91 + SynchronizeAll(nsIRDFResource* aSource, 1.92 + nsIRDFResource* aProperty, 1.93 + nsIRDFNode* aOldTarget, 1.94 + nsIRDFNode* aNewTarget); 1.95 + 1.96 + /* 1.97 + * Return true if a resource is a container 1.98 + */ 1.99 + nsresult 1.100 + CheckContainer(nsIRDFResource* aTargetResource, 1.101 + bool* aIsContainer); 1.102 + 1.103 + /* 1.104 + * Check if a resource does not have any children 1.105 + */ 1.106 + nsresult 1.107 + CheckEmpty(nsIRDFResource* aTargetResource, 1.108 + bool* aIsEmpty); 1.109 + 1.110 + /** 1.111 + * Check if a resource is a separator 1.112 + */ 1.113 + nsresult 1.114 + CheckIsSeparator(nsIRDFResource* aResource, bool* aIsSeparator); 1.115 + 1.116 + /* 1.117 + * Compute the containment properties which are additional arcs which 1.118 + * indicate that a node is a container, in additional to the RDF container 1.119 + * tests. The computed list is stored in mContainmentProperties 1.120 + */ 1.121 + nsresult 1.122 + ComputeContainmentProperties(nsIDOMNode* aRootNode); 1.123 + 1.124 + /** 1.125 + * Compile a query that uses the extended template syntax. The last 1.126 + * compiled node of the query is returned as aLastNode. This node will 1.127 + * have been added to mAllTests which owns the node. 1.128 + */ 1.129 + nsresult 1.130 + CompileExtendedQuery(nsRDFQuery* aQuery, 1.131 + nsIContent* aConditions, 1.132 + TestNode** aLastNode); 1.133 + 1.134 + /** 1.135 + * Compile a single query child and return the compiled node in aResult. 1.136 + * This node will have been added to mAllTests which owns the node and 1.137 + * set as a child of aParentNode. 1.138 + */ 1.139 + virtual nsresult 1.140 + CompileQueryChild(nsIAtom* aTag, 1.141 + nsRDFQuery* aQuery, 1.142 + nsIContent* aConditions, 1.143 + TestNode* aParentNode, 1.144 + TestNode** aResult); 1.145 + 1.146 + /** 1.147 + * Parse the value of a property test assertion for a condition or a simple 1.148 + * rule based on the parseType attribute into the appropriate literal type. 1.149 + */ 1.150 + nsresult ParseLiteral(const nsString& aParseType, 1.151 + const nsString& aValue, 1.152 + nsIRDFNode** aResult); 1.153 + 1.154 + /** 1.155 + * Compile a <triple> condition and return the compiled node in aResult. 1.156 + * This node will have been added to mAllTests which owns the node and 1.157 + * set as a child of aParentNode. 1.158 + */ 1.159 + nsresult 1.160 + CompileTripleCondition(nsRDFQuery* aQuery, 1.161 + nsIContent* aCondition, 1.162 + TestNode* aParentNode, 1.163 + TestNode** aResult); 1.164 + 1.165 + /** 1.166 + * Compile a <member> condition and return the compiled node in aResult. 1.167 + * This node will have been added to mAllTests which owns the node and 1.168 + * set as a child of aParentNode. 1.169 + */ 1.170 + nsresult 1.171 + CompileMemberCondition(nsRDFQuery* aQuery, 1.172 + nsIContent* aCondition, 1.173 + TestNode* aParentNode, 1.174 + TestNode** aResult); 1.175 + 1.176 + /** 1.177 + * Add the default rules shared by all simple queries. This creates 1.178 + * the content start node followed by a member test. The member TestNode 1.179 + * is returned in aChildNode. Both nodes will have been added to mAllTests 1.180 + * which owns the nodes. 1.181 + */ 1.182 + nsresult 1.183 + AddDefaultSimpleRules(nsRDFQuery* aQuery, 1.184 + TestNode** aChildNode); 1.185 + 1.186 + /** 1.187 + * Compile a query that's specified using the simple template 1.188 + * syntax. Each TestNode is created in a chain, the last compiled node 1.189 + * is returned as aLastNode. All nodes will have been added to mAllTests 1.190 + * which owns the nodes. 1.191 + */ 1.192 + nsresult 1.193 + CompileSimpleQuery(nsRDFQuery* aQuery, 1.194 + nsIContent* aQueryElement, 1.195 + TestNode** aLastNode); 1.196 + 1.197 + RDFBindingSet* 1.198 + GetBindingsForRule(nsIDOMNode* aRule); 1.199 + 1.200 + /* 1.201 + * Indicate that a result is dependant on a particular resource. When an 1.202 + * assertion is added to or removed from the graph involving that 1.203 + * resource, that result must be recalculated. 1.204 + */ 1.205 + void 1.206 + AddBindingDependency(nsXULTemplateResultRDF* aResult, 1.207 + nsIRDFResource* aResource); 1.208 + 1.209 + /** 1.210 + * Remove a dependency a result has on a particular resource. 1.211 + */ 1.212 + void 1.213 + RemoveBindingDependency(nsXULTemplateResultRDF* aResult, 1.214 + nsIRDFResource* aResource); 1.215 + 1.216 + /** 1.217 + * A memory element is a hash of an RDF triple. One exists for each triple 1.218 + * that was involved in generating a result. This function adds this to a 1.219 + * map, keyed by memory element, when the value is a list of results that 1.220 + * depend on that memory element. When an RDF triple is removed from the 1.221 + * datasource, RetractElement is called, and this map is examined to 1.222 + * determine which results are no longer valid. 1.223 + */ 1.224 + nsresult 1.225 + AddMemoryElements(const Instantiation& aInst, 1.226 + nsXULTemplateResultRDF* aResult); 1.227 + 1.228 + /** 1.229 + * Remove the memory elements associated with a result when the result is 1.230 + * no longer being used. 1.231 + */ 1.232 + nsresult 1.233 + RemoveMemoryElements(const Instantiation& aInst, 1.234 + nsXULTemplateResultRDF* aResult); 1.235 + 1.236 + /** 1.237 + * Remove the results associated with a memory element since the 1.238 + * RDF triple the memory element is a hash of has been removed. 1.239 + */ 1.240 + void RetractElement(const MemoryElement& aMemoryElement); 1.241 + 1.242 + /** 1.243 + * Return the index of a result's resource in its RDF container 1.244 + */ 1.245 + int32_t 1.246 + GetContainerIndexOf(nsIXULTemplateResult* aResult); 1.247 + 1.248 + /** 1.249 + * Given a result and a predicate to sort on, get the target value of 1.250 + * the triple to use for sorting. The sort predicate is the predicate 1.251 + * with '?sort=true' appended. 1.252 + */ 1.253 + nsresult 1.254 + GetSortValue(nsIXULTemplateResult* aResult, 1.255 + nsIRDFResource* aPredicate, 1.256 + nsIRDFResource* aSortPredicate, 1.257 + nsISupports** aResultNode); 1.258 + 1.259 + nsIRDFDataSource* GetDataSource() { return mDB; } 1.260 + 1.261 + nsIXULTemplateBuilder* GetBuilder() { return mBuilder; } 1.262 + 1.263 + nsResourceSet& ContainmentProperties() { return mContainmentProperties; } 1.264 + 1.265 +#ifdef PR_LOGGING 1.266 + nsresult 1.267 + Log(const char* aOperation, 1.268 + nsIRDFResource* aSource, 1.269 + nsIRDFResource* aProperty, 1.270 + nsIRDFNode* aTarget); 1.271 + 1.272 +#define LOG(_op, _src, _prop, _targ) \ 1.273 + Log(_op, _src, _prop, _targ) 1.274 + 1.275 +#else 1.276 +#define LOG(_op, _src, _prop, _targ) 1.277 +#endif 1.278 + 1.279 +protected: 1.280 + // We are an observer of the composite datasource. The cycle is 1.281 + // broken when the document is destroyed. 1.282 + nsCOMPtr<nsIRDFDataSource> mDB; 1.283 + 1.284 + // weak reference to the builder, cleared when the document is destroyed 1.285 + nsIXULTemplateBuilder* mBuilder; 1.286 + 1.287 + // true if the query processor has been initialized 1.288 + bool mQueryProcessorRDFInited; 1.289 + 1.290 + // true if results have been generated. Once set, bindings can no longer 1.291 + // be added. If they were, the binding value arrays for results that have 1.292 + // already been generated would be the wrong size 1.293 + bool mGenerationStarted; 1.294 + 1.295 + // nesting level for RDF batch notifications 1.296 + int32_t mUpdateBatchNest; 1.297 + 1.298 + // containment properties that are checked to determine if a resource is 1.299 + // a container 1.300 + nsResourceSet mContainmentProperties; 1.301 + 1.302 + // the end node of the default simple node hierarchy 1.303 + TestNode* mSimpleRuleMemberTest; 1.304 + 1.305 + // the reference variable 1.306 + nsCOMPtr<nsIAtom> mRefVariable; 1.307 + 1.308 + // the last ref that was calculated, used for simple rules 1.309 + nsCOMPtr<nsIXULTemplateResult> mLastRef; 1.310 + 1.311 + /** 1.312 + * A map between nsIRDFNodes that form the left-hand side (the subject) of 1.313 + * a <binding> and an array of nsIXULTemplateResults. When a new assertion 1.314 + * is added to the graph involving a particular rdf node, it is looked up 1.315 + * in this binding map. If it exists, the corresponding results must then 1.316 + * be synchronized. 1.317 + */ 1.318 + nsClassHashtable<nsISupportsHashKey, ResultArray> mBindingDependencies; 1.319 + 1.320 + /** 1.321 + * A map between memory elements and an array of nsIXULTemplateResults. 1.322 + * When a triple is unasserted from the graph, the corresponding results 1.323 + * no longer match so they must be removed. 1.324 + */ 1.325 + nsClassHashtable<nsUint32HashKey, 1.326 + nsCOMArray<nsXULTemplateResultRDF> > mMemoryElementToResultMap; 1.327 + 1.328 + // map of the rules to the bindings for those rules. 1.329 + // XXXndeakin this might be better just as an array since there is usually 1.330 + // ten or fewer rules 1.331 + nsRefPtrHashtable<nsISupportsHashKey, RDFBindingSet> mRuleToBindingsMap; 1.332 + 1.333 + /** 1.334 + * The queries 1.335 + */ 1.336 + nsTArray<nsCOMPtr<nsITemplateRDFQuery> > mQueries; 1.337 + 1.338 + /** 1.339 + * All of the RDF tests in the rule network, which are checked when a new 1.340 + * assertion is added to the graph. This is a subset of mAllTests, which 1.341 + * also includes non-RDF tests. 1.342 + */ 1.343 + ReteNodeSet mRDFTests; 1.344 + 1.345 + /** 1.346 + * All of the tests in the rule network, owned by this list 1.347 + */ 1.348 + ReteNodeSet mAllTests; 1.349 + 1.350 + // pseudo-constants 1.351 + static nsrefcnt gRefCnt; 1.352 + 1.353 +public: 1.354 + static nsIRDFService* gRDFService; 1.355 + static nsIRDFContainerUtils* gRDFContainerUtils; 1.356 + static nsIRDFResource* kNC_BookmarkSeparator; 1.357 + static nsIRDFResource* kRDF_type; 1.358 +}; 1.359 + 1.360 +#endif // nsXULTemplateQueryProcessorRDF_h__