From fb32f562eb8e8fdfd8f3e66d3382e8c86cdae5e1 Mon Sep 17 00:00:00 2001 From: Christoph Pohl <christoph.pohl@kit.edu> Date: Fri, 4 Nov 2022 18:19:41 +0100 Subject: [PATCH] Add PropertyHelper Factories and Products --- .../AronComponentConfigExample.cpp | 4 + .../aron_component_config/CMakeLists.txt | 2 + .../PropertyDefinitionVisitors.cpp | 141 ++++++------------ .../PropertyHelper.cpp | 137 +++++++++++++++++ .../TypeDescriptorFactories/PropertyHelper.h | 110 ++++++++++++++ 5 files changed, 297 insertions(+), 97 deletions(-) create mode 100644 source/RobotAPI/libraries/aron_component_config/TypeDescriptorFactories/PropertyHelper.cpp create mode 100644 source/RobotAPI/libraries/aron_component_config/TypeDescriptorFactories/PropertyHelper.h diff --git a/source/RobotAPI/components/AronComponentConfigExample/AronComponentConfigExample.cpp b/source/RobotAPI/components/AronComponentConfigExample/AronComponentConfigExample.cpp index 2f5095b5b..683fcef10 100644 --- a/source/RobotAPI/components/AronComponentConfigExample/AronComponentConfigExample.cpp +++ b/source/RobotAPI/components/AronComponentConfigExample/AronComponentConfigExample.cpp @@ -57,6 +57,10 @@ namespace armarx ARMARX_TRACE; auto& config = aron_component_config_plugin_->config_.getWriteBuffer(); + for (const auto& [key, value] : config.subMember.subsubMember.intDictMember) + { + ARMARX_INFO << key << value; + } config.intMember--; aron_component_config_plugin_->config_.commitWrite(); }, 1000); diff --git a/source/RobotAPI/libraries/aron_component_config/CMakeLists.txt b/source/RobotAPI/libraries/aron_component_config/CMakeLists.txt index f9e545e5c..cc784baff 100644 --- a/source/RobotAPI/libraries/aron_component_config/CMakeLists.txt +++ b/source/RobotAPI/libraries/aron_component_config/CMakeLists.txt @@ -29,6 +29,7 @@ set(LIBS set(LIB_FILES PropertyDefinitionVisitors.cpp RemoteGuiVisitors.cpp + TypeDescriptorFactories/PropertyHelper.cpp ) set(LIB_HEADERS @@ -37,6 +38,7 @@ set(LIB_HEADERS RemoteGuiVisitors.h Util.h ComponentPlugin.h + TypeDescriptorFactories/PropertyHelper.h ) diff --git a/source/RobotAPI/libraries/aron_component_config/PropertyDefinitionVisitors.cpp b/source/RobotAPI/libraries/aron_component_config/PropertyDefinitionVisitors.cpp index bf606b399..94bb96597 100644 --- a/source/RobotAPI/libraries/aron_component_config/PropertyDefinitionVisitors.cpp +++ b/source/RobotAPI/libraries/aron_component_config/PropertyDefinitionVisitors.cpp @@ -26,6 +26,7 @@ #include <ArmarXCore/core/application/properties/PropertyDefinition.h> #include <ArmarXCore/core/application/properties/PropertyUser.h> #include <RobotAPI/libraries/aron/core/data/variant/All.h> +#include <RobotAPI/libraries/aron_component_config/TypeDescriptorFactories/PropertyHelper.h> #include "Util.h" @@ -89,8 +90,13 @@ namespace armarx::aron::component_config void PropertyDefinitionGetterVisitor::visitListOnEnter(DataInput& o, TypeInput& t) { + in_list_ = true; const auto& name = pathToName(o); - const auto& type = type::List::DynamicCast(t); + const auto& t_desc = type::List::DynamicCast(t)->getAcceptedType()->getDescriptor(); + if (t_desc == type::Descriptor::OBJECT) + { + return; + } auto old_list = data::List::DynamicCast(o); old_list->clear(); auto get_list = [this, & name]() -> std::vector<std::string> @@ -100,32 +106,15 @@ namespace armarx::aron::component_config return simox::alg::split(list, ","); }; int i = 0; - switch (type->getAcceptedType()->getDescriptor()) + std::vector<std::string> vector = get_list(); + std::for_each(vector.begin(), vector.end(), [&old_list, &i, &t_desc](const auto& el) { - case type::Descriptor::INT: - { - std::vector<std::string> vector = get_list(); - std::for_each(vector.begin(), vector.end(), [&old_list, &i](const auto& el) - { - old_list->addElement(make_int(std::stoi(el), old_list->getPath().withIndex(i))); - i++; - }); - break; - } - case type::Descriptor::STRING: - { - std::vector<std::string> vector = get_list(); - std::for_each(vector.begin(), vector.end(), [&old_list, &i](const auto& el) - { - old_list->addElement(make_string(el, old_list->getPath().withIndex(i))); - i++; - }); - break; - } - default: - throw armarx::NotImplementedYetException(); - } - in_list_ = true; + old_list->addElement(factories::PropertyHelper::make(t_desc)->from_string(el, + old_list->getPath() + .withIndex(i))); + i++; + }); + } void @@ -159,10 +148,15 @@ namespace armarx::aron::component_config PropertyDefinitionGetterVisitor::visitDictOnEnter(std::shared_ptr<data::Variant>& o, const std::shared_ptr<type::Variant>& t) { + in_list_ = true; const auto& name = pathToName(o); - const auto& type = type::Dict::DynamicCast(t); - auto old_list = data::Dict::DynamicCast(o); - old_list->clear(); + const auto& t_desc = type::Dict::DynamicCast(t)->getAcceptedType()->getDescriptor(); + if (t_desc == type::Descriptor::OBJECT) + { + return; + } + auto old_dict = data::Dict::DynamicCast(o); + old_dict->clear(); auto get_list = [this, & name]() -> std::vector<std::string> { std::string list; @@ -170,34 +164,14 @@ namespace armarx::aron::component_config return simox::alg::split(list, ","); }; std::vector<std::string> vector = get_list(); - switch (type->getAcceptedType()->getDescriptor()) + std::for_each(vector.begin(), vector.end(), [&old_dict, &t_desc](const auto& el) { - case type::Descriptor::INT: - { - std::for_each(vector.begin(), vector.end(), [&old_list](const auto& el) - { - auto key_value = simox::alg::split(el, ":"); - old_list->addElement(key_value.front(), - make_int(std::stoi(key_value.back()), - old_list->getPath().withElement(key_value.front()))); - }); - break; - } - case type::Descriptor::STRING: - { - std::for_each(vector.begin(), vector.end(), [&old_list](const auto& el) - { - auto key_value = simox::alg::split(el, ":"); - old_list->addElement(key_value.front(), - make_string(key_value.back(), - old_list->getPath().withElement(key_value.front()))); - }); - break; - } - default: - throw armarx::NotImplementedYetException(); - } - in_list_ = true; + auto key_value = simox::alg::split(el, ":"); + old_dict->addElement(key_value.front(), + factories::PropertyHelper::make(t_desc)->from_string(key_value.back(), + old_dict->getPath() + .withElement(key_value.front()))); + }); } void @@ -303,34 +277,18 @@ namespace armarx::aron::component_config in_list_ = true; const auto& name = pathToName(l); const auto& t_desc = t->getAcceptedType()->getDescriptor(); + if (t_desc == type::Descriptor::OBJECT) + { + return; + } const auto& input = l->getElements(); std::string str; - switch (t_desc) + std::vector<std::string> vector; + std::transform(input.begin(), input.end(), std::back_inserter(vector), [&t_desc](const auto& el) { - case type::Descriptor::INT: - { - std::vector<int> vector; - std::transform(input.begin(), input.end(), std::back_inserter(vector), [](const auto& el) - { - return data::Int::DynamicCast(el)->getValue(); - }); - str = simox::alg::to_string(vector, ", "); - break; - } - case type::Descriptor::STRING: - { - std::vector<std::string> vector; - std::transform(input.begin(), input.end(), std::back_inserter(vector), [](const auto& el) - { - return data::String::DynamicCast(el)->getValue(); - }); - str = simox::alg::to_string(vector, ", "); - break; - } - // TODO: other basic types - default: - throw armarx::NotImplementedYetException(); - } + return factories::PropertyHelper::make(t_desc)->to_string(el); + }); + str = simox::alg::to_string(vector, ", "); property_definitions_->defineOptionalProperty<std::string>(name, str); } @@ -346,27 +304,16 @@ namespace armarx::aron::component_config in_list_ = true; const auto& name = pathToName(d); const auto& t_desc = t->getAcceptedType()->getDescriptor(); + if (t_desc == type::Descriptor::OBJECT) + { + return; + } const auto& input = d->getElements(); std::stringstream ss; for (const auto& [key, el]: input) { ss << key << ":"; - switch (t_desc) - { - case type::Descriptor::INT: - { - ss << data::Int::DynamicCast(el)->getValue(); - break; - } - case type::Descriptor::STRING: - { - ss << data::String::DynamicCast(el)->getValue(); - break; - } - // TODO: other basic types - default: - throw armarx::NotImplementedYetException(); - } + ss << factories::PropertyHelper::make(t_desc)->to_string(el); ss << ","; } std::string value = ss.str(); diff --git a/source/RobotAPI/libraries/aron_component_config/TypeDescriptorFactories/PropertyHelper.cpp b/source/RobotAPI/libraries/aron_component_config/TypeDescriptorFactories/PropertyHelper.cpp new file mode 100644 index 000000000..14771c282 --- /dev/null +++ b/source/RobotAPI/libraries/aron_component_config/TypeDescriptorFactories/PropertyHelper.cpp @@ -0,0 +1,137 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI + * @author Christoph Pohl ( christoph dot pohl at kit dot edu ) + * @date 04.11.22 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + +#include <RobotAPI/libraries/aron/core/data/variant/All.h> +#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h> +#include "PropertyHelper.h" + +namespace armarx::aron::component_config::products +{ + template <> + std::string + PropertyHelper<type::Descriptor::INT>::to_string(const data::VariantPtr& ptr) const + { + return simox::alg::to_string(data::Int::DynamicCast(ptr)->getValue()); + } + + template <> + std::string + PropertyHelper<type::Descriptor::BOOL>::to_string(const data::VariantPtr& ptr) const + { + return simox::alg::to_string(data::Bool::DynamicCast(ptr)->getValue()); + } + + template <> + std::string + PropertyHelper<type::Descriptor::STRING>::to_string(const data::VariantPtr& ptr) const + { + return data::String::DynamicCast(ptr)->getValue(); + } + + template <> + std::string + PropertyHelper<type::Descriptor::FLOAT>::to_string(const data::VariantPtr& ptr) const + { + return simox::alg::to_string(data::Float::DynamicCast(ptr)->getValue()); + } + + template <> + std::string + PropertyHelper<type::Descriptor::INT_ENUM>::to_string(const data::VariantPtr& ptr) const + { + // TODO: this is should use the name of the enum value + return simox::alg::to_string(data::Int::DynamicCast(ptr)->getValue()); + } + + template <> + std::string + PropertyHelper<type::Descriptor::DOUBLE>::to_string(const data::VariantPtr& ptr) const + { + return simox::alg::to_string(data::Double::DynamicCast(ptr)->getValue()); + } + + template <> + aron::data::VariantPtr + products::PropertyHelper<type::Descriptor::INT>::from_string(const std::string& string, + const armarx::aron::Path& path) const + { + return make_int(std::stoi(string), path); + } + + template <> + aron::data::VariantPtr + products::PropertyHelper<type::Descriptor::FLOAT>::from_string(const std::string& string, + const armarx::aron::Path& path) const + { + return make_float(std::stof(string), path); + } + + template <> + aron::data::VariantPtr + products::PropertyHelper<type::Descriptor::DOUBLE>::from_string(const std::string& string, + const armarx::aron::Path& path) const + { + return make_double(std::stod(string), path); + } + + template <> + aron::data::VariantPtr + products::PropertyHelper<type::Descriptor::BOOL>::from_string(const std::string& string, + const armarx::aron::Path& path) const + { + if (string == "true") + { + return make_bool(true, path); + } + else if (string == "false") + { + return make_bool(false, path); + } + throw armarx::InvalidArgumentException("Boolean string has to be either true or false"); + } + + template <> + aron::data::VariantPtr + products::PropertyHelper<type::Descriptor::INT_ENUM>::from_string(const std::string& string, + const armarx::aron::Path& path) const + { + // TODO: this might not work + return make_int(std::stoi(string), path); + } + + template <> + aron::data::VariantPtr + products::PropertyHelper<type::Descriptor::STRING>::from_string(const std::string& string, + const armarx::aron::Path& path) const + { + return make_string(string, path); + } + + + + template struct products::PropertyHelper<type::Descriptor::INT>; + template struct products::PropertyHelper<type::Descriptor::STRING>; + template struct products::PropertyHelper<type::Descriptor::BOOL>; + template struct products::PropertyHelper<type::Descriptor::FLOAT>; + template struct products::PropertyHelper<type::Descriptor::DOUBLE>; + template struct products::PropertyHelper<type::Descriptor::INT_ENUM>; +} \ No newline at end of file diff --git a/source/RobotAPI/libraries/aron_component_config/TypeDescriptorFactories/PropertyHelper.h b/source/RobotAPI/libraries/aron_component_config/TypeDescriptorFactories/PropertyHelper.h new file mode 100644 index 000000000..cfb5ef2ba --- /dev/null +++ b/source/RobotAPI/libraries/aron_component_config/TypeDescriptorFactories/PropertyHelper.h @@ -0,0 +1,110 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI + * @author Christoph Pohl ( christoph dot pohl at kit dot edu ) + * @date 04.11.22 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + +#pragma once + +#include <ArmarXCore/util/CPPUtility/SelfRegisteringFactory.h> +#include <ArmarXCore/core/application/properties/forward_declarations.h> +#include <RobotAPI/libraries/aron/core/Descriptor.h> +#include <RobotAPI/libraries/aron/core/data/variant/Variant.h> + +namespace armarx::aron::component_config +{ + namespace factories + { + struct PropertyHelper : armarx::Factory<PropertyHelper, type::Descriptor> + { + explicit PropertyHelper(Key) + { + }; + + virtual ~PropertyHelper() = default; + + virtual std::string to_string(const armarx::aron::data::VariantPtr&) const = 0; + virtual aron::data::VariantPtr from_string(const std::string&, const armarx::aron::Path& path) const = 0; + }; + } + namespace products + { + template <type::Descriptor DescT> + struct PropertyHelper : factories::PropertyHelper::Registrar<PropertyHelper<DescT>> + { + using RegistrarT = factories::PropertyHelper::Registrar<PropertyHelper<DescT>>; + static constexpr type::Descriptor id = DescT; + + explicit PropertyHelper() : RegistrarT(typename RegistrarT::Registration()) + { + }; + + [[nodiscard]] std::string to_string(const data::VariantPtr& ptr) const override; + [[nodiscard]] aron::data::VariantPtr from_string(const std::string&, const armarx::aron::Path& path) const override; + }; + + + } + + template <> + std::string + products::PropertyHelper<type::Descriptor::INT>::to_string(const data::VariantPtr& ptr) const; + template <> + aron::data::VariantPtr + products::PropertyHelper<type::Descriptor::INT>::from_string(const std::string&, const armarx::aron::Path& path) const; + template <> + std::string + products::PropertyHelper<type::Descriptor::FLOAT>::to_string(const data::VariantPtr& ptr) const; + template <> + aron::data::VariantPtr + products::PropertyHelper<type::Descriptor::FLOAT>::from_string(const std::string&, const armarx::aron::Path& path) const; + template <> + std::string + products::PropertyHelper<type::Descriptor::BOOL>::to_string(const data::VariantPtr& ptr) const; + template <> + aron::data::VariantPtr + products::PropertyHelper<type::Descriptor::BOOL>::from_string(const std::string&, const armarx::aron::Path& path) const; + template <> + std::string + products::PropertyHelper<type::Descriptor::STRING>::to_string(const data::VariantPtr& ptr) const; + template <> + aron::data::VariantPtr + products::PropertyHelper<type::Descriptor::STRING>::from_string(const std::string&, const armarx::aron::Path& path) const; + template <> + std::string + products::PropertyHelper<type::Descriptor::DOUBLE>::to_string(const data::VariantPtr& ptr) const; + template <> + aron::data::VariantPtr + products::PropertyHelper<type::Descriptor::DOUBLE>::from_string(const std::string&, const armarx::aron::Path& path) const; + template <> + std::string + products::PropertyHelper<type::Descriptor::INT_ENUM>::to_string(const data::VariantPtr& ptr) const; + template <> + aron::data::VariantPtr + products::PropertyHelper<type::Descriptor::INT_ENUM>::from_string(const std::string&, const armarx::aron::Path& path) const; + + + extern template struct products::PropertyHelper<type::Descriptor::INT>; + extern template struct products::PropertyHelper<type::Descriptor::FLOAT>; + extern template struct products::PropertyHelper<type::Descriptor::DOUBLE>; + extern template struct products::PropertyHelper<type::Descriptor::STRING>; + extern template struct products::PropertyHelper<type::Descriptor::BOOL>; + extern template struct products::PropertyHelper<type::Descriptor::INT_ENUM>; +} + -- GitLab