Home | History | Annotate | Download | only in parameter
      1 /*
      2  * Copyright (c) 2011-2015, Intel Corporation
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without modification,
      6  * are permitted provided that the following conditions are met:
      7  *
      8  * 1. Redistributions of source code must retain the above copyright notice, this
      9  * list of conditions and the following disclaimer.
     10  *
     11  * 2. Redistributions in binary form must reproduce the above copyright notice,
     12  * this list of conditions and the following disclaimer in the documentation and/or
     13  * other materials provided with the distribution.
     14  *
     15  * 3. Neither the name of the copyright holder nor the names of its contributors
     16  * may be used to endorse or promote products derived from this software without
     17  * specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
     23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 #include "ConfigurableElement.h"
     31 #include "MappingData.h"
     32 #include "SyncerSet.h"
     33 #include "ConfigurableDomain.h"
     34 #include "ConfigurationAccessContext.h"
     35 #include "ConfigurableElementAggregator.h"
     36 #include "AreaConfiguration.h"
     37 #include "Utility.h"
     38 #include <assert.h>
     39 
     40 #define base CElement
     41 
     42 CConfigurableElement::CConfigurableElement(const std::string& strName) : base(strName), _uiOffset(0)
     43 {
     44 }
     45 
     46 CConfigurableElement::~CConfigurableElement()
     47 {
     48 }
     49 
     50 // XML configuration settings parsing
     51 bool CConfigurableElement::serializeXmlSettings(CXmlElement& xmlConfigurationSettingsElementContent, CConfigurationAccessContext& configurationAccessContext) const
     52 {
     53     size_t uiIndex;
     54     size_t uiNbChildren = getNbChildren();
     55 
     56     if (!configurationAccessContext.serializeOut()) {
     57         // Just do basic checks and propagate to children
     58         CXmlElement::CChildIterator it(xmlConfigurationSettingsElementContent);
     59 
     60         CXmlElement xmlChildConfigurableElementSettingsElement;
     61 
     62         // Propagate to children
     63         for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
     64 
     65             // Get child
     66             const CConfigurableElement* pChildConfigurableElement = static_cast<const CConfigurableElement*>(getChild(uiIndex));
     67 
     68             if (!it.next(xmlChildConfigurableElementSettingsElement)) {
     69 
     70                 // Structure error
     71                 configurationAccessContext.setError("Configuration settings parsing: Settings don't conform to structure of configurable element " + getName());
     72 
     73                 return false;
     74             }
     75 
     76             // Check element type matches in type
     77             if (xmlChildConfigurableElementSettingsElement.getType() != pChildConfigurableElement->getKind()) {
     78 
     79                 // Type error
     80                 configurationAccessContext.setError("Configuration settings parsing: Settings for configurable element " + pChildConfigurableElement->getName() + " does not match expected type: " + xmlChildConfigurableElementSettingsElement.getType() + " instead of " + pChildConfigurableElement->getKind());
     81 
     82                 return false;
     83             }
     84 
     85             // Check element type matches in name
     86             if (xmlChildConfigurableElementSettingsElement.getNameAttribute() != pChildConfigurableElement->getName()) {
     87 
     88                 // Name error
     89                 configurationAccessContext.setError("Configuration settings parsing: Under configurable elememnt " + getName() + ", expected element name " + pChildConfigurableElement->getName() + " but found " + xmlChildConfigurableElementSettingsElement.getNameAttribute() + " instead");
     90 
     91                 return false;
     92             }
     93 
     94             // Parse child configurable element's settings
     95             if (!pChildConfigurableElement->serializeXmlSettings(xmlChildConfigurableElementSettingsElement, configurationAccessContext)) {
     96 
     97                 return false;
     98             }
     99         }
    100         // There should remain no configurable element to parse
    101         if (it.next(xmlChildConfigurableElementSettingsElement)) {
    102 
    103             // Structure error
    104             configurationAccessContext.setError("Configuration settings parsing: Settings don't conform to structure of configurable element " + getName());
    105 
    106             return false;
    107         }
    108     } else {
    109         // Propagate to children
    110         for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
    111 
    112             const CConfigurableElement* pChildConfigurableElement = static_cast<const CConfigurableElement*>(getChild(uiIndex));
    113 
    114             // Create corresponding child element
    115             CXmlElement xmlChildConfigurableElementSettingsElement;
    116 
    117             xmlConfigurationSettingsElementContent.createChild(xmlChildConfigurableElementSettingsElement, pChildConfigurableElement->getKind());
    118 
    119             // Handle element name attribute
    120             xmlChildConfigurableElementSettingsElement.setNameAttribute(pChildConfigurableElement->getName());
    121 
    122             // Propagate
    123             pChildConfigurableElement->serializeXmlSettings(xmlChildConfigurableElementSettingsElement, configurationAccessContext);
    124         }
    125     }
    126     // Done
    127     return true;
    128 }
    129 
    130 // AreaConfiguration creation
    131 CAreaConfiguration* CConfigurableElement::createAreaConfiguration(const CSyncerSet* pSyncerSet) const
    132 {
    133     return new CAreaConfiguration(this, pSyncerSet);
    134 }
    135 
    136 // Parameter access
    137 bool CConfigurableElement::accessValue(CPathNavigator& pathNavigator, std::string& strValue, bool bSet, CParameterAccessContext& parameterAccessContext) const
    138 {
    139     std::string* pStrChildName = pathNavigator.next();
    140 
    141     if (!pStrChildName) {
    142 
    143         parameterAccessContext.setError((bSet ? "Can't set " : "Can't get ") + pathNavigator.getCurrentPath() + " because it is not a parameter");
    144 
    145         return false;
    146     }
    147 
    148     const CConfigurableElement* pChild = static_cast<const CConfigurableElement*>(findChild(*pStrChildName));
    149 
    150     if (!pChild) {
    151 
    152         parameterAccessContext.setError("Path not found: " + pathNavigator.getCurrentPath());
    153 
    154         return false;
    155     }
    156 
    157     return pChild->accessValue(pathNavigator, strValue, bSet, parameterAccessContext);
    158 }
    159 
    160 void CConfigurableElement::getListOfElementsWithMapping(
    161         std::list<const CConfigurableElement*>& configurableElementPath) const
    162 {
    163     // Check parent
    164     const CElement* pParent = getParent();
    165     if (isOfConfigurableElementType(pParent)) {
    166 
    167         const CConfigurableElement* pConfigurableElement =
    168                 static_cast<const CConfigurableElement*>(pParent);
    169 
    170         pConfigurableElement->getListOfElementsWithMapping(configurableElementPath);
    171     }
    172 }
    173 
    174 // Used for simulation and virtual subsystems
    175 void CConfigurableElement::setDefaultValues(CParameterAccessContext& parameterAccessContext) const
    176 {
    177     // Propagate to children
    178     size_t uiIndex;
    179     size_t uiNbChildren = getNbChildren();
    180 
    181     for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
    182 
    183         const CConfigurableElement* pConfigurableElement = static_cast<const CConfigurableElement*>(getChild(uiIndex));
    184 
    185         pConfigurableElement->setDefaultValues(parameterAccessContext);
    186     }
    187 }
    188 
    189 // Element properties
    190 void CConfigurableElement::showProperties(std::string& strResult) const
    191 {
    192     base::showProperties(strResult);
    193 
    194     strResult += "Total size: " + getFootprintAsString() + "\n";
    195 }
    196 
    197 // Offset
    198 void CConfigurableElement::setOffset(uint32_t uiOffset)
    199 {
    200     // Assign offset locally
    201     _uiOffset = uiOffset;
    202 
    203     // Propagate to children
    204     size_t uiIndex;
    205     size_t uiNbChildren = getNbChildren();
    206 
    207     for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
    208 
    209         CConfigurableElement* pConfigurableElement = static_cast<CConfigurableElement*>(getChild(uiIndex));
    210 
    211         pConfigurableElement->setOffset(uiOffset);
    212 
    213         uiOffset += pConfigurableElement->getFootPrint();
    214     }
    215 }
    216 
    217 uint32_t CConfigurableElement::getOffset() const
    218 {
    219     return _uiOffset;
    220 }
    221 
    222 // Memory
    223 uint32_t CConfigurableElement::getFootPrint() const
    224 {
    225     uint32_t uiSize = 0;
    226     size_t uiIndex;
    227     size_t uiNbChildren = getNbChildren();
    228 
    229     for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
    230 
    231         const CConfigurableElement* pConfigurableElement = static_cast<const CConfigurableElement*>(getChild(uiIndex));
    232 
    233         uiSize += pConfigurableElement->getFootPrint();
    234     }
    235 
    236     return uiSize;
    237 }
    238 
    239 // Browse parent path to find syncer
    240 ISyncer* CConfigurableElement::getSyncer() const
    241 {
    242     // Check parent
    243     const CElement* pParent = getParent();
    244 
    245     if (isOfConfigurableElementType(pParent)) {
    246 
    247         return static_cast<const CConfigurableElement*>(pParent)->getSyncer();
    248     }
    249     return NULL;
    250 }
    251 
    252 // Syncer set (me, ascendant or descendant ones)
    253 void CConfigurableElement::fillSyncerSet(CSyncerSet& syncerSet) const
    254 {
    255     //  Try me or ascendants
    256     ISyncer* pMineOrAscendantSyncer = getSyncer();
    257 
    258     if (pMineOrAscendantSyncer) {
    259 
    260         // Provide found syncer object
    261         syncerSet += pMineOrAscendantSyncer;
    262 
    263         // Done
    264         return;
    265     }
    266     // Fetch descendant ones
    267     fillSyncerSetFromDescendant(syncerSet);
    268 }
    269 
    270 // Syncer set (descendant)
    271 void CConfigurableElement::fillSyncerSetFromDescendant(CSyncerSet& syncerSet) const
    272 {
    273     // Dig
    274     size_t uiIndex;
    275     size_t uiNbChildren = getNbChildren();
    276 
    277     for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
    278 
    279         const CConfigurableElement* pConfigurableElement = static_cast<const CConfigurableElement*>(getChild(uiIndex));
    280 
    281         pConfigurableElement->fillSyncerSetFromDescendant(syncerSet);
    282     }
    283 }
    284 
    285 // Configurable domain association
    286 void CConfigurableElement::addAttachedConfigurableDomain(const CConfigurableDomain* pConfigurableDomain)
    287 {
    288     _configurableDomainList.push_back(pConfigurableDomain);
    289 }
    290 
    291 void CConfigurableElement::removeAttachedConfigurableDomain(const CConfigurableDomain* pConfigurableDomain)
    292 {
    293     _configurableDomainList.remove(pConfigurableDomain);
    294 }
    295 
    296 // Belonging domain
    297 bool CConfigurableElement::belongsTo(const CConfigurableDomain* pConfigurableDomain) const
    298 {
    299     if (containsConfigurableDomain(pConfigurableDomain)) {
    300 
    301         return true;
    302     }
    303     return belongsToDomainAscending(pConfigurableDomain);
    304 }
    305 
    306 // Belonging domains
    307 void CConfigurableElement::getBelongingDomains(std::list<const CConfigurableDomain*>& configurableDomainList) const
    308 {
    309     configurableDomainList.insert(configurableDomainList.end(), _configurableDomainList.begin(), _configurableDomainList.end());
    310 
    311     // Check parent
    312     const CElement* pParent = getParent();
    313 
    314     if (isOfConfigurableElementType(pParent)) {
    315 
    316         static_cast<const CConfigurableElement*>(pParent)->getBelongingDomains(configurableDomainList);
    317     }
    318 }
    319 
    320 void CConfigurableElement::listBelongingDomains(std::string& strResult, bool bVertical) const
    321 {
    322     // Get belonging domain list
    323     std::list<const CConfigurableDomain*> configurableDomainList;
    324 
    325     getBelongingDomains(configurableDomainList);
    326 
    327     // Fill list
    328     listDomains(configurableDomainList, strResult, bVertical);
    329 }
    330 
    331 // Elements with no domains
    332 void CConfigurableElement::listRogueElements(std::string& strResult) const
    333 {
    334     strResult = "\n";
    335 
    336     // Get rogue element aggregate list (no associated domain)
    337     std::list<const CConfigurableElement*> rogueElementList;
    338 
    339     CConfigurableElementAggregator configurableElementAggregator(rogueElementList, &CConfigurableElement::hasNoDomainAssociated);
    340 
    341     configurableElementAggregator.aggegate(this);
    342 
    343     // Build list as std::string
    344     std::list<const CConfigurableElement*>::const_iterator it;
    345 
    346     for (it = rogueElementList.begin(); it != rogueElementList.end(); ++it) {
    347 
    348         const CConfigurableElement* pConfigurableElement = *it;
    349 
    350         strResult += pConfigurableElement->getPath() + "\n";
    351     }
    352 }
    353 
    354 // Belonging to no domains
    355 bool CConfigurableElement::isRogue() const
    356 {
    357     return !getBelongingDomainCount();
    358 }
    359 
    360 // Footprint as string
    361 std::string CConfigurableElement::getFootprintAsString() const
    362 {
    363     // Get size as string
    364     return CUtility::toString(getFootPrint()) + " byte(s)";
    365 }
    366 
    367 // Matching check for no domain association
    368 bool CConfigurableElement::hasNoDomainAssociated() const
    369 {
    370     return _configurableDomainList.empty();
    371 }
    372 
    373 // Matching check for no valid associated domains
    374 bool CConfigurableElement::hasNoValidDomainAssociated() const
    375 {
    376     if (_configurableDomainList.empty()) {
    377 
    378         // No domains associated
    379         return true;
    380     }
    381 
    382     ConfigurableDomainListConstIterator it;
    383 
    384     // Browse all configurable domains for validity checking
    385     for (it = _configurableDomainList.begin(); it != _configurableDomainList.end(); ++it) {
    386 
    387         const CConfigurableDomain* pConfigurableDomain = *it;
    388 
    389         if (pConfigurableDomain->isApplicableConfigurationValid(this)) {
    390 
    391             return false;
    392         }
    393     }
    394 
    395     return true;
    396 }
    397 
    398 // Owning domains
    399 void CConfigurableElement::listAssociatedDomains(std::string& strResult, bool bVertical) const
    400 {
    401     // Fill list
    402     listDomains(_configurableDomainList, strResult, bVertical);
    403 }
    404 
    405 size_t CConfigurableElement::getBelongingDomainCount() const
    406 {
    407     // Get belonging domain list
    408     std::list<const CConfigurableDomain*> configurableDomainList;
    409 
    410     getBelongingDomains(configurableDomainList);
    411 
    412     return configurableDomainList.size();
    413 }
    414 
    415 void CConfigurableElement::listDomains(const std::list<const CConfigurableDomain*>& configurableDomainList, std::string& strResult, bool bVertical) const
    416 {
    417     if (bVertical && configurableDomainList.empty()) {
    418 
    419         strResult = "\n";
    420     }
    421 
    422     // Fill list
    423     ConfigurableDomainListConstIterator it;
    424     bool bFirst = true;
    425 
    426     // Browse all configurable domains for comparison
    427     for (it = configurableDomainList.begin(); it != configurableDomainList.end(); ++it) {
    428 
    429         const CConfigurableDomain* pConfigurableDomain = *it;
    430 
    431         if (!bVertical && !bFirst) {
    432 
    433             strResult += ", ";
    434         }
    435 
    436         strResult += pConfigurableDomain->getName();
    437 
    438         if (bVertical) {
    439 
    440             strResult += "\n";
    441         } else {
    442 
    443             bFirst = false;
    444         }
    445     }
    446 }
    447 
    448 bool CConfigurableElement::containsConfigurableDomain(const CConfigurableDomain* pConfigurableDomain) const
    449 {
    450     ConfigurableDomainListConstIterator it;
    451 
    452     // Browse all configurable domains for comparison
    453     for (it = _configurableDomainList.begin(); it != _configurableDomainList.end(); ++it) {
    454 
    455         if (pConfigurableDomain == *it) {
    456 
    457             return true;
    458         }
    459     }
    460     return false;
    461 }
    462 
    463 // Belonging domain ascending search
    464 bool CConfigurableElement::belongsToDomainAscending(const CConfigurableDomain* pConfigurableDomain) const
    465 {
    466     // Check parent
    467     const CElement* pParent = getParent();
    468 
    469     if (isOfConfigurableElementType(pParent)) {
    470 
    471         return static_cast<const CConfigurableElement*>(pParent)->belongsTo(pConfigurableDomain);
    472     }
    473     return false;
    474 }
    475 
    476 // Belonging subsystem
    477 const CSubsystem* CConfigurableElement::getBelongingSubsystem() const
    478 {
    479     const CElement* pParent = getParent();
    480 
    481     // Stop at system class
    482     if (!pParent->getParent()) {
    483 
    484         return NULL;
    485     }
    486 
    487     return static_cast<const CConfigurableElement*>(pParent)->getBelongingSubsystem();
    488 }
    489 
    490 // Check element is a parameter
    491 bool CConfigurableElement::isParameter() const
    492 {
    493     return false;
    494 }
    495 
    496 
    497 // Check parent is still of current type (by structure knowledge)
    498 bool CConfigurableElement::isOfConfigurableElementType(const CElement* pParent) const
    499 {
    500     assert(pParent);
    501 
    502     // Up to system class
    503     return !!pParent->getParent();
    504 }
    505