From 7ffd9b47f808534bc340d6b87e31356f7cb4d328 Mon Sep 17 00:00:00 2001
From: Rainer Kartmann <rainer.kartmann@kit.edu>
Date: Mon, 16 Aug 2021 10:27:18 +0200
Subject: [PATCH] Improve type name sanitization

---
 .../libraries/armem_gui/instance/GroupBox.cpp |  2 +-
 .../armem_gui/instance/InstanceView.cpp       |  4 +
 .../armem_gui/instance/sanitize_typename.cpp  | 46 +++++++--
 .../tree_builders/DataTreeBuilderBase.cpp     |  3 +-
 .../tree_builders/DataTreeBuilderBase.h       |  1 +
 .../libraries/armem_gui/test/ArMemGuiTest.cpp | 98 ++++++++++++++++---
 6 files changed, 133 insertions(+), 21 deletions(-)

diff --git a/source/RobotAPI/libraries/armem_gui/instance/GroupBox.cpp b/source/RobotAPI/libraries/armem_gui/instance/GroupBox.cpp
index ff828d443..6d2336805 100644
--- a/source/RobotAPI/libraries/armem_gui/instance/GroupBox.cpp
+++ b/source/RobotAPI/libraries/armem_gui/instance/GroupBox.cpp
@@ -15,7 +15,7 @@ namespace armarx::armem::gui::instance
 
         view = new armem::gui::InstanceView();
 
-        useTypeInfoCheckBox = new QCheckBox("Use Type Info", this);
+        useTypeInfoCheckBox = new QCheckBox("Use Type Information", this);
         useTypeInfoCheckBox->setChecked(true);
 
         QHBoxLayout* checkBoxLayout = new QHBoxLayout();
