blob: 7d713a1014fedb6880b6dcee0e33b1d59055417a [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
Kevin Rocardace81f82012-12-11 16:19:17 +010093 log_info("Making domain \"%s\" sequence %s", getName().c_str(), bSequenceAware ? "aware" : "unaware");
Patrick Benavoli63499d42011-10-24 18:50:03 +020094
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 }
Kevin Rocardace81f82012-12-11 16:19:17 +0100350 log_info("Adding configurable element \"%s\" into domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200351
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 }
Kevin Rocardace81f82012-12-11 16:19:17 +0100367 log_info("Removing configurable element \"%s\" from domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200368
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 }
Kevin Rocardace81f82012-12-11 16:19:17 +0100385 log_info("Splitting configurable element \"%s\" domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200386
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
Kevin Rocardace81f82012-12-11 16:19:17 +0100441void CConfigurableDomain::apply(CParameterBlackboard* pParameterBlackboard, CSyncerSet& syncerSet, bool bForce) 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
Kevin Rocardace81f82012-12-11 16:19:17 +0100454 log_info("Applying configuration \"%s\" from domain \"%s\"", pApplicableDomainConfiguration->getName().c_str(), getName().c_str());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200455
456 // Do the restore
Kevin Rocardace81f82012-12-11 16:19:17 +0100457 pApplicableDomainConfiguration->restore(pParameterBlackboard, _bSequenceAware, NULL);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200458
459 // Record last applied configuration
460 _pLastAppliedConfiguration = pApplicableDomainConfiguration;
461
Patrick Benavoli63499d42011-10-24 18:50:03 +0200462 // Check we did not already sync the changes
463 if (!_bSequenceAware) {
464
465 // Since we applied changes, add our own sync set to the given one
466 syncerSet += _syncerSet;
467 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200468 }
469 }
470}
471
472// Return applicable configuration validity for given configurable element
473bool CConfigurableDomain::isApplicableConfigurationValid(const CConfigurableElement* pConfigurableElement) const
474{
475 const CDomainConfiguration* pApplicableDomainConfiguration = findApplicableDomainConfiguration();
476
477 return pApplicableDomainConfiguration && pApplicableDomainConfiguration->isValid(pConfigurableElement);
478}
479
Patrick Benavoli68a91282011-08-31 11:23:23 +0200480// In case configurable element was removed
481void CConfigurableDomain::computeSyncSet()
482{
483 // Clean sync set first
Patrick Benavoli63499d42011-10-24 18:50:03 +0200484 _syncerSet.clear();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200485
Patrick Benavoli63499d42011-10-24 18:50:03 +0200486 // Add syncer sets for all associated configurable elements
487 ConfigurableElementToSyncerSetMapIterator mapIt;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200488
Patrick Benavoli63499d42011-10-24 18:50:03 +0200489 for (mapIt = _configurableElementToSyncerSetMap.begin(); mapIt != _configurableElementToSyncerSetMap.end(); ++mapIt) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200490
Patrick Benavoli63499d42011-10-24 18:50:03 +0200491 const CSyncerSet* pSyncerSet = mapIt->second;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200492
Patrick Benavoli63499d42011-10-24 18:50:03 +0200493 _syncerSet += *pSyncerSet;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200494 }
495}
496
497// Configuration Management
498bool CConfigurableDomain::createConfiguration(const string& strName, const CParameterBlackboard* pMainBlackboard, string& strError)
499{
500 // Already exists?
501 if (findChild(strName)) {
502
503 strError = "Already existing configuration";
504
505 return false;
506 }
Kevin Rocardace81f82012-12-11 16:19:17 +0100507 log_info("Creating domain configuration \"%s\" into domain \"%s\"", strName.c_str(), getName().c_str());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200508
509 // Creation
510 CDomainConfiguration* pDomainConfiguration = new CDomainConfiguration(strName);
511
512 // Configurable elements association
513 ConfigurableElementListIterator it;
514
515 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
516
Patrick Benavoli63499d42011-10-24 18:50:03 +0200517 const CConfigurableElement* pConfigurableElement = *it;;
518
519 // Retrieve associated syncer set
520 CSyncerSet* pSyncerSet = getSyncerSet(pConfigurableElement);
521
522 // Associate to configuration
523 pDomainConfiguration->addConfigurableElement(pConfigurableElement, pSyncerSet);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200524 }
525
526 // Hierarchy
527 addChild(pDomainConfiguration);
528
529 // Ensure validity of fresh new domain configuration
530 // Attempt auto validation, so that the user gets his/her own settings by defaults
531 if (!autoValidateConfiguration(pDomainConfiguration)) {
532
533 // No valid configuration found to copy in from, validate againt main blackboard (will concerned remaining invalid parts)
534 pDomainConfiguration->validate(pMainBlackboard);
535 }
536
537 return true;
538}
539
540bool CConfigurableDomain::deleteConfiguration(const string& strName, string& strError)
541{
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100542 CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200543
544 if (!pDomainConfiguration) {
545
Patrick Benavoli68a91282011-08-31 11:23:23 +0200546 return false;
547 }
548
Kevin Rocardace81f82012-12-11 16:19:17 +0100549 log_info("Deleting configuration \"%s\" from domain \"%s\"", strName.c_str(), getName().c_str());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200550
551 // Was the last applied?
552 if (pDomainConfiguration == _pLastAppliedConfiguration) {
553
554 // Forget about it
555 _pLastAppliedConfiguration = NULL;
556 }
557
558 // Hierarchy
559 removeChild(pDomainConfiguration);
560
561 // Destroy
562 delete pDomainConfiguration;
563
564 return true;
565}
566
567void CConfigurableDomain::listAssociatedToElements(string& strResult) const
568{
569 strResult = "\n";
570
571 ConfigurableElementListIterator it;
572
573 // Browse all configurable elements
574 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
575
576 const CConfigurableElement* pConfigurableElement = *it;
577
578 strResult += pConfigurableElement->getPath() + "\n";
579 }
580}
581
582bool CConfigurableDomain::renameConfiguration(const string& strName, const string& strNewName, string& strError)
583{
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100584 CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200585
586 if (!pDomainConfiguration) {
587
Patrick Benavoli68a91282011-08-31 11:23:23 +0200588 return false;
589 }
Kevin Rocardace81f82012-12-11 16:19:17 +0100590 log_info("Renaming domain \"%s\"'s configuration \"%s\" to \"%s\"", getName().c_str(), strName.c_str(), strNewName.c_str());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200591
592 // Rename
593 return pDomainConfiguration->rename(strNewName, strError);
594}
595
Kevin Rocardace81f82012-12-11 16:19:17 +0100596bool CConfigurableDomain::restoreConfiguration(const string& strName, CParameterBlackboard* pMainBlackboard, bool bAutoSync, list<string>& lstrError) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200597{
Kevin Rocardace81f82012-12-11 16:19:17 +0100598 string strError;
599
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100600 const CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200601
602 if (!pDomainConfiguration) {
603
Kevin Rocardace81f82012-12-11 16:19:17 +0100604 lstrError.push_back(strError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200605 return false;
606 }
Kevin Rocardace81f82012-12-11 16:19:17 +0100607 log_info("Restoring domain \"%s\"'s configuration \"%s\" to parameter blackboard", getName().c_str(), pDomainConfiguration->getName().c_str());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200608
609 // Delegate
Kevin Rocardace81f82012-12-11 16:19:17 +0100610 bool bSuccess = pDomainConfiguration->restore(pMainBlackboard, bAutoSync && _bSequenceAware, &lstrError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200611
612 // Record last applied configuration
613 _pLastAppliedConfiguration = pDomainConfiguration;
614
615 // Synchronize
Kevin Rocardace81f82012-12-11 16:19:17 +0100616 if (bAutoSync && !_bSequenceAware) {
617
618 bSuccess &= _syncerSet.sync(*pMainBlackboard, false, &lstrError);
619 }
620 return bSuccess;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200621}
622
623bool CConfigurableDomain::saveConfiguration(const string& strName, const CParameterBlackboard* pMainBlackboard, string& strError)
624{
625 // Find Domain configuration
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100626 CDomainConfiguration* pDomainConfiguration = findConfiguration(strName, strError);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200627
628 if (!pDomainConfiguration) {
629
Patrick Benavoli68a91282011-08-31 11:23:23 +0200630 return false;
631 }
Kevin Rocardace81f82012-12-11 16:19:17 +0100632 log_info("Saving domain \"%s\"'s configuration \"%s\" from parameter blackboard", getName().c_str(), pDomainConfiguration->getName().c_str());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200633
634 // Delegate
635 pDomainConfiguration->save(pMainBlackboard);
636
637 return true;
638}
639
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100640bool CConfigurableDomain::setElementSequence(const string& strConfiguration, const vector<string>& astrNewElementSequence, string& strError)
Patrick Benavoli63499d42011-10-24 18:50:03 +0200641{
642 // Find Domain configuration
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100643 CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strError);
Patrick Benavoli63499d42011-10-24 18:50:03 +0200644
645 if (!pDomainConfiguration) {
646
Patrick Benavoli63499d42011-10-24 18:50:03 +0200647 return false;
648 }
649
650 // Delegate to configuration
651 return pDomainConfiguration->setElementSequence(astrNewElementSequence, strError);
652}
653
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100654bool CConfigurableDomain::getElementSequence(const string& strConfiguration, string& strResult) const
Patrick Benavoli63499d42011-10-24 18:50:03 +0200655{
656 // Find Domain configuration
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100657 const CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strResult);
Patrick Benavoli63499d42011-10-24 18:50:03 +0200658
659 if (!pDomainConfiguration) {
660
Patrick Benavoli63499d42011-10-24 18:50:03 +0200661 return false;
662 }
663
664 // Delegate to configuration
665 pDomainConfiguration->getElementSequence(strResult);
666
667 return true;
668}
669
Patrick Benavoli0bd50542011-11-29 11:10:27 +0100670bool CConfigurableDomain::setApplicationRule(const string& strConfiguration, const string& strApplicationRule, const CSelectionCriteriaDefinition* pSelectionCriteriaDefinition, string& strError)
671{
672 // Find Domain configuration
673 CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strError);
674
675 if (!pDomainConfiguration) {
676
677 return false;
678 }
679
680 // Delegate to configuration
681 return pDomainConfiguration->setApplicationRule(strApplicationRule, pSelectionCriteriaDefinition, strError);
682}
683
684bool CConfigurableDomain::clearApplicationRule(const string& strConfiguration, string& strError)
685{
686 // Find Domain configuration
687 CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strError);
688
689 if (!pDomainConfiguration) {
690
691 return false;
692 }
693
694 // Delegate to configuration
695 pDomainConfiguration->clearApplicationRule();
696
697 return true;
698}
699
700bool CConfigurableDomain::getApplicationRule(const string& strConfiguration, string& strResult) const
701{
702 // Find Domain configuration
703 const CDomainConfiguration* pDomainConfiguration = findConfiguration(strConfiguration, strResult);
704
705 if (!pDomainConfiguration) {
706
707 return false;
708 }
709
710 // Delegate to configuration
711 pDomainConfiguration->getApplicationRule(strResult);
712
713 return true;
714}
715
Patrick Benavoli68a91282011-08-31 11:23:23 +0200716// Last applied configuration
717string CConfigurableDomain::getLastAppliedConfigurationName() const
718{
719 if (_pLastAppliedConfiguration) {
720
721 return _pLastAppliedConfiguration->getName();
722 }
723 return "<none>";
724}
725
Frédéric Boisnard8b243f52012-09-06 18:03:20 +0200726// Pending configuration
727string CConfigurableDomain::getPendingConfigurationName() const
728{
729 const CDomainConfiguration* pPendingConfiguration = getPendingConfiguration();
730
731 if (pPendingConfiguration) {
732
733 return pPendingConfiguration->getName();
734 }
735 return "<none>";
736}
737
Patrick Benavoli68a91282011-08-31 11:23:23 +0200738// Ensure validity on whole domain from main blackboard
739void CConfigurableDomain::validate(const CParameterBlackboard* pMainBlackboard)
740{
Kevin Rocardace81f82012-12-11 16:19:17 +0100741 log_info("Validating whole domain \"" + getName() + "\" against main blackboard");
Patrick Benavoli68a91282011-08-31 11:23:23 +0200742
743 // Propagate
744 uint32_t uiNbConfigurations = getNbChildren();
745 uint32_t uiChild;
746
747 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
748
749 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
750
751 pDomainConfiguration->validate(pMainBlackboard);
752 }
753}
754
755// Ensure validity on areas related to configurable element
756void CConfigurableDomain::validateAreas(const CConfigurableElement* pConfigurableElement, const CParameterBlackboard* pMainBlackboard)
757{
Kevin Rocardace81f82012-12-11 16:19:17 +0100758 log_info("Validating domain \"" + getName() + "\" against main blackboard for configurable element \"" + pConfigurableElement->getPath() + "\"");
Patrick Benavoli68a91282011-08-31 11:23:23 +0200759
760 // Propagate
761 uint32_t uiNbConfigurations = getNbChildren();
762 uint32_t uiChild;
763
764 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
765
766 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
767
768 pDomainConfiguration->validate(pConfigurableElement, pMainBlackboard);
769 }
770}
771
772// Attempt validation for all configurable element's areas, relying on already existing valid configuration inside domain
773void CConfigurableDomain::autoValidateAll()
774{
775 // Validate
776 ConfigurableElementListIterator it;
777
778 // Browse all configurable elements for configuration validation
779 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
780
781 const CConfigurableElement* pConfigurableElement = *it;
782
783 // Auto validate element
784 autoValidateAreas(pConfigurableElement);
785 }
786}
787
788// Attempt validation for configurable element's areas, relying on already existing valid configuration inside domain
789void CConfigurableDomain::autoValidateAreas(const CConfigurableElement* pConfigurableElement)
790{
791 // Find first valid configuration for given configurable element
792 const CDomainConfiguration* pValidDomainConfiguration = findValidDomainConfiguration(pConfigurableElement);
793
794 // No valid configuration found, give up
795 if (!pValidDomainConfiguration) {
796
797 return;
798 }
799
Kevin Rocardace81f82012-12-11 16:19:17 +0100800 log_info("Auto validating domain \"" + getName() + "\" against configuration \"" + pValidDomainConfiguration->getName() + "\" for configurable element " + pConfigurableElement->getPath());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200801
802 // Validate all other configurations against found one, if any
803 uint32_t uiNbConfigurations = getNbChildren();
804 uint32_t uiChild;
805
806 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
807
808 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
809
810 if (pDomainConfiguration != pValidDomainConfiguration && !pDomainConfiguration->isValid(pConfigurableElement)) {
811 // Validate
812 pDomainConfiguration->validateAgainst(pValidDomainConfiguration, pConfigurableElement);
813 }
814 }
815}
816
817// Attempt configuration validation for all configurable elements' areas, relying on already existing valid configuration inside domain
818bool CConfigurableDomain::autoValidateConfiguration(CDomainConfiguration* pDomainConfiguration)
819{
820 // Find another configuration than this one, that ought to be valid!
821 uint32_t uiNbConfigurations = getNbChildren();
822 uint32_t uiChild;
823
824 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
825
826 const CDomainConfiguration* pPotententialValidDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
827
828 if (pPotententialValidDomainConfiguration != pDomainConfiguration) {
829
830 // Validate against it
831 pDomainConfiguration->validateAgainst(pPotententialValidDomainConfiguration);
832
833 return true;
834 }
835 }
836 return false;
837}
Patrick Benavoli68a91282011-08-31 11:23:23 +0200838
Patrick Benavoli68a91282011-08-31 11:23:23 +0200839// Search for a valid configuration for given configurable element
840const CDomainConfiguration* CConfigurableDomain::findValidDomainConfiguration(const CConfigurableElement* pConfigurableElement) const
841{
842 uint32_t uiNbConfigurations = getNbChildren();
843 uint32_t uiChild;
844
845 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
846
847 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
848
849 if (pDomainConfiguration->isValid(pConfigurableElement)) {
850
851 return pDomainConfiguration;
852 }
853 }
854 return NULL;
855}
856
857// Search for an applicable configuration
858const CDomainConfiguration* CConfigurableDomain::findApplicableDomainConfiguration() const
859{
860 uint32_t uiNbConfigurations = getNbChildren();
861 uint32_t uiChild;
862
863 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
864
865 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
866
867 if (pDomainConfiguration->isApplicable()) {
868
869 return pDomainConfiguration;
870 }
871 }
872 return NULL;
873}
874
875// Gather set of configurable elements
876void CConfigurableDomain::gatherConfigurableElements(set<const CConfigurableElement*>& configurableElementSet) const
877{
878 // Insert all configurable elements
879 configurableElementSet.insert(_configurableElementList.begin(), _configurableElementList.end());
880}
881
882// Check configurable element already attached
883bool CConfigurableDomain::containsConfigurableElement(const CConfigurableElement* pConfigurableCandidateElement) const
884{
885 ConfigurableElementListIterator it;
886
887 // Browse all configurable elements for comparison
888 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
889
890 if (pConfigurableCandidateElement == *it) {
891
892 return true;
893 }
894 }
895 return false;
896}
897
898// Merge any descended configurable element to this one with this one
899void CConfigurableDomain::mergeAlreadyAssociatedDescendantConfigurableElements(CConfigurableElement* pNewConfigurableElement)
900{
901 list<CConfigurableElement*> mergedConfigurableElementList;
902
903 ConfigurableElementListIterator it;
904
905 // Browse all configurable elements (new one not yet in the list!)
906 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
907
908 CConfigurableElement* pConfigurablePotentialDescendantElement = *it;
909
910 if (pConfigurablePotentialDescendantElement->isDescendantOf(pNewConfigurableElement)) {
911
Kevin Rocardace81f82012-12-11 16:19:17 +0100912 log_info("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());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200913
914 // Merge configuration data
915 mergeConfigurations(pNewConfigurableElement, pConfigurablePotentialDescendantElement);
916
917 // Keep track for removal
918 mergedConfigurableElementList.push_back(pConfigurablePotentialDescendantElement);
919 }
920 }
921
922 // Remove all merged elements (new one not yet in the list!)
923 for (it = mergedConfigurableElementList.begin(); it != mergedConfigurableElementList.end(); ++it) {
924
925 CConfigurableElement* pMergedConfigurableElement = *it;
926
927 // Remove merged from configurable element from internal tracking list
928 // 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
929 doRemoveConfigurableElement(pMergedConfigurableElement, false);
930 }
931}
932
933void CConfigurableDomain::mergeConfigurations(CConfigurableElement* pToConfigurableElement, CConfigurableElement* pFromConfigurableElement)
934{
935 // Propagate to domain configurations
936 uint32_t uiNbConfigurations = getNbChildren();
937 uint32_t uiChild;
938
939 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
940
941 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
942
943 // Do the merge.
944 pDomainConfiguration->merge(pToConfigurableElement, pFromConfigurableElement);
945 }
946}
947
948// Configurable elements association
Frédéric Boisnard9620e442012-05-30 16:15:02 +0200949void CConfigurableDomain::doAddConfigurableElement(CConfigurableElement* pConfigurableElement, const CParameterBlackboard *pMainBlackboard)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200950{
951 // Inform configurable element
952 pConfigurableElement->addAttachedConfigurableDomain(this);
953
Patrick Benavoli63499d42011-10-24 18:50:03 +0200954 // Create associated syncer set
955 CSyncerSet* pSyncerSet = new CSyncerSet;
956
957 // Add to sync set the configurable element one
958 pConfigurableElement->fillSyncerSet(*pSyncerSet);
959
960 // Store it
961 _configurableElementToSyncerSetMap[pConfigurableElement] = pSyncerSet;
962
963 // Add it to global one
964 _syncerSet += *pSyncerSet;
965
Patrick Benavoli68a91282011-08-31 11:23:23 +0200966 // Inform configurations
967 uint32_t uiNbConfigurations = getNbChildren();
968 uint32_t uiChild;
969
970 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
971
972 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
973
Patrick Benavoli63499d42011-10-24 18:50:03 +0200974 pDomainConfiguration->addConfigurableElement(pConfigurableElement, pSyncerSet);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200975 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200976
Frédéric Boisnard9620e442012-05-30 16:15:02 +0200977 // Ensure area validity for that configurable element (if main blackboard provided)
978 if (pMainBlackboard) {
979
980 // Need to validate against main blackboard
981 validateAreas(pConfigurableElement, pMainBlackboard);
982 }
983
984 // Already associated descendend configurable elements need a merge of their configuration data
Patrick Benavoli68a91282011-08-31 11:23:23 +0200985 mergeAlreadyAssociatedDescendantConfigurableElements(pConfigurableElement);
986
987 // Add to list
988 _configurableElementList.push_back(pConfigurableElement);
989}
990
991void CConfigurableDomain::doRemoveConfigurableElement(CConfigurableElement* pConfigurableElement, bool bRecomputeSyncSet)
992{
993 // Remove from list
994 _configurableElementList.remove(pConfigurableElement);
995
Patrick Benavoli63499d42011-10-24 18:50:03 +0200996 // Remove associated syncer set
997 CSyncerSet* pSyncerSet = getSyncerSet(pConfigurableElement);
998
999 _configurableElementToSyncerSetMap.erase(pConfigurableElement);
1000
1001 delete pSyncerSet;
1002
Patrick Benavoli68a91282011-08-31 11:23:23 +02001003 // Inform configurable element
1004 pConfigurableElement->removeAttachedConfigurableDomain(this);
1005
1006 // Inform configurations
1007 uint32_t uiNbConfigurations = getNbChildren();
1008 uint32_t uiChild;
1009
1010 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
1011
1012 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
1013
1014 pDomainConfiguration->removeConfigurableElement(pConfigurableElement);
1015 }
1016 // Recompute our sync set if needed
1017 if (bRecomputeSyncSet) {
1018
1019 computeSyncSet();
1020 }
1021}
Patrick Benavoli63499d42011-10-24 18:50:03 +02001022
1023// Syncer set retrieval from configurable element
1024CSyncerSet* CConfigurableDomain::getSyncerSet(const CConfigurableElement* pConfigurableElement) const
1025{
1026 ConfigurableElementToSyncerSetMapIterator mapIt = _configurableElementToSyncerSetMap.find(pConfigurableElement);
1027
1028 assert(mapIt != _configurableElementToSyncerSetMap.end());
1029
1030 return mapIt->second;
1031}
Patrick Benavoli0bd50542011-11-29 11:10:27 +01001032
1033// Configuration retrieval
1034CDomainConfiguration* CConfigurableDomain::findConfiguration(const string& strConfiguration, string& strError)
1035{
1036 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(strConfiguration));
1037
1038 if (!pDomainConfiguration) {
1039
1040 strError = "Domain configuration " + strConfiguration + " not found";
1041
1042 return NULL;
1043 }
1044 return pDomainConfiguration;
1045}
1046
1047const CDomainConfiguration* CConfigurableDomain::findConfiguration(const string& strConfiguration, string& strError) const
1048{
1049 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(findChild(strConfiguration));
1050
1051 if (!pDomainConfiguration) {
1052
1053 strError = "Domain configuration " + strConfiguration + " not found";
1054
1055 return NULL;
1056 }
1057 return pDomainConfiguration;
1058}