1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/xul/templates/src/nsRDFPropertyTestNode.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,387 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsRDFPropertyTestNode.h" 1.10 +#include "nsString.h" 1.11 +#include "nsXULContentUtils.h" 1.12 + 1.13 +#include "prlog.h" 1.14 +#ifdef PR_LOGGING 1.15 +extern PRLogModuleInfo* gXULTemplateLog; 1.16 +#include "nsIRDFLiteral.h" 1.17 +#endif 1.18 + 1.19 +nsRDFPropertyTestNode::nsRDFPropertyTestNode(TestNode* aParent, 1.20 + nsXULTemplateQueryProcessorRDF* aProcessor, 1.21 + nsIAtom* aSourceVariable, 1.22 + nsIRDFResource* aProperty, 1.23 + nsIAtom* aTargetVariable) 1.24 + : nsRDFTestNode(aParent), 1.25 + mProcessor(aProcessor), 1.26 + mSourceVariable(aSourceVariable), 1.27 + mSource(nullptr), 1.28 + mProperty(aProperty), 1.29 + mTargetVariable(aTargetVariable), 1.30 + mTarget(nullptr) 1.31 +{ 1.32 +#ifdef PR_LOGGING 1.33 + if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) { 1.34 + const char* prop = "(null)"; 1.35 + if (aProperty) 1.36 + aProperty->GetValueConst(&prop); 1.37 + 1.38 + nsAutoString svar(NS_LITERAL_STRING("(none)")); 1.39 + if (mSourceVariable) 1.40 + mSourceVariable->ToString(svar); 1.41 + 1.42 + nsAutoString tvar(NS_LITERAL_STRING("(none)")); 1.43 + if (mTargetVariable) 1.44 + mTargetVariable->ToString(tvar); 1.45 + 1.46 + PR_LOG(gXULTemplateLog, PR_LOG_DEBUG, 1.47 + ("nsRDFPropertyTestNode[%p]: parent=%p source=%s property=%s target=%s", 1.48 + this, aParent, NS_ConvertUTF16toUTF8(svar).get(), prop, NS_ConvertUTF16toUTF8(tvar).get())); 1.49 + } 1.50 +#endif 1.51 +} 1.52 + 1.53 + 1.54 +nsRDFPropertyTestNode::nsRDFPropertyTestNode(TestNode* aParent, 1.55 + nsXULTemplateQueryProcessorRDF* aProcessor, 1.56 + nsIRDFResource* aSource, 1.57 + nsIRDFResource* aProperty, 1.58 + nsIAtom* aTargetVariable) 1.59 + : nsRDFTestNode(aParent), 1.60 + mProcessor(aProcessor), 1.61 + mSourceVariable(0), 1.62 + mSource(aSource), 1.63 + mProperty(aProperty), 1.64 + mTargetVariable(aTargetVariable), 1.65 + mTarget(nullptr) 1.66 +{ 1.67 +#ifdef PR_LOGGING 1.68 + if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) { 1.69 + const char* source = "(null)"; 1.70 + if (aSource) 1.71 + aSource->GetValueConst(&source); 1.72 + 1.73 + const char* prop = "(null)"; 1.74 + if (aProperty) 1.75 + aProperty->GetValueConst(&prop); 1.76 + 1.77 + nsAutoString tvar(NS_LITERAL_STRING("(none)")); 1.78 + if (mTargetVariable) 1.79 + mTargetVariable->ToString(tvar); 1.80 + 1.81 + PR_LOG(gXULTemplateLog, PR_LOG_DEBUG, 1.82 + ("nsRDFPropertyTestNode[%p]: parent=%p source=%s property=%s target=%s", 1.83 + this, aParent, source, prop, NS_ConvertUTF16toUTF8(tvar).get())); 1.84 + } 1.85 +#endif 1.86 +} 1.87 + 1.88 + 1.89 +nsRDFPropertyTestNode::nsRDFPropertyTestNode(TestNode* aParent, 1.90 + nsXULTemplateQueryProcessorRDF* aProcessor, 1.91 + nsIAtom* aSourceVariable, 1.92 + nsIRDFResource* aProperty, 1.93 + nsIRDFNode* aTarget) 1.94 + : nsRDFTestNode(aParent), 1.95 + mProcessor(aProcessor), 1.96 + mSourceVariable(aSourceVariable), 1.97 + mSource(nullptr), 1.98 + mProperty(aProperty), 1.99 + mTargetVariable(0), 1.100 + mTarget(aTarget) 1.101 +{ 1.102 +#ifdef PR_LOGGING 1.103 + if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) { 1.104 + nsAutoString svar(NS_LITERAL_STRING("(none)")); 1.105 + if (mSourceVariable) 1.106 + mSourceVariable->ToString(svar); 1.107 + 1.108 + const char* prop = "(null)"; 1.109 + if (aProperty) 1.110 + aProperty->GetValueConst(&prop); 1.111 + 1.112 + nsAutoString target; 1.113 + nsXULContentUtils::GetTextForNode(aTarget, target); 1.114 + 1.115 + PR_LOG(gXULTemplateLog, PR_LOG_DEBUG, 1.116 + ("nsRDFPropertyTestNode[%p]: parent=%p source=%s property=%s target=%s", 1.117 + this, aParent, NS_ConvertUTF16toUTF8(svar).get(), prop, NS_ConvertUTF16toUTF8(target).get())); 1.118 + } 1.119 +#endif 1.120 +} 1.121 + 1.122 + 1.123 +nsresult 1.124 +nsRDFPropertyTestNode::FilterInstantiations(InstantiationSet& aInstantiations, 1.125 + bool* aCantHandleYet) const 1.126 +{ 1.127 + nsresult rv; 1.128 + 1.129 + if (aCantHandleYet) 1.130 + *aCantHandleYet = false; 1.131 + 1.132 + nsIRDFDataSource* ds = mProcessor->GetDataSource(); 1.133 + 1.134 + InstantiationSet::Iterator last = aInstantiations.Last(); 1.135 + for (InstantiationSet::Iterator inst = aInstantiations.First(); inst != last; ++inst) { 1.136 + bool hasSourceBinding; 1.137 + nsCOMPtr<nsIRDFResource> sourceRes; 1.138 + 1.139 + if (mSource) { 1.140 + hasSourceBinding = true; 1.141 + sourceRes = mSource; 1.142 + } 1.143 + else { 1.144 + nsCOMPtr<nsIRDFNode> sourceValue; 1.145 + hasSourceBinding = inst->mAssignments.GetAssignmentFor(mSourceVariable, 1.146 + getter_AddRefs(sourceValue)); 1.147 + sourceRes = do_QueryInterface(sourceValue); 1.148 + } 1.149 + 1.150 + bool hasTargetBinding; 1.151 + nsCOMPtr<nsIRDFNode> targetValue; 1.152 + 1.153 + if (mTarget) { 1.154 + hasTargetBinding = true; 1.155 + targetValue = mTarget; 1.156 + } 1.157 + else { 1.158 + hasTargetBinding = inst->mAssignments.GetAssignmentFor(mTargetVariable, 1.159 + getter_AddRefs(targetValue)); 1.160 + } 1.161 + 1.162 +#ifdef PR_LOGGING 1.163 + if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) { 1.164 + const char* source = "(unbound)"; 1.165 + if (hasSourceBinding) 1.166 + sourceRes->GetValueConst(&source); 1.167 + 1.168 + nsAutoString target(NS_LITERAL_STRING("(unbound)")); 1.169 + if (hasTargetBinding) 1.170 + nsXULContentUtils::GetTextForNode(targetValue, target); 1.171 + 1.172 + PR_LOG(gXULTemplateLog, PR_LOG_DEBUG, 1.173 + ("nsRDFPropertyTestNode[%p]: FilterInstantiations() source=[%s] target=[%s]", 1.174 + this, source, NS_ConvertUTF16toUTF8(target).get())); 1.175 + } 1.176 +#endif 1.177 + 1.178 + if (hasSourceBinding && hasTargetBinding) { 1.179 + // it's a consistency check. see if we have a assignment that is consistent 1.180 + bool hasAssertion; 1.181 + rv = ds->HasAssertion(sourceRes, mProperty, targetValue, 1.182 + true, &hasAssertion); 1.183 + if (NS_FAILED(rv)) return rv; 1.184 + 1.185 +#ifdef PR_LOGGING 1.186 + PR_LOG(gXULTemplateLog, PR_LOG_DEBUG, 1.187 + (" consistency check => %s", hasAssertion ? "passed" : "failed")); 1.188 +#endif 1.189 + 1.190 + if (hasAssertion) { 1.191 + // it's consistent. 1.192 + Element* element = 1.193 + new nsRDFPropertyTestNode::Element(sourceRes, mProperty, 1.194 + targetValue); 1.195 + 1.196 + if (! element) 1.197 + return NS_ERROR_OUT_OF_MEMORY; 1.198 + 1.199 + inst->AddSupportingElement(element); 1.200 + } 1.201 + else { 1.202 + // it's inconsistent. remove it. 1.203 + aInstantiations.Erase(inst--); 1.204 + } 1.205 + } 1.206 + else if ((hasSourceBinding && ! hasTargetBinding) || 1.207 + (! hasSourceBinding && hasTargetBinding)) { 1.208 + // it's an open ended query on the source or 1.209 + // target. figure out what matches and add as a 1.210 + // cross-product. 1.211 + nsCOMPtr<nsISimpleEnumerator> results; 1.212 + if (hasSourceBinding) { 1.213 + rv = ds->GetTargets(sourceRes, 1.214 + mProperty, 1.215 + true, 1.216 + getter_AddRefs(results)); 1.217 + } 1.218 + else { 1.219 + rv = ds->GetSources(mProperty, 1.220 + targetValue, 1.221 + true, 1.222 + getter_AddRefs(results)); 1.223 + if (NS_FAILED(rv)) return rv; 1.224 + } 1.225 + 1.226 + while (1) { 1.227 + bool hasMore; 1.228 + rv = results->HasMoreElements(&hasMore); 1.229 + if (NS_FAILED(rv)) return rv; 1.230 + 1.231 + if (! hasMore) 1.232 + break; 1.233 + 1.234 + nsCOMPtr<nsISupports> isupports; 1.235 + rv = results->GetNext(getter_AddRefs(isupports)); 1.236 + if (NS_FAILED(rv)) return rv; 1.237 + 1.238 + nsIAtom* variable; 1.239 + nsCOMPtr<nsIRDFNode> value; 1.240 + 1.241 + if (hasSourceBinding) { 1.242 + variable = mTargetVariable; 1.243 + 1.244 + value = do_QueryInterface(isupports); 1.245 + NS_ASSERTION(value != nullptr, "target is not an nsIRDFNode"); 1.246 + 1.247 +#ifdef PR_LOGGING 1.248 + if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) { 1.249 + nsAutoString s(NS_LITERAL_STRING("(none found)")); 1.250 + if (value) 1.251 + nsXULContentUtils::GetTextForNode(value, s); 1.252 + 1.253 + PR_LOG(gXULTemplateLog, PR_LOG_DEBUG, 1.254 + (" target => %s", NS_ConvertUTF16toUTF8(s).get())); 1.255 + } 1.256 +#endif 1.257 + 1.258 + if (! value) continue; 1.259 + 1.260 + targetValue = value; 1.261 + } 1.262 + else { 1.263 + variable = mSourceVariable; 1.264 + 1.265 + nsCOMPtr<nsIRDFResource> source = do_QueryInterface(isupports); 1.266 + NS_ASSERTION(source != nullptr, "source is not an nsIRDFResource"); 1.267 + 1.268 +#ifdef PR_LOGGING 1.269 + if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) { 1.270 + const char* s = "(none found)"; 1.271 + if (source) 1.272 + source->GetValueConst(&s); 1.273 + 1.274 + PR_LOG(gXULTemplateLog, PR_LOG_DEBUG, 1.275 + (" source => %s", s)); 1.276 + } 1.277 +#endif 1.278 + 1.279 + if (! source) continue; 1.280 + 1.281 + value = sourceRes = source; 1.282 + } 1.283 + 1.284 + // Copy the original instantiation, and add it to the 1.285 + // instantiation set with the new assignment that we've 1.286 + // introduced. Ownership will be transferred to the 1.287 + Instantiation newinst = *inst; 1.288 + newinst.AddAssignment(variable, value); 1.289 + 1.290 + Element* element = 1.291 + new nsRDFPropertyTestNode::Element(sourceRes, mProperty, 1.292 + targetValue); 1.293 + 1.294 + if (! element) 1.295 + return NS_ERROR_OUT_OF_MEMORY; 1.296 + 1.297 + newinst.AddSupportingElement(element); 1.298 + 1.299 + aInstantiations.Insert(inst, newinst); 1.300 + } 1.301 + 1.302 + // finally, remove the "under specified" instantiation. 1.303 + aInstantiations.Erase(inst--); 1.304 + } 1.305 + else { 1.306 + if (!aCantHandleYet) { 1.307 + nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_TRIPLE_UNBOUND); 1.308 + // Neither source nor target assignment! 1.309 + return NS_ERROR_UNEXPECTED; 1.310 + } 1.311 + 1.312 + *aCantHandleYet = true; 1.313 + return NS_OK; 1.314 + } 1.315 + } 1.316 + 1.317 + return NS_OK; 1.318 +} 1.319 + 1.320 +bool 1.321 +nsRDFPropertyTestNode::CanPropagate(nsIRDFResource* aSource, 1.322 + nsIRDFResource* aProperty, 1.323 + nsIRDFNode* aTarget, 1.324 + Instantiation& aInitialBindings) const 1.325 +{ 1.326 + bool result; 1.327 + 1.328 + if ((mProperty.get() != aProperty) || 1.329 + (mSource && mSource.get() != aSource) || 1.330 + (mTarget && mTarget.get() != aTarget)) { 1.331 + result = false; 1.332 + } 1.333 + else { 1.334 + if (mSourceVariable) 1.335 + aInitialBindings.AddAssignment(mSourceVariable, aSource); 1.336 + 1.337 + if (mTargetVariable) 1.338 + aInitialBindings.AddAssignment(mTargetVariable, aTarget); 1.339 + 1.340 + result = true; 1.341 + } 1.342 + 1.343 +#ifdef PR_LOGGING 1.344 + if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) { 1.345 + const char* source; 1.346 + aSource->GetValueConst(&source); 1.347 + 1.348 + const char* property; 1.349 + aProperty->GetValueConst(&property); 1.350 + 1.351 + nsAutoString target; 1.352 + nsXULContentUtils::GetTextForNode(aTarget, target); 1.353 + 1.354 + PR_LOG(gXULTemplateLog, PR_LOG_DEBUG, 1.355 + ("nsRDFPropertyTestNode[%p]: CanPropagate([%s]==[%s]=>[%s]) => %s", 1.356 + this, source, property, NS_ConvertUTF16toUTF8(target).get(), 1.357 + result ? "true" : "false")); 1.358 + } 1.359 +#endif 1.360 + 1.361 + return result; 1.362 +} 1.363 + 1.364 +void 1.365 +nsRDFPropertyTestNode::Retract(nsIRDFResource* aSource, 1.366 + nsIRDFResource* aProperty, 1.367 + nsIRDFNode* aTarget) const 1.368 +{ 1.369 + if (aProperty == mProperty.get()) { 1.370 +#ifdef PR_LOGGING 1.371 + if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) { 1.372 + const char* source; 1.373 + aSource->GetValueConst(&source); 1.374 + 1.375 + const char* property; 1.376 + aProperty->GetValueConst(&property); 1.377 + 1.378 + nsAutoString target; 1.379 + nsXULContentUtils::GetTextForNode(aTarget, target); 1.380 + 1.381 + PR_LOG(gXULTemplateLog, PR_LOG_DEBUG, 1.382 + ("nsRDFPropertyTestNode[%p]: Retract([%s]==[%s]=>[%s])", 1.383 + this, source, property, NS_ConvertUTF16toUTF8(target).get())); 1.384 + } 1.385 +#endif 1.386 + 1.387 + mProcessor->RetractElement(Element(aSource, aProperty, aTarget)); 1.388 + } 1.389 +} 1.390 +