Kea 2.2.0
adaptor.cc
Go to the documentation of this file.
1// Copyright (C) 2018-2022 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <yang/adaptor.h>
10#include <boost/foreach.hpp>
11
12#include <iostream>
13
14using namespace std;
15using namespace isc::data;
16
17namespace isc {
18namespace yang {
19
21}
22
24}
25
28{
29 ConstElementPtr context = parent->get("user-context");
30 ConstElementPtr comment = parent->get("comment");
31 if (!comment) {
32 return (context);
33 }
34 ElementPtr result;
35 if (context) {
36 result = copy(context);
37 } else {
38 result = Element::createMap();
39 }
40 result->set("comment", comment);
41 return (result);
42}
43
44void
45Adaptor::fromParent(const string& name, ConstElementPtr parent,
46 ConstElementPtr list) {
47 ConstElementPtr param = parent->get(name);
48 if (!param) {
49 return;
50 }
51 BOOST_FOREACH(ElementPtr item, list->listValue()) {
52 // don't override. Skip this entry if it already has the parameter.
53 if (item->contains(name)) {
54 continue;
55 }
56 item->set(name, param);
57 }
58}
59
60void
61Adaptor::toParent(const string& name, ElementPtr parent,
62 ConstElementPtr list) {
63 ConstElementPtr param;
64 bool first = true;
65 BOOST_FOREACH(ElementPtr item, list->listValue()) {
66 if (first) {
67 first = false;
68 param = item->get(name);
69 } else if ((!param && item->contains(name)) ||
70 (param && !item->contains(name)) ||
71 (param && item->contains(name) &&
72 !param->equals(*item->get(name)))) {
74 "inconsistent value of " << name
75 << " in " << list->str());
76 }
77 }
78 if (!first && param) {
79 BOOST_FOREACH(ElementPtr item, list->listValue()) {
80 if (param) {
81 item->remove(name);
82 }
83 }
84 parent->set(name, param);
85 }
86}
87
88namespace {
89
101void applyInsert(ConstElementPtr key, ConstElementPtr value,
102 ElementPtr scope) {
103 if (scope->getType() == Element::map) {
104 if (!key || !value || (key->getType() != Element::string)) {
105 return;
106 }
107 string name = key->stringValue();
108 if (!name.empty() && !scope->contains(name)) {
109 scope->set(name, copy(value));
110 }
111 } else if (scope->getType() == Element::list) {
112 if (value) {
113 scope->add(copy(value));
114 }
115 }
116}
117
126void applyReplace(ConstElementPtr key, ConstElementPtr value,
127 ElementPtr scope) {
128 if ((scope->getType() != Element::map) ||
129 !key || !value || (key->getType() != Element::string)) {
130 return;
131 }
132 string name = key->stringValue();
133 if (!name.empty()) {
134 scope->set(name, copy(value));
135 }
136}
137
150void applyDelete(ConstElementPtr key, ElementPtr scope) {
151 if (scope->getType() == Element::map) {
152 if (!key || (key->getType() != Element::string)) {
153 return;
154 }
155 string name = key->stringValue();
156 if (!name.empty()) {
157 scope->remove(name);
158 }
159 } else if (scope->getType() == Element::list) {
160 if (!key) {
161 return;
162 } else if (key->getType() == Element::integer) {
163 int index = key->intValue();
164 if ((index >= 0) && (index < scope->size())) {
165 scope->remove(index);
166 }
167 } else if (key->getType() == Element::map) {
168 ConstElementPtr entry = key->get("key");
169 ConstElementPtr value = key->get("value");
170 if (!entry || !value || (entry->getType() != Element::string)) {
171 return;
172 }
173 string name = entry->stringValue();
174 if (name.empty()) {
175 return;
176 }
177 for (int i = 0; i < scope->size(); ++i) {
178 ConstElementPtr item = scope->get(i);
179 if (!item || (item->getType() != Element::map)) {
180 continue;
181 }
182 ConstElementPtr compare = item->get(name);
183 if (compare && value->equals(*compare)) {
184 scope->remove(i);
185 return;
186 }
187 }
188 }
189 }
190}
191
200void applyAction(ConstElementPtr actions, ElementPtr scope, size_t next) {
201 if (next == actions->size()) {
202 return;
203 }
204 ConstElementPtr action = actions->get(next);
205 ++next;
206 if (!action || (action->getType() != Element::map) ||
207 !action->contains("action")) {
208 applyAction(actions, scope, next);
209 return;
210 }
211 string name = action->get("action")->stringValue();
212 if (name == "insert") {
213 applyInsert(action->get("key"), action->get("value"), scope);
214 } else if (name == "replace") {
215 applyReplace(action->get("key"), action->get("value"), scope);
216 } else if (name == "delete") {
217 applyDelete(action->get("key"), scope);
218 }
219 applyAction(actions, scope, next);
220}
221
236void applyDown(ConstElementPtr path, ConstElementPtr actions, ElementPtr scope,
237 size_t next) {
238 if (!scope) {
239 return;
240 }
241 if (next == path->size()) {
242 applyAction(actions, scope, 0);
243 return;
244 }
245 ConstElementPtr step = path->get(next);
246 ++next;
247 if (scope->getType() == Element::map) {
248 if (!step || (step->getType() != Element::string)) {
249 return;
250 }
251 string name = step->stringValue();
252 if (name.empty() || !scope->contains(name)) {
253 return;
254 }
255 ElementPtr down = boost::const_pointer_cast<Element>(scope->get(name));
256 if (down) {
257 applyDown(path, actions, down, next);
258 }
259 } else if (scope->getType() == Element::list) {
260 if (!step) {
261 return;
262 }
263 auto downs = scope->listValue();
264 if (step->getType() == Element::map) {
265 ConstElementPtr key = step->get("key");
266 ConstElementPtr value = step->get("value");
267 if (!key || !value || (key->getType() != Element::string)) {
268 return;
269 }
270 string name = key->stringValue();
271 if (name.empty()) {
272 return;
273 }
274 for (ElementPtr down : downs) {
275 if (!down || (down->getType() != Element::map)) {
276 continue;
277 }
278 ConstElementPtr compare = down->get(name);
279 if (compare && value->equals(*compare)) {
280 applyDown(path, actions, down, next);
281 return;
282 }
283 }
284 } else if (step->getType() != Element::integer) {
285 return;
286 }
287 int index = step->intValue();
288 if (index == -1) {
289 for (ElementPtr down : downs) {
290 applyDown(path, actions, down, next);
291 }
292 } else if ((index >= 0) && (index < scope->size())) {
293 applyDown(path, actions, scope->getNonConst(index), next);
294 }
295 }
296}
297
298} // end of anonymous namespace
299
301void
303 ElementPtr config) {
304 applyDown(path, actions, config, 0);
305}
306
307} // end of namespace isc::yang
308} // end of namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
static void fromParent(const std::string &name, isc::data::ConstElementPtr parent, isc::data::ConstElementPtr list)
Moves a parameter from parent to a list of children.
Definition: adaptor.cc:45
Adaptor()
Constructor.
Definition: adaptor.cc:20
static isc::data::ConstElementPtr getContext(isc::data::ConstElementPtr parent)
Get user context.
Definition: adaptor.cc:27
static void toParent(const std::string &name, isc::data::ElementPtr parent, isc::data::ConstElementPtr list)
Moves a parameter to a parent.
Definition: adaptor.cc:61
virtual ~Adaptor()
Destructor.
Definition: adaptor.cc:23
static void modify(isc::data::ConstElementPtr path, isc::data::ConstElementPtr actions, isc::data::ElementPtr config)
Modify a configuration in its JSON element format.
Definition: adaptor.cc:302
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
ElementPtr copy(ConstElementPtr from, int level)
Copy the data up to a nesting level.
Definition: data.cc:1360
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
boost::shared_ptr< Element > ElementPtr
Definition: data.h:24
Defines the logger used by the top-level component of kea-lfc.