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