From c3c893229b3bbe71e1eac3afcd3c69271a56b823 Mon Sep 17 00:00:00 2001
From: Rainer Kartmann <rainer.kartmann@kit.edu>
Date: Wed, 27 May 2020 11:19:35 +0200
Subject: [PATCH] Add class ObjectID, which does parsing of ID strings

---
 .../libraries/ArmarXObjects/CMakeLists.txt    |  6 +-
 .../libraries/ArmarXObjects/ObjectFinder.cpp  | 19 ++----
 .../libraries/ArmarXObjects/ObjectFinder.h    |  1 +
 .../libraries/ArmarXObjects/ObjectID.cpp      | 52 ++++++++++++++
 .../libraries/ArmarXObjects/ObjectID.h        | 68 +++++++++++++++++++
 .../libraries/ArmarXObjects/ObjectInfo.cpp    | 34 ++++++----
 .../libraries/ArmarXObjects/ObjectInfo.h      | 11 ++-
 7 files changed, 161 insertions(+), 30 deletions(-)
 create mode 100644 source/RobotAPI/libraries/ArmarXObjects/ObjectID.cpp
 create mode 100644 source/RobotAPI/libraries/ArmarXObjects/ObjectID.h

diff --git a/source/RobotAPI/libraries/ArmarXObjects/CMakeLists.txt b/source/RobotAPI/libraries/ArmarXObjects/CMakeLists.txt
index c819dd3e7..07ae9ab2f 100644
--- a/source/RobotAPI/libraries/ArmarXObjects/CMakeLists.txt
+++ b/source/RobotAPI/libraries/ArmarXObjects/CMakeLists.txt
@@ -10,14 +10,16 @@ set(LIBS
 set(LIB_FILES
     ArmarXObjects.cpp
 
-    ObjectFinder.cpp
+    ObjectID.cpp
     ObjectInfo.cpp
+    ObjectFinder.cpp
 )
 set(LIB_HEADERS
     ArmarXObjects.h
 
-    ObjectFinder.h
+    ObjectID.h
     ObjectInfo.h
+    ObjectFinder.h
 )
 
 
diff --git a/source/RobotAPI/libraries/ArmarXObjects/ObjectFinder.cpp b/source/RobotAPI/libraries/ArmarXObjects/ObjectFinder.cpp
index b7a74d925..28634f811 100644
--- a/source/RobotAPI/libraries/ArmarXObjects/ObjectFinder.cpp
+++ b/source/RobotAPI/libraries/ArmarXObjects/ObjectFinder.cpp
@@ -4,7 +4,6 @@
 
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
 #include <ArmarXCore/core/system/cmake/CMakePackageFinder.h>
-#include <ArmarXCore/core/util/StringHelpers.h>
 
 
 namespace armarx
@@ -67,18 +66,12 @@ namespace armarx
 
     std::optional<ObjectInfo> ObjectFinder::findObject(const std::string& nameOrID) const
     {
-        init();
-        if (nameOrID.find("/") != nameOrID.npos)
-        {
-            const std::vector<std::string> split = armarx::split(nameOrID, "/", true);
-            ARMARX_CHECK_EQUAL(split.size(), 2) << "Expected ID of format 'Dataset/Name', but got: '" << nameOrID
-                                                << "' (too many '/').";
-            return findObject(split[0], split[1]);
-        }
-        else
-        {
-            return findObject("", nameOrID);
-        }
+        return findObject(ObjectID(nameOrID));
+    }
+
+    std::optional<ObjectInfo> ObjectFinder::findObject(const ObjectID& id) const
+    {
+        return findObject(id.dataset(), id.name());
     }
 
     std::vector<std::string> ObjectFinder::getDatasets() const
diff --git a/source/RobotAPI/libraries/ArmarXObjects/ObjectFinder.h b/source/RobotAPI/libraries/ArmarXObjects/ObjectFinder.h
index e7f3170c1..80907d7b4 100644
--- a/source/RobotAPI/libraries/ArmarXObjects/ObjectFinder.h
+++ b/source/RobotAPI/libraries/ArmarXObjects/ObjectFinder.h
@@ -25,6 +25,7 @@ namespace armarx
 
         std::optional<ObjectInfo> findObject(const std::string& dataset, const std::string& name) const;
         std::optional<ObjectInfo> findObject(const std::string& nameOrID) const;
+        std::optional<ObjectInfo> findObject(const ObjectID& id) const;
 
 
         std::vector<std::string> getDatasets() const;
diff --git a/source/RobotAPI/libraries/ArmarXObjects/ObjectID.cpp b/source/RobotAPI/libraries/ArmarXObjects/ObjectID.cpp
new file mode 100644
index 000000000..f24af1a92
--- /dev/null
+++ b/source/RobotAPI/libraries/ArmarXObjects/ObjectID.cpp
@@ -0,0 +1,52 @@
+#include "ObjectID.h"
+
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+#include <ArmarXCore/core/util/StringHelpers.h>
+
+
+namespace armarx
+{
+    ObjectID::ObjectID()
+    {
+    }
+
+    ObjectID::ObjectID(const std::string& dataset, const std::string& name) :
+        _dataset(dataset), _name(name)
+    {
+    }
+
+    ObjectID::ObjectID(const std::string& nameOrID)
+    {
+        if (nameOrID.find("/") != nameOrID.npos)
+        {
+            const std::vector<std::string> split = armarx::split(nameOrID, "/", true);
+            ARMARX_CHECK_EQUAL(split.size(), 2) << "Expected ID of format 'Dataset/Name', but got: '" << nameOrID
+                                                << "' (too many '/').";
+            _dataset = split[0];
+            _name = split[1];
+        }
+        else
+        {
+            // dataset is left empty.
+            _name = nameOrID;
+        }
+    }
+
+    bool ObjectID::operator==(const ObjectID& rhs) const
+    {
+        return _name == rhs._name && _dataset == rhs._dataset;
+    }
+
+    bool ObjectID::operator<(const ObjectID& rhs) const
+    {
+        return _dataset < rhs._dataset
+               || (_dataset == rhs._dataset && _name < rhs._name);
+    }
+
+}
+
+
+std::ostream& armarx::operator<<(std::ostream& os, const ObjectID& id)
+{
+    return os << "'" << id.str() << "'";
+}
diff --git a/source/RobotAPI/libraries/ArmarXObjects/ObjectID.h b/source/RobotAPI/libraries/ArmarXObjects/ObjectID.h
new file mode 100644
index 000000000..437bbaa88
--- /dev/null
+++ b/source/RobotAPI/libraries/ArmarXObjects/ObjectID.h
@@ -0,0 +1,68 @@
+#pragma once
+
+#include <string>
+
+
+namespace armarx
+{
+    /**
+     * @brief A known object ID of the form "Dataset/Name".
+     */
+    class ObjectID
+    {
+    public:
+
+        ObjectID();
+        ObjectID(const std::string& dataset, const std::string& name);
+        /// Construct from either a name ("myobject") or ID ("mydataset/myobject").
+        ObjectID(const std::string& nameOrID);
+
+
+        std::string dataset() const
+        {
+            return _dataset;
+        }
+        std::string name() const
+        {
+            return _name;
+        }
+        /// Return "dataset/name".
+        std::string str() const
+        {
+            return _dataset + "/" + _name;
+        }
+
+        bool operator==(const ObjectID& rhs) const;
+        inline bool operator!=(const ObjectID& rhs) const
+        {
+            return !operator==(rhs);
+        }
+        bool operator< (const ObjectID& rhs) const;
+        inline bool operator> (const ObjectID& rhs) const
+        {
+            return rhs < (*this);
+        }
+        inline bool operator<=(const ObjectID& rhs) const
+        {
+            return !operator> (rhs);
+        }
+        inline bool operator>=(const ObjectID& rhs) const
+        {
+            return !operator< (rhs);
+        }
+
+
+    private:
+
+        std::string _dataset;
+        std::string _name;
+
+    };
+
+    std::ostream& operator<<(std::ostream& os, const ObjectID& rhs);
+
+
+
+}
+
+
diff --git a/source/RobotAPI/libraries/ArmarXObjects/ObjectInfo.cpp b/source/RobotAPI/libraries/ArmarXObjects/ObjectInfo.cpp
index 421f3b5d0..c4696ece6 100644
--- a/source/RobotAPI/libraries/ArmarXObjects/ObjectInfo.cpp
+++ b/source/RobotAPI/libraries/ArmarXObjects/ObjectInfo.cpp
@@ -12,9 +12,15 @@ namespace armarx
     namespace fs = std::filesystem;
 
 
+    ObjectInfo::ObjectInfo(const std::string& packageName, const ObjectInfo::path& packageDataDir,
+                           const ObjectID& id) :
+        _packageName(packageName), _packageDataDir(packageDataDir), _id(id)
+    {
+    }
+
     ObjectInfo::ObjectInfo(const std::string& packageName, const ObjectInfo::path& packageDataDir,
                            const std::string& dataset, const std::string& name) :
-        _packageName(packageName), _packageDataDir(packageDataDir), _dataset(dataset), _name(name)
+        _packageName(packageName), _packageDataDir(packageDataDir), _id(dataset, name)
     {
     }
 
@@ -25,22 +31,27 @@ namespace armarx
 
     std::string ObjectInfo::dataset() const
     {
-        return _dataset;
+        return _id.dataset();
     }
 
     std::string ObjectInfo::name() const
     {
-        return _name;
+        return _id.name();
+    }
+
+    ObjectID ObjectInfo::id() const
+    {
+        return _id;
     }
 
-    std::string ObjectInfo::id() const
+    std::string ObjectInfo::idStr() const
     {
-        return _dataset + "/" + _name;
+        return _id.str();
     }
 
     ObjectInfo::path ObjectInfo::objectDirectory() const
     {
-        return path(_packageName) / _dataset / _name;
+        return path(_packageName) / _id.dataset() / _id.name();
     }
 
     PackageFileLocation ObjectInfo::file(const std::string& _extension, const std::string& suffix) const
@@ -50,7 +61,7 @@ namespace armarx
         {
             extension = "." + extension;
         }
-        std::string filename = _name + suffix + extension;
+        std::string filename = _id.name() + suffix + extension;
 
         PackageFileLocation loc;
         loc.package = _packageName;
@@ -138,11 +149,10 @@ namespace armarx
 
 }
 
