/* * Copyright (c) 2011-2015, Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "ConfigurableElement.h" #include "MappingData.h" #include "SyncerSet.h" #include "ConfigurableDomain.h" #include "ConfigurationAccessContext.h" #include "ConfigurableElementAggregator.h" #include "AreaConfiguration.h" #include "Utility.h" #include #define base CElement CConfigurableElement::CConfigurableElement(const std::string& strName) : base(strName), _uiOffset(0) { } CConfigurableElement::~CConfigurableElement() { } // XML configuration settings parsing bool CConfigurableElement::serializeXmlSettings(CXmlElement& xmlConfigurationSettingsElementContent, CConfigurationAccessContext& configurationAccessContext) const { size_t uiIndex; size_t uiNbChildren = getNbChildren(); if (!configurationAccessContext.serializeOut()) { // Just do basic checks and propagate to children CXmlElement::CChildIterator it(xmlConfigurationSettingsElementContent); CXmlElement xmlChildConfigurableElementSettingsElement; // Propagate to children for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) { // Get child const CConfigurableElement* pChildConfigurableElement = static_cast(getChild(uiIndex)); if (!it.next(xmlChildConfigurableElementSettingsElement)) { // Structure error configurationAccessContext.setError("Configuration settings parsing: Settings don't conform to structure of configurable element " + getName()); return false; } // Check element type matches in type if (xmlChildConfigurableElementSettingsElement.getType() != pChildConfigurableElement->getKind()) { // Type error configurationAccessContext.setError("Configuration settings parsing: Settings for configurable element " + pChildConfigurableElement->getName() + " does not match expected type: " + xmlChildConfigurableElementSettingsElement.getType() + " instead of " + pChildConfigurableElement->getKind()); return false; } // Check element type matches in name if (xmlChildConfigurableElementSettingsElement.getNameAttribute() != pChildConfigurableElement->getName()) { // Name error configurationAccessContext.setError("Configuration settings parsing: Under configurable elememnt " + getName() + ", expected element name " + pChildConfigurableElement->getName() + " but found " + xmlChildConfigurableElementSettingsElement.getNameAttribute() + " instead"); return false; } // Parse child configurable element's settings if (!pChildConfigurableElement->serializeXmlSettings(xmlChildConfigurableElementSettingsElement, configurationAccessContext)) { return false; } } // There should remain no configurable element to parse if (it.next(xmlChildConfigurableElementSettingsElement)) { // Structure error configurationAccessContext.setError("Configuration settings parsing: Settings don't conform to structure of configurable element " + getName()); return false; } } else { // Propagate to children for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) { const CConfigurableElement* pChildConfigurableElement = static_cast(getChild(uiIndex)); // Create corresponding child element CXmlElement xmlChildConfigurableElementSettingsElement; xmlConfigurationSettingsElementContent.createChild(xmlChildConfigurableElementSettingsElement, pChildConfigurableElement->getKind()); // Handle element name attribute xmlChildConfigurableElementSettingsElement.setNameAttribute(pChildConfigurableElement->getName()); // Propagate pChildConfigurableElement->serializeXmlSettings(xmlChildConfigurableElementSettingsElement, configurationAccessContext); } } // Done return true; } // AreaConfiguration creation CAreaConfiguration* CConfigurableElement::createAreaConfiguration(const CSyncerSet* pSyncerSet) const { return new CAreaConfiguration(this, pSyncerSet); } // Parameter access bool CConfigurableElement::accessValue(CPathNavigator& pathNavigator, std::string& strValue, bool bSet, CParameterAccessContext& parameterAccessContext) const { std::string* pStrChildName = pathNavigator.next(); if (!pStrChildName) { parameterAccessContext.setError((bSet ? "Can't set " : "Can't get ") + pathNavigator.getCurrentPath() + " because it is not a parameter"); return false; } const CConfigurableElement* pChild = static_cast(findChild(*pStrChildName)); if (!pChild) { parameterAccessContext.setError("Path not found: " + pathNavigator.getCurrentPath()); return false; } return pChild->accessValue(pathNavigator, strValue, bSet, parameterAccessContext); } void CConfigurableElement::getListOfElementsWithMapping( std::list& configurableElementPath) const { // Check parent const CElement* pParent = getParent(); if (isOfConfigurableElementType(pParent)) { const CConfigurableElement* pConfigurableElement = static_cast(pParent); pConfigurableElement->getListOfElementsWithMapping(configurableElementPath); } } // Used for simulation and virtual subsystems void CConfigurableElement::setDefaultValues(CParameterAccessContext& parameterAccessContext) const { // Propagate to children size_t uiIndex; size_t uiNbChildren = getNbChildren(); for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) { const CConfigurableElement* pConfigurableElement = static_cast(getChild(uiIndex)); pConfigurableElement->setDefaultValues(parameterAccessContext); } } // Element properties void CConfigurableElement::showProperties(std::string& strResult) const { base::showProperties(strResult); strResult += "Total size: " + getFootprintAsString() + "\n"; } // Offset void CConfigurableElement::setOffset(uint32_t uiOffset) { // Assign offset locally _uiOffset = uiOffset; // Propagate to children size_t uiIndex; size_t uiNbChildren = getNbChildren(); for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) { CConfigurableElement* pConfigurableElement = static_cast(getChild(uiIndex)); pConfigurableElement->setOffset(uiOffset); uiOffset += pConfigurableElement->getFootPrint(); } } uint32_t CConfigurableElement::getOffset() const { return _uiOffset; } // Memory uint32_t CConfigurableElement::getFootPrint() const { uint32_t uiSize = 0; size_t uiIndex; size_t uiNbChildren = getNbChildren(); for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) { const CConfigurableElement* pConfigurableElement = static_cast(getChild(uiIndex)); uiSize += pConfigurableElement->getFootPrint(); } return uiSize; } // Browse parent path to find syncer ISyncer* CConfigurableElement::getSyncer() const { // Check parent const CElement* pParent = getParent(); if (isOfConfigurableElementType(pParent)) { return static_cast(pParent)->getSyncer(); } return NULL; } // Syncer set (me, ascendant or descendant ones) void CConfigurableElement::fillSyncerSet(CSyncerSet& syncerSet) const { // Try me or ascendants ISyncer* pMineOrAscendantSyncer = getSyncer(); if (pMineOrAscendantSyncer) { // Provide found syncer object syncerSet += pMineOrAscendantSyncer; // Done return; } // Fetch descendant ones fillSyncerSetFromDescendant(syncerSet); } // Syncer set (descendant) void CConfigurableElement::fillSyncerSetFromDescendant(CSyncerSet& syncerSet) const { // Dig size_t uiIndex; size_t uiNbChildren = getNbChildren(); for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) { const CConfigurableElement* pConfigurableElement = static_cast(getChild(uiIndex)); pConfigurableElement->fillSyncerSetFromDescendant(syncerSet); } } // Configurable domain association void CConfigurableElement::addAttachedConfigurableDomain(const CConfigurableDomain* pConfigurableDomain) { _configurableDomainList.push_back(pConfigurableDomain); } void CConfigurableElement::removeAttachedConfigurableDomain(const CConfigurableDomain* pConfigurableDomain) { _configurableDomainList.remove(pConfigurableDomain); } // Belonging domain bool CConfigurableElement::belongsTo(const CConfigurableDomain* pConfigurableDomain) const { if (containsConfigurableDomain(pConfigurableDomain)) { return true; } return belongsToDomainAscending(pConfigurableDomain); } // Belonging domains void CConfigurableElement::getBelongingDomains(std::list& configurableDomainList) const { configurableDomainList.insert(configurableDomainList.end(), _configurableDomainList.begin(), _configurableDomainList.end()); // Check parent const CElement* pParent = getParent(); if (isOfConfigurableElementType(pParent)) { static_cast(pParent)->getBelongingDomains(configurableDomainList); } } void CConfigurableElement::listBelongingDomains(std::string& strResult, bool bVertical) const { // Get belonging domain list std::list configurableDomainList; getBelongingDomains(configurableDomainList); // Fill list listDomains(configurableDomainList, strResult, bVertical); } // Elements with no domains void CConfigurableElement::listRogueElements(std::string& strResult) const { strResult = "\n"; // Get rogue element aggregate list (no associated domain) std::list rogueElementList; CConfigurableElementAggregator configurableElementAggregator(rogueElementList, &CConfigurableElement::hasNoDomainAssociated); configurableElementAggregator.aggegate(this); // Build list as std::string std::list::const_iterator it; for (it = rogueElementList.begin(); it != rogueElementList.end(); ++it) { const CConfigurableElement* pConfigurableElement = *it; strResult += pConfigurableElement->getPath() + "\n"; } } // Belonging to no domains bool CConfigurableElement::isRogue() const { return !getBelongingDomainCount(); } // Footprint as string std::string CConfigurableElement::getFootprintAsString() const { // Get size as string return CUtility::toString(getFootPrint()) + " byte(s)"; } // Matching check for no domain association bool CConfigurableElement::hasNoDomainAssociated() const { return _configurableDomainList.empty(); } // Matching check for no valid associated domains bool CConfigurableElement::hasNoValidDomainAssociated() const { if (_configurableDomainList.empty()) { // No domains associated return true; } ConfigurableDomainListConstIterator it; // Browse all configurable domains for validity checking for (it = _configurableDomainList.begin(); it != _configurableDomainList.end(); ++it) { const CConfigurableDomain* pConfigurableDomain = *it; if (pConfigurableDomain->isApplicableConfigurationValid(this)) { return false; } } return true; } // Owning domains void CConfigurableElement::listAssociatedDomains(std::string& strResult, bool bVertical) const { // Fill list listDomains(_configurableDomainList, strResult, bVertical); } size_t CConfigurableElement::getBelongingDomainCount() const { // Get belonging domain list std::list configurableDomainList; getBelongingDomains(configurableDomainList); return configurableDomainList.size(); } void CConfigurableElement::listDomains(const std::list& configurableDomainList, std::string& strResult, bool bVertical) const { if (bVertical && configurableDomainList.empty()) { strResult = "\n"; } // Fill list ConfigurableDomainListConstIterator it; bool bFirst = true; // Browse all configurable domains for comparison for (it = configurableDomainList.begin(); it != configurableDomainList.end(); ++it) { const CConfigurableDomain* pConfigurableDomain = *it; if (!bVertical && !bFirst) { strResult += ", "; } strResult += pConfigurableDomain->getName(); if (bVertical) { strResult += "\n"; } else { bFirst = false; } } } bool CConfigurableElement::containsConfigurableDomain(const CConfigurableDomain* pConfigurableDomain) const { ConfigurableDomainListConstIterator it; // Browse all configurable domains for comparison for (it = _configurableDomainList.begin(); it != _configurableDomainList.end(); ++it) { if (pConfigurableDomain == *it) { return true; } } return false; } // Belonging domain ascending search bool CConfigurableElement::belongsToDomainAscending(const CConfigurableDomain* pConfigurableDomain) const { // Check parent const CElement* pParent = getParent(); if (isOfConfigurableElementType(pParent)) { return static_cast(pParent)->belongsTo(pConfigurableDomain); } return false; } // Belonging subsystem const CSubsystem* CConfigurableElement::getBelongingSubsystem() const { const CElement* pParent = getParent(); // Stop at system class if (!pParent->getParent()) { return NULL; } return static_cast(pParent)->getBelongingSubsystem(); } // Check element is a parameter bool CConfigurableElement::isParameter() const { return false; } // Check parent is still of current type (by structure knowledge) bool CConfigurableElement::isOfConfigurableElementType(const CElement* pParent) const { assert(pParent); // Up to system class return !!pParent->getParent(); }