Request YANG schemas via sysrepo

The std::function that is fed into YangSchema::registerModuleCallback
does not have the same signature that libyang requires, because we would
have to include libyang in the sysrepo_access header file. We don't want this
class to know about libyang, so instead, we use an intermediate function,
that has string arguments and a string return type. In YangSchema, this
function is wrapped with another function, that has the required signature.

Change-Id: Ibd2dcb89344cf1454ba0b3970cac0c8e88ffa20d
diff --git a/src/sysrepo_access.cpp b/src/sysrepo_access.cpp
index af553d9..d80f539 100644
--- a/src/sysrepo_access.cpp
+++ b/src/sysrepo_access.cpp
@@ -8,6 +8,7 @@
 
 #include <sysrepo-cpp/Session.h>
 #include "sysrepo_access.hpp"
+#include "yang_schema.hpp"
 
 leaf_data_ leafValueFromVal(const S_Val& value)
 {
@@ -72,8 +73,16 @@
 
 SysrepoAccess::SysrepoAccess(const std::string& appname)
     : m_connection(new Connection(appname.c_str()))
+    , m_schema(new YangSchema())
 {
     m_session = std::make_shared<Session>(m_connection);
+    m_schema->registerModuleCallback([this](const char* moduleName, const char* revision, const char* submodule) {
+        return fetchSchema(moduleName, revision, submodule);
+    });
+
+    for (const auto& it : listImplementedSchemas()) {
+        m_schema->loadModule(it);
+    }
 }
 
 std::map<std::string, leaf_data_> SysrepoAccess::getItems(const std::string& path)
@@ -121,3 +130,29 @@
 {
     m_session->commit();
 }
+
+std::string SysrepoAccess::fetchSchema(const char* module, const char* revision, const char* submodule)
+{
+    auto schema = m_session->get_schema(module, revision, submodule, SR_SCHEMA_YANG); // FIXME: maybe we should use get_submodule_schema for submodules?
+    if (schema.empty())
+        throw std::runtime_error(std::string("Module ") + module + " not available");
+
+    return schema;
+}
+
+std::vector<std::string> SysrepoAccess::listImplementedSchemas()
+{
+    std::vector<std::string> res;
+    auto schemas = m_session->list_schemas();
+    for (unsigned int i = 0; i < schemas->schema_cnt(); i++) {
+        auto schema = schemas->schema(i);
+        if (schema->implemented())
+            res.push_back(schema->module_name());
+    }
+    return res;
+}
+
+std::shared_ptr<Schema> SysrepoAccess::schema()
+{
+    return m_schema;
+}