-namespace armarx
+
+std::ostream& armarx::operator<<(std::ostream& os, const ObjectInfo& rhs)
 {
-    std::ostream& operator<<(std::ostream& os, const ObjectInfo& rhs)
-    {
-        return os << "'" << rhs.id() << "'";
-    }
+    return os << rhs.id();
 }
 
+
diff --git a/source/RobotAPI/libraries/ArmarXObjects/ObjectInfo.h b/source/RobotAPI/libraries/ArmarXObjects/ObjectInfo.h
index 0fd1ef032..61cfea4a7 100644
--- a/source/RobotAPI/libraries/ArmarXObjects/ObjectInfo.h
+++ b/source/RobotAPI/libraries/ArmarXObjects/ObjectInfo.h
@@ -3,6 +3,8 @@
 #include <filesystem>
 #include <string>
 
+#include "ObjectID.h"
+
 
 namespace simox
 {
@@ -37,9 +39,12 @@ namespace armarx
 
     public:
 
+        ObjectInfo(const std::string& packageName, const path& packageDataDir,
+                   const ObjectID& id);
         ObjectInfo(const std::string& packageName, const path& packageDataDir,
                    const std::string& dataset, const std::string& name);
 
+
         virtual ~ObjectInfo() = default;
 
 
@@ -48,7 +53,8 @@ namespace armarx
         std::string dataset() const;
         std::string name() const;
         /// Return "dataset/name".
-        std::string id() const;
+        ObjectID id() const;
+        std::string idStr() const;
 
         PackageFileLocation file(const std::string& extension, const std::string& suffix = "") const;
 
@@ -79,8 +85,7 @@ namespace armarx
         std::string _packageName;
         path _packageDataDir;
 
-        std::string _dataset;
-        std::string _name;
+        ObjectID _id;
 
     };
 
-- 
GitLab