blob: 08a01223a7295024e1b928297247f07bea0a278e [file] [log] [blame]
/*
* Copyright (c) 2011-2015, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ConfigurableElement.h"
#include "MappingData.h"
#include "SyncerSet.h"
#include "ConfigurableDomain.h"
#include "ConfigurationAccessContext.h"
#include "ConfigurableElementAggregator.h"
#include "AreaConfiguration.h"
#include "Utility.h"
#include <assert.h>
#define base CElement
CConfigurableElement::CConfigurableElement(const std::string& strName) : base(strName), _uiOffset(0)
{
}
CConfigurableElement::~CConfigurableElement()
{
}
// XML configuration settings parsing
bool CConfigurableElement::serializeXmlSettings(CXmlElement& xmlConfigurationSettingsElementContent, CConfigurationAccessContext& configurationAccessContext) const
{
size_t uiIndex;
size_t uiNbChildren = getNbChildren();
if (!configurationAccessContext.serializeOut()) {
// Just do basic checks and propagate to children
CXmlElement::CChildIterator it(xmlConfigurationSettingsElementContent);
CXmlElement xmlChildConfigurableElementSettingsElement;
// Propagate to children
for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
// Get child
const CConfigurableElement* pChildConfigurableElement = static_cast<const CConfigurableElement*>(getChild(uiIndex));
if (!it.next(xmlChildConfigurableElementSettingsElement)) {
// Structure error
configurationAccessContext.setError("Configuration settings parsing: Settings don't conform to structure of configurable element " + getName());
return false;
}
// Check element type matches in type
if (xmlChildConfigurableElementSettingsElement.getType() != pChildConfigurableElement->getKind()) {
// Type error
configurationAccessContext.setError("Configuration settings parsing: Settings for configurable element " + pChildConfigurableElement->getName() + " does not match expected type: " + xmlChildConfigurableElementSettingsElement.getType() + " instead of " + pChildConfigurableElement->getKind());
return false;
}
// Check element type matches in name
if (xmlChildConfigurableElementSettingsElement.getNameAttribute() != pChildConfigurableElement->getName()) {
// Name error
configurationAccessContext.setError("Configuration settings parsing: Under configurable elememnt " + getName() + ", expected element name " + pChildConfigurableElement->getName() + " but found " + xmlChildConfigurableElementSettingsElement.getNameAttribute() + " instead");
return false;
}
// Parse child configurable element's settings
if (!pChildConfigurableElement->serializeXmlSettings(xmlChildConfigurableElementSettingsElement, configurationAccessContext)) {
return false;
}
}
// There should remain no configurable element to parse
if (it.next(xmlChildConfigurableElementSettingsElement)) {
// Structure error
configurationAccessContext.setError("Configuration settings parsing: Settings don't conform to structure of configurable element " + getName());
return false;
}
} else {
// Propagate to children
for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
const CConfigurableElement* pChildConfigurableElement = static_cast<const CConfigurableElement*>(getChild(uiIndex));
// Create corresponding child element
CXmlElement xmlChildConfigurableElementSettingsElement;
xmlConfigurationSettingsElementContent.createChild(xmlChildConfigurableElementSettingsElement, pChildConfigurableElement->getKind());
// Handle element name attribute
xmlChildConfigurableElementSettingsElement.setNameAttribute(pChildConfigurableElement->getName());
// Propagate
pChildConfigurableElement->serializeXmlSettings(xmlChildConfigurableElementSettingsElement, configurationAccessContext);
}
}
// Done
return true;
}
// AreaConfiguration creation
CAreaConfiguration* CConfigurableElement::createAreaConfiguration(const CSyncerSet* pSyncerSet) const
{
return new CAreaConfiguration(this, pSyncerSet);
}
// Parameter access
bool CConfigurableElement::accessValue(CPathNavigator& pathNavigator, std::string& strValue, bool bSet, CParameterAccessContext& parameterAccessContext) const
{
std::string* pStrChildName = pathNavigator.next();
if (!pStrChildName) {
parameterAccessContext.setError((bSet ? "Can't set " : "Can't get ") + pathNavigator.getCurrentPath() + " because it is not a parameter");
return false;
}
const CConfigurableElement* pChild = static_cast<const CConfigurableElement*>(findChild(*pStrChildName));
if (!pChild) {
parameterAccessContext.setError("Path not found: " + pathNavigator.getCurrentPath());
return false;
}
return pChild->accessValue(pathNavigator, strValue, bSet, parameterAccessContext);
}
void CConfigurableElement::getListOfElementsWithMapping(
std::list<const CConfigurableElement*>& configurableElementPath) const
{
// Check parent
const CElement* pParent = getParent();
if (isOfConfigurableElementType(pParent)) {
const CConfigurableElement* pConfigurableElement =
static_cast<const CConfigurableElement*>(pParent);
pConfigurableElement->getListOfElementsWithMapping(configurableElementPath);
}
}
// Used for simulation and virtual subsystems
void CConfigurableElement::setDefaultValues(CParameterAccessContext& parameterAccessContext) const
{
// Propagate to children
size_t uiIndex;
size_t uiNbChildren = getNbChildren();
for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
const CConfigurableElement* pConfigurableElement = static_cast<const CConfigurableElement*>(getChild(uiIndex));
pConfigurableElement->setDefaultValues(parameterAccessContext);
}
}
// Element properties
void CConfigurableElement::showProperties(std::string& strResult) const
{
base::showProperties(strResult);
strResult += "Total size: " + getFootprintAsString() + "\n";
}
// Offset
void CConfigurableElement::setOffset(uint32_t uiOffset)
{
// Assign offset locally
_uiOffset = uiOffset;
// Propagate to children
size_t uiIndex;
size_t uiNbChildren = getNbChildren();
for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
CConfigurableElement* pConfigurableElement = static_cast<CConfigurableElement*>(getChild(uiIndex));
pConfigurableElement->setOffset(uiOffset);
uiOffset += pConfigurableElement->getFootPrint();
}
}
uint32_t CConfigurableElement::getOffset() const
{
return _uiOffset;
}
// Memory
uint32_t CConfigurableElement::getFootPrint() const
{
uint32_t uiSize = 0;
size_t uiIndex;
size_t uiNbChildren = getNbChildren();
for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
const CConfigurableElement* pConfigurableElement = static_cast<const CConfigurableElement*>(getChild(uiIndex));
uiSize += pConfigurableElement->getFootPrint();
}
return uiSize;
}
// Browse parent path to find syncer
ISyncer* CConfigurableElement::getSyncer() const
{
// Check parent
const CElement* pParent = getParent();
if (isOfConfigurableElementType(pParent)) {
return static_cast<const CConfigurableElement*>(pParent)->getSyncer();
}
return NULL;
}
// Syncer set (me, ascendant or descendant ones)
void CConfigurableElement::fillSyncerSet(CSyncerSet& syncerSet) const
{
// Try me or ascendants
ISyncer* pMineOrAscendantSyncer = getSyncer();
if (pMineOrAscendantSyncer) {
// Provide found syncer object
syncerSet += pMineOrAscendantSyncer;
// Done
return;
}
// Fetch descendant ones
fillSyncerSetFromDescendant(syncerSet);
}
// Syncer set (descendant)
void CConfigurableElement::fillSyncerSetFromDescendant(CSyncerSet& syncerSet) const
{
// Dig
size_t uiIndex;
size_t uiNbChildren = getNbChildren();
for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {
const CConfigurableElement* pConfigurableElement = static_cast<const CConfigurableElement*>(getChild(uiIndex));
pConfigurableElement->fillSyncerSetFromDescendant(syncerSet);
}
}
// Configurable domain association
void CConfigurableElement::addAttachedConfigurableDomain(const CConfigurableDomain* pConfigurableDomain)
{
_configurableDomainList.push_back(pConfigurableDomain);
}
void CConfigurableElement::removeAttachedConfigurableDomain(const CConfigurableDomain* pConfigurableDomain)
{
_configurableDomainList.remove(pConfigurableDomain);
}
// Belonging domain
bool CConfigurableElement::belongsTo(const CConfigurableDomain* pConfigurableDomain) const
{
if (containsConfigurableDomain(pConfigurableDomain)) {
return true;
}
return belongsToDomainAscending(pConfigurableDomain);
}
// Belonging domains
void CConfigurableElement::getBelongingDomains(std::list<const CConfigurableDomain*>& configurableDomainList) const
{
configurableDomainList.insert(configurableDomainList.end(), _configurableDomainList.begin(), _configurableDomainList.end());
// Check parent
const CElement* pParent = getParent();
if (isOfConfigurableElementType(pParent)) {
static_cast<const CConfigurableElement*>(pParent)->getBelongingDomains(configurableDomainList);
}
}
void CConfigurableElement::listBelongingDomains(std::string& strResult, bool bVertical) const
{
// Get belonging domain list
std::list<const CConfigurableDomain*> configurableDomainList;
getBelongingDomains(configurableDomainList);
// Fill list
listDomains(configurableDomainList, strResult, bVertical);
}
// Elements with no domains
void CConfigurableElement::listRogueElements(std::string& strResult) const
{
strResult = "\n";
// Get rogue element aggregate list (no associated domain)
std::list<const CConfigurableElement*> rogueElementList;
CConfigurableElementAggregator configurableElementAggregator(rogueElementList, &CConfigurableElement::hasNoDomainAssociated);
configurableElementAggregator.aggegate(this);
// Build list as std::string
std::list<const CConfigurableElement*>::const_iterator it;
for (it = rogueElementList.begin(); it != rogueElementList.end(); ++it) {
const CConfigurableElement* pConfigurableElement = *it;
strResult += pConfigurableElement->getPath() + "\n";
}
}
// Belonging to no domains
bool CConfigurableElement::isRogue() const
{
return !getBelongingDomainCount();
}
// Footprint as string
std::string CConfigurableElement::getFootprintAsString() const
{
// Get size as string
return CUtility::toString(getFootPrint()) + " byte(s)";
}
// Matching check for no domain association
bool CConfigurableElement::hasNoDomainAssociated() const
{
return _configurableDomainList.empty();
}
// Matching check for no valid associated domains
bool CConfigurableElement::hasNoValidDomainAssociated() const
{
if (_configurableDomainList.empty()) {
// No domains associated
return true;
}
ConfigurableDomainListConstIterator it;
// Browse all configurable domains for validity checking
for (it = _configurableDomainList.begin(); it != _configurableDomainList.end(); ++it) {
const CConfigurableDomain* pConfigurableDomain = *it;
if (pConfigurableDomain->isApplicableConfigurationValid(this)) {
return false;
}
}
return true;
}
// Owning domains
void CConfigurableElement::listAssociatedDomains(std::string& strResult, bool bVertical) const
{
// Fill list
listDomains(_configurableDomainList, strResult, bVertical);
}
size_t CConfigurableElement::getBelongingDomainCount() const
{
// Get belonging domain list
std::list<const CConfigurableDomain*> configurableDomainList;
getBelongingDomains(configurableDomainList);
return configurableDomainList.size();
}
void CConfigurableElement::listDomains(const std::list<const CConfigurableDomain*>& configurableDomainList, std::string& strResult, bool bVertical) const
{
if (bVertical && configurableDomainList.empty()) {
strResult = "\n";
}
// Fill list
ConfigurableDomainListConstIterator it;
bool bFirst = true;
// Browse all configurable domains for comparison
for (it = configurableDomainList.begin(); it != configurableDomainList.end(); ++it) {
const CConfigurableDomain* pConfigurableDomain = *it;
if (!bVertical && !bFirst) {
strResult += ", ";
}
strResult += pConfigurableDomain->getName();
if (bVertical) {
strResult += "\n";
} else {
bFirst = false;
}
}
}
bool CConfigurableElement::containsConfigurableDomain(const CConfigurableDomain* pConfigurableDomain) const
{
ConfigurableDomainListConstIterator it;
// Browse all configurable domains for comparison
for (it = _configurableDomainList.begin(); it != _configurableDomainList.end(); ++it) {
if (pConfigurableDomain == *it) {
return true;
}
}
return false;
}
// Belonging domain ascending search
bool CConfigurableElement::belongsToDomainAscending(const CConfigurableDomain* pConfigurableDomain) const
{
// Check parent
const CElement* pParent = getParent();
if (isOfConfigurableElementType(pParent)) {
return static_cast<const CConfigurableElement*>(pParent)->belongsTo(pConfigurableDomain);
}
return false;
}
// Belonging subsystem
const CSubsystem* CConfigurableElement::getBelongingSubsystem() const
{
const CElement* pParent = getParent();
// Stop at system class
if (!pParent->getParent()) {
return NULL;
}
return static_cast<const CConfigurableElement*>(pParent)->getBelongingSubsystem();
}
// Check element is a parameter
bool CConfigurableElement::isParameter() const
{
return false;
}
// Check parent is still of current type (by structure knowledge)
bool CConfigurableElement::isOfConfigurableElementType(const CElement* pParent) const
{
assert(pParent);
// Up to system class
return !!pParent->getParent();
}