Create an abstract class for schemas
Change-Id: I0845e8fa11db68add75bed40d44779f67c0a33aa
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4ec7140..9b3e0a1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -55,6 +55,7 @@
add_definitions(-DBOOST_SPIRIT_X3_NO_FILESYSTEM)
set(parser_SRCS
+ src/static_schema.cpp
src/schema.cpp
src/parser.cpp
src/ast_commands.cpp
diff --git a/src/main.cpp b/src/main.cpp
index 2835600..0c02ecf 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -13,7 +13,7 @@
#include "NETCONF_CLI_VERSION.h"
#include "interpreter.hpp"
#include "parser.hpp"
-#include "schema.hpp"
+#include "static_schema.hpp"
static const char usage[] =
@@ -46,7 +46,7 @@
true);
std::cout << "Welcome to netconf-cli" << std::endl;
- auto schema = std::make_shared<Schema>();
+ auto schema = std::make_shared<StaticSchema>();
schema->addContainer("", "a", yang::ContainerTraits::Presence);
schema->addContainer("", "b");
schema->addLeaf("", "leafString", yang::LeafDataTypes::String);
diff --git a/src/schema.cpp b/src/schema.cpp
index 066dc3b..c390e31 100644
--- a/src/schema.cpp
+++ b/src/schema.cpp
@@ -7,126 +7,5 @@
*/
#include "schema.hpp"
-#include "utils.hpp"
-InvalidNodeException::~InvalidNodeException() = default;
-
-Schema::Schema()
-{
- m_nodes.emplace("", std::unordered_map<std::string, NodeType>());
-}
-
-const std::unordered_map<std::string, NodeType>& Schema::children(const std::string& name) const
-{
- return m_nodes.at(name);
-}
-
-bool Schema::nodeExists(const std::string& location, const std::string& name) const
-{
- if (name.empty())
- return true;
- const auto& childrenRef = children(location);
-
- return childrenRef.find(name) != childrenRef.end();
-}
-
-bool Schema::isContainer(const path_& location, const std::string& name) const
-{
- std::string locationString = pathToSchemaString(location);
- if (!nodeExists(locationString, name))
- return false;
-
- return children(locationString).at(name).type() == typeid(yang::container);
-}
-
-void Schema::addContainer(const std::string& location, const std::string& name, yang::ContainerTraits isPresence)
-{
- m_nodes.at(location).emplace(name, yang::container{isPresence});
-
- //create a new set of children for the new node
- std::string key = joinPaths(location, name);
- m_nodes.emplace(key, std::unordered_map<std::string, NodeType>());
-}
-
-
-bool Schema::listHasKey(const path_& location, const std::string& name, const std::string& key) const
-{
- std::string locationString = pathToSchemaString(location);
- assert(isList(location, name));
-
- const auto& child = children(locationString).at(name);
- const auto& list = boost::get<yang::list>(child);
- return list.m_keys.find(key) != list.m_keys.end();
-}
-
-const std::set<std::string>& Schema::listKeys(const path_& location, const std::string& name) const
-{
- std::string locationString = pathToSchemaString(location);
- assert(isList(location, name));
-
- const auto& child = children(locationString).at(name);
- const auto& list = boost::get<yang::list>(child);
- return list.m_keys;
-}
-
-bool Schema::isList(const path_& location, const std::string& name) const
-{
- std::string locationString = pathToSchemaString(location);
- if (!nodeExists(locationString, name))
- return false;
- const auto& child = children(locationString).at(name);
- if (child.type() != typeid(yang::list))
- return false;
-
- return true;
-}
-
-void Schema::addList(const std::string& location, const std::string& name, const std::set<std::string>& keys)
-{
- m_nodes.at(location).emplace(name, yang::list{keys});
-
- m_nodes.emplace(name, std::unordered_map<std::string, NodeType>());
-}
-
-bool Schema::isPresenceContainer(const path_& location, const std::string& name) const
-{
- if (!isContainer(location, name))
- return false;
- std::string locationString = pathToSchemaString(location);
- return boost::get<yang::container>(children(locationString).at(name)).m_presence == yang::ContainerTraits::Presence;
-}
-
-void Schema::addLeaf(const std::string& location, const std::string& name, const yang::LeafDataTypes& type)
-{
- m_nodes.at(location).emplace(name, yang::leaf{type, {}});
-}
-
-void Schema::addLeafEnum(const std::string& location, const std::string& name, std::set<std::string> enumValues)
-{
- m_nodes.at(location).emplace(name, yang::leaf{yang::LeafDataTypes::Enum, enumValues});
-}
-
-bool Schema::leafEnumHasValue(const path_& location, const std::string& name, const std::string& value) const
-{
- std::string locationString = pathToSchemaString(location);
- assert(isLeaf(location, name));
-
- const auto& child = children(locationString).at(name);
- const auto& list = boost::get<yang::leaf>(child);
- return list.m_enumValues.find(value) != list.m_enumValues.end();
-}
-
-bool Schema::isLeaf(const path_& location, const std::string& name) const
-{
- std::string locationString = pathToSchemaString(location);
- if (!nodeExists(locationString, name))
- return false;
-
- return children(locationString).at(name).type() == typeid(yang::leaf);
-}
-
-yang::LeafDataTypes Schema::leafType(const path_& location, const std::string& name) const
-{
- std::string locationString = pathToSchemaString(location);
- return boost::get<yang::leaf>(children(locationString).at(name)).m_type;
-}
+Schema::~Schema() = default;
diff --git a/src/schema.hpp b/src/schema.hpp
index e87619b..7c05d17 100644
--- a/src/schema.hpp
+++ b/src/schema.hpp
@@ -1,3 +1,4 @@
+
/*
* Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
* Copyright (C) 2018 FIT CVUT, https://fit.cvut.cz/
@@ -52,25 +53,21 @@
};
/*! \class Schema
- * \brief The class representing the schema, that the user traverses.
+ * \brief A base schema class for schemas
* */
class Schema {
public:
- Schema();
- bool nodeExists(const std::string& location, const std::string& name) const;
+ virtual ~Schema();
- bool isContainer(const path_& location, const std::string& name) const;
- void addContainer(const std::string& location, const std::string& name, yang::ContainerTraits isPresence = yang::ContainerTraits::None);
- const std::set<std::string>& listKeys(const path_& location, const std::string& name) const;
- bool listHasKey(const path_& location, const std::string& name, const std::string& key) const;
- bool isList(const path_& location, const std::string& name) const;
- void addList(const std::string& location, const std::string& name, const std::set<std::string>& keys);
- bool isPresenceContainer(const path_& location, const std::string& name) const;
- void addLeaf(const std::string& location, const std::string& name, const yang::LeafDataTypes& type);
- void addLeafEnum(const std::string& location, const std::string& name, std::set<std::string> enumValues);
- bool leafEnumHasValue(const path_& location, const std::string& name, const std::string& value) const;
- bool isLeaf(const path_& location, const std::string& name) const;
- yang::LeafDataTypes leafType(const path_& location, const std::string& name) const;
+ virtual bool isContainer(const path_& location, const std::string& name) const = 0;
+ virtual bool isLeaf(const path_& location, const std::string& name) const = 0;
+ virtual bool isList(const path_& location, const std::string& name) const = 0;
+ virtual bool isPresenceContainer(const path_& location, const std::string& name) const = 0;
+ virtual bool leafEnumHasValue(const path_& location, const std::string& name, const std::string& value) const = 0;
+ virtual bool listHasKey(const path_& location, const std::string& name, const std::string& key) const = 0;
+ virtual bool nodeExists(const std::string& location, const std::string& name) const = 0;
+ virtual const std::set<std::string>& listKeys(const path_& location, const std::string& name) const = 0;
+ virtual yang::LeafDataTypes leafType(const path_& location, const std::string& name) const = 0;
private:
const std::unordered_map<std::string, NodeType>& children(const std::string& name) const;
diff --git a/src/static_schema.cpp b/src/static_schema.cpp
new file mode 100644
index 0000000..65debf0
--- /dev/null
+++ b/src/static_schema.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
+ * Copyright (C) 2018 FIT CVUT, https://fit.cvut.cz/
+ *
+ * Written by Václav Kubernát <kubervac@fit.cvut.cz>
+ *
+*/
+
+#include "static_schema.hpp"
+#include "utils.hpp"
+
+InvalidNodeException::~InvalidNodeException() = default;
+
+StaticSchema::StaticSchema()
+{
+ m_nodes.emplace("", std::unordered_map<std::string, NodeType>());
+}
+
+const std::unordered_map<std::string, NodeType>& StaticSchema::children(const std::string& name) const
+{
+ return m_nodes.at(name);
+}
+
+bool StaticSchema::nodeExists(const std::string& location, const std::string& name) const
+{
+ if (name.empty())
+ return true;
+ const auto& childrenRef = children(location);
+
+ return childrenRef.find(name) != childrenRef.end();
+}
+
+bool StaticSchema::isContainer(const path_& location, const std::string& name) const
+{
+ std::string locationString = pathToSchemaString(location);
+ if (!nodeExists(locationString, name))
+ return false;
+
+ return children(locationString).at(name).type() == typeid(yang::container);
+}
+
+void StaticSchema::addContainer(const std::string& location, const std::string& name, yang::ContainerTraits isPresence)
+{
+ m_nodes.at(location).emplace(name, yang::container{isPresence});
+
+ //create a new set of children for the new node
+ std::string key = joinPaths(location, name);
+ m_nodes.emplace(key, std::unordered_map<std::string, NodeType>());
+}
+
+
+bool StaticSchema::listHasKey(const path_& location, const std::string& name, const std::string& key) const
+{
+ std::string locationString = pathToSchemaString(location);
+ assert(isList(location, name));
+
+ const auto& child = children(locationString).at(name);
+ const auto& list = boost::get<yang::list>(child);
+ return list.m_keys.find(key) != list.m_keys.end();
+}
+
+const std::set<std::string>& StaticSchema::listKeys(const path_& location, const std::string& name) const
+{
+ std::string locationString = pathToSchemaString(location);
+ assert(isList(location, name));
+
+ const auto& child = children(locationString).at(name);
+ const auto& list = boost::get<yang::list>(child);
+ return list.m_keys;
+}
+
+bool StaticSchema::isList(const path_& location, const std::string& name) const
+{
+ std::string locationString = pathToSchemaString(location);
+ if (!nodeExists(locationString, name))
+ return false;
+ const auto& child = children(locationString).at(name);
+ if (child.type() != typeid(yang::list))
+ return false;
+
+ return true;
+}
+
+void StaticSchema::addList(const std::string& location, const std::string& name, const std::set<std::string>& keys)
+{
+ m_nodes.at(location).emplace(name, yang::list{keys});
+
+ m_nodes.emplace(name, std::unordered_map<std::string, NodeType>());
+}
+
+bool StaticSchema::isPresenceContainer(const path_& location, const std::string& name) const
+{
+ if (!isContainer(location, name))
+ return false;
+ std::string locationString = pathToSchemaString(location);
+ return boost::get<yang::container>(children(locationString).at(name)).m_presence == yang::ContainerTraits::Presence;
+}
+
+void StaticSchema::addLeaf(const std::string& location, const std::string& name, const yang::LeafDataTypes& type)
+{
+ m_nodes.at(location).emplace(name, yang::leaf{type, {}});
+}
+
+void StaticSchema::addLeafEnum(const std::string& location, const std::string& name, std::set<std::string> enumValues)
+{
+ m_nodes.at(location).emplace(name, yang::leaf{yang::LeafDataTypes::Enum, enumValues});
+}
+
+bool StaticSchema::leafEnumHasValue(const path_& location, const std::string& name, const std::string& value) const
+{
+ std::string locationString = pathToSchemaString(location);
+ assert(isLeaf(location, name));
+
+ const auto& child = children(locationString).at(name);
+ const auto& list = boost::get<yang::leaf>(child);
+ return list.m_enumValues.find(value) != list.m_enumValues.end();
+}
+
+bool StaticSchema::isLeaf(const path_& location, const std::string& name) const
+{
+ std::string locationString = pathToSchemaString(location);
+ if (!nodeExists(locationString, name))
+ return false;
+
+ return children(locationString).at(name).type() == typeid(yang::leaf);
+}
+
+yang::LeafDataTypes StaticSchema::leafType(const path_& location, const std::string& name) const
+{
+ std::string locationString = pathToSchemaString(location);
+ return boost::get<yang::leaf>(children(locationString).at(name)).m_type;
+}
diff --git a/src/static_schema.hpp b/src/static_schema.hpp
new file mode 100644
index 0000000..bab8bde
--- /dev/null
+++ b/src/static_schema.hpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
+ * Copyright (C) 2018 FIT CVUT, https://fit.cvut.cz/
+ *
+ * Written by Václav Kubernát <kubervac@fit.cvut.cz>
+ *
+*/
+
+#pragma once
+
+#include <boost/variant.hpp>
+#include <set>
+#include <stdexcept>
+#include <unordered_map>
+#include "ast_path.hpp"
+#include "schema.hpp"
+
+
+/*! \class StaticSchema
+ * \brief Static schema, used mainly for testing
+ * */
+
+class StaticSchema : public Schema {
+public:
+ StaticSchema();
+
+ bool isContainer(const path_& location, const std::string& name) const override;
+ bool isLeaf(const path_& location, const std::string& name) const override;
+ bool isList(const path_& location, const std::string& name) const override;
+ bool isPresenceContainer(const path_& location, const std::string& name) const override;
+ bool leafEnumHasValue(const path_& location, const std::string& name, const std::string& value) const override;
+ bool listHasKey(const path_& location, const std::string& name, const std::string& key) const override;
+ bool nodeExists(const std::string& location, const std::string& name) const override;
+ const std::set<std::string>& listKeys(const path_& location, const std::string& name) const override;
+ yang::LeafDataTypes leafType(const path_& location, const std::string& name) const override;
+
+ void addContainer(const std::string& location, const std::string& name, yang::ContainerTraits isPresence = yang::ContainerTraits::None);
+ void addLeaf(const std::string& location, const std::string& name, const yang::LeafDataTypes& type);
+ void addLeafEnum(const std::string& location, const std::string& name, std::set<std::string> enumValues);
+ void addList(const std::string& location, const std::string& name, const std::set<std::string>& keys);
+
+private:
+ const std::unordered_map<std::string, NodeType>& children(const std::string& name) const;
+
+ std::unordered_map<std::string, std::unordered_map<std::string, NodeType>> m_nodes;
+};
diff --git a/tests/cd.cpp b/tests/cd.cpp
index 3ba1e2f..29187ff 100644
--- a/tests/cd.cpp
+++ b/tests/cd.cpp
@@ -9,11 +9,11 @@
#include "trompeloeil_catch.h"
#include "ast_commands.hpp"
#include "parser.hpp"
-#include "schema.hpp"
+#include "static_schema.hpp"
TEST_CASE("cd")
{
- auto schema = std::make_shared<Schema>();
+ auto schema = std::make_shared<StaticSchema>();
schema->addContainer("", "a");
schema->addContainer("", "b");
schema->addContainer("a", "a2");
diff --git a/tests/leaf_editing.cpp b/tests/leaf_editing.cpp
index 9ae2d97..b8c5591 100644
--- a/tests/leaf_editing.cpp
+++ b/tests/leaf_editing.cpp
@@ -9,11 +9,11 @@
#include "trompeloeil_catch.h"
#include "ast_commands.hpp"
#include "parser.hpp"
-#include "schema.hpp"
+#include "static_schema.hpp"
TEST_CASE("leaf editing")
{
- auto schema = std::make_shared<Schema>();
+ auto schema = std::make_shared<StaticSchema>();
schema->addContainer("", "contA");
schema->addLeaf("", "leafString", yang::LeafDataTypes::String);
schema->addLeaf("", "leafDecimal", yang::LeafDataTypes::Decimal);
diff --git a/tests/presence_containers.cpp b/tests/presence_containers.cpp
index 0a678fb..87957cb 100644
--- a/tests/presence_containers.cpp
+++ b/tests/presence_containers.cpp
@@ -10,11 +10,11 @@
#include "trompeloeil_catch.h"
#include "ast_commands.hpp"
#include "parser.hpp"
-#include "schema.hpp"
+#include "static_schema.hpp"
TEST_CASE("presence containers")
{
- auto schema = std::make_shared<Schema>();
+ auto schema = std::make_shared<StaticSchema>();
schema->addContainer("", "a", yang::ContainerTraits::Presence);
schema->addContainer("", "b");
schema->addContainer("a", "a2");