// XML composing
void CConfigurableDomain::composeDomainConfigurations(
    CXmlElement &xmlElement, CXmlSerializingContext &serializingContext) const
{
    // Create Configurations element
    CXmlElement xmlConfigurationsElement;

    xmlElement.createChild(xmlConfigurationsElement, "Configurations");

    // Delegate to base
    base::childrenToXml(xmlConfigurationsElement, serializingContext);
}
void CElement::childrenToXml(CXmlElement &xmlElement,
                             CXmlSerializingContext &serializingContext) const
{
    // Browse children and propagate
    for (CElement *pChild : _childArray) {

        // Create corresponding child element
        CXmlElement xmlChildElement;

        xmlElement.createChild(xmlChildElement, pChild->getXmlElementName());

        // Propagate
        pChild->toXml(xmlChildElement, serializingContext);
    }
}
void CConfigurableDomain::composeSettings(CXmlElement &xmlElement,
                                          CXmlDomainExportContext &context) const
{
    if (!context.withSettings()) {

        return;
    }

    // Create Settings element
    CXmlElement xmlSettingsElement;

    xmlElement.createChild(xmlSettingsElement, "Settings");

    // Serialize out all configurations settings
    size_t uiNbConfigurations = getNbChildren();
    size_t uiChildConfiguration;

    for (uiChildConfiguration = 0; uiChildConfiguration < uiNbConfigurations;
         uiChildConfiguration++) {

        const CDomainConfiguration *pDomainConfiguration =
            static_cast<const CDomainConfiguration *>(getChild(uiChildConfiguration));

        // Create child xml element for that configuration
        CXmlElement xmlConfigurationSettingsElement;

        xmlSettingsElement.createChild(xmlConfigurationSettingsElement,
                                       pDomainConfiguration->getXmlElementName());

        // Set its name attribute
        xmlConfigurationSettingsElement.setNameAttribute(pDomainConfiguration->getName());

        // Serialize out configuration settings
        pDomainConfiguration->composeSettings(xmlConfigurationSettingsElement, context);
    }
}
void CConfigurableDomain::composeConfigurableElements(CXmlElement &xmlElement) const
{
    // Create ConfigurableElements element
    CXmlElement xmlConfigurableElementsElement;

    xmlElement.createChild(xmlConfigurableElementsElement, "ConfigurableElements");

    // Serialize out all configurable elements settings
    ConfigurableElementListIterator it;

    for (it = _configurableElementList.begin(); it != _configurableElementList.end(); ++it) {

        const CConfigurableElement *pConfigurableElement = *it;

        // Create corresponding XML child element
        CXmlElement xmlChildConfigurableElement;

        xmlConfigurableElementsElement.createChild(xmlChildConfigurableElement,
                                                   "ConfigurableElement");

        // Set Path attribute
        xmlChildConfigurableElement.setAttribute("Path", pConfigurableElement->getPath());
    }
}
// From IXmlSource
void CSelectionCriterionType::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
{
    // Type Kind
    xmlElement.setAttribute("Kind", isTypeInclusive() ? "Inclusive" : "Exclusive");

    // Value pairs as children
    NumToLitMapConstIt it;

    for (it = _numToLitMap.begin(); it != _numToLitMap.end(); ++it) {

        CXmlElement childValuePairElement;

        xmlElement.createChild(childValuePairElement, "ValuePair");
        // Literal
        childValuePairElement.setAttribute("Literal", it->first);
        // Numerical
        childValuePairElement.setAttribute("Numerical", it->second);
    }

    base::toXml(xmlElement, serializingContext);
}
// From IXmlSource
void CElement::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
{
    // Browse children and propagate
    uint32_t uiNbChildren = getNbChildren();
    uint32_t uiChild;

    for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {

        const CElement* pChild = _childArray[uiChild];

        // Create corresponding child element
        CXmlElement xmlChildElement;

        xmlElement.createChild(xmlChildElement, pChild->getKind());

        // Set attributes
        pChild->setXmlNameAttribute(xmlChildElement);


        // Propagate
        pChild->toXml(xmlChildElement, serializingContext);
    }
}
bool CDomainConfiguration::exportOneConfigurableElementSettings(
    CAreaConfiguration *areaConfiguration, CXmlElement &xmlConfigurableElementSettingsElement,
    CXmlDomainExportContext &context) const
{
    const CConfigurableElement *source = areaConfiguration->getConfigurableElement();

    // Create child XML element
    CXmlElement xmlConfigurableElementSettingsElementContent;
    xmlConfigurableElementSettingsElement.createChild(xmlConfigurableElementSettingsElementContent,
                                                      source->getXmlElementName());

    // Create configuration access context
    string error;
    CConfigurationAccessContext configurationAccessContext(error, true);
    configurationAccessContext.setValueSpaceRaw(context.valueSpaceIsRaw());
    configurationAccessContext.setOutputRawFormat(context.outputRawFormatIsHex());

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

    context.appendToError(error);
    return success;
}
// XML configuration settings composing
void CDomainConfiguration::composeSettings(CXmlElement &xmlConfigurationSettingsElement,
                                           CXmlDomainExportContext &context) const
{
    // Go through all are configurations
    for (auto &areaConfiguration : mAreaConfigurationList) {

        // Retrieve configurable element
        const CConfigurableElement *pConfigurableElement =
            areaConfiguration->getConfigurableElement();

        // Create configurable element child element
        CXmlElement xmlConfigurableElementSettingsElement;

        xmlConfigurationSettingsElement.createChild(xmlConfigurableElementSettingsElement,
                                                    "ConfigurableElement");

        // Set Path attribute
        xmlConfigurableElementSettingsElement.setAttribute("Path", pConfigurableElement->getPath());

        // Delegate composing to area configuration
        exportOneConfigurableElementSettings(areaConfiguration.get(),
                                             xmlConfigurableElementSettingsElement, context);
    }
}
// XML configuration settings parsing
bool CConfigurableElement::serializeXmlSettings(CXmlElement& xmlConfigurationSettingsElementContent, CConfigurationAccessContext& configurationAccessContext) const
{
    uint32_t uiIndex;
    uint32_t uiNbChildren = getNbChildren();

    if (!configurationAccessContext.serializeOut()) {
        // Just do basic checks and propagate to children
        CXmlElement::CChildIterator it(xmlConfigurationSettingsElementContent);

        CXmlElement xmlChildConfigurableElementSettingsElement;

        // Propagate to children
        for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {

            // Get child
            const CConfigurableElement* pChildConfigurableElement = static_cast<const CConfigurableElement*>(getChild(uiIndex));

            if (!it.next(xmlChildConfigurableElementSettingsElement)) {

                // Structure error
                configurationAccessContext.setError("Configuration settings parsing: Settings don't conform to structure of configurable element " + getName());

                return false;
            }

            // Check element type matches in type
            if (xmlChildConfigurableElementSettingsElement.getType() != pChildConfigurableElement->getKind()) {

                // Type error
                configurationAccessContext.setError("Configuration settings parsing: Settings for configurable element " + pChildConfigurableElement->getName() + " does not match expected type: " + xmlChildConfigurableElementSettingsElement.getType() + " instead of " + pChildConfigurableElement->getKind());

                return false;
            }

            // Check element type matches in name
            if (xmlChildConfigurableElementSettingsElement.getNameAttribute() != pChildConfigurableElement->getName()) {

                // Name error
                configurationAccessContext.setError("Configuration settings parsing: Under configurable elememnt " + getName() + ", expected element name " + pChildConfigurableElement->getName() + " but found " + xmlChildConfigurableElementSettingsElement.getNameAttribute() + " instead");

                return false;
            }

            // Parse child configurable element's settings
            if (!pChildConfigurableElement->serializeXmlSettings(xmlChildConfigurableElementSettingsElement, configurationAccessContext)) {

                return false;
            }
        }
        // There should remain no configurable element to parse
        if (it.next(xmlChildConfigurableElementSettingsElement)) {

            // Structure error
            configurationAccessContext.setError("Configuration settings parsing: Settings don't conform to structure of configurable element " + getName());

            return false;
        }
    } else {
        // Propagate to children
        for (uiIndex = 0; uiIndex < uiNbChildren; uiIndex++) {

            const CConfigurableElement* pChildConfigurableElement = static_cast<const CConfigurableElement*>(getChild(uiIndex));

            // Create corresponding child element
            CXmlElement xmlChildConfigurableElementSettingsElement;

            xmlConfigurationSettingsElementContent.createChild(xmlChildConfigurableElementSettingsElement, pChildConfigurableElement->getKind());

            // Handle element name attribute
            xmlChildConfigurableElementSettingsElement.setNameAttribute(pChildConfigurableElement->getName());

            // Propagate
            pChildConfigurableElement->serializeXmlSettings(xmlChildConfigurableElementSettingsElement, configurationAccessContext);
        }
    }
    // Done
    return true;
}