Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / content / xul / templates / src / nsRDFPropertyTestNode.cpp
blob4b9e9fec6866c807d1c8515229668ebe9a2c0e80
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 * Chris Waterson <waterson@netscape.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include "nsRDFPropertyTestNode.h"
40 #include "nsString.h"
42 #include "prlog.h"
43 #ifdef PR_LOGGING
44 extern PRLogModuleInfo* gXULTemplateLog;
45 #include "nsIRDFLiteral.h"
46 #include "nsXULContentUtils.h"
47 #endif
49 nsRDFPropertyTestNode::nsRDFPropertyTestNode(TestNode* aParent,
50 nsXULTemplateQueryProcessorRDF* aProcessor,
51 nsIAtom* aSourceVariable,
52 nsIRDFResource* aProperty,
53 nsIAtom* aTargetVariable)
54 : nsRDFTestNode(aParent),
55 mProcessor(aProcessor),
56 mSourceVariable(aSourceVariable),
57 mSource(nsnull),
58 mProperty(aProperty),
59 mTargetVariable(aTargetVariable),
60 mTarget(nsnull)
62 #ifdef PR_LOGGING
63 if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
64 const char* prop = "(null)";
65 if (aProperty)
66 aProperty->GetValueConst(&prop);
68 nsAutoString svar(NS_LITERAL_STRING("(none)"));
69 if (mSourceVariable)
70 mSourceVariable->ToString(svar);
72 nsAutoString tvar(NS_LITERAL_STRING("(none)"));
73 if (mTargetVariable)
74 mTargetVariable->ToString(tvar);
76 PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
77 ("nsRDFPropertyTestNode[%p]: parent=%p source=%s property=%s target=%s",
78 this, aParent, NS_ConvertUTF16toUTF8(svar).get(), prop, NS_ConvertUTF16toUTF8(tvar).get()));
80 #endif
84 nsRDFPropertyTestNode::nsRDFPropertyTestNode(TestNode* aParent,
85 nsXULTemplateQueryProcessorRDF* aProcessor,
86 nsIRDFResource* aSource,
87 nsIRDFResource* aProperty,
88 nsIAtom* aTargetVariable)
89 : nsRDFTestNode(aParent),
90 mProcessor(aProcessor),
91 mSourceVariable(0),
92 mSource(aSource),
93 mProperty(aProperty),
94 mTargetVariable(aTargetVariable),
95 mTarget(nsnull)
97 #ifdef PR_LOGGING
98 if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
99 const char* source = "(null)";
100 if (aSource)
101 aSource->GetValueConst(&source);
103 const char* prop = "(null)";
104 if (aProperty)
105 aProperty->GetValueConst(&prop);
107 nsAutoString tvar(NS_LITERAL_STRING("(none)"));
108 if (mTargetVariable)
109 mTargetVariable->ToString(tvar);
111 PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
112 ("nsRDFPropertyTestNode[%p]: parent=%p source=%s property=%s target=%s",
113 this, aParent, source, prop, NS_ConvertUTF16toUTF8(tvar).get()));
115 #endif
119 nsRDFPropertyTestNode::nsRDFPropertyTestNode(TestNode* aParent,
120 nsXULTemplateQueryProcessorRDF* aProcessor,
121 nsIAtom* aSourceVariable,
122 nsIRDFResource* aProperty,
123 nsIRDFNode* aTarget)
124 : nsRDFTestNode(aParent),
125 mProcessor(aProcessor),
126 mSourceVariable(aSourceVariable),
127 mSource(nsnull),
128 mProperty(aProperty),
129 mTargetVariable(0),
130 mTarget(aTarget)
132 #ifdef PR_LOGGING
133 if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
134 nsAutoString svar(NS_LITERAL_STRING("(none)"));
135 if (mSourceVariable)
136 mSourceVariable->ToString(svar);
138 const char* prop = "(null)";
139 if (aProperty)
140 aProperty->GetValueConst(&prop);
142 nsAutoString target;
143 nsXULContentUtils::GetTextForNode(aTarget, target);
145 PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
146 ("nsRDFPropertyTestNode[%p]: parent=%p source=%s property=%s target=%s",
147 this, aParent, NS_ConvertUTF16toUTF8(svar).get(), prop, NS_ConvertUTF16toUTF8(target).get()));
149 #endif
153 nsresult
154 nsRDFPropertyTestNode::FilterInstantiations(InstantiationSet& aInstantiations,
155 PRBool* aCantHandleYet) const
157 nsresult rv;
159 if (aCantHandleYet)
160 *aCantHandleYet = PR_FALSE;
162 nsIRDFDataSource* ds = mProcessor->GetDataSource();
164 InstantiationSet::Iterator last = aInstantiations.Last();
165 for (InstantiationSet::Iterator inst = aInstantiations.First(); inst != last; ++inst) {
166 PRBool hasSourceBinding;
167 nsCOMPtr<nsIRDFResource> sourceRes;
169 if (mSource) {
170 hasSourceBinding = PR_TRUE;
171 sourceRes = mSource;
173 else {
174 nsCOMPtr<nsIRDFNode> sourceValue;
175 hasSourceBinding = inst->mAssignments.GetAssignmentFor(mSourceVariable,
176 getter_AddRefs(sourceValue));
177 sourceRes = do_QueryInterface(sourceValue);
180 PRBool hasTargetBinding;
181 nsCOMPtr<nsIRDFNode> targetValue;
183 if (mTarget) {
184 hasTargetBinding = PR_TRUE;
185 targetValue = mTarget;
187 else {
188 hasTargetBinding = inst->mAssignments.GetAssignmentFor(mTargetVariable,
189 getter_AddRefs(targetValue));
192 #ifdef PR_LOGGING
193 if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
194 const char* source = "(unbound)";
195 if (hasSourceBinding)
196 sourceRes->GetValueConst(&source);
198 nsAutoString target(NS_LITERAL_STRING("(unbound)"));
199 if (hasTargetBinding)
200 nsXULContentUtils::GetTextForNode(targetValue, target);
202 PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
203 ("nsRDFPropertyTestNode[%p]: FilterInstantiations() source=[%s] target=[%s]",
204 this, source, NS_ConvertUTF16toUTF8(target).get()));
206 #endif
208 if (hasSourceBinding && hasTargetBinding) {
209 // it's a consistency check. see if we have a assignment that is consistent
210 PRBool hasAssertion;
211 rv = ds->HasAssertion(sourceRes, mProperty, targetValue,
212 PR_TRUE, &hasAssertion);
213 if (NS_FAILED(rv)) return rv;
215 #ifdef PR_LOGGING
216 PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
217 (" consistency check => %s", hasAssertion ? "passed" : "failed"));
218 #endif
220 if (hasAssertion) {
221 // it's consistent.
222 Element* element =
223 nsRDFPropertyTestNode::Element::Create(sourceRes,
224 mProperty,
225 targetValue);
227 if (! element)
228 return NS_ERROR_OUT_OF_MEMORY;
230 inst->AddSupportingElement(element);
232 else {
233 // it's inconsistent. remove it.
234 aInstantiations.Erase(inst--);
237 else if ((hasSourceBinding && ! hasTargetBinding) ||
238 (! hasSourceBinding && hasTargetBinding)) {
239 // it's an open ended query on the source or
240 // target. figure out what matches and add as a
241 // cross-product.
242 nsCOMPtr<nsISimpleEnumerator> results;
243 if (hasSourceBinding) {
244 rv = ds->GetTargets(sourceRes,
245 mProperty,
246 PR_TRUE,
247 getter_AddRefs(results));
249 else {
250 rv = ds->GetSources(mProperty,
251 targetValue,
252 PR_TRUE,
253 getter_AddRefs(results));
254 if (NS_FAILED(rv)) return rv;
257 while (1) {
258 PRBool hasMore;
259 rv = results->HasMoreElements(&hasMore);
260 if (NS_FAILED(rv)) return rv;
262 if (! hasMore)
263 break;
265 nsCOMPtr<nsISupports> isupports;
266 rv = results->GetNext(getter_AddRefs(isupports));
267 if (NS_FAILED(rv)) return rv;
269 nsIAtom* variable;
270 nsCOMPtr<nsIRDFNode> value;
272 if (hasSourceBinding) {
273 variable = mTargetVariable;
275 value = do_QueryInterface(isupports);
276 NS_ASSERTION(value != nsnull, "target is not an nsIRDFNode");
278 #ifdef PR_LOGGING
279 if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
280 nsAutoString s(NS_LITERAL_STRING("(none found)"));
281 if (value)
282 nsXULContentUtils::GetTextForNode(value, s);
284 PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
285 (" target => %s", NS_ConvertUTF16toUTF8(s).get()));
287 #endif
289 if (! value) continue;
291 targetValue = value;
293 else {
294 variable = mSourceVariable;
296 nsCOMPtr<nsIRDFResource> source = do_QueryInterface(isupports);
297 NS_ASSERTION(source != nsnull, "source is not an nsIRDFResource");
299 #ifdef PR_LOGGING
300 if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
301 const char* s = "(none found)";
302 if (source)
303 source->GetValueConst(&s);
305 PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
306 (" source => %s", s));
308 #endif
310 if (! source) continue;
312 value = sourceRes = source;
315 // Copy the original instantiation, and add it to the
316 // instantiation set with the new assignment that we've
317 // introduced. Ownership will be transferred to the
318 Instantiation newinst = *inst;
319 newinst.AddAssignment(variable, value);
321 Element* element =
322 nsRDFPropertyTestNode::Element::Create(sourceRes,
323 mProperty,
324 targetValue);
326 if (! element)
327 return NS_ERROR_OUT_OF_MEMORY;
329 newinst.AddSupportingElement(element);
331 aInstantiations.Insert(inst, newinst);
334 // finally, remove the "under specified" instantiation.
335 aInstantiations.Erase(inst--);
337 else {
338 if (!aCantHandleYet) {
339 // Neither source nor target assignment!
340 return NS_ERROR_UNEXPECTED;
343 *aCantHandleYet = PR_TRUE;
344 return NS_OK;
348 return NS_OK;
351 PRBool
352 nsRDFPropertyTestNode::CanPropagate(nsIRDFResource* aSource,
353 nsIRDFResource* aProperty,
354 nsIRDFNode* aTarget,
355 Instantiation& aInitialBindings) const
357 PRBool result;
359 if ((mProperty.get() != aProperty) ||
360 (mSource && mSource.get() != aSource) ||
361 (mTarget && mTarget.get() != aTarget)) {
362 result = PR_FALSE;
364 else {
365 if (mSourceVariable)
366 aInitialBindings.AddAssignment(mSourceVariable, aSource);
368 if (mTargetVariable)
369 aInitialBindings.AddAssignment(mTargetVariable, aTarget);
371 result = PR_TRUE;
374 #ifdef PR_LOGGING
375 if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
376 const char* source;
377 aSource->GetValueConst(&source);
379 const char* property;
380 aProperty->GetValueConst(&property);
382 nsAutoString target;
383 nsXULContentUtils::GetTextForNode(aTarget, target);
385 PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
386 ("nsRDFPropertyTestNode[%p]: CanPropagate([%s]==[%s]=>[%s]) => %s",
387 this, source, property, NS_ConvertUTF16toUTF8(target).get(),
388 result ? "true" : "false"));
390 #endif
392 return result;
395 void
396 nsRDFPropertyTestNode::Retract(nsIRDFResource* aSource,
397 nsIRDFResource* aProperty,
398 nsIRDFNode* aTarget) const
400 if (aProperty == mProperty.get()) {
401 #ifdef PR_LOGGING
402 if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
403 const char* source;
404 aSource->GetValueConst(&source);
406 const char* property;
407 aProperty->GetValueConst(&property);
409 nsAutoString target;
410 nsXULContentUtils::GetTextForNode(aTarget, target);
412 PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
413 ("nsRDFPropertyTestNode[%p]: Retract([%s]==[%s]=>[%s])",
414 this, source, property, NS_ConvertUTF16toUTF8(target).get()));
416 #endif
418 mProcessor->RetractElement(Element(aSource, aProperty, aTarget));