blob: c72b0a835b4a9399763184dee01763ba0187d165 [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
Frédéric Boisnard9620e442012-05-30 16:15:02 +0200359 doAddConfigurableElement(pConfigurableElement, pMainBlackboard);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200360
361 return true;
362}
363
364bool CConfigurableDomain::removeConfigurableElement(CConfigurableElement* pConfigurableElement, string& strError)
365{
366 // Not associated?
367 if (!containsConfigurableElement(pConfigurableElement)) {
368
369 strError = "Configurable element " + pConfigurableElement->getPath() + " not associated to configuration domain " + getName();
370
371 return false;
372 }
373 log("Removing configurable element \"%s\" from domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str());
374
375 // Do remove
376 doRemoveConfigurableElement(pConfigurableElement, true);
377
378 return true;
379}
380
381// Domain splitting
382bool CConfigurableDomain::split(CConfigurableElement* pConfigurableElement, string& strError)
383{
384 // Not associated?
385 if (!containsConfigurableElement(pConfigurableElement)) {
386
387 strError = "Configurable element " + pConfigurableElement->getPath() + " not associated to configuration domain " + getName();
388
389 return false;
390 }
391 log("Splitting configurable element \"%s\" domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str());
392
393 // Create sub domain areas for all configurable element's children
394 uint32_t uiNbConfigurableElementChildren = pConfigurableElement->getNbChildren();
395
396 if (!uiNbConfigurableElementChildren) {
397
398 strError = "Configurable element " + pConfigurableElement->getPath() + " has no children to split configurable domain to";
399
400 return false;
401 }
402
403 uint32_t uiChild;
404
405 for (uiChild = 0; uiChild < uiNbConfigurableElementChildren; uiChild++) {
406
407 CConfigurableElement* pChildConfigurableElement = static_cast<CConfigurableElement*>(pConfigurableElement->getChild(uiChild));
408
409 doAddConfigurableElement(pChildConfigurableElement);
410 }
411
412 // Delegate to configurations
413 uint32_t uiNbConfigurations = getNbChildren();
414
415 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
416
417 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
418
419 pDomainConfiguration->split(pConfigurableElement);
420 }
421
422 // Remove given configurable element from this domain
423 // 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
424 doRemoveConfigurableElement(pConfigurableElement, false);
425
426 return true;
427}
428
429// Configuration application if required
Patrick Benavoli63499d42011-10-24 18:50:03 +0200430bool CConfigurableDomain::apply(CParameterBlackboard* pParameterBlackboard, CSyncerSet& syncerSet, bool bForce, string& strError) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200431{
432 if (bForce) {
433 // Force a configuration restore by forgetting about last applied configuration
434 _pLastAppliedConfiguration = NULL;
435 }
436 const CDomainConfiguration* pApplicableDomainConfiguration = findApplicableDomainConfiguration();
437
438 if (pApplicableDomainConfiguration) {
439
440 // Check not the last one before applying
441 if (!_pLastAppliedConfiguration || _pLastAppliedConfiguration != pApplicableDomainConfiguration) {
442
443 log("Applying configuration \"%s\" from domain \"%s\"", pApplicableDomainConfiguration->getName().c_str(), getName().c_str());
444
445 // Do the restore
Patrick Benavoli63499d42011-10-24 18:50:03 +0200446 if (!pApplicableDomainConfiguration->restore(pParameterBlackboard, _bSequenceAware, strError)) {
447
448 return false;
449 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200450
451 // Record last applied configuration
452 _pLastAppliedConfiguration = pApplicableDomainConfiguration;
453
Patrick Benavoli63499d42011-10-24 18:50:03 +0200454 // Check we did not already sync the changes
455 if (!_bSequenceAware) {
456
457 // Since we applied changes, add our own sync set to the given one
458 syncerSet += _syncerSet;
459 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200460 }
461 }
Patrick Benavoli63499d42011-10-24 18:50:03 +0200462
463 return true;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200464}
465
466// Return applicable configuration validity for given configurable element
467bool CConfigurableDomain::isApplicableConfigurationValid(const CConfigurableElement* pConfigurableElement) const
468{
469 const CDomainConfiguration* pApplicableDomainConfiguration = findApplicableDomainConfiguration();
470
471 return pApplicableDomainConfiguration && pApplicableDomainConfiguration->isValid(pConfigurableElement);
472}
473
Patrick Benavoli68a91282011-08-31 11:23:23 +0200474// In case configurable element was removed
475void CConfigurableDomain::computeSyncSet()
476{
477 // Clean sync set first
Patrick Benavoli63499d42011-10-24 18:50:03 +0200478 _syncerSet.clear();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200479
Patrick Benavoli63499d42011-10-24 18:50:03 +0200480 // Add syncer sets for all associated configurable elements
481 ConfigurableElementToSyncerSetMapIterator mapIt;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200482
Patrick Benavoli63499d42011-10-24 18:50:03 +0200483 for (mapIt = _configurableElementToSyncerSetMap.begin(); mapIt != _configurableElementToSyncerSetMap.end(); ++mapIt) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200484
Patrick Benavoli63499d42011-10-24 18:50:03 +0200485 const CSyncerSet* pSyncerSet = mapIt->second;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200486
Patrick Benavoli63499d42011-10-24 18:50:03 +0200487 _syncerSet += *pSyncerSet;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200488 }
489}
490
491// Configuration Management
492bool CConfigurableDomain::createConfiguration(const string& strName, const CParameterBlackboard* pMainBlackboard, string& strError)
493{
494 // Already exists?
495 if (findChild(strName)) {
496
497 strError = "Already existing configuration";
498
499 return false;
500 }
501 log("Creating domain configuration \"%s\" into domain \"%s\"", strName.c_str(), getName().c_str());
502
503 // Creation
504 CDomainConfiguration* pDomainConfiguration = new CDomainConfiguration(strName);
505
506 // Configurable elements association
507 ConfigurableElementListIterator it;
508
509 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
510
Patrick Benavoli63499d42011-10-24 18:50:03 +0200511 const CConfigurableElement* pConfigurableElement = *it;;
512
513 // Retrieve associated syncer set
514 CSyncerSet* pSyncerSet = getSyncerSet(pConfigurableElement);
515
516 // Associate to configuration
517 pDomainConfiguration->addConfigurableElement(pConfigurableElement, pSyncerSet);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200518 }
519
520 // Hierarchy
521 addChild(pDomainConfiguration);
522
523 // Ensure validity of fresh new domain configuration
524 // Attempt auto validation, so that the user gets his/her own settings by defaults
525 if (!autoValidateConfiguration(pDomainConfiguration)) {
526
527 // No valid configuration found to copy in from, validate againt main blackboard (will concerned remaining invalid parts)
528 pDomainConfiguration->validate(pMainBlackboard);
529 }
530
531 return true;
532}
533
534bool CConfigurableDomain::deleteConfiguration(const string& strName, string& strError)
535{
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100536 CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200537
538 if (!pDomainConfiguration) {
539
Patrick Benavoli68a91282011-08-31 11:23:23 +0200540 return false;
541 }
542
543 log("Deleting configuration \"%s\" from domain \"%s\"", strName.c_str(), getName().c_str());
544
545 // Was the last applied?
546 if (pDomainConfiguration == _pLastAppliedConfiguration) {
547
548 // Forget about it
549 _pLastAppliedConfiguration = NULL;
550 }
551
552 // Hierarchy
553 removeChild(pDomainConfiguration);
554
555 // Destroy
556 delete pDomainConfiguration;
557
558 return true;
559}
560
561void CConfigurableDomain::listAssociatedToElements(string& strResult) const
562{
563 strResult = "\n";
564
565 ConfigurableElementListIterator it;
566
567 // Browse all configurable elements
568 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
569
570 const CConfigurableElement* pConfigurableElement = *it;
571
572 strResult += pConfigurableElement->getPath() + "\n";
573 }
574}
575
576bool CConfigurableDomain::renameConfiguration(const string& strName, const string& strNewName, string& strError)
577{
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100578 CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200579
580 if (!pDomainConfiguration) {
581
Patrick Benavoli68a91282011-08-31 11:23:23 +0200582 return false;
583 }
584 log("Renaming domain \"%s\"'s configuration \"%s\" to \"%s\"", getName().c_str(), strName.c_str(), strNewName.c_str());
585
586 // Rename
587 return pDomainConfiguration->rename(strNewName, strError);
588}
589
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100590bool CConfigurableDomain::restoreConfiguration(const string& strName, CParameterBlackboard* pMainBlackboard, bool bAutoSync, string& strError) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200591{
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100592 const CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200593
594 if (!pDomainConfiguration) {
595
Patrick Benavoli68a91282011-08-31 11:23:23 +0200596 return false;
597 }
598 log("Restoring domain \"%s\"'s configuration \"%s\" to parameter blackboard", getName().c_str(), pDomainConfiguration->getName().c_str());
599
600 // Delegate
Patrick Benavoli63499d42011-10-24 18:50:03 +0200601 if (!pDomainConfiguration->restore(pMainBlackboard, _bSequenceAware && bAutoSync, strError)) {
602
603 return false;
604 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200605
606 // Record last applied configuration
607 _pLastAppliedConfiguration = pDomainConfiguration;
608
609 // Synchronize
610 return !bAutoSync || _syncerSet.sync(*pMainBlackboard, false, strError);
611}
612
613bool CConfigurableDomain::saveConfiguration(const string& strName, const CParameterBlackboard* pMainBlackboard, string& strError)
614{
615 // Find Domain configuration
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100616 CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200617
618 if (!pDomainConfiguration) {
619
Patrick Benavoli68a91282011-08-31 11:23:23 +0200620 return false;
621 }
622 log("Saving domain \"%s\"'s configuration \"%s\" from parameter blackboard", getName().c_str(), pDomainConfiguration->getName().c_str());
623
624 // Delegate
625 pDomainConfiguration->save(pMainBlackboard);
626
627 return true;
628}
629
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100630bool CConfigurableDomain::setElementSequence(const string& strConfiguration, const vector<string>& astrNewElementSequence, string& strError)
Patrick Benavoli63499d42011-10-24 18:50:03 +0200631{
632 // Find Domain configuration
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100633 CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strError);
Patrick Benavoli63499d42011-10-24 18:50:03 +0200634
635 if (!pDomainConfiguration) {
636
Patrick Benavoli63499d42011-10-24 18:50:03 +0200637 return false;
638 }
639
640 // Delegate to configuration
641 return pDomainConfiguration->setElementSequence(astrNewElementSequence, strError);
642}
643
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100644bool CConfigurableDomain::getElementSequence(const string& strConfiguration, string& strResult) const
Patrick Benavoli63499d42011-10-24 18:50:03 +0200645{
646 // Find Domain configuration
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100647 const CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strResult);
Patrick Benavoli63499d42011-10-24 18:50:03 +0200648
649 if (!pDomainConfiguration) {
650
Patrick Benavoli63499d42011-10-24 18:50:03 +0200651 return false;
652 }
653
654 // Delegate to configuration
655 pDomainConfiguration->getElementSequence(strResult);
656
657 return true;
658}
659
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100660bool CConfigurableDomain::setApplicationRule(const string& strConfiguration, const string& strApplicationRule, const CSelectionCriteriaDefinition* pSelectionCriteriaDefinition, string& strError)
661{
662 // Find Domain configuration
663 CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strError);
664
665 if (!pDomainConfiguration) {
666
667 return false;
668 }
669
670 // Delegate to configuration
671 return pDomainConfiguration->setApplicationRule(strApplicationRule, pSelectionCriteriaDefinition, strError);
672}
673
674bool CConfigurableDomain::clearApplicationRule(const string& strConfiguration, string& strError)
675{
676 // Find Domain configuration
677 CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strError);
678
679 if (!pDomainConfiguration) {
680
681 return false;
682 }
683
684 // Delegate to configuration
685 pDomainConfiguration->clearApplicationRule();
686
687 return true;
688}
689
690bool CConfigurableDomain::getApplicationRule(const string& strConfiguration, string& strResult) const
691{
692 // Find Domain configuration
693 const CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strResult);
694
695 if (!pDomainConfiguration) {
696
697 return false;
698 }
699
700 // Delegate to configuration
701 pDomainConfiguration->getApplicationRule(strResult);
702
703 return true;
704}
705
Patrick Benavoli68a91282011-08-31 11:23:23 +0200706// Last applied configuration
707string CConfigurableDomain::getLastAppliedConfigurationName() const
708{
709 if (_pLastAppliedConfiguration) {
710
711 return _pLastAppliedConfiguration->getName();
712 }
713 return "<none>";
714}
715
716// Ensure validity on whole domain from main blackboard
717void CConfigurableDomain::validate(const CParameterBlackboard* pMainBlackboard)
718{
719 log("Validating whole domain \"" + getName() + "\" against main blackboard");
720
721 // Propagate
722 uint32_t uiNbConfigurations = getNbChildren();
723 uint32_t uiChild;
724
725 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
726
727 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
728
729 pDomainConfiguration->validate(pMainBlackboard);
730 }
731}
732
733// Ensure validity on areas related to configurable element
734void CConfigurableDomain::validateAreas(const CConfigurableElement* pConfigurableElement, const CParameterBlackboard* pMainBlackboard)
735{
736 log("Validating domain \"" + getName() + "\" against main blackboard for configurable element \"" + pConfigurableElement->getPath() + "\"");
737
738 // Propagate
739 uint32_t uiNbConfigurations = getNbChildren();
740 uint32_t uiChild;
741
742 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
743
744 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
745
746 pDomainConfiguration->validate(pConfigurableElement, pMainBlackboard);
747 }
748}
749
750// Attempt validation for all configurable element's areas, relying on already existing valid configuration inside domain
751void CConfigurableDomain::autoValidateAll()
752{
753 // Validate
754 ConfigurableElementListIterator it;
755
756 // Browse all configurable elements for configuration validation
757 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
758
759 const CConfigurableElement* pConfigurableElement = *it;
760
761 // Auto validate element
762 autoValidateAreas(pConfigurableElement);
763 }
764}
765
766// Attempt validation for configurable element's areas, relying on already existing valid configuration inside domain
767void CConfigurableDomain::autoValidateAreas(const CConfigurableElement* pConfigurableElement)
768{
769 // Find first valid configuration for given configurable element
770 const CDomainConfiguration* pValidDomainConfiguration = findValidDomainConfiguration(pConfigurableElement);
771
772 // No valid configuration found, give up
773 if (!pValidDomainConfiguration) {
774
775 return;
776 }
777
778 log("Auto validating domain \"" + getName() + "\" against configuration \"" + pValidDomainConfiguration->getName() + "\" for configurable element " + pConfigurableElement->getPath());
779
780 // Validate all other configurations against found one, if any
781 uint32_t uiNbConfigurations = getNbChildren();
782 uint32_t uiChild;
783
784 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
785
786 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
787
788 if (pDomainConfiguration != pValidDomainConfiguration && !pDomainConfiguration->isValid(pConfigurableElement)) {
789 // Validate
790 pDomainConfiguration->validateAgainst(pValidDomainConfiguration, pConfigurableElement);
791 }
792 }
793}
794
795// Attempt configuration validation for all configurable elements' areas, relying on already existing valid configuration inside domain
796bool CConfigurableDomain::autoValidateConfiguration(CDomainConfiguration* pDomainConfiguration)
797{
798 // Find another configuration than this one, that ought to be valid!
799 uint32_t uiNbConfigurations = getNbChildren();
800 uint32_t uiChild;
801
802 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
803
804 const CDomainConfiguration* pPotententialValidDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
805
806 if (pPotententialValidDomainConfiguration != pDomainConfiguration) {
807
808 // Validate against it
809 pDomainConfiguration->validateAgainst(pPotententialValidDomainConfiguration);
810
811 return true;
812 }
813 }
814 return false;
815}
Patrick Benavoli68a91282011-08-31 11:23:23 +0200816
Patrick Benavoli68a91282011-08-31 11:23:23 +0200817// Search for a valid configuration for given configurable element
818const CDomainConfiguration* CConfigurableDomain::findValidDomainConfiguration(const CConfigurableElement* pConfigurableElement) const
819{
820 uint32_t uiNbConfigurations = getNbChildren();
821 uint32_t uiChild;
822
823 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
824
825 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
826
827 if (pDomainConfiguration->isValid(pConfigurableElement)) {
828
829 return pDomainConfiguration;
830 }
831 }
832 return NULL;
833}
834
835// Search for an applicable configuration
836const CDomainConfiguration* CConfigurableDomain::findApplicableDomainConfiguration() const
837{
838 uint32_t uiNbConfigurations = getNbChildren();
839 uint32_t uiChild;
840
841 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
842
843 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
844
845 if (pDomainConfiguration->isApplicable()) {
846
847 return pDomainConfiguration;
848 }
849 }
850 return NULL;
851}
852
853// Gather set of configurable elements
854void CConfigurableDomain::gatherConfigurableElements(set<const CConfigurableElement*>& configurableElementSet) const
855{
856 // Insert all configurable elements
857 configurableElementSet.insert(_configurableElementList.begin(), _configurableElementList.end());
858}
859
860// Check configurable element already attached
861bool CConfigurableDomain::containsConfigurableElement(const CConfigurableElement* pConfigurableCandidateElement) const
862{
863 ConfigurableElementListIterator it;
864
865 // Browse all configurable elements for comparison
866 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
867
868 if (pConfigurableCandidateElement == *it) {
869
870 return true;
871 }
872 }
873 return false;
874}
875
876// Merge any descended configurable element to this one with this one
877void CConfigurableDomain::mergeAlreadyAssociatedDescendantConfigurableElements(CConfigurableElement* pNewConfigurableElement)
878{
879 list<CConfigurableElement*> mergedConfigurableElementList;
880
881 ConfigurableElementListIterator it;
882
883 // Browse all configurable elements (new one not yet in the list!)
884 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
885
886 CConfigurableElement* pConfigurablePotentialDescendantElement = *it;
887
888 if (pConfigurablePotentialDescendantElement->isDescendantOf(pNewConfigurableElement)) {
889
890 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());
891
892 // Merge configuration data
893 mergeConfigurations(pNewConfigurableElement, pConfigurablePotentialDescendantElement);
894
895 // Keep track for removal
896 mergedConfigurableElementList.push_back(pConfigurablePotentialDescendantElement);
897 }
898 }
899
900 // Remove all merged elements (new one not yet in the list!)
901 for (it = mergedConfigurableElementList.begin(); it != mergedConfigurableElementList.end(); ++it) {
902
903 CConfigurableElement* pMergedConfigurableElement = *it;
904
905 // Remove merged from configurable element from internal tracking list
906 // 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
907 doRemoveConfigurableElement(pMergedConfigurableElement, false);
908 }
909}
910
911void CConfigurableDomain::mergeConfigurations(CConfigurableElement* pToConfigurableElement, CConfigurableElement* pFromConfigurableElement)
912{
913 // Propagate to domain configurations
914 uint32_t uiNbConfigurations = getNbChildren();
915 uint32_t uiChild;
916
917 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
918
919 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
920
921 // Do the merge.
922 pDomainConfiguration->merge(pToConfigurableElement, pFromConfigurableElement);
923 }
924}
925
926// Configurable elements association
Frédéric Boisnard9620e442012-05-30 16:15:02 +0200927void CConfigurableDomain::doAddConfigurableElement(CConfigurableElement* pConfigurableElement, const CParameterBlackboard *pMainBlackboard)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200928{
929 // Inform configurable element
930 pConfigurableElement->addAttachedConfigurableDomain(this);
931
Patrick Benavoli63499d42011-10-24 18:50:03 +0200932 // Create associated syncer set
933 CSyncerSet* pSyncerSet = new CSyncerSet;
934
935 // Add to sync set the configurable element one
936 pConfigurableElement->fillSyncerSet(*pSyncerSet);
937
938 // Store it
939 _configurableElementToSyncerSetMap[pConfigurableElement] = pSyncerSet;
940
941 // Add it to global one
942 _syncerSet += *pSyncerSet;
943
Patrick Benavoli68a91282011-08-31 11:23:23 +0200944 // Inform configurations
945 uint32_t uiNbConfigurations = getNbChildren();
946 uint32_t uiChild;
947
948 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
949
950 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
951
Patrick Benavoli63499d42011-10-24 18:50:03 +0200952 pDomainConfiguration->addConfigurableElement(pConfigurableElement, pSyncerSet);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200953 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200954
Frédéric Boisnard9620e442012-05-30 16:15:02 +0200955 // Ensure area validity for that configurable element (if main blackboard provided)
956 if (pMainBlackboard) {
957
958 // Need to validate against main blackboard
959 validateAreas(pConfigurableElement, pMainBlackboard);
960 }
961
962 // Already associated descendend configurable elements need a merge of their configuration data
Patrick Benavoli68a91282011-08-31 11:23:23 +0200963 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}