blob: 9912584083be10973632a9d1d0a0b3adccf2ada4 [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át82086872020-04-29 01:09:50 +020079 std::set<std::string> toPrint;
80
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
98 for (const auto& it : toPrint)
Václav Kubernát11afac72018-07-18 14:59:53 +020099 std::cout << it << std::endl;
100}
101
Václav Kubernát7160a132020-04-03 02:11:01 +0200102void Interpreter::operator()(const copy_& copy) const
103{
104 m_datastore.copyConfig(copy.m_source, copy.m_destination);
105}
106
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100107std::string Interpreter::buildTypeInfo(const std::string& path) const
108{
109 std::ostringstream ss;
110 switch (m_datastore.schema()->nodeType(path)) {
111 case yang::NodeTypes::Container:
112 ss << "container";
113 break;
114 case yang::NodeTypes::PresenceContainer:
115 ss << "presence container";
116 break;
117 case yang::NodeTypes::Leaf:
118 {
119 auto leafType = m_datastore.schema()->leafType(path);
120 auto typedefName = m_datastore.schema()->leafTypeName(path);
121 std::string baseTypeStr;
Václav Kubernát13b23d72020-04-16 21:49:51 +0200122 if (std::holds_alternative<yang::LeafRef>(leafType.m_type)) {
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100123 ss << "-> ";
124 ss << m_datastore.schema()->leafrefPath(path) << " ";
Václav Kubernát13b23d72020-04-16 21:49:51 +0200125 baseTypeStr = leafDataTypeToString(std::get<yang::LeafRef>(leafType.m_type).m_targetType->m_type);
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100126 } else {
Václav Kubernát13b23d72020-04-16 21:49:51 +0200127 baseTypeStr = leafDataTypeToString(leafType.m_type);
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100128 }
129
130 if (typedefName) {
131 ss << *typedefName << " (" << baseTypeStr << ")";
132 } else {
133 ss << baseTypeStr;
134 }
135
Václav Kubernát13b23d72020-04-16 21:49:51 +0200136 if (leafType.m_units) {
137 ss << " [" + *leafType.m_units + "]";
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100138 }
139
140 if (m_datastore.schema()->leafIsKey(path)) {
141 ss << " (key)";
142 }
Václav Kubernátb1a75c62020-04-21 15:20:16 +0200143
144 if (auto defaultValue = m_datastore.schema()->defaultValue(path)) {
145 ss << " default: " << leafDataToString(*defaultValue);
146 }
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100147 break;
148 }
149 case yang::NodeTypes::List:
150 ss << "list";
151 break;
152 }
Václav Kubernát0599e9f2020-04-21 09:51:33 +0200153
154 if (!m_datastore.schema()->isConfig(path)) {
155 ss << " (ro)";
156 }
157
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100158 return ss.str();
159}
160
161void Interpreter::operator()(const describe_& describe) const
162{
163 auto path = absolutePathFromCommand(describe);
Václav Kubernáta1c4c9e2020-04-22 00:37:52 +0200164 auto status = m_datastore.schema()->status(path);
165 auto statusStr = status == yang::Status::Deprecated ? " (deprecated)" :
166 status == yang::Status::Obsolete ? " (obsolete)" :
167 "";
168
169 std::cout << path << ": " << buildTypeInfo(path) << statusStr << std::endl;
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100170 if (auto description = m_datastore.schema()->description(path)) {
171 std::cout << std::endl << *description << std::endl;
172 }
173}
174
Václav Kubernát054cc992019-02-21 14:23:52 +0100175struct commandLongHelpVisitor : boost::static_visitor<const char*> {
176 template <typename T>
177 auto constexpr operator()(boost::type<T>) const
178 {
179 return T::longHelp;
180 }
181};
182
183struct commandShortHelpVisitor : boost::static_visitor<const char*> {
184 template <typename T>
185 auto constexpr operator()(boost::type<T>) const
186 {
187 return T::shortHelp;
188 }
189};
190
191void Interpreter::operator()(const help_& help) const
192{
193 if (help.m_cmd)
194 std::cout << boost::apply_visitor(commandLongHelpVisitor(), help.m_cmd.get()) << std::endl;
195 else
196 boost::mpl::for_each<CommandTypes, boost::type<boost::mpl::_>>([](auto cmd) {
197 std::cout << commandShortHelpVisitor()(cmd) << std::endl;
198 });
199}
200
Václav Kubernát6415b822018-08-22 17:40:01 +0200201template <typename T>
202std::string Interpreter::absolutePathFromCommand(const T& command) const
203{
Václav Kubernát37171a12018-08-31 17:01:48 +0200204 if (command.m_path.m_scope == Scope::Absolute)
Václav Kubernátefcac932020-01-10 15:26:32 +0100205 return pathToDataString(command.m_path, Prefixes::WhenNeeded);
Václav Kubernát37171a12018-08-31 17:01:48 +0200206 else
Václav Kubernátefcac932020-01-10 15:26:32 +0100207 return joinPaths(m_parser.currentNode(), pathToDataString(command.m_path, Prefixes::WhenNeeded));
Václav Kubernát6415b822018-08-22 17:40:01 +0200208}
209
Václav Kubernát5c75b252018-10-10 18:33:47 +0200210struct pathToStringVisitor : boost::static_visitor<std::string> {
211 std::string operator()(const schemaPath_& path) const
212 {
Václav Kubernátefcac932020-01-10 15:26:32 +0100213 return pathToSchemaString(path, Prefixes::WhenNeeded);
Václav Kubernát5c75b252018-10-10 18:33:47 +0200214 }
215 std::string operator()(const dataPath_& path) const
216 {
Václav Kubernátefcac932020-01-10 15:26:32 +0100217 return pathToDataString(path, Prefixes::WhenNeeded);
Václav Kubernát5c75b252018-10-10 18:33:47 +0200218 }
219};
220
221struct getPathScopeVisitor : boost::static_visitor<Scope> {
222 template <typename T>
223 Scope operator()(const T& path) const
224 {
225 return path.m_scope;
226 }
227};
228
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200229std::string Interpreter::absolutePathFromCommand(const get_& get) const
230{
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200231 using namespace std::string_literals;
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200232 if (!get.m_path) {
233 return m_parser.currentNode();
Václav Kubernát5c75b252018-10-10 18:33:47 +0200234 }
235
236 const auto path = *get.m_path;
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200237 if (path.type() == typeid(module_)) {
238 return "/"s + boost::get<module_>(path).m_name + ":*";
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200239 } else {
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200240 auto actualPath = boost::get<boost::variant<dataPath_, schemaPath_>>(path);
241 std::string pathString = boost::apply_visitor(pathToStringVisitor(), actualPath);
242 auto pathScope{boost::apply_visitor(getPathScopeVisitor(), actualPath)};
243
244 if (pathScope == Scope::Absolute) {
Václav Kubernát82684cf2020-01-06 13:30:37 +0100245 return pathString;
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200246 } else {
247 return joinPaths(m_parser.currentNode(), pathString);
248 }
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200249 }
250}
251
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100252std::string Interpreter::absolutePathFromCommand(const describe_& describe) const
253{
254 auto pathStr = boost::apply_visitor(pathToStringVisitor(), describe.m_path);
255 if (boost::apply_visitor(getPathScopeVisitor(), describe.m_path) == Scope::Absolute)
256 return pathStr;
257 else
258 return joinPaths(m_parser.currentNode(), pathStr);
259}
260
Václav Kubernát6415b822018-08-22 17:40:01 +0200261Interpreter::Interpreter(Parser& parser, DatastoreAccess& datastore)
Václav Kubernát812ee282018-08-30 17:10:03 +0200262 : m_parser(parser)
263 , m_datastore(datastore)
Václav Kubernát96344a12018-05-28 16:33:39 +0200264{
265}