diff options
Diffstat (limited to 'parameter/ConfigurableDomain.cpp')
-rw-r--r-- | parameter/ConfigurableDomain.cpp | 922 |
1 files changed, 922 insertions, 0 deletions
diff --git a/parameter/ConfigurableDomain.cpp b/parameter/ConfigurableDomain.cpp new file mode 100644 index 0000000..807171f --- /dev/null +++ b/parameter/ConfigurableDomain.cpp @@ -0,0 +1,922 @@ +/* <auto_header> + * <FILENAME> + * + * INTEL CONFIDENTIAL + * Copyright © 2011 Intel + * Corporation All Rights Reserved. + * + * The source code contained or described herein and all documents related to + * the source code ("Material") are owned by Intel Corporation or its suppliers + * or licensors. Title to the Material remains with Intel Corporation or its + * suppliers and licensors. The Material contains trade secrets and proprietary + * and confidential information of Intel or its suppliers and licensors. The + * Material is protected by worldwide copyright and trade secret laws and + * treaty provisions. No part of the Material may be used, copied, reproduced, + * modified, published, uploaded, posted, transmitted, distributed, or + * disclosed in any way without Intel’s prior express written permission. + * + * No license under any patent, copyright, trade secret or other intellectual + * property right is granted to or conferred upon you by disclosure or delivery + * of the Materials, either expressly, by implication, inducement, estoppel or + * otherwise. Any license under such intellectual property rights must be + * express and approved by Intel in writing. + * + * AUTHOR: Patrick Benavoli (patrickx.benavoli@intel.com) + * CREATED: 2011-06-01 + * UPDATED: 2011-07-27 + * + * + * </auto_header> + */ +#include "ConfigurableDomain.h" +#include "DomainConfiguration.h" +#include "ConfigurableElement.h" +#include "ConfigurationAccessContext.h" +#include "Subsystem.h" +#include "XmlDomainSerializingContext.h" +#include <assert.h> + +#define base CBinarySerializableElement + +CConfigurableDomain::CConfigurableDomain(const string& strName) : base(strName), _pLastAppliedConfiguration(NULL) +{ +} + +CConfigurableDomain::~CConfigurableDomain() +{ + ConfigurableElementListIterator it; + + // Browse all configurable elements for their syncers + for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) { + + CConfigurableElement* pConfigurableElement = *it; + + // Remove from configurable element + pConfigurableElement->removeAttachedConfigurableDomain(this); + } +} + +string CConfigurableDomain::getKind() const +{ + return "ConfigurableDomain"; +} + +bool CConfigurableDomain::childrenAreDynamic() const +{ + return true; +} + +// From IXmlSource +void CConfigurableDomain::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const +{ + // Configurations + composeDomainConfigurations(xmlElement, serializingContext); + + // Configurable Elements + composeConfigurableElements(xmlElement, serializingContext); +} + +// XML composing +void CConfigurableDomain::composeDomainConfigurations(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const +{ + // Create Configurations element + CXmlElement xmlConfigurationsElement; + + xmlElement.createChild(xmlConfigurationsElement, "Configurations"); + + // Delegate to base + base::toXml(xmlConfigurationsElement, serializingContext); +} + +void CConfigurableDomain::composeConfigurableElements(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const +{ + // Context + const CXmlDomainSerializingContext& xmlDomainSerializingContext = static_cast<const CXmlDomainSerializingContext&>(serializingContext); + + // Create ConfigurableElements element + CXmlElement xmlConfigurableElementsElement; + + xmlElement.createChild(xmlConfigurableElementsElement, "ConfigurableElements"); + + // Serialize out all configurable elements settings + ConfigurableElementListIterator it; + + for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) { + + const CConfigurableElement* pConfigurableElement = *it; + + // Create corresponding XML child element + CXmlElement xmlChildConfigurableElement; + + xmlConfigurableElementsElement.createChild(xmlChildConfigurableElement, "ConfigurableElement"); + + // Set Path attribute + xmlChildConfigurableElement.setAttributeString("Path", pConfigurableElement->getPath()); + + if (xmlDomainSerializingContext.withSettings()) { + + // Compose configurations for that configurable element + composeConfigurableElementConfigurations(pConfigurableElement, xmlChildConfigurableElement, serializingContext); + } + } +} + +// Serialize configurations for one configurable element +void CConfigurableDomain::composeConfigurableElementConfigurations(const CConfigurableElement* pConfigurableElement, CXmlElement& xmlConfigurableElementElement, CXmlSerializingContext& serializingContext) const +{ + uint32_t uiNbConfigurations = getNbChildren(); + uint32_t uiChildConfiguration; + + for (uiChildConfiguration = 0; uiChildConfiguration < uiNbConfigurations; uiChildConfiguration++) { + + const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChildConfiguration)); + + // Create child xml element for that configuration + CXmlElement xmlConfigurationSettingsElement; + + xmlConfigurableElementElement.createChild(xmlConfigurationSettingsElement, pDomainConfiguration->getKind()); + + // Set its name attribute + xmlConfigurationSettingsElement.setNameAttribute(pDomainConfiguration->getName()); + + // Have domain configuration serialize settings for configurable element + ((CConfigurableDomain&)(*this)).serializeConfigurableElementConfiguration((CDomainConfiguration*)pDomainConfiguration, pConfigurableElement, xmlConfigurationSettingsElement, serializingContext, true); + } +} + +// From IXmlSink +bool CConfigurableDomain::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) +{ + // Local parsing. Do not dig + return parseDomainConfigurations(xmlElement, serializingContext) && parseConfigurableElements(xmlElement, serializingContext); +} + +// XML parsing +bool CConfigurableDomain::parseDomainConfigurations(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) +{ + // We're supposedly clean + assert(_configurableElementList.empty()); + + // Get Configurations element + CXmlElement xmlConfigurationsElement; + + xmlElement.getChildElement("Configurations", xmlConfigurationsElement); + + // Parse it and create domain configuration objects + return base::fromXml(xmlConfigurationsElement, serializingContext); +} + +// Parse configurable elements +bool CConfigurableDomain::parseConfigurableElements(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) +{ + // Context + const CXmlDomainSerializingContext& xmlDomainSerializingContext = static_cast<const CXmlDomainSerializingContext&>(serializingContext); + + // Get System Class Element + CElement* pRootElement = getRoot(); + + CElement* pSystemClassElement = pRootElement->findChildOfKind("SystemClass"); + + assert(pSystemClassElement); + + // Get ConfigurableElements element + CXmlElement xmlConfigurableElementsElement; + xmlElement.getChildElement("ConfigurableElements", xmlConfigurableElementsElement); + + // Parse it and associate found configurable elements to it + CXmlElement::CChildIterator it(xmlConfigurableElementsElement); + + CXmlElement xmlConfigurableElementElement; + + while (it.next(xmlConfigurableElementElement)) { + + // Locate configurable element + string strConfigurableElementPath = xmlConfigurableElementElement.getAttributeString("Path"); + + CPathNavigator pathNavigator(strConfigurableElementPath); + + string* pStrChildName = pathNavigator.next(); + + // Is there an element and does it match system class name? + if (!pStrChildName || *pStrChildName != pSystemClassElement->getName()) { + + serializingContext.setError("Could not find configurable element of path " + strConfigurableElementPath + " from ConfigurableDomain description " + getName()); + + return false; + } + + // Browse system class for configurable element + CConfigurableElement* pConfigurableElement = static_cast<CConfigurableElement*>(pSystemClassElement->findDescendant(pathNavigator)); + + if (!pConfigurableElement) { + + serializingContext.setError("Could not find configurable element of path " + strConfigurableElementPath + " from ConfigurableDomain description " + getName()); + + return false; + } + // Add found element to domain + string strError; + if (!addConfigurableElement(pConfigurableElement, NULL, strError)) { + + serializingContext.setError(strError); + + return false; + } + + // Check we need to parse configuration settings + if (xmlDomainSerializingContext.withSettings()) { + + // Make Domain configuration parse associated configuration nodes if any + if (!parseConfigurableElementConfigurations(pConfigurableElement, xmlConfigurableElementElement, serializingContext)) { + + return false; + } + } + } + // All provided configurations are parsed + // Attempt validation on areas of non provided configurations for all configurable elements + autoValidateAll(); + + return true; +} + +// Parse configurations for one configurable element +bool CConfigurableDomain::parseConfigurableElementConfigurations(const CConfigurableElement* pConfigurableElement, CXmlElement& xmlConfigurableElementElement, CXmlSerializingContext& serializingContext) +{ + // Context + CXmlDomainSerializingContext& xmlDomainSerializingContext = static_cast<CXmlDomainSerializingContext&>(serializingContext); + + // Parse configurable element's configuration settings + CXmlElement::CChildIterator it(xmlConfigurableElementElement); + + CXmlElement xmlConfigurationSettingsElement; + + while (it.next(xmlConfigurationSettingsElement)) { + // Get domain configuration + CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(xmlConfigurationSettingsElement.getNameAttribute())); + + if (!pDomainConfiguration) { + + xmlDomainSerializingContext.setError("Could not find domain configuration referred to by configurable element of path " + xmlConfigurableElementElement.getPath() + " from ConfigurableDomain description " + getName()); + + return false; + } + // Have domain configuration parse settings for configurable element + if (!serializeConfigurableElementConfiguration(pDomainConfiguration, pConfigurableElement, xmlConfigurationSettingsElement, xmlDomainSerializingContext, false)) { + + return false; + } + } + + return true; +} + +// Serialize one configuration for one configurable element +bool CConfigurableDomain::serializeConfigurableElementConfiguration(CDomainConfiguration* pDomainConfiguration, const CConfigurableElement* pConfigurableElement, CXmlElement& xmlConfigurationSettingsElement, CXmlSerializingContext& serializingContext, bool bSerializeOut) +{ + // Actual XML context + CXmlDomainSerializingContext& xmlDomainSerializingContext = static_cast<CXmlDomainSerializingContext&>(serializingContext); + + // Change context type for parameter settings access + string strError; + + // Create configuration access context + CConfigurationAccessContext configurationAccessContext(strError, bSerializeOut); + + // Provide current value space + configurationAccessContext.setValueSpaceRaw(xmlDomainSerializingContext.valueSpaceIsRaw()); + + // Get subsystem + const CSubsystem* pSubsystem = pConfigurableElement->getBelongingSubsystem(); + + if (pSubsystem && pSubsystem != pConfigurableElement) { + + // Element is a descendant of subsystem + + // Deal with Endianness + configurationAccessContext.setBigEndianSubsystem(pSubsystem->isBigEndian()); + } + + // Have domain configuration parse settings for configurable element + if (!pDomainConfiguration->serializeXmlSettings(pConfigurableElement, xmlConfigurationSettingsElement, configurationAccessContext)) { + + // Forward error + xmlDomainSerializingContext.setError(strError); + + return false; + } + return true; +} + +// Configurable elements association +bool CConfigurableDomain::addConfigurableElement(CConfigurableElement* pConfigurableElement, const CParameterBlackboard* pMainBlackboard, string& strError) +{ + // Already associated? + if (containsConfigurableElement(pConfigurableElement)) { + + strError = "Configurable element " + pConfigurableElement->getPath() + " already associated to configuration domain " + getName(); + + return false; + } + + // Already owned? + if (pConfigurableElement->belongsTo(this)) { + + strError = "Configurable element " + pConfigurableElement->getPath() + " already owned by configuration domain " + getName(); + + return false; + } + log("Adding configurable element \"%s\" into domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str()); + + // Do add + doAddConfigurableElement(pConfigurableElement); + + // Ensure area validity for that configurable element (if main blackboard provided) + if (pMainBlackboard) { + + // Need to validate against main blackboard + validateAreas(pConfigurableElement, pMainBlackboard); + } + + return true; +} + +bool CConfigurableDomain::removeConfigurableElement(CConfigurableElement* pConfigurableElement, string& strError) +{ + // Not associated? + if (!containsConfigurableElement(pConfigurableElement)) { + + strError = "Configurable element " + pConfigurableElement->getPath() + " not associated to configuration domain " + getName(); + + return false; + } + log("Removing configurable element \"%s\" from domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str()); + + // Do remove + doRemoveConfigurableElement(pConfigurableElement, true); + + return true; +} + +// Domain splitting +bool CConfigurableDomain::split(CConfigurableElement* pConfigurableElement, string& strError) +{ + // Not associated? + if (!containsConfigurableElement(pConfigurableElement)) { + + strError = "Configurable element " + pConfigurableElement->getPath() + " not associated to configuration domain " + getName(); + + return false; + } + log("Splitting configurable element \"%s\" domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str()); + + // Create sub domain areas for all configurable element's children + uint32_t uiNbConfigurableElementChildren = pConfigurableElement->getNbChildren(); + + if (!uiNbConfigurableElementChildren) { + + strError = "Configurable element " + pConfigurableElement->getPath() + " has no children to split configurable domain to"; + + return false; + } + + uint32_t uiChild; + + for (uiChild = 0; uiChild < uiNbConfigurableElementChildren; uiChild++) { + + CConfigurableElement* pChildConfigurableElement = static_cast<CConfigurableElement*>(pConfigurableElement->getChild(uiChild)); + + doAddConfigurableElement(pChildConfigurableElement); + } + + // Delegate to configurations + uint32_t uiNbConfigurations = getNbChildren(); + + for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { + + CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild)); + + pDomainConfiguration->split(pConfigurableElement); + } + + // Remove given configurable element from this domain + // Note: we shouldn't need to recompute the sync set in that case, as the splitted element should include the syncers of its children elements + doRemoveConfigurableElement(pConfigurableElement, false); + + return true; +} + +// Configuration application if required +void CConfigurableDomain::apply(CParameterBlackboard* pParameterBlackboard, CSyncerSet& syncerSet, bool bForce) +{ + if (bForce) { + // Force a configuration restore by forgetting about last applied configuration + _pLastAppliedConfiguration = NULL; + } + const CDomainConfiguration* pApplicableDomainConfiguration = findApplicableDomainConfiguration(); + + if (pApplicableDomainConfiguration) { + + // Check not the last one before applying + if (!_pLastAppliedConfiguration || _pLastAppliedConfiguration != pApplicableDomainConfiguration) { + + log("Applying configuration \"%s\" from domain \"%s\"", pApplicableDomainConfiguration->getName().c_str(), getName().c_str()); + + // Do the restore + pApplicableDomainConfiguration->restore(pParameterBlackboard); + + // Record last applied configuration + _pLastAppliedConfiguration = pApplicableDomainConfiguration; + + // Since we applied changes, add our own sync set to the given one + syncerSet += _syncerSet; + } + } +} + +// Return applicable configuration validity for given configurable element +bool CConfigurableDomain::isApplicableConfigurationValid(const CConfigurableElement* pConfigurableElement) const +{ + const CDomainConfiguration* pApplicableDomainConfiguration = findApplicableDomainConfiguration(); + + return pApplicableDomainConfiguration && pApplicableDomainConfiguration->isValid(pConfigurableElement); +} + +// Presence of application condition on any configuration +bool CConfigurableDomain::hasRules() const +{ + // Delegate to configurations + uint32_t uiNbConfigurations = getNbChildren(); + uint32_t uiChild; + + for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { + + const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild)); + + if (pDomainConfiguration->hasRule()) { + + return true; + } + } + return false; +} + +// In case configurable element was removed +void CConfigurableDomain::computeSyncSet() +{ + // Clean sync set first + _syncerSet.clear(); + + // Browse all configurable elements for their syncers + ConfigurableElementListIterator it; + + for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) { + + const CConfigurableElement* pConfigurableElement = *it; + + pConfigurableElement->fillSyncerSet(_syncerSet); + } +} + +// Configuration Management +bool CConfigurableDomain::createConfiguration(const string& strName, const CParameterBlackboard* pMainBlackboard, string& strError) +{ + // Already exists? + if (findChild(strName)) { + + strError = "Already existing configuration"; + + return false; + } + log("Creating domain configuration \"%s\" into domain \"%s\"", strName.c_str(), getName().c_str()); + + // Creation + CDomainConfiguration* pDomainConfiguration = new CDomainConfiguration(strName); + + // Configurable elements association + ConfigurableElementListIterator it; + + for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) { + + pDomainConfiguration->addConfigurableElement(*it); + } + + // Hierarchy + addChild(pDomainConfiguration); + + // Ensure validity of fresh new domain configuration + // Attempt auto validation, so that the user gets his/her own settings by defaults + if (!autoValidateConfiguration(pDomainConfiguration)) { + + // No valid configuration found to copy in from, validate againt main blackboard (will concerned remaining invalid parts) + pDomainConfiguration->validate(pMainBlackboard); + } + + return true; +} + +bool CConfigurableDomain::deleteConfiguration(const string& strName, string& strError) +{ + CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(strName)); + + if (!pDomainConfiguration) { + + strError = "Configuration not found"; + + return false; + } + + // Check configuration has no rule (prevent accidental loss of data) + if (pDomainConfiguration->hasRule()) { + + strError = "Deletion of configuration containing application rules is not supported to prevent any accitental loss of data.\nPlease consider a direct modification of the XML file."; + + return false; + } + + log("Deleting configuration \"%s\" from domain \"%s\"", strName.c_str(), getName().c_str()); + + // Was the last applied? + if (pDomainConfiguration == _pLastAppliedConfiguration) { + + // Forget about it + _pLastAppliedConfiguration = NULL; + } + + // Hierarchy + removeChild(pDomainConfiguration); + + // Destroy + delete pDomainConfiguration; + + return true; +} + +void CConfigurableDomain::listAssociatedToElements(string& strResult) const +{ + strResult = "\n"; + + ConfigurableElementListIterator it; + + // Browse all configurable elements + for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) { + + const CConfigurableElement* pConfigurableElement = *it; + + strResult += pConfigurableElement->getPath() + "\n"; + } +} + +bool CConfigurableDomain::renameConfiguration(const string& strName, const string& strNewName, string& strError) +{ + CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(strName)); + + if (!pDomainConfiguration) { + + strError = "Configuration not found"; + + return false; + } + log("Renaming domain \"%s\"'s configuration \"%s\" to \"%s\"", getName().c_str(), strName.c_str(), strNewName.c_str()); + + // Rename + return pDomainConfiguration->rename(strNewName, strError); +} + +bool CConfigurableDomain::restoreConfiguration(const string& strName, CParameterBlackboard* pMainBlackboard, bool bAutoSync, string& strError) +{ + // Find Domain configuration + const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(findChild(strName)); + + if (!pDomainConfiguration) { + + strError = "Domain configuration " + strName + " not found"; + + return false; + } + log("Restoring domain \"%s\"'s configuration \"%s\" to parameter blackboard", getName().c_str(), pDomainConfiguration->getName().c_str()); + + // Delegate + pDomainConfiguration->restore(pMainBlackboard); + + // Record last applied configuration + _pLastAppliedConfiguration = pDomainConfiguration; + + // Synchronize + return !bAutoSync || _syncerSet.sync(*pMainBlackboard, false, strError); +} + +bool CConfigurableDomain::saveConfiguration(const string& strName, const CParameterBlackboard* pMainBlackboard, string& strError) +{ + // Find Domain configuration + CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(strName)); + + if (!pDomainConfiguration) { + + strError = "Domain configuration " + strName + " not found"; + + return false; + } + log("Saving domain \"%s\"'s configuration \"%s\" from parameter blackboard", getName().c_str(), pDomainConfiguration->getName().c_str()); + + // Delegate + pDomainConfiguration->save(pMainBlackboard); + + return true; +} + +// Last applied configuration +string CConfigurableDomain::getLastAppliedConfigurationName() const +{ + if (_pLastAppliedConfiguration) { + + return _pLastAppliedConfiguration->getName(); + } + return "<none>"; +} + +// Ensure validity on whole domain from main blackboard +void CConfigurableDomain::validate(const CParameterBlackboard* pMainBlackboard) +{ + log("Validating whole domain \"" + getName() + "\" against main blackboard"); + + // Propagate + uint32_t uiNbConfigurations = getNbChildren(); + uint32_t uiChild; + + for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { + + CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild)); + + pDomainConfiguration->validate(pMainBlackboard); + } +} + +// Ensure validity on areas related to configurable element +void CConfigurableDomain::validateAreas(const CConfigurableElement* pConfigurableElement, const CParameterBlackboard* pMainBlackboard) +{ + log("Validating domain \"" + getName() + "\" against main blackboard for configurable element \"" + pConfigurableElement->getPath() + "\""); + + // Propagate + uint32_t uiNbConfigurations = getNbChildren(); + uint32_t uiChild; + + for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { + + CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild)); + + pDomainConfiguration->validate(pConfigurableElement, pMainBlackboard); + } +} + +// Attempt validation for all configurable element's areas, relying on already existing valid configuration inside domain +void CConfigurableDomain::autoValidateAll() +{ + // Validate + ConfigurableElementListIterator it; + + // Browse all configurable elements for configuration validation + for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) { + + const CConfigurableElement* pConfigurableElement = *it; + + // Auto validate element + autoValidateAreas(pConfigurableElement); + } +} + +// Attempt validation for configurable element's areas, relying on already existing valid configuration inside domain +void CConfigurableDomain::autoValidateAreas(const CConfigurableElement* pConfigurableElement) +{ + // Find first valid configuration for given configurable element + const CDomainConfiguration* pValidDomainConfiguration = findValidDomainConfiguration(pConfigurableElement); + + // No valid configuration found, give up + if (!pValidDomainConfiguration) { + + return; + } + + log("Auto validating domain \"" + getName() + "\" against configuration \"" + pValidDomainConfiguration->getName() + "\" for configurable element " + pConfigurableElement->getPath()); + + // Validate all other configurations against found one, if any + uint32_t uiNbConfigurations = getNbChildren(); + uint32_t uiChild; + + for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { + + CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild)); + + if (pDomainConfiguration != pValidDomainConfiguration && !pDomainConfiguration->isValid(pConfigurableElement)) { + // Validate + pDomainConfiguration->validateAgainst(pValidDomainConfiguration, pConfigurableElement); + } + } +} + +// Attempt configuration validation for all configurable elements' areas, relying on already existing valid configuration inside domain +bool CConfigurableDomain::autoValidateConfiguration(CDomainConfiguration* pDomainConfiguration) +{ + // Find another configuration than this one, that ought to be valid! + uint32_t uiNbConfigurations = getNbChildren(); + uint32_t uiChild; + + for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { + + const CDomainConfiguration* pPotententialValidDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild)); + + if (pPotententialValidDomainConfiguration != pDomainConfiguration) { + + // Validate against it + pDomainConfiguration->validateAgainst(pPotententialValidDomainConfiguration); + + return true; + } + } + return false; +} +#if 0 +void CConfigurableDomain::autoValidateConfiguration(CDomainConfiguration* pDomainConfiguration) +{ + // Validate + ConfigurableElementListIterator it; + + // Browse all configurable elements for configuration validation + for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) { + + const CConfigurableElement* pConfigurableElement = *it; + + // Find first valid configuration for given configurable element + const CDomainConfiguration* pValidDomainConfiguration = findValidDomainConfiguration(pConfigurableElement); + + // Check valid configuration exists for that configurable element + if (pValidDomainConfiguration) { + + // Called on purpose + assert(pValidDomainConfiguration != pDomainConfiguration); + + // Validate + pDomainConfiguration->validateAgainst(pValidDomainConfiguration, pConfigurableElement); + } + } +} +#endif +// Search for a valid configuration for given configurable element +const CDomainConfiguration* CConfigurableDomain::findValidDomainConfiguration(const CConfigurableElement* pConfigurableElement) const +{ + uint32_t uiNbConfigurations = getNbChildren(); + uint32_t uiChild; + + for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { + + const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild)); + + if (pDomainConfiguration->isValid(pConfigurableElement)) { + + return pDomainConfiguration; + } + } + return NULL; +} + +// Search for an applicable configuration +const CDomainConfiguration* CConfigurableDomain::findApplicableDomainConfiguration() const +{ + uint32_t uiNbConfigurations = getNbChildren(); + uint32_t uiChild; + + for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { + + const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild)); + + if (pDomainConfiguration->isApplicable()) { + + return pDomainConfiguration; + } + } + return NULL; +} + +// Gather set of configurable elements +void CConfigurableDomain::gatherConfigurableElements(set<const CConfigurableElement*>& configurableElementSet) const +{ + // Insert all configurable elements + configurableElementSet.insert(_configurableElementList.begin(), _configurableElementList.end()); +} + +// Check configurable element already attached +bool CConfigurableDomain::containsConfigurableElement(const CConfigurableElement* pConfigurableCandidateElement) const +{ + ConfigurableElementListIterator it; + + // Browse all configurable elements for comparison + for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) { + + if (pConfigurableCandidateElement == *it) { + + return true; + } + } + return false; +} + +// Merge any descended configurable element to this one with this one +void CConfigurableDomain::mergeAlreadyAssociatedDescendantConfigurableElements(CConfigurableElement* pNewConfigurableElement) +{ + list<CConfigurableElement*> mergedConfigurableElementList; + + ConfigurableElementListIterator it; + + // Browse all configurable elements (new one not yet in the list!) + for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) { + + CConfigurableElement* pConfigurablePotentialDescendantElement = *it; + + if (pConfigurablePotentialDescendantElement->isDescendantOf(pNewConfigurableElement)) { + + log("In domain \"%s\", merging descendant configurable element's configurations \"%s\" into its ascendant \"%s\" ones", getName().c_str(), pConfigurablePotentialDescendantElement->getName().c_str(), pNewConfigurableElement->getName().c_str()); + + // Merge configuration data + mergeConfigurations(pNewConfigurableElement, pConfigurablePotentialDescendantElement); + + // Keep track for removal + mergedConfigurableElementList.push_back(pConfigurablePotentialDescendantElement); + } + } + + // Remove all merged elements (new one not yet in the list!) + for (it = mergedConfigurableElementList.begin(); it != mergedConfigurableElementList.end(); ++it) { + + CConfigurableElement* pMergedConfigurableElement = *it; + + // Remove merged from configurable element from internal tracking list + // Note: we shouldn't need to recompute the sync set in that case, as the merged to element should include the syncers of merged from elements + doRemoveConfigurableElement(pMergedConfigurableElement, false); + } +} + +void CConfigurableDomain::mergeConfigurations(CConfigurableElement* pToConfigurableElement, CConfigurableElement* pFromConfigurableElement) +{ + // Propagate to domain configurations + uint32_t uiNbConfigurations = getNbChildren(); + uint32_t uiChild; + + for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { + + CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild)); + + // Do the merge. + pDomainConfiguration->merge(pToConfigurableElement, pFromConfigurableElement); + } +} + +// Configurable elements association +void CConfigurableDomain::doAddConfigurableElement(CConfigurableElement* pConfigurableElement) +{ + // Inform configurable element + pConfigurableElement->addAttachedConfigurableDomain(this); + + // Inform configurations + uint32_t uiNbConfigurations = getNbChildren(); + uint32_t uiChild; + + for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { + + CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild)); + + pDomainConfiguration->addConfigurableElement(pConfigurableElement); + } + // Add to our own sync set the configurable element one + pConfigurableElement->fillSyncerSet(_syncerSet); + + // Already associated descended configurable elements need a merge of their configuration data + mergeAlreadyAssociatedDescendantConfigurableElements(pConfigurableElement); + + // Add to list + _configurableElementList.push_back(pConfigurableElement); +} + +void CConfigurableDomain::doRemoveConfigurableElement(CConfigurableElement* pConfigurableElement, bool bRecomputeSyncSet) +{ + // Remove from list + _configurableElementList.remove(pConfigurableElement); + + // Inform configurable element + pConfigurableElement->removeAttachedConfigurableDomain(this); + + // Inform configurations + uint32_t uiNbConfigurations = getNbChildren(); + uint32_t uiChild; + + for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { + + CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild)); + + pDomainConfiguration->removeConfigurableElement(pConfigurableElement); + } + // Recompute our sync set if needed + if (bRecomputeSyncSet) { + + computeSyncSet(); + } +} |