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