// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @file XMLEndpointParser.cpp
 *
 */

#include <string>
#include <cstdlib>

#include <fastrtps/xmlparser/XMLEndpointParser.h>

#include <fastdds/dds/log/Log.hpp>
#include <fastrtps/utils/TimeConversion.h>
#include <fastrtps/utils/IPLocator.h>
#include <fastdds/rtps/builtin/data/WriterProxyData.h>
#include <fastdds/rtps/builtin/data/ReaderProxyData.h>

#include <tinyxml2.h>

using namespace eprosima::fastrtps;
using namespace eprosima::fastrtps::rtps;
using namespace eprosima::fastrtps::xmlparser;

XMLEndpointParser::XMLEndpointParser()
{
    // TODO Auto-generated constructor stub

}

XMLEndpointParser::~XMLEndpointParser()
{
    // TODO Auto-generated destructor stub
    for (std::vector<StaticRTPSParticipantInfo*>::iterator pit = m_RTPSParticipants.begin();
            pit != m_RTPSParticipants.end(); ++pit)
    {
        for (std::vector<ReaderProxyData*>::iterator rit = (*pit)->m_readers.begin();
                rit != (*pit)->m_readers.end(); ++rit)
        {
            delete(*rit);
        }
        for (std::vector<WriterProxyData*>::iterator wit = (*pit)->m_writers.begin();
                wit != (*pit)->m_writers.end(); ++wit)
        {
            delete(*wit);
        }

        delete(*pit);
    }
}

XMLP_ret XMLEndpointParser::loadXMLFile(
        std::string& filename)
{
    logInfo(RTPS_EDP, "File: " << filename);

    tinyxml2::XMLDocument doc;
    doc.LoadFile(filename.c_str());
    tinyxml2::XMLError eResult = doc.LoadFile(filename.c_str());

    if (tinyxml2::XML_SUCCESS != eResult)
    {
        logError(RTPS_EDP, filename << " bad file (bad path?)");
        return XMLP_ret::XML_ERROR;
    }

    tinyxml2::XMLNode* root = doc.FirstChildElement(STATICDISCOVERY);
    if (!root)
    {
        logError(RTPS_EDP, filename << " XML has errors");
        return XMLP_ret::XML_ERROR;
    }


    tinyxml2::XMLElement* xml_RTPSParticipant = root->FirstChildElement();

    while (xml_RTPSParticipant != nullptr)
    {
        std::string key(xml_RTPSParticipant->Name());
        if (key == PARTICIPANT)
        {
            StaticRTPSParticipantInfo* pdata = new StaticRTPSParticipantInfo();
            loadXMLParticipantEndpoint(xml_RTPSParticipant, pdata);
            m_RTPSParticipants.push_back(pdata);
        }
        xml_RTPSParticipant = xml_RTPSParticipant->NextSiblingElement();
    }

    logInfo(RTPS_EDP, "Finished parsing, " << m_RTPSParticipants.size() << " participants found.");
    return XMLP_ret::XML_OK;
}

XMLP_ret XMLEndpointParser::loadXMLNode(
        tinyxml2::XMLDocument& doc)
{
    logInfo(RTPS_EDP, "XML node");

    tinyxml2::XMLNode* root = doc.FirstChildElement(STATICDISCOVERY);
    if (!root)
    {
        logError(RTPS_EDP, "XML node has errors");
        return XMLP_ret::XML_ERROR;
    }


    tinyxml2::XMLElement* xml_RTPSParticipant = root->FirstChildElement();

    while (xml_RTPSParticipant != nullptr)
    {
        std::string key(xml_RTPSParticipant->Name());
        if (key == PARTICIPANT)
        {
            StaticRTPSParticipantInfo* pdata = new StaticRTPSParticipantInfo();
            loadXMLParticipantEndpoint(xml_RTPSParticipant, pdata);
            m_RTPSParticipants.push_back(pdata);
        }
        xml_RTPSParticipant = xml_RTPSParticipant->NextSiblingElement();
    }

    logInfo(RTPS_EDP, "Finished parsing, " << m_RTPSParticipants.size() << " participants found.");
    return XMLP_ret::XML_OK;
}

