1 /*
2  * Copyright (c) 2011-2015, 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 
35 #define base CElement
36 
37 using std::string;
38 
getKind() const39 string CConfigurableDomains::getKind() const
40 {
41     return "ConfigurableDomains";
42 }
43 
childrenAreDynamic() const44 bool CConfigurableDomains::childrenAreDynamic() const
45 {
46     return true;
47 }
48 
49 // Ensure validity on whole domains from main blackboard
validate(const CParameterBlackboard * pMainBlackboard)50 void CConfigurableDomains::validate(const CParameterBlackboard *pMainBlackboard)
51 {
52     // Delegate to domains
53     size_t uiNbConfigurableDomains = getNbChildren();
54 
55     for (size_t child = 0; child < uiNbConfigurableDomains; child++) {
56 
57         CConfigurableDomain *pChildConfigurableDomain =
58             static_cast<CConfigurableDomain *>(getChild(child));
59 
60         pChildConfigurableDomain->validate(pMainBlackboard);
61     }
62 }
63 
64 // Configuration application if required
apply(CParameterBlackboard * pParameterBlackboard,CSyncerSet & syncerSet,bool bForce,core::Results & infos) const65 void CConfigurableDomains::apply(CParameterBlackboard *pParameterBlackboard, CSyncerSet &syncerSet,
66                                  bool bForce, core::Results &infos) const
67 {
68     /// Delegate to domains
69 
70     // Start with domains that can be synchronized all at once (with passed syncer set)
71     size_t uiNbConfigurableDomains = getNbChildren();
72 
73     for (size_t child = 0; child < uiNbConfigurableDomains; child++) {
74 
75         const CConfigurableDomain *pChildConfigurableDomain =
76             static_cast<const CConfigurableDomain *>(getChild(child));
77 
78         std::string info;
79         // Apply and collect syncers when relevant
80         pChildConfigurableDomain->apply(pParameterBlackboard, &syncerSet, bForce, info);
81 
82         if (!info.empty()) {
83             infos.push_back(info);
84         }
85     }
86     // Synchronize those collected syncers
87     syncerSet.sync(*pParameterBlackboard, false, NULL);
88 
89     // Then deal with domains that need to synchronize along apply
90     for (size_t child = 0; child < uiNbConfigurableDomains; child++) {
91 
92         const CConfigurableDomain *pChildConfigurableDomain =
93             static_cast<const CConfigurableDomain *>(getChild(child));
94 
95         std::string info;
96         // Apply and synchronize when relevant
97         pChildConfigurableDomain->apply(pParameterBlackboard, NULL, bForce, info);
98         if (!info.empty()) {
99             infos.push_back(info);
100         }
101     }
102 }
103 
104 // From IXmlSource
toXml(CXmlElement & xmlElement,CXmlSerializingContext & serializingContext) const105 void CConfigurableDomains::toXml(CXmlElement &xmlElement,
106                                  CXmlSerializingContext &serializingContext) const
107 {
108     // Set attribute
109     xmlElement.setAttribute("SystemClassName", getName());
110 
111     base::childrenToXml(xmlElement, serializingContext);
112 }
113 
114 // Configuration/Domains handling
115 /// Domains
createDomain(const string & strName,string & strError)116 bool CConfigurableDomains::createDomain(const string &strName, string &strError)
117 {
118     // Already exists?
119     if (findChild(strName)) {
120 
121         strError = "Already existing configurable domain";
122 
123         return false;
124     }
125 
126     // Creation/Hierarchy
127     addChild(new CConfigurableDomain(strName));
128 
129     return true;
130 }
131 
addDomain(CConfigurableDomain & domain,bool bOverwrite,string & strError)132 bool CConfigurableDomains::addDomain(CConfigurableDomain &domain, bool bOverwrite, string &strError)
133 {
134     string strErrorDrop;
135 
136     string strDomainName(domain.getName());
137     CConfigurableDomain *pExistingDomain = findConfigurableDomain(strDomainName, strErrorDrop);
138 
139     if (pExistingDomain) {
140         if (!bOverwrite) {
141             strError = "Can't add domain \"" + strDomainName +
142                        "\" because it already exists and overwrite was not requested.";
143             return false;
144         }
145 
146         deleteDomain(*pExistingDomain);
147     }
148 
149     addChild(&domain);
150 
151     return true;
152 }
153 
deleteDomain(CConfigurableDomain & configurableDomain)154 void CConfigurableDomains::deleteDomain(CConfigurableDomain &configurableDomain)
155 {
156     removeChild(&configurableDomain);
157 
158     delete &configurableDomain;
159 }
160 
deleteDomain(const string & strName,string & strError)161 bool CConfigurableDomains::deleteDomain(const string &strName, string &strError)
162 {
163     CConfigurableDomain *pConfigurableDomain = findConfigurableDomain(strName, strError);
164 
165     if (pConfigurableDomain) {
166         deleteDomain(*pConfigurableDomain);
167         return true;
168     }
169 
170     return false;
171 }
172 
deleteAllDomains()173 void CConfigurableDomains::deleteAllDomains()
174 {
175     // remove Children
176     clean();
177 }
178 
renameDomain(const string & strName,const string & strNewName,string & strError)179 bool CConfigurableDomains::renameDomain(const string &strName, const string &strNewName,
180                                         string &strError)
181 {
182     CConfigurableDomain *pConfigurableDomain = findConfigurableDomain(strName, strError);
183 
184     if (!pConfigurableDomain) {
185 
186         return false;
187     }
188 
189     // Rename
190     return pConfigurableDomain->rename(strNewName, strError);
191 }
192 
setSequenceAwareness(const string & strDomain,bool bSequenceAware,string & strError)193 bool CConfigurableDomains::setSequenceAwareness(const string &strDomain, bool bSequenceAware,
194                                                 string &strError)
195 {
196     CConfigurableDomain *pConfigurableDomain = findConfigurableDomain(strDomain, strError);
197 
198     if (!pConfigurableDomain) {
199 
200         return false;
201     }
202 
203     pConfigurableDomain->setSequenceAwareness(bSequenceAware);
204 
205     return true;
206 }
207 
getSequenceAwareness(const string & strDomain,bool & bSequenceAware,string & strError) const208 bool CConfigurableDomains::getSequenceAwareness(const string &strDomain, bool &bSequenceAware,
209                                                 string &strError) const
210 {
211     const CConfigurableDomain *pConfigurableDomain = findConfigurableDomain(strDomain, strError);
212 
213     if (!pConfigurableDomain) {
214 
215         return false;
216     }
217 
218     bSequenceAware = pConfigurableDomain->getSequenceAwareness();
219 
220     return true;
221 }
222 
223 /// Configurations
listConfigurations(const string & strDomain,string & strResult) const224 bool CConfigurableDomains::listConfigurations(const string &strDomain, string &strResult) const
225 {
226     const CConfigurableDomain *pConfigurableDomain = findConfigurableDomain(strDomain, strResult);
227 
228     if (!pConfigurableDomain) {
229 
230         return false;
231     }
232     // delegate
233     pConfigurableDomain->listChildren(strResult);
234 
235     return true;
236 }
237 
createConfiguration(const string & strDomain,const string & strConfiguration,const CParameterBlackboard * pMainBlackboard,string & strError)238 bool CConfigurableDomains::createConfiguration(const string &strDomain,
239                                                const string &strConfiguration,
240                                                const CParameterBlackboard *pMainBlackboard,
241                                                string &strError)
242 {
243     // Find domain
244     CConfigurableDomain *pConfigurableDomain = findConfigurableDomain(strDomain, strError);
245 
246     if (!pConfigurableDomain) {
247 
248         return false;
249     }
250     // Delegate
251     return pConfigurableDomain->createConfiguration(strConfiguration, pMainBlackboard, strError);
252 }
253 
deleteConfiguration(const string & strDomain,const string & strConfiguration,string & strError)254 bool CConfigurableDomains::deleteConfiguration(const string &strDomain,
255                                                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,
269                                                const string &strConfigurationName,
270                                                const string &strNewConfigurationName,
271                                                string &strError)
272 {
273     // Find domain
274     CConfigurableDomain *pConfigurableDomain = findConfigurableDomain(strDomain, strError);
275 
276     if (!pConfigurableDomain) {
277 
278         return false;
279     }
280     // Delegate
281     return pConfigurableDomain->renameConfiguration(strConfigurationName, strNewConfigurationName,
282                                                     strError);
283 }
284 
listDomainElements(const string & strDomain,string & strResult) const285 bool CConfigurableDomains::listDomainElements(const string &strDomain, string &strResult) const
286 {
287     // Find domain
288     const CConfigurableDomain *pConfigurableDomain = findConfigurableDomain(strDomain, strResult);
289 
290     if (!pConfigurableDomain) {
291 
292         return false;
293     }
294     // Delegate
295     pConfigurableDomain->listAssociatedToElements(strResult);
296 
297     return true;
298 }
299 
split(const string & domainName,CConfigurableElement * element,core::Results & infos)300 bool CConfigurableDomains::split(const string &domainName, CConfigurableElement *element,
301                                  core::Results &infos)
302 {
303     // Find domain
304     std::string error;
305     CConfigurableDomain *domain = findConfigurableDomain(domainName, error);
306 
307     if (domain == NULL) {
308 
309         infos.push_back(error);
310         return false;
311     }
312     // Delegate
313     domain->split(element, infos);
314 
315     return true;
316 }
317 
listAssociatedElements(string & strResult) const318 void CConfigurableDomains::listAssociatedElements(string &strResult) const
319 {
320     std::set<const CConfigurableElement *> configurableElementSet;
321 
322     // Get all owned configurable elements
323     gatherAllOwnedConfigurableElements(configurableElementSet);
324 
325     // Fill result
326     std::set<const CConfigurableElement *>::const_iterator it;
327 
328     for (it = configurableElementSet.begin(); it != configurableElementSet.end(); ++it) {
329 
330         const CConfigurableElement *pConfigurableElement = *it;
331 
332         string strAssociatedDomainList;
333 
334         pConfigurableElement->listAssociatedDomains(strAssociatedDomainList, false);
335 
336         strResult += pConfigurableElement->getPath() + " [" + strAssociatedDomainList + "]\n";
337     }
338 }
339 
listConflictingElements(string & strResult) const340 void CConfigurableDomains::listConflictingElements(string &strResult) const
341 {
342     std::set<const CConfigurableElement *> configurableElementSet;
343 
344     // Get all owned configurable elements
345     gatherAllOwnedConfigurableElements(configurableElementSet);
346 
347     // Fill result
348     std::set<const CConfigurableElement *>::const_iterator it;
349 
350     for (it = configurableElementSet.begin(); it != configurableElementSet.end(); ++it) {
351 
352         const CConfigurableElement *pConfigurableElement = *it;
353 
354         if (pConfigurableElement->getBelongingDomainCount() > 1) {
355 
356             string strBelongingDomainList;
357 
358             pConfigurableElement->listBelongingDomains(strBelongingDomainList, false);
359 
360             strResult += pConfigurableElement->getPath() + " contained in multiple domains: " +
361                          strBelongingDomainList + "\n";
362         }
363     }
364 }
365 
listDomains(string & strResult) const366 void CConfigurableDomains::listDomains(string &strResult) const
367 {
368     // List domains
369     size_t uiNbConfigurableDomains = getNbChildren();
370 
371     for (size_t child = 0; child < uiNbConfigurableDomains; child++) {
372 
373         const CConfigurableDomain *pChildConfigurableDomain =
374             static_cast<const CConfigurableDomain *>(getChild(child));
375 
376         // Name
377         strResult += pChildConfigurableDomain->getName();
378 
379         // Sequence awareness
380         if (pChildConfigurableDomain->getSequenceAwareness()) {
381 
382             strResult += " [sequence aware]";
383         }
384         strResult += "\n";
385     }
386 }
387 
388 // Gather configurable elements owned by any domain
gatherAllOwnedConfigurableElements(std::set<const CConfigurableElement * > & configurableElementSet) const389 void CConfigurableDomains::gatherAllOwnedConfigurableElements(
390     std::set<const CConfigurableElement *> &configurableElementSet) const
391 {
392     // Delegate to domains
393     size_t uiNbConfigurableDomains = getNbChildren();
394 
395     for (size_t child = 0; child < uiNbConfigurableDomains; child++) {
396 
397         const CConfigurableDomain *pChildConfigurableDomain =
398             static_cast<const CConfigurableDomain *>(getChild(child));
399 
400         pChildConfigurableDomain->gatherConfigurableElements(configurableElementSet);
401     }
402 }
403 
404 // Config restore
restoreConfiguration(const string & domainName,const string & configurationName,CParameterBlackboard * mainBlackboard,bool autoSync,core::Results & errors) const405 bool CConfigurableDomains::restoreConfiguration(const string &domainName,
406                                                 const string &configurationName,
407                                                 CParameterBlackboard *mainBlackboard, bool autoSync,
408                                                 core::Results &errors) const
409 {
410     string error;
411     // Find domain
412     const CConfigurableDomain *domain = findConfigurableDomain(domainName, error);
413 
414     if (domain == NULL) {
415 
416         errors.push_back(error);
417         return false;
418     }
419     // Delegate
420     return domain->restoreConfiguration(configurationName, mainBlackboard, autoSync, errors);
421 }
422 
423 // Config save
saveConfiguration(const string & strDomain,const string & strConfiguration,const CParameterBlackboard * pMainBlackboard,string & strError)424 bool CConfigurableDomains::saveConfiguration(const string &strDomain,
425                                              const string &strConfiguration,
426                                              const CParameterBlackboard *pMainBlackboard,
427                                              string &strError)
428 {
429     // Find domain
430     CConfigurableDomain *pConfigurableDomain = findConfigurableDomain(strDomain, strError);
431 
432     if (!pConfigurableDomain) {
433 
434         return false;
435     }
436     // Delegate
437     return pConfigurableDomain->saveConfiguration(strConfiguration, pMainBlackboard, strError);
438 }
439 
setElementSequence(const string & strDomain,const string & strConfiguration,const std::vector<string> & astrNewElementSequence,string & strError)440 bool CConfigurableDomains::setElementSequence(const string &strDomain,
441                                               const string &strConfiguration,
442                                               const std::vector<string> &astrNewElementSequence,
443                                               string &strError)
444 {
445     // Find domain
446     CConfigurableDomain *pConfigurableDomain = findConfigurableDomain(strDomain, strError);
447 
448     if (!pConfigurableDomain) {
449 
450         return false;
451     }
452 
453     // Delegate to domain
454     return pConfigurableDomain->setElementSequence(strConfiguration, astrNewElementSequence,
455                                                    strError);
456 }
457 
getElementSequence(const string & strDomain,const string & strConfiguration,string & strResult) const458 bool CConfigurableDomains::getElementSequence(const string &strDomain,
459                                               const string &strConfiguration,
460                                               string &strResult) const
461 {
462     // Find domain
463     const CConfigurableDomain *pConfigurableDomain = findConfigurableDomain(strDomain, strResult);
464 
465     if (!pConfigurableDomain) {
466 
467         return false;
468     }
469     // Delegate to domain
470     return pConfigurableDomain->getElementSequence(strConfiguration, strResult);
471 }
472 
setApplicationRule(const string & strDomain,const string & strConfiguration,const string & strApplicationRule,const CSelectionCriteriaDefinition * pSelectionCriteriaDefinition,string & strError)473 bool CConfigurableDomains::setApplicationRule(
474     const string &strDomain, const string &strConfiguration, const string &strApplicationRule,
475     const CSelectionCriteriaDefinition *pSelectionCriteriaDefinition, string &strError)
476 {
477     CConfigurableDomain *pConfigurableDomain = findConfigurableDomain(strDomain, strError);
478 
479     if (!pConfigurableDomain) {
480 
481         return false;
482     }
483 
484     // Delegate to domain
485     return pConfigurableDomain->setApplicationRule(strConfiguration, strApplicationRule,
486                                                    pSelectionCriteriaDefinition, strError);
487 }
488 
clearApplicationRule(const string & strDomain,const string & strConfiguration,string & strError)489 bool CConfigurableDomains::clearApplicationRule(const string &strDomain,
490                                                 const string &strConfiguration, string &strError)
491 {
492     CConfigurableDomain *pConfigurableDomain = findConfigurableDomain(strDomain, strError);
493 
494     if (!pConfigurableDomain) {
495 
496         return false;
497     }
498 
499     // Delegate to domain
500     return pConfigurableDomain->clearApplicationRule(strConfiguration, strError);
501 }
502 
getApplicationRule(const string & strDomain,const string & strConfiguration,string & strResult) const503 bool CConfigurableDomains::getApplicationRule(const string &strDomain,
504                                               const string &strConfiguration,
505                                               string &strResult) const
506 {
507     const CConfigurableDomain *pConfigurableDomain = findConfigurableDomain(strDomain, strResult);
508 
509     if (!pConfigurableDomain) {
510 
511         return false;
512     }
513 
514     // Delegate to domain
515     return pConfigurableDomain->getApplicationRule(strConfiguration, strResult);
516 }
517 
518 // Last applied configurations
listLastAppliedConfigurations(string & strResult) const519 void CConfigurableDomains::listLastAppliedConfigurations(string &strResult) const
520 {
521     // Browse domains
522     size_t uiNbConfigurableDomains = getNbChildren();
523 
524     for (size_t child = 0; child < uiNbConfigurableDomains; child++) {
525 
526         const CConfigurableDomain *pChildConfigurableDomain =
527             static_cast<const CConfigurableDomain *>(getChild(child));
528 
529         strResult += pChildConfigurableDomain->getName() + ": " +
530                      pChildConfigurableDomain->getLastAppliedConfigurationName() + " [" +
531                      pChildConfigurableDomain->getPendingConfigurationName() + "]\n";
532     }
533 }
534 
535 // Configurable element - domain association
addConfigurableElementToDomain(const string & domainName,CConfigurableElement * element,const CParameterBlackboard * mainBlackboard,core::Results & infos)536 bool CConfigurableDomains::addConfigurableElementToDomain(
537     const string &domainName, CConfigurableElement *element,
538     const CParameterBlackboard *mainBlackboard, core::Results &infos)
539 {
540     // Find domain
541     std::string error;
542     CConfigurableDomain *domain = findConfigurableDomain(domainName, error);
543 
544     if (domain == NULL) {
545 
546         infos.push_back(error);
547         return false;
548     }
549     // Delegate
550     return domain->addConfigurableElement(element, mainBlackboard, infos);
551 }
552 
removeConfigurableElementFromDomain(const string & strDomain,CConfigurableElement * pConfigurableElement,string & strError)553 bool CConfigurableDomains::removeConfigurableElementFromDomain(
554     const string &strDomain, CConfigurableElement *pConfigurableElement, string &strError)
555 {
556     // Find domain
557     CConfigurableDomain *pConfigurableDomain = findConfigurableDomain(strDomain, strError);
558 
559     if (!pConfigurableDomain) {
560 
561         return false;
562     }
563     // Delegate
564     return pConfigurableDomain->removeConfigurableElement(pConfigurableElement, strError);
565 }
566 
findConfigurationBlackboard(const string & strDomain,const string & strConfiguration,const CConfigurableElement * pConfigurableElement,size_t & baseOffset,bool & bIsLastApplied,string & strError) const567 CParameterBlackboard *CConfigurableDomains::findConfigurationBlackboard(
568     const string &strDomain, const string &strConfiguration,
569     const CConfigurableElement *pConfigurableElement, size_t &baseOffset, bool &bIsLastApplied,
570     string &strError) const
571 {
572     // Find domain
573     const CConfigurableDomain *pConfigurableDomain = findConfigurableDomain(strDomain, strError);
574 
575     if (!pConfigurableDomain) {
576 
577         return NULL;
578     }
579 
580     // Check that element belongs to the domain
581     if (!pConfigurableElement->belongsTo(pConfigurableDomain)) {
582 
583         strError = "Element \"" + pConfigurableElement->getPath() +
584                    "\" does not belong to domain \"" + strDomain + "\"";
585 
586         return NULL;
587     }
588 
589     // Find Configuration Blackboard and Base Offset
590     return pConfigurableDomain->findConfigurationBlackboard(strConfiguration, pConfigurableElement,
591                                                             baseOffset, bIsLastApplied, strError);
592 }
593 
594 // Domain retrieval
findConfigurableDomain(const string & strDomain,string & strError)595 CConfigurableDomain *CConfigurableDomains::findConfigurableDomain(const string &strDomain,
596                                                                   string &strError)
597 {
598     // Call the const equivalent
599     return const_cast<CConfigurableDomain *>(
600         static_cast<const CConfigurableDomains *>(this)->findConfigurableDomain(strDomain,
601                                                                                 strError));
602 }
603 
findConfigurableDomain(const string & strDomain,string & strError) const604 const CConfigurableDomain *CConfigurableDomains::findConfigurableDomain(const string &strDomain,
605                                                                         string &strError) const
606 {
607     // Find domain
608     const CConfigurableDomain *pConfigurableDomain =
609         static_cast<const CConfigurableDomain *>(findChild(strDomain));
610 
611     if (!pConfigurableDomain) {
612 
613         strError = "Configurable domain " + strDomain + " not found";
614 
615         return NULL;
616     }
617 
618     return pConfigurableDomain;
619 }
620