Skip to content

Commit

Permalink
Refactor XML Parser to return DynamicTypeBuilder instead of DynamicTy…
Browse files Browse the repository at this point in the history
…pe (#4970)

* Refs #21184: Refactor get_dynamic_type_builder_from_xml_by_name and getDynamicTypeByName to get a DynamicTypeBuilder

Signed-off-by: elianalf <[email protected]>

* Refs #21184: Adjust dynamic types tests

Signed-off-by: elianalf <[email protected]>

* Refs #21184: Add flag to xtypes example to get types and profiles from xml

Signed-off-by: elianalf <[email protected]>

* Refs #21184: Update methods name

Signed-off-by: elianalf <[email protected]>

* Refs #21184: Update version.md

Signed-off-by: elianalf <[email protected]>

* Refs #21184: Uncrustify

Signed-off-by: elianalf <[email protected]>

* Refs #21184: Make type definition by xml loaded by environment variable works

Signed-off-by: elianalf <[email protected]>

* Refs #21184: Make type works with hello world

Signed-off-by: elianalf <[email protected]>

* Refs #21184: Add test for the example to load the type from xml

Signed-off-by: elianalf <[email protected]>

* Refs #21184: Apply suggestions

Signed-off-by: elianalf <[email protected]>

* Refs #21184: UNcrustify

Signed-off-by: elianalf <[email protected]>

* Refs #21184: Clarify how to use xml-type flag

Signed-off-by: elianalf <[email protected]>

* Refs #21184: Fix xml parser test

Signed-off-by: elianalf <[email protected]>

* Refs #21184: Fix parse XML dynamic type throwing exception to return nullptr

Signed-off-by: elianalf <[email protected]>

* Refs #Apply suggestions

Signed-off-by: elianalf <[email protected]>

* Refs #21184: Compare DynamicType with DynamicType, instead of DynamicTypeBuilder

Signed-off-by: elianalf <[email protected]>

* Refs #21184: Fix xml parser las test

Signed-off-by: elianalf <[email protected]>

---------

Signed-off-by: elianalf <[email protected]>
  • Loading branch information
elianalf committed Jul 3, 2024
1 parent c21dbcf commit bc557b7
Show file tree
Hide file tree
Showing 18 changed files with 372 additions and 275 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
#include <fastdds/dds/publisher/qos/PublisherQos.hpp>
#include <fastdds/dds/xtypes/dynamic_types/DynamicDataFactory.hpp>
#include <fastdds/dds/xtypes/dynamic_types/DynamicData.hpp>
#include <fastdds/dds/xtypes/dynamic_types/DynamicType.hpp>

using namespace eprosima::fastdds::dds;

Expand All @@ -49,18 +48,18 @@ bool HelloWorldPublisher::init()
return false;
}

DynamicType::_ref_type dyn_type;
DynamicTypeBuilder::_ref_type dyn_type_builder;
if (RETCODE_OK !=
DomainParticipantFactory::get_instance()->get_dynamic_type_builder_from_xml_by_name("HelloWorld",
dyn_type))
dyn_type_builder))
{
std::cout <<
"Error getting dynamic type \"HelloWorld\"." << std::endl;
return false;
}

TypeSupport m_type(new DynamicPubSubType(dyn_type));
m_Hello = DynamicDataFactory::get_instance()->create_data(dyn_type);
TypeSupport m_type(new DynamicPubSubType(dyn_type_builder->build()));
m_Hello = DynamicDataFactory::get_instance()->create_data(dyn_type_builder->build());
m_Hello->set_string_value(m_Hello->get_member_id_by_name("message"), "Hello DDS Dynamic World");
m_Hello->set_uint32_value(m_Hello->get_member_id_by_name("index"), 0);
m_Hello->set_uint32_values(m_Hello->get_member_id_by_name("array"), {10, 20, 30, 40, 50, 60, 70, 80, 90, 100});
Expand Down
46 changes: 35 additions & 11 deletions examples/cpp/xtypes/CLIParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class CLIParser
{
CLIParser::EntityKind entity = CLIParser::EntityKind::UNDEFINED;
uint16_t samples = 0;
bool use_xml = false;
};

