// Parse configurable elements
bool CConfigurableDomain::parseConfigurableElements(const CXmlElement &xmlElement,
                                                    CXmlDomainImportContext &serializingContext)
{
    CSystemClass &systemClass = serializingContext.getSystemClass();

    // Get ConfigurableElements element
    CXmlElement xmlConfigurableElementsElement;
    xmlElement.getChildElement("ConfigurableElements", xmlConfigurableElementsElement);

    // Parse it and associate found configurable elements to it
    CXmlElement::CChildIterator it(xmlConfigurableElementsElement);

    CXmlElement xmlConfigurableElementElement;

    while (it.next(xmlConfigurableElementElement)) {

        // Locate configurable element
        string strConfigurableElementPath;
        xmlConfigurableElementElement.getAttribute("Path", strConfigurableElementPath);

        CPathNavigator pathNavigator(strConfigurableElementPath);
        string strError;

        // Is there an element and does it match system class name?
        if (!pathNavigator.navigateThrough(systemClass.getName(), strError)) {

            serializingContext.setError(
                "Could not find configurable element of path " + strConfigurableElementPath +
                " from ConfigurableDomain description " + getName() + " (" + strError + ")");

            return false;
        }
        // Browse system class for configurable element
        CConfigurableElement *pConfigurableElement =
            static_cast<CConfigurableElement *>(systemClass.findDescendant(pathNavigator));

        if (!pConfigurableElement) {

            serializingContext.setError("Could not find configurable element of path " +
                                        strConfigurableElementPath +
                                        " from ConfigurableDomain description " + getName());

            return false;
        }
        // Add found element to domain
        core::Results infos;
        if (!addConfigurableElement(pConfigurableElement, NULL, infos)) {

            strError = utility::asString(infos);
            serializingContext.setError(strError);

            return false;
        }
    }

    return true;
}
// Serialize one configuration for one configurable element
bool CDomainConfiguration::importOneConfigurableElementSettings(
    CAreaConfiguration *areaConfiguration, CXmlElement &xmlConfigurableElementSettingsElement,
    CXmlDomainImportContext &context)
{
    const CConfigurableElement *destination = areaConfiguration->getConfigurableElement();

    // Check structure
    if (xmlConfigurableElementSettingsElement.getNbChildElements() != 1) {

        // Structure error
        context.setError("Struture error encountered while parsing settings of " +
                         destination->getKind() + " " + destination->getName() +
                         " in Configuration " + getPath());

        return false;
    }

    // Element content
    CXmlElement xmlConfigurableElementSettingsElementContent;
    // Check name and kind
    if (!xmlConfigurableElementSettingsElement.getChildElement(
            destination->getXmlElementName(), destination->getName(),
            xmlConfigurableElementSettingsElementContent)) {

        // "Component" tag has been renamed to "ParameterBlock", but retro-compatibility shall
        // be ensured.
        //
        // So checking if this case occurs, i.e. element name is "ParameterBlock"
        // but found xml setting name is "Component".
        bool compatibilityCase =
            (destination->getXmlElementName() == "ParameterBlock") &&
            xmlConfigurableElementSettingsElement.getChildElement(
                "Component", destination->getName(), xmlConfigurableElementSettingsElementContent);

        // Error if the compatibility case does not occur.
        if (!compatibilityCase) {
            context.setError("Couldn't find settings for " + destination->getXmlElementName() +
                             " " + destination->getName() + " for Configuration " + getPath());

            return false;
        }
    }

    // Create configuration access context
    string error;
    CConfigurationAccessContext configurationAccessContext(error, false);

    // Have domain configuration parse settings for configurable element
    bool success = areaConfiguration->serializeXmlSettings(
        xmlConfigurableElementSettingsElementContent, configurationAccessContext);

    context.appendToError(error);
    return success;
}
// Parse settings
bool CConfigurableDomain::parseSettings(const CXmlElement &xmlElement,
                                        CXmlDomainImportContext &serializingContext)
{
    // Check we actually need to parse configuration settings
    if (!serializingContext.withSettings()) {

        // No parsing required
        return true;
    }

    // Get Settings element
    CXmlElement xmlSettingsElement;
    if (!xmlElement.getChildElement("Settings", xmlSettingsElement)) {

        // No settings, bail out successfully
        return true;
    }

    // Parse configuration settings
    CXmlElement::CChildIterator it(xmlSettingsElement);

    CXmlElement xmlConfigurationSettingsElement;

    while (it.next(xmlConfigurationSettingsElement)) {
        // Get domain configuration
        CDomainConfiguration *pDomainConfiguration = static_cast<CDomainConfiguration *>(
            findChild(xmlConfigurationSettingsElement.getNameAttribute()));

        if (!pDomainConfiguration) {

            serializingContext.setError("Could not find domain configuration referred to by"
                                        " configurable domain \"" +
                                        getName() + "\".");

            return false;
        }
        // Have domain configuration parse settings for all configurable elements
        if (!pDomainConfiguration->parseSettings(xmlConfigurationSettingsElement,
                                                 serializingContext)) {

            return false;
        }
    }

    return true;
}
// XML configuration settings parsing
bool CDomainConfiguration::parseSettings(CXmlElement &xmlConfigurationSettingsElement,
                                         CXmlDomainImportContext &context)
{
    // Parse configurable element's configuration settings
    CXmlElement::CChildIterator it(xmlConfigurationSettingsElement);

    CXmlElement xmlConfigurableElementSettingsElement;
    auto insertLocation = begin(mAreaConfigurationList);

    while (it.next(xmlConfigurableElementSettingsElement)) {

        // Retrieve area configuration
        string configurableElementPath;
        xmlConfigurableElementSettingsElement.getAttribute("Path", configurableElementPath);

        auto areaConfiguration = findAreaConfigurationByPath(configurableElementPath);
        if (areaConfiguration == end(mAreaConfigurationList)) {

            context.setError("Configurable Element " + configurableElementPath +
                             " referred to by Configuration " + getPath() +
                             " not associated to Domain");

            return false;
        }
        // Parse
        if (!importOneConfigurableElementSettings(areaConfiguration->get(),
                                                  xmlConfigurableElementSettingsElement, context)) {

            return false;
        }
        // Take into account the new configuration order by moving the configuration associated to
        // the element to the n-th position of the configuration list.
        // It will result in prepending to the configuration list wit the configuration of all
        // elements found in XML, keeping the order of the processing of the XML file.
        mAreaConfigurationList.splice(insertLocation, mAreaConfigurationList, areaConfiguration);
        // areaConfiguration is still valid, but now refer to the reorderer list
        insertLocation = std::next(areaConfiguration);
    }
    return true;
}