void XMLEndpointParser::loadXMLParticipantEndpoint(
        tinyxml2::XMLElement* xml_endpoint,
        StaticRTPSParticipantInfo* pdata)
{
    tinyxml2::XMLNode* xml_RTPSParticipant_child = xml_endpoint;
    tinyxml2::XMLElement* element = xml_RTPSParticipant_child->FirstChildElement();

    while (element != nullptr)
    {
        std::string key(element->Name());

        if (key == NAME)
        {
            pdata->m_RTPSParticipantName = element->GetText();
        }
        else if (key == READER)
        {
            if (loadXMLReaderEndpoint(element, pdata) != XMLP_ret::XML_OK)
            {
                logError(RTPS_EDP, "Reader Endpoint has error, ignoring");
            }
        }
        else if (key == WRITER)
        {
            if (loadXMLWriterEndpoint(element, pdata) != XMLP_ret::XML_OK)
            {
                logError(RTPS_EDP, "Writer Endpoint has error, ignoring");
            }
        }
        else
        {
            logError(RTPS_EDP, "Unknown XMK tag: " << key);
        }

        element = element->NextSiblingElement();
    }
}

XMLP_ret XMLEndpointParser::loadXMLReaderEndpoint(
        tinyxml2::XMLElement* xml_endpoint,
        StaticRTPSParticipantInfo* pdata)
{
    LocatorList_t unicast_locators;
    LocatorList_t multicast_locators;

    tinyxml2::XMLNode* xml_endpoint_child = xml_endpoint;
    tinyxml2::XMLElement* element = xml_endpoint_child->FirstChildElement();

    // Parse locators first
    while (element != nullptr)
    {
        std::string key(element->Name());
        if (key == UNICAST_LOCATOR)
        {
            Locator_t loc;
            loc.kind = 1;
            const char* address = element->Attribute(ADDRESS);
            std::string auxString(address ? address : "");
            IPLocator::setIPv4(loc, auxString);
            int port = 0;
            element->QueryIntAttribute(PORT, &port);
            loc.port = static_cast<uint16_t>(port);
            unicast_locators.push_back(loc);
        }
        else if (key == MULTICAST_LOCATOR)
        {
            Locator_t loc;
            loc.kind = 1;
            const char* address = element->Attribute(ADDRESS);
            std::string auxString(address ? address : "");
            IPLocator::setIPv4(loc, auxString);
            int port = 0;
            element->QueryIntAttribute(PORT, &port);
            loc.port = static_cast<uint16_t>(port);
            multicast_locators.push_back(loc);
        }

        element = element->NextSiblingElement();
    }


    ReaderProxyData* rdata = new ReaderProxyData(unicast_locators.size(), multicast_locators.size());

    xml_endpoint_child = xml_endpoint;
    element = xml_endpoint_child->FirstChildElement();

    while (element != nullptr)
    {
        std::string key(element->Name());
        if (key == USER_ID)
        {
            int16_t id = static_cast<int16_t>(std::strtol(element->GetText(), nullptr, 10));
            if (id <= 0 || m_endpointIds.insert(id).second == false)
            {
                logError(RTPS_EDP, "Repeated or negative ID in XML file");
                delete(rdata);
                return XMLP_ret::XML_ERROR;
            }
            rdata->userDefinedId(id);
        }
        else if (key == ENTITY_ID)
        {
            int32_t id = std::strtol(element->GetText(), nullptr, 10);
            if (id <= 0 || m_entityIds.insert(id).second == false)
            {
                logError(RTPS_EDP, "Repeated or negative entityId in XML file");
                delete(rdata);
                return XMLP_ret::XML_ERROR;
            }
            octet* c = (octet*)&id;
            rdata->guid().entityId.value[2] = c[0];
            rdata->guid().entityId.value[1] = c[1];
            rdata->guid().entityId.value[0] = c[2];
        }
        else if (key == EXPECT_INLINE_QOS)
        {
            std::string auxString(element->GetText());
            if (auxString == "true")
            {
                rdata->m_expectsInlineQos = true;
            }
            else if (auxString == "false")
            {
                rdata->m_expectsInlineQos = false;
            }
            else
            {
                logError(RTPS_EDP, "Bad XML file, endpoint of expectsInlineQos: " << auxString << " is not valid");
                delete(rdata);
                return XMLP_ret::XML_ERROR;
            }
        }
        else if (key == TOPIC) // deprecated api
        {
            const char* topicName = element->Attribute(NAME);
            const char* typeName = element->Attribute(DATA_TYPE);
            const char* kind = element->Attribute(KIND);

            rdata->topicName((topicName != nullptr) ? std::string(topicName) : std::string(""));
            rdata->typeName((topicName != nullptr) ? std::string(typeName) : std::string(""));
            std::string auxString(kind ? kind : "");
            if (auxString == _NO_KEY)
            {
                rdata->topicKind(NO_KEY);
                rdata->guid().entityId.value[3] = 0x04;
            }
            else if (auxString == _WITH_KEY)
            {
                rdata->topicKind(WITH_KEY);
                rdata->guid().entityId.value[3] = 0x07;
            }
            else
            {
                logError(RTPS_EDP, "Bad XML file, topic of kind: " << auxString << " is not valid");
                delete(rdata);
                return XMLP_ret::XML_ERROR;
            }
            if (rdata->topicName() == EPROSIMA_UNKNOWN_STRING || rdata->typeName() == EPROSIMA_UNKNOWN_STRING)
            {
                logError(RTPS_EDP,
                        "Bad XML file, topic: " << rdata->topicName() << " or typeName: " << rdata->typeName() <<
                        " undefined");
                delete(rdata);
                return XMLP_ret::XML_ERROR;
            }
        }
        else if (key == TOPIC_NAME)
        {
            rdata->topicName() = element->GetText();
        }
        else if (key == TOPIC_DATA_TYPE)
        {
            rdata->typeName() = element->GetText();
        }
        else if (key == TOPIC_KIND)
        {
            std::string auxString(element->GetText());
            if (auxString == _NO_KEY)
            {
                rdata->topicKind() = NO_KEY;
                rdata->guid().entityId.value[3] = 0x04;
            }
            else if (auxString == _WITH_KEY)
            {
                rdata->topicKind() = WITH_KEY;
                rdata->guid().entityId.value[3] = 0x07;
            }
            else
            {
                logError(RTPS_EDP, "Bad XML file, topic of kind: " << auxString << " is not valid");
                delete(rdata);
                return XMLP_ret::XML_ERROR;
            }
        }
        else if (key == RELIABILITY_QOS)
        {
            std::string auxString(element->GetText());
            if (auxString == _RELIABLE_RELIABILITY_QOS)
            {
                rdata->m_qos.m_reliability.kind = RELIABLE_RELIABILITY_QOS;
            }
            else if (auxString == _BEST_EFFORT_RELIABILITY_QOS)
            {
                rdata->m_qos.m_reliability.kind = BEST_EFFORT_RELIABILITY_QOS;
            }
            else
            {
                logError(RTPS_EDP, "Bad XML file, endpoint of stateKind: " << auxString << " is not valid");
                delete(rdata);
                return XMLP_ret::XML_ERROR;
            }
        }
        else if (key == UNICAST_LOCATOR)
        {
            // Empty but necessary to avoid warning on last else
        }
        else if (key == MULTICAST_LOCATOR)
        {
            // Empty but necessary to avoid warning on last else
        }
        else if (key == DURABILITY_QOS)
        {
            std::string auxstring(element->GetText());
            if (auxstring == _PERSISTENT_DURABILITY_QOS)
            {
                rdata->m_qos.m_durability.kind = PERSISTENT_DURABILITY_QOS;
            }
            else if (auxstring == _TRANSIENT_DURABILITY_QOS)
            {
                rdata->m_qos.m_durability.kind = TRANSIENT_DURABILITY_QOS;
            }
            else if (auxstring == _TRANSIENT_LOCAL_DURABILITY_QOS)
            {
                rdata->m_qos.m_durability.kind = TRANSIENT_LOCAL_DURABILITY_QOS;
            }
            else if (auxstring == _VOLATILE_DURABILITY_QOS)
            {
                rdata->m_qos.m_durability.kind = VOLATILE_DURABILITY_QOS;
            }
            else
            {
                logError(RTPS_EDP, "Bad XML file, durability of kind: " << auxstring << " is not valid");
                delete(rdata);
                return XMLP_ret::XML_ERROR;
            }
        }
        else if (key == OWNERSHIP_QOS)
        {
            const char* ownership = element->Attribute(KIND);
            std::string auxstring(ownership ? ownership : OWNERSHIP_KIND_NOT_PRESENT);
            if (auxstring == _SHARED_OWNERSHIP_QOS)
            {
                rdata->m_qos.m_ownership.kind = SHARED_OWNERSHIP_QOS;
            }
            else if (auxstring == _EXCLUSIVE_OWNERSHIP_QOS)
            {
                rdata->m_qos.m_ownership.kind = EXCLUSIVE_OWNERSHIP_QOS;
            }
            else
            {
                logError(RTPS_EDP, "Bad XML file, ownership of kind: " << auxstring << " is not valid");
                delete(rdata);
                return XMLP_ret::XML_ERROR;
            }
        }
        else if (key == PARTITION_QOS)
        {
            rdata->m_qos.m_partition.push_back(element->GetText());
        }
        else if (key == LIVELINESS_QOS)
        {
            const char* kind = element->Attribute(KIND);
            std::string auxstring(kind ? kind : LIVELINESS_KIND_NOT_PRESENT);
            if (auxstring == _AUTOMATIC_LIVELINESS_QOS)
            {
                rdata->m_qos.m_liveliness.kind = AUTOMATIC_LIVELINESS_QOS;
            }
            else if (auxstring == _MANUAL_BY_PARTICIPANT_LIVELINESS_QOS)
            {
                rdata->m_qos.m_liveliness.kind = MANUAL_BY_PARTICIPANT_LIVELINESS_QOS;
            }
            else if (auxstring == _MANUAL_BY_TOPIC_LIVELINESS_QOS)
            {
                rdata->m_qos.m_liveliness.kind = MANUAL_BY_TOPIC_LIVELINESS_QOS;
            }
            else
            {
                logError(RTPS_EDP, "Bad XML file, liveliness of kind: " << auxstring << " is not valid");
                delete(rdata);
                return XMLP_ret::XML_ERROR;
            }
            const char* leaseDuration_ms = element->Attribute(LEASE_DURATION_MS);
            auxstring = std::string(leaseDuration_ms ? leaseDuration_ms : _INF);
            if (auxstring == _INF)
            {
                rdata->m_qos.m_liveliness.lease_duration = c_TimeInfinite;
            }
            else
            {
                uint32_t milliseclease = std::strtoul(auxstring.c_str(), nullptr, 10);
                rdata->m_qos.m_liveliness.lease_duration =
                        TimeConv::MilliSeconds2Time_t((double)milliseclease).to_duration_t();
                if (milliseclease == 0)
                {
                    logWarning(RTPS_EDP, "BAD XML:livelinessQos leaseDuration is 0");
                }
            }
        }
        else if (key == DISABLE_POSITIVE_ACKS)
        {
            // Disable positive acks
            if (XMLP_ret::XML_OK !=
                    XMLParser::getXMLDisablePositiveAcksQos(element, rdata->m_qos.m_disablePositiveACKs, 0))
            {
                return XMLP_ret::XML_ERROR;
            }
        }
        else
        {
            logWarning(RTPS_EDP, "Unkown Endpoint-XML tag, ignoring " << key);
        }

        element = element->NextSiblingElement();
    }

    if (rdata->userDefinedId() == 0)
    {
        logError(RTPS_EDP, "Reader XML endpoint with NO ID defined");
        delete(rdata);
        return XMLP_ret::XML_ERROR;
    }

    for (const Locator_t& loc : unicast_locators)
    {
        rdata->add_unicast_locator(loc);
    }

    for (const Locator_t& loc : multicast_locators)
    {
        rdata->add_multicast_locator(loc);
    }

    pdata->m_readers.push_back(rdata);
    return XMLP_ret::XML_OK;
}

