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 "Element.h"
35
36#include <list>
37#include <vector>
38
39class CConfigurableDomain;
40class CSyncerSet;
41class ISyncer;
42class CSubsystem;
43class CConfigurationAccessContext;
44class CParameterAccessContext;
45class CAreaConfiguration;
46
47class PARAMETER_EXPORT CConfigurableElement : public CElement
48{
49    friend class CConfigurableDomain;
50    friend class CDomainConfiguration;
51    typedef std::list<const CConfigurableDomain *>::const_iterator
52        ConfigurableDomainListConstIterator;
53
54public:
55    CConfigurableElement(const std::string &strName = "");
56    virtual ~CConfigurableElement() = default;
57
58    // Offset in main blackboard
59    void setOffset(size_t offset);
60    size_t getOffset() const;
61
62    // Allocation
63    virtual size_t getFootPrint() const;
64
65    // Syncer set (me, ascendant or descendant ones)
66    void fillSyncerSet(CSyncerSet &syncerSet) const;
67
68    // Belonging domain
69    bool belongsTo(const CConfigurableDomain *pConfigurableDomain) const;
70
71    // Belonging domains
72    void listBelongingDomains(std::string &strResult, bool bVertical = true) const;
73
74    // Matching check for domain association
75    bool hasNoDomainAssociated() const;
76
77    // Matching check for no valid associated domains
78    bool hasNoValidDomainAssociated() const;
79
80    // Owning domains
81    void listAssociatedDomains(std::string &strResult, bool bVertical = true) const;
82    size_t getBelongingDomainCount() const;
83
84    // Elements with no domains
85    void listRogueElements(std::string &strResult) const;
86
87    /** @return true if element is rogue, false otherwise
88     *
89     * An element is rogue if it is disjoint with all domains.
90     *
91     * Ie: An element is rogue if neither its descendants, ascendants
92     *     nor itself are associated with any domain.
93     *
94     * Ie: An element is *not* rogue if any of its descendants, ascendants
95     *     or itself are associated with at least one domain.
96     */
97    bool isRogue() const;
98
99    // Footprint as string
100    std::string getFootprintAsString() const;
101
102    // Belonging subsystem
103    virtual const CSubsystem *getBelongingSubsystem() const;
104
105    // Check element is a parameter
106    virtual bool isParameter() const;
107
108    // AreaConfiguration creation
109    virtual CAreaConfiguration *createAreaConfiguration(const CSyncerSet *pSyncerSet) const;
110
111    // Parameter access
112    virtual bool accessValue(CPathNavigator &pathNavigator, std::string &strValue, bool bSet,
113                             CParameterAccessContext &parameterAccessContext) const;
114
115    /** Gets the element as an array of bytes.
116     *
117     * This is like having a direct access to the blackboard.
118     *
119     * @param[out] bytes Where to store the result.
120     * @param[in] parameterAccessContext Context containing the blackboard to
121     *            read from.
122     */
123    void getSettingsAsBytes(std::vector<uint8_t> &bytes,
124                            CParameterAccessContext &parameterAccessContext) const;
125    /** Sets the element as if it was an array of bytes.
126     *
127     * This is like having a direct access to the blackboard.
128     *
129     * @param[out] bytes The content to be set.
130     * @param[in] parameterAccessContext Context containing the blackboard to
131     *            write to.
132     */
133    bool setSettingsAsBytes(const std::vector<uint8_t> &bytes,
134                            CParameterAccessContext &parameterAccessContext) const;
135
136    /** @return List of all ConfigurableElements that have a mapping relevant in this context.
137     *          Ie: return self and CConfigurableElement ancestor of this node.
138     *
139     */
140    std::list<const CConfigurableElement *> getConfigurableElementContext() const;
141
142    // Used for simulation and virtual subsystems
143    virtual void setDefaultValues(CParameterAccessContext &parameterAccessContext) const;
144
145    // Element properties
146    virtual void showProperties(std::string &strResult) const;
147
148    /**
149     * Get the value associated to a mapping key in the object's mapping
150     *
151     * @param[in] strKey the mapping key
152     * @param[out] pStrValue the associated value
153     *
154     * @return true if @p strKey is found in the object's mapping, false if not
155     */
156    virtual bool getMappingData(const std::string &strKey, const std::string *&pStrValue) const = 0;
157    /** Get the string representation of the mapping
158     *
159     * If applicable, amend values are applied to the leaf element.
160     */
161    virtual std::string getFormattedMapping() const = 0;
162
163    // XML configuration settings parsing
164    virtual bool serializeXmlSettings(
165        CXmlElement &xmlConfigurationSettingsElementContent,
166        CConfigurationAccessContext &configurationAccessContext) const;
167
168    bool fromXml(const CXmlElement &xmlElement,
169                 CXmlSerializingContext &serializingContext) override final;
170
171    void toXml(CXmlElement &xmlElement,
172               CXmlSerializingContext &serializingContext) const override final;
173
174    /** Deserialize the structure from xml. */
175    virtual bool structureFromXml(const CXmlElement &xmlElement,
176                                  CXmlSerializingContext &serializingContext)
177    {
178        // Forward to Element::fromXml.
179        // This is unfortunate as Element::fromXml will call back
180        // fromXml on each children.
181        // Thus on each non leaf node of the tree, the code will test if
182        // the setting or the structure are to be serialized.
183        // This test could be avoided by several ways including:
184        //  - split 2 roles fromXml in two function
185        //    1) construct the elements
186        //    2) recursive call on children
187        //  - dispatch in with a virtual method. This would not not remove
188        //    the branching rather hide it behind a virtual method override.
189        return CElement::fromXml(xmlElement, serializingContext);
190    }
191
192    /** Serialize the structure to xml. */
193    virtual void structureToXml(CXmlElement &xmlElement,
194                                CXmlSerializingContext &serializingContext) const
195    {
196        // See structureFromXml implementation comment.
197        CElement::toXml(xmlElement, serializingContext);
198    }
199
200protected:
201    // Syncer (me or ascendant)
202    virtual ISyncer *getSyncer() const;
203    // Syncer set (descendant)
204    virtual void fillSyncerSetFromDescendant(CSyncerSet &syncerSet) const;
205    // Configuration Domain local search
206    bool containsConfigurableDomain(const CConfigurableDomain *pConfigurableDomain) const;
207
208private:
209    // Content dumping. Override and stop further deriving: Configurable
210    // Elements should be called with the overloaded version taking a
211    // "Parameter Access Context" (The name is misleading as it is actually
212    // used to access any Configurable Element).
213    std::string logValue(utility::ErrorContext &errorContext) const override final;
214    virtual std::string logValue(CParameterAccessContext &context) const;
215
216    // Configurable domain association
217    void addAttachedConfigurableDomain(const CConfigurableDomain *pConfigurableDomain);
218    void removeAttachedConfigurableDomain(const CConfigurableDomain *pConfigurableDomain);
219
220    // Belonging domain ascending search
221    bool belongsToDomainAscending(const CConfigurableDomain *pConfigurableDomain) const;
222
223    // Belonging domains
224    void getBelongingDomains(std::list<const CConfigurableDomain *> &configurableDomainList) const;
225    void listDomains(const std::list<const CConfigurableDomain *> &configurableDomainList,
226                     std::string &strResult, bool bVertical) const;
227
228    // Check parent is still of current type (by structure knowledge)
229    bool isOfConfigurableElementType(const CElement *pParent) const;
230
231    // Offset in main blackboard
232    size_t _offset{0};
233
234    // Associated configurable domains
235    std::list<const CConfigurableDomain *> _configurableDomainList;
236};
237