blob: 912fa5ed28f662552de91bd593075cb115698fa6 [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"
35#include "Subsystem.h"
36#include "XmlDomainSerializingContext.h"
37#include <assert.h>
38
39#define base CBinarySerializableElement
40
41CConfigurableDomain::CConfigurableDomain(const string& strName) : base(strName), _pLastAppliedConfiguration(NULL)
42{
43}
44
45CConfigurableDomain::~CConfigurableDomain()
46{
47 ConfigurableElementListIterator it;
48
49 // Browse all configurable elements for their syncers
50 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
51
52 CConfigurableElement* pConfigurableElement = *it;
53
54 // Remove from configurable element
55 pConfigurableElement->removeAttachedConfigurableDomain(this);
56 }
57}
58
59string CConfigurableDomain::getKind() const
60{
61 return "ConfigurableDomain";
62}
63
64bool CConfigurableDomain::childrenAreDynamic() const
65{
66 return true;
67}
68
69// From IXmlSource
70void CConfigurableDomain::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
71{
72 // Configurations
73 composeDomainConfigurations(xmlElement, serializingContext);
74
75 // Configurable Elements
76 composeConfigurableElements(xmlElement, serializingContext);
77}
78
79// XML composing
80void CConfigurableDomain::composeDomainConfigurations(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
81{
82 // Create Configurations element
83 CXmlElement xmlConfigurationsElement;
84
85 xmlElement.createChild(xmlConfigurationsElement, "Configurations");
86
87 // Delegate to base
88 base::toXml(xmlConfigurationsElement, serializingContext);
89}
90
91void CConfigurableDomain::composeConfigurableElements(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
92{
93 // Context
94 const CXmlDomainSerializingContext& xmlDomainSerializingContext = static_cast<const CXmlDomainSerializingContext&>(serializingContext);
95
96 // Create ConfigurableElements element
97 CXmlElement xmlConfigurableElementsElement;
98
99 xmlElement.createChild(xmlConfigurableElementsElement, "ConfigurableElements");
100
101 // Serialize out all configurable elements settings
102 ConfigurableElementListIterator it;
103
104 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
105
106 const CConfigurableElement* pConfigurableElement = *it;
107
108 // Create corresponding XML child element
109 CXmlElement xmlChildConfigurableElement;
110
111 xmlConfigurableElementsElement.createChild(xmlChildConfigurableElement, "ConfigurableElement");
112
113 // Set Path attribute
114 xmlChildConfigurableElement.setAttributeString("Path", pConfigurableElement->getPath());
115
116 if (xmlDomainSerializingContext.withSettings()) {
117
118 // Compose configurations for that configurable element
119 composeConfigurableElementConfigurations(pConfigurableElement, xmlChildConfigurableElement, serializingContext);
120 }
121 }
122}
123
124// Serialize configurations for one configurable element
125void CConfigurableDomain::composeConfigurableElementConfigurations(const CConfigurableElement* pConfigurableElement, CXmlElement& xmlConfigurableElementElement, CXmlSerializingContext& serializingContext) const
126{
127 uint32_t uiNbConfigurations = getNbChildren();
128 uint32_t uiChildConfiguration;
129
130 for (uiChildConfiguration = 0; uiChildConfiguration < uiNbConfigurations; uiChildConfiguration++) {
131
132 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChildConfiguration));
133
134 // Create child xml element for that configuration
135 CXmlElement xmlConfigurationSettingsElement;
136
137 xmlConfigurableElementElement.createChild(xmlConfigurationSettingsElement, pDomainConfiguration->getKind());
138
139 // Set its name attribute
140 xmlConfigurationSettingsElement.setNameAttribute(pDomainConfiguration->getName());
141
142 // Have domain configuration serialize settings for configurable element
143 ((CConfigurableDomain&)(*this)).serializeConfigurableElementConfiguration((CDomainConfiguration*)pDomainConfiguration, pConfigurableElement, xmlConfigurationSettingsElement, serializingContext, true);
144 }
145}
146
147// From IXmlSink
148bool CConfigurableDomain::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
149{
150 // Local parsing. Do not dig
151 return parseDomainConfigurations(xmlElement, serializingContext) && parseConfigurableElements(xmlElement, serializingContext);
152}
153
154// XML parsing
155bool CConfigurableDomain::parseDomainConfigurations(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
156{
157 // We're supposedly clean
158 assert(_configurableElementList.empty());
159
160 // Get Configurations element
161 CXmlElement xmlConfigurationsElement;
162
163 xmlElement.getChildElement("Configurations", xmlConfigurationsElement);
164
165 // Parse it and create domain configuration objects
166 return base::fromXml(xmlConfigurationsElement, serializingContext);
167}
168
169// Parse configurable elements
170bool CConfigurableDomain::parseConfigurableElements(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
171{
172 // Context
173 const CXmlDomainSerializingContext& xmlDomainSerializingContext = static_cast<const CXmlDomainSerializingContext&>(serializingContext);
174
175 // Get System Class Element
176 CElement* pRootElement = getRoot();
177
178 CElement* pSystemClassElement = pRootElement->findChildOfKind("SystemClass");
179
180 assert(pSystemClassElement);
181
182 // Get ConfigurableElements element
183 CXmlElement xmlConfigurableElementsElement;
184 xmlElement.getChildElement("ConfigurableElements", xmlConfigurableElementsElement);
185
186 // Parse it and associate found configurable elements to it
187 CXmlElement::CChildIterator it(xmlConfigurableElementsElement);
188
189 CXmlElement xmlConfigurableElementElement;
190
191 while (it.next(xmlConfigurableElementElement)) {
192
193 // Locate configurable element
194 string strConfigurableElementPath = xmlConfigurableElementElement.getAttributeString("Path");
195
196 CPathNavigator pathNavigator(strConfigurableElementPath);
197
198 string* pStrChildName = pathNavigator.next();
199
200 // Is there an element and does it match system class name?
201 if (!pStrChildName || *pStrChildName != pSystemClassElement->getName()) {
202
203 serializingContext.setError("Could not find configurable element of path " + strConfigurableElementPath + " from ConfigurableDomain description " + getName());
204
205 return false;
206 }
207
208 // Browse system class for configurable element
209 CConfigurableElement* pConfigurableElement = static_cast<CConfigurableElement*>(pSystemClassElement->findDescendant(pathNavigator));
210
211 if (!pConfigurableElement) {
212
213 serializingContext.setError("Could not find configurable element of path " + strConfigurableElementPath + " from ConfigurableDomain description " + getName());
214
215 return false;
216 }
217 // Add found element to domain
218 string strError;
219 if (!addConfigurableElement(pConfigurableElement, NULL, strError)) {
220
221 serializingContext.setError(strError);
222
223 return false;
224 }
225
226 // Check we need to parse configuration settings
227 if (xmlDomainSerializingContext.withSettings()) {
228
229 // Make Domain configuration parse associated configuration nodes if any
230 if (!parseConfigurableElementConfigurations(pConfigurableElement, xmlConfigurableElementElement, serializingContext)) {
231
232 return false;
233 }
234 }
235 }
236 // All provided configurations are parsed
237 // Attempt validation on areas of non provided configurations for all configurable elements
238 autoValidateAll();
239
240 return true;
241}
242
243// Parse configurations for one configurable element
244bool CConfigurableDomain::parseConfigurableElementConfigurations(const CConfigurableElement* pConfigurableElement, CXmlElement& xmlConfigurableElementElement, CXmlSerializingContext& serializingContext)
245{
246 // Context
247 CXmlDomainSerializingContext& xmlDomainSerializingContext = static_cast<CXmlDomainSerializingContext&>(serializingContext);
248
249 // Parse configurable element's configuration settings
250 CXmlElement::CChildIterator it(xmlConfigurableElementElement);
251
252 CXmlElement xmlConfigurationSettingsElement;
253
254 while (it.next(xmlConfigurationSettingsElement)) {
255 // Get domain configuration
256 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(xmlConfigurationSettingsElement.getNameAttribute()));
257
258 if (!pDomainConfiguration) {
259
260 xmlDomainSerializingContext.setError("Could not find domain configuration referred to by configurable element of path " + xmlConfigurableElementElement.getPath() + " from ConfigurableDomain description " + getName());
261
262 return false;
263 }
264 // Have domain configuration parse settings for configurable element
265 if (!serializeConfigurableElementConfiguration(pDomainConfiguration, pConfigurableElement, xmlConfigurationSettingsElement, xmlDomainSerializingContext, false)) {
266
267 return false;
268 }
269 }
270
271 return true;
272}
273
274// Serialize one configuration for one configurable element
275bool CConfigurableDomain::serializeConfigurableElementConfiguration(CDomainConfiguration* pDomainConfiguration, const CConfigurableElement* pConfigurableElement, CXmlElement& xmlConfigurationSettingsElement, CXmlSerializingContext& serializingContext, bool bSerializeOut)
276{
277 // Actual XML context
278 CXmlDomainSerializingContext& xmlDomainSerializingContext = static_cast<CXmlDomainSerializingContext&>(serializingContext);
279
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200280 // Element content
281 CXmlElement xmlConfigurationSettingsElementContent;
282
283 // Deal with element itself
284 if (!bSerializeOut) {
285
286 // Check structure
287 if (xmlConfigurationSettingsElement.getNbChildElements() != 1) {
288
289 // Structure error
290 serializingContext.setError("Struture error encountered while parsing settinsg of " + pConfigurableElement->getKind() + " " + pConfigurableElement->getName() + " in Configuration " + pDomainConfiguration->getName() + " in Domain " + getName());
291
292 return false;
293 }
294
295 // Check name and kind
296 if (!xmlConfigurationSettingsElement.getChildElement(pConfigurableElement->getKind(), pConfigurableElement->getName(), xmlConfigurationSettingsElementContent)) {
297
298 serializingContext.setError("Couldn't find settings for " + pConfigurableElement->getKind() + " " + pConfigurableElement->getName() + " for Configuration " + pDomainConfiguration->getName() + " in Domain " + getName());
299
300 return false;
301 }
302 } else {
303
304 // Create child XML element
305 xmlConfigurationSettingsElement.createChild(xmlConfigurationSettingsElementContent, pConfigurableElement->getKind());
306
307 // Set Name
308 xmlConfigurationSettingsElementContent.setNameAttribute(pConfigurableElement->getName());
309 }
310
311 // Change context type to parameter settings access
Patrick Benavoli68a91282011-08-31 11:23:23 +0200312 string strError;
313
314 // Create configuration access context
315 CConfigurationAccessContext configurationAccessContext(strError, bSerializeOut);
316
317 // Provide current value space
318 configurationAccessContext.setValueSpaceRaw(xmlDomainSerializingContext.valueSpaceIsRaw());
319
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200320 // Provide current output raw format
321 configurationAccessContext.setOutputRawFormat(xmlDomainSerializingContext.outputRawFormatIsHex());
322
Patrick Benavoli68a91282011-08-31 11:23:23 +0200323 // Get subsystem
324 const CSubsystem* pSubsystem = pConfigurableElement->getBelongingSubsystem();
325
326 if (pSubsystem && pSubsystem != pConfigurableElement) {
327
328 // Element is a descendant of subsystem
329
330 // Deal with Endianness
331 configurationAccessContext.setBigEndianSubsystem(pSubsystem->isBigEndian());
332 }
333
334 // Have domain configuration parse settings for configurable element
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200335 if (!pDomainConfiguration->serializeXmlSettings(pConfigurableElement, xmlConfigurationSettingsElementContent, configurationAccessContext)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200336
337 // Forward error
338 xmlDomainSerializingContext.setError(strError);
339
340 return false;
341 }
342 return true;
343}
344
345// Configurable elements association
346bool CConfigurableDomain::addConfigurableElement(CConfigurableElement* pConfigurableElement, const CParameterBlackboard* pMainBlackboard, string& strError)
347{
348 // Already associated?
349 if (containsConfigurableElement(pConfigurableElement)) {
350
351 strError = "Configurable element " + pConfigurableElement->getPath() + " already associated to configuration domain " + getName();
352
353 return false;
354 }
355
356 // Already owned?
357 if (pConfigurableElement->belongsTo(this)) {
358
359 strError = "Configurable element " + pConfigurableElement->getPath() + " already owned by configuration domain " + getName();
360
361 return false;
362 }
363 log("Adding configurable element \"%s\" into domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str());
364
365 // Do add
366 doAddConfigurableElement(pConfigurableElement);
367
368 // Ensure area validity for that configurable element (if main blackboard provided)
369 if (pMainBlackboard) {
370
371 // Need to validate against main blackboard
372 validateAreas(pConfigurableElement, pMainBlackboard);
373 }
374
375 return true;
376}
377
378bool CConfigurableDomain::removeConfigurableElement(CConfigurableElement* pConfigurableElement, string& strError)
379{
380 // Not associated?
381 if (!containsConfigurableElement(pConfigurableElement)) {
382
383 strError = "Configurable element " + pConfigurableElement->getPath() + " not associated to configuration domain " + getName();
384
385 return false;
386 }
387 log("Removing configurable element \"%s\" from domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str());
388
389 // Do remove
390 doRemoveConfigurableElement(pConfigurableElement, true);
391
392 return true;
393}
394
395// Domain splitting
396bool CConfigurableDomain::split(CConfigurableElement* pConfigurableElement, string& strError)
397{
398 // Not associated?
399 if (!containsConfigurableElement(pConfigurableElement)) {
400
401 strError = "Configurable element " + pConfigurableElement->getPath() + " not associated to configuration domain " + getName();
402
403 return false;
404 }
405 log("Splitting configurable element \"%s\" domain \"%s\"", pConfigurableElement->getPath().c_str(), getName().c_str());
406
407 // Create sub domain areas for all configurable element's children
408 uint32_t uiNbConfigurableElementChildren = pConfigurableElement->getNbChildren();
409
410 if (!uiNbConfigurableElementChildren) {
411
412 strError = "Configurable element " + pConfigurableElement->getPath() + " has no children to split configurable domain to";
413
414 return false;
415 }
416
417 uint32_t uiChild;
418
419 for (uiChild = 0; uiChild < uiNbConfigurableElementChildren; uiChild++) {
420
421 CConfigurableElement* pChildConfigurableElement = static_cast<CConfigurableElement*>(pConfigurableElement->getChild(uiChild));
422
423 doAddConfigurableElement(pChildConfigurableElement);
424 }
425
426 // Delegate to configurations
427 uint32_t uiNbConfigurations = getNbChildren();
428
429 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
430
431 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
432
433 pDomainConfiguration->split(pConfigurableElement);
434 }
435
436 // Remove given configurable element from this domain
437 // 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
438 doRemoveConfigurableElement(pConfigurableElement, false);
439
440 return true;
441}
442
443// Configuration application if required
444void CConfigurableDomain::apply(CParameterBlackboard* pParameterBlackboard, CSyncerSet& syncerSet, bool bForce)
445{
446 if (bForce) {
447 // Force a configuration restore by forgetting about last applied configuration
448 _pLastAppliedConfiguration = NULL;
449 }
450 const CDomainConfiguration* pApplicableDomainConfiguration = findApplicableDomainConfiguration();
451
452 if (pApplicableDomainConfiguration) {
453
454 // Check not the last one before applying
455 if (!_pLastAppliedConfiguration || _pLastAppliedConfiguration != pApplicableDomainConfiguration) {
456
457 log("Applying configuration \"%s\" from domain \"%s\"", pApplicableDomainConfiguration->getName().c_str(), getName().c_str());
458
459 // Do the restore
460 pApplicableDomainConfiguration->restore(pParameterBlackboard);
461
462 // Record last applied configuration
463 _pLastAppliedConfiguration = pApplicableDomainConfiguration;
464
465 // Since we applied changes, add our own sync set to the given one
466 syncerSet += _syncerSet;
467 }
468 }
469}
470
471// Return applicable configuration validity for given configurable element
472bool CConfigurableDomain::isApplicableConfigurationValid(const CConfigurableElement* pConfigurableElement) const
473{
474 const CDomainConfiguration* pApplicableDomainConfiguration = findApplicableDomainConfiguration();
475
476 return pApplicableDomainConfiguration && pApplicableDomainConfiguration->isValid(pConfigurableElement);
477}
478
479// Presence of application condition on any configuration
480bool CConfigurableDomain::hasRules() const
481{
482 // Delegate to configurations
483 uint32_t uiNbConfigurations = getNbChildren();
484 uint32_t uiChild;
485
486 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
487
488 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
489
490 if (pDomainConfiguration->hasRule()) {
491
492 return true;
493 }
494 }
495 return false;
496}
497
498// In case configurable element was removed
499void CConfigurableDomain::computeSyncSet()
500{
501 // Clean sync set first
502 _syncerSet.clear();
503
504 // Browse all configurable elements for their syncers
505 ConfigurableElementListIterator it;
506
507 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
508
509 const CConfigurableElement* pConfigurableElement = *it;
510
511 pConfigurableElement->fillSyncerSet(_syncerSet);
512 }
513}
514
515// Configuration Management
516bool CConfigurableDomain::createConfiguration(const string& strName, const CParameterBlackboard* pMainBlackboard, string& strError)
517{
518 // Already exists?
519 if (findChild(strName)) {
520
521 strError = "Already existing configuration";
522
523 return false;
524 }
525 log("Creating domain configuration \"%s\" into domain \"%s\"", strName.c_str(), getName().c_str());
526
527 // Creation
528 CDomainConfiguration* pDomainConfiguration = new CDomainConfiguration(strName);
529
530 // Configurable elements association
531 ConfigurableElementListIterator it;
532
533 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
534
535 pDomainConfiguration->addConfigurableElement(*it);
536 }
537
538 // Hierarchy
539 addChild(pDomainConfiguration);
540
541 // Ensure validity of fresh new domain configuration
542 // Attempt auto validation, so that the user gets his/her own settings by defaults
543 if (!autoValidateConfiguration(pDomainConfiguration)) {
544
545 // No valid configuration found to copy in from, validate againt main blackboard (will concerned remaining invalid parts)
546 pDomainConfiguration->validate(pMainBlackboard);
547 }
548
549 return true;
550}
551
552bool CConfigurableDomain::deleteConfiguration(const string& strName, string& strError)
553{
554 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(strName));
555
556 if (!pDomainConfiguration) {
557
558 strError = "Configuration not found";
559
560 return false;
561 }
562
563 // Check configuration has no rule (prevent accidental loss of data)
564 if (pDomainConfiguration->hasRule()) {
565
566 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.";
567
568 return false;
569 }
570
571 log("Deleting configuration \"%s\" from domain \"%s\"", strName.c_str(), getName().c_str());
572
573 // Was the last applied?
574 if (pDomainConfiguration == _pLastAppliedConfiguration) {
575
576 // Forget about it
577 _pLastAppliedConfiguration = NULL;
578 }
579
580 // Hierarchy
581 removeChild(pDomainConfiguration);
582
583 // Destroy
584 delete pDomainConfiguration;
585
586 return true;
587}
588
589void CConfigurableDomain::listAssociatedToElements(string& strResult) const
590{
591 strResult = "\n";
592
593 ConfigurableElementListIterator it;
594
595 // Browse all configurable elements
596 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
597
598 const CConfigurableElement* pConfigurableElement = *it;
599
600 strResult += pConfigurableElement->getPath() + "\n";
601 }
602}
603
604bool CConfigurableDomain::renameConfiguration(const string& strName, const string& strNewName, string& strError)
605{
606 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(strName));
607
608 if (!pDomainConfiguration) {
609
610 strError = "Configuration not found";
611
612 return false;
613 }
614 log("Renaming domain \"%s\"'s configuration \"%s\" to \"%s\"", getName().c_str(), strName.c_str(), strNewName.c_str());
615
616 // Rename
617 return pDomainConfiguration->rename(strNewName, strError);
618}
619
620bool CConfigurableDomain::restoreConfiguration(const string& strName, CParameterBlackboard* pMainBlackboard, bool bAutoSync, string& strError)
621{
622 // Find Domain configuration
623 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(findChild(strName));
624
625 if (!pDomainConfiguration) {
626
627 strError = "Domain configuration " + strName + " not found";
628
629 return false;
630 }
631 log("Restoring domain \"%s\"'s configuration \"%s\" to parameter blackboard", getName().c_str(), pDomainConfiguration->getName().c_str());
632
633 // Delegate
634 pDomainConfiguration->restore(pMainBlackboard);
635
636 // Record last applied configuration
637 _pLastAppliedConfiguration = pDomainConfiguration;
638
639 // Synchronize
640 return !bAutoSync || _syncerSet.sync(*pMainBlackboard, false, strError);
641}
642
643bool CConfigurableDomain::saveConfiguration(const string& strName, const CParameterBlackboard* pMainBlackboard, string& strError)
644{
645 // Find Domain configuration
646 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(findChild(strName));
647
648 if (!pDomainConfiguration) {
649
650 strError = "Domain configuration " + strName + " not found";
651
652 return false;
653 }
654 log("Saving domain \"%s\"'s configuration \"%s\" from parameter blackboard", getName().c_str(), pDomainConfiguration->getName().c_str());
655
656 // Delegate
657 pDomainConfiguration->save(pMainBlackboard);
658
659 return true;
660}
661
662// Last applied configuration
663string CConfigurableDomain::getLastAppliedConfigurationName() const
664{
665 if (_pLastAppliedConfiguration) {
666
667 return _pLastAppliedConfiguration->getName();
668 }
669 return "<none>";
670}
671
672// Ensure validity on whole domain from main blackboard
673void CConfigurableDomain::validate(const CParameterBlackboard* pMainBlackboard)
674{
675 log("Validating whole domain \"" + getName() + "\" against main blackboard");
676
677 // Propagate
678 uint32_t uiNbConfigurations = getNbChildren();
679 uint32_t uiChild;
680
681 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
682
683 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
684
685 pDomainConfiguration->validate(pMainBlackboard);
686 }
687}
688
689// Ensure validity on areas related to configurable element
690void CConfigurableDomain::validateAreas(const CConfigurableElement* pConfigurableElement, const CParameterBlackboard* pMainBlackboard)
691{
692 log("Validating domain \"" + getName() + "\" against main blackboard for configurable element \"" + pConfigurableElement->getPath() + "\"");
693
694 // Propagate
695 uint32_t uiNbConfigurations = getNbChildren();
696 uint32_t uiChild;
697
698 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
699
700 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
701
702 pDomainConfiguration->validate(pConfigurableElement, pMainBlackboard);
703 }
704}
705
706// Attempt validation for all configurable element's areas, relying on already existing valid configuration inside domain
707void CConfigurableDomain::autoValidateAll()
708{
709 // Validate
710 ConfigurableElementListIterator it;
711
712 // Browse all configurable elements for configuration validation
713 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
714
715 const CConfigurableElement* pConfigurableElement = *it;
716
717 // Auto validate element
718 autoValidateAreas(pConfigurableElement);
719 }
720}
721
722// Attempt validation for configurable element's areas, relying on already existing valid configuration inside domain
723void CConfigurableDomain::autoValidateAreas(const CConfigurableElement* pConfigurableElement)
724{
725 // Find first valid configuration for given configurable element
726 const CDomainConfiguration* pValidDomainConfiguration = findValidDomainConfiguration(pConfigurableElement);
727
728 // No valid configuration found, give up
729 if (!pValidDomainConfiguration) {
730
731 return;
732 }
733
734 log("Auto validating domain \"" + getName() + "\" against configuration \"" + pValidDomainConfiguration->getName() + "\" for configurable element " + pConfigurableElement->getPath());
735
736 // Validate all other configurations against found one, if any
737 uint32_t uiNbConfigurations = getNbChildren();
738 uint32_t uiChild;
739
740 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
741
742 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
743
744 if (pDomainConfiguration != pValidDomainConfiguration && !pDomainConfiguration->isValid(pConfigurableElement)) {
745 // Validate
746 pDomainConfiguration->validateAgainst(pValidDomainConfiguration, pConfigurableElement);
747 }
748 }
749}
750
751// Attempt configuration validation for all configurable elements' areas, relying on already existing valid configuration inside domain
752bool CConfigurableDomain::autoValidateConfiguration(CDomainConfiguration* pDomainConfiguration)
753{
754 // Find another configuration than this one, that ought to be valid!
755 uint32_t uiNbConfigurations = getNbChildren();
756 uint32_t uiChild;
757
758 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
759
760 const CDomainConfiguration* pPotententialValidDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
761
762 if (pPotententialValidDomainConfiguration != pDomainConfiguration) {
763
764 // Validate against it
765 pDomainConfiguration->validateAgainst(pPotententialValidDomainConfiguration);
766
767 return true;
768 }
769 }
770 return false;
771}
Patrick Benavoli68a91282011-08-31 11:23:23 +0200772
Patrick Benavoli68a91282011-08-31 11:23:23 +0200773// Search for a valid configuration for given configurable element
774const CDomainConfiguration* CConfigurableDomain::findValidDomainConfiguration(const CConfigurableElement* pConfigurableElement) const
775{
776 uint32_t uiNbConfigurations = getNbChildren();
777 uint32_t uiChild;
778
779 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
780
781 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
782
783 if (pDomainConfiguration->isValid(pConfigurableElement)) {
784
785 return pDomainConfiguration;
786 }
787 }
788 return NULL;
789}
790
791// Search for an applicable configuration
792const CDomainConfiguration* CConfigurableDomain::findApplicableDomainConfiguration() const
793{
794 uint32_t uiNbConfigurations = getNbChildren();
795 uint32_t uiChild;
796
797 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
798
799 const CDomainConfiguration* pDomainConfiguration = static_cast<const CDomainConfiguration*>(getChild(uiChild));
800
801 if (pDomainConfiguration->isApplicable()) {
802
803 return pDomainConfiguration;
804 }
805 }
806 return NULL;
807}
808
809// Gather set of configurable elements
810void CConfigurableDomain::gatherConfigurableElements(set<const CConfigurableElement*>& configurableElementSet) const
811{
812 // Insert all configurable elements
813 configurableElementSet.insert(_configurableElementList.begin(), _configurableElementList.end());
814}
815
816// Check configurable element already attached
817bool CConfigurableDomain::containsConfigurableElement(const CConfigurableElement* pConfigurableCandidateElement) const
818{
819 ConfigurableElementListIterator it;
820
821 // Browse all configurable elements for comparison
822 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
823
824 if (pConfigurableCandidateElement == *it) {
825
826 return true;
827 }
828 }
829 return false;
830}
831
832// Merge any descended configurable element to this one with this one
833void CConfigurableDomain::mergeAlreadyAssociatedDescendantConfigurableElements(CConfigurableElement* pNewConfigurableElement)
834{
835 list<CConfigurableElement*> mergedConfigurableElementList;
836
837 ConfigurableElementListIterator it;
838
839 // Browse all configurable elements (new one not yet in the list!)
840 for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {
841
842 CConfigurableElement* pConfigurablePotentialDescendantElement = *it;
843
844 if (pConfigurablePotentialDescendantElement->isDescendantOf(pNewConfigurableElement)) {
845
846 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());
847
848 // Merge configuration data
849 mergeConfigurations(pNewConfigurableElement, pConfigurablePotentialDescendantElement);
850
851 // Keep track for removal
852 mergedConfigurableElementList.push_back(pConfigurablePotentialDescendantElement);
853 }
854 }
855
856 // Remove all merged elements (new one not yet in the list!)
857 for (it = mergedConfigurableElementList.begin(); it != mergedConfigurableElementList.end(); ++it) {
858
859 CConfigurableElement* pMergedConfigurableElement = *it;
860
861 // Remove merged from configurable element from internal tracking list
862 // 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
863 doRemoveConfigurableElement(pMergedConfigurableElement, false);
864 }
865}
866
867void CConfigurableDomain::mergeConfigurations(CConfigurableElement* pToConfigurableElement, CConfigurableElement* pFromConfigurableElement)
868{
869 // Propagate to domain configurations
870 uint32_t uiNbConfigurations = getNbChildren();
871 uint32_t uiChild;
872
873 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
874
875 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
876
877 // Do the merge.
878 pDomainConfiguration->merge(pToConfigurableElement, pFromConfigurableElement);
879 }
880}
881
882// Configurable elements association
883void CConfigurableDomain::doAddConfigurableElement(CConfigurableElement* pConfigurableElement)
884{
885 // Inform configurable element
886 pConfigurableElement->addAttachedConfigurableDomain(this);
887
888 // Inform configurations
889 uint32_t uiNbConfigurations = getNbChildren();
890 uint32_t uiChild;
891
892 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
893
894 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
895
896 pDomainConfiguration->addConfigurableElement(pConfigurableElement);
897 }
898 // Add to our own sync set the configurable element one
899 pConfigurableElement->fillSyncerSet(_syncerSet);
900
901 // Already associated descended configurable elements need a merge of their configuration data
902 mergeAlreadyAssociatedDescendantConfigurableElements(pConfigurableElement);
903
904 // Add to list
905 _configurableElementList.push_back(pConfigurableElement);
906}
907
908void CConfigurableDomain::doRemoveConfigurableElement(CConfigurableElement* pConfigurableElement, bool bRecomputeSyncSet)
909{
910 // Remove from list
911 _configurableElementList.remove(pConfigurableElement);
912
913 // Inform configurable element
914 pConfigurableElement->removeAttachedConfigurableDomain(this);
915
916 // Inform configurations
917 uint32_t uiNbConfigurations = getNbChildren();
918 uint32_t uiChild;
919
920 for (uiChild = 0; uiChild < uiNbConfigurations; uiChild++) {
921
922 CDomainConfiguration* pDomainConfiguration = static_cast<CDomainConfiguration*>(getChild(uiChild));
923
924 pDomainConfiguration->removeConfigurableElement(pConfigurableElement);
925 }
926 // Recompute our sync set if needed
927 if (bRecomputeSyncSet) {
928
929 computeSyncSet();
930 }
931}