summaryrefslogtreecommitdiffstats
path: root/upstream/parameter/ConfigurableElement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'upstream/parameter/ConfigurableElement.cpp')
-rw-r--r--upstream/parameter/ConfigurableElement.cpp652
1 files changed, 652 insertions, 0 deletions
diff --git a/upstream/parameter/ConfigurableElement.cpp b/upstream/parameter/ConfigurableElement.cpp
new file mode 100644
index 0000000..615d72b
--- /dev/null
+++ b/upstream/parameter/ConfigurableElement.cpp
@@ -0,0 +1,652 @@
+/*
+ * 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 "Iterator.hpp"
+#include "Utility.h"
+#include "XmlParameterSerializingContext.h"
+#include <assert.h>
+
+#define base CElement
+
+CConfigurableElement::CConfigurableElement(const std::string &strName) : base(strName)
+{
+}
+
+bool CConfigurableElement::fromXml(const CXmlElement &xmlElement,
+ CXmlSerializingContext &serializingContext)
+{
+ auto &context = static_cast<CXmlParameterSerializingContext &>(serializingContext);
+ auto &accessContext = context.getAccessContext();
+
+ if (accessContext.serializeSettings()) {
+ // As serialization and deserialisation are handled through the *same* function
+ // the (de)serialize object can not be const in `serializeXmlSettings` signature.
+ // As a result a const_cast is unavoidable :(.
+ // Fixme: split serializeXmlSettings in two functions (in and out) to avoid the `const_cast`
+ return serializeXmlSettings(const_cast<CXmlElement &>(xmlElement),
+ static_cast<CConfigurationAccessContext &>(accessContext));
+ }
+ return structureFromXml(xmlElement, serializingContext);
+}
+
+void CConfigurableElement::toXml(CXmlElement &xmlElement,
+ CXmlSerializingContext &serializingContext) const
+{
+ auto &context = static_cast<CXmlParameterSerializingContext &>(serializingContext);
+ auto &accessContext = context.getAccessContext();
+ if (accessContext.serializeSettings()) {
+
+ serializeXmlSettings(xmlElement, static_cast<CConfigurationAccessContext &>(accessContext));
+ } else {
+
+ structureToXml(xmlElement, serializingContext);
+ }
+}
+
+// XML configuration settings parsing
+bool CConfigurableElement::serializeXmlSettings(
+ CXmlElement &xmlConfigurationSettingsElementContent,
+ CConfigurationAccessContext &configurationAccessContext) const
+{
+ 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 (size_t index = 0; index < uiNbChildren; index++) {
+
+ // Get child
+ const CConfigurableElement *pChildConfigurableElement =
+ static_cast<const CConfigurableElement *>(getChild(index));
+
+ if (!it.next(xmlChildConfigurableElementSettingsElement)) {
+
+ // Structure error
+ configurationAccessContext.setError(
+ "Configuration settings parsing: missing child node " +
+ pChildConfigurableElement->getXmlElementName() + " (name:" +
+ pChildConfigurableElement->getName() + ") in " + getName());
+
+ return false;
+ }
+
+ // Check element type matches in type
+ if (xmlChildConfigurableElementSettingsElement.getType() !=
+ pChildConfigurableElement->getXmlElementName()) {
+
+ // "Component" tag has been renamed to "ParameterBlock", but retro-compatibility
+ // shall be ensured.
+ //
+ // So checking if this case occurs, i.e. element name is "ParameterBlock"
+ // but xml setting name is "Component".
+ bool compatibilityCase =
+ (pChildConfigurableElement->getXmlElementName() == "ParameterBlock") &&
+ (xmlChildConfigurableElementSettingsElement.getType() == "Component");
+
+ // Error if the compatibility case does not occur.
+ if (!compatibilityCase) {
+
+ // Type error
+ configurationAccessContext.setError(
+ "Configuration settings parsing: Settings "
+ "for configurable element " +
+ pChildConfigurableElement->getQualifiedPath() +
+ " 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 element " +
+ getQualifiedPath() + ", 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: Unexpected xml element node " +
+ xmlChildConfigurableElementSettingsElement.getType() + " in " + getQualifiedPath());
+
+ return false;
+ }
+ } else {
+ // Handle element name attribute
+ xmlConfigurationSettingsElementContent.setNameAttribute(getName());
+
+ // Propagate to children
+ for (size_t index = 0; index < uiNbChildren; index++) {
+
+ const CConfigurableElement *pChildConfigurableElement =
+ static_cast<const CConfigurableElement *>(getChild(index));
+
+ // Create corresponding child element
+ CXmlElement xmlChildConfigurableElementSettingsElement;
+
+ xmlConfigurationSettingsElementContent.createChild(
+ xmlChildConfigurableElementSettingsElement,
+ pChildConfigurableElement->getXmlElementName());
+
+ // 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);
+}
+
+// Whole element access
+void CConfigurableElement::getSettingsAsBytes(std::vector<uint8_t> &bytes,
+ CParameterAccessContext &parameterAccessContext) const
+{
+ bytes.resize(getFootPrint());
+
+ parameterAccessContext.getParameterBlackboard()->readBytes(
+ bytes, getOffset() - parameterAccessContext.getBaseOffset());
+}
+
+bool CConfigurableElement::setSettingsAsBytes(const std::vector<uint8_t> &bytes,
+ CParameterAccessContext &parameterAccessContext) const
+{
+ CParameterBlackboard *pParameterBlackboard = parameterAccessContext.getParameterBlackboard();
+
+ // Size
+ size_t size = getFootPrint();
+
+ // Check sizes match
+ if (size != bytes.size()) {
+
+ parameterAccessContext.setError(std::string("Wrong size: Expected: ") +
+ std::to_string(size) + " Provided: " +
+ std::to_string(bytes.size()));
+
+ return false;
+ }
+
+ // Write bytes
+ pParameterBlackboard->writeBytes(bytes, getOffset() - parameterAccessContext.getBaseOffset());
+
+ if (not parameterAccessContext.getAutoSync()) {
+ // Auto sync is not activated, sync will be defered until an explicit request
+ return true;
+ }
+
+ CSyncerSet syncerSet;
+ fillSyncerSet(syncerSet);
+ core::Results res;
+ if (not syncerSet.sync(*parameterAccessContext.getParameterBlackboard(), false, &res)) {
+
+ parameterAccessContext.setError(utility::asString(res));
+ return false;
+ }
+ return true;
+}
+
+std::list<const CConfigurableElement *> CConfigurableElement::getConfigurableElementContext() const
+{
+ std::list<const CConfigurableElement *> configurableElementPath;
+
+ const CElement *element = this;
+ while (element != nullptr and isOfConfigurableElementType(element)) {
+ auto configurableElement = static_cast<const CConfigurableElement *>(element);
+
+ configurableElementPath.push_back(configurableElement);
+ element = element->getParent();
+ }
+
+ return configurableElementPath;
+}
+
+// Used for simulation and virtual subsystems
+void CConfigurableElement::setDefaultValues(CParameterAccessContext &parameterAccessContext) const
+{
+ // Propagate to children
+ size_t uiNbChildren = getNbChildren();
+
+ for (size_t index = 0; index < uiNbChildren; index++) {
+
+ const CConfigurableElement *pConfigurableElement =
+ static_cast<const CConfigurableElement *>(getChild(index));
+
+ pConfigurableElement->setDefaultValues(parameterAccessContext);
+ }
+}
+
+// Element properties
+void CConfigurableElement::showProperties(std::string &strResult) const
+{
+ base::showProperties(strResult);
+
+ strResult += "Total size: " + getFootprintAsString() + "\n";
+}
+
+std::string CConfigurableElement::logValue(utility::ErrorContext &context) const
+{
+ return logValue(static_cast<CParameterAccessContext &>(context));
+}
+
+std::string CConfigurableElement::logValue(CParameterAccessContext & /*ctx*/) const
+{
+ // By default, an element does not have a value. Only leaf elements have
+ // one. This method could be pure virtual but then, several derived classes
+ // would need to implement it in order to simply return an empty string.
+ return "";
+}
+
+// Offset
+void CConfigurableElement::setOffset(size_t offset)
+{
+ // Assign offset locally
+ _offset = offset;
+
+ // Propagate to children
+ size_t uiNbChildren = getNbChildren();
+
+ for (size_t index = 0; index < uiNbChildren; index++) {
+
+ CConfigurableElement *pConfigurableElement =
+ static_cast<CConfigurableElement *>(getChild(index));
+
+ pConfigurableElement->setOffset(offset);
+
+ offset += pConfigurableElement->getFootPrint();
+ }
+}
+
+size_t CConfigurableElement::getOffset() const
+{
+ return _offset;
+}
+
+// Memory
+size_t CConfigurableElement::getFootPrint() const
+{
+ size_t uiSize = 0;
+ size_t uiNbChildren = getNbChildren();
+
+ for (size_t index = 0; index < uiNbChildren; index++) {
+
+ const CConfigurableElement *pConfigurableElement =
+ static_cast<const CConfigurableElement *>(getChild(index));
+
+ 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 uiNbChildren = getNbChildren();
+
+ for (size_t index = 0; index < uiNbChildren; index++) {
+
+ const CConfigurableElement *pConfigurableElement =
+ static_cast<const CConfigurableElement *>(getChild(index));
+
+ 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
+{
+ // 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";
+ }
+}
+
+bool CConfigurableElement::isRogue() const
+{
+ // Check not belonging to any domin from current level and towards ascendents
+ if (getBelongingDomainCount() != 0) {
+
+ return false;
+ }
+
+ // Get a list of elements (current + descendants) with no domains associated
+ std::list<const CConfigurableElement *> rogueElementList;
+
+ CConfigurableElementAggregator agregator(rogueElementList,
+ &CConfigurableElement::hasNoDomainAssociated);
+
+ agregator.aggegate(this);
+
+ // Check only one element found which ought to be current one
+ return (rogueElementList.size() == 1) && (rogueElementList.front() == this);
+}
+
+// Footprint as string
+std::string CConfigurableElement::getFootprintAsString() const
+{
+ // Get size as string
+ return std::to_string(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
+{
+ // 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();
+}