XMLP_ret XMLEndpointParser::loadXMLWriterEndpoint(
        tinyxml2::XMLElement* xml_endpoint,
        StaticRTPSParticipantInfo* pdata)
{
    LocatorList_t unicast_locators;
    LocatorList_t multicast_locators;

    tinyxml2::XMLNode* xml_endpoint_child = xml_endpoint;
    tinyxml2::XMLElement* element = xml_endpoint_child->FirstChildElement();

    while (element != nullptr)
    {
        std::string key(element->Name());
        if (key == UNICAST_LOCATOR)
        {
            Locator_t loc;
            loc.kind = 1;
            const char* address = element->Attribute(ADDRESS);
            std::string auxString(address ? address : "");
            IPLocator::setIPv4(loc, auxString);
            int port = 0;
            element->QueryIntAttribute(PORT, &port);
            loc.port = static_cast<uint16_t>(port);
            unicast_locators.push_back(loc);
        }
        else if (key == MULTICAST_LOCATOR)
        {
            Locator_t loc;
            loc.kind = 1;
            const char* address = element->Attribute(ADDRESS);
            std::string auxString(address ? address : "");
            IPLocator::setIPv4(loc, auxString);
            int port = 0;
            element->QueryIntAttribute(PORT, &port);
            loc.port = static_cast<uint16_t>(port);
            multicast_locators.push_back(loc);
        }
        element = element->NextSiblingElement();
    }

    WriterProxyData* wdata = new WriterProxyData(unicast_locators.size(), multicast_locators.size());

    xml_endpoint_child = xml_endpoint;
    element = xml_endpoint_child->FirstChildElement();
    while (element != nullptr)
    {
        std::string key(element->Name());
        if (key == USER_ID)
        {
            int16_t id = static_cast<int16_t>(std::strtol(element->GetText(), nullptr, 10));
            if (id <= 0 || m_endpointIds.insert(id).second == false)
            {
                logError(RTPS_EDP, "Repeated or negative ID in XML file");
                delete(wdata);
                return XMLP_ret::XML_ERROR;
            }
            wdata->userDefinedId(id);
        }
        else if (key == ENTITY_ID)
        {
            int32_t id = std::strtol(element->GetText(), nullptr, 10);
            if (id <= 0 || m_entityIds.insert(id).second == false)
            {
                logError(RTPS_EDP, "Repeated or negative entityId in XML file");
                delete(wdata);
                return XMLP_ret::XML_ERROR;
            }
            octet* c = (octet*)&id;
            wdata->guid().entityId.value[2] = c[0];
            wdata->guid().entityId.value[1] = c[1];
            wdata->guid().entityId.value[0] = c[2];
        }
        else if (key == EXPECT_INLINE_QOS)
        {
            logWarning(RTPS_EDP, "BAD XML tag: Writers don't use expectInlineQos tag");
        }
        else if (key == TOPIC)
        {
            const char* topicName = element->Attribute(NAME);
            wdata->topicName(std::string(topicName ? topicName : EPROSIMA_UNKNOWN_STRING));
            const char* typeName = element->Attribute(DATA_TYPE);
            wdata->typeName(std::string(typeName ? typeName : EPROSIMA_UNKNOWN_STRING));
            const char* kind = element->Attribute(KIND);
            std::string auxString(kind ? kind : "");
            if (auxString == _NO_KEY)
            {
                wdata->topicKind(NO_KEY);
                wdata->guid().entityId.value[3] = 0x03;
            }
            else if (auxString == _WITH_KEY)
            {
                wdata->topicKind(WITH_KEY);
                wdata->guid().entityId.value[3] = 0x02;
            }
            else
            {
                logError(RTPS_EDP, "Bad XML file, topic of kind: " << auxString << " is not valid");
                delete(wdata);
                return XMLP_ret::XML_ERROR;
            }
            if (wdata->topicName() == EPROSIMA_UNKNOWN_STRING || wdata->typeName() == EPROSIMA_UNKNOWN_STRING)
            {
                logError(RTPS_EDP,
                        "Bad XML file, topic: " << wdata->topicName() << " or typeName: " << wdata->typeName() <<
                        " undefined");
                delete(wdata);
                return XMLP_ret::XML_ERROR;
            }
        }
        else if (key == TOPIC_NAME)
        {
            wdata->topicName(std::string(element->GetText()));
        }
        else if (key == TOPIC_DATA_TYPE)
        {
            wdata->typeName(std::string(element->GetText()));
        }
        else if (key == TOPIC_KIND)
        {
            std::string auxString = std::string(element->GetText());
            if (auxString == _NO_KEY)
            {
                wdata->topicKind(NO_KEY);
                wdata->guid().entityId.value[3] = 0x03;
            }
            else if (auxString == _WITH_KEY)
            {
                wdata->topicKind(WITH_KEY);
                wdata->guid().entityId.value[3] = 0x02;
            }
            else
            {
                logError(RTPS_EDP, "Bad XML file, topic of kind: " << auxString << " is not valid");
                delete(wdata);
                return XMLP_ret::XML_ERROR;
            }
        }
        else if (key == RELIABILITY_QOS)
        {
            std::string auxString = std::string(element->GetText());
            if (auxString == _RELIABLE_RELIABILITY_QOS)
            {
                wdata->m_qos.m_reliability.kind = RELIABLE_RELIABILITY_QOS;
            }
            else if (auxString == _BEST_EFFORT_RELIABILITY_QOS)
            {
                wdata->m_qos.m_reliability.kind = BEST_EFFORT_RELIABILITY_QOS;
            }
            else
            {
                logError(RTPS_EDP, "Bad XML file, endpoint of stateKind: " << auxString << " is not valid");
                delete(wdata);
                return XMLP_ret::XML_ERROR;
            }
        }
        else if (key == UNICAST_LOCATOR)
        {
            // Empty but necessary to avoid warning on last else
        }
        else if (key == MULTICAST_LOCATOR)
        {
            // Empty but necessary to avoid warning on last else
        }
        else if (key == DURABILITY_QOS)
        {
            std::string auxstring = std::string(element->GetText());
            if (auxstring == _PERSISTENT_DURABILITY_QOS)
            {
                wdata->m_qos.m_durability.kind = PERSISTENT_DURABILITY_QOS;
            }
            else if (auxstring == _TRANSIENT_DURABILITY_QOS)
            {
                wdata->m_qos.m_durability.kind = TRANSIENT_DURABILITY_QOS;
            }
            else if (auxstring == _TRANSIENT_LOCAL_DURABILITY_QOS)
            {
                wdata->m_qos.m_durability.kind = TRANSIENT_LOCAL_DURABILITY_QOS;
            }
            else if (auxstring == _VOLATILE_DURABILITY_QOS)
            {
                wdata->m_qos.m_durability.kind = VOLATILE_DURABILITY_QOS;
            }
            else
            {
                logError(RTPS_EDP, "Bad XML file, durability of kind: " << auxstring << " is not valid");
                delete(wdata);
                return XMLP_ret::XML_ERROR;
            }
        }
        else if (key == OWNERSHIP_QOS)
        {
            const char* kind = element->Attribute(KIND);
            std::string auxstring(kind ? kind : OWNERSHIP_KIND_NOT_PRESENT);
            if (auxstring == _SHARED_OWNERSHIP_QOS)
            {
                wdata->m_qos.m_ownership.kind = SHARED_OWNERSHIP_QOS;
            }
            else if (auxstring == _EXCLUSIVE_OWNERSHIP_QOS)
            {
                wdata->m_qos.m_ownership.kind = EXCLUSIVE_OWNERSHIP_QOS;
            }
            else
            {
                logError(RTPS_EDP, "Bad XML file, ownership of kind: " << auxstring << " is not valid");
                delete(wdata);
                return XMLP_ret::XML_ERROR;
            }
            int strength = 0;
            element->QueryIntAttribute(STRENGTH, &strength);
            wdata->m_qos.m_ownershipStrength.value = strength;
        }
        else if (key == PARTITION_QOS)
        {
            wdata->m_qos.m_partition.push_back(element->GetText());
        }
        else if (key == LIVELINESS_QOS)
        {
            const char* kind = element->Attribute(KIND);
            std::string auxstring(kind ? kind : LIVELINESS_KIND_NOT_PRESENT);
            if (auxstring == _AUTOMATIC_LIVELINESS_QOS)
            {
                wdata->m_qos.m_liveliness.kind = AUTOMATIC_LIVELINESS_QOS;
            }
            else if (auxstring == _MANUAL_BY_PARTICIPANT_LIVELINESS_QOS)
            {
                wdata->m_qos.m_liveliness.kind = MANUAL_BY_PARTICIPANT_LIVELINESS_QOS;
            }
            else if (auxstring == _MANUAL_BY_TOPIC_LIVELINESS_QOS)
            {
                wdata->m_qos.m_liveliness.kind = MANUAL_BY_TOPIC_LIVELINESS_QOS;
            }
            else
            {
                logError(RTPS_EDP, "Bad XML file, liveliness of kind: " << auxstring << " is not valid");
                delete(wdata);
                return XMLP_ret::XML_ERROR;
            }
            const char* leaseDuration_ms = element->Attribute(LEASE_DURATION_MS);
            auxstring = std::string(leaseDuration_ms ? leaseDuration_ms : _INF);
            if (auxstring == _INF)
            {
                wdata->m_qos.m_liveliness.lease_duration = c_TimeInfinite;
            }
            else
            {
                uint32_t milliseclease = std::strtoul(auxstring.c_str(), nullptr, 10);
                wdata->m_qos.m_liveliness.lease_duration =
                        TimeConv::MilliSeconds2Time_t((double)milliseclease).to_duration_t();
                if (milliseclease == 0)
                {
                    logWarning(RTPS_EDP, "BAD XML:livelinessQos leaseDuration is 0");
                }
            }
        }
        else if (key == DISABLE_POSITIVE_ACKS)
        {
            // Disable positive acks
            if (XMLP_ret::XML_OK !=
                    XMLParser::getXMLDisablePositiveAcksQos(element, wdata->m_qos.m_disablePositiveACKs, 0))
            {
                return XMLP_ret::XML_ERROR;
            }
        }
        else
        {
            logWarning(RTPS_EDP, "Unkown Endpoint-XML tag, ignoring " << key);
        }

        element = element->NextSiblingElement();
    }

    if (wdata->userDefinedId() == 0)
    {
        logError(RTPS_EDP, "Writer XML endpoint with NO ID defined");
        delete(wdata);
        return XMLP_ret::XML_ERROR;
    }

    for (const Locator_t& loc : unicast_locators)
    {
        wdata->add_unicast_locator(loc);
    }

    for (const Locator_t& loc : multicast_locators)
    {
        wdata->add_multicast_locator(loc);
    }

    pdata->m_writers.push_back(wdata);
    return XMLP_ret::XML_OK;
}

