/* * * * 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 * * * */ #include "ConfigurableDomain.h" #include "DomainConfiguration.h" #include "ConfigurableElement.h" #include "ConfigurationAccessContext.h" #include "Subsystem.h" #include "XmlDomainSerializingContext.h" #include #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(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(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(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(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(serializingContext); // Parse configurable element's configuration settings CXmlElement::CChildIterator it(xmlConfigurableElementElement); CXmlElement xmlConfigurationSettingsElement; while (it.next(xmlConfigurationSettingsElement)) { // Get domain configuration CDomainConfiguration* pDomainConfiguration = static_cast(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(serializingContext); // Element content CXmlElement xmlConfigurationSettingsElementContent; // Deal with element itself if (!bSerializeOut) { // Check structure if (xmlConfigurationSettingsElement.getNbChildElements() != 1) { // Structure error serializingContext.setError("Struture error encountered while parsing settinsg of " + pConfigurableElement->getKind() + " " + pConfigurableElement->getName() + " in Configuration " + pDomainConfiguration->getName() + " in Domain " + getName()); return false; } // Check name and kind if (!xmlConfigurationSettingsElement.getChildElement(pConfigurableElement->getKind(), pConfigurableElement->getName(), xmlConfigurationSettingsElementContent)) { serializingContext.setError("Couldn't find settings for " + pConfigurableElement->getKind() + " " + pConfigurableElement->getName() + " for Configuration " + pDomainConfiguration->getName() + " in Domain " + getName()); return false; } } else { // Create child XML element xmlConfigurationSettingsElement.createChild(xmlConfigurationSettingsElementContent, pConfigurableElement->getKind()); // Set Name xmlConfigurationSettingsElementContent.setNameAttribute(pConfigurableElement->getName()); } // Change context type to parameter settings access string strError; // Create configuration access context CConfigurationAccessContext configurationAccessContext(strError, bSerializeOut); // Provide current value space configurationAccessContext.setValueSpaceRaw(xmlDomainSerializingContext.valueSpaceIsRaw()); // Provide current output raw format configurationAccessContext.setOutputRawFormat(xmlDomainSerializingContext.outputRawFormatIsHex()); // 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, xmlConfigurationSettingsElementContent, 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(pConfigurableElement->getChild(uiChild)); doAddConfigurableElement(pChildConfigurableElement); } // Delegate to configurations uint32_t uiNbConfigurations = getNbChildren(); for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { CDomainConfiguration* pDomainConfiguration = static_cast(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(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(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(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(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(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 ""; } // 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(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(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(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(getChild(uiChild)); if (pPotententialValidDomainConfiguration != pDomainConfiguration) { // Validate against it pDomainConfiguration->validateAgainst(pPotententialValidDomainConfiguration); return true; } } return false; } // 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(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(getChild(uiChild)); if (pDomainConfiguration->isApplicable()) { return pDomainConfiguration; } } return NULL; } // Gather set of configurable elements void CConfigurableDomain::gatherConfigurableElements(set& 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 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(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(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(getChild(uiChild)); pDomainConfiguration->removeConfigurableElement(pConfigurableElement); } // Recompute our sync set if needed if (bRecomputeSyncSet) { computeSyncSet(); } }