blob: 696bbd09351f88e729f1213a4d4f8a9d7cca0e92 [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 Benavoli63499d42011-10-24 18:50:03 +020076// Sequence awareness
77void CConfigurableDomain::setSequenceAwareness(bool bSequenceAware)
78{
79 if (_bSequenceAware != bSequenceAware) {
80
81 log("Making domain \"%s\" sequence %s", getName().c_str(), bSequenceAware ? "aware" : "unaware");
82
83 _bSequenceAware = bSequenceAware;
84 }
85}
86
87bool CConfigurableDomain::getSequenceAwareness() const
88{
89 return _bSequenceAware;
90}
91
Patrick Benavoli68a91282011-08-31 11:23:23 +020092// From IXmlSource
93void CConfigurableDomain::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
94{
Patrick Benavoli63499d42011-10-24 18:50:03 +020095 // Sequence awareness
96 xmlElement.setAttributeBoolean("SequenceAware", _bSequenceAware);
97
Patrick Benavoli68a91282011-08-31 11:23:23 +020098 // Configurations
99 composeDomainConfigurations(xmlElement, serializingContext);
100
101 // Configurable Elements
Patrick Benavoli63499d42011-10-24 18:50:03 +0200102 composeConfigurableElements(xmlElement);
103
104 // Settings
105 composeSettings(xmlElement, serializingContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200106}
107
108// XML composing
109void CConfigurableDomain::composeDomainConfigurations(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
110{
111 // Create Configurations element
112 CXmlElement xmlConfigurationsElement;
113
114 xmlElement.createChild(xmlConfigurationsElement, "Configurations");
115
116 // Delegate to base
117 base::toXml(xmlConfigurationsElement, serializingContext);
118}
119
Patrick Benavoli63499d42011-10-24 18:50:03 +0200120void CConfigurableDomain::composeConfigurableElements(CXmlElement& xmlElement) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200121{
Patrick Benavoli68a91282011-08-31 11:23:23 +0200122 // Create ConfigurableElements element
123 CXmlElement xmlConfigurableElementsElement;
124
125 xmlElement.createChild(xmlConfigurableElementsElement, "ConfigurableElements");
126
127 // Serialize out all configurable elements settings
128 ConfigurableElementListIterator it;
129
130 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
131
132 const CConfigurableElement* pConfigurableElement = *it;
133
134 // Create corresponding XML child element
135 CXmlElement xmlChildConfigurableElement;
136
137 xmlConfigurableElementsElement.createChild(xmlChildConfigurableElement, "ConfigurableElement");
138
139 // Set Path attribute
140 xmlChildConfigurableElement.setAttributeString("Path", pConfigurableElement->getPath());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200141 }
142}
143
Patrick Benavoli63499d42011-10-24 18:50:03 +0200144void CConfigurableDomain::composeSettings(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200145{
Patrick Benavoli63499d42011-10-24 18:50:03 +0200146 // Context
147 const CXmlDomainSerializingContext& xmlDomainSerializingContext = static_cast<const CXmlDomainSerializingContext&>(serializingContext);
148
149 if (!xmlDomainSerializingContext.withSettings()) {
150
151 return;
152 }
153
154 // Create Settings element
155 CXmlElement xmlSettingsElement;
156
157 xmlElement.createChild(xmlSettingsElement, "Settings");
158
159 // Serialize out all configurations settings
Patrick Benavoli68a91282011-08-31 11:23:23 +0200160 uint32_t uiNbConfigurations = getNbChildren();
161 uint32_t uiChildConfiguration;
162
163 for (uiChildConfiguration = 0; uiChildConfiguration < uiNbConfigurations; uiChildConfiguration++) {
164
165 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChildConfiguration));
166
167 // Create child xml element for that configuration
168 CXmlElement xmlConfigurationSettingsElement;
169
Patrick Benavoli63499d42011-10-24 18:50:03 +0200170 xmlSettingsElement.createChild(xmlConfigurationSettingsElement, pDomainConfiguration->getKind());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200171
172 // Set its name attribute
173 xmlConfigurationSettingsElement.setNameAttribute(pDomainConfiguration->getName());
174
Patrick Benavoli63499d42011-10-24 18:50:03 +0200175 // Serialize out configuration settings
176 pDomainConfiguration->composeSettings(xmlConfigurationSettingsElement, serializingContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200177 }
178}
179
180// From IXmlSink
181bool CConfigurableDomain::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
182{
Patrick Benavoli63499d42011-10-24 18:50:03 +0200183 // Context
184 CXmlDomainSerializingContext& xmlDomainSerializingContext = static_cast<CXmlDomainSerializingContext&>(serializingContext);
185
186 // Sequence awareness (optional)
187 _bSequenceAware = xmlElement.hasAttribute("SequenceAware") && xmlElement.getAttributeBoolean("SequenceAware");
188
Patrick Benavoli68a91282011-08-31 11:23:23 +0200189 // Local parsing. Do not dig
Patrick Benavoli63499d42011-10-24 18:50:03 +0200190 if (!parseDomainConfigurations(xmlElement, serializingContext) || !parseConfigurableElements(xmlElement, serializingContext) || !parseSettings(xmlElement, serializingContext)) {
191
192 return false;
193 }
194
195 // All provided configurations are parsed
196 // Attempt validation on areas of non provided configurations for all configurable elements if required
197 if (xmlDomainSerializingContext.autoValidationRequired()) {
198
199 autoValidateAll();
200 }
201
202 return true;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200203}
204
205// XML parsing
206bool CConfigurableDomain::parseDomainConfigurations(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
207{
208 // We're supposedly clean
209 assert(_configurableElementList.empty());
210
211 // Get Configurations element
212 CXmlElement xmlConfigurationsElement;
213
214 xmlElement.getChildElement("Configurations", xmlConfigurationsElement);
215
216 // Parse it and create domain configuration objects
217 return base::fromXml(xmlConfigurationsElement, serializingContext);
218}
219
220// Parse configurable elements
221bool CConfigurableDomain::parseConfigurableElements(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
222{
Patrick Benavoli68a91282011-08-31 11:23:23 +0200223 // Get System Class Element
224 CElement* pRootElement = getRoot();
225
226 CElement* pSystemClassElement = pRootElement->findChildOfKind("SystemClass");
227
228 assert(pSystemClassElement);
229
230 // Get ConfigurableElements element
231 CXmlElement xmlConfigurableElementsElement;
232 xmlElement.getChildElement("ConfigurableElements", xmlConfigurableElementsElement);
233
234 // Parse it and associate found configurable elements to it
235 CXmlElement::CChildIterator it(xmlConfigurableElementsElement);
236
237 CXmlElement xmlConfigurableElementElement;
238
239 while (it.next(xmlConfigurableElementElement)) {
240
241 // Locate configurable element
242 string strConfigurableElementPath = xmlConfigurableElementElement.getAttributeString("Path");
243
244 CPathNavigator pathNavigator(strConfigurableElementPath);
Patrick Benavoli065264a2011-11-20 15:46:41 +0100245 string strError;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200246
247 // Is there an element and does it match system class name?
Patrick Benavoli065264a2011-11-20 15:46:41 +0100248 if (!pathNavigator.navigateThrough(pSystemClassElement->getName(), strError)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200249
Patrick Benavoli065264a2011-11-20 15:46:41 +0100250 serializingContext.setError("Could not find configurable element of path " + strConfigurableElementPath + " from ConfigurableDomain description " + getName() + " (" + strError + ")");
Patrick Benavoli68a91282011-08-31 11:23:23 +0200251
252 return false;
253 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200254 // Browse system class for configurable element
255 CConfigurableElement* pConfigurableElement = static_cast<CConfigurableElement*>(pSystemClassElement->findDescendant(pathNavigator));
256
257 if (!pConfigurableElement) {
258
259 serializingContext.setError("Could not find configurable element of path " + strConfigurableElementPath + " from ConfigurableDomain description " + getName());
260
261 return false;
262 }
263 // Add found element to domain
Patrick Benavoli68a91282011-08-31 11:23:23 +0200264 if (!addConfigurableElement(pConfigurableElement, NULL, strError)) {
265
266 serializingContext.setError(strError);
267
268 return false;
269 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200270 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200271
272 return true;
273}
274
Patrick Benavoli63499d42011-10-24 18:50:03 +0200275// Parse settings
276bool CConfigurableDomain::parseSettings(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200277{
278 // Context
279 CXmlDomainSerializingContext& xmlDomainSerializingContext = static_cast<CXmlDomainSerializingContext&>(serializingContext);
280
Patrick Benavoli63499d42011-10-24 18:50:03 +0200281 // Check we actually need to parse configuration settings
282 if (!xmlDomainSerializingContext.withSettings()) {
283
284 // No parsing required
285 return true;
286 }
287
288 // Get Settings element
289 CXmlElement xmlSettingsElement;
290 if (!xmlElement.getChildElement("Settings", xmlSettingsElement)) {
291
292 // No settings, bail out successfully
293 return true;
294 }
295
296 // Parse configuration settings
297 CXmlElement::CChildIterator it(xmlSettingsElement);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200298
299 CXmlElement xmlConfigurationSettingsElement;
300
301 while (it.next(xmlConfigurationSettingsElement)) {
302 // Get domain configuration
303 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(xmlConfigurationSettingsElement.getNameAttribute()));
304
305 if (!pDomainConfiguration) {
306
Patrick Benavoli63499d42011-10-24 18:50:03 +0200307 xmlDomainSerializingContext.setError("Could not find domain configuration referred to by configurable domain " + getName());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200308
309 return false;
310 }
Patrick Benavoli63499d42011-10-24 18:50:03 +0200311 // Have domain configuration parse settings for all configurable elements
312 if (!pDomainConfiguration->parseSettings(xmlConfigurationSettingsElement, xmlDomainSerializingContext)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200313
314 return false;
315 }
316 }
317
318 return true;
319}
Patrick Benavoli68a91282011-08-31 11:23:23 +0200320// Configurable elements association
321bool CConfigurableDomain::addConfigurableElement(CConfigurableElement* pConfigurableElement, const CParameterBlackboard* pMainBlackboard, string& strError)
322{
323 // Already associated?
324 if (containsConfigurableElement(pConfigurableElement)) {
325
326 strError = "Configurable element " + pConfigurableElement->getPath() + " already associated to configuration domain " + getName();
327
328 return false;
329 }
330
331 // Already owned?
332 if (pConfigurableElement->belongsTo(this)) {
333
334 strError = "Configurable element " + pConfigurableElement->getPath() + " already owned by configuration domain " + getName();
335
336 return false;
337 }
338 log("Adding configurable element \"%s\" into domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str());
339
340 // Do add
341 doAddConfigurableElement(pConfigurableElement);
342
343 // Ensure area validity for that configurable element (if main blackboard provided)
344 if (pMainBlackboard) {
345
346 // Need to validate against main blackboard
347 validateAreas(pConfigurableElement, pMainBlackboard);
348 }
349
350 return true;
351}
352
353bool CConfigurableDomain::removeConfigurableElement(CConfigurableElement* pConfigurableElement, string& strError)
354{
355 // Not associated?
356 if (!containsConfigurableElement(pConfigurableElement)) {
357
358 strError = "Configurable element " + pConfigurableElement->getPath() + " not associated to configuration domain " + getName();
359
360 return false;
361 }
362 log("Removing configurable element \"%s\" from domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str());
363
364 // Do remove
365 doRemoveConfigurableElement(pConfigurableElement, true);
366
367 return true;
368}
369
370// Domain splitting
371bool CConfigurableDomain::split(CConfigurableElement* pConfigurableElement, string& strError)
372{
373 // Not associated?
374 if (!containsConfigurableElement(pConfigurableElement)) {
375
376 strError = "Configurable element " + pConfigurableElement->getPath() + " not associated to configuration domain " + getName();
377
378 return false;
379 }
380 log("Splitting configurable element \"%s\" domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str());
381
382 // Create sub domain areas for all configurable element's children
383 uint32_t uiNbConfigurableElementChildren = pConfigurableElement->getNbChildren();
384
385 if (!uiNbConfigurableElementChildren) {
386
387 strError = "Configurable element " + pConfigurableElement->getPath() + " has no children to split configurable domain to";
388
389 return false;
390 }
391
392 uint32_t uiChild;
393
394 for (uiChild = 0; uiChild < uiNbConfigurableElementChildren; uiChild++) {
395
396 CConfigurableElement* pChildConfigurableElement = static_cast<CConfigurableElement*>(pConfigurableElement->getChild(uiChild));
397
398 doAddConfigurableElement(pChildConfigurableElement);
399 }
400
401 // Delegate to configurations
402 uint32_t uiNbConfigurations = getNbChildren();
403
404 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
405
406 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
407
408 pDomainConfiguration->split(pConfigurableElement);
409 }
410
411 // Remove given configurable element from this domain
412 // 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
413 doRemoveConfigurableElement(pConfigurableElement, false);
414
415 return true;
416}
417
418// Configuration application if required
Patrick Benavoli63499d42011-10-24 18:50:03 +0200419bool CConfigurableDomain::apply(CParameterBlackboard* pParameterBlackboard, CSyncerSet& syncerSet, bool bForce, string& strError) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200420{
421 if (bForce) {
422 // Force a configuration restore by forgetting about last applied configuration
423 _pLastAppliedConfiguration = NULL;
424 }
425 const CDomainConfiguration* pApplicableDomainConfiguration = findApplicableDomainConfiguration();
426
427 if (pApplicableDomainConfiguration) {
428
429 // Check not the last one before applying
430 if (!_pLastAppliedConfiguration || _pLastAppliedConfiguration != pApplicableDomainConfiguration) {
431
432 log("Applying configuration \"%s\" from domain \"%s\"", pApplicableDomainConfiguration->getName().c_str(), getName().c_str());
433
434 // Do the restore
Patrick Benavoli63499d42011-10-24 18:50:03 +0200435 if (!pApplicableDomainConfiguration->restore(pParameterBlackboard, _bSequenceAware, strError)) {
436
437 return false;
438 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200439
440 // Record last applied configuration
441 _pLastAppliedConfiguration = pApplicableDomainConfiguration;
442
Patrick Benavoli63499d42011-10-24 18:50:03 +0200443 // Check we did not already sync the changes
444 if (!_bSequenceAware) {
445
446 // Since we applied changes, add our own sync set to the given one
447 syncerSet += _syncerSet;
448 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200449 }
450 }
Patrick Benavoli63499d42011-10-24 18:50:03 +0200451
452 return true;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200453}
454
455// Return applicable configuration validity for given configurable element
456bool CConfigurableDomain::isApplicableConfigurationValid(const CConfigurableElement* pConfigurableElement) const
457{
458 const CDomainConfiguration* pApplicableDomainConfiguration = findApplicableDomainConfiguration();
459
460 return pApplicableDomainConfiguration && pApplicableDomainConfiguration->isValid(pConfigurableElement);
461}
462
463// Presence of application condition on any configuration
464bool CConfigurableDomain::hasRules() const
465{
466 // Delegate to configurations
467 uint32_t uiNbConfigurations = getNbChildren();
468 uint32_t uiChild;
469
470 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
471
472 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
473
474 if (pDomainConfiguration->hasRule()) {
475
476 return true;
477 }
478 }
479 return false;
480}
481
482// In case configurable element was removed
483void CConfigurableDomain::computeSyncSet()
484{
485 // Clean sync set first
Patrick Benavoli63499d42011-10-24 18:50:03 +0200486 _syncerSet.clear();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200487
Patrick Benavoli63499d42011-10-24 18:50:03 +0200488 // Add syncer sets for all associated configurable elements
489 ConfigurableElementToSyncerSetMapIterator mapIt;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200490
Patrick Benavoli63499d42011-10-24 18:50:03 +0200491 for (mapIt = _configurableElementToSyncerSetMap.begin(); mapIt != _configurableElementToSyncerSetMap.end(); ++mapIt) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200492
Patrick Benavoli63499d42011-10-24 18:50:03 +0200493 const CSyncerSet* pSyncerSet = mapIt->second;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200494
Patrick Benavoli63499d42011-10-24 18:50:03 +0200495 _syncerSet += *pSyncerSet;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200496 }
497}
498
499// Configuration Management
500bool CConfigurableDomain::createConfiguration(const string& strName, const CParameterBlackboard* pMainBlackboard, string& strError)
501{
502 // Already exists?
503 if (findChild(strName)) {
504
505 strError = "Already existing configuration";
506
507 return false;
508 }
509 log("Creating domain configuration \"%s\" into domain \"%s\"", strName.c_str(), getName().c_str());
510
511 // Creation
512 CDomainConfiguration* pDomainConfiguration = new CDomainConfiguration(strName);
513
514 // Configurable elements association
515 ConfigurableElementListIterator it;
516
517 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
518
Patrick Benavoli63499d42011-10-24 18:50:03 +0200519 const CConfigurableElement* pConfigurableElement = *it;;
520
521 // Retrieve associated syncer set
522 CSyncerSet* pSyncerSet = getSyncerSet(pConfigurableElement);
523
524 // Associate to configuration
525 pDomainConfiguration->addConfigurableElement(pConfigurableElement, pSyncerSet);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200526 }
527
528 // Hierarchy
529 addChild(pDomainConfiguration);
530
531 // Ensure validity of fresh new domain configuration
532 // Attempt auto validation, so that the user gets his/her own settings by defaults
533 if (!autoValidateConfiguration(pDomainConfiguration)) {
534
535 // No valid configuration found to copy in from, validate againt main blackboard (will concerned remaining invalid parts)
536 pDomainConfiguration->validate(pMainBlackboard);
537 }
538
539 return true;
540}
541
542bool CConfigurableDomain::deleteConfiguration(const string& strName, string& strError)
543{
544 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(strName));
545
546 if (!pDomainConfiguration) {
547
548 strError = "Configuration not found";
549
550 return false;
551 }
552
553 // Check configuration has no rule (prevent accidental loss of data)
554 if (pDomainConfiguration->hasRule()) {
555
556 strError = "Deletion of configuration containing application rules is not supported to prevent any accitental loss of data.\nPlease consider a direct modification of the XML file.";
557
558 return false;
559 }
560
561 log("Deleting configuration \"%s\" from domain \"%s\"", strName.c_str(), getName().c_str());
562
563 // Was the last applied?
564 if (pDomainConfiguration == _pLastAppliedConfiguration) {
565
566 // Forget about it
567 _pLastAppliedConfiguration = NULL;
568 }
569
570 // Hierarchy
571 removeChild(pDomainConfiguration);
572
573 // Destroy
574 delete pDomainConfiguration;
575
576 return true;
577}
578
579void CConfigurableDomain::listAssociatedToElements(string& strResult) const
580{
581 strResult = "\n";
582
583 ConfigurableElementListIterator it;
584
585 // Browse all configurable elements
586 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
587
588 const CConfigurableElement* pConfigurableElement = *it;
589
590 strResult += pConfigurableElement->getPath() + "\n";
591 }
592}
593
594bool CConfigurableDomain::renameConfiguration(const string& strName, const string& strNewName, string& strError)
595{
596 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(strName));
597
598 if (!pDomainConfiguration) {
599
600 strError = "Configuration not found";
601
602 return false;
603 }
604 log("Renaming domain \"%s\"'s configuration \"%s\" to \"%s\"", getName().c_str(), strName.c_str(), strNewName.c_str());
605
606 // Rename
607 return pDomainConfiguration->rename(strNewName, strError);
608}
609
610bool CConfigurableDomain::restoreConfiguration(const string& strName, CParameterBlackboard* pMainBlackboard, bool bAutoSync, string& strError)
611{
612 // Find Domain configuration
613 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(findChild(strName));
614
615 if (!pDomainConfiguration) {
616
617 strError = "Domain configuration " + strName + " not found";
618
619 return false;
620 }
621 log("Restoring domain \"%s\"'s configuration \"%s\" to parameter blackboard", getName().c_str(), pDomainConfiguration->getName().c_str());
622
623 // Delegate
Patrick Benavoli63499d42011-10-24 18:50:03 +0200624 if (!pDomainConfiguration->restore(pMainBlackboard, _bSequenceAware && bAutoSync, strError)) {
625
626 return false;
627 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200628
629 // Record last applied configuration
630 _pLastAppliedConfiguration = pDomainConfiguration;
631
632 // Synchronize
633 return !bAutoSync || _syncerSet.sync(*pMainBlackboard, false, strError);
634}
635
636bool CConfigurableDomain::saveConfiguration(const string& strName, const CParameterBlackboard* pMainBlackboard, string& strError)
637{
638 // Find Domain configuration
639 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(strName));
640
641 if (!pDomainConfiguration) {
642
643 strError = "Domain configuration " + strName + " not found";
644
645 return false;
646 }
647 log("Saving domain \"%s\"'s configuration \"%s\" from parameter blackboard", getName().c_str(), pDomainConfiguration->getName().c_str());
648
649 // Delegate
650 pDomainConfiguration->save(pMainBlackboard);
651
652 return true;
653}
654
Patrick Benavoli63499d42011-10-24 18:50:03 +0200655bool CConfigurableDomain::setElementSequence(const string& strName, const vector<string>& astrNewElementSequence, string& strError)
656{
657 // Find Domain configuration
658 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(strName));
659
660 if (!pDomainConfiguration) {
661
662 strError = "Domain configuration " + strName + " not found";
663
664 return false;
665 }
666
667 // Delegate to configuration
668 return pDomainConfiguration->setElementSequence(astrNewElementSequence, strError);
669}
670
671bool CConfigurableDomain::getElementSequence(const string& strName, string& strResult) const
672{
673 // Find Domain configuration
674 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(findChild(strName));
675
676 if (!pDomainConfiguration) {
677
678 strResult = "Domain configuration " + strName + " not found";
679
680 return false;
681 }
682
683 // Delegate to configuration
684 pDomainConfiguration->getElementSequence(strResult);
685
686 return true;
687}
688
Patrick Benavoli68a91282011-08-31 11:23:23 +0200689// Last applied configuration
690string CConfigurableDomain::getLastAppliedConfigurationName() const
691{
692 if (_pLastAppliedConfiguration) {
693
694 return _pLastAppliedConfiguration->getName();
695 }
696 return "<none>";
697}
698
699// Ensure validity on whole domain from main blackboard
700void CConfigurableDomain::validate(const CParameterBlackboard* pMainBlackboard)
701{
702 log("Validating whole domain \"" + getName() + "\" against main blackboard");
703
704 // Propagate
705 uint32_t uiNbConfigurations = getNbChildren();
706 uint32_t uiChild;
707
708 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
709
710 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
711
712 pDomainConfiguration->validate(pMainBlackboard);
713 }
714}
715
716// Ensure validity on areas related to configurable element
717void CConfigurableDomain::validateAreas(const CConfigurableElement* pConfigurableElement, const CParameterBlackboard* pMainBlackboard)
718{
719 log("Validating domain \"" + getName() + "\" against main blackboard for configurable element \"" + pConfigurableElement->getPath() + "\"");
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(pConfigurableElement, pMainBlackboard);
730 }
731}
732
733// Attempt validation for all configurable element's areas, relying on already existing valid configuration inside domain
734void CConfigurableDomain::autoValidateAll()
735{
736 // Validate
737 ConfigurableElementListIterator it;
738
739 // Browse all configurable elements for configuration validation
740 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
741
742 const CConfigurableElement* pConfigurableElement = *it;
743
744 // Auto validate element
745 autoValidateAreas(pConfigurableElement);
746 }
747}
748
749// Attempt validation for configurable element's areas, relying on already existing valid configuration inside domain
750void CConfigurableDomain::autoValidateAreas(const CConfigurableElement* pConfigurableElement)
751{
752 // Find first valid configuration for given configurable element
753 const CDomainConfiguration* pValidDomainConfiguration = findValidDomainConfiguration(pConfigurableElement);
754
755 // No valid configuration found, give up
756 if (!pValidDomainConfiguration) {
757
758 return;
759 }
760
761 log("Auto validating domain \"" + getName() + "\" against configuration \"" + pValidDomainConfiguration->getName() + "\" for configurable element " + pConfigurableElement->getPath());
762
763 // Validate all other configurations against found one, if any
764 uint32_t uiNbConfigurations = getNbChildren();
765 uint32_t uiChild;
766
767 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
768
769 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
770
771 if (pDomainConfiguration != pValidDomainConfiguration && !pDomainConfiguration->isValid(pConfigurableElement)) {
772 // Validate
773 pDomainConfiguration->validateAgainst(pValidDomainConfiguration, pConfigurableElement);
774 }
775 }
776}
777
778// Attempt configuration validation for all configurable elements' areas, relying on already existing valid configuration inside domain
779bool CConfigurableDomain::autoValidateConfiguration(CDomainConfiguration* pDomainConfiguration)
780{
781 // Find another configuration than this one, that ought to be valid!
782 uint32_t uiNbConfigurations = getNbChildren();
783 uint32_t uiChild;
784
785 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
786
787 const CDomainConfiguration* pPotententialValidDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
788
789 if (pPotententialValidDomainConfiguration != pDomainConfiguration) {
790
791 // Validate against it
792 pDomainConfiguration->validateAgainst(pPotententialValidDomainConfiguration);
793
794 return true;
795 }
796 }
797 return false;
798}
Patrick Benavoli68a91282011-08-31 11:23:23 +0200799
Patrick Benavoli68a91282011-08-31 11:23:23 +0200800// Search for a valid configuration for given configurable element
801const CDomainConfiguration* CConfigurableDomain::findValidDomainConfiguration(const CConfigurableElement* pConfigurableElement) const
802{
803 uint32_t uiNbConfigurations = getNbChildren();
804 uint32_t uiChild;
805
806 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
807
808 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
809
810 if (pDomainConfiguration->isValid(pConfigurableElement)) {
811
812 return pDomainConfiguration;
813 }
814 }
815 return NULL;
816}
817
818// Search for an applicable configuration
819const CDomainConfiguration* CConfigurableDomain::findApplicableDomainConfiguration() const
820{
821 uint32_t uiNbConfigurations = getNbChildren();
822 uint32_t uiChild;
823
824 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
825
826 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
827
828 if (pDomainConfiguration->isApplicable()) {
829
830 return pDomainConfiguration;
831 }
832 }
833 return NULL;
834}
835
836// Gather set of configurable elements
837void CConfigurableDomain::gatherConfigurableElements(set<const CConfigurableElement*>& configurableElementSet) const
838{
839 // Insert all configurable elements
840 configurableElementSet.insert(_configurableElementList.begin(), _configurableElementList.end());
841}
842
843// Check configurable element already attached
844bool CConfigurableDomain::containsConfigurableElement(const CConfigurableElement* pConfigurableCandidateElement) const
845{
846 ConfigurableElementListIterator it;
847
848 // Browse all configurable elements for comparison
849 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
850
851 if (pConfigurableCandidateElement == *it) {
852
853 return true;
854 }
855 }
856 return false;
857}
858
859// Merge any descended configurable element to this one with this one
860void CConfigurableDomain::mergeAlreadyAssociatedDescendantConfigurableElements(CConfigurableElement* pNewConfigurableElement)
861{
862 list<CConfigurableElement*> mergedConfigurableElementList;
863
864 ConfigurableElementListIterator it;
865
866 // Browse all configurable elements (new one not yet in the list!)
867 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
868
869 CConfigurableElement* pConfigurablePotentialDescendantElement = *it;
870
871 if (pConfigurablePotentialDescendantElement->isDescendantOf(pNewConfigurableElement)) {
872
873 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());
874
875 // Merge configuration data
876 mergeConfigurations(pNewConfigurableElement, pConfigurablePotentialDescendantElement);
877
878 // Keep track for removal
879 mergedConfigurableElementList.push_back(pConfigurablePotentialDescendantElement);
880 }
881 }
882
883 // Remove all merged elements (new one not yet in the list!)
884 for (it = mergedConfigurableElementList.begin(); it != mergedConfigurableElementList.end(); ++it) {
885
886 CConfigurableElement* pMergedConfigurableElement = *it;
887
888 // Remove merged from configurable element from internal tracking list
889 // 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
890 doRemoveConfigurableElement(pMergedConfigurableElement, false);
891 }
892}
893
894void CConfigurableDomain::mergeConfigurations(CConfigurableElement* pToConfigurableElement, CConfigurableElement* pFromConfigurableElement)
895{
896 // Propagate to domain configurations
897 uint32_t uiNbConfigurations = getNbChildren();
898 uint32_t uiChild;
899
900 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
901
902 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
903
904 // Do the merge.
905 pDomainConfiguration->merge(pToConfigurableElement, pFromConfigurableElement);
906 }
907}
908
909// Configurable elements association
910void CConfigurableDomain::doAddConfigurableElement(CConfigurableElement* pConfigurableElement)
911{
912 // Inform configurable element
913 pConfigurableElement->addAttachedConfigurableDomain(this);
914
Patrick Benavoli63499d42011-10-24 18:50:03 +0200915 // Create associated syncer set
916 CSyncerSet* pSyncerSet = new CSyncerSet;
917
918 // Add to sync set the configurable element one
919 pConfigurableElement->fillSyncerSet(*pSyncerSet);
920
921 // Store it
922 _configurableElementToSyncerSetMap[pConfigurableElement] = pSyncerSet;
923
924 // Add it to global one
925 _syncerSet += *pSyncerSet;
926
Patrick Benavoli68a91282011-08-31 11:23:23 +0200927 // Inform configurations
928 uint32_t uiNbConfigurations = getNbChildren();
929 uint32_t uiChild;
930
931 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
932
933 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
934
Patrick Benavoli63499d42011-10-24 18:50:03 +0200935 pDomainConfiguration->addConfigurableElement(pConfigurableElement, pSyncerSet);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200936 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200937
938 // Already associated descended configurable elements need a merge of their configuration data
939 mergeAlreadyAssociatedDescendantConfigurableElements(pConfigurableElement);
940
941 // Add to list
942 _configurableElementList.push_back(pConfigurableElement);
943}
944
945void CConfigurableDomain::doRemoveConfigurableElement(CConfigurableElement* pConfigurableElement, bool bRecomputeSyncSet)
946{
947 // Remove from list
948 _configurableElementList.remove(pConfigurableElement);
949
Patrick Benavoli63499d42011-10-24 18:50:03 +0200950 // Remove associated syncer set
951 CSyncerSet* pSyncerSet = getSyncerSet(pConfigurableElement);
952
953 _configurableElementToSyncerSetMap.erase(pConfigurableElement);
954
955 delete pSyncerSet;
956
Patrick Benavoli68a91282011-08-31 11:23:23 +0200957 // Inform configurable element
958 pConfigurableElement->removeAttachedConfigurableDomain(this);
959
960 // Inform configurations
961 uint32_t uiNbConfigurations = getNbChildren();
962 uint32_t uiChild;
963
964 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
965
966 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
967
968 pDomainConfiguration->removeConfigurableElement(pConfigurableElement);
969 }
970 // Recompute our sync set if needed
971 if (bRecomputeSyncSet) {
972
973 computeSyncSet();
974 }
975}
Patrick Benavoli63499d42011-10-24 18:50:03 +0200976
977// Syncer set retrieval from configurable element
978CSyncerSet* CConfigurableDomain::getSyncerSet(const CConfigurableElement* pConfigurableElement) const
979{
980 ConfigurableElementToSyncerSetMapIterator mapIt = _configurableElementToSyncerSetMap.find(pConfigurableElement);
981
982 assert(mapIt != _configurableElementToSyncerSetMap.end());
983
984 return mapIt->second;
985}