blob: 8c83f4895f46638fb5871163e02f72fac1f9af3f [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
Frédéric Boisnard8b243f52012-09-06 18:03:20 +0200423// Check if there is a pending configuration for this domain: i.e. an applicable configuration different from the last applied configuration
424const CDomainConfiguration* CConfigurableDomain::getPendingConfiguration() const
425{
426 const CDomainConfiguration* pApplicableDomainConfiguration = findApplicableDomainConfiguration();
427
428 if (pApplicableDomainConfiguration) {
429
430 // Check not the last one before applying
431 if (!_pLastAppliedConfiguration || (_pLastAppliedConfiguration != pApplicableDomainConfiguration)) {
432
433 return pApplicableDomainConfiguration;
434 }
435 }
436
437 return NULL;
438}
439
Patrick Benavoli68a91282011-08-31 11:23:23 +0200440// Configuration application if required
Patrick Benavoli63499d42011-10-24 18:50:03 +0200441bool CConfigurableDomain::apply(CParameterBlackboard* pParameterBlackboard, CSyncerSet& syncerSet, bool bForce, string& strError) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200442{
443 if (bForce) {
444 // Force a configuration restore by forgetting about last applied configuration
445 _pLastAppliedConfiguration = NULL;
446 }
447 const CDomainConfiguration* pApplicableDomainConfiguration = findApplicableDomainConfiguration();
448
449 if (pApplicableDomainConfiguration) {
450
451 // Check not the last one before applying
452 if (!_pLastAppliedConfiguration || _pLastAppliedConfiguration != pApplicableDomainConfiguration) {
453
454 log("Applying configuration \"%s\" from domain \"%s\"", pApplicableDomainConfiguration->getName().c_str(), getName().c_str());
455
456 // Do the restore
Patrick Benavoli63499d42011-10-24 18:50:03 +0200457 if (!pApplicableDomainConfiguration->restore(pParameterBlackboard, _bSequenceAware, strError)) {
458
459 return false;
460 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200461
462 // Record last applied configuration
463 _pLastAppliedConfiguration = pApplicableDomainConfiguration;
464
Patrick Benavoli63499d42011-10-24 18:50:03 +0200465 // Check we did not already sync the changes
466 if (!_bSequenceAware) {
467
468 // Since we applied changes, add our own sync set to the given one
469 syncerSet += _syncerSet;
470 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200471 }
472 }
Patrick Benavoli63499d42011-10-24 18:50:03 +0200473
474 return true;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200475}
476
477// Return applicable configuration validity for given configurable element
478bool CConfigurableDomain::isApplicableConfigurationValid(const CConfigurableElement* pConfigurableElement) const
479{
480 const CDomainConfiguration* pApplicableDomainConfiguration = findApplicableDomainConfiguration();
481
482 return pApplicableDomainConfiguration && pApplicableDomainConfiguration->isValid(pConfigurableElement);
483}
484
Patrick Benavoli68a91282011-08-31 11:23:23 +0200485// In case configurable element was removed
486void CConfigurableDomain::computeSyncSet()
487{
488 // Clean sync set first
Patrick Benavoli63499d42011-10-24 18:50:03 +0200489 _syncerSet.clear();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200490
Patrick Benavoli63499d42011-10-24 18:50:03 +0200491 // Add syncer sets for all associated configurable elements
492 ConfigurableElementToSyncerSetMapIterator mapIt;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200493
Patrick Benavoli63499d42011-10-24 18:50:03 +0200494 for (mapIt = _configurableElementToSyncerSetMap.begin(); mapIt != _configurableElementToSyncerSetMap.end(); ++mapIt) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200495
Patrick Benavoli63499d42011-10-24 18:50:03 +0200496 const CSyncerSet* pSyncerSet = mapIt->second;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200497
Patrick Benavoli63499d42011-10-24 18:50:03 +0200498 _syncerSet += *pSyncerSet;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200499 }
500}
501
502// Configuration Management
503bool CConfigurableDomain::createConfiguration(const string& strName, const CParameterBlackboard* pMainBlackboard, string& strError)
504{
505 // Already exists?
506 if (findChild(strName)) {
507
508 strError = "Already existing configuration";
509
510 return false;
511 }
512 log("Creating domain configuration \"%s\" into domain \"%s\"", strName.c_str(), getName().c_str());
513
514 // Creation
515 CDomainConfiguration* pDomainConfiguration = new CDomainConfiguration(strName);
516
517 // Configurable elements association
518 ConfigurableElementListIterator it;
519
520 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
521
Patrick Benavoli63499d42011-10-24 18:50:03 +0200522 const CConfigurableElement* pConfigurableElement = *it;;
523
524 // Retrieve associated syncer set
525 CSyncerSet* pSyncerSet = getSyncerSet(pConfigurableElement);
526
527 // Associate to configuration
528 pDomainConfiguration->addConfigurableElement(pConfigurableElement, pSyncerSet);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200529 }
530
531 // Hierarchy
532 addChild(pDomainConfiguration);
533
534 // Ensure validity of fresh new domain configuration
535 // Attempt auto validation, so that the user gets his/her own settings by defaults
536 if (!autoValidateConfiguration(pDomainConfiguration)) {
537
538 // No valid configuration found to copy in from, validate againt main blackboard (will concerned remaining invalid parts)
539 pDomainConfiguration->validate(pMainBlackboard);
540 }
541
542 return true;
543}
544
545bool CConfigurableDomain::deleteConfiguration(const string& strName, string& strError)
546{
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100547 CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200548
549 if (!pDomainConfiguration) {
550
Patrick Benavoli68a91282011-08-31 11:23:23 +0200551 return false;
552 }
553
554 log("Deleting configuration \"%s\" from domain \"%s\"", strName.c_str(), getName().c_str());
555
556 // Was the last applied?
557 if (pDomainConfiguration == _pLastAppliedConfiguration) {
558
559 // Forget about it
560 _pLastAppliedConfiguration = NULL;
561 }
562
563 // Hierarchy
564 removeChild(pDomainConfiguration);
565
566 // Destroy
567 delete pDomainConfiguration;
568
569 return true;
570}
571
572void CConfigurableDomain::listAssociatedToElements(string& strResult) const
573{
574 strResult = "\n";
575
576 ConfigurableElementListIterator it;
577
578 // Browse all configurable elements
579 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
580
581 const CConfigurableElement* pConfigurableElement = *it;
582
583 strResult += pConfigurableElement->getPath() + "\n";
584 }
585}
586
587bool CConfigurableDomain::renameConfiguration(const string& strName, const string& strNewName, string& strError)
588{
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100589 CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200590
591 if (!pDomainConfiguration) {
592
Patrick Benavoli68a91282011-08-31 11:23:23 +0200593 return false;
594 }
595 log("Renaming domain \"%s\"'s configuration \"%s\" to \"%s\"", getName().c_str(), strName.c_str(), strNewName.c_str());
596
597 // Rename
598 return pDomainConfiguration->rename(strNewName, strError);
599}
600
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100601bool CConfigurableDomain::restoreConfiguration(const string& strName, CParameterBlackboard* pMainBlackboard, bool bAutoSync, string& strError) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200602{
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100603 const CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200604
605 if (!pDomainConfiguration) {
606
Patrick Benavoli68a91282011-08-31 11:23:23 +0200607 return false;
608 }
609 log("Restoring domain \"%s\"'s configuration \"%s\" to parameter blackboard", getName().c_str(), pDomainConfiguration->getName().c_str());
610
611 // Delegate
Patrick Benavoli63499d42011-10-24 18:50:03 +0200612 if (!pDomainConfiguration->restore(pMainBlackboard, _bSequenceAware && bAutoSync, strError)) {
613
614 return false;
615 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200616
617 // Record last applied configuration
618 _pLastAppliedConfiguration = pDomainConfiguration;
619
620 // Synchronize
621 return !bAutoSync || _syncerSet.sync(*pMainBlackboard, false, strError);
622}
623
624bool CConfigurableDomain::saveConfiguration(const string& strName, const CParameterBlackboard* pMainBlackboard, string& strError)
625{
626 // Find Domain configuration
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100627 CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200628
629 if (!pDomainConfiguration) {
630
Patrick Benavoli68a91282011-08-31 11:23:23 +0200631 return false;
632 }
633 log("Saving domain \"%s\"'s configuration \"%s\" from parameter blackboard", getName().c_str(), pDomainConfiguration->getName().c_str());
634
635 // Delegate
636 pDomainConfiguration->save(pMainBlackboard);
637
638 return true;
639}
640
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100641bool CConfigurableDomain::setElementSequence(const string& strConfiguration, const vector<string>& astrNewElementSequence, string& strError)
Patrick Benavoli63499d42011-10-24 18:50:03 +0200642{
643 // Find Domain configuration
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100644 CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strError);
Patrick Benavoli63499d42011-10-24 18:50:03 +0200645
646 if (!pDomainConfiguration) {
647
Patrick Benavoli63499d42011-10-24 18:50:03 +0200648 return false;
649 }
650
651 // Delegate to configuration
652 return pDomainConfiguration->setElementSequence(astrNewElementSequence, strError);
653}
654
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100655bool CConfigurableDomain::getElementSequence(const string& strConfiguration, string& strResult) const
Patrick Benavoli63499d42011-10-24 18:50:03 +0200656{
657 // Find Domain configuration
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100658 const CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strResult);
Patrick Benavoli63499d42011-10-24 18:50:03 +0200659
660 if (!pDomainConfiguration) {
661
Patrick Benavoli63499d42011-10-24 18:50:03 +0200662 return false;
663 }
664
665 // Delegate to configuration
666 pDomainConfiguration->getElementSequence(strResult);
667
668 return true;
669}
670
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100671bool CConfigurableDomain::setApplicationRule(const string& strConfiguration, const string& strApplicationRule, const CSelectionCriteriaDefinition* pSelectionCriteriaDefinition, string& strError)
672{
673 // Find Domain configuration
674 CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strError);
675
676 if (!pDomainConfiguration) {
677
678 return false;
679 }
680
681 // Delegate to configuration
682 return pDomainConfiguration->setApplicationRule(strApplicationRule, pSelectionCriteriaDefinition, strError);
683}
684
685bool CConfigurableDomain::clearApplicationRule(const string& strConfiguration, string& strError)
686{
687 // Find Domain configuration
688 CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strError);
689
690 if (!pDomainConfiguration) {
691
692 return false;
693 }
694
695 // Delegate to configuration
696 pDomainConfiguration->clearApplicationRule();
697
698 return true;
699}
700
701bool CConfigurableDomain::getApplicationRule(const string& strConfiguration, string& strResult) const
702{
703 // Find Domain configuration
704 const CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strResult);
705
706 if (!pDomainConfiguration) {
707
708 return false;
709 }
710
711 // Delegate to configuration
712 pDomainConfiguration->getApplicationRule(strResult);
713
714 return true;
715}
716
Patrick Benavoli68a91282011-08-31 11:23:23 +0200717// Last applied configuration
718string CConfigurableDomain::getLastAppliedConfigurationName() const
719{
720 if (_pLastAppliedConfiguration) {
721
722 return _pLastAppliedConfiguration->getName();
723 }
724 return "<none>";
725}
726
Frédéric Boisnard8b243f52012-09-06 18:03:20 +0200727// Pending configuration
728string CConfigurableDomain::getPendingConfigurationName() const
729{
730 const CDomainConfiguration* pPendingConfiguration = getPendingConfiguration();
731
732 if (pPendingConfiguration) {
733
734 return pPendingConfiguration->getName();
735 }
736 return "<none>";
737}
738
Patrick Benavoli68a91282011-08-31 11:23:23 +0200739// Ensure validity on whole domain from main blackboard
740void CConfigurableDomain::validate(const CParameterBlackboard* pMainBlackboard)
741{
742 log("Validating whole domain \"" + getName() + "\" against main blackboard");
743
744 // Propagate
745 uint32_t uiNbConfigurations = getNbChildren();
746 uint32_t uiChild;
747
748 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
749
750 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
751
752 pDomainConfiguration->validate(pMainBlackboard);
753 }
754}
755
756// Ensure validity on areas related to configurable element
757void CConfigurableDomain::validateAreas(const CConfigurableElement* pConfigurableElement, const CParameterBlackboard* pMainBlackboard)
758{
759 log("Validating domain \"" + getName() + "\" against main blackboard for configurable element \"" + pConfigurableElement->getPath() + "\"");
760
761 // Propagate
762 uint32_t uiNbConfigurations = getNbChildren();
763 uint32_t uiChild;
764
765 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
766
767 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
768
769 pDomainConfiguration->validate(pConfigurableElement, pMainBlackboard);
770 }
771}
772
773// Attempt validation for all configurable element's areas, relying on already existing valid configuration inside domain
774void CConfigurableDomain::autoValidateAll()
775{
776 // Validate
777 ConfigurableElementListIterator it;
778
779 // Browse all configurable elements for configuration validation
780 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
781
782 const CConfigurableElement* pConfigurableElement = *it;
783
784 // Auto validate element
785 autoValidateAreas(pConfigurableElement);
786 }
787}
788
789// Attempt validation for configurable element's areas, relying on already existing valid configuration inside domain
790void CConfigurableDomain::autoValidateAreas(const CConfigurableElement* pConfigurableElement)
791{
792 // Find first valid configuration for given configurable element
793 const CDomainConfiguration* pValidDomainConfiguration = findValidDomainConfiguration(pConfigurableElement);
794
795 // No valid configuration found, give up
796 if (!pValidDomainConfiguration) {
797
798 return;
799 }
800
801 log("Auto validating domain \"" + getName() + "\" against configuration \"" + pValidDomainConfiguration->getName() + "\" for configurable element " + pConfigurableElement->getPath());
802
803 // Validate all other configurations against found one, if any
804 uint32_t uiNbConfigurations = getNbChildren();
805 uint32_t uiChild;
806
807 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
808
809 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
810
811 if (pDomainConfiguration != pValidDomainConfiguration && !pDomainConfiguration->isValid(pConfigurableElement)) {
812 // Validate
813 pDomainConfiguration->validateAgainst(pValidDomainConfiguration, pConfigurableElement);
814 }
815 }
816}
817
818// Attempt configuration validation for all configurable elements' areas, relying on already existing valid configuration inside domain
819bool CConfigurableDomain::autoValidateConfiguration(CDomainConfiguration* pDomainConfiguration)
820{
821 // Find another configuration than this one, that ought to be valid!
822 uint32_t uiNbConfigurations = getNbChildren();
823 uint32_t uiChild;
824
825 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
826
827 const CDomainConfiguration* pPotententialValidDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
828
829 if (pPotententialValidDomainConfiguration != pDomainConfiguration) {
830
831 // Validate against it
832 pDomainConfiguration->validateAgainst(pPotententialValidDomainConfiguration);
833
834 return true;
835 }
836 }
837 return false;
838}
Patrick Benavoli68a91282011-08-31 11:23:23 +0200839
Patrick Benavoli68a91282011-08-31 11:23:23 +0200840// Search for a valid configuration for given configurable element
841const CDomainConfiguration* CConfigurableDomain::findValidDomainConfiguration(const CConfigurableElement* pConfigurableElement) const
842{
843 uint32_t uiNbConfigurations = getNbChildren();
844 uint32_t uiChild;
845
846 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
847
848 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
849
850 if (pDomainConfiguration->isValid(pConfigurableElement)) {
851
852 return pDomainConfiguration;
853 }
854 }
855 return NULL;
856}
857
858// Search for an applicable configuration
859const CDomainConfiguration* CConfigurableDomain::findApplicableDomainConfiguration() const
860{
861 uint32_t uiNbConfigurations = getNbChildren();
862 uint32_t uiChild;
863
864 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
865
866 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
867
868 if (pDomainConfiguration->isApplicable()) {
869
870 return pDomainConfiguration;
871 }
872 }
873 return NULL;
874}
875
876// Gather set of configurable elements
877void CConfigurableDomain::gatherConfigurableElements(set<const CConfigurableElement*>& configurableElementSet) const
878{
879 // Insert all configurable elements
880 configurableElementSet.insert(_configurableElementList.begin(), _configurableElementList.end());
881}
882
883// Check configurable element already attached
884bool CConfigurableDomain::containsConfigurableElement(const CConfigurableElement* pConfigurableCandidateElement) const
885{
886 ConfigurableElementListIterator it;
887
888 // Browse all configurable elements for comparison
889 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
890
891 if (pConfigurableCandidateElement == *it) {
892
893 return true;
894 }
895 }
896 return false;
897}
898
899// Merge any descended configurable element to this one with this one
900void CConfigurableDomain::mergeAlreadyAssociatedDescendantConfigurableElements(CConfigurableElement* pNewConfigurableElement)
901{
902 list<CConfigurableElement*> mergedConfigurableElementList;
903
904 ConfigurableElementListIterator it;
905
906 // Browse all configurable elements (new one not yet in the list!)
907 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
908
909 CConfigurableElement* pConfigurablePotentialDescendantElement = *it;
910
911 if (pConfigurablePotentialDescendantElement->isDescendantOf(pNewConfigurableElement)) {
912
913 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());
914
915 // Merge configuration data
916 mergeConfigurations(pNewConfigurableElement, pConfigurablePotentialDescendantElement);
917
918 // Keep track for removal
919 mergedConfigurableElementList.push_back(pConfigurablePotentialDescendantElement);
920 }
921 }
922
923 // Remove all merged elements (new one not yet in the list!)
924 for (it = mergedConfigurableElementList.begin(); it != mergedConfigurableElementList.end(); ++it) {
925
926 CConfigurableElement* pMergedConfigurableElement = *it;
927
928 // Remove merged from configurable element from internal tracking list
929 // 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
930 doRemoveConfigurableElement(pMergedConfigurableElement, false);
931 }
932}
933
934void CConfigurableDomain::mergeConfigurations(CConfigurableElement* pToConfigurableElement, CConfigurableElement* pFromConfigurableElement)
935{
936 // Propagate to domain configurations
937 uint32_t uiNbConfigurations = getNbChildren();
938 uint32_t uiChild;
939
940 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
941
942 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
943
944 // Do the merge.
945 pDomainConfiguration->merge(pToConfigurableElement, pFromConfigurableElement);
946 }
947}
948
949// Configurable elements association
Frédéric Boisnard9620e442012-05-30 16:15:02 +0200950void CConfigurableDomain::doAddConfigurableElement(CConfigurableElement* pConfigurableElement, const CParameterBlackboard *pMainBlackboard)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200951{
952 // Inform configurable element
953 pConfigurableElement->addAttachedConfigurableDomain(this);
954
Patrick Benavoli63499d42011-10-24 18:50:03 +0200955 // Create associated syncer set
956 CSyncerSet* pSyncerSet = new CSyncerSet;
957
958 // Add to sync set the configurable element one
959 pConfigurableElement->fillSyncerSet(*pSyncerSet);
960
961 // Store it
962 _configurableElementToSyncerSetMap[pConfigurableElement] = pSyncerSet;
963
964 // Add it to global one
965 _syncerSet += *pSyncerSet;
966
Patrick Benavoli68a91282011-08-31 11:23:23 +0200967 // Inform configurations
968 uint32_t uiNbConfigurations = getNbChildren();
969 uint32_t uiChild;
970
971 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
972
973 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
974
Patrick Benavoli63499d42011-10-24 18:50:03 +0200975 pDomainConfiguration->addConfigurableElement(pConfigurableElement, pSyncerSet);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200976 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200977
Frédéric Boisnard9620e442012-05-30 16:15:02 +0200978 // Ensure area validity for that configurable element (if main blackboard provided)
979 if (pMainBlackboard) {
980
981 // Need to validate against main blackboard
982 validateAreas(pConfigurableElement, pMainBlackboard);
983 }
984
985 // Already associated descendend configurable elements need a merge of their configuration data
Patrick Benavoli68a91282011-08-31 11:23:23 +0200986 mergeAlreadyAssociatedDescendantConfigurableElements(pConfigurableElement);
987
988 // Add to list
989 _configurableElementList.push_back(pConfigurableElement);
990}
991
992void CConfigurableDomain::doRemoveConfigurableElement(CConfigurableElement* pConfigurableElement, bool bRecomputeSyncSet)
993{
994 // Remove from list
995 _configurableElementList.remove(pConfigurableElement);
996
Patrick Benavoli63499d42011-10-24 18:50:03 +0200997 // Remove associated syncer set
998 CSyncerSet* pSyncerSet = getSyncerSet(pConfigurableElement);
999
1000 _configurableElementToSyncerSetMap.erase(pConfigurableElement);
1001
1002 delete pSyncerSet;
1003
Patrick Benavoli68a91282011-08-31 11:23:23 +02001004 // Inform configurable element
1005 pConfigurableElement->removeAttachedConfigurableDomain(this);
1006
1007 // Inform configurations
1008 uint32_t uiNbConfigurations = getNbChildren();
1009 uint32_t uiChild;
1010
1011 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
1012
1013 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
1014
1015 pDomainConfiguration->removeConfigurableElement(pConfigurableElement);
1016 }
1017 // Recompute our sync set if needed
1018 if (bRecomputeSyncSet) {
1019
1020 computeSyncSet();
1021 }
1022}
Patrick Benavoli63499d42011-10-24 18:50:03 +02001023
1024// Syncer set retrieval from configurable element
1025CSyncerSet* CConfigurableDomain::getSyncerSet(const CConfigurableElement* pConfigurableElement) const
1026{
1027 ConfigurableElementToSyncerSetMapIterator mapIt = _configurableElementToSyncerSetMap.find(pConfigurableElement);
1028
1029 assert(mapIt != _configurableElementToSyncerSetMap.end());
1030
1031 return mapIt->second;
1032}
Patrick Benavoli0bd50542011-11-29 11:10:27 +01001033
1034// Configuration retrieval
1035CDomainConfiguration* CConfigurableDomain::findConfiguration(const string& strConfiguration, string& strError)
1036{
1037 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(strConfiguration));
1038
1039 if (!pDomainConfiguration) {
1040
1041 strError = "Domain configuration " + strConfiguration + " not found";
1042
1043 return NULL;
1044 }
1045 return pDomainConfiguration;
1046}
1047
1048const CDomainConfiguration* CConfigurableDomain::findConfiguration(const string& strConfiguration, string& strError) const
1049{
1050 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(findChild(strConfiguration));
1051
1052 if (!pDomainConfiguration) {
1053
1054 strError = "Domain configuration " + strConfiguration + " not found";
1055
1056 return NULL;
1057 }
1058 return pDomainConfiguration;
1059}