Add ProxyDatastore

This class will be used to intercept certain commands from the cli, like
entering RPC input. Right now, it works just as a pass-through.

Change-Id: I2d252609c1354005a0ccf4a1f26399dc895a73e8
diff --git a/src/cli.cpp b/src/cli.cpp
index 8a3536f..1f62f78 100644
--- a/src/cli.cpp
+++ b/src/cli.cpp
@@ -12,6 +12,7 @@
 #include <sstream>
 #include "NETCONF_CLI_VERSION.h"
 #include "interpreter.hpp"
+#include "proxy_datastore.hpp"
 #if defined(SYSREPO_CLI)
 #include "sysrepo_access.hpp"
 #define PROGRAM_NAME "sysrepo-cli"
@@ -72,10 +73,10 @@
             return 1;
         }
     }
-    SysrepoAccess datastore(PROGRAM_NAME, datastoreType);
+    auto datastore = std::make_shared<SysrepoAccess>(PROGRAM_NAME, datastoreType);
     std::cout << "Connected to sysrepo [datastore: " << (datastoreType == Datastore::Startup ? "startup" : "running") << "]" << std::endl;
 #elif defined(YANG_CLI)
-    YangAccess datastore;
+    auto datastore = std::make_shared<YangAccess>();
     if (args["--configonly"].asBool()) {
         writableOps = WritableOps::No;
     } else {
@@ -83,13 +84,13 @@
         std::cout << "ops is writable" << std::endl;
     }
     if (const auto& search_dir = args["-s"]) {
-        datastore.addSchemaDir(search_dir.asString());
+        datastore->addSchemaDir(search_dir.asString());
     }
     for (const auto& schemaFile : args["<schema_file_or_module_name>"].asStringList()) {
         if (std::filesystem::exists(schemaFile)) {
-            datastore.addSchemaFile(schemaFile);
+            datastore->addSchemaFile(schemaFile);
         } else if (schemaFile.find('/') == std::string::npos) { // Module names cannot have a slash
-            datastore.loadModule(schemaFile);
+            datastore->loadModule(schemaFile);
         } else {
             std::cerr << "Cannot load YANG module " << schemaFile << "\n";
         }
@@ -106,7 +107,7 @@
                 return 1;
             }
             try {
-                datastore.enableFeature(parsed.first, parsed.second);
+                datastore->enableFeature(parsed.first, parsed.second);
             } catch (std::runtime_error& ex) {
                 std::cerr << ex.what() << "\n";
                 return 1;
@@ -116,15 +117,16 @@
     }
     if (const auto& dataFiles = args["-i"]) {
         for (const auto& dataFile : dataFiles.asStringList()) {
-            datastore.addDataFile(dataFile);
+            datastore->addDataFile(dataFile);
         }
     }
 #else
 #error "Unknown CLI backend"
 #endif
 
-    auto dataQuery = std::make_shared<DataQuery>(datastore);
-    Parser parser(datastore.schema(), writableOps, dataQuery);
+    ProxyDatastore proxyDatastore(datastore);
+    auto dataQuery = std::make_shared<DataQuery>(*datastore);
+    Parser parser(datastore->schema(), writableOps, dataQuery);
 
     using replxx::Replxx;
 
@@ -182,7 +184,7 @@
 
         try {
             command_ cmd = parser.parseCommand(line, std::cout);
-            boost::apply_visitor(Interpreter(parser, datastore), cmd);
+            boost::apply_visitor(Interpreter(parser, proxyDatastore), cmd);
         } catch (InvalidCommandException& ex) {
             std::cerr << ex.what() << std::endl;
         } catch (DatastoreException& ex) {
diff --git a/src/interpreter.cpp b/src/interpreter.cpp
index 3b52960..5ff73e7 100644
--- a/src/interpreter.cpp
+++ b/src/interpreter.cpp
@@ -293,7 +293,7 @@
     }
 }
 
