nsRDFPropertyTestNode.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  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. #include "nsRDFPropertyTestNode.h"
  6. #include "nsString.h"
  7. #include "nsXULContentUtils.h"
  8. #include "mozilla/Logging.h"
  9. using mozilla::LogLevel;
  10. extern mozilla::LazyLogModule gXULTemplateLog;
  11. #include "nsIRDFLiteral.h"
  12. nsRDFPropertyTestNode::nsRDFPropertyTestNode(TestNode* aParent,
  13. nsXULTemplateQueryProcessorRDF* aProcessor,
  14. nsIAtom* aSourceVariable,
  15. nsIRDFResource* aProperty,
  16. nsIAtom* aTargetVariable)
  17. : nsRDFTestNode(aParent),
  18. mProcessor(aProcessor),
  19. mSourceVariable(aSourceVariable),
  20. mSource(nullptr),
  21. mProperty(aProperty),
  22. mTargetVariable(aTargetVariable),
  23. mTarget(nullptr)
  24. {
  25. if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
  26. const char* prop = "(null)";
  27. if (aProperty)
  28. aProperty->GetValueConst(&prop);
  29. nsAutoString svar(NS_LITERAL_STRING("(none)"));
  30. if (mSourceVariable)
  31. mSourceVariable->ToString(svar);
  32. nsAutoString tvar(NS_LITERAL_STRING("(none)"));
  33. if (mTargetVariable)
  34. mTargetVariable->ToString(tvar);
  35. MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
  36. ("nsRDFPropertyTestNode[%p]: parent=%p source=%s property=%s target=%s",
  37. this, aParent, NS_ConvertUTF16toUTF8(svar).get(), prop, NS_ConvertUTF16toUTF8(tvar).get()));
  38. }
  39. }
  40. nsRDFPropertyTestNode::nsRDFPropertyTestNode(TestNode* aParent,
  41. nsXULTemplateQueryProcessorRDF* aProcessor,
  42. nsIRDFResource* aSource,
  43. nsIRDFResource* aProperty,
  44. nsIAtom* aTargetVariable)
  45. : nsRDFTestNode(aParent),
  46. mProcessor(aProcessor),
  47. mSourceVariable(nullptr),
  48. mSource(aSource),
  49. mProperty(aProperty),
  50. mTargetVariable(aTargetVariable),
  51. mTarget(nullptr)
  52. {
  53. if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
  54. const char* source = "(null)";
  55. if (aSource)
  56. aSource->GetValueConst(&source);
  57. const char* prop = "(null)";
  58. if (aProperty)
  59. aProperty->GetValueConst(&prop);
  60. nsAutoString tvar(NS_LITERAL_STRING("(none)"));
  61. if (mTargetVariable)
  62. mTargetVariable->ToString(tvar);
  63. MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
  64. ("nsRDFPropertyTestNode[%p]: parent=%p source=%s property=%s target=%s",
  65. this, aParent, source, prop, NS_ConvertUTF16toUTF8(tvar).get()));
  66. }
  67. }
  68. nsRDFPropertyTestNode::nsRDFPropertyTestNode(TestNode* aParent,
  69. nsXULTemplateQueryProcessorRDF* aProcessor,
  70. nsIAtom* aSourceVariable,
  71. nsIRDFResource* aProperty,
  72. nsIRDFNode* aTarget)
  73. : nsRDFTestNode(aParent),
  74. mProcessor(aProcessor),
  75. mSourceVariable(aSourceVariable),
  76. mSource(nullptr),
  77. mProperty(aProperty),
  78. mTargetVariable(nullptr),
  79. mTarget(aTarget)
  80. {
  81. if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
  82. nsAutoString svar(NS_LITERAL_STRING("(none)"));
  83. if (mSourceVariable)
  84. mSourceVariable->ToString(svar);
  85. const char* prop = "(null)";
  86. if (aProperty)
  87. aProperty->GetValueConst(&prop);
  88. nsAutoString target;
  89. nsXULContentUtils::GetTextForNode(aTarget, target);
  90. MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
  91. ("nsRDFPropertyTestNode[%p]: parent=%p source=%s property=%s target=%s",
  92. this, aParent, NS_ConvertUTF16toUTF8(svar).get(), prop, NS_ConvertUTF16toUTF8(target).get()));
  93. }
  94. }
  95. nsresult
  96. nsRDFPropertyTestNode::FilterInstantiations(InstantiationSet& aInstantiations,
  97. bool* aCantHandleYet) const
  98. {
  99. nsresult rv;
  100. if (aCantHandleYet)
  101. *aCantHandleYet = false;
  102. nsIRDFDataSource* ds = mProcessor->GetDataSource();
  103. InstantiationSet::Iterator last = aInstantiations.Last();
  104. for (InstantiationSet::Iterator inst = aInstantiations.First(); inst != last; ++inst) {
  105. bool hasSourceBinding;
  106. nsCOMPtr<nsIRDFResource> sourceRes;
  107. if (mSource) {
  108. hasSourceBinding = true;
  109. sourceRes = mSource;
  110. }
  111. else {
  112. nsCOMPtr<nsIRDFNode> sourceValue;
  113. hasSourceBinding = inst->mAssignments.GetAssignmentFor(mSourceVariable,
  114. getter_AddRefs(sourceValue));
  115. sourceRes = do_QueryInterface(sourceValue);
  116. }
  117. bool hasTargetBinding;
  118. nsCOMPtr<nsIRDFNode> targetValue;
  119. if (mTarget) {
  120. hasTargetBinding = true;
  121. targetValue = mTarget;
  122. }
  123. else {
  124. hasTargetBinding = inst->mAssignments.GetAssignmentFor(mTargetVariable,
  125. getter_AddRefs(targetValue));
  126. }
  127. if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
  128. const char* source = "(unbound)";
  129. if (hasSourceBinding)
  130. sourceRes->GetValueConst(&source);
  131. nsAutoString target(NS_LITERAL_STRING("(unbound)"));
  132. if (hasTargetBinding)
  133. nsXULContentUtils::GetTextForNode(targetValue, target);
  134. MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
  135. ("nsRDFPropertyTestNode[%p]: FilterInstantiations() source=[%s] target=[%s]",
  136. this, source, NS_ConvertUTF16toUTF8(target).get()));
  137. }
  138. if (hasSourceBinding && hasTargetBinding) {
  139. // it's a consistency check. see if we have a assignment that is consistent
  140. bool hasAssertion;
  141. rv = ds->HasAssertion(sourceRes, mProperty, targetValue,
  142. true, &hasAssertion);
  143. if (NS_FAILED(rv)) return rv;
  144. MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
  145. (" consistency check => %s", hasAssertion ? "passed" : "failed"));
  146. if (hasAssertion) {
  147. // it's consistent.
  148. Element* element =
  149. new nsRDFPropertyTestNode::Element(sourceRes, mProperty,
  150. targetValue);
  151. inst->AddSupportingElement(element);
  152. }
  153. else {
  154. // it's inconsistent. remove it.
  155. aInstantiations.Erase(inst--);
  156. }
  157. }
  158. else if ((hasSourceBinding && ! hasTargetBinding) ||
  159. (! hasSourceBinding && hasTargetBinding)) {
  160. // it's an open ended query on the source or
  161. // target. figure out what matches and add as a
  162. // cross-product.
  163. nsCOMPtr<nsISimpleEnumerator> results;
  164. if (hasSourceBinding) {
  165. rv = ds->GetTargets(sourceRes,
  166. mProperty,
  167. true,
  168. getter_AddRefs(results));
  169. }
  170. else {
  171. rv = ds->GetSources(mProperty,
  172. targetValue,
  173. true,
  174. getter_AddRefs(results));
  175. if (NS_FAILED(rv)) return rv;
  176. }
  177. while (1) {
  178. bool hasMore;
  179. rv = results->HasMoreElements(&hasMore);
  180. if (NS_FAILED(rv)) return rv;
  181. if (! hasMore)
  182. break;
  183. nsCOMPtr<nsISupports> isupports;
  184. rv = results->GetNext(getter_AddRefs(isupports));
  185. if (NS_FAILED(rv)) return rv;
  186. nsIAtom* variable;
  187. nsCOMPtr<nsIRDFNode> value;
  188. if (hasSourceBinding) {
  189. variable = mTargetVariable;
  190. value = do_QueryInterface(isupports);
  191. NS_ASSERTION(value != nullptr, "target is not an nsIRDFNode");
  192. if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
  193. nsAutoString s(NS_LITERAL_STRING("(none found)"));
  194. if (value)
  195. nsXULContentUtils::GetTextForNode(value, s);
  196. MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
  197. (" target => %s", NS_ConvertUTF16toUTF8(s).get()));
  198. }
  199. if (! value) continue;
  200. targetValue = value;
  201. }
  202. else {
  203. variable = mSourceVariable;
  204. nsCOMPtr<nsIRDFResource> source = do_QueryInterface(isupports);
  205. NS_ASSERTION(source != nullptr, "source is not an nsIRDFResource");
  206. if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
  207. const char* s = "(none found)";
  208. if (source)
  209. source->GetValueConst(&s);
  210. MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
  211. (" source => %s", s));
  212. }
  213. if (! source) continue;
  214. value = sourceRes = source;
  215. }
  216. // Copy the original instantiation, and add it to the
  217. // instantiation set with the new assignment that we've
  218. // introduced. Ownership will be transferred to the
  219. Instantiation newinst = *inst;
  220. newinst.AddAssignment(variable, value);
  221. Element* element =
  222. new nsRDFPropertyTestNode::Element(sourceRes, mProperty,
  223. targetValue);
  224. newinst.AddSupportingElement(element);
  225. aInstantiations.Insert(inst, newinst);
  226. }
  227. // finally, remove the "under specified" instantiation.
  228. aInstantiations.Erase(inst--);
  229. }
  230. else {
  231. if (!aCantHandleYet) {
  232. nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_TRIPLE_UNBOUND);
  233. // Neither source nor target assignment!
  234. return NS_ERROR_UNEXPECTED;
  235. }
  236. *aCantHandleYet = true;
  237. return NS_OK;
  238. }
  239. }
  240. return NS_OK;
  241. }
  242. bool
  243. nsRDFPropertyTestNode::CanPropagate(nsIRDFResource* aSource,
  244. nsIRDFResource* aProperty,
  245. nsIRDFNode* aTarget,
  246. Instantiation& aInitialBindings) const
  247. {
  248. bool result;
  249. if ((mProperty.get() != aProperty) ||
  250. (mSource && mSource.get() != aSource) ||
  251. (mTarget && mTarget.get() != aTarget)) {
  252. result = false;
  253. }
  254. else {
  255. if (mSourceVariable)
  256. aInitialBindings.AddAssignment(mSourceVariable, aSource);
  257. if (mTargetVariable)
  258. aInitialBindings.AddAssignment(mTargetVariable, aTarget);
  259. result = true;
  260. }
  261. if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
  262. const char* source;
  263. aSource->GetValueConst(&source);
  264. const char* property;
  265. aProperty->GetValueConst(&property);
  266. nsAutoString target;
  267. nsXULContentUtils::GetTextForNode(aTarget, target);
  268. MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
  269. ("nsRDFPropertyTestNode[%p]: CanPropagate([%s]==[%s]=>[%s]) => %s",
  270. this, source, property, NS_ConvertUTF16toUTF8(target).get(),
  271. result ? "true" : "false"));
  272. }
  273. return result;
  274. }
  275. void
  276. nsRDFPropertyTestNode::Retract(nsIRDFResource* aSource,
  277. nsIRDFResource* aProperty,
  278. nsIRDFNode* aTarget) const
  279. {
  280. if (aProperty == mProperty.get()) {
  281. if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
  282. const char* source;
  283. aSource->GetValueConst(&source);
  284. const char* property;
  285. aProperty->GetValueConst(&property);
  286. nsAutoString target;
  287. nsXULContentUtils::GetTextForNode(aTarget, target);
  288. MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
  289. ("nsRDFPropertyTestNode[%p]: Retract([%s]==[%s]=>[%s])",
  290. this, source, property, NS_ConvertUTF16toUTF8(target).get()));
  291. }
  292. mProcessor->RetractElement(Element(aSource, aProperty, aTarget));
  293. }
  294. }