From 9cb51b58788b1aa48ecbe2dc1a4042db894e146f Mon Sep 17 00:00:00 2001
From: "fabian.peller-konrad@kit.edu" <fabian.peller-konrad@kit.edu>
Date: Fri, 23 Apr 2021 16:16:15 +0200
Subject: [PATCH] memory export at file system

---
 .../armem/core/diskMemory/CoreSegment.cpp     | 128 +++++++++++
 .../armem/core/diskMemory/CoreSegment.h       |  50 +++++
 .../armem/core/diskMemory/Entity.cpp          | 108 ++++++++++
 .../libraries/armem/core/diskMemory/Entity.h  |  65 ++++++
 .../armem/core/diskMemory/EntityInstance.cpp  | 201 ++++++++++++++++++
 .../armem/core/diskMemory/EntityInstance.h    |  68 ++++++
 .../armem/core/diskMemory/EntitySnapshot.cpp  | 112 ++++++++++
 .../armem/core/diskMemory/EntitySnapshot.h    |  50 +++++
 .../armem/core/diskMemory/Memory.cpp          | 112 ++++++++++
 .../libraries/armem/core/diskMemory/Memory.h  |  45 ++++
 .../armem/core/diskMemory/ProviderSegment.cpp | 135 ++++++++++++
 .../armem/core/diskMemory/ProviderSegment.h   |  50 +++++
 .../diskMemory/detail/TypedEntityContainer.h  | 100 +++++++++
 .../armem/core/longtermMemory/CoreSegment.h   |   4 +-
 .../armem/core/longtermMemory/Entity.h        |   4 +-
 .../core/longtermMemory/EntityInstance.cpp    |   1 -
 .../core/longtermMemory/EntitySnapshot.h      |   4 +-
 .../armem/core/longtermMemory/Memory.h        |   5 +-
 .../core/longtermMemory/ProviderSegment.h     |   4 +-
 .../longtermMemory/detail/EntityContainer.cpp |  10 -
 .../longtermMemory/detail/EntityContainer.h   |  32 ---
 .../longtermMemory/detail/MemoryContainer.cpp |   7 -
 .../longtermMemory/detail/MemoryContainer.h   |  28 ---
 .../detail/TypedEntityContainer.h             |  26 ---
 .../libraries/armem_gui/MemoryViewer.cpp      |  26 ++-
 25 files changed, 1250 insertions(+), 125 deletions(-)
 create mode 100644 source/RobotAPI/libraries/armem/core/diskMemory/CoreSegment.cpp
 create mode 100644 source/RobotAPI/libraries/armem/core/diskMemory/CoreSegment.h
 create mode 100644 source/RobotAPI/libraries/armem/core/diskMemory/Entity.cpp
 create mode 100644 source/RobotAPI/libraries/armem/core/diskMemory/Entity.h
 create mode 100644 source/RobotAPI/libraries/armem/core/diskMemory/EntityInstance.cpp
 create mode 100644 source/RobotAPI/libraries/armem/core/diskMemory/EntityInstance.h
 create mode 100644 source/RobotAPI/libraries/armem/core/diskMemory/EntitySnapshot.cpp
 create mode 100644 source/RobotAPI/libraries/armem/core/diskMemory/EntitySnapshot.h
 create mode 100644 source/RobotAPI/libraries/armem/core/diskMemory/Memory.cpp
 create mode 100644 source/RobotAPI/libraries/armem/core/diskMemory/Memory.h
 create mode 100644 source/RobotAPI/libraries/armem/core/diskMemory/ProviderSegment.cpp
 create mode 100644 source/RobotAPI/libraries/armem/core/diskMemory/ProviderSegment.h
 create mode 100644 source/RobotAPI/libraries/armem/core/diskMemory/detail/TypedEntityContainer.h
 delete mode 100644 source/RobotAPI/libraries/armem/core/longtermMemory/detail/EntityContainer.cpp
 delete mode 100644 source/RobotAPI/libraries/armem/core/longtermMemory/detail/EntityContainer.h
 delete mode 100644 source/RobotAPI/libraries/armem/core/longtermMemory/detail/MemoryContainer.cpp
 delete mode 100644 source/RobotAPI/libraries/armem/core/longtermMemory/detail/MemoryContainer.h
 delete mode 100644 source/RobotAPI/libraries/armem/core/longtermMemory/detail/TypedEntityContainer.h

