• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ConfigurableDomain.h"
31  #include "DomainConfiguration.h"
32  #include "ConfigurableElement.h"
33  #include "ConfigurationAccessContext.h"
34  #include "XmlDomainSerializingContext.h"
35  #include "XmlDomainImportContext.h"
36  #include "XmlDomainExportContext.h"
37  #include "Utility.h"
38  #include "AlwaysAssert.hpp"
39  #include <cassert>
40  
41  #define base CElement
42  
43  using std::string;
44  
CConfigurableDomain(const string & strName)45  CConfigurableDomain::CConfigurableDomain(const string &strName) : base(strName)
46  {
47  }
48  
~CConfigurableDomain()49  CConfigurableDomain::~CConfigurableDomain()
50  {
51      // Remove all configurable elements
52      ConfigurableElementListIterator it;
53  
54      for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
55  
56          CConfigurableElement *pConfigurableElement = *it;
57  
58          // Remove from configurable element
59          pConfigurableElement->removeAttachedConfigurableDomain(this);
60      }
61  
62      // Remove all associated syncer sets
63      ConfigurableElementToSyncerSetMapIterator mapIt;
64  
65      for (mapIt = _configurableElementToSyncerSetMap.begin();
66           mapIt != _configurableElementToSyncerSetMap.end(); ++mapIt) {
67  
68          delete mapIt->second;
69      }
70  }
71  
getKind() const72  string CConfigurableDomain::getKind() const
73  {
74      return "ConfigurableDomain";
75  }
76  
childrenAreDynamic() const77  bool CConfigurableDomain::childrenAreDynamic() const
78  {
79      return true;
80  }
81  
82  // Content dumping
logValue(utility::ErrorContext &) const83  string CConfigurableDomain::logValue(utility::ErrorContext & /*ctx*/) const
84  {
85      return string("{") +
86  
87             "Sequence aware: " + (_bSequenceAware ? "yes" : "no") +
88  
89             ", Last applied configuration: " +
90             (_pLastAppliedConfiguration ? _pLastAppliedConfiguration->getName() : "<none>") +
91  
92             "}";
93  }
94  
95  // Sequence awareness
setSequenceAwareness(bool bSequenceAware)96  void CConfigurableDomain::setSequenceAwareness(bool bSequenceAware)
97  {
98      if (_bSequenceAware != bSequenceAware) {
99  
100          _bSequenceAware = bSequenceAware;
101      }
102  }
103  
getSequenceAwareness() const104  bool CConfigurableDomain::getSequenceAwareness() const
105  {
106      return _bSequenceAware;
107  }
108  
109  // From IXmlSource
toXml(CXmlElement & xmlElement,CXmlSerializingContext & serializingContext) const110  void CConfigurableDomain::toXml(CXmlElement &xmlElement,
111                                  CXmlSerializingContext &serializingContext) const
112  {
113      base::toXml(xmlElement, serializingContext);
114  
115      // Sequence awareness
116      xmlElement.setAttribute("SequenceAware", _bSequenceAware);
117  }
118  
childrenToXml(CXmlElement & xmlElement,CXmlSerializingContext & serializingContext) const119  void CConfigurableDomain::childrenToXml(CXmlElement &xmlElement,
120                                          CXmlSerializingContext &serializingContext) const
121  {
122      // Configurations
123      composeDomainConfigurations(xmlElement, serializingContext);
124  
125      // Configurable Elements
126      composeConfigurableElements(xmlElement);
127  
128      // Settings
129      composeSettings(xmlElement, static_cast<CXmlDomainExportContext &>(serializingContext));
130  }
131  
132  // XML composing
composeDomainConfigurations(CXmlElement & xmlElement,CXmlSerializingContext & serializingContext) const133  void CConfigurableDomain::composeDomainConfigurations(
134      CXmlElement &xmlElement, CXmlSerializingContext &serializingContext) const
135  {
136      // Create Configurations element
137      CXmlElement xmlConfigurationsElement;
138  
139      xmlElement.createChild(xmlConfigurationsElement, "Configurations");
140  
141      // Delegate to base
142      base::childrenToXml(xmlConfigurationsElement, serializingContext);
143  }
144  
composeConfigurableElements(CXmlElement & xmlElement) const145  void CConfigurableDomain::composeConfigurableElements(CXmlElement &xmlElement) const
146  {
147      // Create ConfigurableElements element
148      CXmlElement xmlConfigurableElementsElement;
149  
150      xmlElement.createChild(xmlConfigurableElementsElement, "ConfigurableElements");
151  
152      // Serialize out all configurable elements settings
153      ConfigurableElementListIterator it;
154  
155      for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
156  
157          const CConfigurableElement *pConfigurableElement = *it;
158  
159          // Create corresponding XML child element
160          CXmlElement xmlChildConfigurableElement;
161  
162          xmlConfigurableElementsElement.createChild(xmlChildConfigurableElement,
163                                                     "ConfigurableElement");
164  
165          // Set Path attribute
166          xmlChildConfigurableElement.setAttribute("Path", pConfigurableElement->getPath());
167      }
168  }
169  
composeSettings(CXmlElement & xmlElement,CXmlDomainExportContext & context) const170  void CConfigurableDomain::composeSettings(CXmlElement &xmlElement,
171                                            CXmlDomainExportContext &context) const
172  {
173      if (!context.withSettings()) {
174  
175          return;
176      }
177  
178      // Create Settings element
179      CXmlElement xmlSettingsElement;
180  
181      xmlElement.createChild(xmlSettingsElement, "Settings");
182  
183      // Serialize out all configurations settings
184      size_t uiNbConfigurations = getNbChildren();
185      size_t uiChildConfiguration;
186  
187      for (uiChildConfiguration = 0; uiChildConfiguration < uiNbConfigurations;
188           uiChildConfiguration++) {
189  
190          const CDomainConfiguration *pDomainConfiguration =
191              static_cast<const CDomainConfiguration *>(getChild(uiChildConfiguration));
192  
193          // Create child xml element for that configuration
194          CXmlElement xmlConfigurationSettingsElement;
195  
196          xmlSettingsElement.createChild(xmlConfigurationSettingsElement,
197                                         pDomainConfiguration->getXmlElementName());
198  
199          // Set its name attribute
200          xmlConfigurationSettingsElement.setNameAttribute(pDomainConfiguration->getName());
201  
202          // Serialize out configuration settings
203          pDomainConfiguration->composeSettings(xmlConfigurationSettingsElement, context);
204      }
205  }
206  
207  // From IXmlSink
fromXml(const CXmlElement & xmlElement,CXmlSerializingContext & serializingContext)208  bool CConfigurableDomain::fromXml(const CXmlElement &xmlElement,
209                                    CXmlSerializingContext &serializingContext)
210  {
211      // Context
212      CXmlDomainImportContext &xmlDomainImportContext =
213          static_cast<CXmlDomainImportContext &>(serializingContext);
214  
215      // Sequence awareness (optional)
216      xmlElement.getAttribute("SequenceAware", _bSequenceAware);
217  
218      std::string name;
219      xmlElement.getAttribute("Name", name);
220      setName(name);
221  
222      // Local parsing. Do not dig
223      if (!parseDomainConfigurations(xmlElement, xmlDomainImportContext) ||
224          !parseConfigurableElements(xmlElement, xmlDomainImportContext) ||
225          !parseSettings(xmlElement, xmlDomainImportContext)) {
226  
227          return false;
228      }
229  
230      // All provided configurations are parsed
231      // Attempt validation on areas of non provided configurations for all configurable elements if
232      // required
233      if (xmlDomainImportContext.autoValidationRequired()) {
234  
235          autoValidateAll();
236      }
237  
238      return true;
239  }
240  
241  // XML parsing
parseDomainConfigurations(const CXmlElement & xmlElement,CXmlDomainImportContext & serializingContext)242  bool CConfigurableDomain::parseDomainConfigurations(const CXmlElement &xmlElement,
243                                                      CXmlDomainImportContext &serializingContext)
244  {
245      // We're supposedly clean
246      assert(_configurableElementList.empty());
247  
248      // Get Configurations element
249      CXmlElement xmlConfigurationsElement;
250  
251      xmlElement.getChildElement("Configurations", xmlConfigurationsElement);
252  
253      // Parse it and create domain configuration objects
254      return base::fromXml(xmlConfigurationsElement, serializingContext);
255  }
256  
257  // Parse configurable elements
parseConfigurableElements(const CXmlElement & xmlElement,CXmlDomainImportContext & serializingContext)258  bool CConfigurableDomain::parseConfigurableElements(const CXmlElement &xmlElement,
259                                                      CXmlDomainImportContext &serializingContext)
260  {
261      CSystemClass &systemClass = serializingContext.getSystemClass();
262  
263      // Get ConfigurableElements element
264      CXmlElement xmlConfigurableElementsElement;
265      xmlElement.getChildElement("ConfigurableElements", xmlConfigurableElementsElement);
266  
267      // Parse it and associate found configurable elements to it
268      CXmlElement::CChildIterator it(xmlConfigurableElementsElement);
269  
270      CXmlElement xmlConfigurableElementElement;
271  
272      while (it.next(xmlConfigurableElementElement)) {
273  
274          // Locate configurable element
275          string strConfigurableElementPath;
276          xmlConfigurableElementElement.getAttribute("Path", strConfigurableElementPath);
277  
278          CPathNavigator pathNavigator(strConfigurableElementPath);
279          string strError;
280  
281          // Is there an element and does it match system class name?
282          if (!pathNavigator.navigateThrough(systemClass.getName(), strError)) {
283  
284              serializingContext.setError(
285                  "Could not find configurable element of path " + strConfigurableElementPath +
286                  " from ConfigurableDomain description " + getName() + " (" + strError + ")");
287  
288              return false;
289          }
290          // Browse system class for configurable element
291          CConfigurableElement *pConfigurableElement =
292              static_cast<CConfigurableElement *>(systemClass.findDescendant(pathNavigator));
293  
294          if (!pConfigurableElement) {
295  
296              serializingContext.setError("Could not find configurable element of path " +
297                                          strConfigurableElementPath +
298                                          " from ConfigurableDomain description " + getName());
299  
300              return false;
301          }
302          // Add found element to domain
303          core::Results infos;
304          if (!addConfigurableElement(pConfigurableElement, NULL, infos)) {
305  
306              strError = utility::asString(infos);
307              serializingContext.setError(strError);
308  
309              return false;
310          }
311      }
312  
313      return true;
314  }
315  
316  // Parse settings
parseSettings(const CXmlElement & xmlElement,CXmlDomainImportContext & serializingContext)317  bool CConfigurableDomain::parseSettings(const CXmlElement &xmlElement,
318                                          CXmlDomainImportContext &serializingContext)
319  {
320      // Check we actually need to parse configuration settings
321      if (!serializingContext.withSettings()) {
322  
323          // No parsing required
324          return true;
325      }
326  
327      // Get Settings element
328      CXmlElement xmlSettingsElement;
329      if (!xmlElement.getChildElement("Settings", xmlSettingsElement)) {
330  
331          // No settings, bail out successfully
332          return true;
333      }
334  
335      // Parse configuration settings
336      CXmlElement::CChildIterator it(xmlSettingsElement);
337  
338      CXmlElement xmlConfigurationSettingsElement;
339  
340      while (it.next(xmlConfigurationSettingsElement)) {
341          // Get domain configuration
342          CDomainConfiguration *pDomainConfiguration = static_cast<CDomainConfiguration *>(
343              findChild(xmlConfigurationSettingsElement.getNameAttribute()));
344  
345          if (!pDomainConfiguration) {
346  
347              serializingContext.setError("Could not find domain configuration referred to by"
348                                          " configurable domain \"" +
349                                          getName() + "\".");
350  
351              return false;
352          }
353          // Have domain configuration parse settings for all configurable elements
354          if (!pDomainConfiguration->parseSettings(xmlConfigurationSettingsElement,
355                                                   serializingContext)) {
356  
357              return false;
358          }
359      }
360  
361      return true;
362  }
363  // Configurable elements association
addConfigurableElement(CConfigurableElement * pConfigurableElement,const CParameterBlackboard * pMainBlackboard,core::Results & infos)364  bool CConfigurableDomain::addConfigurableElement(CConfigurableElement *pConfigurableElement,
365                                                   const CParameterBlackboard *pMainBlackboard,
366                                                   core::Results &infos)
367  {
368      // Already associated?
369      if (containsConfigurableElement(pConfigurableElement)) {
370  
371          infos.push_back("Configurable element " + pConfigurableElement->getPath() +
372                          " already associated to configuration domain " + getName());
373  
374          return false;
375      }
376  
377      // Already owned?
378      if (pConfigurableElement->belongsTo(this)) {
379  
380          infos.push_back("Configurable element " + pConfigurableElement->getPath() +
381                          " already owned by configuration domain " + getName());
382  
383          return false;
384      }
385  
386      // Do add
387      doAddConfigurableElement(pConfigurableElement, infos, pMainBlackboard);
388  
389      return true;
390  }
391  
removeConfigurableElement(CConfigurableElement * pConfigurableElement,string & strError)392  bool CConfigurableDomain::removeConfigurableElement(CConfigurableElement *pConfigurableElement,
393                                                      string &strError)
394  {
395      // Not associated?
396      if (!containsConfigurableElement(pConfigurableElement)) {
397  
398          strError = "Configurable element " + pConfigurableElement->getPath() +
399                     " not associated to configuration domain " + getName();
400  
401          return false;
402      }
403  
404      // Do remove
405      doRemoveConfigurableElement(pConfigurableElement, true);
406  
407      return true;
408  }
409  
410  /**
411  * Blackboard Configuration and Base Offset retrieval.
412  *
413  * This method fetches the Blackboard associated to the ConfigurableElement
414  * given in parameter, for a specific Configuration. The ConfigurableElement
415  * must belong to the Domain. If a Blackboard is found, the base offset of
416  * the ConfigurableElement is returned as well. This base offset corresponds to
417  * the offset of the ancestor of the ConfigurableElement associated to the Configuration.
418  *
419  * @param[in] strConfiguration                           Name of the Configuration.
420  * @param[in] pCandidateDescendantConfigurableElement    Pointer to a CConfigurableElement that
421  *                                                       belongs to the Domain.
422  * @param[out] baseOffset                              The base offset of the CConfigurableElement.
423  * @param[out] bIsLastApplied                            Boolean indicating that the Configuration is
424  *                                                       the last one applied of the Domain.
425  * @param[out] strError                                  Error message
426  *
427  * return Pointer to the Blackboard of the Configuration.
428  */
findConfigurationBlackboard(const string & strConfiguration,const CConfigurableElement * pCandidateDescendantConfigurableElement,size_t & baseOffset,bool & bIsLastApplied,string & strError) const429  CParameterBlackboard *CConfigurableDomain::findConfigurationBlackboard(
430      const string &strConfiguration,
431      const CConfigurableElement *pCandidateDescendantConfigurableElement, size_t &baseOffset,
432      bool &bIsLastApplied, string &strError) const
433  {
434      // Find Configuration
435      const CDomainConfiguration *pDomainConfiguration =
436          static_cast<const CDomainConfiguration *>(findChild(strConfiguration));
437  
438      if (!pDomainConfiguration) {
439  
440          strError = "Domain configuration " + strConfiguration + " not found";
441  
442          return NULL;
443      }
444  
445      // Parse all configurable elements
446      ConfigurableElementListIterator it;
447  
448      for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
449  
450          const CConfigurableElement *pAssociatedConfigurableElement = *it;
451  
452          // Check if the the associated element is the configurable element or one of its ancestors
453          if ((pCandidateDescendantConfigurableElement == pAssociatedConfigurableElement) ||
454              (pCandidateDescendantConfigurableElement->isDescendantOf(
455                  pAssociatedConfigurableElement))) {
456  
457              baseOffset = pAssociatedConfigurableElement->getOffset();
458              bIsLastApplied = (pDomainConfiguration == _pLastAppliedConfiguration);
459  
460              return pDomainConfiguration->getBlackboard(pAssociatedConfigurableElement);
461          }
462      }
463  
464      strError = "Element not associated to the Domain";
465  
466      return NULL;
467  }
468  
469  // Domain splitting
split(CConfigurableElement * pConfigurableElement,core::Results & infos)470  bool CConfigurableDomain::split(CConfigurableElement *pConfigurableElement, core::Results &infos)
471  {
472      // Not associated?
473      if (!containsConfigurableElement(pConfigurableElement)) {
474  
475          std::string strError = "Configurable element " + pConfigurableElement->getPath() +
476                                 " not associated to configuration domain " + getName();
477          infos.push_back(strError);
478  
479          return false;
480      }
481  
482      // Create sub domain areas for all configurable element's children
483      size_t uiNbConfigurableElementChildren = pConfigurableElement->getNbChildren();
484  
485      if (!uiNbConfigurableElementChildren) {
486  
487          std::string strError = "Configurable element " + pConfigurableElement->getPath() +
488                                 " has no children to split configurable domain to";
489          infos.push_back(strError);
490  
491          return false;
492      }
493  
494      for (size_t uiChild = 0; uiChild < uiNbConfigurableElementChildren; uiChild++) {
495  
496          CConfigurableElement *pChildConfigurableElement =
497              static_cast<CConfigurableElement *>(pConfigurableElement->getChild(uiChild));
498  
499          doAddConfigurableElement(pChildConfigurableElement, infos);
500      }
501  
502      // Delegate to configurations
503      size_t uiNbConfigurations = getNbChildren();
504  
505      for (size_t uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
506  
507          CDomainConfiguration *pDomainConfiguration =
508              static_cast<CDomainConfiguration *>(getChild(uiChild));
509  
510          pDomainConfiguration->split(pConfigurableElement);
511      }
512  
513      // Remove given configurable element from this domain
514      // Note: we shouldn't need to recompute the sync set in that case, as the splitted element
515      // should include the syncers of its children elements
516      doRemoveConfigurableElement(pConfigurableElement, false);
517  
518      return true;
519  }
520  
521  // Check if there is a pending configuration for this domain: i.e. an applicable configuration
522  // different from the last applied configuration
getPendingConfiguration() const523  const CDomainConfiguration *CConfigurableDomain::getPendingConfiguration() const
524  {
525      const CDomainConfiguration *pApplicableDomainConfiguration =
526          findApplicableDomainConfiguration();
527  
528      if (pApplicableDomainConfiguration) {
529  
530          // Check not the last one before applying
531          if (!_pLastAppliedConfiguration ||
532              (_pLastAppliedConfiguration != pApplicableDomainConfiguration)) {
533  
534              return pApplicableDomainConfiguration;
535          }
536      }
537  
538      return NULL;
539  }
540  
541  // Configuration application if required
apply(CParameterBlackboard * pParameterBlackboard,CSyncerSet * pSyncerSet,bool bForce,std::string & strInfo) const542  void CConfigurableDomain::apply(CParameterBlackboard *pParameterBlackboard, CSyncerSet *pSyncerSet,
543                                  bool bForce, std::string &strInfo) const
544  {
545      // Apply configuration only if the blackboard will
546      // be synchronized either now or by syncerSet.
547      if (!pSyncerSet ^ _bSequenceAware) {
548          // The configuration can not be syncronised
549          return;
550      }
551  
552      if (bForce) {
553          // Force a configuration restore by forgetting about last applied configuration
554          _pLastAppliedConfiguration = NULL;
555      }
556      const CDomainConfiguration *pApplicableDomainConfiguration =
557          findApplicableDomainConfiguration();
558  
559      if (pApplicableDomainConfiguration) {
560  
561          // Check not the last one before applying
562          if (!_pLastAppliedConfiguration ||
563              _pLastAppliedConfiguration != pApplicableDomainConfiguration) {
564  
565              strInfo = "Applying configuration '" + pApplicableDomainConfiguration->getName() +
566                        "' from domain '" + getName() + "'";
567  
568              // Check if we need to synchronize during restore
569              bool bSync = !pSyncerSet && _bSequenceAware;
570  
571              // Do the restore
572              pApplicableDomainConfiguration->restore(pParameterBlackboard, bSync, NULL);
573  
574              // Record last applied configuration
575              _pLastAppliedConfiguration = pApplicableDomainConfiguration;
576  
577              // Check we need to provide syncer set to caller
578              if (pSyncerSet && !_bSequenceAware) {
579  
580                  // Since we applied changes, add our own sync set to the given one
581                  *pSyncerSet += _syncerSet;
582              }
583          }
584      }
585  }
586  
587  // Return applicable configuration validity for given configurable element
isApplicableConfigurationValid(const CConfigurableElement * pConfigurableElement) const588  bool CConfigurableDomain::isApplicableConfigurationValid(
589      const CConfigurableElement *pConfigurableElement) const
590  {
591      const CDomainConfiguration *pApplicableDomainConfiguration =
592          findApplicableDomainConfiguration();
593  
594      return pApplicableDomainConfiguration &&
595             pApplicableDomainConfiguration->isValid(pConfigurableElement);
596  }
597  
598  // In case configurable element was removed
computeSyncSet()599  void CConfigurableDomain::computeSyncSet()
600  {
601      // Clean sync set first
602      _syncerSet.clear();
603  
604      // Add syncer sets for all associated configurable elements
605      ConfigurableElementToSyncerSetMapIterator mapIt;
606  
607      for (mapIt = _configurableElementToSyncerSetMap.begin();
608           mapIt != _configurableElementToSyncerSetMap.end(); ++mapIt) {
609  
610          const CSyncerSet *pSyncerSet = mapIt->second;
611  
612          _syncerSet += *pSyncerSet;
613      }
614  }
615  
616  // Configuration Management
createConfiguration(const string & strName,const CParameterBlackboard * pMainBlackboard,string & strError)617  bool CConfigurableDomain::createConfiguration(const string &strName,
618                                                const CParameterBlackboard *pMainBlackboard,
619                                                string &strError)
620  {
621      // Already exists?
622      if (findChild(strName)) {
623  
624          strError = "Already existing configuration";
625  
626          return false;
627      }
628  
629      // Creation
630      CDomainConfiguration *pDomainConfiguration = new CDomainConfiguration(strName);
631  
632      // Configurable elements association
633      ConfigurableElementListIterator it;
634  
635      for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
636  
637          const CConfigurableElement *pConfigurableElement = *it;
638          ;
639  
640          // Retrieve associated syncer set
641          CSyncerSet *pSyncerSet = getSyncerSet(pConfigurableElement);
642  
643          // Associate to configuration
644          pDomainConfiguration->addConfigurableElement(pConfigurableElement, pSyncerSet);
645      }
646  
647      // Hierarchy
648      addChild(pDomainConfiguration);
649  
650      // Ensure validity of fresh new domain configuration
651      // Attempt auto validation, so that the user gets his/her own settings by defaults
652      if (!autoValidateConfiguration(pDomainConfiguration)) {
653  
654          // No valid configuration found to copy in from, validate againt main blackboard (will
655          // concerned remaining invalid parts)
656          pDomainConfiguration->validate(pMainBlackboard);
657      }
658  
659      return true;
660  }
661  
deleteConfiguration(const string & strName,string & strError)662  bool CConfigurableDomain::deleteConfiguration(const string &strName, string &strError)
663  {
664      CDomainConfiguration *pDomainConfiguration = findConfiguration(strName, strError);
665  
666      if (!pDomainConfiguration) {
667  
668          return false;
669      }
670  
671      // Was the last applied?
672      if (pDomainConfiguration == _pLastAppliedConfiguration) {
673  
674          // Forget about it
675          _pLastAppliedConfiguration = NULL;
676      }
677  
678      // Hierarchy
679      removeChild(pDomainConfiguration);
680  
681      // Destroy
682      delete pDomainConfiguration;
683  
684      return true;
685  }
686  
listAssociatedToElements(string & strResult) const687  void CConfigurableDomain::listAssociatedToElements(string &strResult) const
688  {
689      ConfigurableElementListIterator it;
690  
691      // Browse all configurable elements
692      for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
693  
694          const CConfigurableElement *pConfigurableElement = *it;
695  
696          strResult += pConfigurableElement->getPath() + "\n";
697      }
698  }
699  
renameConfiguration(const string & strName,const string & strNewName,string & strError)700  bool CConfigurableDomain::renameConfiguration(const string &strName, const string &strNewName,
701                                                string &strError)
702  {
703      CDomainConfiguration *pDomainConfiguration = findConfiguration(strName, strError);
704  
705      if (!pDomainConfiguration) {
706  
707          return false;
708      }
709  
710      // Rename
711      return pDomainConfiguration->rename(strNewName, strError);
712  }
713  
restoreConfiguration(const string & configurationName,CParameterBlackboard * mainBlackboard,bool autoSync,core::Results & errors) const714  bool CConfigurableDomain::restoreConfiguration(const string &configurationName,
715                                                 CParameterBlackboard *mainBlackboard, bool autoSync,
716                                                 core::Results &errors) const
717  {
718      string error;
719  
720      const CDomainConfiguration *configuration = findConfiguration(configurationName, error);
721  
722      if (configuration == NULL) {
723  
724          errors.push_back(error);
725          return false;
726      }
727  
728      // Delegate
729      bool bSuccess = configuration->restore(mainBlackboard, autoSync && _bSequenceAware, &errors);
730  
731      // Record last applied configuration
732      _pLastAppliedConfiguration = configuration;
733  
734      // Synchronize
735      if (autoSync && !_bSequenceAware) {
736  
737          bSuccess &= _syncerSet.sync(*mainBlackboard, false, &errors);
738      }
739      return bSuccess;
740  }
741  
saveConfiguration(const string & strName,const CParameterBlackboard * pMainBlackboard,string & strError)742  bool CConfigurableDomain::saveConfiguration(const string &strName,
743                                              const CParameterBlackboard *pMainBlackboard,
744                                              string &strError)
745  {
746      // Find Domain configuration
747      CDomainConfiguration *pDomainConfiguration = findConfiguration(strName, strError);
748  
749      if (!pDomainConfiguration) {
750  
751          return false;
752      }
753  
754      // Delegate
755      pDomainConfiguration->save(pMainBlackboard);
756  
757      return true;
758  }
759  
setElementSequence(const string & strConfiguration,const std::vector<string> & astrNewElementSequence,string & strError)760  bool CConfigurableDomain::setElementSequence(const string &strConfiguration,
761                                               const std::vector<string> &astrNewElementSequence,
762                                               string &strError)
763  {
764      // Find Domain configuration
765      CDomainConfiguration *pDomainConfiguration = findConfiguration(strConfiguration, strError);
766  
767      if (!pDomainConfiguration) {
768  
769          return false;
770      }
771  
772      // Delegate to configuration
773      return pDomainConfiguration->setElementSequence(astrNewElementSequence, strError);
774  }
775  
getElementSequence(const string & strConfiguration,string & strResult) const776  bool CConfigurableDomain::getElementSequence(const string &strConfiguration,
777                                               string &strResult) const
778  {
779      // Find Domain configuration
780      const CDomainConfiguration *pDomainConfiguration =
781          findConfiguration(strConfiguration, strResult);
782  
783      if (!pDomainConfiguration) {
784  
785          return false;
786      }
787  
788      // Delegate to configuration
789      pDomainConfiguration->getElementSequence(strResult);
790  
791      return true;
792  }
793  
setApplicationRule(const string & strConfiguration,const string & strApplicationRule,const CSelectionCriteriaDefinition * pSelectionCriteriaDefinition,string & strError)794  bool CConfigurableDomain::setApplicationRule(
795      const string &strConfiguration, const string &strApplicationRule,
796      const CSelectionCriteriaDefinition *pSelectionCriteriaDefinition, string &strError)
797  {
798      // Find Domain configuration
799      CDomainConfiguration *pDomainConfiguration = findConfiguration(strConfiguration, strError);
800  
801      if (!pDomainConfiguration) {
802  
803          return false;
804      }
805  
806      // Delegate to configuration
807      return pDomainConfiguration->setApplicationRule(strApplicationRule,
808                                                      pSelectionCriteriaDefinition, strError);
809  }
810  
clearApplicationRule(const string & strConfiguration,string & strError)811  bool CConfigurableDomain::clearApplicationRule(const string &strConfiguration, string &strError)
812  {
813      // Find Domain configuration
814      CDomainConfiguration *pDomainConfiguration = findConfiguration(strConfiguration, strError);
815  
816      if (!pDomainConfiguration) {
817  
818          return false;
819      }
820  
821      // Delegate to configuration
822      pDomainConfiguration->clearApplicationRule();
823  
824      return true;
825  }
826  
getApplicationRule(const string & strConfiguration,string & strResult) const827  bool CConfigurableDomain::getApplicationRule(const string &strConfiguration,
828                                               string &strResult) const
829  {
830      // Find Domain configuration
831      const CDomainConfiguration *pDomainConfiguration =
832          findConfiguration(strConfiguration, strResult);
833  
834      if (!pDomainConfiguration) {
835  
836          return false;
837      }
838  
839      // Delegate to configuration
840      strResult = pDomainConfiguration->getApplicationRule();
841  
842      return true;
843  }
844  
845  // Last applied configuration
getLastAppliedConfigurationName() const846  string CConfigurableDomain::getLastAppliedConfigurationName() const
847  {
848      if (_pLastAppliedConfiguration) {
849  
850          return _pLastAppliedConfiguration->getName();
851      }
852      return "<none>";
853  }
854  
855  // Pending configuration
getPendingConfigurationName() const856  string CConfigurableDomain::getPendingConfigurationName() const
857  {
858      const CDomainConfiguration *pApplicableDomainConfiguration =
859          findApplicableDomainConfiguration();
860  
861      if (!pApplicableDomainConfiguration) {
862  
863          // No configuration is pending
864          return "<none>";
865      }
866  
867      // Check it will be applied
868      if (pApplicableDomainConfiguration != _pLastAppliedConfiguration) {
869  
870          // Found config will get applied
871          return pApplicableDomainConfiguration->getName();
872      } else {
873  
874          // Same configuration as current
875          return "";
876      }
877  }
878  
879  // Ensure validity on whole domain from main blackboard
validate(const CParameterBlackboard * pMainBlackboard)880  void CConfigurableDomain::validate(const CParameterBlackboard *pMainBlackboard)
881  {
882  
883      // Propagate
884      size_t uiNbConfigurations = getNbChildren();
885  
886      for (size_t uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
887  
888          CDomainConfiguration *pDomainConfiguration =
889              static_cast<CDomainConfiguration *>(getChild(uiChild));
890  
891          pDomainConfiguration->validate(pMainBlackboard);
892      }
893  }
894  
895  // Ensure validity on areas related to configurable element
validateAreas(const CConfigurableElement * pConfigurableElement,const CParameterBlackboard * pMainBlackboard)896  void CConfigurableDomain::validateAreas(const CConfigurableElement *pConfigurableElement,
897                                          const CParameterBlackboard *pMainBlackboard)
898  {
899      // Propagate
900      size_t uiNbConfigurations = getNbChildren();
901  
902      for (size_t uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
903  
904          CDomainConfiguration *pDomainConfiguration =
905              static_cast<CDomainConfiguration *>(getChild(uiChild));
906  
907          pDomainConfiguration->validate(pConfigurableElement, pMainBlackboard);
908      }
909  }
910  
911  // Attempt validation for all configurable element's areas, relying on already existing valid
912  // configuration inside domain
autoValidateAll()913  void CConfigurableDomain::autoValidateAll()
914  {
915      // Validate
916      ConfigurableElementListIterator it;
917  
918      // Browse all configurable elements for configuration validation
919      for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
920  
921          const CConfigurableElement *pConfigurableElement = *it;
922  
923          // Auto validate element
924          autoValidateAreas(pConfigurableElement);
925      }
926  }
927  
928  // Attempt validation for configurable element's areas, relying on already existing valid
929  // configuration inside domain
autoValidateAreas(const CConfigurableElement * pConfigurableElement)930  void CConfigurableDomain::autoValidateAreas(const CConfigurableElement *pConfigurableElement)
931  {
932      // Find first valid configuration for given configurable element
933      const CDomainConfiguration *pValidDomainConfiguration =
934          findValidDomainConfiguration(pConfigurableElement);
935  
936      // No valid configuration found, give up
937      if (!pValidDomainConfiguration) {
938  
939          return;
940      }
941  
942      // Validate all other configurations against found one, if any
943      size_t uiNbConfigurations = getNbChildren();
944  
945      for (size_t uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
946  
947          CDomainConfiguration *pDomainConfiguration =
948              static_cast<CDomainConfiguration *>(getChild(uiChild));
949  
950          if (pDomainConfiguration != pValidDomainConfiguration &&
951              !pDomainConfiguration->isValid(pConfigurableElement)) {
952              // Validate
953              pDomainConfiguration->validateAgainst(pValidDomainConfiguration, pConfigurableElement);
954          }
955      }
956  }
957  
958  // Attempt configuration validation for all configurable elements' areas, relying on already
959  // existing valid configuration inside domain
autoValidateConfiguration(CDomainConfiguration * pDomainConfiguration)960  bool CConfigurableDomain::autoValidateConfiguration(CDomainConfiguration *pDomainConfiguration)
961  {
962      // Find another configuration than this one, that ought to be valid!
963      size_t uiNbConfigurations = getNbChildren();
964  
965      for (size_t uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
966  
967          const CDomainConfiguration *pPotententialValidDomainConfiguration =
968              static_cast<const CDomainConfiguration *>(getChild(uiChild));
969  
970          if (pPotententialValidDomainConfiguration != pDomainConfiguration) {
971  
972              // Validate against it
973              pDomainConfiguration->validateAgainst(pPotententialValidDomainConfiguration);
974  
975              return true;
976          }
977      }
978      return false;
979  }
980  
981  // Search for a valid configuration for given configurable element
findValidDomainConfiguration(const CConfigurableElement * pConfigurableElement) const982  const CDomainConfiguration *CConfigurableDomain::findValidDomainConfiguration(
983      const CConfigurableElement *pConfigurableElement) const
984  {
985      size_t uiNbConfigurations = getNbChildren();
986  
987      for (size_t uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
988  
989          const CDomainConfiguration *pDomainConfiguration =
990              static_cast<const CDomainConfiguration *>(getChild(uiChild));
991  
992          if (pDomainConfiguration->isValid(pConfigurableElement)) {
993  
994              return pDomainConfiguration;
995          }
996      }
997      return NULL;
998  }
999  
1000  // Search for an applicable configuration
findApplicableDomainConfiguration() const1001  const CDomainConfiguration *CConfigurableDomain::findApplicableDomainConfiguration() const
1002  {
1003      size_t uiNbConfigurations = getNbChildren();
1004  
1005      for (size_t uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
1006  
1007          const CDomainConfiguration *pDomainConfiguration =
1008              static_cast<const CDomainConfiguration *>(getChild(uiChild));
1009  
1010          if (pDomainConfiguration->isApplicable()) {
1011  
1012              return pDomainConfiguration;
1013          }
1014      }
1015      return NULL;
1016  }
1017  
1018  // Gather set of configurable elements
gatherConfigurableElements(std::set<const CConfigurableElement * > & configurableElementSet) const1019  void CConfigurableDomain::gatherConfigurableElements(
1020      std::set<const CConfigurableElement *> &configurableElementSet) const
1021  {
1022      // Insert all configurable elements
1023      configurableElementSet.insert(_configurableElementList.begin(), _configurableElementList.end());
1024  }
1025  
1026  // Check configurable element already attached
containsConfigurableElement(const CConfigurableElement * pConfigurableCandidateElement) const1027  bool CConfigurableDomain::containsConfigurableElement(
1028      const CConfigurableElement *pConfigurableCandidateElement) const
1029  {
1030      ConfigurableElementListIterator it;
1031  
1032      // Browse all configurable elements for comparison
1033      for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
1034  
1035          if (pConfigurableCandidateElement == *it) {
1036  
1037              return true;
1038          }
1039      }
1040      return false;
1041  }
1042  
1043  // Merge any descended configurable element to this one with this one
mergeAlreadyAssociatedDescendantConfigurableElements(CConfigurableElement * newElement,core::Results & infos)1044  void CConfigurableDomain::mergeAlreadyAssociatedDescendantConfigurableElements(
1045      CConfigurableElement *newElement, core::Results &infos)
1046  {
1047      std::list<CConfigurableElement *> mergedConfigurableElementList;
1048  
1049      ConfigurableElementListIterator it;
1050  
1051      // Browse all configurable elements (new one not yet in the list!)
1052      for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
1053  
1054          CConfigurableElement *pConfigurablePotentialDescendantElement = *it;
1055  
1056          if (pConfigurablePotentialDescendantElement->isDescendantOf(newElement)) {
1057  
1058              infos.push_back("In domain '" + getName() +
1059                              "', merging descendant configurable element's configurations '" +
1060                              pConfigurablePotentialDescendantElement->getName() +
1061                              "' into its ascendant '" + newElement->getName() + "' ones");
1062  
1063              // Merge configuration data
1064              mergeConfigurations(newElement, pConfigurablePotentialDescendantElement);
1065  
1066              // Keep track for removal
1067              mergedConfigurableElementList.push_back(pConfigurablePotentialDescendantElement);
1068          }
1069      }
1070  
1071      // Remove all merged elements (new one not yet in the list!)
1072      for (it = mergedConfigurableElementList.begin(); it != mergedConfigurableElementList.end();
1073           ++it) {
1074  
1075          CConfigurableElement *pMergedConfigurableElement = *it;
1076  
1077          // Remove merged from configurable element from internal tracking list
1078          // Note: we shouldn't need to recompute the sync set in that case, as the merged to element
1079          // should include the syncers of merged from elements
1080          doRemoveConfigurableElement(pMergedConfigurableElement, false);
1081      }
1082  }
1083  
mergeConfigurations(CConfigurableElement * pToConfigurableElement,CConfigurableElement * pFromConfigurableElement)1084  void CConfigurableDomain::mergeConfigurations(CConfigurableElement *pToConfigurableElement,
1085                                                CConfigurableElement *pFromConfigurableElement)
1086  {
1087      // Propagate to domain configurations
1088      size_t uiNbConfigurations = getNbChildren();
1089  
1090      for (size_t uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
1091  
1092          CDomainConfiguration *pDomainConfiguration =
1093              static_cast<CDomainConfiguration *>(getChild(uiChild));
1094  
1095          // Do the merge.
1096          pDomainConfiguration->merge(pToConfigurableElement, pFromConfigurableElement);
1097      }
1098  }
1099  
1100  // Configurable elements association
doAddConfigurableElement(CConfigurableElement * pConfigurableElement,core::Results & infos,const CParameterBlackboard * pMainBlackboard)1101  void CConfigurableDomain::doAddConfigurableElement(CConfigurableElement *pConfigurableElement,
1102                                                     core::Results &infos,
1103                                                     const CParameterBlackboard *pMainBlackboard)
1104  {
1105      // Inform configurable element
1106      pConfigurableElement->addAttachedConfigurableDomain(this);
1107  
1108      // Create associated syncer set
1109      CSyncerSet *pSyncerSet = new CSyncerSet;
1110  
1111      // Add to sync set the configurable element one
1112      pConfigurableElement->fillSyncerSet(*pSyncerSet);
1113  
1114      // Store it
1115      _configurableElementToSyncerSetMap[pConfigurableElement] = pSyncerSet;
1116  
1117      // Add it to global one
1118      _syncerSet += *pSyncerSet;
1119  
1120      // Inform configurations
1121      size_t uiNbConfigurations = getNbChildren();
1122  
1123      for (size_t uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
1124  
1125          CDomainConfiguration *pDomainConfiguration =
1126              static_cast<CDomainConfiguration *>(getChild(uiChild));
1127  
1128          pDomainConfiguration->addConfigurableElement(pConfigurableElement, pSyncerSet);
1129      }
1130  
1131      // Ensure area validity for that configurable element (if main blackboard provided)
1132      if (pMainBlackboard) {
1133  
1134          infos.push_back("Validating domain '" + getName() +
1135                          "' against main blackboard for configurable element '" +
1136                          pConfigurableElement->getPath() + "'");
1137          // Need to validate against main blackboard
1138          validateAreas(pConfigurableElement, pMainBlackboard);
1139      }
1140  
1141      // Already associated descendend configurable elements need a merge of their configuration data
1142      mergeAlreadyAssociatedDescendantConfigurableElements(pConfigurableElement, infos);
1143  
1144      // Add to list
1145      _configurableElementList.push_back(pConfigurableElement);
1146  }
1147  
doRemoveConfigurableElement(CConfigurableElement * pConfigurableElement,bool bRecomputeSyncSet)1148  void CConfigurableDomain::doRemoveConfigurableElement(CConfigurableElement *pConfigurableElement,
1149                                                        bool bRecomputeSyncSet)
1150  {
1151      // Remove from list
1152      _configurableElementList.remove(pConfigurableElement);
1153  
1154      // Remove associated syncer set
1155      CSyncerSet *pSyncerSet = getSyncerSet(pConfigurableElement);
1156  
1157      _configurableElementToSyncerSetMap.erase(pConfigurableElement);
1158  
1159      delete pSyncerSet;
1160  
1161      // Inform configurable element
1162      pConfigurableElement->removeAttachedConfigurableDomain(this);
1163  
1164      // Inform configurations
1165      size_t uiNbConfigurations = getNbChildren();
1166  
1167      for (size_t uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
1168  
1169          CDomainConfiguration *pDomainConfiguration =
1170              static_cast<CDomainConfiguration *>(getChild(uiChild));
1171  
1172          pDomainConfiguration->removeConfigurableElement(pConfigurableElement);
1173      }
1174      // Recompute our sync set if needed
1175      if (bRecomputeSyncSet) {
1176  
1177          computeSyncSet();
1178      }
1179  }
1180  
1181  // Syncer set retrieval from configurable element
getSyncerSet(const CConfigurableElement * pConfigurableElement) const1182  CSyncerSet *CConfigurableDomain::getSyncerSet(
1183      const CConfigurableElement *pConfigurableElement) const
1184  {
1185      ConfigurableElementToSyncerSetMapIterator mapIt =
1186          _configurableElementToSyncerSetMap.find(pConfigurableElement);
1187  
1188      ALWAYS_ASSERT(mapIt != _configurableElementToSyncerSetMap.end(),
1189                    "Could not find syncer set for " << getName() << " configurable domain");
1190  
1191      return mapIt->second;
1192  }
1193  
1194  // Configuration retrieval
findConfiguration(const string & strConfiguration,string & strError)1195  CDomainConfiguration *CConfigurableDomain::findConfiguration(const string &strConfiguration,
1196                                                               string &strError)
1197  {
1198      CDomainConfiguration *pDomainConfiguration =
1199          static_cast<CDomainConfiguration *>(findChild(strConfiguration));
1200  
1201      if (!pDomainConfiguration) {
1202  
1203          strError = "Domain configuration " + strConfiguration + " not found";
1204  
1205          return NULL;
1206      }
1207      return pDomainConfiguration;
1208  }
1209  
findConfiguration(const string & strConfiguration,string & strError) const1210  const CDomainConfiguration *CConfigurableDomain::findConfiguration(const string &strConfiguration,
1211                                                                     string &strError) const
1212  {
1213      const CDomainConfiguration *pDomainConfiguration =
1214          static_cast<const CDomainConfiguration *>(findChild(strConfiguration));
1215  
1216      if (!pDomainConfiguration) {
1217  
1218          strError = "Domain configuration " + strConfiguration + " not found";
1219  
1220          return NULL;
1221      }
1222      return pDomainConfiguration;
1223  }
1224