From c3bb7889df67772fdf340e7973e6e22436bfa438 Mon Sep 17 00:00:00 2001
From: Rainer Kartmann <rainer.kartmann@student.kit.edu>
Date: Wed, 3 Apr 2019 10:37:54 +0200
Subject: [PATCH] Added Visitor

---
 VirtualRobot/CMakeLists.txt                 |  2 +
 VirtualRobot/MJCF/elements/core/Visitor.cpp | 48 ++++++++++++++++++
 VirtualRobot/MJCF/elements/core/Visitor.h   | 55 +++++++++++++++++++++
 3 files changed, 105 insertions(+)
 create mode 100644 VirtualRobot/MJCF/elements/core/Visitor.cpp
 create mode 100644 VirtualRobot/MJCF/elements/core/Visitor.h

diff --git a/VirtualRobot/CMakeLists.txt b/VirtualRobot/CMakeLists.txt
index e636b335a..7427eeee2 100644
--- a/VirtualRobot/CMakeLists.txt
+++ b/VirtualRobot/CMakeLists.txt
@@ -328,6 +328,7 @@ SET(SOURCES
     MJCF/elements/core/Element.cpp
     MJCF/elements/core/exceptions.cpp
     MJCF/elements/core/mjcf_utils.cpp
+    MJCF/elements/core/Visitor.cpp
     
     Nodes/CameraSensor.cpp
     Nodes/CameraSensorFactory.cpp
@@ -534,6 +535,7 @@ SET(INCLUDES
     MJCF/elements/core/Element.h
     MJCF/elements/core/exceptions.h
     MJCF/elements/core/mjcf_utils.h
+    MJCF/elements/core/Visitor.h
     
     Nodes/CameraSensor.h
     Nodes/CameraSensorFactory.h
diff --git a/VirtualRobot/MJCF/elements/core/Visitor.cpp b/VirtualRobot/MJCF/elements/core/Visitor.cpp
new file mode 100644
index 000000000..237cdd4e4
--- /dev/null
+++ b/VirtualRobot/MJCF/elements/core/Visitor.cpp
@@ -0,0 +1,48 @@
+#include "Visitor.h"
+
+#include "AnyElement.h"
+
+namespace mjcf
+{
+
+namespace detail
+{
+
+VisitorAdapter::VisitorAdapter(Visitor& owner) : 
+    owner(owner)
+{}
+
+bool VisitorAdapter::visitEnter(const tinyxml2::XMLElement& element)
+{
+    return owner.visitEnter(owner.cast(element));
+}
+
+bool VisitorAdapter::visitExit(const tinyxml2::XMLElement& element)
+{
+    return owner.visitExit(owner.cast(element));
+}
+
+}
+
+Visitor::Visitor(Document& document) : document(document)
+{}
+
+detail::VisitorAdapter* Visitor::adapter()
+{
+    return &_adapter;
+}
+
+const detail::VisitorAdapter* Visitor::adapter() const
+{
+    return &_adapter;
+}
+
+const AnyElement Visitor::cast(const tinyxml2::XMLElement& element)
+{
+    // The constructor of Element requires a non-const element pointer.
+    // As AnyElement is passed as const& to the user-provided visit method,
+    // this const cast should be sufficiently safe.
+    return { &document, const_cast<tinyxml2::XMLElement*>(&element) };
+}
+
+}
diff --git a/VirtualRobot/MJCF/elements/core/Visitor.h b/VirtualRobot/MJCF/elements/core/Visitor.h
new file mode 100644
index 000000000..04a9dbd3a
--- /dev/null
+++ b/VirtualRobot/MJCF/elements/core/Visitor.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <VirtualRobot/Util/xml/tinyxml2.h>
+
+
+namespace mjcf
+{
+    class AnyElement;
+    class Document;
+    class Visitor;
+
+namespace detail
+{
+
+    class VisitorAdapter : public tinyxml2::XMLVisitor
+    {
+    public:
+        VisitorAdapter(Visitor& owner);
+        virtual bool visitEnter(const tinyxml2::XMLElement& element);
+        virtual bool visitExit(const tinyxml2::XMLElement& element);
+        
+    private:
+        Visitor& owner;
+    };
+
+}
+
+    class Visitor
+    {
+    public:
+        
+        Visitor(Document& document);
+        virtual ~Visitor() = default;
+        
+        virtual bool visitEnter(const AnyElement&) { return true; }
+        virtual bool visitExit(const AnyElement&) { return true; }
+        
+        
+        detail::VisitorAdapter* adapter();
+        const detail::VisitorAdapter* adapter() const;
+        
+        
+    private:
+        
+        friend class detail::VisitorAdapter;
+        const AnyElement cast(const tinyxml2::XMLElement& element);
+        
+        
+        Document& document;
+        
+        detail::VisitorAdapter _adapter { *this };
+        
+    };
+
+}
-- 
GitLab