ConfigurableDomain.cpp revision d8a53107d5f965c8ca406ee95f5999efd6694730
1/* 2 * Copyright (c) 2011-2014, 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 "ConfigurableDomain.h" 31#include "DomainConfiguration.h" 32#include "ConfigurableElement.h" 33#include "ConfigurationAccessContext.h" 34#include "XmlDomainSerializingContext.h" 35#include "XmlDomainImportContext.h" 36#include "XmlDomainExportContext.h" 37#include <assert.h> 38 39#define base CBinarySerializableElement 40 41using std::string; 42 43CConfigurableDomain::CConfigurableDomain(const string& strName) : base(strName), _bSequenceAware(false), _pLastAppliedConfiguration(NULL) 44{ 45} 46 47CConfigurableDomain::~CConfigurableDomain() 48{ 49 // Remove all configurable elements 50 ConfigurableElementListIterator it; 51 52 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) { 53 54 CConfigurableElement* pConfigurableElement = *it; 55 56 // Remove from configurable element 57 pConfigurableElement->removeAttachedConfigurableDomain(this); 58 } 59 60 // Remove all associated syncer sets 61 ConfigurableElementToSyncerSetMapIterator mapIt; 62 63 for (mapIt = _configurableElementToSyncerSetMap.begin(); mapIt != _configurableElementToSyncerSetMap.end(); ++mapIt) { 64 65 delete mapIt->second; 66 } 67} 68 69string CConfigurableDomain::getKind() const 70{ 71 return "ConfigurableDomain"; 72} 73 74bool CConfigurableDomain::childrenAreDynamic() const 75{ 76 return true; 77} 78 79// Content dumping 80void CConfigurableDomain::logValue(string& strValue, CErrorContext& errorContext) const 81{ 82 (void)errorContext; 83 84 strValue = "{"; 85 86 // Sequence awareness 87 strValue += "Sequence aware: "; 88 strValue += _bSequenceAware ? "yes" : "no"; 89 90 // Last applied configuration 91 strValue += ", Last applied configuration: "; 92 strValue += _pLastAppliedConfiguration ? _pLastAppliedConfiguration->getName() : "<none>"; 93 94 strValue += "}"; 95} 96 97// Sequence awareness 98void CConfigurableDomain::setSequenceAwareness(bool bSequenceAware) 99{ 100 if (_bSequenceAware != bSequenceAware) { 101 102 log_info("Making domain \"%s\" sequence %s", getName().c_str(), bSequenceAware ? "aware" : "unaware"); 103 104 _bSequenceAware = bSequenceAware; 105 } 106} 107 108bool CConfigurableDomain::getSequenceAwareness() const 109{ 110 return _bSequenceAware; 111} 112 113// From IXmlSource 114void CConfigurableDomain::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const 115{ 116 base::toXml(xmlElement, serializingContext); 117 118 // Sequence awareness 119 xmlElement.setAttributeBoolean("SequenceAware", _bSequenceAware); 120} 121 122void CConfigurableDomain::childrenToXml(CXmlElement& xmlElement, 123 CXmlSerializingContext& serializingContext) const 124{ 125 // Configurations 126 composeDomainConfigurations(xmlElement, serializingContext); 127 128 // Configurable Elements 129 composeConfigurableElements(xmlElement); 130 131 // Settings 132 composeSettings(xmlElement, serializingContext); 133} 134 135// XML composing 136void CConfigurableDomain::composeDomainConfigurations(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const 137{ 138 // Create Configurations element 139 CXmlElement xmlConfigurationsElement; 140 141 xmlElement.createChild(xmlConfigurationsElement, "Configurations"); 142 143 // Delegate to base 144 base::childrenToXml(xmlConfigurationsElement, serializingContext); 145} 146 147void CConfigurableDomain::composeConfigurableElements(CXmlElement& xmlElement) const 148{ 149 // Create ConfigurableElements element 150 CXmlElement xmlConfigurableElementsElement; 151 152 xmlElement.createChild(xmlConfigurableElementsElement, "ConfigurableElements"); 153 154 // Serialize out all configurable elements settings 155 ConfigurableElementListIterator it; 156 157 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) { 158 159 const CConfigurableElement* pConfigurableElement = *it; 160 161 // Create corresponding XML child element 162 CXmlElement xmlChildConfigurableElement; 163 164 xmlConfigurableElementsElement.createChild(xmlChildConfigurableElement, "ConfigurableElement"); 165 166 // Set Path attribute 167 xmlChildConfigurableElement.setAttributeString("Path", pConfigurableElement->getPath()); 168 } 169} 170 171void CConfigurableDomain::composeSettings(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const 172{ 173 // Context 174 const CXmlDomainExportContext& xmlDomainExportContext = 175 static_cast<const CXmlDomainExportContext&>(serializingContext); 176 177 if (!xmlDomainExportContext.withSettings()) { 178 179 return; 180 } 181 182 // Create Settings element 183 CXmlElement xmlSettingsElement; 184 185 xmlElement.createChild(xmlSettingsElement, "Settings"); 186 187 // Serialize out all configurations settings 188 uint32_t uiNbConfigurations = getNbChildren(); 189 uint32_t uiChildConfiguration; 190 191 for (uiChildConfiguration = 0; uiChildConfiguration < uiNbConfigurations; uiChildConfiguration++) { 192 193 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChildConfiguration)); 194 195 // Create child xml element for that configuration 196 CXmlElement xmlConfigurationSettingsElement; 197 198 xmlSettingsElement.createChild(xmlConfigurationSettingsElement, pDomainConfiguration->getKind()); 199 200 // Set its name attribute 201 xmlConfigurationSettingsElement.setNameAttribute(pDomainConfiguration->getName()); 202 203 // Serialize out configuration settings 204 pDomainConfiguration->composeSettings(xmlConfigurationSettingsElement, serializingContext); 205 } 206} 207 208// From IXmlSink 209bool CConfigurableDomain::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) 210{ 211 // Context 212 CXmlDomainImportContext& xmlDomainImportContext = 213 static_cast<CXmlDomainImportContext&>(serializingContext); 214 215 // Sequence awareness (optional) 216 _bSequenceAware = xmlElement.hasAttribute("SequenceAware") && xmlElement.getAttributeBoolean("SequenceAware"); 217 218 // Local parsing. Do not dig 219 if (!parseDomainConfigurations(xmlElement, xmlDomainImportContext) || 220 !parseConfigurableElements(xmlElement, xmlDomainImportContext) || 221 !parseSettings(xmlElement, xmlDomainImportContext)) { 222 223 return false; 224 } 225 226 // All provided configurations are parsed 227 // Attempt validation on areas of non provided configurations for all configurable elements if required 228 if (xmlDomainImportContext.autoValidationRequired()) { 229 230 autoValidateAll(); 231 } 232 233 return true; 234} 235 236// XML parsing 237bool CConfigurableDomain::parseDomainConfigurations(const CXmlElement& xmlElement, 238 CXmlDomainImportContext& serializingContext) 239{ 240 // We're supposedly clean 241 assert(_configurableElementList.empty()); 242 243 // Get Configurations element 244 CXmlElement xmlConfigurationsElement; 245 246 xmlElement.getChildElement("Configurations", xmlConfigurationsElement); 247 248 // Parse it and create domain configuration objects 249 return base::fromXml(xmlConfigurationsElement, serializingContext); 250} 251 252// Parse configurable elements 253bool CConfigurableDomain::parseConfigurableElements(const CXmlElement& xmlElement, 254 CXmlDomainImportContext& serializingContext) 255{ 256 CSystemClass& systemClass = serializingContext.getSystemClass(); 257 258 // Get ConfigurableElements element 259 CXmlElement xmlConfigurableElementsElement; 260 xmlElement.getChildElement("ConfigurableElements", xmlConfigurableElementsElement); 261 262 // Parse it and associate found configurable elements to it 263 CXmlElement::CChildIterator it(xmlConfigurableElementsElement); 264 265 CXmlElement xmlConfigurableElementElement; 266 267 while (it.next(xmlConfigurableElementElement)) { 268 269 // Locate configurable element 270 string strConfigurableElementPath = xmlConfigurableElementElement.getAttributeString("Path"); 271 272 CPathNavigator pathNavigator(strConfigurableElementPath); 273 string strError; 274 275 // Is there an element and does it match system class name? 276 if (!pathNavigator.navigateThrough(systemClass.getName(), strError)) { 277 278 serializingContext.setError("Could not find configurable element of path " + strConfigurableElementPath + " from ConfigurableDomain description " + getName() + " (" + strError + ")"); 279 280 return false; 281 } 282 // Browse system class for configurable element 283 CConfigurableElement* pConfigurableElement = 284 static_cast<CConfigurableElement*>(systemClass.findDescendant(pathNavigator)); 285 286 if (!pConfigurableElement) { 287 288 serializingContext.setError("Could not find configurable element of path " + strConfigurableElementPath + " from ConfigurableDomain description " + getName()); 289 290 return false; 291 } 292 // Add found element to domain 293 if (!addConfigurableElement(pConfigurableElement, NULL, strError)) { 294 295 serializingContext.setError(strError); 296 297 return false; 298 } 299 } 300 301 return true; 302} 303 304// Parse settings 305bool CConfigurableDomain::parseSettings(const CXmlElement& xmlElement, 306 CXmlDomainImportContext& serializingContext) 307{ 308 // Check we actually need to parse configuration settings 309 if (!serializingContext.withSettings()) { 310 311 // No parsing required 312 return true; 313 } 314 315 // Get Settings element 316 CXmlElement xmlSettingsElement; 317 if (!xmlElement.getChildElement("Settings", xmlSettingsElement)) { 318 319 // No settings, bail out successfully 320 return true; 321 } 322 323 // Parse configuration settings 324 CXmlElement::CChildIterator it(xmlSettingsElement); 325 326 CXmlElement xmlConfigurationSettingsElement; 327 328 while (it.next(xmlConfigurationSettingsElement)) { 329 // Get domain configuration 330 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(xmlConfigurationSettingsElement.getNameAttribute())); 331 332 if (!pDomainConfiguration) { 333 334 serializingContext.setError("Could not find domain configuration referred to by" 335 " configurable domain \"" + getName() + "\"."); 336 337 return false; 338 } 339 // Have domain configuration parse settings for all configurable elements 340 if (!pDomainConfiguration->parseSettings(xmlConfigurationSettingsElement, 341 serializingContext)) { 342 343 return false; 344 } 345 } 346 347 return true; 348} 349// Configurable elements association 350bool CConfigurableDomain::addConfigurableElement(CConfigurableElement* pConfigurableElement, const CParameterBlackboard* pMainBlackboard, string& strError) 351{ 352 // Already associated? 353 if (containsConfigurableElement(pConfigurableElement)) { 354 355 strError = "Configurable element " + pConfigurableElement->getPath() + " already associated to configuration domain " + getName(); 356 357 return false; 358 } 359 360 // Already owned? 361 if (pConfigurableElement->belongsTo(this)) { 362 363 strError = "Configurable element " + pConfigurableElement->getPath() + " already owned by configuration domain " + getName(); 364 365 return false; 366 } 367 368 // Do add 369 doAddConfigurableElement(pConfigurableElement, pMainBlackboard); 370 371 return true; 372} 373 374bool CConfigurableDomain::removeConfigurableElement(CConfigurableElement* pConfigurableElement, string& strError) 375{ 376 // Not associated? 377 if (!containsConfigurableElement(pConfigurableElement)) { 378 379 strError = "Configurable element " + pConfigurableElement->getPath() + " not associated to configuration domain " + getName(); 380 381 return false; 382 } 383 log_info("Removing configurable element \"%s\" from domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str()); 384 385 // Do remove 386 doRemoveConfigurableElement(pConfigurableElement, true); 387 388 return true; 389} 390 391/** 392* Blackboard Configuration and Base Offset retrieval. 393* 394* This method fetches the Blackboard associated to the ConfigurableElement 395* given in parameter, for a specific Configuration. The ConfigurableElement 396* must belong to the Domain. If a Blackboard is found, the base offset of 397* the ConfigurableElement is returned as well. This base offset corresponds to 398* the offset of the ancestor of the ConfigurableElement associated to the Configuration. 399* 400* @param[in] strConfiguration Name of the Configuration. 401* @param[in] pCandidateDescendantConfigurableElement Pointer to a CConfigurableElement that 402* belongs to the Domain. 403* @param[out] uiBaseOffset The base offset of the CConfigurableElement. 404* @param[out] bIsLastApplied Boolean indicating that the Configuration is 405* the last one applied of the Domain. 406* @param[out] strError Error message 407* 408* return Pointer to the Blackboard of the Configuration. 409*/ 410CParameterBlackboard* CConfigurableDomain::findConfigurationBlackboard(const string& strConfiguration, 411 const CConfigurableElement* pCandidateDescendantConfigurableElement, 412 uint32_t& uiBaseOffset, 413 bool& bIsLastApplied, 414 string& strError) const 415{ 416 // Find Configuration 417 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(findChild(strConfiguration)); 418 419 if (!pDomainConfiguration) { 420 421 strError = "Domain configuration " + strConfiguration + " not found"; 422 423 return NULL; 424 } 425 426 // Parse all configurable elements 427 ConfigurableElementListIterator it; 428 429 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) { 430 431 const CConfigurableElement* pAssociatedConfigurableElement = *it; 432 433 // Check if the the associated element is the configurable element or one of its ancestors 434 if ((pCandidateDescendantConfigurableElement == pAssociatedConfigurableElement) || 435 (pCandidateDescendantConfigurableElement->isDescendantOf(pAssociatedConfigurableElement))) { 436 437 uiBaseOffset = pAssociatedConfigurableElement->getOffset(); 438 bIsLastApplied = (pDomainConfiguration == _pLastAppliedConfiguration); 439 440 return pDomainConfiguration->getBlackboard(pAssociatedConfigurableElement); 441 } 442 } 443 444 strError = "Element not associated to the Domain"; 445 446 return NULL; 447} 448 449// Domain splitting 450bool CConfigurableDomain::split(CConfigurableElement* pConfigurableElement, string& strError) 451{ 452 // Not associated? 453 if (!containsConfigurableElement(pConfigurableElement)) { 454 455 strError = "Configurable element " + pConfigurableElement->getPath() + " not associated to configuration domain " + getName(); 456 457 return false; 458 } 459 log_info("Splitting configurable element \"%s\" domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str()); 460 461 // Create sub domain areas for all configurable element's children 462 uint32_t uiNbConfigurableElementChildren = pConfigurableElement->getNbChildren(); 463 464 if (!uiNbConfigurableElementChildren) { 465 466 strError = "Configurable element " + pConfigurableElement->getPath() + " has no children to split configurable domain to"; 467 468 return false; 469 } 470 471 uint32_t uiChild; 472 473 for (uiChild = 0; uiChild < uiNbConfigurableElementChildren; uiChild++) { 474 475 CConfigurableElement* pChildConfigurableElement = static_cast<CConfigurableElement*>(pConfigurableElement->getChild(uiChild)); 476 477 doAddConfigurableElement(pChildConfigurableElement); 478 } 479 480 // Delegate to configurations 481 uint32_t uiNbConfigurations = getNbChildren(); 482 483 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { 484 485 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild)); 486 487 pDomainConfiguration->split(pConfigurableElement); 488 } 489 490 // Remove given configurable element from this domain 491 // 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 492 doRemoveConfigurableElement(pConfigurableElement, false); 493 494 return true; 495} 496 497// Check if there is a pending configuration for this domain: i.e. an applicable configuration different from the last applied configuration 498const CDomainConfiguration* CConfigurableDomain::getPendingConfiguration() const 499{ 500 const CDomainConfiguration* pApplicableDomainConfiguration = findApplicableDomainConfiguration(); 501 502 if (pApplicableDomainConfiguration) { 503 504 // Check not the last one before applying 505 if (!_pLastAppliedConfiguration || (_pLastAppliedConfiguration != pApplicableDomainConfiguration)) { 506 507 return pApplicableDomainConfiguration; 508 } 509 } 510 511 return NULL; 512} 513 514// Configuration application if required 515void CConfigurableDomain::apply(CParameterBlackboard* pParameterBlackboard, CSyncerSet* pSyncerSet, bool bForce) const 516{ 517 // Apply configuration only if the blackboard will 518 // be synchronized either now or by syncerSet. 519 if(!pSyncerSet ^ _bSequenceAware) { 520 // The configuration can not be syncronised 521 return; 522 } 523 524 if (bForce) { 525 // Force a configuration restore by forgetting about last applied configuration 526 _pLastAppliedConfiguration = NULL; 527 } 528 const CDomainConfiguration* pApplicableDomainConfiguration = findApplicableDomainConfiguration(); 529 530 if (pApplicableDomainConfiguration) { 531 532 // Check not the last one before applying 533 if (!_pLastAppliedConfiguration || _pLastAppliedConfiguration != pApplicableDomainConfiguration) { 534 535 log_info("Applying configuration \"%s\" from domain \"%s\"", 536 pApplicableDomainConfiguration->getName().c_str(), 537 getName().c_str()); 538 539 // Check if we need to synchronize during restore 540 bool bSync = !pSyncerSet && _bSequenceAware; 541 542 // Do the restore 543 pApplicableDomainConfiguration->restore(pParameterBlackboard, bSync, NULL); 544 545 // Record last applied configuration 546 _pLastAppliedConfiguration = pApplicableDomainConfiguration; 547 548 // Check we need to provide syncer set to caller 549 if (pSyncerSet && !_bSequenceAware) { 550 551 // Since we applied changes, add our own sync set to the given one 552 *pSyncerSet += _syncerSet; 553 } 554 } 555 } 556} 557 558// Return applicable configuration validity for given configurable element 559bool CConfigurableDomain::isApplicableConfigurationValid(const CConfigurableElement* pConfigurableElement) const 560{ 561 const CDomainConfiguration* pApplicableDomainConfiguration = findApplicableDomainConfiguration(); 562 563 return pApplicableDomainConfiguration && pApplicableDomainConfiguration->isValid(pConfigurableElement); 564} 565 566// In case configurable element was removed 567void CConfigurableDomain::computeSyncSet() 568{ 569 // Clean sync set first 570 _syncerSet.clear(); 571 572 // Add syncer sets for all associated configurable elements 573 ConfigurableElementToSyncerSetMapIterator mapIt; 574 575 for (mapIt = _configurableElementToSyncerSetMap.begin(); mapIt != _configurableElementToSyncerSetMap.end(); ++mapIt) { 576 577 const CSyncerSet* pSyncerSet = mapIt->second; 578 579 _syncerSet += *pSyncerSet; 580 } 581} 582 583// Configuration Management 584bool CConfigurableDomain::createConfiguration(const string& strName, const CParameterBlackboard* pMainBlackboard, string& strError) 585{ 586 // Already exists? 587 if (findChild(strName)) { 588 589 strError = "Already existing configuration"; 590 591 return false; 592 } 593 log_info("Creating domain configuration \"%s\" into domain \"%s\"", strName.c_str(), getName().c_str()); 594 595 // Creation 596 CDomainConfiguration* pDomainConfiguration = new CDomainConfiguration(strName); 597 598 // Configurable elements association 599 ConfigurableElementListIterator it; 600 601 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) { 602 603 const CConfigurableElement* pConfigurableElement = *it;; 604 605 // Retrieve associated syncer set 606 CSyncerSet* pSyncerSet = getSyncerSet(pConfigurableElement); 607 608 // Associate to configuration 609 pDomainConfiguration->addConfigurableElement(pConfigurableElement, pSyncerSet); 610 } 611 612 // Hierarchy 613 addChild(pDomainConfiguration); 614 615 // Ensure validity of fresh new domain configuration 616 // Attempt auto validation, so that the user gets his/her own settings by defaults 617 if (!autoValidateConfiguration(pDomainConfiguration)) { 618 619 // No valid configuration found to copy in from, validate againt main blackboard (will concerned remaining invalid parts) 620 pDomainConfiguration->validate(pMainBlackboard); 621 } 622 623 return true; 624} 625 626bool CConfigurableDomain::deleteConfiguration(const string& strName, string& strError) 627{ 628 CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError); 629 630 if (!pDomainConfiguration) { 631 632 return false; 633 } 634 635 log_info("Deleting configuration \"%s\" from domain \"%s\"", strName.c_str(), getName().c_str()); 636 637 // Was the last applied? 638 if (pDomainConfiguration == _pLastAppliedConfiguration) { 639 640 // Forget about it 641 _pLastAppliedConfiguration = NULL; 642 } 643 644 // Hierarchy 645 removeChild(pDomainConfiguration); 646 647 // Destroy 648 delete pDomainConfiguration; 649 650 return true; 651} 652 653void CConfigurableDomain::listAssociatedToElements(string& strResult) const 654{ 655 strResult = "\n"; 656 657 ConfigurableElementListIterator it; 658 659 // Browse all configurable elements 660 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) { 661 662 const CConfigurableElement* pConfigurableElement = *it; 663 664 strResult += pConfigurableElement->getPath() + "\n"; 665 } 666} 667 668bool CConfigurableDomain::renameConfiguration(const string& strName, const string& strNewName, string& strError) 669{ 670 CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError); 671 672 if (!pDomainConfiguration) { 673 674 return false; 675 } 676 log_info("Renaming domain \"%s\"'s configuration \"%s\" to \"%s\"", getName().c_str(), strName.c_str(), strNewName.c_str()); 677 678 // Rename 679 return pDomainConfiguration->rename(strNewName, strError); 680} 681 682bool CConfigurableDomain::restoreConfiguration(const string& strName, CParameterBlackboard* pMainBlackboard, bool bAutoSync, std::list<string>& lstrError) const 683{ 684 string strError; 685 686 const CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError); 687 688 if (!pDomainConfiguration) { 689 690 lstrError.push_back(strError); 691 return false; 692 } 693 log_info("Restoring domain \"%s\"'s configuration \"%s\" to parameter blackboard", getName().c_str(), pDomainConfiguration->getName().c_str()); 694 695 // Delegate 696 bool bSuccess = pDomainConfiguration->restore(pMainBlackboard, bAutoSync && _bSequenceAware, &lstrError); 697 698 // Record last applied configuration 699 _pLastAppliedConfiguration = pDomainConfiguration; 700 701 // Synchronize 702 if (bAutoSync && !_bSequenceAware) { 703 704 bSuccess &= _syncerSet.sync(*pMainBlackboard, false, &lstrError); 705 } 706 return bSuccess; 707} 708 709bool CConfigurableDomain::saveConfiguration(const string& strName, const CParameterBlackboard* pMainBlackboard, string& strError) 710{ 711 // Find Domain configuration 712 CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError); 713 714 if (!pDomainConfiguration) { 715 716 return false; 717 } 718 log_info("Saving domain \"%s\"'s configuration \"%s\" from parameter blackboard", getName().c_str(), pDomainConfiguration->getName().c_str()); 719 720 // Delegate 721 pDomainConfiguration->save(pMainBlackboard); 722 723 return true; 724} 725 726bool CConfigurableDomain::setElementSequence(const string& strConfiguration, const std::vector<string>& astrNewElementSequence, string& strError) 727{ 728 // Find Domain configuration 729 CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strError); 730 731 if (!pDomainConfiguration) { 732 733 return false; 734 } 735 736 // Delegate to configuration 737 return pDomainConfiguration->setElementSequence(astrNewElementSequence, strError); 738} 739 740bool CConfigurableDomain::getElementSequence(const string& strConfiguration, string& strResult) const 741{ 742 // Find Domain configuration 743 const CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strResult); 744 745 if (!pDomainConfiguration) { 746 747 return false; 748 } 749 750 // Delegate to configuration 751 pDomainConfiguration->getElementSequence(strResult); 752 753 return true; 754} 755 756bool CConfigurableDomain::setApplicationRule(const string& strConfiguration, const string& strApplicationRule, const CSelectionCriteriaDefinition* pSelectionCriteriaDefinition, string& strError) 757{ 758 // Find Domain configuration 759 CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strError); 760 761 if (!pDomainConfiguration) { 762 763 return false; 764 } 765 766 // Delegate to configuration 767 return pDomainConfiguration->setApplicationRule(strApplicationRule, pSelectionCriteriaDefinition, strError); 768} 769 770bool CConfigurableDomain::clearApplicationRule(const string& strConfiguration, string& strError) 771{ 772 // Find Domain configuration 773 CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strError); 774 775 if (!pDomainConfiguration) { 776 777 return false; 778 } 779 780 // Delegate to configuration 781 pDomainConfiguration->clearApplicationRule(); 782 783 return true; 784} 785 786bool CConfigurableDomain::getApplicationRule(const string& strConfiguration, string& strResult) const 787{ 788 // Find Domain configuration 789 const CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strResult); 790 791 if (!pDomainConfiguration) { 792 793 return false; 794 } 795 796 // Delegate to configuration 797 pDomainConfiguration->getApplicationRule(strResult); 798 799 return true; 800} 801 802// Last applied configuration 803string CConfigurableDomain::getLastAppliedConfigurationName() const 804{ 805 if (_pLastAppliedConfiguration) { 806 807 return _pLastAppliedConfiguration->getName(); 808 } 809 return "<none>"; 810} 811 812// Pending configuration 813string CConfigurableDomain::getPendingConfigurationName() const 814{ 815 const CDomainConfiguration* pPendingConfiguration = getPendingConfiguration(); 816 817 if (pPendingConfiguration) { 818 819 return pPendingConfiguration->getName(); 820 } 821 return "<none>"; 822} 823 824// Ensure validity on whole domain from main blackboard 825void CConfigurableDomain::validate(const CParameterBlackboard* pMainBlackboard) 826{ 827 828 // Propagate 829 uint32_t uiNbConfigurations = getNbChildren(); 830 uint32_t uiChild; 831 832 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { 833 834 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild)); 835 836 pDomainConfiguration->validate(pMainBlackboard); 837 } 838} 839 840// Ensure validity on areas related to configurable element 841void CConfigurableDomain::validateAreas(const CConfigurableElement* pConfigurableElement, const CParameterBlackboard* pMainBlackboard) 842{ 843 log_info("Validating domain \"" + getName() + "\" against main blackboard for configurable element \"" + pConfigurableElement->getPath() + "\""); 844 845 // Propagate 846 uint32_t uiNbConfigurations = getNbChildren(); 847 uint32_t uiChild; 848 849 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { 850 851 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild)); 852 853 pDomainConfiguration->validate(pConfigurableElement, pMainBlackboard); 854 } 855} 856 857// Attempt validation for all configurable element's areas, relying on already existing valid configuration inside domain 858void CConfigurableDomain::autoValidateAll() 859{ 860 // Validate 861 ConfigurableElementListIterator it; 862 863 // Browse all configurable elements for configuration validation 864 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) { 865 866 const CConfigurableElement* pConfigurableElement = *it; 867 868 // Auto validate element 869 autoValidateAreas(pConfigurableElement); 870 } 871} 872 873// Attempt validation for configurable element's areas, relying on already existing valid configuration inside domain 874void CConfigurableDomain::autoValidateAreas(const CConfigurableElement* pConfigurableElement) 875{ 876 // Find first valid configuration for given configurable element 877 const CDomainConfiguration* pValidDomainConfiguration = findValidDomainConfiguration(pConfigurableElement); 878 879 // No valid configuration found, give up 880 if (!pValidDomainConfiguration) { 881 882 return; 883 } 884 885 // Validate all other configurations against found one, if any 886 uint32_t uiNbConfigurations = getNbChildren(); 887 uint32_t uiChild; 888 889 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { 890 891 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild)); 892 893 if (pDomainConfiguration != pValidDomainConfiguration && !pDomainConfiguration->isValid(pConfigurableElement)) { 894 // Validate 895 pDomainConfiguration->validateAgainst(pValidDomainConfiguration, pConfigurableElement); 896 } 897 } 898} 899 900// Attempt configuration validation for all configurable elements' areas, relying on already existing valid configuration inside domain 901bool CConfigurableDomain::autoValidateConfiguration(CDomainConfiguration* pDomainConfiguration) 902{ 903 // Find another configuration than this one, that ought to be valid! 904 uint32_t uiNbConfigurations = getNbChildren(); 905 uint32_t uiChild; 906 907 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { 908 909 const CDomainConfiguration* pPotententialValidDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild)); 910 911 if (pPotententialValidDomainConfiguration != pDomainConfiguration) { 912 913 // Validate against it 914 pDomainConfiguration->validateAgainst(pPotententialValidDomainConfiguration); 915 916 return true; 917 } 918 } 919 return false; 920} 921 922// Search for a valid configuration for given configurable element 923const CDomainConfiguration* CConfigurableDomain::findValidDomainConfiguration(const CConfigurableElement* pConfigurableElement) const 924{ 925 uint32_t uiNbConfigurations = getNbChildren(); 926 uint32_t uiChild; 927 928 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { 929 930 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild)); 931 932 if (pDomainConfiguration->isValid(pConfigurableElement)) { 933 934 return pDomainConfiguration; 935 } 936 } 937 return NULL; 938} 939 940// Search for an applicable configuration 941const CDomainConfiguration* CConfigurableDomain::findApplicableDomainConfiguration() const 942{ 943 uint32_t uiNbConfigurations = getNbChildren(); 944 uint32_t uiChild; 945 946 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { 947 948 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild)); 949 950 if (pDomainConfiguration->isApplicable()) { 951 952 return pDomainConfiguration; 953 } 954 } 955 return NULL; 956} 957 958// Gather set of configurable elements 959void CConfigurableDomain::gatherConfigurableElements(std::set<const CConfigurableElement*>& configurableElementSet) const 960{ 961 // Insert all configurable elements 962 configurableElementSet.insert(_configurableElementList.begin(), _configurableElementList.end()); 963} 964 965// Check configurable element already attached 966bool CConfigurableDomain::containsConfigurableElement(const CConfigurableElement* pConfigurableCandidateElement) const 967{ 968 ConfigurableElementListIterator it; 969 970 // Browse all configurable elements for comparison 971 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) { 972 973 if (pConfigurableCandidateElement == *it) { 974 975 return true; 976 } 977 } 978 return false; 979} 980 981// Merge any descended configurable element to this one with this one 982void CConfigurableDomain::mergeAlreadyAssociatedDescendantConfigurableElements(CConfigurableElement* pNewConfigurableElement) 983{ 984 std::list<CConfigurableElement*> mergedConfigurableElementList; 985 986 ConfigurableElementListIterator it; 987 988 // Browse all configurable elements (new one not yet in the list!) 989 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) { 990 991 CConfigurableElement* pConfigurablePotentialDescendantElement = *it; 992 993 if (pConfigurablePotentialDescendantElement->isDescendantOf(pNewConfigurableElement)) { 994 995 log_info("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()); 996 997 // Merge configuration data 998 mergeConfigurations(pNewConfigurableElement, pConfigurablePotentialDescendantElement); 999 1000 // Keep track for removal 1001 mergedConfigurableElementList.push_back(pConfigurablePotentialDescendantElement); 1002 } 1003 } 1004 1005 // Remove all merged elements (new one not yet in the list!) 1006 for (it = mergedConfigurableElementList.begin(); it != mergedConfigurableElementList.end(); ++it) { 1007 1008 CConfigurableElement* pMergedConfigurableElement = *it; 1009 1010 // Remove merged from configurable element from internal tracking list 1011 // 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 1012 doRemoveConfigurableElement(pMergedConfigurableElement, false); 1013 } 1014} 1015 1016void CConfigurableDomain::mergeConfigurations(CConfigurableElement* pToConfigurableElement, CConfigurableElement* pFromConfigurableElement) 1017{ 1018 // Propagate to domain configurations 1019 uint32_t uiNbConfigurations = getNbChildren(); 1020 uint32_t uiChild; 1021 1022 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { 1023 1024 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild)); 1025 1026 // Do the merge. 1027 pDomainConfiguration->merge(pToConfigurableElement, pFromConfigurableElement); 1028 } 1029} 1030 1031// Configurable elements association 1032void CConfigurableDomain::doAddConfigurableElement(CConfigurableElement* pConfigurableElement, const CParameterBlackboard *pMainBlackboard) 1033{ 1034 // Inform configurable element 1035 pConfigurableElement->addAttachedConfigurableDomain(this); 1036 1037 // Create associated syncer set 1038 CSyncerSet* pSyncerSet = new CSyncerSet; 1039 1040 // Add to sync set the configurable element one 1041 pConfigurableElement->fillSyncerSet(*pSyncerSet); 1042 1043 // Store it 1044 _configurableElementToSyncerSetMap[pConfigurableElement] = pSyncerSet; 1045 1046 // Add it to global one 1047 _syncerSet += *pSyncerSet; 1048 1049 // Inform configurations 1050 uint32_t uiNbConfigurations = getNbChildren(); 1051 uint32_t uiChild; 1052 1053 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { 1054 1055 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild)); 1056 1057 pDomainConfiguration->addConfigurableElement(pConfigurableElement, pSyncerSet); 1058 } 1059 1060 // Ensure area validity for that configurable element (if main blackboard provided) 1061 if (pMainBlackboard) { 1062 1063 // Need to validate against main blackboard 1064 validateAreas(pConfigurableElement, pMainBlackboard); 1065 } 1066 1067 // Already associated descendend configurable elements need a merge of their configuration data 1068 mergeAlreadyAssociatedDescendantConfigurableElements(pConfigurableElement); 1069 1070 // Add to list 1071 _configurableElementList.push_back(pConfigurableElement); 1072} 1073 1074void CConfigurableDomain::doRemoveConfigurableElement(CConfigurableElement* pConfigurableElement, bool bRecomputeSyncSet) 1075{ 1076 // Remove from list 1077 _configurableElementList.remove(pConfigurableElement); 1078 1079 // Remove associated syncer set 1080 CSyncerSet* pSyncerSet = getSyncerSet(pConfigurableElement); 1081 1082 _configurableElementToSyncerSetMap.erase(pConfigurableElement); 1083 1084 delete pSyncerSet; 1085 1086 // Inform configurable element 1087 pConfigurableElement->removeAttachedConfigurableDomain(this); 1088 1089 // Inform configurations 1090 uint32_t uiNbConfigurations = getNbChildren(); 1091 uint32_t uiChild; 1092 1093 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) { 1094 1095 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild)); 1096 1097 pDomainConfiguration->removeConfigurableElement(pConfigurableElement); 1098 } 1099 // Recompute our sync set if needed 1100 if (bRecomputeSyncSet) { 1101 1102 computeSyncSet(); 1103 } 1104} 1105 1106// Syncer set retrieval from configurable element 1107CSyncerSet* CConfigurableDomain::getSyncerSet(const CConfigurableElement* pConfigurableElement) const 1108{ 1109 ConfigurableElementToSyncerSetMapIterator mapIt = _configurableElementToSyncerSetMap.find(pConfigurableElement); 1110 1111 assert(mapIt != _configurableElementToSyncerSetMap.end()); 1112 1113 return mapIt->second; 1114} 1115 1116// Configuration retrieval 1117CDomainConfiguration* CConfigurableDomain::findConfiguration(const string& strConfiguration, string& strError) 1118{ 1119 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(strConfiguration)); 1120 1121 if (!pDomainConfiguration) { 1122 1123 strError = "Domain configuration " + strConfiguration + " not found"; 1124 1125 return NULL; 1126 } 1127 return pDomainConfiguration; 1128} 1129 1130const CDomainConfiguration* CConfigurableDomain::findConfiguration(const string& strConfiguration, string& strError) const 1131{ 1132 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(findChild(strConfiguration)); 1133 1134 if (!pDomainConfiguration) { 1135 1136 strError = "Domain configuration " + strConfiguration + " not found"; 1137 1138 return NULL; 1139 } 1140 return pDomainConfiguration; 1141} 1142