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     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 
159 protected:
160     // Content dumping
161     std::string logValue(utility::ErrorContext &errorContext) const override;
162 
163 private:
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