Kea  2.1.7-git
adaptor.cc
Go to the documentation of this file.
1 // Copyright (C) 2018-2020 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 
14 using namespace std;
15 using namespace isc::data;
16 
17 namespace isc {
18 namespace yang {
19 
20 Adaptor::Adaptor() {
21 }
22 
23 Adaptor::~Adaptor() {
24 }
25 
27 Adaptor::getContext(ConstElementPtr parent)
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 
44 void
45 Adaptor::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 
60 void
61 Adaptor::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 
88 namespace {
89 
101 void 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 
126 void 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 
150 void 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 
200 void 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 
236 void 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 
301 void
302 Adaptor::modify(ConstElementPtr path, ConstElementPtr actions,
303  ElementPtr config) {
304  applyDown(path, actions, config, 0);
305 }
306 
307 }; // end of namespace isc::yang
308 }; // end of namespace isc
boost::shared_ptr< Element > ElementPtr
Definition: data.h:24
STL namespace.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
ElementPtr copy(ConstElementPtr from, int level)
Copy the data up to a nesting level.
Definition: data.cc:1152
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
Defines the logger used by the top-level component of kea-lfc.
The Element class represents a piece of data, used by the command channel and configuration parts...
Definition: data.h:70