diff --git a/source/RobotAPI/libraries/armem_gui/instance/InstanceView.cpp b/source/RobotAPI/libraries/armem_gui/instance/InstanceView.cpp
index 2c788d698..a4b8af14b 100644
--- a/source/RobotAPI/libraries/armem_gui/instance/InstanceView.cpp
+++ b/source/RobotAPI/libraries/armem_gui/instance/InstanceView.cpp
@@ -175,6 +175,8 @@ namespace armarx::armem::gui::instance
     {
         if (!data)
         {
+            treeItemData->setText(int(Columns::TYPE), QString::fromStdString(""));
+
             armarx::gui::clearItem(treeItemData);
             QTreeWidgetItem* item = new QTreeWidgetItem({"(No data.)"});
             treeItemData->addChild(item);
@@ -189,6 +191,8 @@ namespace armarx::armem::gui::instance
         }
         else
         {
+            treeItemData->setText(int(Columns::TYPE), QString::fromStdString(""));
+
             DataTreeBuilder builder;
             builder.setColumns(int(Columns::KEY), int(Columns::VALUE), int(Columns::TYPE));
             builder.updateTree(treeItemData, data);
diff --git a/source/RobotAPI/libraries/armem_gui/instance/sanitize_typename.cpp b/source/RobotAPI/libraries/armem_gui/instance/sanitize_typename.cpp
index 0180b5196..c548192cb 100644
--- a/source/RobotAPI/libraries/armem_gui/instance/sanitize_typename.cpp
+++ b/source/RobotAPI/libraries/armem_gui/instance/sanitize_typename.cpp
@@ -10,6 +10,28 @@
 const std::string armarx::armem::gui::instance::rawMemoryIDTypeName = armarx::armem::arondto::MemoryID::toAronType()->getName();
 const std::string armarx::armem::gui::instance::sanitizedMemoryIDTypeName = "MemoryID";
 
+
+namespace
+{
+    std::string remove_prefix(const std::string& string, const std::string& prefix)
+    {
+        return simox::alg::starts_with(string, prefix)
+               ? string.substr(prefix.size(), std::string::npos)
+               : string;
+    }
+    std::string remove_wrap(const std::string& string, const std::string& prefix, const std::string& suffix)
+    {
+        if (simox::alg::starts_with(string, prefix) && simox::alg::ends_with(string, suffix))
+        {
+            return string.substr(prefix.size(), string.size() - prefix.size() - suffix.size());
+        }
+        else
+        {
+            return string;
+        }
+    }
+}
+
 std::string armarx::armem::gui::instance::sanitizeTypeName(const std::string& typeName)
 {
     if (typeName == rawMemoryIDTypeName)
@@ -19,15 +41,25 @@ std::string armarx::armem::gui::instance::sanitizeTypeName(const std::string& ty
 
     namespace s = simox::alg;
     std::string n = typeName;
-    n = s::replace_all(n, "Aron", "");
-    n = s::replace_all(n, "Type", "");
-    n = s::replace_all(n, "type::", "");
-    if (s::starts_with(n, "Object<") && s::ends_with(n, ">"))
+    n = s::replace_all(n, "type::Aron", "");
+    n = s::replace_all(n, "data::Aron", "");
+
+    if (false)
     {
-        std::string begin = "Object<";
-        std::string end = ">";
-        n = n.substr(begin.size(), n.size() - begin.size() - end.size());
+        const std::vector<std::string> containers { "Dict", "List", "Object", "Tuple", "Pair", "NDArray" };
+        for (const std::string& s : containers)
+        {
+            n = s::replace_all(n, s + "Type", s);
+        }
     }
+    else
+    {
+        n = s::replace_all(n, "Type", "");
+    }
+
+
+    n = remove_prefix(n, "Aron");
+    n = remove_wrap(n, "Object<", ">");
 
     if (true)
     {
diff --git a/source/RobotAPI/libraries/armem_gui/instance/tree_builders/DataTreeBuilderBase.cpp b/source/RobotAPI/libraries/armem_gui/instance/tree_builders/DataTreeBuilderBase.cpp
index f837fe2fa..3b624f940 100644
--- a/source/RobotAPI/libraries/armem_gui/instance/tree_builders/DataTreeBuilderBase.cpp
+++ b/source/RobotAPI/libraries/armem_gui/instance/tree_builders/DataTreeBuilderBase.cpp
@@ -5,6 +5,7 @@
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
 
 #include <RobotAPI/libraries/armem_gui/TreeWidgetBuilder.h>
+#include <RobotAPI/libraries/armem_gui/instance/sanitize_typename.h>
 #include <RobotAPI/libraries/armem_gui/instance/display_visitors/DataDisplayVisitor.h>
 
 
@@ -50,7 +51,7 @@ namespace armarx::armem::gui::instance
         QTreeWidgetItem* item, const std::string& key, aron::datanavigator::Navigator& data)
     {
         const std::string value = armarx::aron::DataDisplayVisitor::getValue(data);
-        setRowTexts(item, key, value, data.getName());
+        setRowTexts(item, key, value, sanitizeTypeName(data.getName()));
     }
 
     DataTreeBuilderBase::DictBuilder DataTreeBuilderBase::getDictBuilder() const
diff --git a/source/RobotAPI/libraries/armem_gui/instance/tree_builders/DataTreeBuilderBase.h b/source/RobotAPI/libraries/armem_gui/instance/tree_builders/DataTreeBuilderBase.h
index b225a093d..d8ce4516b 100644
--- a/source/RobotAPI/libraries/armem_gui/instance/tree_builders/DataTreeBuilderBase.h
+++ b/source/RobotAPI/libraries/armem_gui/instance/tree_builders/DataTreeBuilderBase.h
@@ -42,6 +42,7 @@ namespace armarx::armem::gui::instance
         void setRowTexts(QTreeWidgetItem* item, const std::string& key, const std::string& value, const std::string& typeName = "") const;
         void setRowTexts(QTreeWidgetItem* item, const std::string& key, aron::datanavigator::Navigator& data);
 
+
     public:
 
         int columnKey = 0;
diff --git a/source/RobotAPI/libraries/armem_gui/test/ArMemGuiTest.cpp b/source/RobotAPI/libraries/armem_gui/test/ArMemGuiTest.cpp
index 303a319bc..f7bb3e3e9 100644
--- a/source/RobotAPI/libraries/armem_gui/test/ArMemGuiTest.cpp
+++ b/source/RobotAPI/libraries/armem_gui/test/ArMemGuiTest.cpp
@@ -30,27 +30,101 @@
 #include <iostream>
 
 #include <RobotAPI/libraries/armem_gui/instance/sanitize_typename.h>
+#include <RobotAPI/libraries/aron/core/navigator/data/AllNavigators.h>
 #include <RobotAPI/libraries/aron/core/navigator/type/AllNavigators.h>
 
-using namespace armarx::armem::gui::instance;
+namespace dn = armarx::aron::datanavigator;
+namespace tn = armarx::aron::typenavigator;
 
 
-BOOST_AUTO_TEST_CASE(test_sanitizeTypeName)
+namespace ArMemGuiTest
 {
-    using namespace armarx::aron::typenavigator;
+    struct Fixture
     {
-        DictNavigator dict;
-        dict.setAcceptedType(std::make_shared<FloatNavigator>());
-        BOOST_CHECK_EQUAL(sanitizeTypeName(dict.getName()), "Dict<Float>");
+    };
+
+    void test_sanitize(const std::string& in, const std::string& expected)
+    {
+        const std::string out = armarx::armem::gui::instance::sanitizeTypeName(in);
+        BOOST_TEST_CONTEXT("in = '" << in << "'")
+        {
+            BOOST_CHECK_EQUAL(out, expected);
+        }
     }
+}
+
+
+
+BOOST_FIXTURE_TEST_SUITE(ArMemGuiTest, ArMemGuiTest::Fixture)
+
+
+BOOST_AUTO_TEST_CASE(test_sanitizeTypeName_int)
+{
+    test_sanitize(tn::IntNavigator().getName(), "Int");
+    test_sanitize(dn::IntNavigator().getName(), "Int");
+}
+
+BOOST_AUTO_TEST_CASE(test_sanitizeTypeName_float)
+{
+    test_sanitize(tn::FloatNavigator().getName(), "Float");
+    test_sanitize(dn::FloatNavigator().getName(), "Float");
+}
+
+BOOST_AUTO_TEST_CASE(test_sanitizeTypeName_dict)
+{
+    tn::DictNavigator dict;
+    dict.setAcceptedType(std::make_shared<tn::FloatNavigator>());
+    test_sanitize(dict.getName(), "Dict<Float>");
+
+    test_sanitize(dn::DictNavigator().getName(), "Dict");
+}
+
+BOOST_AUTO_TEST_CASE(test_sanitizeTypeName_list)
+{
+    tn::ListNavigator list;
+    list.setAcceptedType(std::make_shared<tn::LongNavigator>());
+    test_sanitize(list.getName(), "List<Long>");
+
+    test_sanitize(dn::ListNavigator().getName(), "List");
+}
+
+BOOST_AUTO_TEST_CASE(test_sanitizeTypeName_object)
+{
+    tn::ObjectNavigator obj;
+    obj.setObjectName("namespace::MyObjectName");
+    test_sanitize(obj.getName(), "MyObjectName    (namespace)");
+}
+
+BOOST_AUTO_TEST_CASE(test_sanitizeTypeName_tuple)
+{
+    tn::TupleNavigator type;
+    type.addAcceptedType(std::make_shared<tn::IntNavigator>());
+    type.addAcceptedType(std::make_shared<tn::FloatNavigator>());
+    test_sanitize(type.getName(), "Tuple<Int, Float>");
+}
+
+BOOST_AUTO_TEST_CASE(test_sanitizeTypeName_pair)
+{
+    tn::PairNavigator type;
+    type.setFirstAcceptedType(std::make_shared<tn::IntNavigator>());
+    type.setSecondAcceptedType(std::make_shared<tn::FloatNavigator>());
+    test_sanitize(type.getName(), "Pair<Int, Float>");
+}
+
+BOOST_AUTO_TEST_CASE(test_sanitizeTypeName_ndarry)
+{
     {
-        ListNavigator list;
-        list.setAcceptedType(std::make_shared<LongNavigator>());
-        BOOST_CHECK_EQUAL(sanitizeTypeName(list.getName()), "List<Long>");
+        tn::NDArrayNavigator type;
+        type.setDimensions({ 3, 2, 1});
+        type.setTypename("float");
+        test_sanitize(type.getName(), "NDArray");
     }
     {
-        ObjectNavigator obj;
-        obj.setObjectName("namespace::MyObjectName");
-        BOOST_CHECK_EQUAL(sanitizeTypeName(obj.getName()), "MyObjectName    (namespace)");
+        dn::NDArrayNavigator data;
+        data.setDimensions({ 3, 2, 1});
+        test_sanitize(data.getName(), "NDArray<3, 2, 1, >");
     }
 }
+
+
+BOOST_AUTO_TEST_SUITE_END()
-- 
GitLab