Allow loading initial data to yang-cli

Change-Id: I527d6998b518a65ffde827bcf2d56335f1fb210d
diff --git a/src/cli.cpp b/src/cli.cpp
index b036ebc..46650b2 100644
--- a/src/cli.cpp
+++ b/src/cli.cpp
@@ -31,13 +31,14 @@
 static const auto usage = R"(CLI interface for creating local YANG data instances
 
 Usage:
-  yang-cli [-s <search_dir>] [-e enable_features]... <schema_file>...
+  yang-cli [-s <search_dir>] [-e enable_features]... [-i data_file]... <schema_file>...
   yang-cli (-h | --help)
   yang-cli --version
 
 Options:
   -s <search_dir>       Set search for schema lookup
-  -e <enable_features>  Feature to enable after modules are loaded. This option can be supplied more than once. Format: <module_name>:<feature>)";
+  -e <enable_features>  Feature to enable after modules are loaded. This option can be supplied more than once. Format: <module_name>:<feature>
+  -i <data_file>        File to import data from)";
 #else
 #error "Unknown CLI backend"
 #endif
@@ -94,6 +95,11 @@
 
         }
     }
+    if (const auto& dataFiles = args["-i"]) {
+        for (const auto& dataFile : dataFiles.asStringList()) {
+            datastore.addDataFile(dataFile);
+        }
+    }
 #else
 #error "Unknown CLI backend"
 #endif
diff --git a/src/yang_access.cpp b/src/yang_access.cpp
index 7e7238e..8eccef4 100644
--- a/src/yang_access.cpp
+++ b/src/yang_access.cpp
@@ -1,5 +1,6 @@
 #include <boost/algorithm/string/predicate.hpp>
 #include <experimental/iterator>
+#include <fstream>
 #include <iostream>
 #include <libyang/Tree_Data.hpp>
 #include <libyang/libyang.h>
@@ -292,3 +293,25 @@
 {
     m_schema->enableFeature(module, feature);
 }
+
+void YangAccess::addDataFile(const std::string& path)
+{
+    std::ifstream fs(path);
+    char firstChar;
+    fs >> firstChar;
+
+    std::cout << "Parsing \"" << path << "\" as " << (firstChar == '{' ? "JSON" : "XML") << "...\n";
+    auto dataNode = lyd_parse_path(m_ctx.get(), path.c_str(), firstChar == '{' ? LYD_JSON : LYD_XML, LYD_OPT_DATA | LYD_OPT_DATA_NO_YANGLIB | LYD_OPT_TRUSTED);
+
+    if (!dataNode) {
+        throw std::runtime_error("Supplied data file " + path + " couldn't be parsed.");
+    }
+
+    if (!m_datastore) {
+        m_datastore = lyWrap(dataNode);
+    } else {
+        lyd_merge(m_datastore.get(), dataNode, LYD_OPT_DESTRUCT);
+    }
+
+    validate();
+}
diff --git a/src/yang_access.hpp b/src/yang_access.hpp
index 7fa562c..acbcc08 100644
--- a/src/yang_access.hpp
+++ b/src/yang_access.hpp
@@ -39,6 +39,7 @@
 
     void addSchemaFile(const std::string& path);
     void addSchemaDir(const std::string& path);
+    void addDataFile(const std::string& path);
 
 private:
     std::vector<ListInstance> listInstances(const std::string& path) override;