Support context mapping at Subsystem level

BZ: 176942

Add a class (ConfigurableMappingElement) handling the mapping; to be derived by
all classes that can contain mapping.  ConfigurableMappingElement derives from
ConfigurableElement.  Until now, the only child of ConfigurableElement that
could have mapping was InstanceConfigurableElement (through TypeElement, that
contains all information related to its type).

Now, both InstanceConfigurableElement and Subsystem derive from
ConfigurableMappingElement.  That way, Subsystem XML elements can now have a
"Mapping" attribute, propagated to all Elements in the tree.  The Subsystem.xsd
schema is updated in that regard.

Only context mapping is relevant at the Subsystem-level (as opposed to
instantiation mapping).  If an instantiation mapping is set in the Subsystem,
it is silently ignored.

Change-Id: I3c09959bc5e3d18c5a4d354e498d69cc5489a247
Signed-off-by: David Wagner <david.wagner@intel.com>
Signed-off-by: Mattijs Korpershoek <mattijsx.korpershoek@intel.com>
diff --git a/parameter/Subsystem.cpp b/parameter/Subsystem.cpp
index d4bc7c8..9a550d5 100644
--- a/parameter/Subsystem.cpp
+++ b/parameter/Subsystem.cpp
@@ -38,9 +38,9 @@
 #include <assert.h>
 #include <sstream>
 
-#define base CConfigurableElement
+#define base CConfigurableElementWithMapping
 
-CSubsystem::CSubsystem(const string& strName) : base(strName), _pComponentLibrary(new CComponentLibrary), _pInstanceDefinition(new CInstanceDefinition), _bBigEndian(false)
+CSubsystem::CSubsystem(const string& strName) : base(strName), _pComponentLibrary(new CComponentLibrary), _pInstanceDefinition(new CInstanceDefinition), _bBigEndian(false), _pMappingData(NULL)
 {
     // Note: A subsystem contains instance components
     // InstanceDefintion and ComponentLibrary objects are then not chosen to be children
@@ -68,6 +68,8 @@
     // Order matters!
     delete _pInstanceDefinition;
     delete _pComponentLibrary;
+
+    delete _pMappingData;
 }
 
 string CSubsystem::getKind() const
@@ -106,6 +108,16 @@
 
     CXmlElement childElement;
 
+    // Manage mapping attribute
+    if (xmlElement.hasAttribute("Mapping")) {
+
+        _pMappingData = new CMappingData;
+        if (!_pMappingData->fromXml(xmlElement, serializingContext)) {
+
+            return false;
+        }
+    }
+
     // XML populate ComponentLibrary
     xmlElement.getChildElement("ComponentLibrary", childElement);
 
@@ -152,7 +164,11 @@
 bool CSubsystem::mapSubsystemElements(string& strError)
 {
     // Default mapping context
-    _contextStack.push(CMappingContext(_contextMappingKeyArray.size()));
+    CMappingContext context(_contextMappingKeyArray.size());
+    // Add Subsystem-level mapping data, which will be propagated to all children
+    handleMappingContext(this, context, strError);
+
+    _contextStack.push(context);
 
     // Map all instantiated subelements in subsystem
     uint32_t uiNbChildren = getNbChildren();
@@ -326,20 +342,30 @@
 }
 
 // Generic error handling from derived subsystem classes
-string CSubsystem::getMappingError(const string& strKey,
-                                   const string& strMessage,
-                                   const CInstanceConfigurableElement* pInstanceConfigurableElement)
-const
+string CSubsystem::getMappingError(
+        const string& strKey,
+        const string& strMessage,
+        const CConfigurableElementWithMapping* pConfigurableElementWithMapping) const
 {
     return getName() + " " + getKind() + " " +
             "mapping:\n" + strKey + " " +
             "error: \"" + strMessage + "\" " +
-            "for element " + pInstanceConfigurableElement->getPath();
+            "for element " + pConfigurableElementWithMapping->getPath();
+}
+
+
+bool CSubsystem::getMappingData(const std::string& strKey, const std::string*& pStrValue) const
+{
+    if (_pMappingData) {
+
+        return _pMappingData->getValue(strKey, pStrValue);
+    }
+    return false;
 }
 
 // Mapping generic context handling
 bool CSubsystem::handleMappingContext(
-        const CInstanceConfigurableElement* pInstanceConfigurableElement,
+        const CConfigurableElementWithMapping* pConfigurableElementWithMapping,
         CMappingContext& context,
         string& strError) const
 {
@@ -351,11 +377,11 @@
         const string& strKey = _contextMappingKeyArray[uiItem];
         const string* pStrValue;
 
-        if (pInstanceConfigurableElement->getMappingData(strKey, pStrValue)) {
+        if (pConfigurableElementWithMapping->getMappingData(strKey, pStrValue)) {
             // Assign item to context
             if (!context.setItem(uiItem, &strKey, pStrValue)) {
 
-                strError = getMappingError(strKey, "Already set", pInstanceConfigurableElement);
+                strError = getMappingError(strKey, "Already set", pConfigurableElementWithMapping);
 
                 return false;
             }