Home | History | Annotate | Download | only in parameter
      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 
     45 CConfigurableDomain::CConfigurableDomain(const string &strName) : base(strName)
     46 {
     47 }
     48 
     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 
     72 string CConfigurableDomain::getKind() const
     73 {
     74     return "ConfigurableDomain";
     75 }
     76 
     77 bool CConfigurableDomain::childrenAreDynamic() const
     78 {
     79     return true;
     80 }
     81 
     82 // Content dumping
     83 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
     96 void CConfigurableDomain::setSequenceAwareness(bool bSequenceAware)
     97 {
     98     if (_bSequenceAware != bSequenceAware) {
     99 
    100         _bSequenceAware = bSequenceAware;
    101     }
    102 }
    103 
    104 bool CConfigurableDomain::getSequenceAwareness() const
    105 {
    106     return _bSequenceAware;
    107 }
    108 
    109 // From IXmlSource
    110 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 
    119 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
    133 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 
    145 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 
    170 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
    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
    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
    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
    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
    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 
    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 */
    429 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
    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
    523 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
    542 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
    588 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
    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
    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 
    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 
    687 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 
    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 
    714 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 
    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 
    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 
    776 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 
    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 
    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 
    827 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
    846 string CConfigurableDomain::getLastAppliedConfigurationName() const
    847 {
    848     if (_pLastAppliedConfiguration) {
    849 
    850         return _pLastAppliedConfiguration->getName();
    851     }
    852     return "<none>";
    853 }
    854 
    855 // Pending configuration
    856 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
    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
    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
    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
    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
    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
    982 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
   1001 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
   1019 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
   1027 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
   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 
   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
   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 
   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
   1182 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
   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 
   1210 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