blob: 4c6541f176feb300f42f12e345a019615b18edea [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"
Patrick Benavoli68a91282011-08-31 11:23:23 +020035#include "XmlDomainSerializingContext.h"
36#include <assert.h>
37
38#define base CBinarySerializableElement
39
Patrick Benavoli63499d42011-10-24 18:50:03 +020040CConfigurableDomain::CConfigurableDomain(const string& strName) : base(strName), _bSequenceAware(false), _pLastAppliedConfiguration(NULL)
Patrick Benavoli68a91282011-08-31 11:23:23 +020041{
42}
43
44CConfigurableDomain::~CConfigurableDomain()
45{
Patrick Benavoli63499d42011-10-24 18:50:03 +020046 // Remove all configurable elements
Patrick Benavoli68a91282011-08-31 11:23:23 +020047 ConfigurableElementListIterator it;
48
Patrick Benavoli68a91282011-08-31 11:23:23 +020049 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
50
51 CConfigurableElement* pConfigurableElement = *it;
52
53 // Remove from configurable element
54 pConfigurableElement->removeAttachedConfigurableDomain(this);
55 }
Patrick Benavoli63499d42011-10-24 18:50:03 +020056
57 // Remove all associated syncer sets
58 ConfigurableElementToSyncerSetMapIterator mapIt;
59
60 for (mapIt = _configurableElementToSyncerSetMap.begin(); mapIt != _configurableElementToSyncerSetMap.end(); ++mapIt) {
61
62 delete mapIt->second;
63 }
Patrick Benavoli68a91282011-08-31 11:23:23 +020064}
65
66string CConfigurableDomain::getKind() const
67{
68 return "ConfigurableDomain";
69}
70
71bool CConfigurableDomain::childrenAreDynamic() const
72{
73 return true;
74}
75
Patrick Benavoli0bd50542011-11-29 11:10:27 +010076// Content dumping
77void CConfigurableDomain::logValue(string& strValue, CErrorContext& errorContext) const
78{
79 (void)errorContext;
80
81 strValue = "{";
82
83 // Sequence awareness
84 strValue += "Sequence aware: ";
85 strValue += _bSequenceAware ? "yes" : "no";
86
87 // Last applied configuration
88 strValue += ", Last applied configuration: ";
89 strValue += _pLastAppliedConfiguration ? _pLastAppliedConfiguration->getName() : "<none>";
90
91 strValue += "}";
92}
93
Patrick Benavoli63499d42011-10-24 18:50:03 +020094// Sequence awareness
95void CConfigurableDomain::setSequenceAwareness(bool bSequenceAware)
96{
97 if (_bSequenceAware != bSequenceAware) {
98
99 log("Making domain \"%s\" sequence %s", getName().c_str(), bSequenceAware ? "aware" : "unaware");
100
101 _bSequenceAware = bSequenceAware;
102 }
103}
104
105bool CConfigurableDomain::getSequenceAwareness() const
106{
107 return _bSequenceAware;
108}
109
Patrick Benavoli68a91282011-08-31 11:23:23 +0200110// From IXmlSource
111void CConfigurableDomain::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
112{
Patrick Benavoli63499d42011-10-24 18:50:03 +0200113 // Sequence awareness
114 xmlElement.setAttributeBoolean("SequenceAware", _bSequenceAware);
115
Patrick Benavoli68a91282011-08-31 11:23:23 +0200116 // Configurations
117 composeDomainConfigurations(xmlElement, serializingContext);
118
119 // Configurable Elements
Patrick Benavoli63499d42011-10-24 18:50:03 +0200120 composeConfigurableElements(xmlElement);
121
122 // Settings
123 composeSettings(xmlElement, serializingContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200124}
125
126// XML composing
127void CConfigurableDomain::composeDomainConfigurations(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
128{
129 // Create Configurations element
130 CXmlElement xmlConfigurationsElement;
131
132 xmlElement.createChild(xmlConfigurationsElement, "Configurations");
133
134 // Delegate to base
135 base::toXml(xmlConfigurationsElement, serializingContext);
136}
137
Patrick Benavoli63499d42011-10-24 18:50:03 +0200138void CConfigurableDomain::composeConfigurableElements(CXmlElement& xmlElement) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200139{
Patrick Benavoli68a91282011-08-31 11:23:23 +0200140 // Create ConfigurableElements element
141 CXmlElement xmlConfigurableElementsElement;
142
143 xmlElement.createChild(xmlConfigurableElementsElement, "ConfigurableElements");
144
145 // Serialize out all configurable elements settings
146 ConfigurableElementListIterator it;
147
148 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
149
150 const CConfigurableElement* pConfigurableElement = *it;
151
152 // Create corresponding XML child element
153 CXmlElement xmlChildConfigurableElement;
154
155 xmlConfigurableElementsElement.createChild(xmlChildConfigurableElement, "ConfigurableElement");
156
157 // Set Path attribute
158 xmlChildConfigurableElement.setAttributeString("Path", pConfigurableElement->getPath());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200159 }
160}
161
Patrick Benavoli63499d42011-10-24 18:50:03 +0200162void CConfigurableDomain::composeSettings(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200163{
Patrick Benavoli63499d42011-10-24 18:50:03 +0200164 // Context
165 const CXmlDomainSerializingContext& xmlDomainSerializingContext = static_cast<const CXmlDomainSerializingContext&>(serializingContext);
166
167 if (!xmlDomainSerializingContext.withSettings()) {
168
169 return;
170 }
171
172 // Create Settings element
173 CXmlElement xmlSettingsElement;
174
175 xmlElement.createChild(xmlSettingsElement, "Settings");
176
177 // Serialize out all configurations settings
Patrick Benavoli68a91282011-08-31 11:23:23 +0200178 uint32_t uiNbConfigurations = getNbChildren();
179 uint32_t uiChildConfiguration;
180
181 for (uiChildConfiguration = 0; uiChildConfiguration < uiNbConfigurations; uiChildConfiguration++) {
182
183 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChildConfiguration));
184
185 // Create child xml element for that configuration
186 CXmlElement xmlConfigurationSettingsElement;
187
Patrick Benavoli63499d42011-10-24 18:50:03 +0200188 xmlSettingsElement.createChild(xmlConfigurationSettingsElement, pDomainConfiguration->getKind());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200189
190 // Set its name attribute
191 xmlConfigurationSettingsElement.setNameAttribute(pDomainConfiguration->getName());
192
Patrick Benavoli63499d42011-10-24 18:50:03 +0200193 // Serialize out configuration settings
194 pDomainConfiguration->composeSettings(xmlConfigurationSettingsElement, serializingContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200195 }
196}
197
198// From IXmlSink
199bool CConfigurableDomain::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
200{
Patrick Benavoli63499d42011-10-24 18:50:03 +0200201 // Context
202 CXmlDomainSerializingContext& xmlDomainSerializingContext = static_cast<CXmlDomainSerializingContext&>(serializingContext);
203
204 // Sequence awareness (optional)
205 _bSequenceAware = xmlElement.hasAttribute("SequenceAware") && xmlElement.getAttributeBoolean("SequenceAware");
206
Patrick Benavoli68a91282011-08-31 11:23:23 +0200207 // Local parsing. Do not dig
Patrick Benavoli63499d42011-10-24 18:50:03 +0200208 if (!parseDomainConfigurations(xmlElement, serializingContext) || !parseConfigurableElements(xmlElement, serializingContext) || !parseSettings(xmlElement, serializingContext)) {
209
210 return false;
211 }
212
213 // All provided configurations are parsed
214 // Attempt validation on areas of non provided configurations for all configurable elements if required
215 if (xmlDomainSerializingContext.autoValidationRequired()) {
216
217 autoValidateAll();
218 }
219
220 return true;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200221}
222
223// XML parsing
224bool CConfigurableDomain::parseDomainConfigurations(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
225{
226 // We're supposedly clean
227 assert(_configurableElementList.empty());
228
229 // Get Configurations element
230 CXmlElement xmlConfigurationsElement;
231
232 xmlElement.getChildElement("Configurations", xmlConfigurationsElement);
233
234 // Parse it and create domain configuration objects
235 return base::fromXml(xmlConfigurationsElement, serializingContext);
236}
237
238// Parse configurable elements
239bool CConfigurableDomain::parseConfigurableElements(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
240{
Patrick Benavoli68a91282011-08-31 11:23:23 +0200241 // Get System Class Element
242 CElement* pRootElement = getRoot();
243
244 CElement* pSystemClassElement = pRootElement->findChildOfKind("SystemClass");
245
246 assert(pSystemClassElement);
247
248 // Get ConfigurableElements element
249 CXmlElement xmlConfigurableElementsElement;
250 xmlElement.getChildElement("ConfigurableElements", xmlConfigurableElementsElement);
251
252 // Parse it and associate found configurable elements to it
253 CXmlElement::CChildIterator it(xmlConfigurableElementsElement);
254
255 CXmlElement xmlConfigurableElementElement;
256
257 while (it.next(xmlConfigurableElementElement)) {
258
259 // Locate configurable element
260 string strConfigurableElementPath = xmlConfigurableElementElement.getAttributeString("Path");
261
262 CPathNavigator pathNavigator(strConfigurableElementPath);
Patrick Benavoli065264a2011-11-20 15:46:41 +0100263 string strError;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200264
265 // Is there an element and does it match system class name?
Patrick Benavoli065264a2011-11-20 15:46:41 +0100266 if (!pathNavigator.navigateThrough(pSystemClassElement->getName(), strError)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200267
Patrick Benavoli065264a2011-11-20 15:46:41 +0100268 serializingContext.setError("Could not find configurable element of path " + strConfigurableElementPath + " from ConfigurableDomain description " + getName() + " (" + strError + ")");
Patrick Benavoli68a91282011-08-31 11:23:23 +0200269
270 return false;
271 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200272 // Browse system class for configurable element
273 CConfigurableElement* pConfigurableElement = static_cast<CConfigurableElement*>(pSystemClassElement->findDescendant(pathNavigator));
274
275 if (!pConfigurableElement) {
276
277 serializingContext.setError("Could not find configurable element of path " + strConfigurableElementPath + " from ConfigurableDomain description " + getName());
278
279 return false;
280 }
281 // Add found element to domain
Patrick Benavoli68a91282011-08-31 11:23:23 +0200282 if (!addConfigurableElement(pConfigurableElement, NULL, strError)) {
283
284 serializingContext.setError(strError);
285
286 return false;
287 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200288 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200289
290 return true;
291}
292
Patrick Benavoli63499d42011-10-24 18:50:03 +0200293// Parse settings
294bool CConfigurableDomain::parseSettings(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200295{
296 // Context
297 CXmlDomainSerializingContext& xmlDomainSerializingContext = static_cast<CXmlDomainSerializingContext&>(serializingContext);
298
Patrick Benavoli63499d42011-10-24 18:50:03 +0200299 // Check we actually need to parse configuration settings
300 if (!xmlDomainSerializingContext.withSettings()) {
301
302 // No parsing required
303 return true;
304 }
305
306 // Get Settings element
307 CXmlElement xmlSettingsElement;
308 if (!xmlElement.getChildElement("Settings", xmlSettingsElement)) {
309
310 // No settings, bail out successfully
311 return true;
312 }
313
314 // Parse configuration settings
315 CXmlElement::CChildIterator it(xmlSettingsElement);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200316
317 CXmlElement xmlConfigurationSettingsElement;
318
319 while (it.next(xmlConfigurationSettingsElement)) {
320 // Get domain configuration
321 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(xmlConfigurationSettingsElement.getNameAttribute()));
322
323 if (!pDomainConfiguration) {
324
Patrick Benavoli63499d42011-10-24 18:50:03 +0200325 xmlDomainSerializingContext.setError("Could not find domain configuration referred to by configurable domain " + getName());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200326
327 return false;
328 }
Patrick Benavoli63499d42011-10-24 18:50:03 +0200329 // Have domain configuration parse settings for all configurable elements
330 if (!pDomainConfiguration->parseSettings(xmlConfigurationSettingsElement, xmlDomainSerializingContext)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200331
332 return false;
333 }
334 }
335
336 return true;
337}
Patrick Benavoli68a91282011-08-31 11:23:23 +0200338// Configurable elements association
339bool CConfigurableDomain::addConfigurableElement(CConfigurableElement* pConfigurableElement, const CParameterBlackboard* pMainBlackboard, string& strError)
340{
341 // Already associated?
342 if (containsConfigurableElement(pConfigurableElement)) {
343
344 strError = "Configurable element " + pConfigurableElement->getPath() + " already associated to configuration domain " + getName();
345
346 return false;
347 }
348
349 // Already owned?
350 if (pConfigurableElement->belongsTo(this)) {
351
352 strError = "Configurable element " + pConfigurableElement->getPath() + " already owned by configuration domain " + getName();
353
354 return false;
355 }
356 log("Adding configurable element \"%s\" into domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str());
357
358 // Do add
359 doAddConfigurableElement(pConfigurableElement);
360
361 // Ensure area validity for that configurable element (if main blackboard provided)
362 if (pMainBlackboard) {
363
364 // Need to validate against main blackboard
365 validateAreas(pConfigurableElement, pMainBlackboard);
366 }
367
368 return true;
369}
370
371bool CConfigurableDomain::removeConfigurableElement(CConfigurableElement* pConfigurableElement, string& strError)
372{
373 // Not associated?
374 if (!containsConfigurableElement(pConfigurableElement)) {
375
376 strError = "Configurable element " + pConfigurableElement->getPath() + " not associated to configuration domain " + getName();
377
378 return false;
379 }
380 log("Removing configurable element \"%s\" from domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str());
381
382 // Do remove
383 doRemoveConfigurableElement(pConfigurableElement, true);
384
385 return true;
386}
387
388// Domain splitting
389bool CConfigurableDomain::split(CConfigurableElement* pConfigurableElement, string& strError)
390{
391 // Not associated?
392 if (!containsConfigurableElement(pConfigurableElement)) {
393
394 strError = "Configurable element " + pConfigurableElement->getPath() + " not associated to configuration domain " + getName();
395
396 return false;
397 }
398 log("Splitting configurable element \"%s\" domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str());
399
400 // Create sub domain areas for all configurable element's children
401 uint32_t uiNbConfigurableElementChildren = pConfigurableElement->getNbChildren();
402
403 if (!uiNbConfigurableElementChildren) {
404
405 strError = "Configurable element " + pConfigurableElement->getPath() + " has no children to split configurable domain to";
406
407 return false;
408 }
409
410 uint32_t uiChild;
411
412 for (uiChild = 0; uiChild < uiNbConfigurableElementChildren; uiChild++) {
413
414 CConfigurableElement* pChildConfigurableElement = static_cast<CConfigurableElement*>(pConfigurableElement->getChild(uiChild));
415
416 doAddConfigurableElement(pChildConfigurableElement);
417 }
418
419 // Delegate to configurations
420 uint32_t uiNbConfigurations = getNbChildren();
421
422 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
423
424 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
425
426 pDomainConfiguration->split(pConfigurableElement);
427 }
428
429 // Remove given configurable element from this domain
430 // 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
431 doRemoveConfigurableElement(pConfigurableElement, false);
432
433 return true;
434}
435
436// Configuration application if required
Patrick Benavoli63499d42011-10-24 18:50:03 +0200437bool CConfigurableDomain::apply(CParameterBlackboard* pParameterBlackboard, CSyncerSet& syncerSet, bool bForce, string& strError) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200438{
439 if (bForce) {
440 // Force a configuration restore by forgetting about last applied configuration
441 _pLastAppliedConfiguration = NULL;
442 }
443 const CDomainConfiguration* pApplicableDomainConfiguration = findApplicableDomainConfiguration();
444
445 if (pApplicableDomainConfiguration) {
446
447 // Check not the last one before applying
448 if (!_pLastAppliedConfiguration || _pLastAppliedConfiguration != pApplicableDomainConfiguration) {
449
450 log("Applying configuration \"%s\" from domain \"%s\"", pApplicableDomainConfiguration->getName().c_str(), getName().c_str());
451
452 // Do the restore
Patrick Benavoli63499d42011-10-24 18:50:03 +0200453 if (!pApplicableDomainConfiguration->restore(pParameterBlackboard, _bSequenceAware, strError)) {
454
455 return false;
456 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200457
458 // Record last applied configuration
459 _pLastAppliedConfiguration = pApplicableDomainConfiguration;
460
Patrick Benavoli63499d42011-10-24 18:50:03 +0200461 // Check we did not already sync the changes
462 if (!_bSequenceAware) {
463
464 // Since we applied changes, add our own sync set to the given one
465 syncerSet += _syncerSet;
466 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200467 }
468 }
Patrick Benavoli63499d42011-10-24 18:50:03 +0200469
470 return true;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200471}
472
473// Return applicable configuration validity for given configurable element
474bool CConfigurableDomain::isApplicableConfigurationValid(const CConfigurableElement* pConfigurableElement) const
475{
476 const CDomainConfiguration* pApplicableDomainConfiguration = findApplicableDomainConfiguration();
477
478 return pApplicableDomainConfiguration && pApplicableDomainConfiguration->isValid(pConfigurableElement);
479}
480
Patrick Benavoli68a91282011-08-31 11:23:23 +0200481// In case configurable element was removed
482void CConfigurableDomain::computeSyncSet()
483{
484 // Clean sync set first
Patrick Benavoli63499d42011-10-24 18:50:03 +0200485 _syncerSet.clear();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200486
Patrick Benavoli63499d42011-10-24 18:50:03 +0200487 // Add syncer sets for all associated configurable elements
488 ConfigurableElementToSyncerSetMapIterator mapIt;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200489
Patrick Benavoli63499d42011-10-24 18:50:03 +0200490 for (mapIt = _configurableElementToSyncerSetMap.begin(); mapIt != _configurableElementToSyncerSetMap.end(); ++mapIt) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200491
Patrick Benavoli63499d42011-10-24 18:50:03 +0200492 const CSyncerSet* pSyncerSet = mapIt->second;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200493
Patrick Benavoli63499d42011-10-24 18:50:03 +0200494 _syncerSet += *pSyncerSet;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200495 }
496}
497
498// Configuration Management
499bool CConfigurableDomain::createConfiguration(const string& strName, const CParameterBlackboard* pMainBlackboard, string& strError)
500{
501 // Already exists?
502 if (findChild(strName)) {
503
504 strError = "Already existing configuration";
505
506 return false;
507 }
508 log("Creating domain configuration \"%s\" into domain \"%s\"", strName.c_str(), getName().c_str());
509
510 // Creation
511 CDomainConfiguration* pDomainConfiguration = new CDomainConfiguration(strName);
512
513 // Configurable elements association
514 ConfigurableElementListIterator it;
515
516 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
517
Patrick Benavoli63499d42011-10-24 18:50:03 +0200518 const CConfigurableElement* pConfigurableElement = *it;;
519
520 // Retrieve associated syncer set
521 CSyncerSet* pSyncerSet = getSyncerSet(pConfigurableElement);
522
523 // Associate to configuration
524 pDomainConfiguration->addConfigurableElement(pConfigurableElement, pSyncerSet);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200525 }
526
527 // Hierarchy
528 addChild(pDomainConfiguration);
529
530 // Ensure validity of fresh new domain configuration
531 // Attempt auto validation, so that the user gets his/her own settings by defaults
532 if (!autoValidateConfiguration(pDomainConfiguration)) {
533
534 // No valid configuration found to copy in from, validate againt main blackboard (will concerned remaining invalid parts)
535 pDomainConfiguration->validate(pMainBlackboard);
536 }
537
538 return true;
539}
540
541bool CConfigurableDomain::deleteConfiguration(const string& strName, string& strError)
542{
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100543 CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200544
545 if (!pDomainConfiguration) {
546
Patrick Benavoli68a91282011-08-31 11:23:23 +0200547 return false;
548 }
549
550 log("Deleting configuration \"%s\" from domain \"%s\"", strName.c_str(), getName().c_str());
551
552 // Was the last applied?
553 if (pDomainConfiguration == _pLastAppliedConfiguration) {
554
555 // Forget about it
556 _pLastAppliedConfiguration = NULL;
557 }
558
559 // Hierarchy
560 removeChild(pDomainConfiguration);
561
562 // Destroy
563 delete pDomainConfiguration;
564
565 return true;
566}
567
568void CConfigurableDomain::listAssociatedToElements(string& strResult) const
569{
570 strResult = "\n";
571
572 ConfigurableElementListIterator it;
573
574 // Browse all configurable elements
575 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
576
577 const CConfigurableElement* pConfigurableElement = *it;
578
579 strResult += pConfigurableElement->getPath() + "\n";
580 }
581}
582
583bool CConfigurableDomain::renameConfiguration(const string& strName, const string& strNewName, string& strError)
584{
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100585 CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200586
587 if (!pDomainConfiguration) {
588
Patrick Benavoli68a91282011-08-31 11:23:23 +0200589 return false;
590 }
591 log("Renaming domain \"%s\"'s configuration \"%s\" to \"%s\"", getName().c_str(), strName.c_str(), strNewName.c_str());
592
593 // Rename
594 return pDomainConfiguration->rename(strNewName, strError);
595}
596
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100597bool CConfigurableDomain::restoreConfiguration(const string& strName, CParameterBlackboard* pMainBlackboard, bool bAutoSync, string& strError) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200598{
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100599 const CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200600
601 if (!pDomainConfiguration) {
602
Patrick Benavoli68a91282011-08-31 11:23:23 +0200603 return false;
604 }
605 log("Restoring domain \"%s\"'s configuration \"%s\" to parameter blackboard", getName().c_str(), pDomainConfiguration->getName().c_str());
606
607 // Delegate
Patrick Benavoli63499d42011-10-24 18:50:03 +0200608 if (!pDomainConfiguration->restore(pMainBlackboard, _bSequenceAware && bAutoSync, strError)) {
609
610 return false;
611 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200612
613 // Record last applied configuration
614 _pLastAppliedConfiguration = pDomainConfiguration;
615
616 // Synchronize
617 return !bAutoSync || _syncerSet.sync(*pMainBlackboard, false, strError);
618}
619
620bool CConfigurableDomain::saveConfiguration(const string& strName, const CParameterBlackboard* pMainBlackboard, string& strError)
621{
622 // Find Domain configuration
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100623 CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200624
625 if (!pDomainConfiguration) {
626
Patrick Benavoli68a91282011-08-31 11:23:23 +0200627 return false;
628 }
629 log("Saving domain \"%s\"'s configuration \"%s\" from parameter blackboard", getName().c_str(), pDomainConfiguration->getName().c_str());
630
631 // Delegate
632 pDomainConfiguration->save(pMainBlackboard);
633
634 return true;
635}
636
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100637bool CConfigurableDomain::setElementSequence(const string& strConfiguration, const vector<string>& astrNewElementSequence, string& strError)
Patrick Benavoli63499d42011-10-24 18:50:03 +0200638{
639 // Find Domain configuration
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100640 CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strError);
Patrick Benavoli63499d42011-10-24 18:50:03 +0200641
642 if (!pDomainConfiguration) {
643
Patrick Benavoli63499d42011-10-24 18:50:03 +0200644 return false;
645 }
646
647 // Delegate to configuration
648 return pDomainConfiguration->setElementSequence(astrNewElementSequence, strError);
649}
650
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100651bool CConfigurableDomain::getElementSequence(const string& strConfiguration, string& strResult) const
Patrick Benavoli63499d42011-10-24 18:50:03 +0200652{
653 // Find Domain configuration
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100654 const CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strResult);
Patrick Benavoli63499d42011-10-24 18:50:03 +0200655
656 if (!pDomainConfiguration) {
657
Patrick Benavoli63499d42011-10-24 18:50:03 +0200658 return false;
659 }
660
661 // Delegate to configuration
662 pDomainConfiguration->getElementSequence(strResult);
663
664 return true;
665}
666
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100667bool CConfigurableDomain::setApplicationRule(const string& strConfiguration, const string& strApplicationRule, const CSelectionCriteriaDefinition* pSelectionCriteriaDefinition, string& strError)
668{
669 // Find Domain configuration
670 CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strError);
671
672 if (!pDomainConfiguration) {
673
674 return false;
675 }
676
677 // Delegate to configuration
678 return pDomainConfiguration->setApplicationRule(strApplicationRule, pSelectionCriteriaDefinition, strError);
679}
680
681bool CConfigurableDomain::clearApplicationRule(const string& strConfiguration, string& strError)
682{
683 // Find Domain configuration
684 CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strError);
685
686 if (!pDomainConfiguration) {
687
688 return false;
689 }
690
691 // Delegate to configuration
692 pDomainConfiguration->clearApplicationRule();
693
694 return true;
695}
696
697bool CConfigurableDomain::getApplicationRule(const string& strConfiguration, string& strResult) const
698{
699 // Find Domain configuration
700 const CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strResult);
701
702 if (!pDomainConfiguration) {
703
704 return false;
705 }
706
707 // Delegate to configuration
708 pDomainConfiguration->getApplicationRule(strResult);
709
710 return true;
711}
712
Patrick Benavoli68a91282011-08-31 11:23:23 +0200713// Last applied configuration
714string CConfigurableDomain::getLastAppliedConfigurationName() const
715{
716 if (_pLastAppliedConfiguration) {
717
718 return _pLastAppliedConfiguration->getName();
719 }
720 return "<none>";
721}
722
723// Ensure validity on whole domain from main blackboard
724void CConfigurableDomain::validate(const CParameterBlackboard* pMainBlackboard)
725{
726 log("Validating whole domain \"" + getName() + "\" against main blackboard");
727
728 // Propagate
729 uint32_t uiNbConfigurations = getNbChildren();
730 uint32_t uiChild;
731
732 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
733
734 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
735
736 pDomainConfiguration->validate(pMainBlackboard);
737 }
738}
739
740// Ensure validity on areas related to configurable element
741void CConfigurableDomain::validateAreas(const CConfigurableElement* pConfigurableElement, const CParameterBlackboard* pMainBlackboard)
742{
743 log("Validating domain \"" + getName() + "\" against main blackboard for configurable element \"" + pConfigurableElement->getPath() + "\"");
744
745 // Propagate
746 uint32_t uiNbConfigurations = getNbChildren();
747 uint32_t uiChild;
748
749 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
750
751 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
752
753 pDomainConfiguration->validate(pConfigurableElement, pMainBlackboard);
754 }
755}
756
757// Attempt validation for all configurable element's areas, relying on already existing valid configuration inside domain
758void CConfigurableDomain::autoValidateAll()
759{
760 // Validate
761 ConfigurableElementListIterator it;
762
763 // Browse all configurable elements for configuration validation
764 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
765
766 const CConfigurableElement* pConfigurableElement = *it;
767
768 // Auto validate element
769 autoValidateAreas(pConfigurableElement);
770 }
771}
772
773// Attempt validation for configurable element's areas, relying on already existing valid configuration inside domain
774void CConfigurableDomain::autoValidateAreas(const CConfigurableElement* pConfigurableElement)
775{
776 // Find first valid configuration for given configurable element
777 const CDomainConfiguration* pValidDomainConfiguration = findValidDomainConfiguration(pConfigurableElement);
778
779 // No valid configuration found, give up
780 if (!pValidDomainConfiguration) {
781
782 return;
783 }
784
785 log("Auto validating domain \"" + getName() + "\" against configuration \"" + pValidDomainConfiguration->getName() + "\" for configurable element " + pConfigurableElement->getPath());
786
787 // Validate all other configurations against found one, if any
788 uint32_t uiNbConfigurations = getNbChildren();
789 uint32_t uiChild;
790
791 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
792
793 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
794
795 if (pDomainConfiguration != pValidDomainConfiguration && !pDomainConfiguration->isValid(pConfigurableElement)) {
796 // Validate
797 pDomainConfiguration->validateAgainst(pValidDomainConfiguration, pConfigurableElement);
798 }
799 }
800}
801
802// Attempt configuration validation for all configurable elements' areas, relying on already existing valid configuration inside domain
803bool CConfigurableDomain::autoValidateConfiguration(CDomainConfiguration* pDomainConfiguration)
804{
805 // Find another configuration than this one, that ought to be valid!
806 uint32_t uiNbConfigurations = getNbChildren();
807 uint32_t uiChild;
808
809 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
810
811 const CDomainConfiguration* pPotententialValidDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
812
813 if (pPotententialValidDomainConfiguration != pDomainConfiguration) {
814
815 // Validate against it
816 pDomainConfiguration->validateAgainst(pPotententialValidDomainConfiguration);
817
818 return true;
819 }
820 }
821 return false;
822}
Patrick Benavoli68a91282011-08-31 11:23:23 +0200823
Patrick Benavoli68a91282011-08-31 11:23:23 +0200824// Search for a valid configuration for given configurable element
825const CDomainConfiguration* CConfigurableDomain::findValidDomainConfiguration(const CConfigurableElement* pConfigurableElement) const
826{
827 uint32_t uiNbConfigurations = getNbChildren();
828 uint32_t uiChild;
829
830 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
831
832 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
833
834 if (pDomainConfiguration->isValid(pConfigurableElement)) {
835
836 return pDomainConfiguration;
837 }
838 }
839 return NULL;
840}
841
842// Search for an applicable configuration
843const CDomainConfiguration* CConfigurableDomain::findApplicableDomainConfiguration() const
844{
845 uint32_t uiNbConfigurations = getNbChildren();
846 uint32_t uiChild;
847
848 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
849
850 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
851
852 if (pDomainConfiguration->isApplicable()) {
853
854 return pDomainConfiguration;
855 }
856 }
857 return NULL;
858}
859
860// Gather set of configurable elements
861void CConfigurableDomain::gatherConfigurableElements(set<const CConfigurableElement*>& configurableElementSet) const
862{
863 // Insert all configurable elements
864 configurableElementSet.insert(_configurableElementList.begin(), _configurableElementList.end());
865}
866
867// Check configurable element already attached
868bool CConfigurableDomain::containsConfigurableElement(const CConfigurableElement* pConfigurableCandidateElement) const
869{
870 ConfigurableElementListIterator it;
871
872 // Browse all configurable elements for comparison
873 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
874
875 if (pConfigurableCandidateElement == *it) {
876
877 return true;
878 }
879 }
880 return false;
881}
882
883// Merge any descended configurable element to this one with this one
884void CConfigurableDomain::mergeAlreadyAssociatedDescendantConfigurableElements(CConfigurableElement* pNewConfigurableElement)
885{
886 list<CConfigurableElement*> mergedConfigurableElementList;
887
888 ConfigurableElementListIterator it;
889
890 // Browse all configurable elements (new one not yet in the list!)
891 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
892
893 CConfigurableElement* pConfigurablePotentialDescendantElement = *it;
894
895 if (pConfigurablePotentialDescendantElement->isDescendantOf(pNewConfigurableElement)) {
896
897 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());
898
899 // Merge configuration data
900 mergeConfigurations(pNewConfigurableElement, pConfigurablePotentialDescendantElement);
901
902 // Keep track for removal
903 mergedConfigurableElementList.push_back(pConfigurablePotentialDescendantElement);
904 }
905 }
906
907 // Remove all merged elements (new one not yet in the list!)
908 for (it = mergedConfigurableElementList.begin(); it != mergedConfigurableElementList.end(); ++it) {
909
910 CConfigurableElement* pMergedConfigurableElement = *it;
911
912 // Remove merged from configurable element from internal tracking list
913 // 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
914 doRemoveConfigurableElement(pMergedConfigurableElement, false);
915 }
916}
917
918void CConfigurableDomain::mergeConfigurations(CConfigurableElement* pToConfigurableElement, CConfigurableElement* pFromConfigurableElement)
919{
920 // Propagate to domain configurations
921 uint32_t uiNbConfigurations = getNbChildren();
922 uint32_t uiChild;
923
924 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
925
926 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
927
928 // Do the merge.
929 pDomainConfiguration->merge(pToConfigurableElement, pFromConfigurableElement);
930 }
931}
932
933// Configurable elements association
934void CConfigurableDomain::doAddConfigurableElement(CConfigurableElement* pConfigurableElement)
935{
936 // Inform configurable element
937 pConfigurableElement->addAttachedConfigurableDomain(this);
938
Patrick Benavoli63499d42011-10-24 18:50:03 +0200939 // Create associated syncer set
940 CSyncerSet* pSyncerSet = new CSyncerSet;
941
942 // Add to sync set the configurable element one
943 pConfigurableElement->fillSyncerSet(*pSyncerSet);
944
945 // Store it
946 _configurableElementToSyncerSetMap[pConfigurableElement] = pSyncerSet;
947
948 // Add it to global one
949 _syncerSet += *pSyncerSet;
950
Patrick Benavoli68a91282011-08-31 11:23:23 +0200951 // Inform configurations
952 uint32_t uiNbConfigurations = getNbChildren();
953 uint32_t uiChild;
954
955 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
956
957 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
958
Patrick Benavoli63499d42011-10-24 18:50:03 +0200959 pDomainConfiguration->addConfigurableElement(pConfigurableElement, pSyncerSet);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200960 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200961
962 // Already associated descended configurable elements need a merge of their configuration data
963 mergeAlreadyAssociatedDescendantConfigurableElements(pConfigurableElement);
964
965 // Add to list
966 _configurableElementList.push_back(pConfigurableElement);
967}
968
969void CConfigurableDomain::doRemoveConfigurableElement(CConfigurableElement* pConfigurableElement, bool bRecomputeSyncSet)
970{
971 // Remove from list
972 _configurableElementList.remove(pConfigurableElement);
973
Patrick Benavoli63499d42011-10-24 18:50:03 +0200974 // Remove associated syncer set
975 CSyncerSet* pSyncerSet = getSyncerSet(pConfigurableElement);
976
977 _configurableElementToSyncerSetMap.erase(pConfigurableElement);
978
979 delete pSyncerSet;
980
Patrick Benavoli68a91282011-08-31 11:23:23 +0200981 // Inform configurable element
982 pConfigurableElement->removeAttachedConfigurableDomain(this);
983
984 // Inform configurations
985 uint32_t uiNbConfigurations = getNbChildren();
986 uint32_t uiChild;
987
988 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
989
990 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
991
992 pDomainConfiguration->removeConfigurableElement(pConfigurableElement);
993 }
994 // Recompute our sync set if needed
995 if (bRecomputeSyncSet) {
996
997 computeSyncSet();
998 }
999}
Patrick Benavoli63499d42011-10-24 18:50:03 +02001000
1001// Syncer set retrieval from configurable element
1002CSyncerSet* CConfigurableDomain::getSyncerSet(const CConfigurableElement* pConfigurableElement) const
1003{
1004 ConfigurableElementToSyncerSetMapIterator mapIt = _configurableElementToSyncerSetMap.find(pConfigurableElement);
1005
1006 assert(mapIt != _configurableElementToSyncerSetMap.end());
1007
1008 return mapIt->second;
1009}
Patrick Benavoli0bd50542011-11-29 11:10:27 +01001010
1011// Configuration retrieval
1012CDomainConfiguration* CConfigurableDomain::findConfiguration(const string& strConfiguration, string& strError)
1013{
1014 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(strConfiguration));
1015
1016 if (!pDomainConfiguration) {
1017
1018 strError = "Domain configuration " + strConfiguration + " not found";
1019
1020 return NULL;
1021 }
1022 return pDomainConfiguration;
1023}
1024
1025const CDomainConfiguration* CConfigurableDomain::findConfiguration(const string& strConfiguration, string& strError) const
1026{
1027 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(findChild(strConfiguration));
1028
1029 if (!pDomainConfiguration) {
1030
1031 strError = "Domain configuration " + strConfiguration + " not found";
1032
1033 return NULL;
1034 }
1035 return pDomainConfiguration;
1036}