Kea 2.7.0
adaptor.cc
Go to the documentation of this file.
1// Copyright (C) 2018-2024 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
11#include <iostream>
12
13using namespace std;
14using namespace isc::data;
15
16namespace isc {
17namespace yang {
18
21 ConstElementPtr context = parent->get("user-context");
22 ConstElementPtr comment = parent->get("comment");
23 if (!comment) {
24 return (context);
25 }
26 ElementPtr result;
27 if (context) {
28 result = copy(context);
29 } else {
30 result = Element::createMap();
31 }
32 result->set("comment", comment);
33 return (result);
34}
35
36void
37Adaptor::fromParent(const string& name, ConstElementPtr parent,
38 ConstElementPtr list) {
39 ConstElementPtr param = parent->get(name);
40 if (!param) {
41 return;
42 }
43 for (ElementPtr const& item : list->listValue()) {
44 // don't override. Skip this entry if it already has the parameter.
45 if (item->contains(name)) {
46 continue;
47 }
48 item->set(name, param);
49 }
50}
51
52void
53Adaptor::toParent(const string& name, ElementPtr parent,
54 ConstElementPtr list) {
55 ConstElementPtr param;
56 bool first = true;
57 for (ElementPtr const& item : list->listValue()) {
58 if (first) {
59 first = false;
60 param = item->get(name);
61 } else if ((!param && item->contains(name)) ||
62 (param && !item->contains(name)) ||
63 (param && item->contains(name) &&
64 !param->equals(*item->get(name)))) {
66 "inconsistent value of " << name
67 << " in " << list->str());
68 }
69 }
70 if (!first && param) {
71 for (ElementPtr const& item : list->listValue()) {
72 if (param) {
73 item->remove(name);
74 }
75 }
76 parent->set(name, param);
77 }
78}
79
80namespace {
81
93void applyInsert(ConstElementPtr key, ConstElementPtr value,
94 ElementPtr scope) {
95 if (scope->getType() == Element::map) {
96 if (!key || !value || (key->getType() != Element::string)) {
97 return;
98 }
99 string name = key->stringValue();
100 if (!name.empty() && !scope->contains(name)) {
101 scope->set(name, copy(value));
102 }
103 } else if (scope->getType() == Element::list) {
104 if (value) {
105 scope->add(copy(value));
106 }
107 }
108}
109
118void applyReplace(ConstElementPtr key, ConstElementPtr value,
119 ElementPtr scope) {
120 if ((scope->getType() != Element::map) ||
121 !key || !value || (key->getType() != Element::string)) {
122 return;
123 }
124 string name = key->stringValue();
125 if (!name.empty()) {
126 scope->set(name, copy(value));
127 }
128}
129
142void applyDelete(ConstElementPtr key, ElementPtr scope) {
143 if (scope->getType() == Element::map) {
144 if (!key || (key->getType() != Element::string)) {
145 return;
146 }
147 string name = key->stringValue();
148 if (!name.empty()) {
149 scope->remove(name);
150 }
151 } else if (scope->getType() == Element::list) {
152 if (!key) {
153 return;
154 } else if (key->getType() == Element::integer) {
155 int index = key->intValue();
156 if ((index >= 0) && (index < scope->size())) {
157 scope->remove(index);
158 }
159 } else if (key->getType() == Element::map) {
160 ConstElementPtr entry = key->get("key");
161 ConstElementPtr value = key->get("value");
162 if (!entry || !value || (entry->getType() != Element::string)) {
163 return;
164 }
165 string name = entry->stringValue();
166 if (name.empty()) {
167 return;
168 }
169 for (int i = 0; i < scope->size(); ++i) {
170 ElementPtr item = scope->getNonConst(i);
171 if (!item || (item->getType() != Element::map)) {
172 continue;
173 }
174 ConstElementPtr compare = item->get(name);
175 if (compare && value->equals(*compare)) {
176 scope->remove(i);
177 return;
178 }
179 }
180 }
181 }
182}
183
192void applyAction(ConstElementPtr actions, ElementPtr scope, size_t next) {
193 if (next == actions->size()) {
194 return;
195 }
196 ConstElementPtr action = actions->get(next);
197 ++next;
198 if (!action || (action->getType() != Element::map) ||
199 !action->contains("action")) {
200 applyAction(actions, scope, next);
201 return;
202 }
203 string name = action->get("action")->stringValue();
204 if (name == "insert") {
205 applyInsert(action->get("key"), action->get("value"), scope);
206 } else if (name == "replace") {
207 applyReplace(action->get("key"), action->get("value"), scope);
208 } else if (name == "delete") {
209 applyDelete(action->get("key"), scope);
210 }
211 applyAction(actions, scope, next);
212}
213
228void applyDown(ConstElementPtr path, ConstElementPtr actions, ElementPtr scope,
229 size_t next) {
230 if (!scope) {
231 return;
232 }
233 if (next == path->size()) {
234 applyAction(actions, scope, 0);
235 return;
236 }
237 ConstElementPtr step = path->get(next);
238 ++next;
239 if (scope->getType() == Element::map) {
240 if (!step || (step->getType() != Element::string)) {
241 return;
242 }
243 string name = step->stringValue();
244 if (name.empty() || !scope->contains(name)) {
245 return;
246 }
247 ConstElementPtr down(scope->get(name));
248 if (down) {
249 ElementPtr mutable_down(copy(down, 0));
250 applyDown(path, actions, mutable_down, next);
251 scope->set(name, mutable_down);
252 }
253 } else if (scope->getType() == Element::list) {
254 if (!step) {
255 return;
256 }
257 auto downs = scope->listValue();
258 if (step->getType() == Element::map) {
259 ConstElementPtr key = step->get("key");
260 ConstElementPtr value = step->get("value");
261 if (!key || !value || (key->getType() != Element::string)) {
262 return;
263 }
264 string name = key->stringValue();
265 if (name.empty()) {
266 return;
267 }
268 for (ElementPtr& down : downs) {
269 if (!down || (down->getType() != Element::map)) {
270 continue;
271 }
272 ConstElementPtr compare = down->get(name);
273 if (compare && value->equals(*compare)) {
274 applyDown(path, actions, down, next);
275 return;
276 }
277 }
278 } else if (step->getType() != Element::integer) {
279 return;
280 }
281 int index = step->intValue();
282 if (index == -1) {
283 for (ElementPtr& down : downs) {
284 applyDown(path, actions, down, next);
285 }
286 } else if ((index >= 0) && (index < scope->size())) {
287 applyDown(path, actions, scope->getNonConst(index), next);
288 }
289 }
290}
291
292} //anonymous namespace
293
295void
297 ElementPtr config) {
298 applyDown(path, actions, config, 0);
299}
300
301} // namespace yang
302} // namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:304
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:37
static isc::data::ConstElementPtr getContext(isc::data::ConstElementPtr parent)
Get user context.
Definition adaptor.cc:20
static void toParent(const std::string &name, isc::data::ElementPtr parent, isc::data::ConstElementPtr list)
Moves a parameter to a parent.
Definition adaptor.cc:53
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:296
#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:1420
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:29
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
Defines the logger used by the top-level component of kea-lfc.