-Interpreter::Interpreter(Parser& parser, DatastoreAccess& datastore)
+Interpreter::Interpreter(Parser& parser, ProxyDatastore& datastore)
     : m_parser(parser)
     , m_datastore(datastore)
 {
diff --git a/src/interpreter.hpp b/src/interpreter.hpp
index 543fb2e..000cc21 100644
--- a/src/interpreter.hpp
+++ b/src/interpreter.hpp
@@ -9,12 +9,12 @@
 #pragma once
 
 #include <boost/variant/static_visitor.hpp>
-#include "datastore_access.hpp"
+#include "proxy_datastore.hpp"
 #include "parser.hpp"
 
 
 struct Interpreter : boost::static_visitor<void> {
-    Interpreter(Parser& parser, DatastoreAccess& datastore);
+    Interpreter(Parser& parser, ProxyDatastore& datastore);
 
     void operator()(const commit_&) const;
     void operator()(const set_&) const;
@@ -40,5 +40,5 @@
     [[nodiscard]] boost::variant<dataPath_, schemaPath_, module_> toCanonicalPath(const PathType& path) const;
 
     Parser& m_parser;
-    DatastoreAccess& m_datastore;
+    ProxyDatastore& m_datastore;
 };
diff --git a/src/proxy_datastore.cpp b/src/proxy_datastore.cpp
new file mode 100644
index 0000000..ab9193c
--- /dev/null
+++ b/src/proxy_datastore.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 CESNET, https://photonics.cesnet.cz/
+ *
+ * Written by Václav Kubernát <kubernat@cesnet.cz>
+ *
+*/
+#include "proxy_datastore.hpp"
+
+ProxyDatastore::ProxyDatastore(const std::shared_ptr<DatastoreAccess>& datastore)
+    : m_datastore(datastore)
+{
+}
+
+DatastoreAccess::Tree ProxyDatastore::getItems(const std::string& path) const
+{
+    return m_datastore->getItems(path);
+}
+
+void ProxyDatastore::setLeaf(const std::string& path, leaf_data_ value)
+{
+    m_datastore->setLeaf(path, value);
+}
+
+void ProxyDatastore::createItem(const std::string& path)
+{
+    m_datastore->createItem(path);
+}
+
+void ProxyDatastore::deleteItem(const std::string& path)
+{
+    m_datastore->deleteItem(path);
+}
+
+void ProxyDatastore::moveItem(const std::string& source, std::variant<yang::move::Absolute, yang::move::Relative> move)
+{
+    m_datastore->moveItem(source, move);
+}
+
+void ProxyDatastore::commitChanges()
+{
+    m_datastore->commitChanges();
+}
+
+void ProxyDatastore::discardChanges()
+{
+    m_datastore->discardChanges();
+}
+
+void ProxyDatastore::copyConfig(const Datastore source, const Datastore destination)
+{
+    m_datastore->copyConfig(source, destination);
+}
+
+std::string ProxyDatastore::dump(const DataFormat format) const
+{
+    return m_datastore->dump(format);
+}
+
+std::shared_ptr<Schema> ProxyDatastore::schema() const
+{
+    return m_datastore->schema();
+}
diff --git a/src/proxy_datastore.hpp b/src/proxy_datastore.hpp
new file mode 100644
index 0000000..0ed5e2d
--- /dev/null
+++ b/src/proxy_datastore.hpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 CESNET, https://photonics.cesnet.cz/
+ *
+ * Written by Václav Kubernát <kubernat@cesnet.cz>
+ *
+*/
+
+#pragma once
+#include "datastore_access.hpp"
+
+/*! \class ProxyDatastore
+ *     \brief DatastoreAccess wrapper that handles RPC input
+ */
+class ProxyDatastore {
+public:
+    ProxyDatastore(const std::shared_ptr<DatastoreAccess>& datastore);
+    [[nodiscard]] DatastoreAccess::Tree getItems(const std::string& path) const;
+    void setLeaf(const std::string& path, leaf_data_ value);
+    void createItem(const std::string& path);
+    void deleteItem(const std::string& path);
+    void moveItem(const std::string& source, std::variant<yang::move::Absolute, yang::move::Relative> move);
+    void commitChanges();
+    void discardChanges();
+    void copyConfig(const Datastore source, const Datastore destination);
+    [[nodiscard]] std::string dump(const DataFormat format) const;
+
+    [[nodiscard]] std::shared_ptr<Schema> schema() const;
+private:
+    std::shared_ptr<DatastoreAccess> m_datastore;
+};