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