blob: 22c18241c01b865cc48b2deb4910304bcfcf0954 [file] [log] [blame]
Václav Kubernát96344a12018-05-28 16:33: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
Václav Kubernát509ce652019-05-29 19:46:44 +02009#include <boost/mpl/for_each.hpp>
Václav Kubernátb61336d2018-05-28 17:35:03 +020010#include <iostream>
Václav Kubernát9cfcd872020-02-18 12:34:02 +010011#include <sstream>
Václav Kubernát6415b822018-08-22 17:40:01 +020012#include "datastore_access.hpp"
Václav Kubernát96344a12018-05-28 16:33:39 +020013#include "interpreter.hpp"
Václav Kubernát509ce652019-05-29 19:46:44 +020014#include "utils.hpp"
Václav Kubernát96344a12018-05-28 16:33:39 +020015
Václav Kubernát812ee282018-08-30 17:10:03 +020016void Interpreter::operator()(const commit_&) const
17{
18 m_datastore.commitChanges();
19}
20
Václav Kubernát6d791432018-10-25 16:00:35 +020021void Interpreter::operator()(const discard_&) const
22{
23 m_datastore.discardChanges();
24}
25
Václav Kubernát07204242018-06-04 18:12:09 +020026void Interpreter::operator()(const set_& set) const
27{
Václav Kubernáteeb38842019-03-20 19:46:05 +010028 auto data = set.m_data;
29
30 // If the user didn't supply a module prefix for identityref, we need to add it ourselves
31 if (data.type() == typeid(identityRef_)) {
32 auto identityRef = boost::get<identityRef_>(data);
33 if (!identityRef.m_prefix) {
34 identityRef.m_prefix = set.m_path.m_nodes.front().m_prefix.value();
35 data = identityRef;
36 }
37 }
38 m_datastore.setLeaf(absolutePathFromCommand(set), data);
Václav Kubernát07204242018-06-04 18:12:09 +020039}
40
Václav Kubernátb6ff0b62018-08-30 16:14:53 +020041void Interpreter::operator()(const get_& get) const
42{
43 auto items = m_datastore.getItems(absolutePathFromCommand(get));
44 for (auto it : items) {
Václav Kubernát9b725992019-05-29 16:39:47 +020045 std::cout << it.first << " = " << leafDataToString(it.second) << std::endl;
Václav Kubernátb6ff0b62018-08-30 16:14:53 +020046 }
47}
48
Václav Kubernát96344a12018-05-28 16:33:39 +020049void Interpreter::operator()(const cd_& cd) const
50{
51 m_parser.changeNode(cd.m_path);
52}
53
Václav Kubernátb61336d2018-05-28 17:35:03 +020054void Interpreter::operator()(const create_& create) const
55{
Václav Kubernátbe228622019-05-23 14:44:12 +020056 if (create.m_path.m_nodes.back().m_suffix.type() == typeid(listElement_))
57 m_datastore.createListInstance(absolutePathFromCommand(create));
58 else
59 m_datastore.createPresenceContainer(absolutePathFromCommand(create));
Václav Kubernátb61336d2018-05-28 17:35:03 +020060}
61
62void Interpreter::operator()(const delete_& delet) const
63{
Václav Kubernátf5f64f02019-03-19 17:15:47 +010064 if (delet.m_path.m_nodes.back().m_suffix.type() == typeid(container_))
65 m_datastore.deletePresenceContainer(absolutePathFromCommand(delet));
66 else
67 m_datastore.deleteListInstance(absolutePathFromCommand(delet));
Václav Kubernátb61336d2018-05-28 17:35:03 +020068}
69
Václav Kubernát11afac72018-07-18 14:59:53 +020070void Interpreter::operator()(const ls_& ls) const
71{
72 std::cout << "Possible nodes:" << std::endl;
Václav Kubernáte7d4aea2018-09-11 18:15:48 +020073 auto recursion{Recursion::NonRecursive};
74 for (auto it : ls.m_options) {
75 if (it == LsOption::Recursive)
76 recursion = Recursion::Recursive;
77 }
Václav Kubernát11afac72018-07-18 14:59:53 +020078
Václav Kubernáte7d4aea2018-09-11 18:15:48 +020079 for (const auto& it : m_parser.availableNodes(ls.m_path, recursion))
Václav Kubernát11afac72018-07-18 14:59:53 +020080 std::cout << it << std::endl;
81}
82
Václav Kubernát7160a132020-04-03 02:11:01 +020083void Interpreter::operator()(const copy_& copy) const
84{
85 m_datastore.copyConfig(copy.m_source, copy.m_destination);
86}
87
Václav Kubernát9cfcd872020-02-18 12:34:02 +010088std::string Interpreter::buildTypeInfo(const std::string& path) const
89{
90 std::ostringstream ss;
91 switch (m_datastore.schema()->nodeType(path)) {
92 case yang::NodeTypes::Container:
93 ss << "container";
94 break;
95 case yang::NodeTypes::PresenceContainer:
96 ss << "presence container";
97 break;
98 case yang::NodeTypes::Leaf:
99 {
100 auto leafType = m_datastore.schema()->leafType(path);
101 auto typedefName = m_datastore.schema()->leafTypeName(path);
102 std::string baseTypeStr;
Václav Kubernát13b23d72020-04-16 21:49:51 +0200103 if (std::holds_alternative<yang::LeafRef>(leafType.m_type)) {
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100104 ss << "-> ";
105 ss << m_datastore.schema()->leafrefPath(path) << " ";
Václav Kubernát13b23d72020-04-16 21:49:51 +0200106 baseTypeStr = leafDataTypeToString(std::get<yang::LeafRef>(leafType.m_type).m_targetType->m_type);
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100107 } else {
Václav Kubernát13b23d72020-04-16 21:49:51 +0200108 baseTypeStr = leafDataTypeToString(leafType.m_type);
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100109 }
110
111 if (typedefName) {
112 ss << *typedefName << " (" << baseTypeStr << ")";
113 } else {
114 ss << baseTypeStr;
115 }
116
Václav Kubernát13b23d72020-04-16 21:49:51 +0200117 if (leafType.m_units) {
118 ss << " [" + *leafType.m_units + "]";
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100119 }
120
121 if (m_datastore.schema()->leafIsKey(path)) {
122 ss << " (key)";
123 }
124 break;
125 }
126 case yang::NodeTypes::List:
127 ss << "list";
128 break;
129 }
130 return ss.str();
131}
132
133void Interpreter::operator()(const describe_& describe) const
134{
135 auto path = absolutePathFromCommand(describe);
136 std::cout << path << ": " << buildTypeInfo(path) << std::endl;
137 if (auto description = m_datastore.schema()->description(path)) {
138 std::cout << std::endl << *description << std::endl;
139 }
140}
141
Václav Kubernát054cc992019-02-21 14:23:52 +0100142struct commandLongHelpVisitor : boost::static_visitor<const char*> {
143 template <typename T>
144 auto constexpr operator()(boost::type<T>) const
145 {
146 return T::longHelp;
147 }
148};
149
150struct commandShortHelpVisitor : boost::static_visitor<const char*> {
151 template <typename T>
152 auto constexpr operator()(boost::type<T>) const
153 {
154 return T::shortHelp;
155 }
156};
157
158void Interpreter::operator()(const help_& help) const
159{
160 if (help.m_cmd)
161 std::cout << boost::apply_visitor(commandLongHelpVisitor(), help.m_cmd.get()) << std::endl;
162 else
163 boost::mpl::for_each<CommandTypes, boost::type<boost::mpl::_>>([](auto cmd) {
164 std::cout << commandShortHelpVisitor()(cmd) << std::endl;
165 });
166}
167
Václav Kubernát6415b822018-08-22 17:40:01 +0200168template <typename T>
169std::string Interpreter::absolutePathFromCommand(const T& command) const
170{
Václav Kubernát37171a12018-08-31 17:01:48 +0200171 if (command.m_path.m_scope == Scope::Absolute)
Václav Kubernátefcac932020-01-10 15:26:32 +0100172 return pathToDataString(command.m_path, Prefixes::WhenNeeded);
Václav Kubernát37171a12018-08-31 17:01:48 +0200173 else
Václav Kubernátefcac932020-01-10 15:26:32 +0100174 return joinPaths(m_parser.currentNode(), pathToDataString(command.m_path, Prefixes::WhenNeeded));
Václav Kubernát6415b822018-08-22 17:40:01 +0200175}
176
Václav Kubernát5c75b252018-10-10 18:33:47 +0200177struct pathToStringVisitor : boost::static_visitor<std::string> {
178 std::string operator()(const schemaPath_& path) const
179 {
Václav Kubernátefcac932020-01-10 15:26:32 +0100180 return pathToSchemaString(path, Prefixes::WhenNeeded);
Václav Kubernát5c75b252018-10-10 18:33:47 +0200181 }
182 std::string operator()(const dataPath_& path) const
183 {
Václav Kubernátefcac932020-01-10 15:26:32 +0100184 return pathToDataString(path, Prefixes::WhenNeeded);
Václav Kubernát5c75b252018-10-10 18:33:47 +0200185 }
186};
187
188struct getPathScopeVisitor : boost::static_visitor<Scope> {
189 template <typename T>
190 Scope operator()(const T& path) const
191 {
192 return path.m_scope;
193 }
194};
195
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200196std::string Interpreter::absolutePathFromCommand(const get_& get) const
197{
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200198 using namespace std::string_literals;
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200199 if (!get.m_path) {
200 return m_parser.currentNode();
Václav Kubernát5c75b252018-10-10 18:33:47 +0200201 }
202
203 const auto path = *get.m_path;
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200204 if (path.type() == typeid(module_)) {
205 return "/"s + boost::get<module_>(path).m_name + ":*";
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200206 } else {
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200207 auto actualPath = boost::get<boost::variant<dataPath_, schemaPath_>>(path);
208 std::string pathString = boost::apply_visitor(pathToStringVisitor(), actualPath);
209 auto pathScope{boost::apply_visitor(getPathScopeVisitor(), actualPath)};
210
211 if (pathScope == Scope::Absolute) {
Václav Kubernát82684cf2020-01-06 13:30:37 +0100212 return pathString;
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200213 } else {
214 return joinPaths(m_parser.currentNode(), pathString);
215 }
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200216 }
217}
218
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100219std::string Interpreter::absolutePathFromCommand(const describe_& describe) const
220{
221 auto pathStr = boost::apply_visitor(pathToStringVisitor(), describe.m_path);
222 if (boost::apply_visitor(getPathScopeVisitor(), describe.m_path) == Scope::Absolute)
223 return pathStr;
224 else
225 return joinPaths(m_parser.currentNode(), pathStr);
226}
227
Václav Kubernát6415b822018-08-22 17:40:01 +0200228Interpreter::Interpreter(Parser& parser, DatastoreAccess& datastore)
Václav Kubernát812ee282018-08-30 17:10:03 +0200229 : m_parser(parser)
230 , m_datastore(datastore)
Václav Kubernát96344a12018-05-28 16:33:39 +0200231{
232}