Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / content / xul / templates / src / nsXULTemplateBuilder.h
blobea32001c21feb363e34c8293dc9efde08992c595
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is Mozilla Communicator client code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Robert Churchill <rjc@netscape.com>
24 * David Hyatt <hyatt@netscape.com>
25 * Chris Waterson <waterson@netscape.com>
26 * Pierre Phaneuf <pp@ludusdesign.com>
27 * Neil Deakin <enndeakin@sympatico.ca>
29 * Alternatively, the contents of this file may be used under the terms of
30 * either of the GNU General Public License Version 2 or later (the "GPL"),
31 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
32 * in which case the provisions of the GPL or the LGPL are applicable instead
33 * of those above. If you wish to allow use of your version of this file only
34 * under the terms of either the GPL or the LGPL, and not to allow others to
35 * use your version of this file under the terms of the MPL, indicate your
36 * decision by deleting the provisions above and replace them with the notice
37 * and other provisions required by the GPL or the LGPL. If you do not delete
38 * the provisions above, a recipient may use your version of this file under
39 * the terms of any one of the MPL, the GPL or the LGPL.
41 * ***** END LICENSE BLOCK ***** */
43 #ifndef nsXULTemplateBuilder_h__
44 #define nsXULTemplateBuilder_h__
46 #include "nsStubDocumentObserver.h"
47 #include "nsIScriptSecurityManager.h"
48 #include "nsIContent.h"
49 #include "nsIObserver.h"
50 #include "nsIRDFCompositeDataSource.h"
51 #include "nsIRDFContainer.h"
52 #include "nsIRDFContainerUtils.h"
53 #include "nsIRDFDataSource.h"
54 #include "nsIRDFObserver.h"
55 #include "nsIRDFService.h"
56 #include "nsIXULTemplateBuilder.h"
58 #include "nsFixedSizeAllocator.h"
59 #include "nsVoidArray.h"
60 #include "nsCOMArray.h"
61 #include "nsTArray.h"
62 #include "nsDataHashtable.h"
63 #include "nsTemplateRule.h"
64 #include "nsTemplateMatch.h"
65 #include "nsIXULTemplateQueryProcessor.h"
66 #include "nsCycleCollectionParticipant.h"
68 #include "prlog.h"
69 #ifdef PR_LOGGING
70 extern PRLogModuleInfo* gXULTemplateLog;
71 #endif
73 class nsIXULDocument;
74 class nsIRDFCompositeDataSource;
75 class nsIObserverService;
77 /**
78 * An object that translates an RDF graph into a presentation using a
79 * set of rules.
81 class nsXULTemplateBuilder : public nsIXULTemplateBuilder,
82 public nsIObserver,
83 public nsStubDocumentObserver
85 public:
86 nsXULTemplateBuilder();
87 virtual ~nsXULTemplateBuilder();
89 nsresult InitGlobals();
91 /**
92 * Clear the template builder structures. The aIsFinal flag is set to true
93 * when the template is going away.
95 virtual void Uninit(PRBool aIsFinal);
97 // nsISupports interface
98 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
99 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULTemplateBuilder,
100 nsIXULTemplateBuilder)
102 // nsIXULTemplateBuilder interface
103 NS_DECL_NSIXULTEMPLATEBUILDER
105 // nsIObserver Interface
106 NS_DECL_NSIOBSERVER
108 // nsIMutationObserver
109 NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
110 NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
111 NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
114 * Remove an old result and/or add a new result. This method will retrieve
115 * the set of containers where the result could be inserted and either add
116 * the new result to those containers, or remove the result from those
117 * containers. UpdateResultInContainer is called for each container.
119 * @param aOldResult result to remove
120 * @param aNewResult result to add
121 * @param aQueryNode query node for new result
123 nsresult
124 UpdateResult(nsIXULTemplateResult* aOldResult,
125 nsIXULTemplateResult* aNewResult,
126 nsIDOMNode* aQueryNode);
129 * Remove an old result and/or add a new result from a specific container.
131 * @param aOldResult result to remove
132 * @param aNewResult result to add
133 * @param aQueryNode queryset for the new result
134 * @param aOldId id of old result
135 * @param aNewId id of new result
136 * @param aInsertionPoint container to remove or add result inside
138 nsresult
139 UpdateResultInContainer(nsIXULTemplateResult* aOldResult,
140 nsIXULTemplateResult* aNewResult,
141 nsTemplateQuerySet* aQuerySet,
142 nsIRDFResource* aOldId,
143 nsIRDFResource* aNewId,
144 nsIContent* aInsertionPoint);
146 nsresult
147 ComputeContainmentProperties();
149 static PRBool
150 IsTemplateElement(nsIContent* aContent);
152 virtual nsresult
153 RebuildAll() = 0; // must be implemented by subclasses
156 * Find the <template> tag that applies for this builder
158 nsresult
159 GetTemplateRoot(nsIContent** aResult);
162 * Compile the template's queries
164 nsresult
165 CompileQueries();
168 * Compile the template given a <template> in aTemplate. This function
169 * is called recursively to handle queries inside a queryset. For the
170 * outer pass, aIsQuerySet will be false, while the inner pass this will
171 * be true.
173 * aCanUseTemplate will be set to true if the template's queries could be
174 * compiled, and false otherwise. If false, the entire template is
175 * invalid.
177 * @param aTemplate <template> to compile
178 * @param aQuerySet first queryset
179 * @param aIsQuerySet true if
180 * @param aPriority the queryset index, incremented when a new one is added
181 * @param aCanUseTemplate true if template is valid
183 nsresult
184 CompileTemplate(nsIContent* aTemplate,
185 nsTemplateQuerySet* aQuerySet,
186 PRBool aIsQuerySet,
187 PRInt32* aPriority,
188 PRBool* aCanUseTemplate);
191 * Compile a query using the extended syntax. For backwards compatible RDF
192 * syntax where there is no <query>, the <conditions> becomes the query.
194 * @param aRuleElement <rule> element
195 * @param aActionElement <action> element
196 * @param aMemberVariable member variable for the query
197 * @param aQuerySet the queryset
199 nsresult
200 CompileExtendedQuery(nsIContent* aRuleElement,
201 nsIContent* aActionElement,
202 nsIAtom* aMemberVariable,
203 nsTemplateQuerySet* aQuerySet);
206 * Determine the ref variable and tag from inside a RDF query.
208 void DetermineRDFQueryRef(nsIContent* aQueryElement, nsIAtom** tag);
211 * Determine the member variable from inside an action body. It will be
212 * the value of the uri attribute on a node.
214 nsresult
215 DetermineMemberVariable(nsIContent* aActionElement, nsIAtom** aMemberVariable);
218 * Compile a simple query. A simple query is one that doesn't have a
219 * <query> and should use a default query which would normally just return
220 * a list of children of the reference point.
222 * @param aRuleElement the <rule>
223 * @param aQuerySet the query set
224 * @param aCanUseTemplate true if the query is valid
226 nsresult
227 CompileSimpleQuery(nsIContent* aRuleElement,
228 nsTemplateQuerySet* aQuerySet,
229 PRBool* aCanUseTemplate);
232 * Compile the <conditions> tag in a rule
234 * @param aRule template rule
235 * @param aConditions <conditions> element
237 nsresult
238 CompileConditions(nsTemplateRule* aRule, nsIContent* aConditions);
241 * Compile a <where> tag in a condition. The caller should set
242 * *aCurrentCondition to null for the first condition. This value will be
243 * updated to point to the new condition before returning. The conditions
244 * will be added to the rule aRule by this method.
246 * @param aRule template rule
247 * @param aCondition <where> element
248 * @param aCurrentCondition compiled condition
250 nsresult
251 CompileWhereCondition(nsTemplateRule* aRule,
252 nsIContent* aCondition,
253 nsTemplateCondition** aCurrentCondition);
256 * Compile the <bindings> for an extended template syntax rule.
258 nsresult
259 CompileBindings(nsTemplateRule* aRule, nsIContent* aBindings);
262 * Compile a single binding for an extended template syntax rule.
264 nsresult
265 CompileBinding(nsTemplateRule* aRule, nsIContent* aBinding);
268 * Add automatic bindings for simple rules
270 nsresult
271 AddSimpleRuleBindings(nsTemplateRule* aRule, nsIContent* aElement);
273 static void
274 AddBindingsFor(nsXULTemplateBuilder* aSelf,
275 const nsAString& aVariable,
276 void* aClosure);
279 * Load the datasources for the template. shouldDelayBuilding is an out
280 * parameter which will be set to true to indicate that content building
281 * should not be performed yet as the datasource has not yet loaded. If
282 * false, the datasource has already loaded so building can proceed
283 * immediately. In the former case, the datasource or query processor
284 * should either rebuild the template or update results when the
285 * datasource is loaded as needed.
287 nsresult
288 LoadDataSources(nsIDocument* aDoc, PRBool* shouldDelayBuilding);
291 * Called by LoadDataSources to load a datasource given a uri list
292 * in aDataSource. The list is a set of uris separated by spaces.
293 * If aIsRDFQuery is true, then this is for an RDF datasource which
294 * causes the method to check for additional flags specific to the
295 * RDF processor.
297 nsresult
298 LoadDataSourceUrls(nsIDocument* aDocument,
299 const nsAString& aDataSources,
300 PRBool aIsRDFQuery,
301 PRBool* aShouldDelayBuilding);
303 nsresult
304 InitHTMLTemplateRoot();
307 * Determine which rule matches a given result. aContainer is used for
308 * tag matching and is optional for non-content generating builders.
309 * The returned matched rule is always one of the rules owned by the
310 * query set aQuerySet.
312 * @param aContainer parent where generated content will be inserted
313 * @param aResult result to match
314 * @param aQuerySet query set to examine the rules of
315 * @param aMatchedRule [out] rule that has matched, or null if any.
316 * @param aRuleIndex [out] index of the rule
318 nsresult
319 DetermineMatchedRule(nsIContent* aContainer,
320 nsIXULTemplateResult* aResult,
321 nsTemplateQuerySet* aQuerySet,
322 nsTemplateRule** aMatchedRule,
323 PRInt16 *aRuleIndex);
325 // XXX sigh, the string template foo doesn't mix with
326 // operator->*() on egcs-1.1.2, so we'll need to explicitly pass
327 // "this" and use good ol' fashioned static callbacks.
328 void
329 ParseAttribute(const nsAString& aAttributeValue,
330 void (*aVariableCallback)(nsXULTemplateBuilder* aThis, const nsAString&, void*),
331 void (*aTextCallback)(nsXULTemplateBuilder* aThis, const nsAString&, void*),
332 void* aClosure);
334 nsresult
335 SubstituteText(nsIXULTemplateResult* aMatch,
336 const nsAString& aAttributeValue,
337 nsAString& aResult);
339 static void
340 SubstituteTextAppendText(nsXULTemplateBuilder* aThis, const nsAString& aText, void* aClosure);
342 static void
343 SubstituteTextReplaceVariable(nsXULTemplateBuilder* aThis, const nsAString& aVariable, void* aClosure);
345 nsresult
346 IsSystemPrincipal(nsIPrincipal *principal, PRBool *result);
349 * Convenience method which gets a resource for a result. If a result
350 * doesn't have a resource set, it will create one from the result's id.
352 nsresult GetResultResource(nsIXULTemplateResult* aResult,
353 nsIRDFResource** aResource);
355 protected:
356 nsCOMPtr<nsISupports> mDataSource;
357 nsCOMPtr<nsIRDFDataSource> mDB;
358 nsCOMPtr<nsIRDFCompositeDataSource> mCompDB;
361 * Circular reference, broken when the document is destroyed.
363 nsCOMPtr<nsIContent> mRoot;
366 * The root result, translated from the root element's ref
368 nsCOMPtr<nsIXULTemplateResult> mRootResult;
370 nsCOMArray<nsIXULBuilderListener> mListeners;
373 * The query processor which generates results
375 nsCOMPtr<nsIXULTemplateQueryProcessor> mQueryProcessor;
378 * The list of querysets
380 nsTArray<nsTemplateQuerySet *> mQuerySets;
383 * Set to true if the rules have already been compiled
385 PRBool mQueriesCompiled;
388 * The default reference and member variables.
390 nsCOMPtr<nsIAtom> mRefVariable;
391 nsCOMPtr<nsIAtom> mMemberVariable;
394 * The match map contains nsTemplateMatch objects, one for each unique
395 * match found, keyed by the resource for that match. A particular match
396 * will contain a linked list of all of the matches for that unique result
397 * id. Only one is active at a time. When a match is retracted, look in
398 * the match map, remove it, and apply the next valid match in sequence to
399 * make active.
401 nsDataHashtable<nsISupportsHashKey, nsTemplateMatch*> mMatchMap;
404 * Fixed size allocator used to allocate matches
406 nsFixedSizeAllocator mPool;
408 public:
410 nsFixedSizeAllocator& GetPool() { return mPool; }
412 protected:
413 // pseudo-constants
414 static nsrefcnt gRefCnt;
415 static nsIRDFService* gRDFService;
416 static nsIRDFContainerUtils* gRDFContainerUtils;
417 static nsIScriptSecurityManager* gScriptSecurityManager;
418 static nsIPrincipal* gSystemPrincipal;
419 static nsIObserverService* gObserverService;
421 enum {
422 eDontTestEmpty = (1 << 0),
423 eDontRecurse = (2 << 0)
426 PRInt32 mFlags;
429 * Stack-based helper class to maintain a list of ``activated''
430 * resources; i.e., resources for which we are currently building
431 * content.
433 class ActivationEntry {
434 public:
435 nsIRDFResource *mResource;
436 ActivationEntry *mPrevious;
437 ActivationEntry **mLink;
439 ActivationEntry(nsIRDFResource *aResource, ActivationEntry **aLink)
440 : mResource(aResource),
441 mPrevious(*aLink),
442 mLink(aLink) { *mLink = this; }
444 ~ActivationEntry() { *mLink = mPrevious; }
448 * The top of the stack of resources that we're currently building
449 * content for.
451 ActivationEntry *mTop;
454 * Determine if a resource is currently on the activation stack.
456 PRBool
457 IsActivated(nsIRDFResource *aResource);
460 * Returns true if content may be generated for a result, or false if it
461 * cannot, for example, if it would be created inside a closed container.
462 * Those results will be generated when the container is opened.
463 * If false is returned, no content should be generated. Possible
464 * insertion locations may optionally be set for new content, depending on
465 * the builder being used. Note that *aLocations or some items within
466 * aLocations may be null.
468 virtual PRBool
469 GetInsertionLocations(nsIXULTemplateResult* aResult,
470 nsCOMArray<nsIContent>** aLocations) = 0;
473 * Must be implemented by subclasses. Handle removing the generated
474 * output for aOldMatch and adding new output for aNewMatch. Either
475 * aOldMatch or aNewMatch may be null. aContext is the location returned
476 * from the call to MayGenerateResult.
478 virtual nsresult
479 ReplaceMatch(nsIXULTemplateResult* aOldResult,
480 nsTemplateMatch* aNewMatch,
481 nsTemplateRule* aNewMatchRule,
482 void *aContext) = 0;
485 * Must be implemented by subclasses. Handle change in bound
486 * variable values for aResult. aModifiedVars contains the set
487 * of variables that have changed.
488 * @param aResult the ersult for which variable bindings has changed.
489 * @param aModifiedVars the set of variables for which the bindings
490 * have changed.
492 virtual nsresult
493 SynchronizeResult(nsIXULTemplateResult* aResult) = 0;
495 virtual void Traverse(nsCycleCollectionTraversalCallback &cb) const
500 * Document that we're observing. Weak ref!
502 nsIDocument* mObservedDocument;
505 #endif // nsXULTemplateBuilder_h__