/**
Expand All @@ -57,17 +58,22 @@ class CLIParser
static void print_help(
uint8_t return_code)
{
std::cout << "Usage: xtypes <entity> [options]" << std::endl;
std::cout << "" << std::endl;
std::cout << "Entities:" << std::endl;
std::cout << " publisher Run a publisher entity" << std::endl;
std::cout << " subscriber Run a subscriber entity" << std::endl;
std::cout << "" << std::endl;
std::cout << "Common options:" << std::endl;
std::cout << " -h, --help Print this help message" << std::endl;
std::cout << " -s <num>, --samples <num> Number of samples to send or receive" << std::endl;
std::cout << " [0 <= <num> <= 65535]" << std::endl;
std::cout << " (Default: 0 [unlimited])" << std::endl;
std::cout << "Usage: xtypes <entity> [options]" << std::endl;
std::cout << "" << std::endl;
std::cout << "Entities:" << std::endl;
std::cout << " publisher Run a publisher entity" << std::endl;
std::cout << " subscriber Run a subscriber entity" << std::endl;
std::cout << "" << std::endl;
std::cout << "Common options:" << std::endl;
std::cout << " -h, --help Print this help message" << std::endl;
std::cout << " -s <num>, --samples <num> Number of samples to send or receive" << std::endl;
std::cout << " [0 <= <num> <= 65535]" << std::endl;
std::cout << " (Default: 0 [unlimited])" << std::endl;
std::cout << "Publisher options:" << std::endl;
std::cout << " --xml-type Get types defined in xml file. " << std::endl;
std::cout << " The xml file to use must be set " << std::endl;
std::cout << " through environment variable." << std::endl;
std::cout << " (Default: Types defined with C++ API) " << std::endl;
std::exit(return_code);
}

Expand Down Expand Up @@ -158,6 +164,24 @@ class CLIParser
print_help(EXIT_FAILURE);
}
}
else if (arg == "--xml-type")
{
if (config.entity == CLIParser::EntityKind::PUBLISHER)
{
config.use_xml = true;
}
else if (config.entity == CLIParser::EntityKind::SUBSCRIBER)
{
EPROSIMA_LOG_ERROR(CLI_PARSER, "--xml-type flag available only for subscriber entity");
print_help(EXIT_FAILURE);
}
else
{
EPROSIMA_LOG_ERROR(CLI_PARSER, "entity not specified for --xml-type flag");
print_help(EXIT_FAILURE);
}
}

else
{
EPROSIMA_LOG_ERROR(CLI_PARSER, "unknown option " + arg);
Expand Down
95 changes: 55 additions & 40 deletions examples/cpp/xtypes/PublisherApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,17 @@ PublisherApp::PublisherApp(
, samples_(config.samples)
, stop_(false)
{
// Create the type
DynamicType::_ref_type dynamic_type = create_type();
// Create the participant
auto factory = DomainParticipantFactory::get_instance();
participant_ = factory->create_participant_with_default_profile(nullptr, StatusMask::none());

if (participant_ == nullptr)
{
throw std::runtime_error("Participant initialization failed");
}

// Create the type
DynamicType::_ref_type dynamic_type = create_type(config.use_xml);
if (!dynamic_type)
{
throw std::runtime_error("Error creating dynamic type");
Expand All @@ -71,15 +79,6 @@ PublisherApp::PublisherApp(
hello_->set_uint32_value(hello_->get_member_id_by_name("index"), 0);
hello_->set_string_value(hello_->get_member_id_by_name("message"), "Hello xtypes world");

// Create the participant
auto factory = DomainParticipantFactory::get_instance();
participant_ = factory->create_participant_with_default_profile(nullptr, StatusMask::none());

if (participant_ == nullptr)
{
throw std::runtime_error("Participant initialization failed");
}

// Register the type
TypeSupport type(new DynamicPubSubType(dynamic_type));

Expand Down Expand Up @@ -227,43 +226,59 @@ void PublisherApp::stop()
cv_.notify_one();
}

DynamicType::_ref_type PublisherApp::create_type()
DynamicType::_ref_type PublisherApp::create_type(
bool use_xml_type)
{
// Define a struct type with various primitive members
TypeDescriptor::_ref_type type_descriptor {traits<TypeDescriptor>::make_shared()};
type_descriptor->kind(TK_STRUCTURE);
type_descriptor->name("HelloWorld");
DynamicTypeBuilder::_ref_type struct_builder {DynamicTypeBuilderFactory::get_instance()->create_type(type_descriptor)};

if (!struct_builder)
DynamicTypeBuilder::_ref_type struct_builder;
if (use_xml_type)
{
throw std::runtime_error("Error creating type builder");
// Retrieve the type builder from xml
if (RETCODE_OK !=
DomainParticipantFactory::get_instance()->get_dynamic_type_builder_from_xml_by_name("HelloWorld",
struct_builder))
{
std::cout <<
"Error getting dynamic type \"HelloWorld\"." << std::endl;
}
}
else
{
TypeDescriptor::_ref_type type_descriptor {traits<TypeDescriptor>::make_shared()};
type_descriptor->kind(TK_STRUCTURE);
type_descriptor->name("HelloWorld");
struct_builder = DynamicTypeBuilderFactory::get_instance()->create_type(type_descriptor);

// Add index member
MemberDescriptor::_ref_type index_member_descriptor {traits<MemberDescriptor>::make_shared()};
index_member_descriptor->name("index");
index_member_descriptor->type(DynamicTypeBuilderFactory::get_instance()->get_primitive_type(TK_UINT32));
if (!struct_builder)
{
throw std::runtime_error("Error creating type builder");
}

if (RETCODE_OK != struct_builder->add_member(index_member_descriptor))
{
throw std::runtime_error("Error adding index member");
}
// Add index member
MemberDescriptor::_ref_type index_member_descriptor {traits<MemberDescriptor>::make_shared()};
index_member_descriptor->name("index");
index_member_descriptor->type(DynamicTypeBuilderFactory::get_instance()->get_primitive_type(TK_UINT32));

// Add message member
MemberDescriptor::_ref_type message_member_descriptor {traits<MemberDescriptor>::make_shared()};
message_member_descriptor->name("message");
message_member_descriptor->type(DynamicTypeBuilderFactory::get_instance()->create_string_type(static_cast<uint32_t>(
LENGTH_UNLIMITED))->build());
if (RETCODE_OK != struct_builder->add_member(index_member_descriptor))
{
throw std::runtime_error("Error adding index member");
}

if (!message_member_descriptor)
{
throw std::runtime_error("Error creating string type");
}
// Add message member
MemberDescriptor::_ref_type message_member_descriptor {traits<MemberDescriptor>::make_shared()};
message_member_descriptor->name("message");
message_member_descriptor->type(DynamicTypeBuilderFactory::get_instance()->create_string_type(static_cast<
uint32_t>(
LENGTH_UNLIMITED))->build());

if (RETCODE_OK != struct_builder->add_member(message_member_descriptor))
{
throw std::runtime_error("Error adding message member");
if (!message_member_descriptor)
{
throw std::runtime_error("Error creating string type");
}

if (RETCODE_OK != struct_builder->add_member(message_member_descriptor))
{
throw std::runtime_error("Error adding message member");
}
}

// Build the type
Expand Down
3 changes: 2 additions & 1 deletion examples/cpp/xtypes/PublisherApp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ class PublisherApp : public Application, public DataWriterListener
bool publish();

//! Create the dynamic type used by the PublisherApp
static DynamicType::_ref_type create_type();
static DynamicType::_ref_type create_type(
bool use_xml_type);

//! Auxilary function to get a uint32_t value from a DynamicData object
static uint32_t get_uint32_value(
Expand Down
4 changes: 3 additions & 1 deletion examples/cpp/xtypes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ For further information regarding the configuration environment, please refer to
The particularity of this example resides in the use of X-Types, which allows the definition of types at runtime.
In this case:

1. The publisher application defines a type at runtime using the Fast DDS Dynamic Types API.
1. The publisher application creates a type at runtime using the Fast DDS Dynamic Types API.
The types can be configured through C++ API or [XML file](https://fast-dds.docs.eprosima.com/en/latest/fastdds/xml_configuration/dynamic_types.html).
The flag `--xml-types` allows to use the types defined in the XML file. The profile must be uploaded setting the environment variable ``FASTDDS_DEFAULT_PROFILES_FILE`` to the XML file path, see [XML profile playground](#xml-profile-playground).
2. The subscriber application discovers the type defined by the publisher and uses it to create a data reader, introspect the type, and print the received data.

It is important to note that this example is fully type compatible with the [Hello world](../hello_world/README.md) example, meaning that the publisher and subscriber applications can be run interchangeably with the *hello world* example applications.
Expand Down
1 change: 1 addition & 0 deletions examples/cpp/xtypes/SubscriberApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ SubscriberApp::SubscriberApp(
, reader_(nullptr)
, samples_(config.samples)
, received_samples_(0)
, type_discovered_(false)
, stop_(false)
{
// Create the participant
Expand Down
111 changes: 61 additions & 50 deletions examples/cpp/xtypes/xtypes_profile.xml
Original file line number Diff line number Diff line change
@@ -1,52 +1,63 @@
<?xml version="1.0" encoding="UTF-8" ?>
<profiles xmlns="http://www.eprosima.com" >
<participant profile_name="xtypes_participant_profile" is_default_profile="true">
<domainId>0</domainId>
<rtps>
<name>xtypes_participant</name>
</rtps>
</participant>
<data_writer profile_name="xtypes_datawriter_profile" is_default_profile="true">
<qos>
<durability>
<kind>TRANSIENT_LOCAL</kind>
</durability>
<reliability>
<kind>RELIABLE</kind>
</reliability>
</qos>
<topic>
<historyQos>
<kind>KEEP_LAST</kind>
<depth>100</depth>
</historyQos>
<resourceLimitsQos>
<max_samples>100</max_samples>
<max_instances>1</max_instances>
<max_samples_per_instance>100</max_samples_per_instance>
</resourceLimitsQos>
</topic>
</data_writer>
<dds xmlns="http://www.eprosima.com" >
<profiles>
<participant profile_name="xtypes_participant_profile" is_default_profile="true">
<domainId>0</domainId>
<rtps>
<name>xtypes_participant</name>
</rtps>
</participant>
<data_writer profile_name="xtypes_datawriter_profile" is_default_profile="true">
<qos>
<durability>
<kind>TRANSIENT_LOCAL</kind>
</durability>
<reliability>
<kind>RELIABLE</kind>
</reliability>
</qos>
<topic>
<historyQos>
<kind>KEEP_LAST</kind>
<depth>100</depth>
</historyQos>
<resourceLimitsQos>
<max_samples>100</max_samples>
<max_instances>1</max_instances>
<max_samples_per_instance>100</max_samples_per_instance>
</resourceLimitsQos>
</topic>
</data_writer>

<data_reader profile_name="xtypes_datareader_profile" is_default_profile="true">
<qos>
<durability>
<kind>TRANSIENT_LOCAL</kind>
</durability>
<reliability>
<kind>RELIABLE</kind>
</reliability>
</qos>
<topic>
<historyQos>
<kind>KEEP_LAST</kind>
<depth>100</depth>
</historyQos>
<resourceLimitsQos>
<max_samples>100</max_samples>
<max_instances>1</max_instances>
<max_samples_per_instance>100</max_samples_per_instance>
</resourceLimitsQos>
</topic>
</data_reader>
</profiles>
<data_reader profile_name="xtypes_datareader_profile" is_default_profile="true">
<qos>
<durability>
<kind>TRANSIENT_LOCAL</kind>
</durability>
<reliability>
<kind>RELIABLE</kind>
</reliability>
</qos>
<topic>
<historyQos>
<kind>KEEP_LAST</kind>
<depth>100</depth>
</historyQos>
<resourceLimitsQos>
<max_samples>100</max_samples>
<max_instances>1</max_instances>
<max_samples_per_instance>100</max_samples_per_instance>
</resourceLimitsQos>
</topic>
</data_reader>
</profiles>

<types>
<type>
<struct name="HelloWorld">
<member name="index" type="uint32"/>
<member name="message" type="string"/>
</struct>
</type>
</types>
</dds>
3 changes: 2 additions & 1 deletion include/fastdds/dds/domain/DomainParticipantFactory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <fastdds/dds/domain/qos/DomainParticipantFactoryQos.hpp>
#include <fastdds/dds/domain/qos/DomainParticipantQos.hpp>
#include <fastdds/dds/xtypes/dynamic_types/DynamicType.hpp>
#include <fastdds/dds/xtypes/dynamic_types/DynamicTypeBuilder.hpp>
#include <fastdds/dds/xtypes/type_representation/ITypeObjectRegistry.hpp>
#include <fastdds/LibrarySettings.hpp>

Expand Down Expand Up @@ -344,7 +345,7 @@ class DomainParticipantFactory
*/
FASTDDS_EXPORTED_API ReturnCode_t get_dynamic_type_builder_from_xml_by_name(
const std::string& type_name,
DynamicType::_ref_type& type);
DynamicTypeBuilder::_ref_type& type);

/**
* @brief Return the TypeObjectRegistry member to access the public API.
Expand Down
4 changes: 2 additions & 2 deletions src/cpp/fastdds/domain/DomainParticipantFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,13 +542,13 @@ ReturnCode_t DomainParticipantFactory::set_library_settings(

ReturnCode_t DomainParticipantFactory::get_dynamic_type_builder_from_xml_by_name(
const std::string& type_name,
DynamicType::_ref_type& type)
DynamicTypeBuilder::_ref_type& type_builder)
{
if (type_name.empty())
{
return RETCODE_BAD_PARAMETER;
}
if (XMLP_ret::XML_OK != XMLProfileManager::getDynamicTypeByName(type, type_name))
if (XMLP_ret::XML_OK != XMLProfileManager::getDynamicTypeBuilderByName(type_builder, type_name))
{
return RETCODE_NO_DATA;
}
Expand Down
Loading

0 comments on commit bc557b7

Please sign in to comment.