blob: f3fde9e22f3efb021412b3ec8927e3c7eb7e4074 [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 }
Václav Kubernát0599e9f2020-04-21 09:51:33 +0200130
131 if (!m_datastore.schema()->isConfig(path)) {
132 ss << " (ro)";
133 }
134
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100135 return ss.str();
136}
137
138void Interpreter::operator()(const describe_& describe) const
139{
140 auto path = absolutePathFromCommand(describe);
141 std::cout << path << ": " << buildTypeInfo(path) << std::endl;
142 if (auto description = m_datastore.schema()->description(path)) {
143 std::cout << std::endl << *description << std::endl;
144 }
145}
146
Václav Kubernát054cc992019-02-21 14:23:52 +0100147struct commandLongHelpVisitor : boost::static_visitor<const char*> {
148 template <typename T>
149 auto constexpr operator()(boost::type<T>) const
150 {
151 return T::longHelp;
152 }
153};
154
155struct commandShortHelpVisitor : boost::static_visitor<const char*> {
156 template <typename T>
157 auto constexpr operator()(boost::type<T>) const
158 {
159 return T::shortHelp;
160 }
161};
162
163void Interpreter::operator()(const help_& help) const
164{
165 if (help.m_cmd)
166 std::cout << boost::apply_visitor(commandLongHelpVisitor(), help.m_cmd.get()) << std::endl;
167 else
168 boost::mpl::for_each<CommandTypes, boost::type<boost::mpl::_>>([](auto cmd) {
169 std::cout << commandShortHelpVisitor()(cmd) << std::endl;
170 });
171}
172
Václav Kubernát6415b822018-08-22 17:40:01 +0200173template <typename T>
174std::string Interpreter::absolutePathFromCommand(const T& command) const
175{
Václav Kubernát37171a12018-08-31 17:01:48 +0200176 if (command.m_path.m_scope == Scope::Absolute)
Václav Kubernátefcac932020-01-10 15:26:32 +0100177 return pathToDataString(command.m_path, Prefixes::WhenNeeded);
Václav Kubernát37171a12018-08-31 17:01:48 +0200178 else
Václav Kubernátefcac932020-01-10 15:26:32 +0100179 return joinPaths(m_parser.currentNode(), pathToDataString(command.m_path, Prefixes::WhenNeeded));
Václav Kubernát6415b822018-08-22 17:40:01 +0200180}
181
Václav Kubernát5c75b252018-10-10 18:33:47 +0200182struct pathToStringVisitor : boost::static_visitor<std::string> {
183 std::string operator()(const schemaPath_& path) const
184 {
Václav Kubernátefcac932020-01-10 15:26:32 +0100185 return pathToSchemaString(path, Prefixes::WhenNeeded);
Václav Kubernát5c75b252018-10-10 18:33:47 +0200186 }
187 std::string operator()(const dataPath_& path) const
188 {
Václav Kubernátefcac932020-01-10 15:26:32 +0100189 return pathToDataString(path, Prefixes::WhenNeeded);
Václav Kubernát5c75b252018-10-10 18:33:47 +0200190 }
191};
192
193struct getPathScopeVisitor : boost::static_visitor<Scope> {
194 template <typename T>
195 Scope operator()(const T& path) const
196 {
197 return path.m_scope;
198 }
199};
200
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200201std::string Interpreter::absolutePathFromCommand(const get_& get) const
202{
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200203 using namespace std::string_literals;
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200204 if (!get.m_path) {
205 return m_parser.currentNode();
Václav Kubernát5c75b252018-10-10 18:33:47 +0200206 }
207
208 const auto path = *get.m_path;
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200209 if (path.type() == typeid(module_)) {
210 return "/"s + boost::get<module_>(path).m_name + ":*";
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200211 } else {
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200212 auto actualPath = boost::get<boost::variant<dataPath_, schemaPath_>>(path);
213 std::string pathString = boost::apply_visitor(pathToStringVisitor(), actualPath);
214 auto pathScope{boost::apply_visitor(getPathScopeVisitor(), actualPath)};
215
216 if (pathScope == Scope::Absolute) {
Václav Kubernát82684cf2020-01-06 13:30:37 +0100217 return pathString;
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200218 } else {
219 return joinPaths(m_parser.currentNode(), pathString);
220 }
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200221 }
222}
223
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100224std::string Interpreter::absolutePathFromCommand(const describe_& describe) const
225{
226 auto pathStr = boost::apply_visitor(pathToStringVisitor(), describe.m_path);
227 if (boost::apply_visitor(getPathScopeVisitor(), describe.m_path) == Scope::Absolute)
228 return pathStr;
229 else
230 return joinPaths(m_parser.currentNode(), pathStr);
231}
232
Václav Kubernát6415b822018-08-22 17:40:01 +0200233Interpreter::Interpreter(Parser& parser, DatastoreAccess& datastore)
Václav Kubernát812ee282018-08-30 17:10:03 +0200234 : m_parser(parser)
235 , m_datastore(datastore)
Václav Kubernát96344a12018-05-28 16:33:39 +0200236{
237}