blob: a3649aea11f0d98326e2cb25ebfb5c14f6836c43 [file] [log] [blame]
Václav Kubernátbddbb172018-06-13 16:27:39 +02001/*
2 * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
3 * Copyright (C) 2018 FIT CVUT, https://fit.cvut.cz/
4 *
5 * Written by Václav Kubernát <kubervac@fit.cvut.cz>
6 *
7*/
8
9#include "static_schema.hpp"
10#include "utils.hpp"
11
12InvalidNodeException::~InvalidNodeException() = default;
13
14StaticSchema::StaticSchema()
15{
16 m_nodes.emplace("", std::unordered_map<std::string, NodeType>());
17}
18
19const std::unordered_map<std::string, NodeType>& StaticSchema::children(const std::string& name) const
20{
21 return m_nodes.at(name);
22}
23
Václav Kubernát744f57f2018-06-29 22:46:26 +020024bool StaticSchema::nodeExists(const std::string& location, const std::string& node) const
Václav Kubernátbddbb172018-06-13 16:27:39 +020025{
Václav Kubernát744f57f2018-06-29 22:46:26 +020026 if (node.empty())
Václav Kubernátbddbb172018-06-13 16:27:39 +020027 return true;
28 const auto& childrenRef = children(location);
29
Václav Kubernát744f57f2018-06-29 22:46:26 +020030 return childrenRef.find(node) != childrenRef.end();
Václav Kubernátbddbb172018-06-13 16:27:39 +020031}
32
Václav Kubernát2eaceb82018-10-08 19:56:30 +020033bool StaticSchema::isModule(const schemaPath_&, const std::string& name) const
Václav Kubernátbddbb172018-06-13 16:27:39 +020034{
Václav Kubernát744f57f2018-06-29 22:46:26 +020035 return m_modules.find(name) != m_modules.end();
36}
37
Václav Kubernát2eaceb82018-10-08 19:56:30 +020038bool StaticSchema::isContainer(const schemaPath_& location, const ModuleNodePair& node) const
Václav Kubernát744f57f2018-06-29 22:46:26 +020039{
40 std::string locationString = pathToAbsoluteSchemaString(location);
41 auto fullName = fullNodeName(location, node);
42 if (!nodeExists(locationString, fullName))
Václav Kubernátbddbb172018-06-13 16:27:39 +020043 return false;
44
Václav Kubernát744f57f2018-06-29 22:46:26 +020045 return children(locationString).at(fullName).type() == typeid(yang::container);
Václav Kubernátbddbb172018-06-13 16:27:39 +020046}
47
48void StaticSchema::addContainer(const std::string& location, const std::string& name, yang::ContainerTraits isPresence)
49{
50 m_nodes.at(location).emplace(name, yang::container{isPresence});
51
52 //create a new set of children for the new node
53 std::string key = joinPaths(location, name);
54 m_nodes.emplace(key, std::unordered_map<std::string, NodeType>());
55}
56
Václav Kubernát2eaceb82018-10-08 19:56:30 +020057bool StaticSchema::listHasKey(const schemaPath_& location, const ModuleNodePair& node, const std::string& key) const
Václav Kubernátbddbb172018-06-13 16:27:39 +020058{
Václav Kubernát744f57f2018-06-29 22:46:26 +020059 std::string locationString = pathToAbsoluteSchemaString(location);
60 assert(isList(location, node));
Václav Kubernátbddbb172018-06-13 16:27:39 +020061
Václav Kubernát744f57f2018-06-29 22:46:26 +020062 const auto& child = children(locationString).at(fullNodeName(location, node));
Václav Kubernátbddbb172018-06-13 16:27:39 +020063 const auto& list = boost::get<yang::list>(child);
64 return list.m_keys.find(key) != list.m_keys.end();
65}
66
Václav Kubernát2eaceb82018-10-08 19:56:30 +020067const std::set<std::string> StaticSchema::listKeys(const schemaPath_& location, const ModuleNodePair& node) const
Václav Kubernátbddbb172018-06-13 16:27:39 +020068{
Václav Kubernát744f57f2018-06-29 22:46:26 +020069 std::string locationString = pathToAbsoluteSchemaString(location);
70 assert(isList(location, node));
Václav Kubernátbddbb172018-06-13 16:27:39 +020071
Václav Kubernát744f57f2018-06-29 22:46:26 +020072 const auto& child = children(locationString).at(fullNodeName(location, node));
Václav Kubernátbddbb172018-06-13 16:27:39 +020073 const auto& list = boost::get<yang::list>(child);
74 return list.m_keys;
75}
76
Václav Kubernát2eaceb82018-10-08 19:56:30 +020077bool StaticSchema::isList(const schemaPath_& location, const ModuleNodePair& node) const
Václav Kubernátbddbb172018-06-13 16:27:39 +020078{
Václav Kubernát744f57f2018-06-29 22:46:26 +020079 std::string locationString = pathToAbsoluteSchemaString(location);
80 auto fullName = fullNodeName(location, node);
81 if (!nodeExists(locationString, fullName))
Václav Kubernátbddbb172018-06-13 16:27:39 +020082 return false;
Václav Kubernát744f57f2018-06-29 22:46:26 +020083 const auto& child = children(locationString).at(fullName);
Václav Kubernátbddbb172018-06-13 16:27:39 +020084 if (child.type() != typeid(yang::list))
85 return false;
86
87 return true;
88}
89
90void StaticSchema::addList(const std::string& location, const std::string& name, const std::set<std::string>& keys)
91{
92 m_nodes.at(location).emplace(name, yang::list{keys});
93
94 m_nodes.emplace(name, std::unordered_map<std::string, NodeType>());
95}
96
Václav Kubernát2eaceb82018-10-08 19:56:30 +020097bool StaticSchema::isPresenceContainer(const schemaPath_& location, const ModuleNodePair& node) const
Václav Kubernátbddbb172018-06-13 16:27:39 +020098{
Václav Kubernát744f57f2018-06-29 22:46:26 +020099 if (!isContainer(location, node))
Václav Kubernátbddbb172018-06-13 16:27:39 +0200100 return false;
Václav Kubernát744f57f2018-06-29 22:46:26 +0200101 std::string locationString = pathToAbsoluteSchemaString(location);
102 return boost::get<yang::container>(children(locationString).at(fullNodeName(location, node))).m_presence == yang::ContainerTraits::Presence;
Václav Kubernátbddbb172018-06-13 16:27:39 +0200103}
104
105void StaticSchema::addLeaf(const std::string& location, const std::string& name, const yang::LeafDataTypes& type)
106{
Václav Kubernáteeb38842019-03-20 19:46:05 +0100107 m_nodes.at(location).emplace(name, yang::leaf{type, {}, {}});
Václav Kubernátbddbb172018-06-13 16:27:39 +0200108}
109
110void StaticSchema::addLeafEnum(const std::string& location, const std::string& name, std::set<std::string> enumValues)
111{
Václav Kubernáteeb38842019-03-20 19:46:05 +0100112 yang::leaf toAdd;
113 toAdd.m_type = yang::LeafDataTypes::Enum;
114 toAdd.m_enumValues = enumValues;
115 m_nodes.at(location).emplace(name, toAdd);
116}
117
118void StaticSchema::addLeafIdentityRef(const std::string& location, const std::string& name, const ModuleValuePair& base)
119{
120 assert(base.first); // base identity cannot have an empty module
121 yang::leaf toAdd;
122 toAdd.m_type = yang::LeafDataTypes::IdentityRef;
123 toAdd.m_identBase = base;
124 m_nodes.at(location).emplace(name, toAdd);
Václav Kubernátbddbb172018-06-13 16:27:39 +0200125}
126
Václav Kubernát744f57f2018-06-29 22:46:26 +0200127void StaticSchema::addModule(const std::string& name)
Václav Kubernátbddbb172018-06-13 16:27:39 +0200128{
Václav Kubernát744f57f2018-06-29 22:46:26 +0200129 m_modules.emplace(name);
130}
Václav Kubernátbddbb172018-06-13 16:27:39 +0200131
Václav Kubernáteeb38842019-03-20 19:46:05 +0100132void StaticSchema::addIdentity(const std::optional<ModuleValuePair>& base, const ModuleValuePair& name)
133{
134 if (base)
135 m_identities.at(base.value()).emplace(name);
136
137 m_identities.emplace(name, std::set<ModuleValuePair>());
138}
Václav Kubernát744f57f2018-06-29 22:46:26 +0200139
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200140bool StaticSchema::leafEnumHasValue(const schemaPath_& location, const ModuleNodePair& node, const std::string& value) const
Václav Kubernát744f57f2018-06-29 22:46:26 +0200141{
Václav Kubernát989b5de2019-02-20 16:28:35 +0100142 auto enums = enumValues(location, node);
143 return enums.find(value) != enums.end();
Václav Kubernátbddbb172018-06-13 16:27:39 +0200144}
145
Václav Kubernáteeb38842019-03-20 19:46:05 +0100146void StaticSchema::getIdentSet(const ModuleValuePair& ident, std::set<ModuleValuePair>& res) const
147{
148 res.insert(ident);
149 auto derivedIdentities = m_identities.at(ident);
150 for (auto it : derivedIdentities) {
151 getIdentSet(it, res);
152 }
153}
154
155const std::set<std::string> StaticSchema::validIdentities(const schemaPath_& location, const ModuleNodePair& node, const Prefixes prefixes) const
156{
157 std::string locationString = pathToAbsoluteSchemaString(location);
158 assert(isLeaf(location, node));
159
160 const auto& child = children(locationString).at(fullNodeName(location, node));
161 const auto& leaf = boost::get<yang::leaf>(child);
162
163 std::set<ModuleValuePair> identSet;
164 getIdentSet(leaf.m_identBase, identSet);
165
166 std::set<std::string> res;
167 std::transform(identSet.begin(), identSet.end(), std::inserter(res, res.end()), [location, node, prefixes](const auto& it) {
168 auto topLevelModule = location.m_nodes.empty() ? node.first.get() : location.m_nodes.front().m_prefix.get().m_name;
169 std::string stringIdent;
170 if (prefixes == Prefixes::Always || (it.first && it.first.value() != topLevelModule)) {
171 stringIdent += it.first ? it.first.value() : topLevelModule;
172 stringIdent += ":";
173 }
174 stringIdent += it.second;
175 return stringIdent;
176 });
177
178 return res;
179}
180
181bool StaticSchema::leafIdentityIsValid(const schemaPath_& location, const ModuleNodePair& node, const ModuleValuePair& value) const
182{
183 auto identities = validIdentities(location, node, Prefixes::Always);
184
185 auto topLevelModule = location.m_nodes.empty() ? node.first.get() : location.m_nodes.front().m_prefix.get().m_name;
186 auto identModule = value.first ? value.first.value() : topLevelModule;
187 return std::any_of(identities.begin(), identities.end(), [identModule, value](const auto& x) { return x == identModule + ":" + value.second; });
188}
189
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200190bool StaticSchema::isLeaf(const schemaPath_& location, const ModuleNodePair& node) const
Václav Kubernátbddbb172018-06-13 16:27:39 +0200191{
Václav Kubernát744f57f2018-06-29 22:46:26 +0200192 std::string locationString = pathToAbsoluteSchemaString(location);
193 auto fullName = fullNodeName(location, node);
194 if (!nodeExists(locationString, fullName))
Václav Kubernátbddbb172018-06-13 16:27:39 +0200195 return false;
196
Václav Kubernát744f57f2018-06-29 22:46:26 +0200197 return children(locationString).at(fullName).type() == typeid(yang::leaf);
Václav Kubernátbddbb172018-06-13 16:27:39 +0200198}
199
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200200yang::LeafDataTypes StaticSchema::leafType(const schemaPath_& location, const ModuleNodePair& node) const
Václav Kubernátbddbb172018-06-13 16:27:39 +0200201{
Václav Kubernát744f57f2018-06-29 22:46:26 +0200202 std::string locationString = pathToAbsoluteSchemaString(location);
203 return boost::get<yang::leaf>(children(locationString).at(fullNodeName(location, node))).m_type;
204}
205
Václav Kubernát989b5de2019-02-20 16:28:35 +0100206const std::set<std::string> StaticSchema::enumValues(const schemaPath_& location, const ModuleNodePair& node) const
207{
208 std::string locationString = pathToAbsoluteSchemaString(location);
209 assert(isLeaf(location, node));
210
211 const auto& child = children(locationString).at(fullNodeName(location, node));
212 const auto& leaf = boost::get<yang::leaf>(child);
213 return leaf.m_enumValues;
214}
215
Václav Kubernáte7d4aea2018-09-11 18:15:48 +0200216// We do not test StaticSchema, so we don't need to implement recursive childNodes
217// for this class.
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200218std::set<std::string> StaticSchema::childNodes(const schemaPath_& path, const Recursion) const
Václav Kubernát744f57f2018-06-29 22:46:26 +0200219{
220 std::string locationString = pathToAbsoluteSchemaString(path);
221 std::set<std::string> res;
222
223 auto childrenRef = children(locationString);
224
225 std::transform(childrenRef.begin(), childrenRef.end(),
226 std::inserter(res, res.end()),
227 [] (auto it) { return it.first; });
228 return res;
Václav Kubernátbddbb172018-06-13 16:27:39 +0200229}