XMLP_ret XMLEndpointParser::lookforReader(
        const char* partname,
        uint16_t id,
        ReaderProxyData** rdataptr)
{
    for (std::vector<StaticRTPSParticipantInfo*>::iterator pit = m_RTPSParticipants.begin();
            pit != m_RTPSParticipants.end(); ++pit)
    {
        if ((*pit)->m_RTPSParticipantName == partname || true) //it doenst matter the name fo the RTPSParticipant, only for organizational purposes
        {
            for (std::vector<ReaderProxyData*>::iterator rit = (*pit)->m_readers.begin();
                    rit != (*pit)->m_readers.end(); ++rit)
            {
                if ((*rit)->userDefinedId() == id)
                {
                    *rdataptr = *rit;
                    return XMLP_ret::XML_OK;
                }
            }
        }
    }
    return XMLP_ret::XML_ERROR;
}

XMLP_ret XMLEndpointParser::lookforWriter(
        const char* partname,
        uint16_t id,
        WriterProxyData** wdataptr)
{
    for (std::vector<StaticRTPSParticipantInfo*>::iterator pit = m_RTPSParticipants.begin();
            pit != m_RTPSParticipants.end(); ++pit)
    {
        if ((*pit)->m_RTPSParticipantName == partname || true) //it doenst matter the name fo the RTPSParticipant, only for organizational purposes
        {
            for (std::vector<WriterProxyData*>::iterator wit = (*pit)->m_writers.begin();
                    wit != (*pit)->m_writers.end(); ++wit)
            {
                if ((*wit)->userDefinedId() == id)
                {
                    *wdataptr = *wit;
                    return XMLP_ret::XML_OK;
                }
            }
        }
    }
    return XMLP_ret::XML_ERROR;
}
