1 /*
2  * Copyright (c) 2011-2014, Intel Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this
9  * list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation and/or
13  * other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  * may be used to endorse or promote products derived from this software without
17  * specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 #include <cassert>
31 #include "ConfigurableDomains.h"
32 #include "ConfigurableDomain.h"
33 #include "ConfigurableElement.h"
34 #include "BinaryStream.h"
35 #include "AutoLog.h"
36 
37 #define base CBinarySerializableElement
38 
39 using std::string;
40 
CConfigurableDomains()41 CConfigurableDomains::CConfigurableDomains()
42 {
43 }
44 
getKind() const45 string CConfigurableDomains::getKind() const
46 {
47     return "ConfigurableDomains";
48 }
49 
childrenAreDynamic() const50 bool CConfigurableDomains::childrenAreDynamic() const
51 {
52     return true;
53 }
54 
55 // Ensure validity on whole domains from main blackboard
validate(const CParameterBlackboard * pMainBlackboard)56 void CConfigurableDomains::validate(const CParameterBlackboard* pMainBlackboard)
57 {
58     // Delegate to domains
59     size_t uiChild;
60     size_t uiNbConfigurableDomains = getNbChildren();
61 
62     for (uiChild = 0; uiChild < uiNbConfigurableDomains; uiChild++) {
63 
64         CConfigurableDomain* pChildConfigurableDomain = static_cast<CConfigurableDomain*>(getChild(uiChild));
65 
66         pChildConfigurableDomain->validate(pMainBlackboard);
67     }
68 }
69 
70 // Configuration application if required
apply(CParameterBlackboard * pParameterBlackboard,CSyncerSet & syncerSet,bool bForce) const71 void CConfigurableDomains::apply(CParameterBlackboard* pParameterBlackboard, CSyncerSet& syncerSet, bool bForce) const
72 {
73    CAutoLog autoLog(this, "Applying configurations");
74 
75     /// Delegate to domains
76 
77     // Start with domains that can be synchronized all at once (with passed syncer set)
78     size_t uiChild;
79     size_t uiNbConfigurableDomains = getNbChildren();
80 
81     for (uiChild = 0; uiChild < uiNbConfigurableDomains; uiChild++) {
82 
83         const CConfigurableDomain* pChildConfigurableDomain = static_cast<const CConfigurableDomain*>(getChild(uiChild));
84 
85         // Apply and collect syncers when relevant
86         pChildConfigurableDomain->apply(pParameterBlackboard, &syncerSet, bForce);
87     }
88     // Synchronize those collected syncers
89     syncerSet.sync(*pParameterBlackboard, false, NULL);
90 
91     // Then deal with domains that need to synchronize along apply
92     for (uiChild = 0; uiChild < uiNbConfigurableDomains; uiChild++) {
93 
94         const CConfigurableDomain* pChildConfigurableDomain = static_cast<const CConfigurableDomain*>(getChild(uiChild));
95 
96         // Apply and synchronize when relevant
97         pChildConfigurableDomain->apply(pParameterBlackboard, NULL, bForce);
98     }
99 }
100 
101 // From IXmlSource
toXml(CXmlElement & xmlElement,CXmlSerializingContext & serializingContext) const102 void CConfigurableDomains::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
103 {
104     // Set attribute
105     xmlElement.setAttributeString("SystemClassName", getName());
106 
107     base::childrenToXml(xmlElement, serializingContext);
108 }
109 
110 // Configuration/Domains handling
111 /// Domains
createDomain(const string & strName,string & strError)112 bool CConfigurableDomains::createDomain(const string& strName, string& strError)
113 {
114     // Already exists?
115     if (findChild(strName)) {
116 
117         strError = "Already existing configurable domain";
118 
119         return false;
120     }
121 
122     log_info("Creating configurable domain \"%s\"", strName.c_str());
123 
124     // Creation/Hierarchy
125     addChild(new CConfigurableDomain(strName));
126 
127     return true;
128 }
129 
addDomain(CConfigurableDomain & domain,bool bOverwrite,string & strError)130 bool CConfigurableDomains::addDomain(CConfigurableDomain& domain, bool bOverwrite,
131                                      string& strError)
132 {
133     string strErrorDrop;
134 
135     string strDomainName(domain.getName());
136     CConfigurableDomain* pExistingDomain = findConfigurableDomain(strDomainName, strErrorDrop);
137 
138     if (pExistingDomain) {
139         if (!bOverwrite) {
140             strError = "Can't add domain \"" + strDomainName +
141                 "\" because it already exists and overwrite was not requested.";
142             return false;
143         }
144 
145         deleteDomain(*pExistingDomain);
146     }
147 
148     log_info("Adding configurable domain \"%s\"", strDomainName.c_str());
149 
150     addChild(&domain);
151 
152     return true;
153 }
154 
deleteDomain(CConfigurableDomain & configurableDomain)155 void CConfigurableDomains::deleteDomain(CConfigurableDomain& configurableDomain)
156 {
157     log_info("Deleting configurable domain \"%s\"", configurableDomain.getName().c_str() );
158 
159     removeChild(&configurableDomain);
160 
161     delete &configurableDomain;
162 }
163 
deleteDomain(const string & strName,string & strError)164 bool CConfigurableDomains::deleteDomain(const string& strName, string& strError)
165 {
166     CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strName, strError);
167 
168     if (pConfigurableDomain) {
169         deleteDomain(*pConfigurableDomain);
170         return true;
171     }
172 
173     return false;
174 }
175 
deleteAllDomains()176 void CConfigurableDomains::deleteAllDomains()
177 {
178     log_info("Deleting all configurable domains");
179 
180     //remove Children
181     clean();
182 }
183 
renameDomain(const string & strName,const string & strNewName,string & strError)184 bool CConfigurableDomains::renameDomain(const string& strName, const string& strNewName, string& strError)
185 {
186     CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strName, strError);
187 
188     if (!pConfigurableDomain) {
189 
190         return false;
191     }
192 
193     log_info("Renaming configurable domain \"%s\" to \"%s\"", strName.c_str(), strNewName.c_str());
194 
195     // Rename
196     return pConfigurableDomain->rename(strNewName, strError);
197 }
198 
setSequenceAwareness(const string & strDomain,bool bSequenceAware,string & strError)199 bool CConfigurableDomains::setSequenceAwareness(const string& strDomain, bool bSequenceAware, string& strError)
200 {
201     CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strError);
202 
203     if (!pConfigurableDomain) {
204 
205         return false;
206     }
207 
208     pConfigurableDomain->setSequenceAwareness(bSequenceAware);
209 
210     return true;
211 }
212 
getSequenceAwareness(const string & strDomain,bool & bSequenceAware,string & strError) const213 bool CConfigurableDomains::getSequenceAwareness(const string& strDomain, bool& bSequenceAware, string& strError) const
214 {
215     const CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strError);
216 
217     if (!pConfigurableDomain) {
218 
219         return false;
220     }
221 
222     bSequenceAware = pConfigurableDomain->getSequenceAwareness();
223 
224     return true;
225 }
226 
227 /// Configurations
listConfigurations(const string & strDomain,string & strResult) const228 bool CConfigurableDomains::listConfigurations(const string& strDomain, string& strResult) const
229 {
230     const CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strResult);
231 
232     if (!pConfigurableDomain) {
233 
234         return false;
235     }
236     // delegate
237     pConfigurableDomain->listChildren(strResult);
238 
239     return true;
240 }
241 
createConfiguration(const string & strDomain,const string & strConfiguration,const CParameterBlackboard * pMainBlackboard,string & strError)242 bool CConfigurableDomains::createConfiguration(const string& strDomain, const string& strConfiguration, const CParameterBlackboard* pMainBlackboard, string& strError)
243 {
244     // Find domain
245     CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strError);
246 
247     if (!pConfigurableDomain) {
248 
249         return false;
250     }
251     // Delegate
252     return pConfigurableDomain->createConfiguration(strConfiguration, pMainBlackboard, strError);
253 }
254 
deleteConfiguration(const string & strDomain,const string & strConfiguration,string & strError)255 bool CConfigurableDomains::deleteConfiguration(const string& strDomain, const string& strConfiguration, string& strError)
256 {
257     // Find domain
258     CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strError);
259 
260     if (!pConfigurableDomain) {
261 
262         return false;
263     }
264     // Delegate
265     return pConfigurableDomain->deleteConfiguration(strConfiguration, strError);
266 }
267 
renameConfiguration(const string & strDomain,const string & strConfigurationName,const string & strNewConfigurationName,string & strError)268 bool CConfigurableDomains::renameConfiguration(const string& strDomain, const string& strConfigurationName, const string& strNewConfigurationName, string& strError)
269 {
270     // Find domain
271     CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strError);
272 
273     if (!pConfigurableDomain) {
274 
275         return false;
276     }
277     // Delegate
278     return pConfigurableDomain->renameConfiguration(strConfigurationName, strNewConfigurationName, strError);
279 }
280 
listDomainElements(const string & strDomain,string & strResult) const281 bool CConfigurableDomains::listDomainElements(const string& strDomain, string& strResult) const
282 {
283     // Find domain
284     const CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strResult);
285 
286     if (!pConfigurableDomain) {
287 
288         return false;
289     }
290     // Delegate
291     pConfigurableDomain->listAssociatedToElements(strResult);
292 
293     return true;
294 }
295 
split(const string & strDomain,CConfigurableElement * pConfigurableElement,string & strError)296 bool CConfigurableDomains::split(const string& strDomain, CConfigurableElement* pConfigurableElement, string& strError)
297 {
298     // Find domain
299     CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strError);
300 
301     if (!pConfigurableDomain) {
302 
303         return false;
304     }
305     // Delegate
306     pConfigurableDomain->split(pConfigurableElement, strError);
307 
308     return true;
309 }
310 
listAssociatedElements(string & strResult) const311 void CConfigurableDomains::listAssociatedElements(string& strResult) const
312 {
313     strResult = "\n";
314 
315     std::set<const CConfigurableElement*> configurableElementSet;
316 
317     // Get all owned configurable elements
318     gatherAllOwnedConfigurableElements(configurableElementSet);
319 
320     // Fill result
321     std::set<const CConfigurableElement*>::const_iterator it;
322 
323     for (it = configurableElementSet.begin(); it != configurableElementSet.end(); ++it) {
324 
325         const CConfigurableElement* pConfigurableElement = *it;
326 
327         string strAssociatedDomainList;
328 
329         pConfigurableElement->listAssociatedDomains(strAssociatedDomainList, false);
330 
331         strResult += pConfigurableElement->getPath() + " [" + strAssociatedDomainList + "]\n";
332     }
333 }
334 
listConflictingElements(string & strResult) const335 void CConfigurableDomains::listConflictingElements(string& strResult) const
336 {
337     strResult = "\n";
338 
339     std::set<const CConfigurableElement*> configurableElementSet;
340 
341     // Get all owned configurable elements
342     gatherAllOwnedConfigurableElements(configurableElementSet);
343 
344     // Fill result
345     std::set<const CConfigurableElement*>::const_iterator it;
346 
347     for (it = configurableElementSet.begin(); it != configurableElementSet.end(); ++it) {
348 
349         const CConfigurableElement* pConfigurableElement = *it;
350 
351         if (pConfigurableElement->getBelongingDomainCount() > 1) {
352 
353             string strBelongingDomainList;
354 
355             pConfigurableElement->listBelongingDomains(strBelongingDomainList, false);
356 
357             strResult += pConfigurableElement->getPath() + " contained in multiple domains: " + strBelongingDomainList + "\n";
358         }
359     }
360 }
361 
listDomains(string & strResult) const362 void CConfigurableDomains::listDomains(string& strResult) const
363 {
364     strResult = "\n";
365 
366     // List domains
367     size_t uiChild;
368     size_t uiNbConfigurableDomains = getNbChildren();
369 
370     for (uiChild = 0; uiChild < uiNbConfigurableDomains; uiChild++) {
371 
372         const CConfigurableDomain* pChildConfigurableDomain = static_cast<const CConfigurableDomain*>(getChild(uiChild));
373 
374         // Name
375         strResult += pChildConfigurableDomain->getName();
376 
377         // Sequence awareness
378         if (pChildConfigurableDomain->getSequenceAwareness()) {
379 
380             strResult += " [sequence aware]";
381         }
382         strResult += "\n";
383     }
384 }
385 
386 // Gather configurable elements owned by any domain
gatherAllOwnedConfigurableElements(std::set<const CConfigurableElement * > & configurableElementSet) const387 void CConfigurableDomains::gatherAllOwnedConfigurableElements(std::set<const CConfigurableElement*>& configurableElementSet) const
388 {
389     // Delegate to domains
390     size_t uiChild;
391     size_t uiNbConfigurableDomains = getNbChildren();
392 
393     for (uiChild = 0; uiChild < uiNbConfigurableDomains; uiChild++) {
394 
395         const CConfigurableDomain* pChildConfigurableDomain = static_cast<const CConfigurableDomain*>(getChild(uiChild));
396 
397         pChildConfigurableDomain->gatherConfigurableElements(configurableElementSet);
398     }
399 }
400 
401 // Config restore
restoreConfiguration(const string & strDomain,const string & strConfiguration,CParameterBlackboard * pMainBlackboard,bool bAutoSync,std::list<string> & lstrError) const402 bool CConfigurableDomains::restoreConfiguration(const string& strDomain, const string& strConfiguration, CParameterBlackboard* pMainBlackboard, bool bAutoSync, std::list<string>& lstrError) const
403 {
404     string strError;
405     // Find domain
406     const CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strError);
407 
408     if (!pConfigurableDomain) {
409 
410         lstrError.push_back(strError);
411         return false;
412     }
413     // Delegate
414     return pConfigurableDomain->restoreConfiguration(strConfiguration, pMainBlackboard, bAutoSync, lstrError);
415 }
416 
417 // Config save
saveConfiguration(const string & strDomain,const string & strConfiguration,const CParameterBlackboard * pMainBlackboard,string & strError)418 bool CConfigurableDomains::saveConfiguration(const string& strDomain, const string& strConfiguration, const CParameterBlackboard* pMainBlackboard, string& strError)
419 {
420     // Find domain
421     CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strError);
422 
423     if (!pConfigurableDomain) {
424 
425         return false;
426     }
427     // Delegate
428     return pConfigurableDomain->saveConfiguration(strConfiguration, pMainBlackboard, strError);
429 }
430 
setElementSequence(const string & strDomain,const string & strConfiguration,const std::vector<string> & astrNewElementSequence,string & strError)431 bool CConfigurableDomains::setElementSequence(const string& strDomain, const string& strConfiguration, const std::vector<string>& astrNewElementSequence, string& strError)
432 {
433     // Find domain
434     CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strError);
435 
436     if (!pConfigurableDomain) {
437 
438         return false;
439     }
440 
441     // Delegate to domain
442     return pConfigurableDomain->setElementSequence(strConfiguration, astrNewElementSequence, strError);
443 }
444 
getElementSequence(const string & strDomain,const string & strConfiguration,string & strResult) const445 bool CConfigurableDomains::getElementSequence(const string& strDomain, const string& strConfiguration, string& strResult) const
446 {
447     // Find domain
448     const CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strResult);
449 
450     if (!pConfigurableDomain) {
451 
452         return false;
453     }
454     // Delegate to domain
455     return pConfigurableDomain->getElementSequence(strConfiguration, strResult);
456 }
457 
setApplicationRule(const string & strDomain,const string & strConfiguration,const string & strApplicationRule,const CSelectionCriteriaDefinition * pSelectionCriteriaDefinition,string & strError)458 bool CConfigurableDomains::setApplicationRule(const string& strDomain, const string& strConfiguration, const string& strApplicationRule, const CSelectionCriteriaDefinition* pSelectionCriteriaDefinition, string& strError)
459 {
460     CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strError);
461 
462     if (!pConfigurableDomain) {
463 
464         return false;
465     }
466 
467     // Delegate to domain
468     return pConfigurableDomain->setApplicationRule(strConfiguration, strApplicationRule, pSelectionCriteriaDefinition, strError);
469 }
470 
clearApplicationRule(const string & strDomain,const string & strConfiguration,string & strError)471 bool CConfigurableDomains::clearApplicationRule(const string& strDomain, const string& strConfiguration, string& strError)
472 {
473     CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strError);
474 
475     if (!pConfigurableDomain) {
476 
477         return false;
478     }
479 
480     // Delegate to domain
481     return pConfigurableDomain->clearApplicationRule(strConfiguration, strError);
482 }
483 
getApplicationRule(const string & strDomain,const string & strConfiguration,string & strResult) const484 bool CConfigurableDomains::getApplicationRule(const string& strDomain, const string& strConfiguration, string& strResult) const
485 {
486     const CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strResult);
487 
488     if (!pConfigurableDomain) {
489 
490         return false;
491     }
492 
493     // Delegate to domain
494     return pConfigurableDomain->getApplicationRule(strConfiguration, strResult);
495 }
496 
497 // Last applied configurations
listLastAppliedConfigurations(string & strResult) const498 void CConfigurableDomains::listLastAppliedConfigurations(string& strResult) const
499 {
500     // Browse domains
501     size_t uiChild;
502     size_t uiNbConfigurableDomains = getNbChildren();
503 
504     for (uiChild = 0; uiChild < uiNbConfigurableDomains; uiChild++) {
505 
506         const CConfigurableDomain* pChildConfigurableDomain = static_cast<const CConfigurableDomain*>(getChild(uiChild));
507 
508         strResult += pChildConfigurableDomain->getName() + ": " + pChildConfigurableDomain->getLastAppliedConfigurationName() + " [" + pChildConfigurableDomain->getPendingConfigurationName() + "]\n";
509     }
510 }
511 
512 // Configurable element - domain association
addConfigurableElementToDomain(const string & strDomain,CConfigurableElement * pConfigurableElement,const CParameterBlackboard * pMainBlackboard,string & strError)513 bool CConfigurableDomains::addConfigurableElementToDomain(const string& strDomain, CConfigurableElement* pConfigurableElement, const CParameterBlackboard* pMainBlackboard, string& strError)
514 {
515     // Find domain
516     CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strError);
517 
518     if (!pConfigurableDomain) {
519 
520         return false;
521     }
522     // Delegate
523     return pConfigurableDomain->addConfigurableElement(pConfigurableElement, pMainBlackboard, strError);
524 }
525 
removeConfigurableElementFromDomain(const string & strDomain,CConfigurableElement * pConfigurableElement,string & strError)526 bool CConfigurableDomains::removeConfigurableElementFromDomain(const string& strDomain, CConfigurableElement* pConfigurableElement, string& strError)
527 {
528     // Find domain
529     CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strError);
530 
531     if (!pConfigurableDomain) {
532 
533         return false;
534     }
535     // Delegate
536     return pConfigurableDomain->removeConfigurableElement(pConfigurableElement, strError);
537 }
538 
findConfigurationBlackboard(const string & strDomain,const string & strConfiguration,const CConfigurableElement * pConfigurableElement,uint32_t & uiBaseOffset,bool & bIsLastApplied,string & strError) const539 CParameterBlackboard* CConfigurableDomains::findConfigurationBlackboard(const string& strDomain,
540                                                        const string& strConfiguration,
541                                                        const CConfigurableElement* pConfigurableElement,
542                                                        uint32_t& uiBaseOffset,
543                                                        bool& bIsLastApplied,
544                                                        string& strError) const
545 {
546     log_info("Find configuration blackboard for Domain:%s, Configuration:%s, Element:%s",
547              strDomain.c_str(), strConfiguration.c_str(), pConfigurableElement->getPath().c_str());
548 
549     // Find domain
550     const CConfigurableDomain* pConfigurableDomain = findConfigurableDomain(strDomain, strError);
551 
552     if (!pConfigurableDomain) {
553 
554         return NULL;
555     }
556 
557     // Check that element belongs to the domain
558     if (!pConfigurableElement->belongsTo(pConfigurableDomain)) {
559 
560         strError = "Element \"" + pConfigurableElement->getPath() + "\" does not belong to domain \"" + strDomain + "\"";
561 
562         return NULL;
563     }
564 
565     // Find Configuration Blackboard and Base Offset
566     return pConfigurableDomain->findConfigurationBlackboard(strConfiguration, pConfigurableElement, uiBaseOffset, bIsLastApplied, strError);
567 }
568 
569 // Binary settings load/store
serializeSettings(const string & strBinarySettingsFilePath,bool bOut,uint8_t uiStructureChecksum,string & strError)570 bool CConfigurableDomains::serializeSettings(const string& strBinarySettingsFilePath, bool bOut, uint8_t uiStructureChecksum, string& strError)
571 {
572     // Instantiate byte stream
573     CBinaryStream binarySettingsStream(strBinarySettingsFilePath, bOut, getDataSize(), uiStructureChecksum);
574 
575     // Open file
576     if (!binarySettingsStream.open(strError)) {
577 
578         strError = "Unable to open binary settings file " + strBinarySettingsFilePath + ": " + strError;
579 
580         return false;
581     }
582 
583     // Serialize
584     binarySerialize(binarySettingsStream);
585 
586     // Close stream
587     binarySettingsStream.close();
588 
589     return true;
590 }
591 
592 // Domain retrieval
findConfigurableDomain(const string & strDomain,string & strError)593 CConfigurableDomain* CConfigurableDomains::findConfigurableDomain(const string& strDomain, string& strError)
594 {
595     // Call the const equivalent
596     return const_cast<CConfigurableDomain*>(
597         static_cast<const CConfigurableDomains*>(this)->findConfigurableDomain(strDomain, strError)
598         );
599 }
600 
findConfigurableDomain(const string & strDomain,string & strError) const601 const CConfigurableDomain* CConfigurableDomains::findConfigurableDomain(const string& strDomain, string& strError) const
602 {
603     // Find domain
604     const CConfigurableDomain* pConfigurableDomain = static_cast<const CConfigurableDomain*>(findChild(strDomain));
605 
606     if (!pConfigurableDomain) {
607 
608         strError = "Configurable domain " + strDomain + " not found";
609 
610         return NULL;
611     }
612 
613     return pConfigurableDomain;
614 }
615