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 "XmlSerializingContext.h"
33#include "XmlDomainImportContext.h"
34#include "XmlDomainExportContext.h"
35#include "SyncerSet.h"
36#include "Results.h"
37#include <list>
38#include <set>
39#include <map>
40#include <string>
41
42class CConfigurableElement;
43class CDomainConfiguration;
44class CParameterBlackboard;
45class CSelectionCriteriaDefinition;
46
47class CConfigurableDomain : public CElement
48{
49    typedef std::list<CConfigurableElement *>::const_iterator ConfigurableElementListIterator;
50    typedef std::map<const CConfigurableElement *, CSyncerSet *>::const_iterator
51        ConfigurableElementToSyncerSetMapIterator;
52
53public:
54    CConfigurableDomain() = default;
55    CConfigurableDomain(const std::string &strName);
56    virtual ~CConfigurableDomain();
57
58    // Sequence awareness
59    void setSequenceAwareness(bool bSequenceAware);
60    bool getSequenceAwareness() const;
61
62    // Configuration Management
63    bool createConfiguration(const std::string &strName,
64                             const CParameterBlackboard *pMainBlackboard, std::string &strError);
65    bool deleteConfiguration(const std::string &strName, std::string &strError);
66    bool renameConfiguration(const std::string &strName, const std::string &strNewName,
67                             std::string &strError);
68
69    /** Restore a configuration
70     *
71     * @param[in] configurationName the configuration name
72     * @param[in] mainBlackboard the application main blackboard
73     * @param[in] autoSync boolean which indicates if auto sync mechanism is on
74     * @param[out] errors, errors encountered during restoration
75     * @return true if success false otherwise
76     */
77    bool restoreConfiguration(const std::string &configurationName,
78                              CParameterBlackboard *mainBlackboard, bool autoSync,
79                              core::Results &errors) const;
80
81    bool saveConfiguration(const std::string &strName, const CParameterBlackboard *pMainBlackboard,
82                           std::string &strError);
83    bool setElementSequence(const std::string &strConfiguration,
84                            const std::vector<std::string> &astrNewElementSequence,
85                            std::string &strError);
86    bool getElementSequence(const std::string &strConfiguration, std::string &strResult) const;
87    bool setApplicationRule(const std::string &strConfiguration,
88                            const std::string &strApplicationRule,
89                            const CSelectionCriteriaDefinition *pSelectionCriteriaDefinition,
90                            std::string &strError);
91    bool clearApplicationRule(const std::string &strConfiguration, std::string &strError);
92    bool getApplicationRule(const std::string &strConfiguration, std::string &strResult) const;
93
94    // Last applied configuration name
95    std::string getLastAppliedConfigurationName() const;
96
97    // Pending configuration name
98    std::string getPendingConfigurationName() const;
99
100    // Associated Configurable elements
101    void gatherConfigurableElements(
102        std::set<const CConfigurableElement *> &configurableElementSet) const;
103    void listAssociatedToElements(std::string &strResult) const;
104
105    /** Add a configurable element to the domain
106     *
107     * @param[in] pConfigurableElement pointer to the element to add
108     * @param[in] pMainBlackboard pointer to the application main blackboard
109     * @param[out] infos useful information we can provide to client
110     * @return true if succeed false otherwise
111     */
112    bool addConfigurableElement(CConfigurableElement *pConfigurableElement,
113                                const CParameterBlackboard *pMainBlackboard, core::Results &infos);
114
115    bool removeConfigurableElement(CConfigurableElement *pConfigurableElement,
116                                   std::string &strError);
117
118    // Blackboard Configuration and Base Offset retrieval
119    CParameterBlackboard *findConfigurationBlackboard(
120        const std::string &strConfiguration, const CConfigurableElement *pConfigurableElement,
121        size_t &baseOffset, bool &bIsLastApplied, std::string &strError) const;
122
123    /** Split the domain in two.
124     * Remove an element of a domain and create a new domain which owns the element.
125     *
126     * @param[in] pConfigurableElement pointer to the element to remove
127     * @param[out] infos useful information we can provide to client
128     * @return true if succeed false otherwise
129     */
130    bool split(CConfigurableElement *pConfigurableElement, core::Results &infos);
131
132    // Ensure validity on whole domain from main blackboard
133    void validate(const CParameterBlackboard *pMainBlackboard);
134
135    /** Apply the configuration if required
136     *
137     * @param[in] pParameterBlackboard the blackboard to synchronize
138     * @param[in] pSyncerSet pointer to the set containing application syncers
139     * @param[in] bForced boolean used to force configuration application
140     * @param[out] info string containing useful information we can provide to client
141     */
142    void apply(CParameterBlackboard *pParameterBlackboard, CSyncerSet *pSyncerSet, bool bForced,
143               std::string &info) const;
144
145    // Return applicable configuration validity for given configurable element
146    bool isApplicableConfigurationValid(const CConfigurableElement *pConfigurableElement) const;
147
148    // From IXmlSink
149    virtual bool fromXml(const CXmlElement &xmlElement, CXmlSerializingContext &serializingContext);
150
151    // From IXmlSource
152    virtual void toXml(CXmlElement &xmlElement, CXmlSerializingContext &serializingContext) const;
153    virtual void childrenToXml(CXmlElement &xmlElement,
154                               CXmlSerializingContext &serializingContext) const;
155
156    // Class kind
157    virtual std::string getKind() const;
158
159protected:
160    // Content dumping
161    std::string logValue(utility::ErrorContext &errorContext) const override;
162
163private:
164    // Get pending configuration
165    const CDomainConfiguration *getPendingConfiguration() const;
166
167    // Search for an applicable configuration
168    const CDomainConfiguration *findApplicableDomainConfiguration() const;
169
170    // Returns true if children dynamic creation is to be dealt with (here, will allow child
171    // deletion upon clean)
172    virtual bool childrenAreDynamic() const;
173
174    // Ensure validity on areas related to configurable element
175    void validateAreas(const CConfigurableElement *pConfigurableElement,
176                       const CParameterBlackboard *pMainBlackboard);
177
178    // Attempt validation for all configurable element's areas, relying on already existing valid
179    // configuration inside domain
180    void autoValidateAll();
181
182    // Attempt validation for one configurable element's areas, relying on already existing valid
183    // configuration inside domain
184    void autoValidateAreas(const CConfigurableElement *pConfigurableElement);
185
186    // Attempt configuration validation for all configurable elements' areas, relying on already
187    // existing valid configuration inside domain
188    bool autoValidateConfiguration(CDomainConfiguration *pDomainConfiguration);
189
190    // Search for a valid configuration for given configurable element
191    const CDomainConfiguration *findValidDomainConfiguration(
192        const CConfigurableElement *pConfigurableElement) const;
193
194    // In case configurable element was removed
195    void computeSyncSet();
196
197    // Check configurable element already attached
198    bool containsConfigurableElement(
199        const CConfigurableElement *pConfigurableCandidateElement) const;
200
201    /** Merge any descended configurable element to this one
202     *
203     * @param[in] newElement pointer to element which has potential descendants which can be merged
204     * @param[out] infos useful information we can provide to client
205     */
206    void mergeAlreadyAssociatedDescendantConfigurableElements(CConfigurableElement *newElement,
207                                                              core::Results &infos);
208
209    void mergeConfigurations(CConfigurableElement *pToConfigurableElement,
210                             CConfigurableElement *pFromConfigurableElement);
211
212    /** Actually realize the association between the domain and a configurable  element
213     *
214     * @param[in] pConfigurableElement pointer to the element to add
215     * @param[out] infos useful information we can provide to client
216     * @param[in] (optional) pMainBlackboard, pointer to the application main blackboard
217     *            Default value is NULL, when provided, blackboard area concerning the configurable
218     *            element are validated.
219     */
220    void doAddConfigurableElement(CConfigurableElement *pConfigurableElement, core::Results &infos,
221                                  const CParameterBlackboard *pMainBlackboard = NULL);
222
223    void doRemoveConfigurableElement(CConfigurableElement *pConfigurableElement,
224                                     bool bRecomputeSyncSet);
225
226    // XML parsing
227    /**
228     * Deserialize domain configurations from an Xml document and add them to
229     * the domain.
230     *
231     * @param[in] xmlElement the XML element to be parsed
232     * @param[in] serializingContext context for the deserialization
233     *
234     * @return false if an error occurs, true otherwise.
235     */
236    bool parseDomainConfigurations(const CXmlElement &xmlElement,
237                                   CXmlDomainImportContext &serializingContext);
238    /**
239     * Deserialize domain elements from an Xml document and add them to
240     * the domain.
241     *
242     * @param[in] xmlElement the XML element to be parsed
243     * @param[in] serializingContext context for the deserialization
244     *
245     * @return false if an error occurs, true otherwise.
246     */
247    bool parseConfigurableElements(const CXmlElement &xmlElement,
248                                   CXmlDomainImportContext &serializingContext);
249    /**
250     * Deserialize settings from an Xml document and add them to
251     * the domain.
252     *
253     * @param[in] xmlElement the XML element to be parsed
254     * @param[in] xmlDomainImportContext context for the deserialization
255     *
256     * @return false if an error occurs, true otherwise.
257     */
258    bool parseSettings(const CXmlElement &xmlElement, CXmlDomainImportContext &serializingContext);
259
260    // XML composing
261    void composeDomainConfigurations(CXmlElement &xmlElement,
262                                     CXmlSerializingContext &serializingContext) const;
263    void composeConfigurableElements(CXmlElement &xmlElement) const;
264    void composeSettings(CXmlElement &xmlElement, CXmlDomainExportContext &context) const;
265
266    // Syncer set retrieval from configurable element
267    CSyncerSet *getSyncerSet(const CConfigurableElement *pConfigurableElement) const;
268
269    // Configuration retrieval
270    CDomainConfiguration *findConfiguration(const std::string &strConfiguration,
271                                            std::string &strError);
272    const CDomainConfiguration *findConfiguration(const std::string &strConfiguration,
273                                                  std::string &strError) const;
274
275    // Configurable elements
276    std::list<CConfigurableElement *> _configurableElementList;
277
278    // Associated syncer sets
279    std::map<const CConfigurableElement *, CSyncerSet *> _configurableElementToSyncerSetMap;
280
281    // Sequence awareness
282    bool _bSequenceAware{false};
283
284    // Syncer set used to ensure propoer synchronization of restored configurable elements
285    CSyncerSet _syncerSet;
286
287    // Last applied configuration
288    mutable const CDomainConfiguration *_pLastAppliedConfiguration{nullptr};
289};
290