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 #pragma once
31 
32 #include "parameter_export.h"
33 
34 #include "ConfigurableElement.h"
35 #include "Mapper.h"
36 #include "MappingContext.h"
37 #include <log/Logger.h>
38 
39 #include <list>
40 #include <stack>
41 #include <string>
42 #include <vector>
43 
44 class CInstanceDefinition;
45 class CComponentLibrary;
46 class CSubsystemObject;
47 class CSubsystemObjectCreator;
48 class CInstanceConfigurableElement;
49 class CMappingData;
50 
51 class PARAMETER_EXPORT CSubsystem : public CConfigurableElement, private IMapper
52 {
53     // Subsystem objects iterator
54     typedef std::list<CSubsystemObject *>::const_iterator SubsystemObjectListIterator;
55 
56 public:
57     /**
58      * Class Constructor
59      *
60      * @param[in] strName subsystem name
61      * @param[in] logger the main logger of the application
62      */
63     CSubsystem(const std::string &strName, core::log::Logger &logger);
64     virtual ~CSubsystem();
65 
66     virtual bool structureFromXml(const CXmlElement &xmlElement,
67                                   CXmlSerializingContext &serializingContext);
68 
69     // Susbsystem sanity
70     virtual bool isAlive() const;
71 
72     // Resynchronization after subsystem restart needed
73     virtual bool needResync(bool bClear);
74 
75     // from CElement
76     virtual std::string getKind() const;
77 
78     virtual bool getMappingData(const std::string &strKey, const std::string *&pStrValue) const;
79     std::string getFormattedMapping() const override;
80 
81     /**
82      * Fetch mapping data of an element.
83      *
84      * The mapping is represented as a std::string of all the mapping data (key:value) defined in
85      * the
86      * context of the element.
87      * This method gathers the mapping data found in each Element of the configurableElementPath
88      * list to format the resulting std::string.
89      *
90      * @param[in] configurableElementPath List of all the ConfigurableElements found
91      * that have a mapping. Elements are added at the end of the list, so the root Element will be
92      * the last one.
93      *
94      * @return Formatted std::string of the mapping data
95      */
96     virtual std::string getMapping(
97         std::list<const CConfigurableElement *> &configurableElementPath) const;
98 
99 protected:
100     // Used for simulation and virtual subsystems
101     virtual void setDefaultValues(CParameterAccessContext &parameterAccessContext) const;
102 
103     /// Functionality intendedn for derived Subsystems
104     // Subsystem context mapping keys publication
105     void addContextMappingKey(const std::string &strMappingKey);
106     // Subsystem object creator publication (strong reference)
107     void addSubsystemObjectFactory(CSubsystemObjectCreator *pSubsystemObjectCreator);
108 
109 private:
110     CSubsystem(const CSubsystem &);
111     CSubsystem &operator=(const CSubsystem &);
112 
113     // Belonging subsystem
114     virtual const CSubsystem *getBelongingSubsystem() const;
115 
116     // Mapping execution
117     bool mapSubsystemElements(std::string &strError);
118 
119     /**
120      * Handle a configurable element mapping.
121      *
122      * Add context mappings to the context and instantiate a subsystem object if needed.
123      *
124      * @param[in,out] pInstanceConfigurableElement The configurable element
125      * @param[out] bKeepDiving Keep diving for mapping keys
126                    Is set to true if a subsystem object (tree leave) has been instantiated.
127                    Undetermined on error
128      * @param[out] strError String filled with an human readable error on error,
129                    left unmodified otherwise
130      *
131      * @return true on success, false on failure
132      */
133     virtual bool mapBegin(CInstanceConfigurableElement *pInstanceConfigurableElement,
134                           bool &bKeepDiving, std::string &strError);
135     virtual void mapEnd();
136 
137     // Mapping access
138     /**
139      * Generic mapping error handling
140      *
141      * Format an human readable error std::string from a key and a message in case of mapping error
142      *
143      * @param[in] strKey The key on which the error refers
144      * @param[in] strMessage The error message
145      * @param[in] pConfigurableElement The element on which the error refers
146      *
147      * returns The formated error std::string
148      */
149     std::string getMappingError(const std::string &strKey, const std::string &strMessage,
150                                 const CConfigurableElement *pConfigurableElement) const;
151 
152     /**
153      * Format the mapping data of the ConfigurableElements that have been gathered through recursive
154      * calls to the getMapping() method.
155      * These elements shall be evaluated from the root level to the leaves level, so the list must
156      * be parsed in reverse order.
157      *
158      * @param[in] configurableElementPath List of ConfigurableElements containing mapping data
159      *
160      * @return String containing the formatted mapping
161      */
162     std::string formatMappingDataList(
163         const std::list<const CConfigurableElement *> &configurableElementPath) const;
164 
165     /**
166      * Find the SubystemObject which contains a specific CInstanceConfigurableElement.
167      *
168      * @param[in] pInstanceConfigurableElement The CInstanceConfigurableElement that is related to
169      * the wanted SubsystemObject. Each SubsystemObject of the Subystem internal list is checked in
170      * order to find a match.
171      *
172      * @return A pointer to the SubsystemObject related to pInstanceConfigurableElement
173      */
174     const CSubsystemObject *findSubsystemObjectFromConfigurableElement(
175         const CInstanceConfigurableElement *pInstanceConfigurableElement) const;
176 
177     /**
178      * Find the mapping data defined for the CInstanceConfigurableElement given in parameter, that
179      * corresponds to Subsystem level mapping (Subsystem level mapping keys are defined in
180      * CSubsystemObjectCreator classes).
181      * The CInstanceConfigurableElement might as well contain local mapping data.
182      *
183      * @param[in] pInstanceConfigurableElement The element which mapping data will be parsed for
184      * a match
185      * @param[out] strMappingKey Mapping key defined at the Subsystem level
186      * @param[out] strMappingValue Mapping value contained in pInstanceConfigurableElement
187      */
188     void findSubsystemLevelMappingKeyValue(
189         const CInstanceConfigurableElement *pInstanceConfigurableElement,
190         std::string &strMappingKey, std::string &strMappingValue) const;
191 
192     /**
193      * Formats the mapping of a SubsystemObject
194      *
195      * @param[in] pInstanceConfigurableElement Element corresponding to a SubsystemObject
196      *
197      * @return String containing the formatted mapping
198      */
199     std::string getFormattedSubsystemMappingData(
200         const CInstanceConfigurableElement *pInstanceConfigurableElement) const;
201     /**
202      * Generic context handling
203      *
204      * Feed context with mapping data of the current element
205      *
206      * @param[in] pConfigurableElement The element containing mapping data
207      * @param[out] context The context mapping to update with the current element mapping values
208      * @param[out] strError The formated error std::string
209      *
210      * @return true on success
211      */
212     bool handleMappingContext(const CConfigurableElement *pConfigurableElement,
213                               CMappingContext &context, std::string &strError) const;
214 
215     /**
216      * Looks if a subsystem object needs to be instantiated for the given configurable
217      * element, then instantiate it if needed.
218      *
219      * @param[in,out] pInstanceConfigurableElement The configurable element to check
220      *            for instanciation
221      * @param[in] context The mapping values container
222      * @param[out] bHasCreatedSubsystemObject If a subsystem object has been instantiated.
223                    Undetermined on error
224      * @param[out] strError String filled with an human readable error on error,
225                    left unmodified otherwise
226      *
227      * @return true on success, false on failure
228      */
229     bool handleSubsystemObjectCreation(CInstanceConfigurableElement *pInstanceConfigurableElement,
230                                        CMappingContext &context, bool &bHasCreatedSubsystemObject,
231                                        std::string &strError);
232 
233     // Subsystem context mapping keys
234     std::vector<std::string> _contextMappingKeyArray;
235 
236     // Subsystem object creator map
237     std::vector<CSubsystemObjectCreator *> _subsystemObjectCreatorArray;
238 
239     // Subsystem sync objects (house keeping)
240     std::list<CSubsystemObject *> _subsystemObjectList;
241 
242     // Mapping Context stack
243     std::stack<CMappingContext> _contextStack;
244 
245     // Subelements
246     CComponentLibrary *_pComponentLibrary;
247     CInstanceDefinition *_pInstanceDefinition;
248 
249     //! Contains the mapping info at Subsystem level
250     CMappingData *_pMappingData{nullptr};
251 
252     /** Logger which has to be provided to subsystem objects */
253     core::log::Logger &_logger;
254 };
255