|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 |
|
7 #ifndef nsXULTemplateQueryProcessorRDF_h__ |
|
8 #define nsXULTemplateQueryProcessorRDF_h__ |
|
9 |
|
10 #include "nsIRDFContainer.h" |
|
11 #include "nsIRDFContainerUtils.h" |
|
12 #include "nsIRDFDataSource.h" |
|
13 #include "nsIRDFObserver.h" |
|
14 #include "nsIRDFService.h" |
|
15 #include "nsIXULTemplateBuilder.h" |
|
16 #include "nsIXULTemplateQueryProcessor.h" |
|
17 #include "nsCollationCID.h" |
|
18 |
|
19 #include "nsResourceSet.h" |
|
20 #include "nsRuleNetwork.h" |
|
21 #include "nsRDFQuery.h" |
|
22 #include "nsRDFBinding.h" |
|
23 #include "nsXULTemplateResultSetRDF.h" |
|
24 #include "nsCOMArray.h" |
|
25 #include "nsString.h" |
|
26 #include "nsClassHashtable.h" |
|
27 #include "nsRefPtrHashtable.h" |
|
28 #include "nsCycleCollectionParticipant.h" |
|
29 #include "mozilla/Attributes.h" |
|
30 |
|
31 #include "prlog.h" |
|
32 #ifdef PR_LOGGING |
|
33 extern PRLogModuleInfo* gXULTemplateLog; |
|
34 #endif |
|
35 |
|
36 class nsIContent; |
|
37 class nsIRDFCompositeDataSource; |
|
38 class nsXULTemplateResultRDF; |
|
39 |
|
40 /** |
|
41 * An object that generates results from a query on an RDF graph |
|
42 */ |
|
43 class nsXULTemplateQueryProcessorRDF MOZ_FINAL : public nsIXULTemplateQueryProcessor, |
|
44 public nsIRDFObserver |
|
45 { |
|
46 public: |
|
47 typedef nsTArray<nsRefPtr<nsXULTemplateResultRDF> > ResultArray; |
|
48 |
|
49 nsXULTemplateQueryProcessorRDF(); |
|
50 |
|
51 ~nsXULTemplateQueryProcessorRDF(); |
|
52 |
|
53 nsresult InitGlobals(); |
|
54 |
|
55 // nsISupports interface |
|
56 NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
|
57 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULTemplateQueryProcessorRDF, |
|
58 nsIXULTemplateQueryProcessor) |
|
59 |
|
60 // nsIXULTemplateQueryProcessor interface |
|
61 NS_DECL_NSIXULTEMPLATEQUERYPROCESSOR |
|
62 |
|
63 // nsIRDFObserver interface |
|
64 NS_DECL_NSIRDFOBSERVER |
|
65 |
|
66 /* |
|
67 * Propagate all changes through the rule network when an assertion is |
|
68 * added to the graph, adding any new results. |
|
69 */ |
|
70 nsresult |
|
71 Propagate(nsIRDFResource* aSource, |
|
72 nsIRDFResource* aProperty, |
|
73 nsIRDFNode* aTarget); |
|
74 |
|
75 /* |
|
76 * Retract all changes through the rule network when an assertion is |
|
77 * removed from the graph, removing any results that no longer match. |
|
78 */ |
|
79 nsresult |
|
80 Retract(nsIRDFResource* aSource, |
|
81 nsIRDFResource* aProperty, |
|
82 nsIRDFNode* aTarget); |
|
83 |
|
84 /* |
|
85 * Synchronize results when the graph changes, updating their bindings. |
|
86 */ |
|
87 nsresult |
|
88 SynchronizeAll(nsIRDFResource* aSource, |
|
89 nsIRDFResource* aProperty, |
|
90 nsIRDFNode* aOldTarget, |
|
91 nsIRDFNode* aNewTarget); |
|
92 |
|
93 /* |
|
94 * Return true if a resource is a container |
|
95 */ |
|
96 nsresult |
|
97 CheckContainer(nsIRDFResource* aTargetResource, |
|
98 bool* aIsContainer); |
|
99 |
|
100 /* |
|
101 * Check if a resource does not have any children |
|
102 */ |
|
103 nsresult |
|
104 CheckEmpty(nsIRDFResource* aTargetResource, |
|
105 bool* aIsEmpty); |
|
106 |
|
107 /** |
|
108 * Check if a resource is a separator |
|
109 */ |
|
110 nsresult |
|
111 CheckIsSeparator(nsIRDFResource* aResource, bool* aIsSeparator); |
|
112 |
|
113 /* |
|
114 * Compute the containment properties which are additional arcs which |
|
115 * indicate that a node is a container, in additional to the RDF container |
|
116 * tests. The computed list is stored in mContainmentProperties |
|
117 */ |
|
118 nsresult |
|
119 ComputeContainmentProperties(nsIDOMNode* aRootNode); |
|
120 |
|
121 /** |
|
122 * Compile a query that uses the extended template syntax. The last |
|
123 * compiled node of the query is returned as aLastNode. This node will |
|
124 * have been added to mAllTests which owns the node. |
|
125 */ |
|
126 nsresult |
|
127 CompileExtendedQuery(nsRDFQuery* aQuery, |
|
128 nsIContent* aConditions, |
|
129 TestNode** aLastNode); |
|
130 |
|
131 /** |
|
132 * Compile a single query child and return the compiled node in aResult. |
|
133 * This node will have been added to mAllTests which owns the node and |
|
134 * set as a child of aParentNode. |
|
135 */ |
|
136 virtual nsresult |
|
137 CompileQueryChild(nsIAtom* aTag, |
|
138 nsRDFQuery* aQuery, |
|
139 nsIContent* aConditions, |
|
140 TestNode* aParentNode, |
|
141 TestNode** aResult); |
|
142 |
|
143 /** |
|
144 * Parse the value of a property test assertion for a condition or a simple |
|
145 * rule based on the parseType attribute into the appropriate literal type. |
|
146 */ |
|
147 nsresult ParseLiteral(const nsString& aParseType, |
|
148 const nsString& aValue, |
|
149 nsIRDFNode** aResult); |
|
150 |
|
151 /** |
|
152 * Compile a <triple> condition and return the compiled node in aResult. |
|
153 * This node will have been added to mAllTests which owns the node and |
|
154 * set as a child of aParentNode. |
|
155 */ |
|
156 nsresult |
|
157 CompileTripleCondition(nsRDFQuery* aQuery, |
|
158 nsIContent* aCondition, |
|
159 TestNode* aParentNode, |
|
160 TestNode** aResult); |
|
161 |
|
162 /** |
|
163 * Compile a <member> condition and return the compiled node in aResult. |
|
164 * This node will have been added to mAllTests which owns the node and |
|
165 * set as a child of aParentNode. |
|
166 */ |
|
167 nsresult |
|
168 CompileMemberCondition(nsRDFQuery* aQuery, |
|
169 nsIContent* aCondition, |
|
170 TestNode* aParentNode, |
|
171 TestNode** aResult); |
|
172 |
|
173 /** |
|
174 * Add the default rules shared by all simple queries. This creates |
|
175 * the content start node followed by a member test. The member TestNode |
|
176 * is returned in aChildNode. Both nodes will have been added to mAllTests |
|
177 * which owns the nodes. |
|
178 */ |
|
179 nsresult |
|
180 AddDefaultSimpleRules(nsRDFQuery* aQuery, |
|
181 TestNode** aChildNode); |
|
182 |
|
183 /** |
|
184 * Compile a query that's specified using the simple template |
|
185 * syntax. Each TestNode is created in a chain, the last compiled node |
|
186 * is returned as aLastNode. All nodes will have been added to mAllTests |
|
187 * which owns the nodes. |
|
188 */ |
|
189 nsresult |
|
190 CompileSimpleQuery(nsRDFQuery* aQuery, |
|
191 nsIContent* aQueryElement, |
|
192 TestNode** aLastNode); |
|
193 |
|
194 RDFBindingSet* |
|
195 GetBindingsForRule(nsIDOMNode* aRule); |
|
196 |
|
197 /* |
|
198 * Indicate that a result is dependant on a particular resource. When an |
|
199 * assertion is added to or removed from the graph involving that |
|
200 * resource, that result must be recalculated. |
|
201 */ |
|
202 void |
|
203 AddBindingDependency(nsXULTemplateResultRDF* aResult, |
|
204 nsIRDFResource* aResource); |
|
205 |
|
206 /** |
|
207 * Remove a dependency a result has on a particular resource. |
|
208 */ |
|
209 void |
|
210 RemoveBindingDependency(nsXULTemplateResultRDF* aResult, |
|
211 nsIRDFResource* aResource); |
|
212 |
|
213 /** |
|
214 * A memory element is a hash of an RDF triple. One exists for each triple |
|
215 * that was involved in generating a result. This function adds this to a |
|
216 * map, keyed by memory element, when the value is a list of results that |
|
217 * depend on that memory element. When an RDF triple is removed from the |
|
218 * datasource, RetractElement is called, and this map is examined to |
|
219 * determine which results are no longer valid. |
|
220 */ |
|
221 nsresult |
|
222 AddMemoryElements(const Instantiation& aInst, |
|
223 nsXULTemplateResultRDF* aResult); |
|
224 |
|
225 /** |
|
226 * Remove the memory elements associated with a result when the result is |
|
227 * no longer being used. |
|
228 */ |
|
229 nsresult |
|
230 RemoveMemoryElements(const Instantiation& aInst, |
|
231 nsXULTemplateResultRDF* aResult); |
|
232 |
|
233 /** |
|
234 * Remove the results associated with a memory element since the |
|
235 * RDF triple the memory element is a hash of has been removed. |
|
236 */ |
|
237 void RetractElement(const MemoryElement& aMemoryElement); |
|
238 |
|
239 /** |
|
240 * Return the index of a result's resource in its RDF container |
|
241 */ |
|
242 int32_t |
|
243 GetContainerIndexOf(nsIXULTemplateResult* aResult); |
|
244 |
|
245 /** |
|
246 * Given a result and a predicate to sort on, get the target value of |
|
247 * the triple to use for sorting. The sort predicate is the predicate |
|
248 * with '?sort=true' appended. |
|
249 */ |
|
250 nsresult |
|
251 GetSortValue(nsIXULTemplateResult* aResult, |
|
252 nsIRDFResource* aPredicate, |
|
253 nsIRDFResource* aSortPredicate, |
|
254 nsISupports** aResultNode); |
|
255 |
|
256 nsIRDFDataSource* GetDataSource() { return mDB; } |
|
257 |
|
258 nsIXULTemplateBuilder* GetBuilder() { return mBuilder; } |
|
259 |
|
260 nsResourceSet& ContainmentProperties() { return mContainmentProperties; } |
|
261 |
|
262 #ifdef PR_LOGGING |
|
263 nsresult |
|
264 Log(const char* aOperation, |
|
265 nsIRDFResource* aSource, |
|
266 nsIRDFResource* aProperty, |
|
267 nsIRDFNode* aTarget); |
|
268 |
|
269 #define LOG(_op, _src, _prop, _targ) \ |
|
270 Log(_op, _src, _prop, _targ) |
|
271 |
|
272 #else |
|
273 #define LOG(_op, _src, _prop, _targ) |
|
274 #endif |
|
275 |
|
276 protected: |
|
277 // We are an observer of the composite datasource. The cycle is |
|
278 // broken when the document is destroyed. |
|
279 nsCOMPtr<nsIRDFDataSource> mDB; |
|
280 |
|
281 // weak reference to the builder, cleared when the document is destroyed |
|
282 nsIXULTemplateBuilder* mBuilder; |
|
283 |
|
284 // true if the query processor has been initialized |
|
285 bool mQueryProcessorRDFInited; |
|
286 |
|
287 // true if results have been generated. Once set, bindings can no longer |
|
288 // be added. If they were, the binding value arrays for results that have |
|
289 // already been generated would be the wrong size |
|
290 bool mGenerationStarted; |
|
291 |
|
292 // nesting level for RDF batch notifications |
|
293 int32_t mUpdateBatchNest; |
|
294 |
|
295 // containment properties that are checked to determine if a resource is |
|
296 // a container |
|
297 nsResourceSet mContainmentProperties; |
|
298 |
|
299 // the end node of the default simple node hierarchy |
|
300 TestNode* mSimpleRuleMemberTest; |
|
301 |
|
302 // the reference variable |
|
303 nsCOMPtr<nsIAtom> mRefVariable; |
|
304 |
|
305 // the last ref that was calculated, used for simple rules |
|
306 nsCOMPtr<nsIXULTemplateResult> mLastRef; |
|
307 |
|
308 /** |
|
309 * A map between nsIRDFNodes that form the left-hand side (the subject) of |
|
310 * a <binding> and an array of nsIXULTemplateResults. When a new assertion |
|
311 * is added to the graph involving a particular rdf node, it is looked up |
|
312 * in this binding map. If it exists, the corresponding results must then |
|
313 * be synchronized. |
|
314 */ |
|
315 nsClassHashtable<nsISupportsHashKey, ResultArray> mBindingDependencies; |
|
316 |
|
317 /** |
|
318 * A map between memory elements and an array of nsIXULTemplateResults. |
|
319 * When a triple is unasserted from the graph, the corresponding results |
|
320 * no longer match so they must be removed. |
|
321 */ |
|
322 nsClassHashtable<nsUint32HashKey, |
|
323 nsCOMArray<nsXULTemplateResultRDF> > mMemoryElementToResultMap; |
|
324 |
|
325 // map of the rules to the bindings for those rules. |
|
326 // XXXndeakin this might be better just as an array since there is usually |
|
327 // ten or fewer rules |
|
328 nsRefPtrHashtable<nsISupportsHashKey, RDFBindingSet> mRuleToBindingsMap; |
|
329 |
|
330 /** |
|
331 * The queries |
|
332 */ |
|
333 nsTArray<nsCOMPtr<nsITemplateRDFQuery> > mQueries; |
|
334 |
|
335 /** |
|
336 * All of the RDF tests in the rule network, which are checked when a new |
|
337 * assertion is added to the graph. This is a subset of mAllTests, which |
|
338 * also includes non-RDF tests. |
|
339 */ |
|
340 ReteNodeSet mRDFTests; |
|
341 |
|
342 /** |
|
343 * All of the tests in the rule network, owned by this list |
|
344 */ |
|
345 ReteNodeSet mAllTests; |
|
346 |
|
347 // pseudo-constants |
|
348 static nsrefcnt gRefCnt; |
|
349 |
|
350 public: |
|
351 static nsIRDFService* gRDFService; |
|
352 static nsIRDFContainerUtils* gRDFContainerUtils; |
|
353 static nsIRDFResource* kNC_BookmarkSeparator; |
|
354 static nsIRDFResource* kRDF_type; |
|
355 }; |
|
356 |
|
357 #endif // nsXULTemplateQueryProcessorRDF_h__ |