content/xul/templates/src/nsTemplateRule.h

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:9ac9ec32922d
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 #ifndef nsTemplateRule_h__
7 #define nsTemplateRule_h__
8
9 #include "nsCOMPtr.h"
10 #include "nsIAtom.h"
11 #include "nsIRDFDataSource.h"
12 #include "nsIRDFResource.h"
13 #include "nsIContent.h"
14 #include "nsIDOMNode.h"
15 #include "nsTArray.h"
16 #include "nsString.h"
17 #include "nsIXULTemplateRuleFilter.h"
18 #include "nsCycleCollectionParticipant.h"
19
20 class nsIXULTemplateQueryProcessor;
21 class nsTemplateQuerySet;
22
23 class nsTemplateCondition
24 {
25 public:
26 // relations that may be used in a rule. They may be negated with the
27 // negate flag. Less and Greater are used for numeric comparisons and
28 // Before and After are used for string comparisons. For Less, Greater,
29 // Before, After, Startswith, Endswith, and Contains, the source is
30 // conceptually on the left of the relation and the target is on the
31 // right. For example, if the relation is Contains, that means Match if
32 // the source contains the target.
33 enum ConditionRelation {
34 eUnknown,
35 eEquals,
36 eLess,
37 eGreater,
38 eBefore,
39 eAfter,
40 eStartswith,
41 eEndswith,
42 eContains
43 };
44
45 nsTemplateCondition(nsIAtom* aSourceVariable,
46 const nsAString& aRelation,
47 nsIAtom* aTargetVariable,
48 bool mIgnoreCase,
49 bool mNegate);
50
51 nsTemplateCondition(nsIAtom* aSourceVariable,
52 const nsAString& aRelation,
53 const nsAString& aTargets,
54 bool mIgnoreCase,
55 bool mNegate,
56 bool aIsMultiple);
57
58 nsTemplateCondition(const nsAString& aSource,
59 const nsAString& aRelation,
60 nsIAtom* aTargetVariable,
61 bool mIgnoreCase,
62 bool mNegate);
63
64 ~nsTemplateCondition() { MOZ_COUNT_DTOR(nsTemplateCondition); }
65
66 nsTemplateCondition* GetNext() { return mNext; }
67 void SetNext(nsTemplateCondition* aNext) { mNext = aNext; }
68
69 void SetRelation(const nsAString& aRelation);
70
71 bool
72 CheckMatch(nsIXULTemplateResult* aResult);
73
74 bool
75 CheckMatchStrings(const nsAString& aLeftString,
76 const nsAString& aRightString);
77 protected:
78
79 nsCOMPtr<nsIAtom> mSourceVariable;
80 nsString mSource;
81 ConditionRelation mRelation;
82 nsCOMPtr<nsIAtom> mTargetVariable;
83 nsTArray<nsString> mTargetList;
84 bool mIgnoreCase;
85 bool mNegate;
86
87 nsTemplateCondition* mNext;
88 };
89
90 /**
91 * A rule consists of:
92 *
93 * - Conditions, a set of unbound variables with consistency
94 * constraints that specify the values that each variable can
95 * assume. The conditions must be completely and consistently
96 * "bound" for the rule to be considered "matched".
97 *
98 * - Bindings, a set of unbound variables with consistency constraints
99 * that specify the values that each variable can assume. Unlike the
100 * conditions, the bindings need not be bound for the rule to be
101 * considered matched.
102 *
103 * - Content that should be constructed when the rule is "activated".
104 *
105 */
106 class nsTemplateRule
107 {
108 public:
109 nsTemplateRule(nsIContent* aRuleNode,
110 nsIContent* aAction,
111 nsTemplateQuerySet* aQuerySet);
112 /**
113 * The copy-constructor should only be called from nsTArray when appending
114 * a new rule, otherwise things break because the copy constructor expects
115 * mBindings and mConditions to be nullptr.
116 */
117 nsTemplateRule(const nsTemplateRule& aOtherRule);
118
119 ~nsTemplateRule();
120
121 /**
122 * Return the <action> node that this rule was constructed from, or its
123 * logical equivalent for shorthand syntaxes. That is, the parent node of
124 * the content that should be generated for this rule.
125 */
126 nsIContent* GetAction() const { return mAction; }
127
128 /**
129 * Return the <rule> content node that this rule was constructed from.
130 * @param aResult an out parameter, which will contain the rule node
131 * @return NS_OK if no errors occur.
132 */
133 nsresult GetRuleNode(nsIDOMNode** aResult) const;
134
135 void SetVars(nsIAtom* aRefVariable, nsIAtom* aMemberVariable)
136 {
137 mRefVariable = aRefVariable;
138 mMemberVariable = aMemberVariable;
139 }
140
141 void SetRuleFilter(nsIXULTemplateRuleFilter* aRuleFilter)
142 {
143 mRuleFilter = aRuleFilter;
144 }
145
146 nsIAtom* GetTag() { return mTag; }
147 void SetTag(nsIAtom* aTag) { mTag = aTag; }
148
149 nsIAtom* GetMemberVariable() { return mMemberVariable; }
150
151 /**
152 * Set the first condition for the rule. Other conditions are linked
153 * to it using the condition's SetNext method.
154 */
155 void SetCondition(nsTemplateCondition* aConditions);
156
157 /**
158 * Check if the result matches the rule by first looking at the conditions.
159 * If the results is accepted by the conditions, the rule filter, if any
160 * was set, is checked. If either check rejects a result, a match cannot
161 * occur for this rule and result.
162 */
163 bool
164 CheckMatch(nsIXULTemplateResult* aResult) const;
165
166 /**
167 * Determine if the rule has the specified binding
168 */
169 bool
170 HasBinding(nsIAtom* aSourceVariable,
171 nsAString& aExpr,
172 nsIAtom* aTargetVariable) const;
173
174 /**
175 * Add a binding to the rule. A binding consists of an already-bound
176 * source variable, and the RDF property that should be tested to
177 * generate a target value. The target value is bound to a target
178 * variable.
179 *
180 * @param aSourceVariable the source variable that will be used in
181 * the RDF query.
182 * @param aExpr the expression that will be used in the query.
183 * @param aTargetVariable the variable whose value will be bound
184 * to the RDF node that is returned when querying the binding
185 * @return NS_OK if no errors occur.
186 */
187 nsresult AddBinding(nsIAtom* aSourceVariable,
188 nsAString& aExpr,
189 nsIAtom* aTargetVariable);
190
191 /**
192 * Inform the query processor of the bindings that are set for a rule.
193 * This should be called after all the bindings for a rule are compiled.
194 */
195 nsresult
196 AddBindingsToQueryProcessor(nsIXULTemplateQueryProcessor* aProcessor);
197
198 void Traverse(nsCycleCollectionTraversalCallback &cb) const
199 {
200 cb.NoteXPCOMChild(mRuleNode);
201 cb.NoteXPCOMChild(mAction);
202 }
203
204 protected:
205
206 struct Binding {
207 nsCOMPtr<nsIAtom> mSourceVariable;
208 nsCOMPtr<nsIAtom> mTargetVariable;
209 nsString mExpr;
210 Binding* mNext;
211 Binding* mParent;
212 };
213
214 // backreference to the query set which owns this rule
215 nsTemplateQuerySet* mQuerySet;
216
217 // the <rule> node, or the <template> node if there is no <rule>
218 nsCOMPtr<nsIDOMNode> mRuleNode;
219
220 // the <action> node, or, if there is no <action>, the container node
221 // which contains the content to generate
222 nsCOMPtr<nsIContent> mAction;
223
224 // the rule filter set by the builder's SetRuleFilter function
225 nsCOMPtr<nsIXULTemplateRuleFilter> mRuleFilter;
226
227 // indicates that the rule will only match when generating content
228 // to be inserted into a container with this tag
229 nsCOMPtr<nsIAtom> mTag;
230
231 // linked-list of the bindings for the rule, owned by the rule.
232 Binding* mBindings;
233
234 nsCOMPtr<nsIAtom> mRefVariable;
235 nsCOMPtr<nsIAtom> mMemberVariable;
236
237 nsTemplateCondition* mConditions; // owned by nsTemplateRule
238 };
239
240 /** nsTemplateQuerySet
241 *
242 * A single <queryset> which holds the query node and the rules for it.
243 * All builders have at least one queryset, which may be created with an
244 * explicit <queryset> tag or implied if the tag is not used.
245 *
246 * These queryset objects are created and owned by the builder in its
247 * mQuerySets array.
248 */
249 class nsTemplateQuerySet
250 {
251 protected:
252 nsTArray<nsTemplateRule> mRules;
253
254 // a number which increments for each successive queryset. It is stored so
255 // it can be used as an optimization when updating results so that it is
256 // known where to insert them into a match.
257 int32_t mPriority;
258
259 public:
260
261 // <query> node
262 nsCOMPtr<nsIContent> mQueryNode;
263
264 // compiled opaque query object returned by the query processor's
265 // CompileQuery call
266 nsCOMPtr<nsISupports> mCompiledQuery;
267
268 // indicates that the query will only generate content to be inserted into
269 // a container with this tag
270 nsCOMPtr<nsIAtom> mTag;
271
272 nsTemplateQuerySet(int32_t aPriority)
273 : mPriority(aPriority)
274 {
275 MOZ_COUNT_CTOR(nsTemplateQuerySet);
276 }
277
278 ~nsTemplateQuerySet()
279 {
280 MOZ_COUNT_DTOR(nsTemplateQuerySet);
281 }
282
283 int32_t Priority() const
284 {
285 return mPriority;
286 }
287
288 nsIAtom* GetTag() { return mTag; }
289 void SetTag(nsIAtom* aTag) { mTag = aTag; }
290
291 nsTemplateRule* NewRule(nsIContent* aRuleNode,
292 nsIContent* aAction,
293 nsTemplateQuerySet* aQuerySet)
294 {
295 // nsTemplateMatch stores the index as a 16-bit value,
296 // so check to make sure for overflow
297 if (mRules.Length() == INT16_MAX)
298 return nullptr;
299
300 return mRules.AppendElement(nsTemplateRule(aRuleNode, aAction,
301 aQuerySet));
302 }
303
304 void RemoveRule(nsTemplateRule *aRule)
305 {
306 mRules.RemoveElementAt(aRule - mRules.Elements());
307 }
308
309 int16_t RuleCount() const
310 {
311 return mRules.Length();
312 }
313
314 nsTemplateRule* GetRuleAt(int16_t aIndex)
315 {
316 if (uint32_t(aIndex) < mRules.Length()) {
317 return &mRules[aIndex];
318 }
319 return nullptr;
320 }
321
322 void Clear()
323 {
324 mRules.Clear();
325 }
326 };
327
328 #endif // nsTemplateRule_h__

mercurial