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