1/*
2 * Copyright (c) 2011-2016, 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#include "version.h"
31#include "ParameterMgr.h"
32#include "ConfigurationAccessContext.h"
33#include "XmlParameterSerializingContext.h"
34#include "XmlElementSerializingContext.h"
35#include "SystemClass.h"
36#include "ElementLibrarySet.h"
37#include "SubsystemLibrary.h"
38#include "NamedElementBuilderTemplate.h"
39#include "KindElementBuilderTemplate.h"
40#include "ElementBuilderTemplate.h"
41#include "SelectionCriterionType.h"
42#include "SubsystemElementBuilder.h"
43#include "FileIncluderElementBuilder.h"
44#include "SelectionCriteria.h"
45#include "ComponentType.h"
46#include "ComponentInstance.h"
47#include "ParameterBlockType.h"
48#include "BooleanParameterType.h"
49#include "IntegerParameterType.h"
50#include "FixedPointParameterType.h"
51#include "FloatingPointParameterType.h"
52#include "ParameterBlackboard.h"
53#include "Parameter.h"
54#include "ParameterAccessContext.h"
55#include "ParameterFrameworkConfiguration.h"
56#include "FrameworkConfigurationGroup.h"
57#include "PluginLocation.h"
58#include "SubsystemPlugins.h"
59#include "FrameworkConfigurationLocation.h"
60#include "ConfigurableDomains.h"
61#include "ConfigurableDomain.h"
62#include "DomainConfiguration.h"
63#include "XmlDomainSerializingContext.h"
64#include "XmlDomainExportContext.h"
65#include "XmlDomainImportContext.h"
66#include "BitParameterBlockType.h"
67#include "BitParameterType.h"
68#include "StringParameterType.h"
69#include "EnumParameterType.h"
70#include "BackgroundRemoteProcessorServer.h"
71#include "ElementLocator.h"
72#include "CompoundRule.h"
73#include "SelectionCriterionRule.h"
74#include "SimulatedBackSynchronizer.h"
75#include "HardwareBackSynchronizer.h"
76#include <cassert>
77#include "ParameterHandle.h"
78#include "LinearParameterAdaptation.h"
79#include "LogarithmicParameterAdaptation.h"
80#include "EnumValuePair.h"
81#include "Subsystem.h"
82#include "XmlStreamDocSink.h"
83#include "XmlMemoryDocSink.h"
84#include "XmlDocSource.h"
85#include "XmlMemoryDocSource.h"
86#include "SelectionCriteriaDefinition.h"
87#include "Utility.h"
88#include "Memory.hpp"
89#include <sstream>
90#include <fstream>
91#include <algorithm>
92#include <stdexcept>
93#include <mutex>
94#include <iomanip>
95#include "convert.hpp"
96
97#define base CElement
98
99/** Private macro helper to declare a new context
100 *
101 * Context declaration always need logger and logging prefix to be
102 * passed as parameters.
103 * This macro aims to avoid this boring notation.
104 * This macro should be called only once in a scope. Nested scopes can
105 * call this macro too, as variable shadowing is supported.
106 */
107#define LOG_CONTEXT(contextTitle) core::log::Context context(_logger, contextTitle)
108
109#ifdef SIMULATION
110// In simulation, back synchronization of the blackboard won't probably work
111// We need to ensure though the blackboard is initialized with valid data
112typedef CSimulatedBackSynchronizer BackSynchronizer;
113#else
114// Real back synchronizer from subsystems
115typedef CHardwareBackSynchronizer BackSynchronizer;
116#endif
117
118using std::string;
119using std::list;
120using std::vector;
121using std::ostringstream;
122using std::ofstream;
123using std::ifstream;
124using std::mutex;
125using std::lock_guard;
126
127// FIXME: integrate ParameterMgr to core namespace
128using namespace core;
129
130// Used for remote processor server creation
131typedef IRemoteProcessorServerInterface *(*CreateRemoteProcessorServer)(
132    uint16_t uiPort, IRemoteCommandHandler *pCommandHandler);
133
134// Config File System looks normally like this:
135// ---------------------------------------------
136//|-- <ParameterFrameworkConfiguration>.xml
137//|-- schemas
138//|   `-- *.xsd
139//|-- Settings
140//|   `-- <SystemClassName folder>*
141//|       |-- <ConfigurableDomains>.xml
142//|       `-- <Settings>.bin?
143//`-- Structure
144//    `-- <SystemClassName folder>*
145//        |-- <SystemClassName>Class.xml
146//        `-- <Subsystem>.xml*
147// --------------------------------------------
148
149// Remote command parser array
150const CParameterMgr::SRemoteCommandParserItem CParameterMgr::gastRemoteCommandParserItems[] = {
151
152    /// Version
153    {"version", &CParameterMgr::versionCommandProcess, 0, "", "Show version"},
154
155    /// Status
156    {"status", &CParameterMgr::statusCommandProcess, 0, "", "Show current status"},
157
158    /// Tuning Mode
159    {"setTuningMode", &CParameterMgr::setTuningModeCommandProcess, 1, "on|off*",
160     "Turn on or off Tuning Mode"},
161    {"getTuningMode", &CParameterMgr::getTuningModeCommandProcess, 0, "", "Show Tuning Mode"},
162
163    /// Value Space
164    {"setValueSpace", &CParameterMgr::setValueSpaceCommandProcess, 1, "raw|real*",
165     "Assigns Value Space used for parameter value interpretation"},
166    {"getValueSpace", &CParameterMgr::getValueSpaceCommandProcess, 0, "", "Show Value Space"},
167
168    /// Output Raw Format
169    {"setOutputRawFormat", &CParameterMgr::setOutputRawFormatCommandProcess, 1, "dec*|hex",
170     "Assigns format used to output parameter values when in raw Value Space"},
171    {"getOutputRawFormat", &CParameterMgr::getOutputRawFormatCommandProcess, 0, "",
172     "Show Output Raw Format"},
173
174    /// Sync
175    {"setAutoSync", &CParameterMgr::setAutoSyncCommandProcess, 1, "on*|off",
176     "Turn on or off automatic synchronization to hardware while in Tuning Mode"},
177    {"getAutoSync", &CParameterMgr::getAutoSyncCommandProcess, 0, "", "Show Auto Sync state"},
178    {"sync", &CParameterMgr::syncCommandProcess, 0, "",
179     "Synchronize current settings to hardware while in Tuning Mode and Auto Sync off"},
180
181    /// Criteria
182    {"listCriteria", &CParameterMgr::listCriteriaCommandProcess, 0, "[CSV|XML]",
183     "List selection criteria"},
184
185    /// Domains
186    {"listDomains", &CParameterMgr::listDomainsCommandProcess, 0, "", "List configurable domains"},
187    {"dumpDomains", &CParameterMgr::dumpDomainsCommandProcess, 0, "",
188     "Show all domains and configurations, including applicability conditions"},
189    {"createDomain", &CParameterMgr::createDomainCommandProcess, 1, "<domain>",
190     "Create new configurable domain"},
191    {"deleteDomain", &CParameterMgr::deleteDomainCommandProcess, 1, "<domain>",
192     "Delete configurable domain"},
193    {"deleteAllDomains", &CParameterMgr::deleteAllDomainsCommandProcess, 0, "",
194     "Delete all configurable domains"},
195    {"renameDomain", &CParameterMgr::renameDomainCommandProcess, 2, "<domain> <new name>",
196     "Rename configurable domain"},
197    {"setSequenceAwareness", &CParameterMgr::setSequenceAwarenessCommandProcess, 1,
198     "<domain> true|false*", "Set configurable domain sequence awareness"},
199    {"getSequenceAwareness", &CParameterMgr::getSequenceAwarenessCommandProcess, 1, "<domain>",
200     "Get configurable domain sequence awareness"},
201    {"listDomainElements", &CParameterMgr::listDomainElementsCommandProcess, 1, "<domain>",
202     "List elements associated to configurable domain"},
203    {"addElement", &CParameterMgr::addElementCommandProcess, 2, "<domain> <elem path>",
204     "Associate element at given path to configurable domain"},
205    {"removeElement", &CParameterMgr::removeElementCommandProcess, 2, "<domain> <elem path>",
206     "Dissociate element at given path from configurable domain"},
207    {"splitDomain", &CParameterMgr::splitDomainCommandProcess, 2, "<domain> <elem path>",
208     "Split configurable domain at given associated element path"},
209
210    /// Configurations
211    {"listConfigurations", &CParameterMgr::listConfigurationsCommandProcess, 1, "<domain>",
212     "List domain configurations"},
213    {"createConfiguration", &CParameterMgr::createConfigurationCommandProcess, 2,
214     "<domain> <configuration>", "Create new domain configuration"},
215    {"deleteConfiguration", &CParameterMgr::deleteConfigurationCommandProcess, 2,
216     "<domain> <configuration>", "Delete domain configuration"},
217    {"renameConfiguration", &CParameterMgr::renameConfigurationCommandProcess, 3,
218     "<domain> <configuration> <new name>", "Rename domain configuration"},
219    {"saveConfiguration", &CParameterMgr::saveConfigurationCommandProcess, 2,
220     "<domain> <configuration>", "Save current settings into configuration"},
221    {"restoreConfiguration", &CParameterMgr::restoreConfigurationCommandProcess, 2,
222     "<domain> <configuration>", "Restore current settings from configuration"},
223    {"setElementSequence", &CParameterMgr::setElementSequenceCommandProcess, 3,
224     "<domain> <configuration> <elem path list>",
225     "Set element application order for configuration"},
226    {"getElementSequence", &CParameterMgr::getElementSequenceCommandProcess, 2,
227     "<domain> <configuration>", "Get element application order for configuration"},
228    {"setRule", &CParameterMgr::setRuleCommandProcess, 3, "<domain> <configuration> <rule>",
229     "Set configuration application rule"},
230    {"clearRule", &CParameterMgr::clearRuleCommandProcess, 2, "<domain> <configuration>",
231     "Clear configuration application rule"},
232    {"getRule", &CParameterMgr::getRuleCommandProcess, 2, "<domain> <configuration>",
233     "Get configuration application rule"},
234
235    /// Elements/Parameters
236    {"listElements", &CParameterMgr::listElementsCommandProcess, 1, "<elem path>|/",
237     "List elements under element at given path or root"},
238    {"listParameters", &CParameterMgr::listParametersCommandProcess, 1, "<elem path>|/",
239     "List parameters under element at given path or root"},
240    {"getElementStructureXML", &CParameterMgr::getElementStructureXMLCommandProcess, 1,
241     "<elem path>", "Get structure of element at given path in XML format"},
242    {"getElementBytes", &CParameterMgr::getElementBytesCommandProcess, 1, "<elem path>",
243     "Get settings of element at given path in Byte Array format"},
244    {"setElementBytes", &CParameterMgr::setElementBytesCommandProcess, 2, "<elem path> <values>",
245     "Set settings of element at given path in Byte Array format"},
246    {"getElementXML", &CParameterMgr::getElementXMLCommandProcess, 1, "<elem path>",
247     "Get settings of element at given path in XML format"},
248    {"setElementXML", &CParameterMgr::setElementXMLCommandProcess, 2, "<elem path> <values>",
249     "Set settings of element at given path in XML format"},
250    {"dumpElement", &CParameterMgr::dumpElementCommandProcess, 1, "<elem path>",
251     "Dump structure and content of element at given path"},
252    {"getElementSize", &CParameterMgr::getElementSizeCommandProcess, 1, "<elem path>",
253     "Show size of element at given path"},
254    {"showProperties", &CParameterMgr::showPropertiesCommandProcess, 1, "<elem path>",
255     "Show properties of element at given path"},
256    {"getParameter", &CParameterMgr::getParameterCommandProcess, 1, "<param path>",
257     "Get value for parameter at given path"},
258    {"setParameter", &CParameterMgr::setParameterCommandProcess, 2, "<param path> <value>",
259     "Set value for parameter at given path"},
260    {"listBelongingDomains", &CParameterMgr::listBelongingDomainsCommandProcess, 1, "<elem path>",
261     "List domain(s) element at given path belongs to"},
262    {"listAssociatedDomains", &CParameterMgr::listAssociatedDomainsCommandProcess, 1, "<elem path>",
263     "List domain(s) element at given path is associated to"},
264    {"getConfigurationParameter", &CParameterMgr::getConfigurationParameterCommandProcess, 3,
265     "<domain> <configuration> <param path>",
266     "Get value for parameter at given path from configuration"},
267    {"setConfigurationParameter", &CParameterMgr::setConfigurationParameterCommandProcess, 4,
268     "<domain> <configuration> <param path> <value>",
269     "Set value for parameter at given path to configuration"},
270    {"showMapping", &CParameterMgr::showMappingCommandProcess, 1, "<elem path>",
271     "Show mapping for an element at given path"},
272
273    /// Browse
274    {"listAssociatedElements", &CParameterMgr::listAssociatedElementsCommandProcess, 0, "",
275     "List element sub-trees associated to at least one configurable domain"},
276    {"listConflictingElements", &CParameterMgr::listConflictingElementsCommandProcess, 0, "",
277     "List element sub-trees contained in more than one configurable domain"},
278    {"listRogueElements", &CParameterMgr::listRogueElementsCommandProcess, 0, "",
279     "List element sub-trees owned by no configurable domain"},
280
281    /// Settings Import/Export
282    {"exportDomainsXML", &CParameterMgr::exportDomainsXMLCommandProcess, 1, "<file path> ",
283     "Export domains to an XML file (provide an absolute path or relative"
284     "to the client's working directory)"},
285    {"importDomainsXML", &CParameterMgr::importDomainsXMLCommandProcess, 1, "<file path>",
286     "Import domains from an XML file (provide an absolute path or relative"
287     "to the client's working directory)"},
288    {"exportDomainsWithSettingsXML", &CParameterMgr::exportDomainsWithSettingsXMLCommandProcess, 1,
289     "<file path> ",
290     "Export domains including settings to XML file (provide an absolute path or relative"
291     "to the client's working directory)"},
292    {"exportDomainWithSettingsXML", &CParameterMgr::exportDomainWithSettingsXMLCommandProcess, 2,
293     "<domain> <file path> ", "Export a single given domain including settings to XML file"
294                              " (provide an absolute path or relative to the client's"
295                              " working directory)"},
296    {"importDomainsWithSettingsXML", &CParameterMgr::importDomainsWithSettingsXMLCommandProcess, 1,
297     "<file path>",
298     "Import domains including settings from XML file (provide an absolute path or relative"
299     "to the client's working directory)"},
300    {"importDomainWithSettingsXML", &CParameterMgr::importDomainWithSettingsXMLCommandProcess, 1,
301     "<file path> [overwrite]",
302     "Import a single domain including settings from XML file."
303     " Does not overwrite an existing domain unless 'overwrite' is passed as second"
304     " argument. Provide an absolute path or relative to the client's working directory)"},
305    {"getDomainsWithSettingsXML", &CParameterMgr::getDomainsWithSettingsXMLCommandProcess, 0, "",
306     "Print domains including settings as XML"},
307    {"getDomainWithSettingsXML", &CParameterMgr::getDomainWithSettingsXMLCommandProcess, 1,
308     "<domain>", "Print the given domain including settings as XML"},
309    {"setDomainsWithSettingsXML", &CParameterMgr::setDomainsWithSettingsXMLCommandProcess, 1,
310     "<xml configurable domains>", "Import domains including settings from XML string"},
311    {"setDomainWithSettingsXML", &CParameterMgr::setDomainWithSettingsXMLCommandProcess, 1,
312     "<xml configurable domain> [overwrite]",
313     "Import domains including settings from XML"
314     " string. Does not overwrite an existing domain unless 'overwrite' is passed as second"
315     " argument"},
316    /// Structure Export
317    {"getSystemClassXML", &CParameterMgr::getSystemClassXMLCommandProcess, 0, "",
318     "Print parameter structure as XML"},
319    /// Deprecated Commands
320    {"getDomainsXML", &CParameterMgr::getDomainsWithSettingsXMLCommandProcess, 0, "",
321     "DEPRECATED COMMAND, please use getDomainsWithSettingsXML"},
322
323};
324
325// Remote command parsers array Size
326CParameterMgr::CParameterMgr(const string &strConfigurationFilePath, log::ILogger &logger)
327    : _pMainParameterBlackboard(new CParameterBlackboard),
328      _pElementLibrarySet(new CElementLibrarySet),
329      _xmlConfigurationUri(CXmlDocSource::mkUri(strConfigurationFilePath, "")), _logger(logger)
330{
331    // Deal with children
332    addChild(new CParameterFrameworkConfiguration);
333    addChild(new CSelectionCriteria);
334    addChild(new CSystemClass(_logger));
335    addChild(new CConfigurableDomains);
336}
337
338CParameterMgr::~CParameterMgr()
339{
340    // Children
341    delete _pRemoteProcessorServer;
342    delete _pMainParameterBlackboard;
343    delete _pElementLibrarySet;
344}
345
346string CParameterMgr::getKind() const
347{
348    return "ParameterMgr";
349}
350
351// Version
352string CParameterMgr::getVersion() const
353{
354    return PARAMETER_FRAMEWORK_VERSION;
355}
356
357bool CParameterMgr::load(string &strError)
358{
359    LOG_CONTEXT("Loading");
360
361    feedElementLibraries();
362
363    // Load Framework configuration
364    if (!loadFrameworkConfiguration(strError)) {
365
366        return false;
367    }
368
369    if (!loadSubsystems(strError)) {
370
371        return false;
372    }
373
374    // Load structure
375    if (!loadStructure(strError)) {
376
377        return false;
378    }
379
380    // Load settings
381    if (!loadSettings(strError)) {
382
383        return false;
384    }
385
386    // Init flow of element tree
387    if (!init(strError)) {
388
389        return false;
390    }
391
392    {
393        LOG_CONTEXT("Main blackboard back synchronization");
394
395        // Back synchronization for areas in parameter blackboard not covered by any domain
396        BackSynchronizer(getConstSystemClass(), _pMainParameterBlackboard).sync();
397    }
398
399    // We're done loading the settings and back synchronizing
400    CConfigurableDomains *pConfigurableDomains = getConfigurableDomains();
401
402    // We need to ensure all domains are valid
403    pConfigurableDomains->validate(_pMainParameterBlackboard);
404
405    // Log selection criterion states
406    {
407        LOG_CONTEXT("Criterion states");
408
409        const CSelectionCriteria *selectionCriteria = getConstSelectionCriteria();
410
411        list<string> criteria;
412        selectionCriteria->listSelectionCriteria(criteria, true, false);
413
414        info() << criteria;
415    }
416
417    // Subsystem can not ask for resync as they have not been synced yet
418    getSystemClass()->cleanSubsystemsNeedToResync();
419
420    // At initialization, check subsystems that need resync
421    doApplyConfigurations(true);
422
423    // Start remote processor server if appropriate
424    return handleRemoteProcessingInterface(strError);
425}
426
427bool CParameterMgr::loadFrameworkConfiguration(string &strError)
428{
429    LOG_CONTEXT("Loading framework configuration");
430
431    // Parse Structure XML file
432    CXmlElementSerializingContext elementSerializingContext(strError);
433
434    _xmlDoc *doc =
435        CXmlDocSource::mkXmlDoc(_xmlConfigurationUri, true, true, elementSerializingContext);
436    if (doc == NULL) {
437        return false;
438    }
439
440    if (!xmlParse(elementSerializingContext, getFrameworkConfiguration(), doc, _xmlConfigurationUri,
441                  EFrameworkConfigurationLibrary)) {
442
443        return false;
444    }
445    // Set class name to system class and configurable domains
446    getSystemClass()->setName(getConstFrameworkConfiguration()->getSystemClassName());
447    getConfigurableDomains()->setName(getConstFrameworkConfiguration()->getSystemClassName());
448
449    // Get subsystem plugins elements
450    _pSubsystemPlugins = static_cast<const CSubsystemPlugins *>(
451        getConstFrameworkConfiguration()->findChild("SubsystemPlugins"));
452
453    if (!_pSubsystemPlugins) {
454
455        strError = "Parameter Framework Configuration: couldn't find SubsystemPlugins element";
456
457        return false;
458    }
459
460    // Log tuning availability
461    info() << "Tuning "
462           << (getConstFrameworkConfiguration()->isTuningAllowed() ? "allowed" : "prohibited");
463
464    return true;
465}
466
467bool CParameterMgr::loadSubsystems(std::string &error)
468{
469    LOG_CONTEXT("Loading subsystem plugins");
470
471    // Load subsystems
472    bool isSuccess =
473        getSystemClass()->loadSubsystems(error, _pSubsystemPlugins, !_bFailOnMissingSubsystem);
474
475    if (isSuccess) {
476        info() << "All subsystem plugins successfully loaded";
477
478        if (!error.empty()) {
479            // Log missing subsystems as info
480            info() << error;
481        }
482    } else {
483        warning() << error;
484    }
485    return isSuccess;
486}
487
488bool CParameterMgr::loadStructure(string &strError)
489{
490    // Retrieve system to load structure to
491    CSystemClass *pSystemClass = getSystemClass();
492
493    LOG_CONTEXT("Loading " + pSystemClass->getName() + " system class structure");
494
495    // Get structure description element
496    const CFrameworkConfigurationLocation *pStructureDescriptionFileLocation =
497        static_cast<const CFrameworkConfigurationLocation *>(
498            getConstFrameworkConfiguration()->findChildOfKind("StructureDescriptionFileLocation"));
499
500    if (!pStructureDescriptionFileLocation) {
501
502        strError = "No StructureDescriptionFileLocation element found for SystemClass " +
503                   pSystemClass->getName();
504
505        return false;
506    }
507
508    // Parse Structure XML file
509    CParameterAccessContext accessContext(strError);
510    CXmlParameterSerializingContext parameterBuildContext(accessContext, strError);
511
512    {
513        // Get structure URI
514        string structureUri =
515            CXmlDocSource::mkUri(_xmlConfigurationUri, pStructureDescriptionFileLocation->getUri());
516
517        LOG_CONTEXT("Importing system structure from file " + structureUri);
518
519        _xmlDoc *doc = CXmlDocSource::mkXmlDoc(structureUri, true, true, parameterBuildContext);
520        if (doc == NULL) {
521            return false;
522        }
523
524        if (!xmlParse(parameterBuildContext, pSystemClass, doc, structureUri,
525                      EParameterCreationLibrary)) {
526
527            return false;
528        }
529    }
530
531    // Initialize offsets
532    pSystemClass->setOffset(0);
533
534    // Initialize main blackboard's size
535    _pMainParameterBlackboard->setSize(pSystemClass->getFootPrint());
536
537    return true;
538}
539
540bool CParameterMgr::loadSettings(string &strError)
541{
542    string strLoadError;
543    bool success = loadSettingsFromConfigFile(strLoadError);
544
545    if (!success && !_bFailOnFailedSettingsLoad) {
546        // Load can not fail, ie continue but log the load errors
547        warning() << strLoadError;
548        warning() << "Failed to load settings, continue without domains.";
549        success = true;
550    }
551
552    if (!success) {
553        // Propagate the litteral error only if the function fails
554        strError = strLoadError;
555        return false;
556    }
557
558    return true;
559}
560
561bool CParameterMgr::loadSettingsFromConfigFile(string &strError)
562{
563    LOG_CONTEXT("Loading settings");
564
565    // Get settings configuration element
566    const CFrameworkConfigurationGroup *pParameterConfigurationGroup =
567        static_cast<const CFrameworkConfigurationGroup *>(
568            getConstFrameworkConfiguration()->findChildOfKind("SettingsConfiguration"));
569
570    if (!pParameterConfigurationGroup) {
571
572        // No settings to load
573
574        return true;
575    }
576
577    // Get configurable domains element
578    const CFrameworkConfigurationLocation *pConfigurableDomainsFileLocation =
579        static_cast<const CFrameworkConfigurationLocation *>(
580            pParameterConfigurationGroup->findChildOfKind("ConfigurableDomainsFileLocation"));
581
582    if (!pConfigurableDomainsFileLocation) {
583
584        strError = "No ConfigurableDomainsFileLocation element found for SystemClass " +
585                   getSystemClass()->getName();
586
587        return false;
588    }
589    // Get destination root element
590    CConfigurableDomains *pConfigurableDomains = getConfigurableDomains();
591
592    // Get Xml configuration domains URI
593    string configurationDomainsUri =
594        CXmlDocSource::mkUri(_xmlConfigurationUri, pConfigurableDomainsFileLocation->getUri());
595
596    // Parse configuration domains XML file
597    CXmlDomainImportContext xmlDomainImportContext(strError, true, *getSystemClass());
598
599    // Selection criteria definition for rule creation
600    xmlDomainImportContext.setSelectionCriteriaDefinition(
601        getConstSelectionCriteria()->getSelectionCriteriaDefinition());
602
603    // Auto validation of configurations
604    xmlDomainImportContext.setAutoValidationRequired(true);
605
606    info() << "Importing configurable domains from file " << configurationDomainsUri
607           << " with settings";
608
609    _xmlDoc *doc =
610        CXmlDocSource::mkXmlDoc(configurationDomainsUri, true, true, xmlDomainImportContext);
611    if (doc == NULL) {
612        return false;
613    }
614
615    return xmlParse(xmlDomainImportContext, pConfigurableDomains, doc, _xmlConfigurationUri,
616                    EParameterConfigurationLibrary, true, "SystemClassName");
617}
618
619// XML parsing
620bool CParameterMgr::xmlParse(CXmlElementSerializingContext &elementSerializingContext,
621                             CElement *pRootElement, _xmlDoc *doc, const string &baseUri,
622                             CParameterMgr::ElementLibrary eElementLibrary, bool replace,
623                             const string &strNameAttributeName)
624{
625    // Init serializing context
626    elementSerializingContext.set(_pElementLibrarySet->getElementLibrary(eElementLibrary), baseUri);
627
628    CXmlDocSource docSource(doc, _bValidateSchemasOnStart, pRootElement->getXmlElementName(),
629                            pRootElement->getName(), strNameAttributeName);
630
631    docSource.setSchemaBaseUri(getSchemaUri());
632
633    // Start clean
634    auto clean = [replace, &pRootElement] {
635        if (replace) {
636            pRootElement->clean();
637        }
638    };
639    clean();
640
641    CXmlMemoryDocSink memorySink(pRootElement);
642
643    if (!memorySink.process(docSource, elementSerializingContext)) {
644        clean();
645        return false;
646    }
647
648    return true;
649}
650
651// Init
652bool CParameterMgr::init(string &strError)
653{
654    return base::init(strError);
655}
656
657// Selection criteria interface
658CSelectionCriterionType *CParameterMgr::createSelectionCriterionType(bool bIsInclusive)
659{
660    // Propagate
661    return getSelectionCriteria()->createSelectionCriterionType(bIsInclusive);
662}
663
664CSelectionCriterion *CParameterMgr::createSelectionCriterion(
665    const string &strName, const CSelectionCriterionType *pSelectionCriterionType)
666{
667    // Propagate
668    return getSelectionCriteria()->createSelectionCriterion(strName, pSelectionCriterionType,
669                                                            _logger);
670}
671
672// Selection criterion retrieval
673CSelectionCriterion *CParameterMgr::getSelectionCriterion(const string &strName)
674{
675    // Propagate
676    return getSelectionCriteria()->getSelectionCriterion(strName);
677}
678
679// Configuration application
680void CParameterMgr::applyConfigurations()
681{
682    LOG_CONTEXT("Configuration application request");
683
684    // Lock state
685    lock_guard<mutex> autoLock(getBlackboardMutex());
686
687    if (!_bTuningModeIsOn) {
688
689        // Apply configuration(s)
690        doApplyConfigurations(false);
691    } else {
692
693        warning() << "Configurations were not applied because the TuningMode is on";
694    }
695}
696
697const CConfigurableElement *CParameterMgr::getConfigurableElement(const string &strPath,
698                                                                  string &strError) const
699{
700    CPathNavigator pathNavigator(strPath);
701
702    // Nagivate through system class
703    if (!pathNavigator.navigateThrough(getConstSystemClass()->getName(), strError)) {
704
705        return NULL;
706    }
707
708    // Find element
709    const CElement *pElement = getConstSystemClass()->findDescendant(pathNavigator);
710
711    if (!pElement) {
712
713        strError = "Path not found: " + strPath;
714
715        return NULL;
716    }
717
718    // Check found element is a parameter
719    const CConfigurableElement *pConfigurableElement =
720        static_cast<const CConfigurableElement *>(pElement);
721
722    return pConfigurableElement;
723}
724
725CConfigurableElement *CParameterMgr::getConfigurableElement(const string &strPath, string &strError)
726{
727    // Implement the mutable version by calling the const one and removing
728    // the const from the result.
729    const auto *constThis = this;
730    return const_cast<CConfigurableElement *>(constThis->getConfigurableElement(strPath, strError));
731}
732
733// Dynamic parameter handling
734CParameterHandle *CParameterMgr::createParameterHandle(const string &strPath, string &strError)
735{
736    CConfigurableElement *pConfigurableElement = getConfigurableElement(strPath, strError);
737
738    if (!pConfigurableElement) {
739
740        // Element not found
741        strError = "Element not found: " + strPath;
742        return NULL;
743    }
744
745    if (!pConfigurableElement->isParameter()) {
746
747        // Element is not parameter
748        strError = "Not a parameter: " + strPath;
749
750        return NULL;
751    }
752
753    // Convert as parameter and return new handle
754    return new CParameterHandle(static_cast<CBaseParameter &>(*pConfigurableElement), *this);
755}
756
757// Dynamic element handling
758ElementHandle *CParameterMgr::createElementHandle(const std::string &path, std::string &error)
759{
760    CConfigurableElement *pConfigurableElement;
761
762    if (path == "/") {
763        // Attempt to access root configurable element
764        pConfigurableElement = getSystemClass();
765    } else {
766        pConfigurableElement = getConfigurableElement(path, error);
767    }
768
769    if (!pConfigurableElement) {
770
771        // Element not found
772        error = "Element not found: " + path;
773        return nullptr;
774    }
775
776    // The only reason why a heap object is returned instead of retuning by copy
777    // is to inform the client of a failure through a nullptr.
778    // It could be avoided (return by copy) with an
779    //  - optional equivalent (see boost::optional or std::experimental::optional)
780    //  - exception (but the api is noexcept)
781    return new ElementHandle(*pConfigurableElement, *this);
782}
783
784void CParameterMgr::getSettingsAsBytes(const CConfigurableElement &element,
785                                       std::vector<uint8_t> &settings) const
786{
787    // Not useful as the get can not fail,
788    // but the current design forces all serialization and deserialization to
789    // have an error out string
790    std::string error;
791
792    // Prepare parameter access context for main blackboard.
793    // No need to handle output raw format and value space as Byte arrays are hexa formatted
794    CParameterAccessContext parameterAccessContext(error);
795    parameterAccessContext.setParameterBlackboard(_pMainParameterBlackboard);
796
797    // Get the settings
798    element.getSettingsAsBytes(settings, parameterAccessContext);
799}
800
801bool CParameterMgr::setSettingsAsBytes(const CConfigurableElement &element,
802                                       const std::vector<uint8_t> &settings, std::string &error)
803{
804    // Prepare parameter access context for main blackboard.
805    // Notes:
806    //     - No need to handle output raw format and value space as Byte arrays are interpreted as
807    //     raw formatted
808    //     - No check is done as to the intgrity of the input data.
809    //       This may lead to undetected out of range value assignment.
810    //       Use this functionality with caution
811    CParameterAccessContext parameterAccessContext(error);
812    parameterAccessContext.setParameterBlackboard(_pMainParameterBlackboard);
813    parameterAccessContext.setAutoSync(autoSyncOn());
814
815    // Set the settings
816    return element.setSettingsAsBytes(settings, parameterAccessContext);
817}
818
819void CParameterMgr::setFailureOnMissingSubsystem(bool bFail)
820{
821    _bFailOnMissingSubsystem = bFail;
822}
823
824bool CParameterMgr::getFailureOnMissingSubsystem() const
825{
826    return _bFailOnMissingSubsystem;
827}
828
829void CParameterMgr::setFailureOnFailedSettingsLoad(bool bFail)
830{
831    _bFailOnFailedSettingsLoad = bFail;
832}
833
834bool CParameterMgr::getFailureOnFailedSettingsLoad() const
835{
836    return _bFailOnFailedSettingsLoad;
837}
838
839const string &CParameterMgr::getSchemaUri() const
840{
841    return _schemaUri;
842}
843
844void CParameterMgr::setSchemaUri(const string &schemaUri)
845{
846    _schemaUri = schemaUri;
847}
848
849void CParameterMgr::setValidateSchemasOnStart(bool bValidate)
850{
851    _bValidateSchemasOnStart = bValidate;
852}
853
854bool CParameterMgr::getValidateSchemasOnStart() const
855{
856    return _bValidateSchemasOnStart;
857}
858
859/////////////////// Remote command parsers
860/// Version
861CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::versionCommandProcess(
862    const IRemoteCommand & /*command*/, string &strResult)
863{
864    // Show version
865    strResult = getVersion();
866
867    return CCommandHandler::ESucceeded;
868}
869
870/// Status
871CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::statusCommandProcess(
872    const IRemoteCommand & /*command*/, string &strResult)
873{
874    // System class
875    const CSystemClass *pSystemClass = getSystemClass();
876
877    // Show status
878    /// General section
879    utility::appendTitle(strResult, "General:");
880    // System class
881    strResult += "System Class: ";
882    strResult += pSystemClass->getName();
883    strResult += "\n";
884
885    // Tuning mode
886    strResult += "Tuning Mode: ";
887    strResult += tuningModeOn() ? "on" : "off";
888    strResult += "\n";
889
890    // Value space
891    strResult += "Value Space: ";
892    strResult += valueSpaceIsRaw() ? "raw" : "real";
893    strResult += "\n";
894
895    // Output raw format
896    strResult += "Output Raw Format: ";
897    strResult += outputRawFormatIsHex() ? "hex" : "dec";
898    strResult += "\n";
899
900    // Auto Sync
901    strResult += "Auto Sync: ";
902    strResult += autoSyncOn() ? "on" : "off";
903    strResult += "\n";
904
905    /// Subsystem list
906    utility::appendTitle(strResult, "Subsystems:");
907    string strSubsystemList;
908    pSystemClass->listChildrenPaths(strSubsystemList);
909    strResult += strSubsystemList;
910
911    /// Last applied configurations
912    utility::appendTitle(strResult, "Last Applied [Pending] Configurations:");
913    string strLastAppliedConfigurations;
914    getConfigurableDomains()->listLastAppliedConfigurations(strLastAppliedConfigurations);
915    strResult += strLastAppliedConfigurations;
916
917    /// Criteria states
918    utility::appendTitle(strResult, "Selection Criteria:");
919    list<string> lstrSelectionCriteria;
920    getSelectionCriteria()->listSelectionCriteria(lstrSelectionCriteria, false, true);
921    // Concatenate the criterion list as the command result
922    strResult += utility::asString(lstrSelectionCriteria);
923
924    return CCommandHandler::ESucceeded;
925}
926
927/// Tuning Mode
928CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setTuningModeCommandProcess(
929    const IRemoteCommand &remoteCommand, string &strResult)
930{
931    if (remoteCommand.getArgument(0) == "on") {
932
933        if (setTuningMode(true, strResult)) {
934
935            return CCommandHandler::EDone;
936        }
937    } else if (remoteCommand.getArgument(0) == "off") {
938
939        if (setTuningMode(false, strResult)) {
940
941            return CCommandHandler::EDone;
942        }
943    } else {
944        // Show usage
945        return CCommandHandler::EShowUsage;
946    }
947    return CCommandHandler::EFailed;
948}
949
950CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getTuningModeCommandProcess(
951    const IRemoteCommand & /*command*/, string &strResult)
952{
953    strResult = tuningModeOn() ? "on" : "off";
954
955    return CCommandHandler::ESucceeded;
956}
957
958/// Value Space
959CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setValueSpaceCommandProcess(
960    const IRemoteCommand &remoteCommand, string & /*strResult*/)
961{
962    if (remoteCommand.getArgument(0) == "raw") {
963
964        setValueSpace(true);
965
966        return CCommandHandler::EDone;
967
968    } else if (remoteCommand.getArgument(0) == "real") {
969
970        setValueSpace(false);
971
972        return CCommandHandler::EDone;
973
974    } else {
975        // Show usage
976        return CCommandHandler::EShowUsage;
977    }
978    return CCommandHandler::EFailed;
979}
980
981CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getValueSpaceCommandProcess(
982    const IRemoteCommand & /*command*/, string &strResult)
983{
984    strResult = valueSpaceIsRaw() ? "raw" : "real";
985
986    return CCommandHandler::ESucceeded;
987}
988
989/// Output Raw Format
990CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setOutputRawFormatCommandProcess(
991    const IRemoteCommand &remoteCommand, string & /*strResult*/)
992{
993    if (remoteCommand.getArgument(0) == "hex") {
994
995        setOutputRawFormat(true);
996
997        return CCommandHandler::EDone;
998
999    } else if (remoteCommand.getArgument(0) == "dec") {
1000
1001        setOutputRawFormat(false);
1002
1003        return CCommandHandler::EDone;
1004
1005    } else {
1006        // Show usage
1007        return CCommandHandler::EShowUsage;
1008    }
1009    return CCommandHandler::EFailed;
1010}
1011
1012CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getOutputRawFormatCommandProcess(
1013    const IRemoteCommand & /*command*/, string &strResult)
1014{
1015    strResult = outputRawFormatIsHex() ? "hex" : "dec";
1016
1017    return CCommandHandler::ESucceeded;
1018}
1019
1020/// Sync
1021CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setAutoSyncCommandProcess(
1022    const IRemoteCommand &remoteCommand, string &strResult)
1023{
1024    if (remoteCommand.getArgument(0) == "on") {
1025
1026        if (setAutoSync(true, strResult)) {
1027
1028            return CCommandHandler::EDone;
1029        }
1030    } else if (remoteCommand.getArgument(0) == "off") {
1031
1032        if (setAutoSync(false, strResult)) {
1033
1034            return CCommandHandler::EDone;
1035        }
1036    } else {
1037        // Show usage
1038        return CCommandHandler::EShowUsage;
1039    }
1040    return CCommandHandler::EFailed;
1041}
1042
1043CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getAutoSyncCommandProcess(
1044    const IRemoteCommand & /*command*/, string &strResult)
1045{
1046    strResult = autoSyncOn() ? "on" : "off";
1047
1048    return CCommandHandler::ESucceeded;
1049}
1050
1051CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::syncCommandProcess(
1052    const IRemoteCommand &, string &strResult)
1053{
1054    return sync(strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed;
1055}
1056
1057/// Criteria
1058CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listCriteriaCommandProcess(
1059    const IRemoteCommand &remoteCommand, string &strResult)
1060{
1061    if (remoteCommand.getArgumentCount() > 1) {
1062
1063        return CCommandHandler::EShowUsage;
1064    }
1065
1066    string strOutputFormat;
1067
1068    // Look for optional arguments
1069    if (remoteCommand.getArgumentCount() == 1) {
1070
1071        // Get requested format
1072        strOutputFormat = remoteCommand.getArgument(0);
1073
1074        // Capitalize
1075        std::transform(strOutputFormat.begin(), strOutputFormat.end(), strOutputFormat.begin(),
1076                       ::toupper);
1077
1078        if (strOutputFormat != "XML" && strOutputFormat != "CSV") {
1079
1080            return CCommandHandler::EShowUsage;
1081        }
1082    }
1083
1084    if (strOutputFormat == "XML") {
1085        // Get Root element where to export from
1086        const CSelectionCriteriaDefinition *pSelectionCriteriaDefinition =
1087            getConstSelectionCriteria()->getSelectionCriteriaDefinition();
1088
1089        if (!exportElementToXMLString(pSelectionCriteriaDefinition, "SelectionCriteria",
1090                                      CXmlSerializingContext{strResult}, strResult)) {
1091
1092            return CCommandHandler::EFailed;
1093        }
1094
1095        // Succeeded
1096        return CCommandHandler::ESucceeded;
1097    } else {
1098
1099        // Requested format will be either CSV or human readable based on strOutputFormat content
1100        bool bHumanReadable = strOutputFormat.empty();
1101
1102        list<string> lstrResult;
1103        getSelectionCriteria()->listSelectionCriteria(lstrResult, true, bHumanReadable);
1104
1105        // Concatenate the criterion list as the command result
1106        strResult += utility::asString(lstrResult);
1107
1108        return CCommandHandler::ESucceeded;
1109    }
1110}
1111
1112/// Domains
1113CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listDomainsCommandProcess(
1114    const IRemoteCommand & /*command*/, string &strResult)
1115{
1116    getConfigurableDomains()->listDomains(strResult);
1117
1118    return CCommandHandler::ESucceeded;
1119}
1120
1121CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::createDomainCommandProcess(
1122    const IRemoteCommand &remoteCommand, string &strResult)
1123{
1124    return createDomain(remoteCommand.getArgument(0), strResult) ? CCommandHandler::EDone
1125                                                                 : CCommandHandler::EFailed;
1126}
1127
1128CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::deleteDomainCommandProcess(
1129    const IRemoteCommand &remoteCommand, string &strResult)
1130{
1131    return deleteDomain(remoteCommand.getArgument(0), strResult) ? CCommandHandler::EDone
1132                                                                 : CCommandHandler::EFailed;
1133}
1134
1135CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::deleteAllDomainsCommandProcess(
1136    const IRemoteCommand & /*command*/, string &strResult)
1137{
1138    return deleteAllDomains(strResult) ? CCommandHandler::EDone : CCommandHandler::EFailed;
1139}
1140
1141CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::renameDomainCommandProcess(
1142    const IRemoteCommand &remoteCommand, string &strResult)
1143{
1144    return renameDomain(remoteCommand.getArgument(0), remoteCommand.getArgument(1), strResult)
1145               ? CCommandHandler::EDone
1146               : CCommandHandler::EFailed;
1147}
1148
1149CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setSequenceAwarenessCommandProcess(
1150    const IRemoteCommand &remoteCommand, string &strResult)
1151{
1152    // Set property
1153    bool bSequenceAware;
1154
1155    if (remoteCommand.getArgument(1) == "true") {
1156
1157        bSequenceAware = true;
1158
1159    } else if (remoteCommand.getArgument(1) == "false") {
1160
1161        bSequenceAware = false;
1162
1163    } else {
1164        // Show usage
1165        return CCommandHandler::EShowUsage;
1166    }
1167
1168    return setSequenceAwareness(remoteCommand.getArgument(0), bSequenceAware, strResult)
1169               ? CCommandHandler::EDone
1170               : CCommandHandler::EFailed;
1171}
1172
1173CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getSequenceAwarenessCommandProcess(
1174    const IRemoteCommand &remoteCommand, string &strResult)
1175{
1176    // Get property
1177    bool bSequenceAware;
1178
1179    if (!getSequenceAwareness(remoteCommand.getArgument(0), bSequenceAware, strResult)) {
1180
1181        return CCommandHandler::EFailed;
1182    }
1183
1184    strResult = bSequenceAware ? "true" : "false";
1185
1186    return CCommandHandler::ESucceeded;
1187}
1188
1189CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listDomainElementsCommandProcess(
1190    const IRemoteCommand &remoteCommand, string &strResult)
1191{
1192    return getConfigurableDomains()->listDomainElements(remoteCommand.getArgument(0), strResult)
1193               ? CCommandHandler::ESucceeded
1194               : CCommandHandler::EFailed;
1195}
1196
1197CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::addElementCommandProcess(
1198    const IRemoteCommand &remoteCommand, string &strResult)
1199{
1200    return addConfigurableElementToDomain(remoteCommand.getArgument(0),
1201                                          remoteCommand.getArgument(1), strResult)
1202               ? CCommandHandler::EDone
1203               : CCommandHandler::EFailed;
1204}
1205
1206CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::removeElementCommandProcess(
1207    const IRemoteCommand &remoteCommand, string &strResult)
1208{
1209    return removeConfigurableElementFromDomain(remoteCommand.getArgument(0),
1210                                               remoteCommand.getArgument(1), strResult)
1211               ? CCommandHandler::EDone
1212               : CCommandHandler::EFailed;
1213}
1214
1215CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::splitDomainCommandProcess(
1216    const IRemoteCommand &remoteCommand, string &strResult)
1217{
1218    return split(remoteCommand.getArgument(0), remoteCommand.getArgument(1), strResult)
1219               ? CCommandHandler::EDone
1220               : CCommandHandler::EFailed;
1221}
1222
1223/// Configurations
1224CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listConfigurationsCommandProcess(
1225    const IRemoteCommand &remoteCommand, string &strResult)
1226{
1227    return getConstConfigurableDomains()->listConfigurations(remoteCommand.getArgument(0),
1228                                                             strResult)
1229               ? CCommandHandler::ESucceeded
1230               : CCommandHandler::EFailed;
1231}
1232
1233CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::dumpDomainsCommandProcess(
1234    const IRemoteCommand & /*command*/, string &strResult)
1235{
1236    // Dummy error context
1237    string strError;
1238    utility::ErrorContext errorContext(strError);
1239
1240    // Dump
1241    strResult = getConstConfigurableDomains()->dumpContent(errorContext);
1242
1243    return CCommandHandler::ESucceeded;
1244}
1245
1246CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::createConfigurationCommandProcess(
1247    const IRemoteCommand &remoteCommand, string &strResult)
1248{
1249    return createConfiguration(remoteCommand.getArgument(0), remoteCommand.getArgument(1),
1250                               strResult)
1251               ? CCommandHandler::EDone
1252               : CCommandHandler::EFailed;
1253}
1254
1255CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::deleteConfigurationCommandProcess(
1256    const IRemoteCommand &remoteCommand, string &strResult)
1257{
1258    return deleteConfiguration(remoteCommand.getArgument(0), remoteCommand.getArgument(1),
1259                               strResult)
1260               ? CCommandHandler::EDone
1261               : CCommandHandler::EFailed;
1262}
1263
1264CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::renameConfigurationCommandProcess(
1265    const IRemoteCommand &remoteCommand, string &strResult)
1266{
1267    return renameConfiguration(remoteCommand.getArgument(0), remoteCommand.getArgument(1),
1268                               remoteCommand.getArgument(2), strResult)
1269               ? CCommandHandler::EDone
1270               : CCommandHandler::EFailed;
1271}
1272
1273CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::saveConfigurationCommandProcess(
1274    const IRemoteCommand &remoteCommand, string &strResult)
1275{
1276    return saveConfiguration(remoteCommand.getArgument(0), remoteCommand.getArgument(1), strResult)
1277               ? CCommandHandler::EDone
1278               : CCommandHandler::EFailed;
1279}
1280
1281CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::restoreConfigurationCommandProcess(
1282    const IRemoteCommand &remoteCommand, string &strResult)
1283{
1284    core::Results result;
1285    if (!restoreConfiguration(remoteCommand.getArgument(0), remoteCommand.getArgument(1), result)) {
1286        // Concatenate the error list as the command result
1287        strResult = utility::asString(result);
1288
1289        return CCommandHandler::EFailed;
1290    }
1291    return CCommandHandler::EDone;
1292}
1293
1294CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setElementSequenceCommandProcess(
1295    const IRemoteCommand &remoteCommand, string &strResult)
1296{
1297    // Build configurable element path list
1298    std::vector<string> astrNewElementSequence;
1299
1300    for (size_t argument = 2; argument < remoteCommand.getArgumentCount(); argument++) {
1301
1302        astrNewElementSequence.push_back(remoteCommand.getArgument(argument));
1303    }
1304
1305    // Delegate to configurable domains
1306    return setElementSequence(remoteCommand.getArgument(0), remoteCommand.getArgument(1),
1307                              astrNewElementSequence, strResult)
1308               ? CCommandHandler::EDone
1309               : CCommandHandler::EFailed;
1310}
1311
1312CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getElementSequenceCommandProcess(
1313    const IRemoteCommand &remoteCommand, string &strResult)
1314{
1315    // Delegate to configurable domains
1316    return getConfigurableDomains()->getElementSequence(remoteCommand.getArgument(0),
1317                                                        remoteCommand.getArgument(1), strResult)
1318               ? CCommandHandler::ESucceeded
1319               : CCommandHandler::EFailed;
1320}
1321
1322CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setRuleCommandProcess(
1323    const IRemoteCommand &remoteCommand, string &strResult)
1324{
1325    // Delegate to configurable domains
1326    return setApplicationRule(remoteCommand.getArgument(0), remoteCommand.getArgument(1),
1327                              remoteCommand.packArguments(2, remoteCommand.getArgumentCount() - 2),
1328                              strResult)
1329               ? CCommandHandler::EDone
1330               : CCommandHandler::EFailed;
1331}
1332
1333CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::clearRuleCommandProcess(
1334    const IRemoteCommand &remoteCommand, string &strResult)
1335{
1336    // Delegate to configurable domains
1337    return clearApplicationRule(remoteCommand.getArgument(0), remoteCommand.getArgument(1),
1338                                strResult)
1339               ? CCommandHandler::EDone
1340               : CCommandHandler::EFailed;
1341}
1342
1343CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getRuleCommandProcess(
1344    const IRemoteCommand &remoteCommand, string &strResult)
1345{
1346    // Delegate to configurable domains
1347    return getApplicationRule(remoteCommand.getArgument(0), remoteCommand.getArgument(1), strResult)
1348               ? CCommandHandler::ESucceeded
1349               : CCommandHandler::EFailed;
1350}
1351
1352/// Elements/Parameters
1353CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listElementsCommandProcess(
1354    const IRemoteCommand &remoteCommand, string &strResult)
1355{
1356    CElementLocator elementLocator(getSystemClass(), false);
1357
1358    CElement *pLocatedElement = NULL;
1359
1360    if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) {
1361
1362        return CCommandHandler::EFailed;
1363    }
1364
1365    if (!pLocatedElement) {
1366
1367        // List from root folder
1368
1369        // Return system class qualified name
1370        pLocatedElement = getSystemClass();
1371    }
1372
1373    // Return sub-elements
1374    strResult += pLocatedElement->listQualifiedPaths(false);
1375
1376    return CCommandHandler::ESucceeded;
1377}
1378
1379/// Elements/Parameters
1380CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listParametersCommandProcess(
1381    const IRemoteCommand &remoteCommand, string &strResult)
1382{
1383    CElementLocator elementLocator(getSystemClass(), false);
1384
1385    CElement *pLocatedElement = NULL;
1386
1387    if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) {
1388
1389        return CCommandHandler::EFailed;
1390    }
1391
1392    if (!pLocatedElement) {
1393
1394        // List from root folder
1395
1396        // Return system class qualified name
1397        pLocatedElement = getSystemClass();
1398    }
1399
1400    // Return sub-elements
1401    strResult += pLocatedElement->listQualifiedPaths(true);
1402
1403    return CCommandHandler::ESucceeded;
1404}
1405
1406CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getElementStructureXMLCommandProcess(
1407    const IRemoteCommand &remoteCommand, string &strResult)
1408{
1409    CElementLocator elementLocator(getSystemClass());
1410
1411    CElement *pLocatedElement = NULL;
1412
1413    if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) {
1414
1415        return CCommandHandler::EFailed;
1416    }
1417
1418    // Use default access context for structure export
1419    CParameterAccessContext accessContext(strResult);
1420    if (!exportElementToXMLString(pLocatedElement, pLocatedElement->getXmlElementName(),
1421                                  CXmlParameterSerializingContext{accessContext, strResult},
1422                                  strResult)) {
1423
1424        return CCommandHandler::EFailed;
1425    }
1426
1427    return CCommandHandler::ESucceeded;
1428}
1429
1430CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getElementBytesCommandProcess(
1431    const IRemoteCommand &remoteCommand, std::string &strResult)
1432{
1433    CElementLocator elementLocator(getSystemClass());
1434
1435    CElement *pLocatedElement = NULL;
1436
1437    if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) {
1438
1439        return CCommandHandler::EFailed;
1440    }
1441
1442    const CConfigurableElement *pConfigurableElement =
1443        static_cast<CConfigurableElement *>(pLocatedElement);
1444
1445    // Get the settings
1446    vector<uint8_t> bytes;
1447    getSettingsAsBytes(*pConfigurableElement, bytes);
1448
1449    // Hexa formatting
1450    std::ostringstream ostream;
1451    ostream << std::hex << std::setfill('0');
1452
1453    // Format bytes
1454    for (auto byte : bytes) {
1455
1456        // Convert to an int in order to avoid the "char" overload that would
1457        // print characters instead of numbers.
1458        ostream << "0x" << std::setw(2) << int{byte} << " ";
1459    }
1460
1461    strResult = ostream.str();
1462    if (not strResult.empty()) {
1463        // Remove the trailing space
1464        strResult.pop_back();
1465    }
1466
1467    return CCommandHandler::ESucceeded;
1468}
1469
1470CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setElementBytesCommandProcess(
1471    const IRemoteCommand &remoteCommand, string &strResult)
1472{
1473    // Check tuning mode
1474    if (!checkTuningModeOn(strResult)) {
1475
1476        return CCommandHandler::EFailed;
1477    }
1478
1479    // Retrieve configurable element
1480    CElementLocator elementLocator(getSystemClass());
1481
1482    CElement *pLocatedElement = NULL;
1483
1484    if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) {
1485
1486        return CCommandHandler::EFailed;
1487    }
1488
1489    const CConfigurableElement *pConfigurableElement =
1490        static_cast<CConfigurableElement *>(pLocatedElement);
1491
1492    // Convert input data to binary
1493    vector<uint8_t> bytes;
1494
1495    auto first = remoteCommand.getArguments().cbegin() + 1;
1496    auto last = remoteCommand.getArguments().cend();
1497
1498    try {
1499        std::transform(first, last, begin(bytes), [](decltype(*first) input) {
1500            uint8_t byte;
1501
1502            if (!convertTo(input, byte)) {
1503                throw std::domain_error("Some values out of byte range");
1504            }
1505
1506            return byte;
1507        });
1508    } catch (const std::domain_error &e) {
1509        strResult = e.what();
1510
1511        return CCommandHandler::EFailed;
1512    }
1513
1514    // Set the settings
1515    if (!setSettingsAsBytes(*pConfigurableElement, bytes, strResult)) {
1516
1517        return CCommandHandler::EFailed;
1518    }
1519
1520    return CCommandHandler::EDone;
1521}
1522
1523bool CParameterMgr::getSettingsAsXML(const CConfigurableElement *configurableElement,
1524                                     string &result) const
1525{
1526    string error;
1527    CConfigurationAccessContext configContext(error, _pMainParameterBlackboard, _bValueSpaceIsRaw,
1528                                              _bOutputRawFormatIsHex, true);
1529
1530    CXmlParameterSerializingContext xmlParameterContext(configContext, error);
1531
1532    // Use a doc source by loading data from instantiated Configurable Domains
1533    CXmlMemoryDocSource memorySource(configurableElement, false,
1534                                     configurableElement->getXmlElementName());
1535
1536    // Use a doc sink that write the doc data in a string
1537    ostringstream output;
1538    CXmlStreamDocSink streamSink(output);
1539
1540    if (not streamSink.process(memorySource, xmlParameterContext)) {
1541        result = error;
1542        return false;
1543    }
1544    result = output.str();
1545    return true;
1546}
1547
1548bool CParameterMgr::setSettingsAsXML(CConfigurableElement *configurableElement,
1549                                     const string &settings, string &error)
1550{
1551    CConfigurationAccessContext configContext(error, _pMainParameterBlackboard, _bValueSpaceIsRaw,
1552                                              _bOutputRawFormatIsHex, false);
1553
1554    CXmlParameterSerializingContext xmlParameterContext(configContext, error);
1555
1556    // It doesn't make sense to resolve XIncludes on an imported file because
1557    // we can't reliably decide of a "base url"
1558    _xmlDoc *doc = CXmlDocSource::mkXmlDoc(settings, false, false, xmlParameterContext);
1559    if (doc == nullptr) {
1560        return false;
1561    }
1562    if (not xmlParse(xmlParameterContext, configurableElement, doc, "",
1563                     EParameterConfigurationLibrary, false)) {
1564        return false;
1565    }
1566    if (_bAutoSyncOn) {
1567        CSyncerSet syncerSet;
1568        static_cast<CConfigurableElement *>(configurableElement)->fillSyncerSet(syncerSet);
1569        core::Results errors;
1570        if (not syncerSet.sync(*_pMainParameterBlackboard, false, &errors)) {
1571            error = utility::asString(errors);
1572
1573            return false;
1574        }
1575    }
1576    return true;
1577}
1578
1579CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getElementXMLCommandProcess(
1580    const IRemoteCommand &remoteCommand, string &result)
1581{
1582    CElementLocator elementLocator(getSystemClass());
1583
1584    CElement *locatedElement = nullptr;
1585
1586    if (not elementLocator.locate(remoteCommand.getArgument(0), &locatedElement, result)) {
1587
1588        return CCommandHandler::EFailed;
1589    }
1590
1591    if (not getSettingsAsXML(static_cast<CConfigurableElement *>(locatedElement), result)) {
1592        return CCommandHandler::EFailed;
1593    }
1594    return CCommandHandler::ESucceeded;
1595}
1596
1597CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setElementXMLCommandProcess(
1598    const IRemoteCommand &remoteCommand, string &result)
1599{
1600    if (!checkTuningModeOn(result)) {
1601
1602        return CCommandHandler::EFailed;
1603    }
1604
1605    CElementLocator elementLocator(getSystemClass());
1606
1607    CElement *locatedElement = nullptr;
1608
1609    if (not elementLocator.locate(remoteCommand.getArgument(0), &locatedElement, result)) {
1610
1611        return CCommandHandler::EFailed;
1612    }
1613    if (not setSettingsAsXML(static_cast<CConfigurableElement *>(locatedElement),
1614                             remoteCommand.getArgument(1), result)) {
1615        return CCommandHandler::EFailed;
1616    }
1617    return CCommandHandler::EDone;
1618}
1619
1620CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::dumpElementCommandProcess(
1621    const IRemoteCommand &remoteCommand, string &strResult)
1622{
1623    CElementLocator elementLocator(getSystemClass());
1624
1625    CElement *pLocatedElement = NULL;
1626
1627    if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) {
1628
1629        return CCommandHandler::EFailed;
1630    }
1631
1632    string strError;
1633
1634    CParameterAccessContext parameterAccessContext(strError, _pMainParameterBlackboard,
1635                                                   _bValueSpaceIsRaw, _bOutputRawFormatIsHex);
1636
1637    // Dump elements
1638    strResult = pLocatedElement->dumpContent(parameterAccessContext);
1639
1640    return CCommandHandler::ESucceeded;
1641}
1642
1643CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getElementSizeCommandProcess(
1644    const IRemoteCommand &remoteCommand, string &strResult)
1645{
1646    CElementLocator elementLocator(getSystemClass());
1647
1648    CElement *pLocatedElement = NULL;
1649
1650    if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) {
1651
1652        return CCommandHandler::EFailed;
1653    }
1654
1655    // Converted to actual sizable element
1656    const CConfigurableElement *pConfigurableElement =
1657        static_cast<const CConfigurableElement *>(pLocatedElement);
1658
1659    // Get size as string
1660    strResult = pConfigurableElement->getFootprintAsString();
1661
1662    return CCommandHandler::ESucceeded;
1663}
1664
1665CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::showPropertiesCommandProcess(
1666    const IRemoteCommand &remoteCommand, string &strResult)
1667{
1668    CElementLocator elementLocator(getSystemClass());
1669
1670    CElement *pLocatedElement = NULL;
1671
1672    if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) {
1673
1674        return CCommandHandler::EFailed;
1675    }
1676
1677    // Convert element
1678    const CConfigurableElement *pConfigurableElement =
1679        static_cast<const CConfigurableElement *>(pLocatedElement);
1680
1681    // Return element properties
1682    pConfigurableElement->showProperties(strResult);
1683
1684    return CCommandHandler::ESucceeded;
1685}
1686
1687CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getParameterCommandProcess(
1688    const IRemoteCommand &remoteCommand, string &strResult)
1689{
1690    string strValue;
1691
1692    if (!accessParameterValue(remoteCommand.getArgument(0), strValue, false, strResult)) {
1693
1694        return CCommandHandler::EFailed;
1695    }
1696    // Succeeded
1697    strResult = strValue;
1698
1699    return CCommandHandler::ESucceeded;
1700}
1701
1702CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setParameterCommandProcess(
1703    const IRemoteCommand &remoteCommand, string &strResult)
1704{
1705    // Get value to set
1706    string strValue = remoteCommand.packArguments(1, remoteCommand.getArgumentCount() - 1);
1707
1708    return accessParameterValue(remoteCommand.getArgument(0), strValue, true, strResult)
1709               ? CCommandHandler::EDone
1710               : CCommandHandler::EFailed;
1711}
1712
1713CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listBelongingDomainsCommandProcess(
1714    const IRemoteCommand &remoteCommand, string &strResult)
1715{
1716    CElementLocator elementLocator(getSystemClass());
1717
1718    CElement *pLocatedElement = NULL;
1719
1720    if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) {
1721
1722        return CCommandHandler::EFailed;
1723    }
1724
1725    // Convert element
1726    const CConfigurableElement *pConfigurableElement =
1727        static_cast<const CConfigurableElement *>(pLocatedElement);
1728
1729    // Return element belonging domains
1730    pConfigurableElement->listBelongingDomains(strResult);
1731
1732    return CCommandHandler::ESucceeded;
1733}
1734
1735CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listAssociatedDomainsCommandProcess(
1736    const IRemoteCommand &remoteCommand, string &strResult)
1737{
1738    CElementLocator elementLocator(getSystemClass());
1739
1740    CElement *pLocatedElement = NULL;
1741
1742    if (!elementLocator.locate(remoteCommand.getArgument(0), &pLocatedElement, strResult)) {
1743
1744        return CCommandHandler::EFailed;
1745    }
1746
1747    // Convert element
1748    const CConfigurableElement *pConfigurableElement =
1749        static_cast<const CConfigurableElement *>(pLocatedElement);
1750
1751    // Return element belonging domains
1752    pConfigurableElement->listAssociatedDomains(strResult);
1753
1754    return CCommandHandler::ESucceeded;
1755}
1756
1757CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listAssociatedElementsCommandProcess(
1758    const IRemoteCommand & /*command*/, string &strResult)
1759{
1760    getConfigurableDomains()->listAssociatedElements(strResult);
1761
1762    return CCommandHandler::ESucceeded;
1763}
1764
1765CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listConflictingElementsCommandProcess(
1766    const IRemoteCommand & /*command*/, string &strResult)
1767{
1768    getConfigurableDomains()->listConflictingElements(strResult);
1769
1770    return CCommandHandler::ESucceeded;
1771}
1772
1773CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::listRogueElementsCommandProcess(
1774    const IRemoteCommand & /*command*/, string &strResult)
1775{
1776    getSystemClass()->listRogueElements(strResult);
1777
1778    return CCommandHandler::ESucceeded;
1779}
1780
1781CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::
1782    getConfigurationParameterCommandProcess(const IRemoteCommand &remoteCommand, string &strResult)
1783{
1784    string strOutputValue;
1785    string strError;
1786
1787    if (!accessConfigurationValue(remoteCommand.getArgument(0), remoteCommand.getArgument(1),
1788                                  remoteCommand.getArgument(2), strOutputValue, false, strError)) {
1789
1790        strResult = strError;
1791        return CCommandHandler::EFailed;
1792    }
1793    // Succeeded
1794    strResult = strOutputValue;
1795
1796    return CCommandHandler::ESucceeded;
1797}
1798
1799CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::
1800    setConfigurationParameterCommandProcess(const IRemoteCommand &remoteCommand, string &strResult)
1801{
1802    // Get value to set
1803    string strValue = remoteCommand.packArguments(3, remoteCommand.getArgumentCount() - 3);
1804
1805    bool bSuccess =
1806        accessConfigurationValue(remoteCommand.getArgument(0), remoteCommand.getArgument(1),
1807                                 remoteCommand.getArgument(2), strValue, true, strResult);
1808
1809    return bSuccess ? CCommandHandler::EDone : CCommandHandler::EFailed;
1810}
1811
1812CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::showMappingCommandProcess(
1813    const IRemoteCommand &remoteCommand, string &strResult)
1814{
1815    if (!getParameterMapping(remoteCommand.getArgument(0), strResult)) {
1816
1817        return CCommandHandler::EFailed;
1818    }
1819
1820    return CCommandHandler::ESucceeded;
1821}
1822
1823/// Settings Import/Export
1824CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::exportDomainsXMLCommandProcess(
1825    const IRemoteCommand &remoteCommand, string &strResult)
1826{
1827    string strFileName = remoteCommand.getArgument(0);
1828    return exportDomainsXml(strFileName, false, true, strResult) ? CCommandHandler::EDone
1829                                                                 : CCommandHandler::EFailed;
1830}
1831
1832CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::importDomainsXMLCommandProcess(
1833    const IRemoteCommand &remoteCommand, string &strResult)
1834{
1835    return importDomainsXml(remoteCommand.getArgument(0), false, true, strResult)
1836               ? CCommandHandler::EDone
1837               : CCommandHandler::EFailed;
1838}
1839
1840CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::
1841    exportDomainsWithSettingsXMLCommandProcess(const IRemoteCommand &remoteCommand,
1842                                               string &strResult)
1843{
1844    string strFileName = remoteCommand.getArgument(0);
1845    return exportDomainsXml(strFileName, true, true, strResult) ? CCommandHandler::EDone
1846                                                                : CCommandHandler::EFailed;
1847}
1848
1849CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::
1850    exportDomainWithSettingsXMLCommandProcess(const IRemoteCommand &remoteCommand, string &result)
1851{
1852    string domainName = remoteCommand.getArgument(0);
1853    string fileName = remoteCommand.getArgument(1);
1854    return exportSingleDomainXml(fileName, domainName, true, true, result)
1855               ? CCommandHandler::EDone
1856               : CCommandHandler::EFailed;
1857}
1858
1859CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::
1860    importDomainsWithSettingsXMLCommandProcess(const IRemoteCommand &remoteCommand,
1861                                               string &strResult)
1862{
1863    return importDomainsXml(remoteCommand.getArgument(0), true, true, strResult)
1864               ? CCommandHandler::EDone
1865               : CCommandHandler::EFailed;
1866}
1867
1868CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::
1869    importDomainWithSettingsXMLCommandProcess(const IRemoteCommand &remoteCommand,
1870                                              string &strResult)
1871{
1872    bool bOverwrite = false;
1873
1874    // Look for optional arguments
1875    if (remoteCommand.getArgumentCount() > 1) {
1876
1877        if (remoteCommand.getArgument(1) == "overwrite") {
1878
1879            bOverwrite = true;
1880        } else {
1881            // Show usage
1882            return CCommandHandler::EShowUsage;
1883        }
1884    }
1885
1886    return importSingleDomainXml(remoteCommand.getArgument(0), bOverwrite, true, true, strResult)
1887               ? CCommandHandler::EDone
1888               : CCommandHandler::EFailed;
1889}
1890
1891CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::
1892    getDomainsWithSettingsXMLCommandProcess(const IRemoteCommand & /*command*/, string &strResult)
1893{
1894    if (!exportDomainsXml(strResult, true, false, strResult)) {
1895
1896        return CCommandHandler::EFailed;
1897    }
1898    // Succeeded
1899    return CCommandHandler::ESucceeded;
1900}
1901
1902CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getDomainWithSettingsXMLCommandProcess(
1903    const IRemoteCommand &remoteCommand, string &strResult)
1904{
1905    string strDomainName = remoteCommand.getArgument(0);
1906
1907    return exportSingleDomainXml(strResult, strDomainName, true, false, strResult)
1908               ? CCommandHandler::ESucceeded
1909               : CCommandHandler::EFailed;
1910}
1911
1912CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::
1913    setDomainsWithSettingsXMLCommandProcess(const IRemoteCommand &remoteCommand, string &strResult)
1914{
1915    return importDomainsXml(remoteCommand.getArgument(0), true, false, strResult)
1916               ? CCommandHandler::EDone
1917               : CCommandHandler::EFailed;
1918}
1919
1920CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::setDomainWithSettingsXMLCommandProcess(
1921    const IRemoteCommand &remoteCommand, string &result)
1922{
1923    bool overwrite = false;
1924
1925    if (remoteCommand.getArgumentCount() > 1) {
1926
1927        if (remoteCommand.getArgument(1) == "overwrite") {
1928
1929            overwrite = true;
1930        } else {
1931            // Show usage
1932            return CCommandHandler::EShowUsage;
1933        }
1934    }
1935
1936    return importSingleDomainXml(remoteCommand.getArgument(0), overwrite, true, false, result)
1937               ? CCommandHandler::EDone
1938               : CCommandHandler::EFailed;
1939}
1940
1941CParameterMgr::CCommandHandler::CommandStatus CParameterMgr::getSystemClassXMLCommandProcess(
1942    const IRemoteCommand & /*command*/, string &strResult)
1943{
1944    // Get Root element where to export from
1945    const CSystemClass *pSystemClass = getSystemClass();
1946
1947    // Use default access context for structure export
1948    CParameterAccessContext accessContext(strResult);
1949    if (!exportElementToXMLString(pSystemClass, pSystemClass->getXmlElementName(),
1950                                  CXmlParameterSerializingContext{accessContext, strResult},
1951                                  strResult)) {
1952        return CCommandHandler::EFailed;
1953    }
1954    // Succeeded
1955    return CCommandHandler::ESucceeded;
1956}
1957
1958// User set/get parameters in main BlackBoard
1959bool CParameterMgr::accessParameterValue(const string &strPath, string &strValue, bool bSet,
1960                                         string &strError)
1961{
1962    // Forbid write access when not in TuningMode
1963    if (bSet && !checkTuningModeOn(strError)) {
1964
1965        return false;
1966    }
1967
1968    // Define context
1969    CParameterAccessContext parameterAccessContext(strError, _pMainParameterBlackboard,
1970                                                   _bValueSpaceIsRaw, _bOutputRawFormatIsHex);
1971
1972    // Activate the auto synchronization with the hardware
1973    if (bSet) {
1974
1975        parameterAccessContext.setAutoSync(_bAutoSyncOn);
1976    }
1977
1978    return accessValue(parameterAccessContext, strPath, strValue, bSet, strError);
1979}
1980
1981// User get parameter mapping
1982bool CParameterMgr::getParameterMapping(const string &strPath, string &strResult) const
1983{
1984    // Get the ConfigurableElement corresponding to strPath
1985    const CConfigurableElement *pConfigurableElement = getConfigurableElement(strPath, strResult);
1986    if (!pConfigurableElement) {
1987
1988        return false;
1989    }
1990
1991    // Find the list of the ancestors of the current ConfigurableElement that have a mapping
1992    auto configurableElementPath = pConfigurableElement->getConfigurableElementContext();
1993
1994    // Get the Subsystem containing the ConfigurableElement
1995    const CSubsystem *pSubsystem = pConfigurableElement->getBelongingSubsystem();
1996    if (!pSubsystem) {
1997
1998        strResult = "Unable to find the Subsystem containing the parameter";
1999        return false;
2000    }
2001
2002    // Fetch the mapping corresponding to the ConfigurableElement
2003    strResult = pSubsystem->getMapping(configurableElementPath);
2004
2005    return true;
2006}
2007
2008// User set/get parameters in specific Configuration BlackBoard
2009bool CParameterMgr::accessConfigurationValue(const string &strDomain,
2010                                             const string &strConfiguration, const string &strPath,
2011                                             string &strValue, bool bSet, string &strError)
2012{
2013    CElementLocator elementLocator(getSystemClass());
2014
2015    CElement *pLocatedElement = NULL;
2016
2017    if (!elementLocator.locate(strPath, &pLocatedElement, strError)) {
2018
2019        return false;
2020    }
2021
2022    // Convert element
2023    const CConfigurableElement *pConfigurableElement =
2024        static_cast<const CConfigurableElement *>(pLocatedElement);
2025
2026    // Get the Configuration blackboard and the Base Offset of the configurable element in this
2027    // blackboard
2028    size_t baseOffset;
2029    bool bIsLastApplied;
2030
2031    CParameterBlackboard *pConfigurationBlackboard = NULL;
2032
2033    {
2034        pConfigurationBlackboard = getConstConfigurableDomains()->findConfigurationBlackboard(
2035            strDomain, strConfiguration, pConfigurableElement, baseOffset, bIsLastApplied,
2036            strError);
2037        if (!pConfigurationBlackboard) {
2038
2039            warning() << "Fail: " << strError;
2040            return false;
2041        }
2042    }
2043
2044    info() << "Element " << strPath << " in Domain " << strDomain
2045           << ", offset: " << pConfigurableElement->getOffset() << ", base offset: " << baseOffset;
2046
2047    /// Update the Configuration Blackboard
2048
2049    // Define Configuration context using Base Offset and keep Auto Sync off to prevent access to HW
2050    CParameterAccessContext parameterAccessContext(
2051        strError, pConfigurationBlackboard, _bValueSpaceIsRaw, _bOutputRawFormatIsHex, baseOffset);
2052
2053    // Deactivate the auto synchronization with the hardware during the Configuration Blackboard
2054    // access (only Main Blackboard shall be synchronized, Configurations Blackboards are copied
2055    // into the Main Blackboard each time a configuration is restored but they are not synchronized
2056    // directly).
2057    if (bSet) {
2058
2059        parameterAccessContext.setAutoSync(false);
2060    }
2061
2062    // Access Value in the Configuration Blackboard
2063    if (!accessValue(parameterAccessContext, strPath, strValue, bSet, strError)) {
2064
2065        return false;
2066    }
2067
2068    /// If the Configuration is the last one applied, update the Main Blackboard as well
2069
2070    if (bIsLastApplied) {
2071
2072        // Define Main context
2073        parameterAccessContext.setParameterBlackboard(_pMainParameterBlackboard);
2074
2075        // Activate the auto synchronization with the hardware
2076        if (bSet) {
2077
2078            parameterAccessContext.setAutoSync(_bAutoSyncOn);
2079        }
2080
2081        // Access Value in the Main Blackboard
2082        return accessValue(parameterAccessContext, strPath, strValue, bSet, strError);
2083    }
2084
2085    return true;
2086}
2087
2088// User set/get parameters
2089bool CParameterMgr::accessValue(CParameterAccessContext &parameterAccessContext,
2090                                const string &strPath, string &strValue, bool bSet,
2091                                string &strError)
2092{
2093    // Lock state
2094    lock_guard<mutex> autoLock(getBlackboardMutex());
2095
2096    CPathNavigator pathNavigator(strPath);
2097
2098    // Nagivate through system class
2099    if (!pathNavigator.navigateThrough(getConstSystemClass()->getName(), strError)) {
2100
2101        parameterAccessContext.setError(strError);
2102
2103        return false;
2104    }
2105
2106    // Do the get
2107    return getConstSystemClass()->accessValue(pathNavigator, strValue, bSet,
2108                                              parameterAccessContext);
2109}
2110
2111// Tuning mode
2112bool CParameterMgr::setTuningMode(bool bOn, string &strError)
2113{
2114    if (bOn == tuningModeOn()) {
2115        strError = "Tuning mode is already in the state requested";
2116        return false;
2117    }
2118    // Tuning allowed?
2119    if (bOn && !getConstFrameworkConfiguration()->isTuningAllowed()) {
2120
2121        strError = "Tuning prohibited";
2122
2123        return false;
2124    }
2125    // Lock state
2126    lock_guard<mutex> autoLock(getBlackboardMutex());
2127
2128    // Warn domains about exiting tuning mode
2129    if (!bOn) {
2130
2131        // Ensure application of currently selected configurations
2132        // Force-apply configurations
2133        doApplyConfigurations(true);
2134    }
2135
2136    // Store
2137    _bTuningModeIsOn = bOn;
2138
2139    return true;
2140}
2141
2142bool CParameterMgr::tuningModeOn() const
2143{
2144    return _bTuningModeIsOn;
2145}
2146
2147// Current value space for user set/get value interpretation
2148void CParameterMgr::setValueSpace(bool bIsRaw)
2149{
2150    _bValueSpaceIsRaw = bIsRaw;
2151}
2152
2153bool CParameterMgr::valueSpaceIsRaw()
2154{
2155    return _bValueSpaceIsRaw;
2156}
2157
2158// Current Output Raw Format for user get value interpretation
2159void CParameterMgr::setOutputRawFormat(bool bIsHex)
2160{
2161    _bOutputRawFormatIsHex = bIsHex;
2162}
2163
2164bool CParameterMgr::outputRawFormatIsHex()
2165{
2166    return _bOutputRawFormatIsHex;
2167}
2168
2169/// Sync
2170// Automatic hardware synchronization control (during tuning session)
2171bool CParameterMgr::setAutoSync(bool bAutoSyncOn, string &strError)
2172{
2173    // Warn domains about turning auto sync back on
2174    if (bAutoSyncOn && !_bAutoSyncOn) {
2175
2176        // Do the synchronization at system class level (could be optimized by keeping track of all
2177        // modified parameters)
2178        if (!sync(strError)) {
2179
2180            return false;
2181        }
2182    }
2183
2184    // Set Auto sync
2185    _bAutoSyncOn = bAutoSyncOn;
2186
2187    return true;
2188}
2189
2190bool CParameterMgr::autoSyncOn() const
2191{
2192    return _bAutoSyncOn;
2193}
2194
2195// Manual hardware synchronization control (during tuning session)
2196bool CParameterMgr::sync(string &strError)
2197{
2198    // Warn domains about turning auto sync back on
2199    if (_bAutoSyncOn) {
2200
2201        strError = "Feature unavailable when Auto Sync is on";
2202
2203        return false;
2204    }
2205
2206    // Get syncer set
2207    CSyncerSet syncerSet;
2208    // ... from system class
2209    getConstSystemClass()->fillSyncerSet(syncerSet);
2210
2211    // Sync
2212    core::Results error;
2213    if (!syncerSet.sync(*_pMainParameterBlackboard, false, &error)) {
2214
2215        strError = utility::asString(error);
2216        return false;
2217    };
2218
2219    return true;
2220}
2221
2222// Configuration/Domains handling
2223bool CParameterMgr::createDomain(const string &strName, string &strError)
2224{
2225    LOG_CONTEXT("Creating configurable domain " + strName);
2226    // Check tuning mode
2227    if (!checkTuningModeOn(strError)) {
2228
2229        return false;
2230    }
2231
2232    // Delegate to configurable domains
2233    return logResult(getConfigurableDomains()->createDomain(strName, strError), strError);
2234}
2235
2236bool CParameterMgr::deleteDomain(const string &strName, string &strError)
2237{
2238    LOG_CONTEXT("Deleting configurable domain '" + strName + "'");
2239
2240    // Check tuning mode
2241    if (!checkTuningModeOn(strError)) {
2242
2243        warning() << "Fail: " << strError;
2244        return false;
2245    }
2246
2247    // Delegate to configurable domains
2248    return logResult(getConfigurableDomains()->deleteDomain(strName, strError), strError);
2249}
2250
2251bool CParameterMgr::renameDomain(const string &strName, const string &strNewName, string &strError)
2252{
2253    LOG_CONTEXT("Renaming configurable domain '" + strName + "' to '" + strNewName + "'");
2254
2255    // Delegate to configurable domains
2256    return logResult(getConfigurableDomains()->renameDomain(strName, strNewName, strError),
2257                     strError);
2258}
2259
2260bool CParameterMgr::deleteAllDomains(string &strError)
2261{
2262    LOG_CONTEXT("Deleting all configurable domains");
2263
2264    // Check tuning mode
2265    if (!checkTuningModeOn(strError)) {
2266
2267        warning() << "Fail: " << strError;
2268        return false;
2269    }
2270
2271    // Delegate to configurable domains
2272    getConfigurableDomains()->deleteAllDomains();
2273
2274    info() << "Success";
2275    return true;
2276}
2277
2278bool CParameterMgr::setSequenceAwareness(const string &strName, bool bSequenceAware,
2279                                         string &strResult)
2280{
2281    LOG_CONTEXT("Making domain '" + strName + "' sequence " +
2282                (bSequenceAware ? "aware" : "unaware"));
2283    // Check tuning mode
2284    if (!checkTuningModeOn(strResult)) {
2285
2286        warning() << "Fail: " << strResult;
2287        return false;
2288    }
2289
2290    return logResult(
2291        getConfigurableDomains()->setSequenceAwareness(strName, bSequenceAware, strResult),
2292        strResult);
2293}
2294
2295bool CParameterMgr::getSequenceAwareness(const string &strName, bool &bSequenceAware,
2296                                         string &strResult)
2297{
2298    return getConfigurableDomains()->getSequenceAwareness(strName, bSequenceAware, strResult);
2299}
2300
2301bool CParameterMgr::createConfiguration(const string &strDomain, const string &strConfiguration,
2302                                        string &strError)
2303{
2304    LOG_CONTEXT("Creating domain configuration '" + strConfiguration + "' into domain '" +
2305                strDomain + "'");
2306    // Check tuning mode
2307    if (!checkTuningModeOn(strError)) {
2308
2309        warning() << "Fail: " << strError;
2310        return false;
2311    }
2312
2313    // Delegate to configurable domains
2314    return logResult(getConfigurableDomains()->createConfiguration(
2315                         strDomain, strConfiguration, _pMainParameterBlackboard, strError),
2316                     strError);
2317}
2318bool CParameterMgr::renameConfiguration(const string &strDomain, const string &strConfiguration,
2319                                        const string &strNewConfiguration, string &strError)
2320{
2321    LOG_CONTEXT("Renaming domain '" + strDomain + "''s configuration '" + strConfiguration +
2322                "' to '" + strNewConfiguration + "'");
2323
2324    return logResult(getConfigurableDomains()->renameConfiguration(strDomain, strConfiguration,
2325                                                                   strNewConfiguration, strError),
2326                     strError);
2327}
2328
2329bool CParameterMgr::deleteConfiguration(const string &strDomain, const string &strConfiguration,
2330                                        string &strError)
2331{
2332    LOG_CONTEXT("Deleting configuration '" + strConfiguration + "' from domain '" + strDomain +
2333                "'");
2334
2335    // Check tuning mode
2336    if (!checkTuningModeOn(strError)) {
2337
2338        warning() << "Fail:" << strError;
2339        return false;
2340    }
2341
2342    // Delegate to configurable domains
2343    return logResult(
2344        getConfigurableDomains()->deleteConfiguration(strDomain, strConfiguration, strError),
2345        strError);
2346}
2347
2348bool CParameterMgr::restoreConfiguration(const string &strDomain, const string &strConfiguration,
2349                                         core::Results &errors)
2350{
2351    string strError;
2352    LOG_CONTEXT("Restoring domain '" + strDomain + "''s configuration '" + strConfiguration +
2353                "' to parameter blackboard");
2354    // Check tuning mode
2355    if (!checkTuningModeOn(strError)) {
2356
2357        errors.push_back(strError);
2358        warning() << "Fail:" << strError;
2359        return false;
2360    }
2361
2362    // Delegate to configurable domains
2363    return logResult(
2364        getConstConfigurableDomains()->restoreConfiguration(
2365            strDomain, strConfiguration, _pMainParameterBlackboard, _bAutoSyncOn, errors),
2366        strError);
2367}
2368
2369bool CParameterMgr::saveConfiguration(const string &strDomain, const string &strConfiguration,
2370                                      string &strError)
2371{
2372    LOG_CONTEXT("Saving domain '" + strDomain + "' configuration '" + strConfiguration +
2373                "' from parameter blackboard");
2374    // Check tuning mode
2375    if (!checkTuningModeOn(strError)) {
2376
2377        warning() << "Fail:" << strError;
2378        return false;
2379    }
2380
2381    // Delegate to configurable domains
2382    return logResult(getConfigurableDomains()->saveConfiguration(
2383                         strDomain, strConfiguration, _pMainParameterBlackboard, strError),
2384                     strError);
2385}
2386
2387// Configurable element - domain association
2388bool CParameterMgr::addConfigurableElementToDomain(const string &strDomain,
2389                                                   const string &strConfigurableElementPath,
2390                                                   string &strError)
2391{
2392    LOG_CONTEXT("Adding configurable element '" + strConfigurableElementPath + "' to domain '" +
2393                strDomain + "'");
2394    // Check tuning mode
2395    if (!checkTuningModeOn(strError)) {
2396
2397        warning() << "Fail: " << strError;
2398        return false;
2399    }
2400
2401    CElementLocator elementLocator(getSystemClass());
2402
2403    CElement *pLocatedElement = NULL;
2404
2405    if (!elementLocator.locate(strConfigurableElementPath, &pLocatedElement, strError)) {
2406
2407        warning() << "Fail: " << strError;
2408        return false;
2409    }
2410
2411    // Convert element
2412    CConfigurableElement *pConfigurableElement =
2413        static_cast<CConfigurableElement *>(pLocatedElement);
2414
2415    // Delegate
2416    core::Results infos;
2417    bool isSuccess = getConfigurableDomains()->addConfigurableElementToDomain(
2418        strDomain, pConfigurableElement, _pMainParameterBlackboard, infos);
2419
2420    if (isSuccess) {
2421        info() << infos;
2422    } else {
2423        warning() << infos;
2424    }
2425
2426    strError = utility::asString(infos);
2427    return isSuccess;
2428}
2429
2430bool CParameterMgr::removeConfigurableElementFromDomain(const string &strDomain,
2431                                                        const string &strConfigurableElementPath,
2432                                                        string &strError)
2433{
2434    LOG_CONTEXT("Removing configurable element '" + strConfigurableElementPath + "' from domain '" +
2435                strDomain + "'");
2436
2437    // Check tuning mode
2438    if (!checkTuningModeOn(strError)) {
2439
2440        warning() << "Fail:" << strError;
2441        return false;
2442    }
2443
2444    CElementLocator elementLocator(getSystemClass());
2445
2446    CElement *pLocatedElement = NULL;
2447
2448    if (!elementLocator.locate(strConfigurableElementPath, &pLocatedElement, strError)) {
2449
2450        warning() << "Fail:" << strError;
2451        return false;
2452    }
2453
2454    // Convert element
2455    CConfigurableElement *pConfigurableElement =
2456        static_cast<CConfigurableElement *>(pLocatedElement);
2457
2458    // Delegate
2459    return logResult(getConfigurableDomains()->removeConfigurableElementFromDomain(
2460                         strDomain, pConfigurableElement, strError),
2461                     strError);
2462}
2463
2464bool CParameterMgr::split(const string &strDomain, const string &strConfigurableElementPath,
2465                          string &strError)
2466{
2467    LOG_CONTEXT("Splitting configurable element '" + strConfigurableElementPath + "' domain '" +
2468                strDomain + "'");
2469    // Check tuning mode
2470    if (!checkTuningModeOn(strError)) {
2471
2472        warning() << "Fail:" << strError;
2473        return false;
2474    }
2475
2476    CElementLocator elementLocator(getSystemClass());
2477
2478    CElement *pLocatedElement = NULL;
2479
2480    if (!elementLocator.locate(strConfigurableElementPath, &pLocatedElement, strError)) {
2481
2482        warning() << "Fail: " << strError;
2483        return false;
2484    }
2485
2486    // Convert element
2487    CConfigurableElement *pConfigurableElement =
2488        static_cast<CConfigurableElement *>(pLocatedElement);
2489
2490    // Delegate
2491    core::Results infos;
2492    bool isSuccess = getConfigurableDomains()->split(strDomain, pConfigurableElement, infos);
2493
2494    if (isSuccess) {
2495        info() << infos;
2496    } else {
2497        warning() << infos;
2498    }
2499
2500    strError = utility::asString(infos);
2501    return isSuccess;
2502}
2503
2504bool CParameterMgr::setElementSequence(const string &strDomain, const string &strConfiguration,
2505                                       const std::vector<string> &astrNewElementSequence,
2506                                       string &strError)
2507{
2508    // Check tuning mode
2509    if (!checkTuningModeOn(strError)) {
2510
2511        return false;
2512    }
2513
2514    return getConfigurableDomains()->setElementSequence(strDomain, strConfiguration,
2515                                                        astrNewElementSequence, strError);
2516}
2517
2518bool CParameterMgr::getApplicationRule(const string &strDomain, const string &strConfiguration,
2519                                       string &strResult)
2520{
2521    return getConfigurableDomains()->getApplicationRule(strDomain, strConfiguration, strResult);
2522}
2523
2524bool CParameterMgr::setApplicationRule(const string &strDomain, const string &strConfiguration,
2525                                       const string &strApplicationRule, string &strError)
2526{
2527    return getConfigurableDomains()->setApplicationRule(
2528        strDomain, strConfiguration, strApplicationRule,
2529        getConstSelectionCriteria()->getSelectionCriteriaDefinition(), strError);
2530}
2531
2532bool CParameterMgr::clearApplicationRule(const string &strDomain, const string &strConfiguration,
2533                                         string &strError)
2534{
2535    return getConfigurableDomains()->clearApplicationRule(strDomain, strConfiguration, strError);
2536}
2537
2538bool CParameterMgr::importDomainsXml(const string &xmlSource, bool withSettings, bool fromFile,
2539                                     string &errorMsg)
2540{
2541    // Check tuning mode
2542    if (!checkTuningModeOn(errorMsg)) {
2543
2544        return false;
2545    }
2546
2547    LOG_CONTEXT("Importing domains from " +
2548                (fromFile ? ("\"" + xmlSource + "\"") : "a user-provided buffer"));
2549
2550    // Root element
2551    CConfigurableDomains *pConfigurableDomains = getConfigurableDomains();
2552
2553    bool importSuccess = wrapLegacyXmlImport(xmlSource, fromFile, withSettings,
2554                                             *pConfigurableDomains, "SystemClassName", errorMsg);
2555
2556    if (importSuccess) {
2557
2558        // Validate domains after XML import
2559        pConfigurableDomains->validate(_pMainParameterBlackboard);
2560    }
2561
2562    return importSuccess;
2563}
2564
2565bool CParameterMgr::importSingleDomainXml(const string &xmlSource, bool overwrite,
2566                                          bool withSettings, bool fromFile, string &errorMsg)
2567{
2568    if (!checkTuningModeOn(errorMsg)) {
2569
2570        return false;
2571    }
2572
2573    LOG_CONTEXT("Importing a single domain from " +
2574                (fromFile ? ('"' + xmlSource + '"') : "a user-provided buffer"));
2575
2576    // We initialize the domain with an empty name but since we have set the isDomainStandalone
2577    // context, the name will be retrieved during de-serialization
2578    auto standaloneDomain = utility::make_unique<CConfigurableDomain>();
2579
2580    if (!wrapLegacyXmlImport(xmlSource, fromFile, withSettings, *standaloneDomain, "", errorMsg)) {
2581        return false;
2582    }
2583
2584    if (!getConfigurableDomains()->addDomain(*standaloneDomain, overwrite, errorMsg)) {
2585        return false;
2586    }
2587
2588    // ownership has been transfered to the ConfigurableDomains object
2589    standaloneDomain.release();
2590    return true;
2591}
2592
2593bool CParameterMgr::wrapLegacyXmlImport(const string &xmlSource, bool fromFile, bool withSettings,
2594                                        CElement &element, const string &nameAttributeName,
2595                                        string &errorMsg)
2596{
2597    CXmlDomainImportContext xmlDomainImportContext(errorMsg, withSettings, *getSystemClass());
2598
2599    // Selection criteria definition for rule creation
2600    xmlDomainImportContext.setSelectionCriteriaDefinition(
2601        getConstSelectionCriteria()->getSelectionCriteriaDefinition());
2602
2603    // It doesn't make sense to resolve XIncludes on an imported file because
2604    // we can't reliably decide of a "base url"
2605    _xmlDoc *doc = CXmlDocSource::mkXmlDoc(xmlSource, fromFile, false, xmlDomainImportContext);
2606    if (doc == NULL) {
2607        return false;
2608    }
2609
2610    return xmlParse(xmlDomainImportContext, &element, doc, "", EParameterConfigurationLibrary, true,
2611                    nameAttributeName);
2612}
2613
2614bool CParameterMgr::serializeElement(std::ostream &output,
2615                                     CXmlSerializingContext &xmlSerializingContext,
2616                                     const CElement &element) const
2617{
2618    if (!output.good()) {
2619        xmlSerializingContext.setError("Can't write XML: the output is in a bad state.");
2620        return false;
2621    }
2622
2623    // Use a doc source by loading data from instantiated Configurable Domains
2624    CXmlMemoryDocSource memorySource(&element, _bValidateSchemasOnStart,
2625                                     element.getXmlElementName(), "parameter-framework",
2626                                     getVersion());
2627
2628    // Use a doc sink to write the doc data in a stream
2629    CXmlStreamDocSink sink(output);
2630
2631    bool processSuccess = sink.process(memorySource, xmlSerializingContext);
2632
2633    return processSuccess;
2634}
2635
2636bool CParameterMgr::exportDomainsXml(string &xmlDest, bool withSettings, bool toFile,
2637                                     string &errorMsg) const
2638{
2639    LOG_CONTEXT("Exporting domains to " +
2640                (toFile ? ('"' + xmlDest + '"') : "a user-provided buffer"));
2641
2642    const CConfigurableDomains *configurableDomains = getConstConfigurableDomains();
2643
2644    return wrapLegacyXmlExport(xmlDest, toFile, withSettings, *configurableDomains, errorMsg);
2645}
2646
2647bool CParameterMgr::exportSingleDomainXml(string &xmlDest, const string &domainName,
2648                                          bool withSettings, bool toFile, string &errorMsg) const
2649{
2650    LOG_CONTEXT("Exporting single domain '" + domainName + "' to " +
2651                (toFile ? ('"' + xmlDest + '"') : "a user-provided buffer"));
2652
2653    // Element to be serialized
2654    const CConfigurableDomain *requestedDomain =
2655        getConstConfigurableDomains()->findConfigurableDomain(domainName, errorMsg);
2656
2657    if (requestedDomain == NULL) {
2658        return false;
2659    }
2660
2661    return wrapLegacyXmlExport(xmlDest, toFile, withSettings, *requestedDomain, errorMsg);
2662}
2663
2664bool CParameterMgr::wrapLegacyXmlExport(string &xmlDest, bool toFile, bool withSettings,
2665                                        const CElement &element, string &errorMsg) const
2666{
2667    CXmlDomainExportContext context(errorMsg, withSettings, _bValueSpaceIsRaw,
2668                                    _bOutputRawFormatIsHex);
2669
2670    if (toFile) {
2671        return wrapLegacyXmlExportToFile(xmlDest, element, context);
2672    } else {
2673        return wrapLegacyXmlExportToString(xmlDest, element, context);
2674    }
2675}
2676
2677bool CParameterMgr::wrapLegacyXmlExportToFile(string &xmlDest, const CElement &element,
2678                                              CXmlDomainExportContext &context) const
2679{
2680    try {
2681        std::ofstream output;
2682        // Force stream to throw instead of using fail/bad bit
2683        // in order to retreive an error message.
2684        output.exceptions(~std::ifstream::goodbit);
2685
2686        output.open(xmlDest.c_str());
2687        bool status = serializeElement(output, context, element);
2688        output.close(); // Explicit close to detect errors
2689
2690        return status;
2691
2692    } catch (std::ofstream::failure &e) {
2693        context.setError("Failed to open \"" + xmlDest + "\" for writing: " + e.what());
2694        return false;
2695    }
2696}
2697
2698bool CParameterMgr::wrapLegacyXmlExportToString(string &xmlDest, const CElement &element,
2699                                                CXmlDomainExportContext &context) const
2700{
2701    std::ostringstream output;
2702
2703    if (!serializeElement(output, context, element)) {
2704        return false;
2705    }
2706
2707    xmlDest = output.str();
2708
2709    return true;
2710}
2711
2712// For tuning, check we're in tuning mode
2713bool CParameterMgr::checkTuningModeOn(string &strError) const
2714{
2715    // Tuning Mode on?
2716    if (!_bTuningModeIsOn) {
2717
2718        strError = "Tuning Mode must be on";
2719
2720        return false;
2721    }
2722    return true;
2723}
2724
2725// Tuning mutex dynamic parameter handling
2726std::mutex &CParameterMgr::getBlackboardMutex()
2727{
2728    return _blackboardMutex;
2729}
2730
2731// Blackboard reference (dynamic parameter handling)
2732CParameterBlackboard *CParameterMgr::getParameterBlackboard()
2733{
2734    return _pMainParameterBlackboard;
2735}
2736
2737// Dynamic creation library feeding
2738void CParameterMgr::feedElementLibraries()
2739{
2740    // Global Configuration handling
2741    CElementLibrary *pFrameworkConfigurationLibrary = new CElementLibrary;
2742
2743    pFrameworkConfigurationLibrary->addElementBuilder(
2744        "ParameterFrameworkConfiguration",
2745        new TElementBuilderTemplate<CParameterFrameworkConfiguration>());
2746    pFrameworkConfigurationLibrary->addElementBuilder(
2747        "SubsystemPlugins", new TKindElementBuilderTemplate<CSubsystemPlugins>());
2748    pFrameworkConfigurationLibrary->addElementBuilder(
2749        "Location", new TKindElementBuilderTemplate<CPluginLocation>());
2750    pFrameworkConfigurationLibrary->addElementBuilder(
2751        "StructureDescriptionFileLocation",
2752        new TKindElementBuilderTemplate<CFrameworkConfigurationLocation>());
2753    pFrameworkConfigurationLibrary->addElementBuilder(
2754        "SettingsConfiguration", new TKindElementBuilderTemplate<CFrameworkConfigurationGroup>());
2755    pFrameworkConfigurationLibrary->addElementBuilder(
2756        "ConfigurableDomainsFileLocation",
2757        new TKindElementBuilderTemplate<CFrameworkConfigurationLocation>());
2758
2759    _pElementLibrarySet->addElementLibrary(pFrameworkConfigurationLibrary);
2760
2761    // Parameter creation
2762    CElementLibrary *pParameterCreationLibrary = new CElementLibrary;
2763
2764    pParameterCreationLibrary->addElementBuilder(
2765        "Subsystem", new CSubsystemElementBuilder(getSystemClass()->getSubsystemLibrary()));
2766    pParameterCreationLibrary->addElementBuilder(
2767        "ComponentType", new TNamedElementBuilderTemplate<CComponentType>());
2768    pParameterCreationLibrary->addElementBuilder(
2769        "Component", new TNamedElementBuilderTemplate<CComponentInstance>());
2770    pParameterCreationLibrary->addElementBuilder(
2771        "BitParameter", new TNamedElementBuilderTemplate<CBitParameterType>());
2772    pParameterCreationLibrary->addElementBuilder(
2773        "BitParameterBlock", new TNamedElementBuilderTemplate<CBitParameterBlockType>());
2774    pParameterCreationLibrary->addElementBuilder(
2775        "StringParameter", new TNamedElementBuilderTemplate<CStringParameterType>());
2776    pParameterCreationLibrary->addElementBuilder(
2777        "ParameterBlock", new TNamedElementBuilderTemplate<CParameterBlockType>());
2778    pParameterCreationLibrary->addElementBuilder(
2779        "BooleanParameter", new TNamedElementBuilderTemplate<CBooleanParameterType>());
2780    pParameterCreationLibrary->addElementBuilder(
2781        "IntegerParameter", new TNamedElementBuilderTemplate<CIntegerParameterType>());
2782    pParameterCreationLibrary->addElementBuilder(
2783        "LinearAdaptation", new TElementBuilderTemplate<CLinearParameterAdaptation>());
2784    pParameterCreationLibrary->addElementBuilder(
2785        "LogarithmicAdaptation", new TElementBuilderTemplate<CLogarithmicParameterAdaptation>());
2786    pParameterCreationLibrary->addElementBuilder(
2787        "EnumParameter", new TNamedElementBuilderTemplate<CEnumParameterType>());
2788    pParameterCreationLibrary->addElementBuilder("ValuePair",
2789                                                 new TElementBuilderTemplate<CEnumValuePair>());
2790    pParameterCreationLibrary->addElementBuilder(
2791        "FixedPointParameter", new TNamedElementBuilderTemplate<CFixedPointParameterType>());
2792    pParameterCreationLibrary->addElementBuilder(
2793        "FloatingPointParameter", new TNamedElementBuilderTemplate<CFloatingPointParameterType>);
2794    pParameterCreationLibrary->addElementBuilder(
2795        "SubsystemInclude",
2796        new CFileIncluderElementBuilder(_bValidateSchemasOnStart, getSchemaUri()));
2797
2798    _pElementLibrarySet->addElementLibrary(pParameterCreationLibrary);
2799
2800    // Parameter Configuration Domains creation
2801    CElementLibrary *pParameterConfigurationLibrary = new CElementLibrary;
2802
2803    pParameterConfigurationLibrary->addElementBuilder(
2804        "ConfigurableDomain", new TElementBuilderTemplate<CConfigurableDomain>());
2805    pParameterConfigurationLibrary->addElementBuilder(
2806        "Configuration", new TNamedElementBuilderTemplate<CDomainConfiguration>());
2807    pParameterConfigurationLibrary->addElementBuilder("CompoundRule",
2808                                                      new TElementBuilderTemplate<CCompoundRule>());
2809    pParameterConfigurationLibrary->addElementBuilder(
2810        "SelectionCriterionRule", new TElementBuilderTemplate<CSelectionCriterionRule>());
2811
2812    _pElementLibrarySet->addElementLibrary(pParameterConfigurationLibrary);
2813}
2814
2815bool CParameterMgr::getForceNoRemoteInterface() const
2816{
2817    return _bForceNoRemoteInterface;
2818}
2819
2820void CParameterMgr::setForceNoRemoteInterface(bool bForceNoRemoteInterface)
2821{
2822    _bForceNoRemoteInterface = bForceNoRemoteInterface;
2823}
2824
2825CParameterMgr::CommandHandler CParameterMgr::createCommandHandler()
2826{
2827    auto commandHandler = utility::make_unique<CCommandHandler>(this);
2828
2829    // Add command parsers
2830    for (const auto &remoteCommandParserItem : gastRemoteCommandParserItems) {
2831        commandHandler->addCommandParser(
2832            remoteCommandParserItem._pcCommandName, remoteCommandParserItem._pfnParser,
2833            remoteCommandParserItem._minArgumentCount, remoteCommandParserItem._pcHelp,
2834            remoteCommandParserItem._pcDescription);
2835    }
2836
2837    return commandHandler;
2838}
2839
2840bool CParameterMgr::isRemoteInterfaceRequired()
2841{
2842    // The remote interface should only be started if the client didn't
2843    // explicitly forbid it and if the configuration file allows it.
2844    return (not _bForceNoRemoteInterface) and getConstFrameworkConfiguration()->isTuningAllowed();
2845}
2846
2847// Remote Processor Server connection handling
2848bool CParameterMgr::handleRemoteProcessingInterface(string &strError)
2849{
2850    LOG_CONTEXT("Handling remote processing interface");
2851
2852    if (not isRemoteInterfaceRequired()) {
2853        return true;
2854    }
2855
2856    auto port = getConstFrameworkConfiguration()->getServerPort();
2857
2858    try {
2859        // The ownership of remoteComandHandler is given to Bg remote processor server.
2860        _pRemoteProcessorServer = new BackgroundRemoteProcessorServer(port, createCommandHandler());
2861    } catch (std::runtime_error &e) {
2862        strError = string("ParameterMgr: Unable to create Remote Processor Server: ") + e.what();
2863        return false;
2864    }
2865
2866    if (_pRemoteProcessorServer == NULL) {
2867        strError = "ParameterMgr: Unable to create Remote Processor Server";
2868        return false;
2869    }
2870
2871    if (!_pRemoteProcessorServer->start(strError)) {
2872        ostringstream oss;
2873        oss << "ParameterMgr: Unable to start remote processor server on port " << port;
2874        strError = oss.str() + ": " + strError;
2875        return false;
2876    }
2877    info() << "Remote Processor Server started on port " << port;
2878    return true;
2879}
2880
2881// Children typwise access
2882CParameterFrameworkConfiguration *CParameterMgr::getFrameworkConfiguration()
2883{
2884    return static_cast<CParameterFrameworkConfiguration *>(getChild(EFrameworkConfiguration));
2885}
2886
2887const CParameterFrameworkConfiguration *CParameterMgr::getConstFrameworkConfiguration()
2888{
2889    return getFrameworkConfiguration();
2890}
2891
2892CSelectionCriteria *CParameterMgr::getSelectionCriteria()
2893{
2894    return static_cast<CSelectionCriteria *>(getChild(ESelectionCriteria));
2895}
2896
2897const CSelectionCriteria *CParameterMgr::getConstSelectionCriteria()
2898{
2899    return static_cast<const CSelectionCriteria *>(getChild(ESelectionCriteria));
2900}
2901
2902CSystemClass *CParameterMgr::getSystemClass()
2903{
2904    return static_cast<CSystemClass *>(getChild(ESystemClass));
2905}
2906
2907const CSystemClass *CParameterMgr::getConstSystemClass() const
2908{
2909    return static_cast<const CSystemClass *>(getChild(ESystemClass));
2910}
2911
2912// Configurable Domains
2913CConfigurableDomains *CParameterMgr::getConfigurableDomains()
2914{
2915    return static_cast<CConfigurableDomains *>(getChild(EConfigurableDomains));
2916}
2917
2918const CConfigurableDomains *CParameterMgr::getConstConfigurableDomains()
2919{
2920    return static_cast<const CConfigurableDomains *>(getChild(EConfigurableDomains));
2921}
2922
2923const CConfigurableDomains *CParameterMgr::getConstConfigurableDomains() const
2924{
2925    return static_cast<const CConfigurableDomains *>(getChild(EConfigurableDomains));
2926}
2927
2928// Apply configurations
2929void CParameterMgr::doApplyConfigurations(bool bForce)
2930{
2931    LOG_CONTEXT("Applying configurations");
2932
2933    CSyncerSet syncerSet;
2934
2935    core::Results infos;
2936    // Check subsystems that need resync
2937    getSystemClass()->checkForSubsystemsToResync(syncerSet, infos);
2938
2939    // Ensure application of currently selected configurations
2940    getConfigurableDomains()->apply(_pMainParameterBlackboard, syncerSet, bForce, infos);
2941    info() << infos;
2942
2943    // Reset the modified status of the current criteria to indicate that a new configuration has
2944    // been applied
2945    getSelectionCriteria()->resetModifiedStatus();
2946}
2947
2948// Export to XML string
2949bool CParameterMgr::exportElementToXMLString(const IXmlSource *pXmlSource,
2950                                             const string &strRootElementType,
2951                                             CXmlSerializingContext &&xmlSerializingContext,
2952                                             string &strResult) const
2953{
2954    // Use a doc source by loading data from instantiated Configurable Domains
2955    CXmlMemoryDocSource memorySource(pXmlSource, false, strRootElementType);
2956
2957    // Use a doc sink that write the doc data in a string
2958    ostringstream output;
2959    CXmlStreamDocSink streamSink(output);
2960
2961    // Do the export
2962    bool bProcessSuccess = streamSink.process(memorySource, xmlSerializingContext);
2963
2964    strResult = output.str();
2965
2966    return bProcessSuccess;
2967}
2968
2969bool CParameterMgr::logResult(bool isSuccess, const std::string &result)
2970{
2971    std::string log = result.empty() ? "" : ": " + result;
2972
2973    if (isSuccess) {
2974        info() << "Success" << log;
2975    } else {
2976        warning() << "Fail" << log;
2977    }
2978
2979    return isSuccess;
2980}
2981
2982log::details::Info CParameterMgr::info()
2983{
2984    return _logger.info();
2985}
2986
2987log::details::Warning CParameterMgr::warning()
2988{
2989    return _logger.warning();
2990}
2991