In structure XML files, implement component library files inclusion

BZ: 168727

In the PFW structure file, it is not possible to include a component
library from another XML file.

Implement the possibility to import component from another XML file
that would be included in a structure XML file and that would
describe a component library.

Change-Id: Id6125140de1c8e9882375d01199f695b929f45e2
Signed-off-by: Guillaume Denneulin <guillaume.denneulin@intel.com>
diff --git a/Schemas/ComponentLibrary.xsd b/Schemas/ComponentLibrary.xsd
new file mode 100644
index 0000000..09d2e27
--- /dev/null
+++ b/Schemas/ComponentLibrary.xsd
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2005/08/xml.xsd"/>
+    <xs:include schemaLocation="ComponentTypeSet.xsd"/>
+    <xs:element name="ComponentLibrary" type="ComponentTypeSetType">
+        <xs:key name="ComponentTypeUniqueness">
+            <xs:selector xpath=".//ComponentType"/>
+            <xs:field xpath="@Name"/>
+        </xs:key>
+        <xs:keyref name="ComponentTypeNotFound" refer="ComponentTypeUniqueness">
+            <xs:selector xpath=".//ComponentType/Component"/>
+            <xs:field xpath="@Type"/>
+        </xs:keyref>
+    </xs:element>
+</xs:schema>
diff --git a/Schemas/ComponentTypeSet.xsd b/Schemas/ComponentTypeSet.xsd
new file mode 100644
index 0000000..d00be00
--- /dev/null
+++ b/Schemas/ComponentTypeSet.xsd
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2005/08/xml.xsd"/>
+    <xs:include schemaLocation="Parameter.xsd"/>
+    <xs:complexType name="ComponentType">
+        <xs:sequence>
+            <xs:sequence maxOccurs="unbounded">
+                <xs:group ref="ParameterBlockGroup"/>
+            </xs:sequence>
+        </xs:sequence>
+        <xs:attributeGroup ref="Nameable"/>
+        <xs:attribute name="Extends" use="optional"/>
+        <xs:attribute name="Mapping" use="optional"/>
+    </xs:complexType>
+    <xs:group name="ComponentTypeSetGroup">
+        <xs:choice>
+            <xs:element name="ComponentLibrary" type="ComponentTypeSetType"/>
+            <xs:element name="ComponentTypeSet" type="ComponentTypeSetType"/>
+            <xs:element name="ComponentType" type="ComponentType">
+                <xs:unique name="ComponentTypeSubElementsUniqueness">
+                    <xs:selector xpath="*"/>
+                    <xs:field xpath="@Name"/>
+                </xs:unique>
+            </xs:element>
+        </xs:choice>
+    </xs:group>
+    <xs:complexType name="ComponentTypeSetType">
+        <xs:sequence>
+            <xs:group ref="ComponentTypeSetGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute ref="xml:base"/>
+    </xs:complexType>
+    <xs:element name="ComponentTypeSet" type="ComponentTypeSetType">
+        <xs:unique name="ComponentTypeUniquenessInComponentTypeSet">
+            <xs:selector xpath=".//ComponentType"/>
+            <xs:field xpath="@Name"/>
+        </xs:unique>
+    </xs:element>
+</xs:schema>
diff --git a/Schemas/Parameter.xsd b/Schemas/Parameter.xsd
index ad3d739..3b635fc 100644
--- a/Schemas/Parameter.xsd
+++ b/Schemas/Parameter.xsd
@@ -4,6 +4,14 @@
 		<xs:attribute name="Name" type="xs:NMTOKEN" use="required"/>

 		<xs:attribute name="Description" type="xs:string" use="optional"/>

 	</xs:attributeGroup>

+	<xs:attributeGroup name="TypedNameable">

+		<xs:attributeGroup ref="Nameable"/>

+		<xs:attribute name="Type" type="xs:NMTOKEN" use="required"/>

+	</xs:attributeGroup>

+	<xs:complexType name="ComponentInstance">

+		<xs:attributeGroup ref="TypedNameable"/>

+		<xs:attribute name="Mapping" use="optional"/>

+	</xs:complexType>

 	<xs:simpleType name="SizeType">

 		<xs:restriction base="xs:positiveInteger">

 			<xs:pattern value="8|16|32"/>

