blob: 3c3fcede240523fed4d559181fbf4523e57e8591 [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
Václav Kubernát1446fe12019-10-02 19:32:51 +020094 std::string key = joinPaths(location, name);
95 m_nodes.emplace(key, std::unordered_map<std::string, NodeType>());
Václav Kubernátbddbb172018-06-13 16:27:39 +020096}
97
Václav Kubernát2eaceb82018-10-08 19:56:30 +020098bool StaticSchema::isPresenceContainer(const schemaPath_& location, const ModuleNodePair& node) const
Václav Kubernátbddbb172018-06-13 16:27:39 +020099{
Václav Kubernát744f57f2018-06-29 22:46:26 +0200100 if (!isContainer(location, node))
Václav Kubernátbddbb172018-06-13 16:27:39 +0200101 return false;
Václav Kubernát744f57f2018-06-29 22:46:26 +0200102 std::string locationString = pathToAbsoluteSchemaString(location);
103 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 +0200104}
105
106void StaticSchema::addLeaf(const std::string& location, const std::string& name, const yang::LeafDataTypes& type)
107{
Václav Kubernát6a8d1d92019-04-24 20:30:36 +0200108 m_nodes.at(location).emplace(name, yang::leaf{type, {}, {}, {}});
Václav Kubernátbddbb172018-06-13 16:27:39 +0200109}
110
111void StaticSchema::addLeafEnum(const std::string& location, const std::string& name, std::set<std::string> enumValues)
112{
Václav Kubernáteeb38842019-03-20 19:46:05 +0100113 yang::leaf toAdd;
114 toAdd.m_type = yang::LeafDataTypes::Enum;
115 toAdd.m_enumValues = enumValues;
116 m_nodes.at(location).emplace(name, toAdd);
117}
118
119void StaticSchema::addLeafIdentityRef(const std::string& location, const std::string& name, const ModuleValuePair& base)
120{
121 assert(base.first); // base identity cannot have an empty module
122 yang::leaf toAdd;
123 toAdd.m_type = yang::LeafDataTypes::IdentityRef;
124 toAdd.m_identBase = base;
125 m_nodes.at(location).emplace(name, toAdd);
Václav Kubernátbddbb172018-06-13 16:27:39 +0200126}
127
Václav Kubernát6a8d1d92019-04-24 20:30:36 +0200128void StaticSchema::addLeafRef(const std::string& location, const std::string& name, const std::string& source)
129{
130 yang::leaf toAdd;
131 toAdd.m_type = yang::LeafDataTypes::LeafRef;
132 toAdd.m_leafRefSource = source;
133 m_nodes.at(location).emplace(name, toAdd);
134}
135
Václav Kubernát744f57f2018-06-29 22:46:26 +0200136void StaticSchema::addModule(const std::string& name)
Václav Kubernátbddbb172018-06-13 16:27:39 +0200137{
Václav Kubernát744f57f2018-06-29 22:46:26 +0200138 m_modules.emplace(name);
139}
Václav Kubernátbddbb172018-06-13 16:27:39 +0200140
Václav Kubernáteeb38842019-03-20 19:46:05 +0100141void StaticSchema::addIdentity(const std::optional<ModuleValuePair>& base, const ModuleValuePair& name)
142{
143 if (base)
144 m_identities.at(base.value()).emplace(name);
145
146 m_identities.emplace(name, std::set<ModuleValuePair>());
147}
Václav Kubernát744f57f2018-06-29 22:46:26 +0200148
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200149bool StaticSchema::leafEnumHasValue(const schemaPath_& location, const ModuleNodePair& node, const std::string& value) const
Václav Kubernát744f57f2018-06-29 22:46:26 +0200150{
Václav Kubernát989b5de2019-02-20 16:28:35 +0100151 auto enums = enumValues(location, node);
152 return enums.find(value) != enums.end();
Václav Kubernátbddbb172018-06-13 16:27:39 +0200153}
154
Václav Kubernáteeb38842019-03-20 19:46:05 +0100155void StaticSchema::getIdentSet(const ModuleValuePair& ident, std::set<ModuleValuePair>& res) const
156{
157 res.insert(ident);
158 auto derivedIdentities = m_identities.at(ident);
159 for (auto it : derivedIdentities) {
160 getIdentSet(it, res);
161 }
162}
163
164const std::set<std::string> StaticSchema::validIdentities(const schemaPath_& location, const ModuleNodePair& node, const Prefixes prefixes) const
165{
166 std::string locationString = pathToAbsoluteSchemaString(location);
167 assert(isLeaf(location, node));
168
169 const auto& child = children(locationString).at(fullNodeName(location, node));
170 const auto& leaf = boost::get<yang::leaf>(child);
171
172 std::set<ModuleValuePair> identSet;
173 getIdentSet(leaf.m_identBase, identSet);
174
175 std::set<std::string> res;
176 std::transform(identSet.begin(), identSet.end(), std::inserter(res, res.end()), [location, node, prefixes](const auto& it) {
177 auto topLevelModule = location.m_nodes.empty() ? node.first.get() : location.m_nodes.front().m_prefix.get().m_name;
178 std::string stringIdent;
179 if (prefixes == Prefixes::Always || (it.first && it.first.value() != topLevelModule)) {
180 stringIdent += it.first ? it.first.value() : topLevelModule;
181 stringIdent += ":";
182 }
183 stringIdent += it.second;
184 return stringIdent;
185 });
186
187 return res;
188}
189
190bool StaticSchema::leafIdentityIsValid(const schemaPath_& location, const ModuleNodePair& node, const ModuleValuePair& value) const
191{
192 auto identities = validIdentities(location, node, Prefixes::Always);
193
194 auto topLevelModule = location.m_nodes.empty() ? node.first.get() : location.m_nodes.front().m_prefix.get().m_name;
195 auto identModule = value.first ? value.first.value() : topLevelModule;
Václav Kubernát1bf704e2019-04-12 13:30:50 +0200196 return std::any_of(identities.begin(), identities.end(), [toFind = identModule + ":" + value.second](const auto& x) { return x == toFind; });
Václav Kubernáteeb38842019-03-20 19:46:05 +0100197}
198
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200199bool StaticSchema::isLeaf(const schemaPath_& location, const ModuleNodePair& node) const
Václav Kubernátbddbb172018-06-13 16:27:39 +0200200{
Václav Kubernát744f57f2018-06-29 22:46:26 +0200201 std::string locationString = pathToAbsoluteSchemaString(location);
202 auto fullName = fullNodeName(location, node);
203 if (!nodeExists(locationString, fullName))
Václav Kubernátbddbb172018-06-13 16:27:39 +0200204 return false;
205
Václav Kubernát744f57f2018-06-29 22:46:26 +0200206 return children(locationString).at(fullName).type() == typeid(yang::leaf);
Václav Kubernátbddbb172018-06-13 16:27:39 +0200207}
208
Václav Kubernát6a8d1d92019-04-24 20:30:36 +0200209std::string lastNodeOfSchemaPath(const std::string& path)
210{
211 std::string res = path;
212 auto pos = res.find_last_of('/');
213 if (pos != res.npos)
214 res.erase(0, pos);
215 return res;
216}
217
218yang::LeafDataTypes StaticSchema::leafrefBase(const schemaPath_& location, const ModuleNodePair& node) const
219{
220 std::string locationString = pathToAbsoluteSchemaString(location);
221 auto leaf{boost::get<yang::leaf>(children(locationString).at(fullNodeName(location, node)))};
222 auto locationOfSource = stripLastNodeFromPath(leaf.m_leafRefSource);
223 auto nameOfSource = lastNodeOfSchemaPath(leaf.m_leafRefSource);
224 return boost::get<yang::leaf>(children(locationOfSource).at(nameOfSource)).m_type;
225}
226
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200227yang::LeafDataTypes StaticSchema::leafType(const schemaPath_& location, const ModuleNodePair& node) const
Václav Kubernátbddbb172018-06-13 16:27:39 +0200228{
Václav Kubernát744f57f2018-06-29 22:46:26 +0200229 std::string locationString = pathToAbsoluteSchemaString(location);
230 return boost::get<yang::leaf>(children(locationString).at(fullNodeName(location, node))).m_type;
231}
232
Václav Kubernát989b5de2019-02-20 16:28:35 +0100233const std::set<std::string> StaticSchema::enumValues(const schemaPath_& location, const ModuleNodePair& node) const
234{
235 std::string locationString = pathToAbsoluteSchemaString(location);
236 assert(isLeaf(location, node));
237
238 const auto& child = children(locationString).at(fullNodeName(location, node));
239 const auto& leaf = boost::get<yang::leaf>(child);
240 return leaf.m_enumValues;
241}
242
Václav Kubernáte7d4aea2018-09-11 18:15:48 +0200243// We do not test StaticSchema, so we don't need to implement recursive childNodes
244// for this class.
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200245std::set<std::string> StaticSchema::childNodes(const schemaPath_& path, const Recursion) const
Václav Kubernát744f57f2018-06-29 22:46:26 +0200246{
247 std::string locationString = pathToAbsoluteSchemaString(path);
248 std::set<std::string> res;
249
250 auto childrenRef = children(locationString);
251
252 std::transform(childrenRef.begin(), childrenRef.end(),
253 std::inserter(res, res.end()),
254 [] (auto it) { return it.first; });
255 return res;
Václav Kubernátbddbb172018-06-13 16:27:39 +0200256}