summaryrefslogtreecommitdiffstats
path: root/parameter/ConfigurableDomain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'parameter/ConfigurableDomain.cpp')
-rw-r--r--parameter/ConfigurableDomain.cpp922
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();
+ }
+}