diff --git a/Schemas/Subsystem.xsd b/Schemas/Subsystem.xsd
index aa2c35c..ab0fdf6 100644
--- a/Schemas/Subsystem.xsd
+++ b/Schemas/Subsystem.xsd
@@ -1,39 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>

 <!--W3C Schema generated by XMLSpy v2007 (http://www.altova.com)-->

 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

-	<xs:include schemaLocation="Parameter.xsd"/>

-	<xs:attributeGroup name="TypedNameable">

-		<xs:attributeGroup ref="Nameable"/>

-		<xs:attribute name="Type" type="xs:NMTOKEN" use="required"/>

-	</xs:attributeGroup>

-	<xs:complexType name="ComponentInstance">

-		<xs:attributeGroup ref="TypedNameable"/>

-		<xs:attribute name="Mapping" use="optional"/>

-	</xs:complexType>

-	<xs:complexType name="ComponentType">

-		<xs:sequence>

-			<xs:sequence maxOccurs="unbounded">

-				<xs:group ref="ParameterBlockGroup"/>

-			</xs:sequence>

-		</xs:sequence>

-		<xs:attributeGroup ref="Nameable"/>

-		<xs:attribute name="Extends" use="optional"/>

-		<xs:attribute name="Mapping" use="optional"/>

-	</xs:complexType>

+	<xs:include schemaLocation="ComponentLibrary.xsd"/>

 	<xs:complexType name="SubsystemType">

 		<xs:sequence>

-			<xs:element name="ComponentLibrary">

-				<xs:complexType>

-					<xs:sequence>

-						<xs:element name="ComponentType" type="ComponentType" minOccurs="0" maxOccurs="unbounded">

-							<xs:unique name="ComponentTypeSubElementsUniqueness">

-								<xs:selector xpath="*"/>

-								<xs:field xpath="@Name"/>

-							</xs:unique>

-						</xs:element>

-					</xs:sequence>

-				</xs:complexType>

-			</xs:element>

+			<xs:element ref="ComponentLibrary"/>

 			<xs:element name="InstanceDefinition">

 				<xs:complexType>

 					<xs:sequence>

@@ -60,21 +31,9 @@
 		<xs:attribute name="Type" use="required"/>

 	</xs:complexType>

 	<xs:element name="Subsystem" type="SubsystemType">

-		<xs:key name="ComponentTypeUniqueness">

-			<xs:selector xpath="ComponentLibrary/ComponentType"/>

-			<xs:field xpath="@Name"/>

-		</xs:key>

 		<xs:keyref name="InstanceDefinitionComponentTypeNotFound" refer="ComponentTypeUniqueness">

 			<xs:selector xpath="InstanceDefinition/Component"/>

 			<xs:field xpath="@Type"/>

-		</xs:keyref>		

-		<xs:keyref name="ComponentTypeNotFound" refer="ComponentTypeUniqueness">

-			<xs:selector xpath="ComponentLibrary/ComponentType/Component"/>

-			<xs:field xpath="@Type"/>

-		</xs:keyref>		

-		<!--xs:keyref name="ExtendedComponentTypeNotFound" refer="ComponentTypeUniqueness">

-			<xs:selector xpath="ComponentLibrary/ComponentType"/>

-			<xs:field xpath="@Extends"/>

-		</xs:keyref-->		

+		</xs:keyref>

 	</xs:element>

 </xs:schema>

diff --git a/parameter/ComponentLibrary.cpp b/parameter/ComponentLibrary.cpp
index f133213..f3576e8 100644
--- a/parameter/ComponentLibrary.cpp
+++ b/parameter/ComponentLibrary.cpp
@@ -45,3 +45,35 @@
     return static_cast<const CComponentType*>(findChild(strName));
 }
 
