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 
42 class CConfigurableElement;
43 class CDomainConfiguration;
44 class CParameterBlackboard;
45 class CSelectionCriteriaDefinition;
46 
47 class CConfigurableDomain : public CElement
48 {
49     typedef std::list<CConfigurableElement *>::const_iterator ConfigurableElementListIterator;
50     typedef std::map<const CConfigurableElement *, CSyncerSet *>::const_iterator
51         ConfigurableElementToSyncerSetMapIterator;
52 
53 public:
54     CConfigurableDomain() = default;
55     CConfigurableDomain(const std::string &strName);
56     ~CConfigurableDomain() override;
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     bool fromXml(const CXmlElement &xmlElement,
150                  CXmlSerializingContext &serializingContext) override;
151 
152     // From IXmlSource
153     void toXml(CXmlElement &xmlElement, CXmlSerializingContext &serializingContext) const override;
154     void childrenToXml(CXmlElement &xmlElement,
155                        CXmlSerializingContext &serializingContext) const override;
156 
157     // Class kind
158     std::string getKind() const override;
159 
160 protected:
161     // Content dumping
162     std::string logValue(utility::ErrorContext &errorContext) const override;
163 
164 private:
165     // Get pending configuration
166     const CDomainConfiguration *getPendingConfiguration() const;
167 
168     // Search for an applicable configuration
169     const CDomainConfiguration *findApplicableDomainConfiguration() const;
170 
171     // Returns true if children dynamic creation is to be dealt with (here, will allow child
172     // deletion upon clean)
173     bool childrenAreDynamic() const override;
174 
175     // Ensure validity on areas related to configurable element
176     void validateAreas(const CConfigurableElement *pConfigurableElement,
177                        const CParameterBlackboard *pMainBlackboard);
178 
179     // Attempt validation for all configurable element's areas, relying on already existing valid
180     // configuration inside domain
181     void autoValidateAll();
182 
183     // Attempt validation for one configurable element's areas, relying on already existing valid
184     // configuration inside domain
185     void autoValidateAreas(const CConfigurableElement *pConfigurableElement);
186 
187     // Attempt configuration validation for all configurable elements' areas, relying on already
188     // existing valid configuration inside domain
189     bool autoValidateConfiguration(CDomainConfiguration *pDomainConfiguration);
190 
191     // Search for a valid configuration for given configurable element
192     const CDomainConfiguration *findValidDomainConfiguration(
193         const CConfigurableElement *pConfigurableElement) const;
194 
195     // In case configurable element was removed
196     void computeSyncSet();
197 
198     // Check configurable element already attached
199     bool containsConfigurableElement(
200         const CConfigurableElement *pConfigurableCandidateElement) const;
201 
202     /** Merge any descended configurable element to this one
203      *
204      * @param[in] newElement pointer to element which has potential descendants which can be merged
205      * @param[out] infos useful information we can provide to client
206      */
207     void mergeAlreadyAssociatedDescendantConfigurableElements(CConfigurableElement *newElement,
208                                                               core::Results &infos);
209 
210     void mergeConfigurations(CConfigurableElement *pToConfigurableElement,
211                              CConfigurableElement *pFromConfigurableElement);
212 
213     /** Actually realize the association between the domain and a configurable  element
214      *
215      * @param[in] pConfigurableElement pointer to the element to add
216      * @param[out] infos useful information we can provide to client
217      * @param[in] (optional) pMainBlackboard, pointer to the application main blackboard
218      *            Default value is NULL, when provided, blackboard area concerning the configurable
219      *            element are validated.
220      */
221     void doAddConfigurableElement(CConfigurableElement *pConfigurableElement, core::Results &infos,
222                                   const CParameterBlackboard *pMainBlackboard = nullptr);
223 
224     void doRemoveConfigurableElement(CConfigurableElement *pConfigurableElement,
225                                      bool bRecomputeSyncSet);
226 
227     // XML parsing
228     /**
229      * Deserialize domain configurations from an Xml document and add them to
230      * the domain.
231      *
232      * @param[in] xmlElement the XML element to be parsed
233      * @param[in] serializingContext context for the deserialization
234      *
235      * @return false if an error occurs, true otherwise.
236      */
237     bool parseDomainConfigurations(const CXmlElement &xmlElement,
238                                    CXmlDomainImportContext &serializingContext);
239     /**
240      * Deserialize domain elements from an Xml document and add them to
241      * the domain.
242      *
243      * @param[in] xmlElement the XML element to be parsed
244      * @param[in] serializingContext context for the deserialization
245      *
246      * @return false if an error occurs, true otherwise.
247      */
248     bool parseConfigurableElements(const CXmlElement &xmlElement,
249                                    CXmlDomainImportContext &serializingContext);
250     /**
251      * Deserialize settings from an Xml document and add them to
252      * the domain.
253      *
254      * @param[in] xmlElement the XML element to be parsed
255      * @param[in] xmlDomainImportContext context for the deserialization
256      *
257      * @return false if an error occurs, true otherwise.
258      */
259     bool parseSettings(const CXmlElement &xmlElement, CXmlDomainImportContext &serializingContext);
260 
261     // XML composing
262     void composeDomainConfigurations(CXmlElement &xmlElement,
263                                      CXmlSerializingContext &serializingContext) const;
264     void composeConfigurableElements(CXmlElement &xmlElement) const;
265     void composeSettings(CXmlElement &xmlElement, CXmlDomainExportContext &context) const;
266 
267     // Syncer set retrieval from configurable element
268     CSyncerSet *getSyncerSet(const CConfigurableElement *pConfigurableElement) const;
269 
270     // Configuration retrieval
271     CDomainConfiguration *findConfiguration(const std::string &strConfiguration,
272                                             std::string &strError);
273     const CDomainConfiguration *findConfiguration(const std::string &strConfiguration,
274                                                   std::string &strError) const;
275 
276     // Configurable elements
277     std::list<CConfigurableElement *> _configurableElementList;
278 
279     // Associated syncer sets
280     std::map<const CConfigurableElement *, CSyncerSet *> _configurableElementToSyncerSetMap;
281 
282     // Sequence awareness
283     bool _bSequenceAware{false};
284 
285     // Syncer set used to ensure propoer synchronization of restored configurable elements
286     CSyncerSet _syncerSet;
287 
288     // Last applied configuration
289     mutable const CDomainConfiguration *_pLastAppliedConfiguration{nullptr};
290 };
291