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
44class CInstanceDefinition;
45class CComponentLibrary;
46class CSubsystemObject;
47class CSubsystemObjectCreator;
48class CInstanceConfigurableElement;
49class CMappingData;
50
51class PARAMETER_EXPORT CSubsystem : public CConfigurableElement, private IMapper
52{
53    // Subsystem objects iterator
54    typedef std::list<CSubsystemObject *>::const_iterator SubsystemObjectListIterator;
55
56public:
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
99protected:
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
109private:
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