diff --git a/source/RobotAPI/libraries/armem/core/diskMemory/CoreSegment.cpp b/source/RobotAPI/libraries/armem/core/diskMemory/CoreSegment.cpp
new file mode 100644
index 000000000..e8be60e6c
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/core/diskMemory/CoreSegment.cpp
@@ -0,0 +1,128 @@
+#include "CoreSegment.h"
+
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include "error.h"
+
+
+namespace armarx::armem::diskMemory
+{
+
+    CoreSegment::CoreSegment()
+    {
+    }
+
+    CoreSegment::CoreSegment(const std::string& name, aron::typenavigator::ObjectNavigatorPtr aronType) :
+        armarx::armem::detail::MemoryItem(MemoryID().withCoreSegmentName(name)),
+        armarx::armem::detail::TypedEntityContainerBase<ProviderSegment, Entity, CoreSegment>(MemoryID().withCoreSegmentName(name), aronType)
+    {
+    }
+
+    CoreSegment::CoreSegment(const std::string& name, const MemoryID& parentID, aron::typenavigator::ObjectNavigatorPtr aronType) :
+        armarx::armem::detail::MemoryItem(MemoryID().withCoreSegmentName(name)),
+        armarx::armem::detail::TypedEntityContainerBase<ProviderSegment, Entity, CoreSegment>(parentID.withCoreSegmentName(name), aronType)
+    {
+    }
+
+    CoreSegment::CoreSegment(const MemoryID& id, aron::typenavigator::ObjectNavigatorPtr aronType) :
+        armarx::armem::detail::MemoryItem(id),
+        armarx::armem::detail::TypedEntityContainerBase<ProviderSegment, Entity, CoreSegment>(id, aronType)
+    {
+    }
+
+    CoreSegment::CoreSegment(const CoreSegment& other) :
+        armarx::armem::detail::MemoryItem(other),
+        MemoryContainerBase<std::map<std::string, ProviderSegment>, CoreSegment>(other),
+        armarx::armem::detail::TypedEntityContainerBase<ProviderSegment, Entity, CoreSegment>(other)
+    {
+    }
+
+    CoreSegment& CoreSegment::operator=(const CoreSegment& other)
+    {
+        other._copySelf(*this);
+        return *this;
+    }
+
+    std::filesystem::path CoreSegment::_fullPath() const
+    {
+        if(path)
+        {
+            return _fullPath(*path);
+        }
+        return std::filesystem::path();
+    }
+
+    std::filesystem::path CoreSegment::_fullPath(const std::filesystem::path& path) const
+    {
+        return path / id.memoryName / id.coreSegmentName;
+    }
+
+    workingmemory::CoreSegment CoreSegment::convert() const
+    {
+        workingmemory::CoreSegment m;
+        for (const auto& [_, s] : container)
+        {
+            m.addProviderSegment(s.convert(aronType));
+        }
+        return m;
+    }
+
+    void CoreSegment::reload(const std::shared_ptr<std::filesystem::path>& p_ptr)
+    {
+        if(!p_ptr)
+        {
+            ARMARX_WARNING << "The entered is NULL.";
+        }
+        std::filesystem::path p = _fullPath(*p_ptr);
+        if(std::filesystem::is_regular_file(p))
+        {
+            ARMARX_ERROR << "The entered path is leading to a file! Abort due to error.";
+        }
+
+        container.clear();
+        path = p_ptr;
+
+        if(!std::filesystem::exists(p))
+        {
+            ARMARX_INFO << "The entered path does not exist. Assuming an empty container.";
+        }
+        else
+        {
+            for (const auto& d : std::filesystem::directory_iterator(p))
+            {
+                if(d.is_directory())
+                {
+                    std::string k = d.path().filename();
+                    auto wms = container.emplace(std::make_pair(k, id.withProviderSegmentName(k)));
+                    wms.first->second.reload(p_ptr);
+                }
+
+                if(d.is_regular_file())
+                {
+                    readAronType(d.path());
+                }
+            }
+        }
+    }
+
+    void CoreSegment::append(const workingmemory::CoreSegment& m)
+    {
+        std::filesystem::create_directories(_fullPath());
+        writeAronType(_fullPath());
+
+        for (const auto& [k, s] : m.container)
+        {
+            if (const auto& it = container.find(k); it != container.end())
+            {
+                it->second.append(s);
+            }
+            else
+            {
+                std::filesystem::create_directory(_fullPath() / k);
+                auto wms = container.emplace(std::make_pair(k, id.withProviderSegmentName(k)));
+                wms.first->second.path = path;
+                wms.first->second.append(s);
+            }
+        }
+    }
+}
diff --git a/source/RobotAPI/libraries/armem/core/diskMemory/CoreSegment.h b/source/RobotAPI/libraries/armem/core/diskMemory/CoreSegment.h
new file mode 100644
index 000000000..d5a8314d2
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/core/diskMemory/CoreSegment.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include <filesystem>
+
+#include "../base/CoreSegment.h"
+#include "detail/TypedEntityContainer.h"
+
+#include "ProviderSegment.h"
+
+#include "../workingMemory/CoreSegment.h"
+
+
+namespace armarx::armem::diskMemory
+{
+
+    /**
+     * @brief Data of a core segment containing multiple provider segments.
+     */
+    class CoreSegment :
+            virtual public CoreSegmentBase<ProviderSegment, CoreSegment>,
+            virtual public detail::TypedEntityContainer<ProviderSegment, CoreSegment>
+    {
+    public:
+        using Base = CoreSegmentBase<ProviderSegment, CoreSegment>;
+        using ProviderSegmentT = ProviderSegment;
+
+        CoreSegment();
+        CoreSegment(const std::string& name, aron::typenavigator::ObjectNavigatorPtr aronType = nullptr);
+        CoreSegment(const std::string& name, const MemoryID& parentID, aron::typenavigator::ObjectNavigatorPtr aronType = nullptr);
+        CoreSegment(const MemoryID& id, aron::typenavigator::ObjectNavigatorPtr aronType = nullptr);
+
+        CoreSegment(const CoreSegment& other);
+        CoreSegment& operator=(const CoreSegment& other);
+
+        // Conversion
+        workingmemory::CoreSegment convert() const;
+
+        // Filesystem connection
+        void reload(const std::shared_ptr<std::filesystem::path>&);
+        void append(const workingmemory::CoreSegment&);
+
+    private:
+        std::filesystem::path _fullPath() const;
+        std::filesystem::path _fullPath(const std::filesystem::path&) const;
+
+    public:
+        std::shared_ptr<std::filesystem::path> path;
+    };
+
+}
diff --git a/source/RobotAPI/libraries/armem/core/diskMemory/Entity.cpp b/source/RobotAPI/libraries/armem/core/diskMemory/Entity.cpp
new file mode 100644
index 000000000..c2c8982a8
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/core/diskMemory/Entity.cpp
@@ -0,0 +1,108 @@
+#include "Entity.h"
+
+namespace armarx::armem::diskMemory
+{
+
+    Entity::Entity()
+    {
+    }
+
+    Entity::Entity(const std::string& name, const MemoryID& parentID) :
+        armarx::armem::detail::MemoryItem(parentID.withEntityName(name))
+    {
+    }
+
+    Entity::Entity(const MemoryID& id) :
+        armarx::armem::detail::MemoryItem(id)
+    {
+    }
+
+    Entity::Entity(const Entity& other) :
+        armarx::armem::detail::MemoryItem(other),
+        armarx::armem::detail::MemoryContainerBase<std::map<Time, EntitySnapshot>, Entity>(other)
+    {
+    }
+
+    Entity& Entity::operator=(const Entity& other)
+    {
+        other._copySelf(*this);
+        return *this;
+    }
+
+    std::filesystem::path Entity::_fullPath() const
+    {
+        if(path)
+        {
+            return _fullPath(*path);
+        }
+        return std::filesystem::path();
+    }
+
+    std::filesystem::path Entity::_fullPath(const std::filesystem::path& path) const
+    {
+        return path / id.memoryName / id.coreSegmentName / id.providerSegmentName / id.entityName;
+    }
+
+    workingmemory::Entity Entity::convert(const aron::typenavigator::NavigatorPtr& expectedStructure) const
+    {
+        workingmemory::Entity m;
+        for (const auto& [_, s] : container)
+        {
+            m.addSnapshot(s.convert(expectedStructure));
+        }
+        return m;
+    }
+
+    void Entity::reload(const std::shared_ptr<std::filesystem::path>& p_ptr)
+    {
+        if(!p_ptr)
+        {
+            ARMARX_WARNING << "The entered is NULL.";
+        }
+        std::filesystem::path p = _fullPath(*p_ptr);
+        if(std::filesystem::is_regular_file(p))
+        {
+            ARMARX_ERROR << "The entered path is leading to a file! Abort due to error.";
+        }
+
+        container.clear();
+        path = p_ptr;
+
+        if(!std::filesystem::exists(p))
+        {
+            ARMARX_INFO << "The entered path does not exist. Assuming an empty container.";
+        }
+        else
+        {
+            for (const auto& d : std::filesystem::directory_iterator(p))
+            {
+                if(d.is_directory())
+                {
+                    std::string k = d.path().filename();
+                    armem::Time t = armem::Time::microSeconds(std::stol(k));
+                    auto wms = container.emplace(std::make_pair(t, id.withTimestamp(t)));
+                    wms.first->second.reload(p_ptr);
+                }
+            }
+        }
+    }
+
+    void Entity::append(const workingmemory::Entity& m)
+    {
+        std::filesystem::create_directories(_fullPath());
+        for (const auto& [k, s] : m.container)
+        {
+            if (const auto& it = container.find(k); it != container.end())
+            {
+                it->second.setTo(s);
+            }
+            else
+            {
+                std::filesystem::create_directory(_fullPath() / std::to_string(k.toMicroSeconds()));
+                auto wms = container.emplace(std::make_pair(k, id.withTimestamp(k)));
+                wms.first->second.path = path;
+                wms.first->second.setTo(s);
+            }
+        }
+    }
+}
diff --git a/source/RobotAPI/libraries/armem/core/diskMemory/Entity.h b/source/RobotAPI/libraries/armem/core/diskMemory/Entity.h
new file mode 100644
index 000000000..391eefb05
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/core/diskMemory/Entity.h
@@ -0,0 +1,65 @@
+#pragma once
+
+#include <filesystem>
+
+#include "../base/Entity.h"
+
+#include "EntitySnapshot.h"
+
+#include "../workingMemory/Entity.h"
+
+
+namespace armarx::armem::diskMemory
+{
+    /**
+     * @brief An entity over a period of time.
+     *
+     * An entity should be a physical thing or abstract concept existing
+     * (and potentially evolving) over some time.
+     *
+     * Examples are:
+     * - objects (the green box)
+     * - agents (robot, human)
+     * - locations (frige, sink)
+     * - grasp affordances (general, or for a specific object)
+     * - images
+     * - point clouds
+     * - other sensory values
+     *
+     * At each point in time (`EntitySnapshot`), the entity can have a
+     * (potentially variable) number of instances (`EntityInstance`),
+     * each containing a single `AronData` object of a specific `AronType`.
+     */
+    class Entity :
+        virtual public EntityBase<EntitySnapshot, Entity>
+    {
+
+    public:
+        using Base = EntityBase<EntitySnapshot, Entity>;
+        using EntitySnapshotT = EntitySnapshot;
+
+        Entity();
+        Entity(const std::string& name, const MemoryID& parentID = {});
+        Entity(const MemoryID& id);
+
+        /// Copy the history from `other` to this.
+        Entity(const Entity& other);
+        /// Copy the history from `other` to this.
+        Entity& operator=(const Entity& other);
+
+        // Conversion
+        workingmemory::Entity convert(const aron::typenavigator::NavigatorPtr& expectedStructure) const;
+
+        // Filesystem connection
+        void reload(const std::shared_ptr<std::filesystem::path>&);
+        void append(const workingmemory::Entity&);
+
+    private:
+        std::filesystem::path _fullPath() const;
+        std::filesystem::path _fullPath(const std::filesystem::path&) const;
+
+    public:
+        std::shared_ptr<std::filesystem::path> path;
+    };
+
+}
diff --git a/source/RobotAPI/libraries/armem/core/diskMemory/EntityInstance.cpp b/source/RobotAPI/libraries/armem/core/diskMemory/EntityInstance.cpp
new file mode 100644
index 000000000..dc131b44b
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/core/diskMemory/EntityInstance.cpp
@@ -0,0 +1,201 @@
+#include "EntityInstance.h"
+
+#include <iostream>
+#include <fstream>
+
+#include "../../core/error.h"
+
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+#include <RobotAPI/libraries/aron/core/io/dataIO/converter/Converter.h>
+#include <RobotAPI/libraries/aron/core/io/dataIO/visitor/Visitor.h>
+#include <RobotAPI/libraries/aron/core/io/dataIO/reader/nlohmannJSON/NlohmannJSONReader.h>
+#include <RobotAPI/libraries/aron/core/io/dataIO/writer/nlohmannJSON/NlohmannJSONWriter.h>
+
+namespace armarx::armem::diskMemory
+{
+    EntityInstance::EntityInstance()
+    {
+    }
+
+    EntityInstance::EntityInstance(const EntityInstance& other) :
+        MemoryItem(other.id)
+    {
+    }
+
+    EntityInstance::EntityInstance(int index, const MemoryID& parentID) :
+        EntityInstance(parentID.withInstanceIndex(index))
+    {
+    }
+
+    EntityInstance::EntityInstance(const MemoryID& id) :
+        MemoryItem(id)
+    {
+    }
+
+    EntityInstance& EntityInstance::operator=(const EntityInstance& other)
+    {
+        other._copySelf(*this);
+        return *this;
+    }
+
+    bool EntityInstance::equalsDeep(const EntityInstance& other) const
+    {
+        return id == other.id;
+    }
+
+    void EntityInstance::update(const EntityUpdate& update, int index)
+    {
+        ARMARX_CHECK_FITS_SIZE(index, update.instancesData.size());
+
+        this->index() = index;
+    }
+
+    EntityInstance EntityInstance::copy() const
+    {
+        EntityInstance d;
+        this->_copySelf(d);
+        return d;
+    }
+
+    void EntityInstance::_copySelf(EntityInstance& other) const
+    {
+        EntityInstanceBase<EntityInstance>::_copySelf(other);
+    }
+
+    std::filesystem::path EntityInstance::_fullPath() const
+    {
+        if(path)
+        {
+            return _fullPath(*path);
+        }
+        return std::filesystem::path();
+    }
+
+    std::filesystem::path EntityInstance::_fullPath(const std::filesystem::path& path) const
+    {
+        return path / id.memoryName / id.coreSegmentName / id.providerSegmentName / id.entityName / std::to_string(id.timestamp.toMicroSeconds()) / std::to_string(id.instanceIndex);
+    }
+
+    workingmemory::EntityInstance EntityInstance::convert(const aron::typenavigator::NavigatorPtr& expectedStructure) const
+    {
+        std::filesystem::path p = _fullPath();
+        std::filesystem::path d = p / (std::string(DATA_FILENAME) + ".json");
+
+        if(std::filesystem::is_regular_file(d))
+        {
+            std::ifstream ifs(d);
+            std::string file_content((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
+            aron::dataIO::reader::NlohmannJSONReader dataReader(file_content);
+            aron::dataIO::writer::NavigatorWriter navWriter;
+
+            aron::dataIO::Converter::ReadAndConvert(dataReader, navWriter, expectedStructure);
+
+            aron::datanavigator::DictNavigatorPtr aron = aron::datanavigator::DictNavigator::DynamicCastAndCheck(navWriter.getResult());
+            return unwrapData(aron);
+        }
+        else
+        {
+            throw error::ArMemError("An diskMemory EntityInstance is not leading to a regular file.");
+        }
+    }
+
+    void EntityInstance::reload(const std::shared_ptr<std::filesystem::path>& p_ptr)
+    {
+        if(!p_ptr)
+        {
+            ARMARX_WARNING << "The entered is NULL.";
+        }
+        std::filesystem::path p = _fullPath(*p_ptr);
+        if(!std::filesystem::is_directory(p))
+        {
+            ARMARX_ERROR << "The entered path is not leading to a file! This is an error since if the folder for an EntityInstance exists there must be a data file in it (containing at least the metadata).";
+        }
+        else
+        {
+            path = p_ptr;
+        }
+    }
+
+    void EntityInstance::setTo(const workingmemory::EntityInstance& m)
+    {
+        std::filesystem::path p = _fullPath();
+        std::filesystem::create_directories(p);
+
+        std::filesystem::path d = p / (std::string(DATA_FILENAME) + ".json");
+
+        if(std::filesystem::is_regular_file(d))
+        {
+            std::filesystem::remove(d);
+        }
+
+        std::ofstream ofs;
+        ofs.open(d);
+
+        aron::datanavigator::DictNavigatorPtr aron = wrapData(m);
+        aron::dataIO::writer::NlohmannJSONWriter dataWriter;
+        aron::dataIO::Visitor::VisitAndSetup(dataWriter, aron);
+        std::string new_file_full_content = dataWriter.getResult().dump(2);
+
+        ofs << new_file_full_content;
+        ofs.close();
+    }
+
+
+    workingmemory::EntityInstance EntityInstance::unwrapData(const aron::datanavigator::DictNavigatorPtr& dataWrapped) const
+    {
+        workingmemory::EntityInstance e(id);
+        workingmemory::EntityInstanceMetadata& metadata = e.metadata();
+
+        if (dataWrapped->hasElement(DATA_WRAPPER_DATA_FIELD))
+        {
+            aron::datanavigator::DictNavigatorPtr data = aron::datanavigator::DictNavigator::DynamicCastAndCheck(dataWrapped->getElement(DATA_WRAPPER_DATA_FIELD));
+            e.setData(data);
+        }
+
+        auto timeCreated = aron::datanavigator::LongNavigator::DynamicCastAndCheck(dataWrapped->getElement(DATA_WRAPPER_TIME_CREATED_FIELD));
+        metadata.timeCreated = Time::microSeconds(timeCreated->toAronLongPtr()->value);
+
+        auto timeSent = aron::datanavigator::LongNavigator::DynamicCastAndCheck(dataWrapped->getElement(DATA_WRAPPER_TIME_SENT_FIELD));
+        metadata.timeSent = Time::microSeconds(timeSent->toAronLongPtr()->value);
+
+        auto timeArrived = aron::datanavigator::LongNavigator::DynamicCastAndCheck(dataWrapped->getElement(DATA_WRAPPER_TIME_ARRIVED_FIELD));
+        metadata.timeArrived = Time::microSeconds(timeArrived->toAronLongPtr()->value);
+
+        auto confidence = aron::datanavigator::DoubleNavigator::DynamicCastAndCheck(dataWrapped->getElement(DATA_WRAPPER_CONFIDENCE_FIELD));
+        metadata.confidence = static_cast<float>(confidence->toAronDoublePtr()->value);
+
+        return e;
+    }
+
+    aron::datanavigator::DictNavigatorPtr EntityInstance::wrapData(const workingmemory::EntityInstance& e) const
+    {
+        auto dataWrapped = std::make_shared<aron::datanavigator::DictNavigator>();
+        if(e.data())
+        {
+            dataWrapped->addElement(DATA_WRAPPER_DATA_FIELD, e.data());
+        }
+
+        auto timeWrapped = std::make_shared<aron::datanavigator::LongNavigator>();
+        timeWrapped->setValue(Time::now().toMicroSeconds());
+        dataWrapped->addElement(DATA_WRAPPER_TIME_STORED_FIELD, timeWrapped);
+
+        const workingmemory::EntityInstanceMetadata& metadata = e.metadata();
+        auto timeCreated = std::make_shared<aron::datanavigator::LongNavigator>();
+        timeCreated->setValue(metadata.timeCreated.toMicroSeconds());
+        dataWrapped->addElement(DATA_WRAPPER_TIME_CREATED_FIELD, timeCreated);
+
+        auto timeSent = std::make_shared<aron::datanavigator::LongNavigator>();
+        timeSent->setValue(metadata.timeSent.toMicroSeconds());
+        dataWrapped->addElement(DATA_WRAPPER_TIME_SENT_FIELD, timeSent);
+
+        auto timeArrived = std::make_shared<aron::datanavigator::LongNavigator>();
+        timeArrived->setValue(metadata.timeArrived.toMicroSeconds());
+        dataWrapped->addElement(DATA_WRAPPER_TIME_ARRIVED_FIELD, timeArrived);
+
+        auto confidence = std::make_shared<aron::datanavigator::DoubleNavigator>();
+        confidence->setValue(metadata.confidence);
+        dataWrapped->addElement(DATA_WRAPPER_CONFIDENCE_FIELD, confidence);
+
+        return dataWrapped;
+    }
+}
diff --git a/source/RobotAPI/libraries/armem/core/diskMemory/EntityInstance.h b/source/RobotAPI/libraries/armem/core/diskMemory/EntityInstance.h
new file mode 100644
index 000000000..6eb97bd13
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/core/diskMemory/EntityInstance.h
@@ -0,0 +1,68 @@
+#pragma once
+
+#include <filesystem>
+
+#include "../base/EntityInstance.h"
+
+#include "../workingMemory/EntityInstance.h"
+
+namespace armarx::armem::diskMemory
+{
+    /**
+     * @brief Data of a single entity instance.
+     */
+    class EntityInstance :
+        virtual public EntityInstanceBase<EntityInstance>
+    {
+
+    public:
+        using Base = EntityInstanceBase<EntityInstance>;
+
+        EntityInstance();
+        EntityInstance(const EntityInstance&);
+        EntityInstance(int index, const MemoryID& parentID = {});
+        EntityInstance(const MemoryID& id);
+
+        EntityInstance& operator=(const EntityInstance& other);
+
+        /**
+         * @brief Fill `*this` with the update's values.
+         * @param update The update.
+         * @param index The instances index.
+         */
+        virtual void update(const EntityUpdate& update, int index) override;
+
+        virtual bool equalsDeep(const EntityInstance& other) const override;
+
+        virtual EntityInstance copy() const override;
+
+        // Conversion
+        workingmemory::EntityInstance convert(const aron::typenavigator::NavigatorPtr& expectedStructure) const;
+
+        // Filesystem connection
+        void reload(const std::shared_ptr<std::filesystem::path>&);
+        void setTo(const workingmemory::EntityInstance&);
+
+    protected:
+        virtual void _copySelf(EntityInstance& other) const override;
+
+    private:
+        std::filesystem::path _fullPath() const;
+        std::filesystem::path _fullPath(const std::filesystem::path&) const;
+
+        workingmemory::EntityInstance unwrapData(const aron::datanavigator::DictNavigatorPtr&) const;
+        aron::datanavigator::DictNavigatorPtr wrapData(const workingmemory::EntityInstance&) const;
+
+    public:
+        std::shared_ptr<std::filesystem::path> path;
+
+    private:
+        static const constexpr char* DATA_FILENAME = "data";
+        static constexpr const char* DATA_WRAPPER_DATA_FIELD            = "__ARON_DATA";
+        static constexpr const char* DATA_WRAPPER_TIME_STORED_FIELD     = "__WRITER_METADATA__TIME_STORED";
+        static constexpr const char* DATA_WRAPPER_TIME_CREATED_FIELD    = "__ENTITY_METADATA__TIME_CREATED";
+        static constexpr const char* DATA_WRAPPER_TIME_SENT_FIELD       = "__ENTITY_METADATA__TIME_SENT";
+        static constexpr const char* DATA_WRAPPER_TIME_ARRIVED_FIELD    = "__ENTITY_METADATA__TIME_ARRIVED";
+        static constexpr const char* DATA_WRAPPER_CONFIDENCE_FIELD      = "__ENTITY_METADATA__CONFIDENCE";
+    };
+}
diff --git a/source/RobotAPI/libraries/armem/core/diskMemory/EntitySnapshot.cpp b/source/RobotAPI/libraries/armem/core/diskMemory/EntitySnapshot.cpp
new file mode 100644
index 000000000..05e4bd68c
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/core/diskMemory/EntitySnapshot.cpp
@@ -0,0 +1,112 @@
+#include "EntitySnapshot.h"
+
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include "error.h"
+
+
+namespace armarx::armem::diskMemory
+{
+
+
+    EntitySnapshot::EntitySnapshot()
+    {
+    }
+
+    EntitySnapshot::EntitySnapshot(Time time, const MemoryID& parentID) :
+        EntitySnapshot(parentID.withTimestamp(time))
+    {
+    }
+
+    EntitySnapshot::EntitySnapshot(const MemoryID& id) :
+        MemoryItem(id)
+    {
+    }
+
+    EntitySnapshot::EntitySnapshot(const EntitySnapshot& other) :
+        armarx::armem::detail::MemoryItem(other),
+        armarx::armem::detail::MemoryContainerBase<std::vector<EntityInstance>, EntitySnapshot>(other)
+    {
+    }
+
+    EntitySnapshot& EntitySnapshot::operator=(const EntitySnapshot& other)
+    {
+        other._copySelf(*this);
+        return *this;
+    }
+
+    std::filesystem::path EntitySnapshot::_fullPath() const
+    {
+        if(path)
+        {
+            return _fullPath(*path);
+        }
+        return std::filesystem::path();
+    }
+
+    std::filesystem::path EntitySnapshot::_fullPath(const std::filesystem::path& path) const
+    {
+        return path / id.memoryName / id.coreSegmentName / id.providerSegmentName / id.entityName / std::to_string(id.timestamp.toMicroSeconds());
+    }
+
+    workingmemory::EntitySnapshot EntitySnapshot::convert(const aron::typenavigator::NavigatorPtr& expectedStructure) const
+    {
+        workingmemory::EntitySnapshot m;
+        for (const auto& s : container)
+        {
+            m.addInstance(s.convert(expectedStructure));
+        }
+        return m;
+    }
+
+    void EntitySnapshot::reload(const std::shared_ptr<std::filesystem::path>& p_ptr)
+    {
+        if(!p_ptr)
+        {
+            ARMARX_WARNING << "The entered is NULL.";
+        }
+        std::filesystem::path p = _fullPath(*p_ptr);
+        if(!std::filesystem::is_directory(p))
+        {
+            ARMARX_ERROR << "The entered path is not leading to a directory! Every EntitySnapshot must at least contain one EntityInstance.";
+        }
+        else
+        {
+            container.clear();
+            path = p_ptr;
+
+            // todo
+            for (int i = 0; i < 1000; ++i)
+            {
+                std::filesystem::path d = p / std::to_string(i);
+                if(std::filesystem::is_directory(d))
+                {
+                    auto wms = container.emplace_back(id.withInstanceIndex(i));
+                    wms.reload(p_ptr);
+                }
+                else
+                {
+                    break;
+                }
+            }
+        }
+    }
+
+    void EntitySnapshot::setTo(const workingmemory::EntitySnapshot& m)
+    {
+        std::filesystem::create_directories(_fullPath());
+
+        // We remove the contente here and reset it with new values
+        container.clear();
+
+        unsigned int i = 0;
+        for (const auto& s : m.container)
+        {
+            std::filesystem::create_directory(_fullPath() / std::to_string(i));
+
+            auto wms = container.emplace_back(id.withInstanceIndex(i++));
+            wms.path = path;
+            wms.setTo(s);
+        }
+    }
+}
diff --git a/source/RobotAPI/libraries/armem/core/diskMemory/EntitySnapshot.h b/source/RobotAPI/libraries/armem/core/diskMemory/EntitySnapshot.h
new file mode 100644
index 000000000..d286ce8f5
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/core/diskMemory/EntitySnapshot.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include <filesystem>
+
+#include "../base/EntitySnapshot.h"
+
+#include "EntityInstance.h"
+
+#include "../workingMemory/EntitySnapshot.h"
+
+
+namespace armarx::armem::diskMemory
+{
+
+    /**
+     * @brief Data of an entity at one point in time.
+     */
+    class EntitySnapshot :
+        virtual public EntitySnapshotBase<EntityInstance, EntitySnapshot>
+    {
+
+    public:
+        using Base = EntitySnapshotBase<EntityInstance, EntitySnapshot>;
+        using EntityInstanceT = EntityInstance;
+
+        EntitySnapshot();
+        EntitySnapshot(Time time, const MemoryID& parentID = {});
+        EntitySnapshot(const MemoryID& id);
+
+        /// Copy the instances from `other` to this.
+        EntitySnapshot(const EntitySnapshot& other);
+
+        /// Copy the instances from `other` to this.
+        EntitySnapshot& operator=(const EntitySnapshot& other);
+
+        // Conversion
+        void reload(const std::shared_ptr<std::filesystem::path>&);
+        workingmemory::EntitySnapshot convert(const aron::typenavigator::NavigatorPtr& expectedStructure) const;
+
+        // MongoDB connection
+        void setTo(const workingmemory::EntitySnapshot&);
+
+    private:
+        std::filesystem::path _fullPath() const;
+        std::filesystem::path _fullPath(const std::filesystem::path&) const;
+
+    public:
+        std::shared_ptr<std::filesystem::path> path;
+    };
+}
diff --git a/source/RobotAPI/libraries/armem/core/diskMemory/Memory.cpp b/source/RobotAPI/libraries/armem/core/diskMemory/Memory.cpp
new file mode 100644
index 000000000..0b99f1460
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/core/diskMemory/Memory.cpp
@@ -0,0 +1,112 @@
+#include "Memory.h"
+
+#include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include "error.h"
+
+
+namespace armarx::armem::diskMemory
+{
+
+    Memory::Memory()
+    {
+    }
+
+    Memory::Memory(const std::string& name) :
+        armarx::armem::detail::MemoryItem(MemoryID().withMemoryName(name))
+    {
+    }
+
+    Memory::Memory(const MemoryID& id) :
+        MemoryItem(id)
+    {
+    }
+
+    Memory::Memory(const Memory& other) :
+        armarx::armem::detail::MemoryItem(other),
+        MemoryContainerBase<std::map<std::string, CoreSegment>, Memory>(other)
+    {
+        *this = other;
+    }
+
+    Memory& Memory::operator=(const Memory& other)
+    {
+        other._copySelf(*this);
+        return *this;
+    }
+
+    std::filesystem::path Memory::_fullPath() const
+    {
+        if(path)
+        {
+            return _fullPath(*path);
+        }
+        return std::filesystem::path();
+    }
+
+    std::filesystem::path Memory::_fullPath(const std::filesystem::path& path) const
+    {
+        return path / id.memoryName;
+    }
+
+    workingmemory::Memory Memory::convert() const
+    {
+        workingmemory::Memory m;
+        for (const auto& [_, s] : container)
+        {
+            m.addCoreSegment(s.convert());
+        }
+        return m;
+    }
+
+    void Memory::reload(const std::filesystem::path& p)
+    {
+        if(std::filesystem::is_regular_file(p))
+        {
+            ARMARX_ERROR << "The entered path is leading to a file! Abort due to error.";
+        }
+
+        container.clear();
+        path = std::make_shared<std::filesystem::path>(p.parent_path());
+
+        if(!std::filesystem::exists(p))
+        {
+            ARMARX_INFO << "The entered path does not exist. Assuming an empty container.";
+        }
+        else
+        {
+            id = MemoryID().withMemoryName(p.filename());
+
+            for (const auto& d : std::filesystem::directory_iterator(p))
+            {
+                if(d.is_directory())
+                {
+                    std::string k = d.path().filename();
+                    auto wms = container.emplace(std::make_pair(k, id.withCoreSegmentName(k)));
+                    wms.first->second.reload(path);
+                }
+            }
+        }
+    }
+
+    void Memory::append(const workingmemory::Memory& m)
+    {
+        std::filesystem::create_directories(_fullPath());
+        for (const auto& [k, s] : m.container)
+        {
+            if (const auto& it = container.find(k); it != container.end())
+            {
+                it->second.append(s);
+            }
+            else
+            {
+                std::filesystem::create_directory(_fullPath() / k);
+
+                auto wms = container.emplace(std::make_pair(k, id.withCoreSegmentName(k)));
+                wms.first->second.path = path;
+                wms.first->second.append(s);
+            }
+        }
+    }
+}
diff --git a/source/RobotAPI/libraries/armem/core/diskMemory/Memory.h b/source/RobotAPI/libraries/armem/core/diskMemory/Memory.h
new file mode 100644
index 000000000..a32b1dcc1
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/core/diskMemory/Memory.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <filesystem>
+
+#include "../base/Memory.h"
+
+#include "CoreSegment.h"
+
+#include "../workingMemory/Memory.h"
+
+namespace armarx::armem::diskMemory
+{
+
+    /**
+     * @brief Data of a memory consisting of multiple core segments.
+     */
+    class Memory :
+        virtual public MemoryBase<CoreSegment, Memory>
+    {
+    public:
+        using Base = MemoryBase<CoreSegment, Memory>;
+        using CoreSegmentT = CoreSegment;
+
+        Memory();
+        Memory(const std::string& name);
+        Memory(const MemoryID& id);
+
+        Memory(const Memory& other);
+        Memory& operator=(const Memory& other);
+
+        // Conversion
+        workingmemory::Memory convert() const;
+
+        // Filesystem connection
+        void reload(const std::filesystem::path&);
+        void append(const workingmemory::Memory&);
+
+    private:
+        std::filesystem::path _fullPath() const;
+        std::filesystem::path _fullPath(const std::filesystem::path&) const;
+
+    public:
+        std::shared_ptr<std::filesystem::path> path;
+    };
+}
diff --git a/source/RobotAPI/libraries/armem/core/diskMemory/ProviderSegment.cpp b/source/RobotAPI/libraries/armem/core/diskMemory/ProviderSegment.cpp
new file mode 100644
index 000000000..0afa005a8
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/core/diskMemory/ProviderSegment.cpp
@@ -0,0 +1,135 @@
+#include "ProviderSegment.h"
+
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include "error.h"
+
+
+namespace armarx::armem::diskMemory
+{
+
+    ProviderSegment::ProviderSegment()
+    {
+    }
+
+    ProviderSegment::ProviderSegment(const std::string& name, aron::typenavigator::ObjectNavigatorPtr aronType) :
+        armarx::armem::detail::MemoryItem(MemoryID().withProviderSegmentName(name)),
+        armarx::armem::detail::TypedEntityContainerBase<Entity, Entity, ProviderSegment>(MemoryID().withProviderSegmentName(name), aronType)
+    {
+    }
+
+    ProviderSegment::ProviderSegment(const std::string& name, const MemoryID parentID, aron::typenavigator::ObjectNavigatorPtr aronType) :
+        armarx::armem::detail::MemoryItem(parentID.withProviderSegmentName(name)),
+        armarx::armem::detail::TypedEntityContainerBase<Entity, Entity, ProviderSegment>(parentID.withProviderSegmentName(name), aronType)
+    {
+    }
+
+    ProviderSegment::ProviderSegment(const MemoryID id, aron::typenavigator::ObjectNavigatorPtr aronType) :
+        armarx::armem::detail::MemoryItem(id),
+        armarx::armem::detail::TypedEntityContainerBase<Entity, Entity, ProviderSegment>(id, aronType)
+    {
+    }
+
+    ProviderSegment::ProviderSegment(const ProviderSegment& other) :
+        armarx::armem::detail::MemoryItem(other),
+        MemoryContainerBase<std::map<std::string, Entity>, ProviderSegment>(other),
+        armarx::armem::detail::TypedEntityContainerBase<Entity, Entity, ProviderSegment>(other)
+    {
+    }
+
+    ProviderSegment& ProviderSegment::operator=(const ProviderSegment& other)
+    {
+        other._copySelf(*this);
+        return *this;
+    }
+
+    std::filesystem::path ProviderSegment::_fullPath() const
+    {
+        if(path)
+        {
+            return _fullPath(*path);
+        }
+        return std::filesystem::path();
+    }
+
+    std::filesystem::path ProviderSegment::_fullPath(const std::filesystem::path& path) const
+    {
+        return path / id.memoryName / id.coreSegmentName / id.providerSegmentName;
+    }
+
+    workingmemory::ProviderSegment ProviderSegment::convert(const aron::typenavigator::NavigatorPtr& expectedStructure) const
+    {
+        workingmemory::ProviderSegment m;
+        for (const auto& [_, s] : container)
+        {
+            if(hasAronType())
+            {
+                m.addEntity(s.convert(aronType));
+            }
+            else
+            {
+                m.addEntity(s.convert(expectedStructure));
+            }
+        }
+        return m;
+    }
+
+    void ProviderSegment::reload(const std::shared_ptr<std::filesystem::path>& p_ptr)
+    {
+        if(!p_ptr)
+        {
+            ARMARX_WARNING << "The entered is NULL.";
+        }
+        std::filesystem::path p = _fullPath(*p_ptr);
+        if(std::filesystem::is_regular_file(p))
+        {
+            ARMARX_ERROR << "The entered path is leading to a file! Abort due to error.";
+        }
+
+        container.clear();
+        path = p_ptr;
+
+        if(!std::filesystem::exists(p))
+        {
+            ARMARX_INFO << "The entered path does not exist. Assuming an empty container.";
+        }
+        else
+        {
+            for (const auto& d : std::filesystem::directory_iterator(p))
+            {
+                if(d.is_directory())
+                {
+                    std::string k = d.path().filename();
+                    auto wms = container.emplace(std::make_pair(k, id.withEntityName(k)));
+                    wms.first->second.reload(p_ptr);
+                }
+
+                if(d.is_regular_file())
+                {
+                    readAronType(d.path());
+                }
+            }
+        }
+    }
+
+    void ProviderSegment::append(const workingmemory::ProviderSegment& m)
+    {
+        std::filesystem::create_directories(_fullPath());
+        writeAronType(_fullPath());
+
+        for (const auto& [k, s] : m.container)
+        {
+            if (const auto& it = container.find(k); it != container.end())
+            {
+                it->second.append(s);
+            }
+            else
+            {
+                std::filesystem::create_directory(_fullPath() / k);
+                auto wms = container.emplace(std::make_pair(k, id.withEntityName(k)));
+                wms.first->second.path = path;
+                wms.first->second.append(s);
+            }
+        }
+    }
+}
diff --git a/source/RobotAPI/libraries/armem/core/diskMemory/ProviderSegment.h b/source/RobotAPI/libraries/armem/core/diskMemory/ProviderSegment.h
new file mode 100644
index 000000000..2a2033d74
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/core/diskMemory/ProviderSegment.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include <filesystem>
+
+#include "../base/ProviderSegment.h"
+#include "detail/TypedEntityContainer.h"
+
+#include "Entity.h"
+
+#include "../workingMemory/ProviderSegment.h"
+
+
+namespace armarx::armem::diskMemory
+{
+
+    /**
+     * @brief Data of a provider segment containing multiple entities.
+     */
+    class ProviderSegment :
+            virtual public ProviderSegmentBase<Entity, ProviderSegment>,
+            virtual public detail::TypedEntityContainer<Entity, ProviderSegment>
+    {
+    public:
+        using Base = ProviderSegmentBase<Entity, ProviderSegment>;
+        using EntityT = Entity;
+
+        ProviderSegment();
+        ProviderSegment(const std::string& name, aron::typenavigator::ObjectNavigatorPtr aronType = nullptr);
+        ProviderSegment(const std::string& name, const MemoryID parentID, aron::typenavigator::ObjectNavigatorPtr aronType = nullptr);
+        ProviderSegment(const MemoryID id, aron::typenavigator::ObjectNavigatorPtr aronType = nullptr);
+
+        ProviderSegment(const ProviderSegment& other);
+        ProviderSegment& operator=(const ProviderSegment& other);
+
+        // Conversion
+        workingmemory::ProviderSegment convert(const aron::typenavigator::NavigatorPtr& expectedStructure) const;
+
+        // Filesystem connection
+        void reload(const std::shared_ptr<std::filesystem::path>&);
+        void append(const workingmemory::ProviderSegment&);
+
+    private:
+        std::filesystem::path _fullPath() const;
+        std::filesystem::path _fullPath(const std::filesystem::path&) const;
+
+    public:
+        std::shared_ptr<std::filesystem::path> path;
+    };
+
+}
diff --git a/source/RobotAPI/libraries/armem/core/diskMemory/detail/TypedEntityContainer.h b/source/RobotAPI/libraries/armem/core/diskMemory/detail/TypedEntityContainer.h
new file mode 100644
index 000000000..205cffa96
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/core/diskMemory/detail/TypedEntityContainer.h
@@ -0,0 +1,100 @@
+#pragma once
+
+#include <iostream>
+#include <fstream>
+
+#include "../../base/detail/TypedEntityContainer.h"
+#include "../Entity.h"
+
+#include <RobotAPI/libraries/aron/core/navigator/type/container/Object.h>
+#include <RobotAPI/libraries/aron/core/io/typeIO/visitor/Visitor.h>
+#include <RobotAPI/libraries/aron/core/io/typeIO/converter/Converter.h>
+#include <RobotAPI/libraries/aron/core/io/typeIO/reader/nlohmannJSON/NlohmannJSONReader.h>
+#include <RobotAPI/libraries/aron/core/io/typeIO/writer/navigator/NavigatorWriter.h>
+#include <RobotAPI/libraries/aron/core/io/typeIO/writer/nlohmannJSON/NlohmannJSONWriter.h>
+
+namespace armarx::armem::diskMemory::detail
+{
+
+    /**
+     * @brief An entity container with a specific (Aron) type.
+     */
+    template <class _ValueT, class Derived>
+    class TypedEntityContainer :
+        virtual public armarx::armem::detail::TypedEntityContainerBase<_ValueT, Entity, Derived>
+    {
+        using Base = armarx::armem::detail::TypedEntityContainerBase<_ValueT, Entity, Derived>;
+
+    public:
+        TypedEntityContainer& operator=(const TypedEntityContainer& other)
+        {
+            other._copySelf(*this);
+            return *this;
+        }
+
+    protected:
+        aron::typenavigator::ObjectNavigatorPtr unwrapType(const aron::typenavigator::ObjectNavigatorPtr& t) const
+        {
+            return aron::typenavigator::ObjectNavigator::DynamicCastAndCheck(t->getMemberType(TYPE_WRAPPER_DATA_FIELD));
+        }
+
+        aron::typenavigator::ObjectNavigatorPtr wrapType(const aron::typenavigator::ObjectNavigatorPtr& t) const
+        {
+            aron::typenavigator::ObjectNavigatorPtr typeWrapped(new aron::typenavigator::ObjectNavigator());
+            typeWrapped->setObjectName(t->getObjectName() + "__ltm_type_export");
+            typeWrapped->addMemberType(TYPE_WRAPPER_DATA_FIELD, t);
+
+            typeWrapped->addMemberType(TYPE_WRAPPER_TIME_STORED_FIELD, std::make_shared<aron::typenavigator::LongNavigator>());
+            typeWrapped->addMemberType(TYPE_WRAPPER_TIME_CREATED_FIELD, std::make_shared<aron::typenavigator::LongNavigator>());
+            typeWrapped->addMemberType(TYPE_WRAPPER_TIME_SENT_FIELD, std::make_shared<aron::typenavigator::LongNavigator>());
+            typeWrapped->addMemberType(TYPE_WRAPPER_TIME_ARRIVED_FIELD, std::make_shared<aron::typenavigator::LongNavigator>());
+            typeWrapped->addMemberType(TYPE_WRAPPER_CONFIDENCE_FIELD, std::make_shared<aron::typenavigator::DoubleNavigator>());
+
+            return typeWrapped;
+        }
+
+        using Base::aronType;
+        void readAronType(const std::filesystem::path& d)
+        {
+            if(std::filesystem::is_regular_file(d))
+            {
+                if(d.filename() == (std::string(TYPE_FILENAME) + ".json"))
+                {
+                    std::ifstream ifs(d);
+                    std::string file_content((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
+
+                    aron::typeIO::reader::NlohmannJSONReader typeReader(file_content);
+                    aron::typeIO::writer::NavigatorWriter navWriter;
+                    aron::typeIO::Converter::ReadAndConvert(typeReader, navWriter);
+                    aronType = aron::typenavigator::ObjectNavigator::DynamicCastAndCheck(navWriter.getResult());
+                }
+            }
+        }
+
+        using Base::hasAronType;
+        void writeAronType(const std::filesystem::path& d)
+        {
+            if(hasAronType())
+            {
+                std::ofstream ofs;
+                ofs.open(d);
+
+                aron::typeIO::writer::NlohmannJSONWriter typeWriter;
+                aron::typeIO::Visitor::VisitAndSetup(typeWriter, aronType);
+                std::string new_file_full_content = typeWriter.getResult().dump(2);
+
+                ofs << new_file_full_content;
+                ofs.close();
+            }
+        }
+
+    private:
+        static const constexpr char* TYPE_FILENAME = "type";
+        static constexpr const char* TYPE_WRAPPER_DATA_FIELD            = "__ARON_DATA";
+        static constexpr const char* TYPE_WRAPPER_TIME_STORED_FIELD     = "__WRITER_METADATA__TIME_STORED";
+        static constexpr const char* TYPE_WRAPPER_TIME_CREATED_FIELD    = "__ENTITY_METADATA__TIME_CREATED";
+        static constexpr const char* TYPE_WRAPPER_TIME_SENT_FIELD       = "__ENTITY_METADATA__TIME_SENT";
+        static constexpr const char* TYPE_WRAPPER_TIME_ARRIVED_FIELD    = "__ENTITY_METADATA__TIME_ARRIVED";
+        static constexpr const char* TYPE_WRAPPER_CONFIDENCE_FIELD      = "__ENTITY_METADATA__CONFIDENCE";
+    };
+}
diff --git a/source/RobotAPI/libraries/armem/core/longtermMemory/CoreSegment.h b/source/RobotAPI/libraries/armem/core/longtermMemory/CoreSegment.h
index ec710907f..ed8b60c67 100644
--- a/source/RobotAPI/libraries/armem/core/longtermMemory/CoreSegment.h
+++ b/source/RobotAPI/libraries/armem/core/longtermMemory/CoreSegment.h
@@ -3,7 +3,6 @@
 #include "../base/CoreSegment.h"
 
 #include "ProviderSegment.h"
-#include "detail/TypedEntityContainer.h"
 
 #include "../workingMemory/CoreSegment.h"
 
@@ -15,8 +14,7 @@ namespace armarx::armem::longtermmemory
      * @brief Data of a core segment containing multiple provider segments.
      */
     class CoreSegment :
-        virtual public CoreSegmentBase<ProviderSegment, CoreSegment>,
-        virtual public detail::TypedEntityContainer<ProviderSegment, CoreSegment>
+        virtual public CoreSegmentBase<ProviderSegment, CoreSegment>
     {
     public:
         using Base = CoreSegmentBase<ProviderSegment, CoreSegment>;
diff --git a/source/RobotAPI/libraries/armem/core/longtermMemory/Entity.h b/source/RobotAPI/libraries/armem/core/longtermMemory/Entity.h
index 967fa2b76..edc46900e 100644
--- a/source/RobotAPI/libraries/armem/core/longtermMemory/Entity.h
+++ b/source/RobotAPI/libraries/armem/core/longtermMemory/Entity.h
@@ -3,7 +3,6 @@
 #include "../base/Entity.h"
 
 #include "EntitySnapshot.h"
-#include "detail/MemoryContainer.h"
 
 #include "../workingMemory/Entity.h"
 
@@ -30,8 +29,7 @@ namespace armarx::armem::longtermmemory
      * each containing a single `AronData` object of a specific `AronType`.
      */
     class Entity :
-        virtual public EntityBase<EntitySnapshot, Entity>,
-        virtual public detail::MemoryContainer<std::map<Time, EntitySnapshot>, Entity>
+        virtual public EntityBase<EntitySnapshot, Entity>
     {
 
     public:
diff --git a/source/RobotAPI/libraries/armem/core/longtermMemory/EntityInstance.cpp b/source/RobotAPI/libraries/armem/core/longtermMemory/EntityInstance.cpp
index 696b5c5c5..d4770ded9 100644
--- a/source/RobotAPI/libraries/armem/core/longtermMemory/EntityInstance.cpp
+++ b/source/RobotAPI/libraries/armem/core/longtermMemory/EntityInstance.cpp
@@ -2,7 +2,6 @@
 
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
 
-
 namespace armarx::armem::longtermmemory
 {
 
diff --git a/source/RobotAPI/libraries/armem/core/longtermMemory/EntitySnapshot.h b/source/RobotAPI/libraries/armem/core/longtermMemory/EntitySnapshot.h
index 6f2b9c74c..16dc077f3 100644
--- a/source/RobotAPI/libraries/armem/core/longtermMemory/EntitySnapshot.h
+++ b/source/RobotAPI/libraries/armem/core/longtermMemory/EntitySnapshot.h
@@ -3,7 +3,6 @@
 #include "../base/EntitySnapshot.h"
 
 #include "EntityInstance.h"
-#include "detail/MemoryContainer.h"
 
 #include "../workingMemory/EntitySnapshot.h"
 
@@ -15,8 +14,7 @@ namespace armarx::armem::longtermmemory
      * @brief Data of an entity at one point in time.
      */
     class EntitySnapshot :
-        virtual public EntitySnapshotBase<EntityInstance, EntitySnapshot>,
-        virtual public detail::MemoryContainer<std::vector<EntityInstance>, EntitySnapshot>
+        virtual public EntitySnapshotBase<EntityInstance, EntitySnapshot>
     {
 
     public:
diff --git a/source/RobotAPI/libraries/armem/core/longtermMemory/Memory.h b/source/RobotAPI/libraries/armem/core/longtermMemory/Memory.h
index 85137aaf4..ab7c8b90f 100644
--- a/source/RobotAPI/libraries/armem/core/longtermMemory/Memory.h
+++ b/source/RobotAPI/libraries/armem/core/longtermMemory/Memory.h
@@ -3,20 +3,17 @@
 #include "../base/Memory.h"
 
 #include "CoreSegment.h"
-#include "detail/EntityContainer.h"
 
 #include "../workingMemory/Memory.h"
 #include "mongodb/MongoDBConnectionManager.h"
 
 namespace armarx::armem::longtermmemory
 {
-
     /**
      * @brief Data of a memory consisting of multiple core segments.
      */
     class Memory :
-        virtual public MemoryBase<CoreSegment, Memory>,
-        virtual public detail::EntityContainer<CoreSegment, Memory>
+        virtual public MemoryBase<CoreSegment, Memory>
     {
     public:
         using Base = MemoryBase<CoreSegment, Memory>;
diff --git a/source/RobotAPI/libraries/armem/core/longtermMemory/ProviderSegment.h b/source/RobotAPI/libraries/armem/core/longtermMemory/ProviderSegment.h
index 0c43e80e1..0ccff9600 100644
--- a/source/RobotAPI/libraries/armem/core/longtermMemory/ProviderSegment.h
+++ b/source/RobotAPI/libraries/armem/core/longtermMemory/ProviderSegment.h
@@ -3,7 +3,6 @@
 #include "../base/ProviderSegment.h"
 
 #include "Entity.h"
-#include "detail/TypedEntityContainer.h"
 
 #include "../workingMemory/ProviderSegment.h"
 
@@ -15,8 +14,7 @@ namespace armarx::armem::longtermmemory
      * @brief Data of a provider segment containing multiple entities.
      */
     class ProviderSegment :
-        virtual public ProviderSegmentBase<Entity, ProviderSegment>,
-        virtual public detail::TypedEntityContainer<Entity, ProviderSegment>
+        virtual public ProviderSegmentBase<Entity, ProviderSegment>
     {
     public:
         using Base = ProviderSegmentBase<Entity, ProviderSegment>;
diff --git a/source/RobotAPI/libraries/armem/core/longtermMemory/detail/EntityContainer.cpp b/source/RobotAPI/libraries/armem/core/longtermMemory/detail/EntityContainer.cpp
deleted file mode 100644
index 43ade411e..000000000
--- a/source/RobotAPI/libraries/armem/core/longtermMemory/detail/EntityContainer.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#include "EntityContainer.h"
-
-#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
-
-
-namespace armarx::armem::detail
-{
-
-
-}
diff --git a/source/RobotAPI/libraries/armem/core/longtermMemory/detail/EntityContainer.h b/source/RobotAPI/libraries/armem/core/longtermMemory/detail/EntityContainer.h
deleted file mode 100644
index 73e5ea68e..000000000
--- a/source/RobotAPI/libraries/armem/core/longtermMemory/detail/EntityContainer.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#pragma once
-
-#include "../../base/detail/EntityContainer.h"
-#include "MemoryContainer.h"
-
-#include "../Entity.h"
-#include "../EntitySnapshot.h"
-#include "../EntityInstance.h"
-
-
-namespace armarx::armem::longtermmemory::detail
-{
-
-    /**
-     * @brief A container of entities at some point in the hierarchy.
-     *
-     * Can be updated by multiple entity updates.
-     */
-    template <class _ValueT, class Derived>
-    class EntityContainer :
-        virtual public armarx::armem::detail::EntityContainerBase<_ValueT, Entity, Derived>,
-        virtual public MemoryContainer<std::map<std::string, _ValueT>, Derived>
-    {
-    public:
-        EntityContainer& operator=(const EntityContainer& other)
-        {
-            other._copySelf(*this);
-            return *this;
-        }
-    };
-
-}
diff --git a/source/RobotAPI/libraries/armem/core/longtermMemory/detail/MemoryContainer.cpp b/source/RobotAPI/libraries/armem/core/longtermMemory/detail/MemoryContainer.cpp
deleted file mode 100644
index 9fd73048f..000000000
--- a/source/RobotAPI/libraries/armem/core/longtermMemory/detail/MemoryContainer.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "MemoryContainer.h"
-
-
-namespace armarx::armem::detail
-{
-
-}
diff --git a/source/RobotAPI/libraries/armem/core/longtermMemory/detail/MemoryContainer.h b/source/RobotAPI/libraries/armem/core/longtermMemory/detail/MemoryContainer.h
deleted file mode 100644
index 5913d50db..000000000
--- a/source/RobotAPI/libraries/armem/core/longtermMemory/detail/MemoryContainer.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#pragma once
-
-#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
-
-#include "../../error.h"
-
-#include "../../base/detail/MemoryContainer.h"
-
-
-namespace armarx::armem::longtermmemory::detail
-{
-
-    /**
-     * @class Provides default implmentations of `MemoryContainer`, as well as
-     * iterators (which requires a template).
-     */
-    template <class _ContainerT, class Derived>
-    class MemoryContainer :
-            virtual public armarx::armem::detail::MemoryContainerBase<_ContainerT, Derived>
-    {
-    public:
-        MemoryContainer& operator=(const MemoryContainer& other)
-        {
-            other._copySelf(*this);
-            return *this;
-        }
-    };
-}
diff --git a/source/RobotAPI/libraries/armem/core/longtermMemory/detail/TypedEntityContainer.h b/source/RobotAPI/libraries/armem/core/longtermMemory/detail/TypedEntityContainer.h
deleted file mode 100644
index ea826343e..000000000
--- a/source/RobotAPI/libraries/armem/core/longtermMemory/detail/TypedEntityContainer.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma once
-
-#include "../../base/detail/TypedEntityContainer.h"
-#include "EntityContainer.h"
-
-#include <RobotAPI/libraries/aron/core/navigator/type/container/Object.h>
-
-namespace armarx::armem::longtermmemory::detail
-{
-
-    /**
-     * @brief An entity container with a specific (Aron) type.
-     */
-    template <class _ValueT, class Derived>
-    class TypedEntityContainer :
-        virtual public armarx::armem::detail::TypedEntityContainerBase<_ValueT, Entity, Derived>,
-        virtual public EntityContainer<_ValueT, Derived>
-    {
-    public:
-        TypedEntityContainer& operator=(const TypedEntityContainer& other)
-        {
-            other._copySelf(*this);
-            return *this;
-        }
-    };
-}
diff --git a/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp b/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp
index 564984f22..698b1ced4 100644
--- a/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp
+++ b/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp
@@ -3,7 +3,7 @@
 #include <RobotAPI/libraries/armem/core/ice_conversions.h>
 #include <RobotAPI/libraries/armem_gui/gui_utils.h>
 
-//#include <RobotAPI/libraries/armem/core/io/diskWriter/NlohmannJSON/NlohmannJSONDiskWriter.h>
+#include <RobotAPI/libraries/armem/core/diskMemory/Memory.h>
 
 #include <ArmarXGui/libraries/SimpleConfigDialog/SimpleConfigDialog.h>
 
@@ -140,7 +140,27 @@ namespace armarx::armem::gui
         QString qs = ltmControlWidget->getEnteredPath();
         std::string utf8_text = qs.toUtf8().constData();
 
+        ARMARX_IMPORTANT << "Exporting all memories at '" << utf8_text << "'.";
 
+        std::filesystem::path p(utf8_text);
+        if (std::filesystem::is_regular_file(p))
+        {
+            ARMARX_WARNING << "Could not export a memory at '" << utf8_text << "'. Skipping export.";
+            return;
+        }
+
+        std::filesystem::create_directories(p);
+        for (auto& [name, reader] : memoryReaders)
+        {
+            armem::client::QueryInput input = memoryGroup->queryWidget()->queryInput();
+            armem::client::QueryResult result = reader.query(input);
+
+            armem::diskMemory::Memory dMem(name);
+            ARMARX_IMPORTANT << "RELOAD";
+            dMem.reload(p / name);
+            ARMARX_IMPORTANT << "APPEND";
+            dMem.append(result.memory);
+        }
 
         TIMING_END_STREAM(MemoryExport, ARMARX_VERBOSE);
     }
@@ -271,10 +291,6 @@ namespace armarx::armem::gui
             {
                 convMap[name] = &data.value();
             }
-            /*if (data.second.has_value())
-            {
-                convMap[name].second = &data.second.value();
-            }*/
         }
 
         if (convMap.empty())
-- 
GitLab