nsTemplateRule.h 10.0 KB

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