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