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