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 #ifndef ISC_ADAPTOR_H
8 #define ISC_ADAPTOR_H 1
9 
10 #include <exceptions/exceptions.h>
11 #include <cc/data.h>
12 
13 namespace isc {
14 namespace yang {
15 
16 /// @brief Missing key error.
17 class MissingKey : public isc::Exception {
18 public:
MissingKey(const char * file,size_t line,const char * what)19     MissingKey(const char* file, size_t line, const char* what) :
20         isc::Exception(file, line, what)
21     {}
22 };
23 
24 /// @brief JSON adaptor between canonical Kea and YANG models.
25 ///
26 /// An adaptor slightly modifies a JSON configuration between canonical Kea
27 /// what required or rendered by a YANG model, e.g. moving a parameter
28 /// to/from a parent.
29 /// The basic adaptor provides a set of tools.
30 class Adaptor {
31 public:
32 
33     /// @brief Constructor.
34     Adaptor();
35 
36     /// @brief Destructor.
37     virtual ~Adaptor();
38 
39     /// @brief Get user context.
40     ///
41     /// Get user-context and/or comment and return it with the comment
42     /// if exists moved inside the user-context (without checking if
43     /// there is already a comment as it should never be the case).
44     ///
45     /// This behavior is used to handle comments. For historical purposes
46     /// Kea allows to define comments in some scopes. Once the user-context
47     /// has been introduced, the comment (as a separate text field)
48     /// disappeared and was moved to comment key within user-context.
49     /// Nevertheless, the old syntax is still supported.
50     static isc::data::ConstElementPtr
51     getContext(isc::data::ConstElementPtr parent);
52 
53     /// @brief Moves a parameter from parent to a list of children.
54     ///
55     /// Move a parameter from the parent to each item in a list.
56     /// If the parameter exists in a child, it is skipped for this
57     /// particular child, not overridden.
58     ///
59     /// @param name The parameter name.
60     /// @param parent The parent element.
61     /// @param list The children list.
62     static void fromParent(const std::string& name,
63                            isc::data::ConstElementPtr parent,
64                            isc::data::ConstElementPtr list);
65 
66     /// @brief Moves a parameter to a parent.
67     ///
68     /// Move a parameter from children to the parent. All children
69     /// on the list must have the parameter specified and it has to have
70     /// the same value.
71     ///
72     /// @param name The parameter name.
73     /// @param parent The parent element.
74     /// @param list The children list.
75     static void toParent(const std::string& name,
76                          isc::data::ElementPtr parent,
77                          isc::data::ConstElementPtr list);
78 
79     /// @brief Modify a configuration in its JSON element format.
80     ///
81     /// Smart merging tool, e.g. completing a from yang configuration.
82     ///
83     /// A modification is a path and actions:
84     ///  - path item can be:
85     ///   * a string: current scope is a map, go down following the string
86     ///     as a key.
87     ///   * a number: current scope is a list, go down the number as an index.
88     ///   * special value -1: current scope is a list, apply to all items.
89     ///   * map { "<key>": <value> }: current scope is a list, go down to
90     ///     the item using the key / value pair.
91     ///  - an action can be: insert, replace or delete:
92     ///   * insert adds a value at a key:
93     ///     . in a map the key is the new entry key
94     ///     . in a list an integer key is the new element index
95     ///     . in a list a map key is the key / value pair the to-be-modified
96     ///       element contains
97     ///   * replace adds or replaces if it already exists a value at
98     ///     an entry key in a map.
99     ///   * delete removes a value designed by a key
100     ///
101     /// For instance to add a control-socket entry in a configuration
102     /// from a generic (vs Kea) model:
103     /// @code
104     ///   path := [ ]
105     ///   actions := [ {
106     ///     "action": "insert",
107     ///     "key": "Dhcp4",
108     ///     "value":
109     ///       {
110     ///         "control-socket":
111     ///           {
112     ///              "socket-type": "unix",
113     ///              "socket-name": "/tmp/kea4-ctrl-socket"
114     ///           }
115     ///       }
116     ///    }
117     /// @endcode
118     ///
119     /// @param path The search list to follow down to the place to
120     ///             apply the action list.
121     /// @param actions The action list
122     /// @param config The configuration (JSON map) to modify.
123     /// @note modify does not throw but returns on unexpected conditions.
124     static void modify(isc::data::ConstElementPtr path,
125                        isc::data::ConstElementPtr actions,
126                        isc::data::ElementPtr config);
127 
128 };
129 
130 }; // end of namespace isc::yang
131 }; // end of namespace isc
132 
133 #endif // ISC_ADAPTOR_H
134