Kea 1.5.0
adaptor.cc
Go to the documentation of this file.
1// Copyright (C) 2018 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 <yang/adaptor.h>
8#include <boost/foreach.hpp>
9
10#include <iostream>
11
12using namespace std;
13using namespace isc::data;
14
15namespace isc {
16namespace yang {
17
19}
20
22}
23
26{
27 ConstElementPtr context = parent->get("user-context");
28 ConstElementPtr comment = parent->get("comment");
29 if (!comment) {
30 return (context);
31 }
32 ElementPtr result;
33 if (context) {
34 result = copy(context);
35 } else {
36 result = Element::createMap();
37 }
38 result->set("comment", comment);
39 return (result);
40}
41
42void
43Adaptor::fromParent(const string& name, ConstElementPtr parent,
44 ConstElementPtr list) {
45 ConstElementPtr param = parent->get(name);
46 if (!param) {
47 return;
48 }
49 BOOST_FOREACH(ElementPtr item, list->listValue()) {
50 // don't override. Skip this entry if it already has the parameter.
51 if (item->contains(name)) {
52 continue;
53 }
54 item->set(name, param);
55 }
56}
57
58void
59Adaptor::toParent(const string& name, ElementPtr parent,
60 ConstElementPtr list) {
61 ConstElementPtr param;
62 bool first = true;
63 BOOST_FOREACH(ElementPtr item, list->listValue()) {
64 if (first) {
65 first = false;
66 param = item->get(name);
67 } else if ((!param && item->contains(name)) ||
68 (param && !item->contains(name)) ||
69 (param && item->contains(name) &&
70 !param->equals(*item->get(name)))) {
72 "inconsistent value of " << name
73 << " in " << list->str());
74 }
75 }
76 if (!first && param) {
77 BOOST_FOREACH(ElementPtr item, list->listValue()) {
78 if (param) {
79 item->remove(name);
80 }
81 }
82 parent->set(name, param);
83 }
84}
85
86namespace {
87
99void applyInsert(ConstElementPtr key, ConstElementPtr value,
100 ElementPtr scope) {
101 if (scope->getType() == Element::map) {
102 if (!key || !value || (key->getType() != Element::string)) {
103 return;
104 }
105 string name = key->stringValue();
106 if (!name.empty() && !scope->contains(name)) {
107 scope->set(name, copy(value));
108 }
109 } else if (scope->getType() == Element::list) {
110 if (value) {
111 scope->add(copy(value));
112 }
113 }
114}
115
124void applyReplace(ConstElementPtr key, ConstElementPtr value,
125 ElementPtr scope) {
126 if ((scope->getType() != Element::map) ||
127 !key || !value || (key->getType() != Element::string)) {
128 return;
129 }
130 string name = key->stringValue();
131 if (!name.empty()) {
132 scope->set(name, copy(value));
133 }
134}
135
148void applyDelete(ConstElementPtr key, ElementPtr scope) {
149 if (scope->getType() == Element::map) {
150 if (!key || (key->getType() != Element::string)) {
151 return;
152 }
153 string name = key->stringValue();
154 if (!name.empty()) {
155 scope->remove(name);
156 }
157 } else if (scope->getType() == Element::list) {
158 if (!key) {
159 return;
160 } else if (key->getType() == Element::integer) {
161 int index = key->intValue();
162 if ((index >= 0) && (index < scope->size())) {
163 scope->remove(index);
164 }
165 } else if (key->getType() == Element::map) {
166 ConstElementPtr entry = key->get("key");
167 ConstElementPtr value = key->get("value");
168 if (!entry || !value || (entry->getType() != Element::string)) {
169 return;
170 }
171 string name = entry->stringValue();
172 if (name.empty()) {
173 return;
174 }
175 for (int i = 0; i < scope->size(); ++i) {
176 ConstElementPtr item = scope->get(i);
177 if (!item || (item->getType() != Element::map)) {
178 continue;
179 }
180 ConstElementPtr compare = item->get(name);
181 if (compare && value->equals(*compare)) {
182 scope->remove(i);
183 return;
184 }
185 }
186 }
187 }
188}
189
198void applyAction(ConstElementPtr actions, ElementPtr scope, size_t next) {
199 if (next == actions->size()) {
200 return;
201 }
202 ConstElementPtr action = actions->get(next);
203 ++next;
204 if (!action || (action->getType() != Element::map) ||
205 !action->contains("action")) {
206 applyAction(actions, scope, next);
207 return;
208 }
209 string name = action->get("action")->stringValue();
210 if (name == "insert") {
211 applyInsert(action->get("key"), action->get("value"), scope);
212 } else if (name == "replace") {
213 applyReplace(action->get("key"), action->get("value"), scope);
214 } else if (name == "delete") {
215 applyDelete(action->get("key"), scope);
216 }
217 applyAction(actions, scope, next);
218}
219
234void applyDown(ConstElementPtr path, ConstElementPtr actions, ElementPtr scope,
235 size_t next) {
236 if (!scope) {
237 return;
238 }
239 if (next == path->size()) {
240 applyAction(actions, scope, 0);
241 return;
242 }
243 ConstElementPtr step = path->get(next);
244 ++next;
245 if (scope->getType() == Element::map) {
246 if (!step || (step->getType() != Element::string)) {
247 return;
248 }
249 string name = step->stringValue();
250 if (name.empty() || !scope->contains(name)) {
251 return;
252 }
253 ElementPtr down = boost::const_pointer_cast<Element>(scope->get(name));
254 if (down) {
255 applyDown(path, actions, down, next);
256 }
257 } else if (scope->getType() == Element::list) {
258 if (!step) {
259 return;
260 }
261 auto downs = scope->listValue();
262 if (step->getType() == Element::map) {
263 ConstElementPtr key = step->get("key");
264 ConstElementPtr value = step->get("value");
265 if (!key || !value || (key->getType() != Element::string)) {
266 return;
267 }
268 string name = key->stringValue();
269 if (name.empty()) {
270 return;
271 }
272 for (ElementPtr down : downs) {
273 if (!down || (down->getType() != Element::map)) {
274 continue;
275 }
276 ConstElementPtr compare = down->get(name);
277 if (compare && value->equals(*compare)) {
278 applyDown(path, actions, down, next);
279 return;
280 }
281 }
282 } else if (step->getType() != Element::integer) {
283 return;
284 }
285 int index = step->intValue();
286 if (index == -1) {
287 for (ElementPtr down : downs) {
288 applyDown(path, actions, down, next);
289 }
290 } else if ((index >= 0) && (index < scope->size())) {
291 applyDown(path, actions, scope->getNonConst(index), next);
292 }
293 }
294}
295
296} // end of anonymous namespace
297
299void
301 ElementPtr config) {
302 applyDown(path, actions, config, 0);
303}
304
305}; // end of namespace isc::yang
306}; // end of 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:268
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:43
Adaptor()
Constructor.
Definition: adaptor.cc:18
static isc::data::ConstElementPtr getContext(isc::data::ConstElementPtr parent)
Get user context.
Definition: adaptor.cc:25
static void toParent(const std::string &name, isc::data::ElementPtr parent, isc::data::ConstElementPtr list)
Moves a parameter to a parent.
Definition: adaptor.cc:59
virtual ~Adaptor()
Destructor.
Definition: adaptor.cc:21
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:300
#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:1114
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
boost::shared_ptr< Element > ElementPtr
Definition: data.h:22
Defines the logger used by the top-level component of kea-dhcp-ddns.