blob: 5b13337170f10e7d463ff4e66fade87ebf89afe1 [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át9cfcd872020-02-18 12:34:02 +010083std::string Interpreter::buildTypeInfo(const std::string& path) const
84{
85 std::ostringstream ss;
86 switch (m_datastore.schema()->nodeType(path)) {
87 case yang::NodeTypes::Container:
88 ss << "container";
89 break;
90 case yang::NodeTypes::PresenceContainer:
91 ss << "presence container";
92 break;
93 case yang::NodeTypes::Leaf:
94 {
95 auto leafType = m_datastore.schema()->leafType(path);
96 auto typedefName = m_datastore.schema()->leafTypeName(path);
97 std::string baseTypeStr;
98 if (leafType == yang::LeafDataTypes::LeafRef) {
99 ss << "-> ";
100 ss << m_datastore.schema()->leafrefPath(path) << " ";
101 baseTypeStr = leafDataTypeToString(m_datastore.schema()->leafrefBaseType(path));
102 } else {
103 baseTypeStr = leafDataTypeToString(leafType);
104 }
105
106 if (typedefName) {
107 ss << *typedefName << " (" << baseTypeStr << ")";
108 } else {
109 ss << baseTypeStr;
110 }
111
112 if (auto units = m_datastore.schema()->units(path)) {
113 ss << " [" + *units + "]";
114 }
115
116 if (m_datastore.schema()->leafIsKey(path)) {
117 ss << " (key)";
118 }
119 break;
120 }
121 case yang::NodeTypes::List:
122 ss << "list";
123 break;
124 }
125 return ss.str();
126}
127
128void Interpreter::operator()(const describe_& describe) const
129{
130 auto path = absolutePathFromCommand(describe);
131 std::cout << path << ": " << buildTypeInfo(path) << std::endl;
132 if (auto description = m_datastore.schema()->description(path)) {
133 std::cout << std::endl << *description << std::endl;
134 }
135}
136
Václav Kubernát054cc992019-02-21 14:23:52 +0100137struct commandLongHelpVisitor : boost::static_visitor<const char*> {
138 template <typename T>
139 auto constexpr operator()(boost::type<T>) const
140 {
141 return T::longHelp;
142 }
143};
144
145struct commandShortHelpVisitor : boost::static_visitor<const char*> {
146 template <typename T>
147 auto constexpr operator()(boost::type<T>) const
148 {
149 return T::shortHelp;
150 }
151};
152
153void Interpreter::operator()(const help_& help) const
154{
155 if (help.m_cmd)
156 std::cout << boost::apply_visitor(commandLongHelpVisitor(), help.m_cmd.get()) << std::endl;
157 else
158 boost::mpl::for_each<CommandTypes, boost::type<boost::mpl::_>>([](auto cmd) {
159 std::cout << commandShortHelpVisitor()(cmd) << std::endl;
160 });
161}
162
Václav Kubernát6415b822018-08-22 17:40:01 +0200163template <typename T>
164std::string Interpreter::absolutePathFromCommand(const T& command) const
165{
Václav Kubernát37171a12018-08-31 17:01:48 +0200166 if (command.m_path.m_scope == Scope::Absolute)
Václav Kubernátefcac932020-01-10 15:26:32 +0100167 return pathToDataString(command.m_path, Prefixes::WhenNeeded);
Václav Kubernát37171a12018-08-31 17:01:48 +0200168 else
Václav Kubernátefcac932020-01-10 15:26:32 +0100169 return joinPaths(m_parser.currentNode(), pathToDataString(command.m_path, Prefixes::WhenNeeded));
Václav Kubernát6415b822018-08-22 17:40:01 +0200170}
171
Václav Kubernát5c75b252018-10-10 18:33:47 +0200172struct pathToStringVisitor : boost::static_visitor<std::string> {
173 std::string operator()(const schemaPath_& path) const
174 {
Václav Kubernátefcac932020-01-10 15:26:32 +0100175 return pathToSchemaString(path, Prefixes::WhenNeeded);
Václav Kubernát5c75b252018-10-10 18:33:47 +0200176 }
177 std::string operator()(const dataPath_& path) const
178 {
Václav Kubernátefcac932020-01-10 15:26:32 +0100179 return pathToDataString(path, Prefixes::WhenNeeded);
Václav Kubernát5c75b252018-10-10 18:33:47 +0200180 }
181};
182
183struct getPathScopeVisitor : boost::static_visitor<Scope> {
184 template <typename T>
185 Scope operator()(const T& path) const
186 {
187 return path.m_scope;
188 }
189};
190
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200191std::string Interpreter::absolutePathFromCommand(const get_& get) const
192{
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200193 using namespace std::string_literals;
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200194 if (!get.m_path) {
195 return m_parser.currentNode();
Václav Kubernát5c75b252018-10-10 18:33:47 +0200196 }
197
198 const auto path = *get.m_path;
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200199 if (path.type() == typeid(module_)) {
200 return "/"s + boost::get<module_>(path).m_name + ":*";
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200201 } else {
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200202 auto actualPath = boost::get<boost::variant<dataPath_, schemaPath_>>(path);
203 std::string pathString = boost::apply_visitor(pathToStringVisitor(), actualPath);
204 auto pathScope{boost::apply_visitor(getPathScopeVisitor(), actualPath)};
205
206 if (pathScope == Scope::Absolute) {
Václav Kubernát82684cf2020-01-06 13:30:37 +0100207 return pathString;
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200208 } else {
209 return joinPaths(m_parser.currentNode(), pathString);
210 }
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200211 }
212}
213
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100214std::string Interpreter::absolutePathFromCommand(const describe_& describe) const
215{
216 auto pathStr = boost::apply_visitor(pathToStringVisitor(), describe.m_path);
217 if (boost::apply_visitor(getPathScopeVisitor(), describe.m_path) == Scope::Absolute)
218 return pathStr;
219 else
220 return joinPaths(m_parser.currentNode(), pathStr);
221}
222
Václav Kubernát6415b822018-08-22 17:40:01 +0200223Interpreter::Interpreter(Parser& parser, DatastoreAccess& datastore)
Václav Kubernát812ee282018-08-30 17:10:03 +0200224 : m_parser(parser)
225 , m_datastore(datastore)
Václav Kubernát96344a12018-05-28 16:33:39 +0200226{
227}