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