1 /*
2 * Copyright (c) 2011-2015, Intel Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software without
17 * specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 #include "ConfigurableElement.h"
31 #include "MappingData.h"
32 #include "SyncerSet.h"
33 #include "ConfigurableDomain.h"
34 #include "ConfigurationAccessContext.h"
35 #include "ConfigurableElementAggregator.h"
36 #include "AreaConfiguration.h"
37 #include "Utility.h"
38 #include <assert.h>
39
40 #define base CElement
41
CConfigurableElement(const std::string & strName)42 CConfigurableElement::CConfigurableElement(const std::string& strName) : base(strName), _uiOffset(0)
43 {
44 }
45
~CConfigurableElement()46 CConfigurableElement::~CConfigurableElement()
47 {
48 }
49
50 // XML configuration settings parsing
serializeXmlSettings(CXmlElement & xmlConfigurationSettingsElementContent,CConfigurationAccessContext & configurationAccessContext) const51 bool CConfigurableElement::serializeXmlSettings(CXmlElement& xmlConfigurationSettingsElementContent, CConfigurationAccessContext& configurationAccessContext) const
52 {
53 size_t uiIndex;
54 size_t uiNbChildren = getNbChildren();
55
56 if (!configurationAccessContext.serializeOut()) {
57 // Just do basic checks and propagate to children
58 CXmlElement::CChildIterator it(xmlConfigurationSettingsElementContent);
59
60 CXmlElement xmlChildConfigurableElementSettingsElement;
61
62 // Propagate to children
63 for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
64
65 // Get child
66 const CConfigurableElement* pChildConfigurableElement = static_cast<const CConfigurableElement*>(getChild(uiIndex));
67
68 if (!it.next(xmlChildConfigurableElementSettingsElement)) {
69
70 // Structure error
71 configurationAccessContext.setError("Configuration settings parsing: Settings don't conform to structure of configurable element " + getName());
72
73 return false;
74 }
75
76 // Check element type matches in type
77 if (xmlChildConfigurableElementSettingsElement.getType() != pChildConfigurableElement->getKind()) {
78
79 // Type error
80 configurationAccessContext.setError("Configuration settings parsing: Settings for configurable element " + pChildConfigurableElement->getName() + " does not match expected type: " + xmlChildConfigurableElementSettingsElement.getType() + " instead of " + pChildConfigurableElement->getKind());
81
82 return false;
83 }
84
85 // Check element type matches in name
86 if (xmlChildConfigurableElementSettingsElement.getNameAttribute() != pChildConfigurableElement->getName()) {
87
88 // Name error
89 configurationAccessContext.setError("Configuration settings parsing: Under configurable elememnt " + getName() + ", expected element name " + pChildConfigurableElement->getName() + " but found " + xmlChildConfigurableElementSettingsElement.getNameAttribute() + " instead");
90
91 return false;
92 }
93
94 // Parse child configurable element's settings
95 if (!pChildConfigurableElement->serializeXmlSettings(xmlChildConfigurableElementSettingsElement, configurationAccessContext)) {
96
97 return false;
98 }
99 }
100 // There should remain no configurable element to parse
101 if (it.next(xmlChildConfigurableElementSettingsElement)) {
102
103 // Structure error
104 configurationAccessContext.setError("Configuration settings parsing: Settings don't conform to structure of configurable element " + getName());
105
106 return false;
107 }
108 } else {
109 // Propagate to children
110 for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
111
112 const CConfigurableElement* pChildConfigurableElement = static_cast<const CConfigurableElement*>(getChild(uiIndex));
113
114 // Create corresponding child element
115 CXmlElement xmlChildConfigurableElementSettingsElement;
116
117 xmlConfigurationSettingsElementContent.createChild(xmlChildConfigurableElementSettingsElement, pChildConfigurableElement->getKind());
118
119 // Handle element name attribute
120 xmlChildConfigurableElementSettingsElement.setNameAttribute(pChildConfigurableElement->getName());
121
122 // Propagate
123 pChildConfigurableElement->serializeXmlSettings(xmlChildConfigurableElementSettingsElement, configurationAccessContext);
124 }
125 }
126 // Done
127 return true;
128 }
129
130 // AreaConfiguration creation
createAreaConfiguration(const CSyncerSet * pSyncerSet) const131 CAreaConfiguration* CConfigurableElement::createAreaConfiguration(const CSyncerSet* pSyncerSet) const
132 {
133 return new CAreaConfiguration(this, pSyncerSet);
134 }
135
136 // Parameter access
accessValue(CPathNavigator & pathNavigator,std::string & strValue,bool bSet,CParameterAccessContext & parameterAccessContext) const137 bool CConfigurableElement::accessValue(CPathNavigator& pathNavigator, std::string& strValue, bool bSet, CParameterAccessContext& parameterAccessContext) const
138 {
139 std::string* pStrChildName = pathNavigator.next();
140
141 if (!pStrChildName) {
142
143 parameterAccessContext.setError((bSet ? "Can't set " : "Can't get ") + pathNavigator.getCurrentPath() + " because it is not a parameter");
144
145 return false;
146 }
147
148 const CConfigurableElement* pChild = static_cast<const CConfigurableElement*>(findChild(*pStrChildName));
149
150 if (!pChild) {
151
152 parameterAccessContext.setError("Path not found: " + pathNavigator.getCurrentPath());
153
154 return false;
155 }
156
157 return pChild->accessValue(pathNavigator, strValue, bSet, parameterAccessContext);
158 }
159
getListOfElementsWithMapping(std::list<const CConfigurableElement * > & configurableElementPath) const160 void CConfigurableElement::getListOfElementsWithMapping(
161 std::list<const CConfigurableElement*>& configurableElementPath) const
162 {
163 // Check parent
164 const CElement* pParent = getParent();
165 if (isOfConfigurableElementType(pParent)) {
166
167 const CConfigurableElement* pConfigurableElement =
168 static_cast<const CConfigurableElement*>(pParent);
169
170 pConfigurableElement->getListOfElementsWithMapping(configurableElementPath);
171 }
172 }
173
174 // Used for simulation and virtual subsystems
setDefaultValues(CParameterAccessContext & parameterAccessContext) const175 void CConfigurableElement::setDefaultValues(CParameterAccessContext& parameterAccessContext) const
176 {
177 // Propagate to children
178 size_t uiIndex;
179 size_t uiNbChildren = getNbChildren();
180
181 for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
182
183 const CConfigurableElement* pConfigurableElement = static_cast<const CConfigurableElement*>(getChild(uiIndex));
184
185 pConfigurableElement->setDefaultValues(parameterAccessContext);
186 }
187 }
188
189 // Element properties
showProperties(std::string & strResult) const190 void CConfigurableElement::showProperties(std::string& strResult) const
191 {
192 base::showProperties(strResult);
193
194 strResult += "Total size: " + getFootprintAsString() + "\n";
195 }
196
197 // Offset
setOffset(uint32_t uiOffset)198 void CConfigurableElement::setOffset(uint32_t uiOffset)
199 {
200 // Assign offset locally
201 _uiOffset = uiOffset;
202
203 // Propagate to children
204 size_t uiIndex;
205 size_t uiNbChildren = getNbChildren();
206
207 for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
208
209 CConfigurableElement* pConfigurableElement = static_cast<CConfigurableElement*>(getChild(uiIndex));
210
211 pConfigurableElement->setOffset(uiOffset);
212
213 uiOffset += pConfigurableElement->getFootPrint();
214 }
215 }
216
getOffset() const217 uint32_t CConfigurableElement::getOffset() const
218 {
219 return _uiOffset;
220 }
221
222 // Memory
getFootPrint() const223 uint32_t CConfigurableElement::getFootPrint() const
224 {
225 uint32_t uiSize = 0;
226 size_t uiIndex;
227 size_t uiNbChildren = getNbChildren();
228
229 for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
230
231 const CConfigurableElement* pConfigurableElement = static_cast<const CConfigurableElement*>(getChild(uiIndex));
232
233 uiSize += pConfigurableElement->getFootPrint();
234 }
235
236 return uiSize;
237 }
238
239 // Browse parent path to find syncer
getSyncer() const240 ISyncer* CConfigurableElement::getSyncer() const
241 {
242 // Check parent
243 const CElement* pParent = getParent();
244
245 if (isOfConfigurableElementType(pParent)) {
246
247 return static_cast<const CConfigurableElement*>(pParent)->getSyncer();
248 }
249 return NULL;
250 }
251
252 // Syncer set (me, ascendant or descendant ones)
fillSyncerSet(CSyncerSet & syncerSet) const253 void CConfigurableElement::fillSyncerSet(CSyncerSet& syncerSet) const
254 {
255 // Try me or ascendants
256 ISyncer* pMineOrAscendantSyncer = getSyncer();
257
258 if (pMineOrAscendantSyncer) {
259
260 // Provide found syncer object
261 syncerSet += pMineOrAscendantSyncer;
262
263 // Done
264 return;
265 }
266 // Fetch descendant ones
267 fillSyncerSetFromDescendant(syncerSet);
268 }
269
270 // Syncer set (descendant)
fillSyncerSetFromDescendant(CSyncerSet & syncerSet) const271 void CConfigurableElement::fillSyncerSetFromDescendant(CSyncerSet& syncerSet) const
272 {
273 // Dig
274 size_t uiIndex;
275 size_t uiNbChildren = getNbChildren();
276
277 for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
278
279 const CConfigurableElement* pConfigurableElement = static_cast<const CConfigurableElement*>(getChild(uiIndex));
280
281 pConfigurableElement->fillSyncerSetFromDescendant(syncerSet);
282 }
283 }
284
285 // Configurable domain association
addAttachedConfigurableDomain(const CConfigurableDomain * pConfigurableDomain)286 void CConfigurableElement::addAttachedConfigurableDomain(const CConfigurableDomain* pConfigurableDomain)
287 {
288 _configurableDomainList.push_back(pConfigurableDomain);
289 }
290
removeAttachedConfigurableDomain(const CConfigurableDomain * pConfigurableDomain)291 void CConfigurableElement::removeAttachedConfigurableDomain(const CConfigurableDomain* pConfigurableDomain)
292 {
293 _configurableDomainList.remove(pConfigurableDomain);
294 }
295
296 // Belonging domain
belongsTo(const CConfigurableDomain * pConfigurableDomain) const297 bool CConfigurableElement::belongsTo(const CConfigurableDomain* pConfigurableDomain) const
298 {
299 if (containsConfigurableDomain(pConfigurableDomain)) {
300
301 return true;
302 }
303 return belongsToDomainAscending(pConfigurableDomain);
304 }
305
306 // Belonging domains
getBelongingDomains(std::list<const CConfigurableDomain * > & configurableDomainList) const307 void CConfigurableElement::getBelongingDomains(std::list<const CConfigurableDomain*>& configurableDomainList) const
308 {
309 configurableDomainList.insert(configurableDomainList.end(), _configurableDomainList.begin(), _configurableDomainList.end());
310
311 // Check parent
312 const CElement* pParent = getParent();
313
314 if (isOfConfigurableElementType(pParent)) {
315
316 static_cast<const CConfigurableElement*>(pParent)->getBelongingDomains(configurableDomainList);
317 }
318 }
319
listBelongingDomains(std::string & strResult,bool bVertical) const320 void CConfigurableElement::listBelongingDomains(std::string& strResult, bool bVertical) const
321 {
322 // Get belonging domain list
323 std::list<const CConfigurableDomain*> configurableDomainList;
324
325 getBelongingDomains(configurableDomainList);
326
327 // Fill list
328 listDomains(configurableDomainList, strResult, bVertical);
329 }
330
331 // Elements with no domains
listRogueElements(std::string & strResult) const332 void CConfigurableElement::listRogueElements(std::string& strResult) const
333 {
334 strResult = "\n";
335
336 // Get rogue element aggregate list (no associated domain)
337 std::list<const CConfigurableElement*> rogueElementList;
338
339 CConfigurableElementAggregator configurableElementAggregator(rogueElementList, &CConfigurableElement::hasNoDomainAssociated);
340
341 configurableElementAggregator.aggegate(this);
342
343 // Build list as std::string
344 std::list<const CConfigurableElement*>::const_iterator it;
345
346 for (it = rogueElementList.begin(); it != rogueElementList.end(); ++it) {
347
348 const CConfigurableElement* pConfigurableElement = *it;
349
350 strResult += pConfigurableElement->getPath() + "\n";
351 }
352 }
353
354 // Belonging to no domains
isRogue() const355 bool CConfigurableElement::isRogue() const
356 {
357 return !getBelongingDomainCount();
358 }
359
360 // Footprint as string
getFootprintAsString() const361 std::string CConfigurableElement::getFootprintAsString() const
362 {
363 // Get size as string
364 return CUtility::toString(getFootPrint()) + " byte(s)";
365 }
366
367 // Matching check for no domain association
hasNoDomainAssociated() const368 bool CConfigurableElement::hasNoDomainAssociated() const
369 {
370 return _configurableDomainList.empty();
371 }
372
373 // Matching check for no valid associated domains
hasNoValidDomainAssociated() const374 bool CConfigurableElement::hasNoValidDomainAssociated() const
375 {
376 if (_configurableDomainList.empty()) {
377
378 // No domains associated
379 return true;
380 }
381
382 ConfigurableDomainListConstIterator it;
383
384 // Browse all configurable domains for validity checking
385 for (it = _configurableDomainList.begin(); it != _configurableDomainList.end(); ++it) {
386
387 const CConfigurableDomain* pConfigurableDomain = *it;
388
389 if (pConfigurableDomain->isApplicableConfigurationValid(this)) {
390
391 return false;
392 }
393 }
394
395 return true;
396 }
397
398 // Owning domains
listAssociatedDomains(std::string & strResult,bool bVertical) const399 void CConfigurableElement::listAssociatedDomains(std::string& strResult, bool bVertical) const
400 {
401 // Fill list
402 listDomains(_configurableDomainList, strResult, bVertical);
403 }
404
getBelongingDomainCount() const405 size_t CConfigurableElement::getBelongingDomainCount() const
406 {
407 // Get belonging domain list
408 std::list<const CConfigurableDomain*> configurableDomainList;
409
410 getBelongingDomains(configurableDomainList);
411
412 return configurableDomainList.size();
413 }
414
listDomains(const std::list<const CConfigurableDomain * > & configurableDomainList,std::string & strResult,bool bVertical) const415 void CConfigurableElement::listDomains(const std::list<const CConfigurableDomain*>& configurableDomainList, std::string& strResult, bool bVertical) const
416 {
417 if (bVertical && configurableDomainList.empty()) {
418
419 strResult = "\n";
420 }
421
422 // Fill list
423 ConfigurableDomainListConstIterator it;
424 bool bFirst = true;
425
426 // Browse all configurable domains for comparison
427 for (it = configurableDomainList.begin(); it != configurableDomainList.end(); ++it) {
428
429 const CConfigurableDomain* pConfigurableDomain = *it;
430
431 if (!bVertical && !bFirst) {
432
433 strResult += ", ";
434 }
435
436 strResult += pConfigurableDomain->getName();
437
438 if (bVertical) {
439
440 strResult += "\n";
441 } else {
442
443 bFirst = false;
444 }
445 }
446 }
447
containsConfigurableDomain(const CConfigurableDomain * pConfigurableDomain) const448 bool CConfigurableElement::containsConfigurableDomain(const CConfigurableDomain* pConfigurableDomain) const
449 {
450 ConfigurableDomainListConstIterator it;
451
452 // Browse all configurable domains for comparison
453 for (it = _configurableDomainList.begin(); it != _configurableDomainList.end(); ++it) {
454
455 if (pConfigurableDomain == *it) {
456
457 return true;
458 }
459 }
460 return false;
461 }
462
463 // Belonging domain ascending search
belongsToDomainAscending(const CConfigurableDomain * pConfigurableDomain) const464 bool CConfigurableElement::belongsToDomainAscending(const CConfigurableDomain* pConfigurableDomain) const
465 {
466 // Check parent
467 const CElement* pParent = getParent();
468
469 if (isOfConfigurableElementType(pParent)) {
470
471 return static_cast<const CConfigurableElement*>(pParent)->belongsTo(pConfigurableDomain);
472 }
473 return false;
474 }
475
476 // Belonging subsystem
getBelongingSubsystem() const477 const CSubsystem* CConfigurableElement::getBelongingSubsystem() const
478 {
479 const CElement* pParent = getParent();
480
481 // Stop at system class
482 if (!pParent->getParent()) {
483
484 return NULL;
485 }
486
487 return static_cast<const CConfigurableElement*>(pParent)->getBelongingSubsystem();
488 }
489
490 // Check element is a parameter
isParameter() const491 bool CConfigurableElement::isParameter() const
492 {
493 return false;
494 }
495
496
497 // Check parent is still of current type (by structure knowledge)
isOfConfigurableElementType(const CElement * pParent) const498 bool CConfigurableElement::isOfConfigurableElementType(const CElement* pParent) const
499 {
500 assert(pParent);
501
502 // Up to system class
503 return !!pParent->getParent();
504 }
505