blob: eb0fd667bd452c7f1b12a6b3762958521caca03a [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át95b08872020-04-28 01:04:17 +020079 std::set<ModuleNodePair> toPrint;
Václav Kubernát82086872020-04-29 01:09:50 +020080
81 auto pathArg = dataPathToSchemaPath(m_parser.currentPath());
82 if (ls.m_path) {
83 if (ls.m_path->type() == typeid(module_)) {
84 toPrint = m_datastore.schema()->availableNodes(*ls.m_path, recursion);
85 } else {
86 auto schemaPath = anyPathToSchemaPath(*ls.m_path);
87 if (schemaPath.m_scope == Scope::Absolute) {
88 pathArg = schemaPath;
89 } else {
90 pathArg.m_nodes.insert(pathArg.m_nodes.end(), schemaPath.m_nodes.begin(), schemaPath.m_nodes.end());
91 }
92 toPrint = m_datastore.schema()->availableNodes(pathArg, recursion);
93 }
94 } else {
95 toPrint = m_datastore.schema()->availableNodes(pathArg, recursion);
96 }
97
Václav Kubernát95b08872020-04-28 01:04:17 +020098 for (const auto& it : toPrint) {
99 std::cout << (it.first ? *it.first + ":" : "" ) + it.second << std::endl;
100 }
Václav Kubernát11afac72018-07-18 14:59:53 +0200101}
102
Václav Kubernát7160a132020-04-03 02:11:01 +0200103void Interpreter::operator()(const copy_& copy) const
104{
105 m_datastore.copyConfig(copy.m_source, copy.m_destination);
106}
107
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100108std::string Interpreter::buildTypeInfo(const std::string& path) const
109{
110 std::ostringstream ss;
111 switch (m_datastore.schema()->nodeType(path)) {
112 case yang::NodeTypes::Container:
113 ss << "container";
114 break;
115 case yang::NodeTypes::PresenceContainer:
116 ss << "presence container";
117 break;
118 case yang::NodeTypes::Leaf:
119 {
120 auto leafType = m_datastore.schema()->leafType(path);
121 auto typedefName = m_datastore.schema()->leafTypeName(path);
122 std::string baseTypeStr;
Václav Kubernát13b23d72020-04-16 21:49:51 +0200123 if (std::holds_alternative<yang::LeafRef>(leafType.m_type)) {
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100124 ss << "-> ";
125 ss << m_datastore.schema()->leafrefPath(path) << " ";
Václav Kubernát13b23d72020-04-16 21:49:51 +0200126 baseTypeStr = leafDataTypeToString(std::get<yang::LeafRef>(leafType.m_type).m_targetType->m_type);
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100127 } else {
Václav Kubernát13b23d72020-04-16 21:49:51 +0200128 baseTypeStr = leafDataTypeToString(leafType.m_type);
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100129 }
130
131 if (typedefName) {
132 ss << *typedefName << " (" << baseTypeStr << ")";
133 } else {
134 ss << baseTypeStr;
135 }
136
Václav Kubernát13b23d72020-04-16 21:49:51 +0200137 if (leafType.m_units) {
138 ss << " [" + *leafType.m_units + "]";
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100139 }
140
141 if (m_datastore.schema()->leafIsKey(path)) {
142 ss << " (key)";
143 }
Václav Kubernátb1a75c62020-04-21 15:20:16 +0200144
145 if (auto defaultValue = m_datastore.schema()->defaultValue(path)) {
146 ss << " default: " << leafDataToString(*defaultValue);
147 }
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100148 break;
149 }
150 case yang::NodeTypes::List:
151 ss << "list";
152 break;
Václav Kubernátaaafeae2020-05-05 15:41:45 +0200153 case yang::NodeTypes::Action:
154 case yang::NodeTypes::AnyXml:
155 case yang::NodeTypes::LeafList:
156 case yang::NodeTypes::Notification:
157 case yang::NodeTypes::Rpc:
158 throw std::logic_error("describe got an rpc or an action: this should never happen, because their paths cannot be parsed");
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100159 }
Václav Kubernát0599e9f2020-04-21 09:51:33 +0200160
161 if (!m_datastore.schema()->isConfig(path)) {
162 ss << " (ro)";
163 }
164
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100165 return ss.str();
166}
167
168void Interpreter::operator()(const describe_& describe) const
169{
170 auto path = absolutePathFromCommand(describe);
Václav Kubernáta1c4c9e2020-04-22 00:37:52 +0200171 auto status = m_datastore.schema()->status(path);
172 auto statusStr = status == yang::Status::Deprecated ? " (deprecated)" :
173 status == yang::Status::Obsolete ? " (obsolete)" :
174 "";
175
176 std::cout << path << ": " << buildTypeInfo(path) << statusStr << std::endl;
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100177 if (auto description = m_datastore.schema()->description(path)) {
178 std::cout << std::endl << *description << std::endl;
179 }
180}
181
Václav Kubernát054cc992019-02-21 14:23:52 +0100182struct commandLongHelpVisitor : boost::static_visitor<const char*> {
183 template <typename T>
184 auto constexpr operator()(boost::type<T>) const
185 {
186 return T::longHelp;
187 }
188};
189
190struct commandShortHelpVisitor : boost::static_visitor<const char*> {
191 template <typename T>
192 auto constexpr operator()(boost::type<T>) const
193 {
194 return T::shortHelp;
195 }
196};
197
198void Interpreter::operator()(const help_& help) const
199{
200 if (help.m_cmd)
201 std::cout << boost::apply_visitor(commandLongHelpVisitor(), help.m_cmd.get()) << std::endl;
202 else
203 boost::mpl::for_each<CommandTypes, boost::type<boost::mpl::_>>([](auto cmd) {
204 std::cout << commandShortHelpVisitor()(cmd) << std::endl;
205 });
206}
207
Václav Kubernát6415b822018-08-22 17:40:01 +0200208template <typename T>
209std::string Interpreter::absolutePathFromCommand(const T& command) const
210{
Václav Kubernát37171a12018-08-31 17:01:48 +0200211 if (command.m_path.m_scope == Scope::Absolute)
Václav Kubernátefcac932020-01-10 15:26:32 +0100212 return pathToDataString(command.m_path, Prefixes::WhenNeeded);
Václav Kubernát37171a12018-08-31 17:01:48 +0200213 else
Václav Kubernátefcac932020-01-10 15:26:32 +0100214 return joinPaths(m_parser.currentNode(), pathToDataString(command.m_path, Prefixes::WhenNeeded));
Václav Kubernát6415b822018-08-22 17:40:01 +0200215}
216
Václav Kubernát5c75b252018-10-10 18:33:47 +0200217struct pathToStringVisitor : boost::static_visitor<std::string> {
218 std::string operator()(const schemaPath_& path) const
219 {
Václav Kubernátefcac932020-01-10 15:26:32 +0100220 return pathToSchemaString(path, Prefixes::WhenNeeded);
Václav Kubernát5c75b252018-10-10 18:33:47 +0200221 }
222 std::string operator()(const dataPath_& path) const
223 {
Václav Kubernátefcac932020-01-10 15:26:32 +0100224 return pathToDataString(path, Prefixes::WhenNeeded);
Václav Kubernát5c75b252018-10-10 18:33:47 +0200225 }
226};
227
228struct getPathScopeVisitor : boost::static_visitor<Scope> {
229 template <typename T>
230 Scope operator()(const T& path) const
231 {
232 return path.m_scope;
233 }
234};
235
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200236std::string Interpreter::absolutePathFromCommand(const get_& get) const
237{
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200238 using namespace std::string_literals;
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200239 if (!get.m_path) {
240 return m_parser.currentNode();
Václav Kubernát5c75b252018-10-10 18:33:47 +0200241 }
242
243 const auto path = *get.m_path;
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200244 if (path.type() == typeid(module_)) {
245 return "/"s + boost::get<module_>(path).m_name + ":*";
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200246 } else {
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200247 auto actualPath = boost::get<boost::variant<dataPath_, schemaPath_>>(path);
248 std::string pathString = boost::apply_visitor(pathToStringVisitor(), actualPath);
249 auto pathScope{boost::apply_visitor(getPathScopeVisitor(), actualPath)};
250
251 if (pathScope == Scope::Absolute) {
Václav Kubernát82684cf2020-01-06 13:30:37 +0100252 return pathString;
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200253 } else {
254 return joinPaths(m_parser.currentNode(), pathString);
255 }
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200256 }
257}
258
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100259std::string Interpreter::absolutePathFromCommand(const describe_& describe) const
260{
261 auto pathStr = boost::apply_visitor(pathToStringVisitor(), describe.m_path);
262 if (boost::apply_visitor(getPathScopeVisitor(), describe.m_path) == Scope::Absolute)
263 return pathStr;
264 else
265 return joinPaths(m_parser.currentNode(), pathStr);
266}
267
Václav Kubernát6415b822018-08-22 17:40:01 +0200268Interpreter::Interpreter(Parser& parser, DatastoreAccess& datastore)
Václav Kubernát812ee282018-08-30 17:10:03 +0200269 : m_parser(parser)
270 , m_datastore(datastore)
Václav Kubernát96344a12018-05-28 16:33:39 +0200271{
272}