+bool CComponentLibrary::fromXml(const CXmlElement& xmlElement,
+                                CXmlSerializingContext& serializingContext)
+{
+    CXmlElement childElement;
+
+    CXmlElement::CChildIterator it(xmlElement);
+
+    // XML populate all component libraries
+    while (it.next(childElement)) {
+
+        // Filter component library/type set elements
+        if (childElement.getType() == "ComponentLibrary" ||
+            childElement.getType() == "ComponentTypeSet") {
+
+            if (!fromXml(childElement, serializingContext)) {
+
+                return false;
+            }
+        } else {
+            // Regular child creation and populating
+            CElement* pChild = createChild(childElement, serializingContext);
+
+            if (!pChild || !pChild->fromXml(childElement, serializingContext)) {
+
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
diff --git a/parameter/ComponentLibrary.h b/parameter/ComponentLibrary.h
index 443d634..835373b 100644
--- a/parameter/ComponentLibrary.h
+++ b/parameter/ComponentLibrary.h
@@ -38,6 +38,10 @@
     const CComponentType* getComponentType(const string& strName) const;
 
     virtual string getKind() const;
+
+    // From IXmlSink
+    virtual bool fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext);
+
 private:
     virtual bool childrenAreDynamic() const;
 };
diff --git a/parameter/Element.cpp b/parameter/Element.cpp
index b68205b..43f1c57 100755
--- a/parameter/Element.cpp
+++ b/parameter/Element.cpp
@@ -263,15 +263,9 @@
 
         } else {
             // Child needs creation
-            pChild = elementSerializingContext.getElementLibrary()->createElement(childElement);
+            pChild = createChild(childElement, serializingContext);
 
-            if (pChild) {
-
-                // Store created child!
-                addChild(pChild);
-            } else {
-
-                elementSerializingContext.setError("Unable to create XML element " + childElement.getPath());
+            if (!pChild) {
 
                 return false;
             }
@@ -403,6 +397,29 @@
     return _childArray[uiNbChildren - 1];
 }
 
+CElement* CElement::createChild(const CXmlElement& childElement,
+                                CXmlSerializingContext& serializingContext)
+{
+    // Context
+    CXmlElementSerializingContext& elementSerializingContext =
+            static_cast<CXmlElementSerializingContext&>(serializingContext);
+
+    // Child needs creation
+    CElement* pChild = elementSerializingContext.getElementLibrary()->createElement(childElement);
+
+    if (!pChild) {
+
+        elementSerializingContext.setError(
+                    "Unable to create XML element " + childElement.getPath());
+
+        return NULL;
+    }
+    // Store created child!
+    addChild(pChild);
+
+    return pChild;
+}
+
 bool CElement::removeChild(CElement* pChild)
 {
     ChildArrayIterator it;
diff --git a/parameter/Element.h b/parameter/Element.h
index b381898..01e4254 100644
--- a/parameter/Element.h
+++ b/parameter/Element.h
@@ -120,6 +120,18 @@
     CElement* findAscendantOfKind(const string& strKind);
     CElement* getRoot();
     const CElement* getRoot() const;
+
+    /**
+     * Creates a child CElement from a child XML Element
+     *
+     * @param[in] childElement the XML element to create CElement from
+     * @param[in] elementSerializingContext the serializing context
+     *
+     * @return child a pointer on the CElement object that has been added to the tree
+     */
+    CElement* createChild(const CXmlElement& childElement,
+                          CXmlSerializingContext& elementSerializingContext);
+
 private:
     // Logging (done by root)
     virtual void doLog(bool bIsWarning, const string& strLog) const;
diff --git a/xmlserializer/XmlFileDocSource.cpp b/xmlserializer/XmlFileDocSource.cpp
index 4df2ad1..53e7c86 100644
--- a/xmlserializer/XmlFileDocSource.cpp
+++ b/xmlserializer/XmlFileDocSource.cpp
@@ -24,6 +24,7 @@
 
 #include "XmlFileDocSource.h"
 #include <libxml/parser.h>
+#include <libxml/xinclude.h>
 
 #define base CXmlDocSource
 
@@ -32,7 +33,7 @@
                                      const string& strRootElementType,
                                      const string& strRootElementName,
                                      const string& strNameAttrituteName) :
-        base(xmlReadFile(strXmlInstanceFile.c_str(),NULL, 0),
+        base(readFile(strXmlInstanceFile),
              strXmlSchemaFile,
              strRootElementType,
              strRootElementName,
@@ -44,7 +45,7 @@
 CXmlFileDocSource::CXmlFileDocSource(const string& strXmlInstanceFile,
                                      const string& strXmlSchemaFile,
                                      const string& strRootElementType) :
-        base(xmlReadFile(strXmlInstanceFile.c_str(), NULL, 0),
+        base(readFile(strXmlInstanceFile),
              strXmlSchemaFile,
              strRootElementType),
         _strXmlInstanceFile(strXmlInstanceFile)
@@ -66,7 +67,7 @@
 
 bool CXmlFileDocSource::populate(CXmlSerializingContext& serializingContext)
 {
-    if (!base::validate(serializingContext)) {
+    if (!validate(serializingContext)) {
 
         // Add the file's name in the error message
         serializingContext.appendLineToError("File : " + _strXmlInstanceFile);
@@ -76,3 +77,23 @@
 
     return true;
 }
+
+_xmlDoc* CXmlFileDocSource::readFile(const string& strFileName)
+{
+    // Read xml file
+    xmlDocPtr pDoc = xmlReadFile(strFileName.c_str(), NULL, 0);
+
+    if (!pDoc) {
+
+        return NULL;
+    }
+    // Process file inclusion
+    // WARNING: this symbol is available if libxml2 has been compiled with LIBXML_XINCLUDE_ENABLED
+    if (xmlXIncludeProcess(pDoc) < 0) {
+
+        xmlFreeDoc(pDoc);
+        return NULL;
+    }
+
+    return pDoc;
+}
diff --git a/xmlserializer/XmlFileDocSource.h b/xmlserializer/XmlFileDocSource.h
index 98ba6e3..1efafe2 100644
--- a/xmlserializer/XmlFileDocSource.h
+++ b/xmlserializer/XmlFileDocSource.h
@@ -73,6 +73,17 @@
     virtual bool isParsable(CXmlSerializingContext& serializingContext) const;
 
 private:
+    /**
+     * Read xml file
+     *
+     * This function reads an xml file and processes eventual included files
+     * WARNING: to compile this function, libxml2 has to be compiled with LIBXML_XINCLUDE_ENABLED
+     *
+     * @param[in] strFileName the file name
+     *
+     * @return a pointer to generated xml document object
+     */
+    static _xmlDoc* readFile(const string& strFileName);
 
     /**
       * Instance file