Config manager api refinements
[archive/platform/core/system/libConfig.git] / src / config / from-kvjson-visitor.hpp
1 #ifndef CONFIG_FROM_KVJSON_VISITOR_HPP
2 #define CONFIG_FROM_KVJSON_VISITOR_HPP
3
4 /*
5  *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
6  *
7  *  Contact: Krzysztof Dynowski (k.dynowski@samsumg.com)
8  *
9  *  Licensed under the Apache License, Version 2.0 (the "License");
10  *  you may not use this file except in compliance with the License.
11  *  You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  *  Unless required by applicable law or agreed to in writing, software
16  *  distributed under the License is distributed on an "AS IS" BASIS,
17  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  *  See the License for the specific language governing permissions and
19  *  limitations under the License
20  */
21
22
23 /**
24  * @file
25  * @author  Krzysztof Dynowski (k.dynowski@samsumg.com)
26  * @brief   KVStore visitor with defaults values from json
27  */
28
29 #include "config/manager.hpp"
30
31
32 namespace config {
33
34 class FromKVJsonVisitor {
35 public:
36     FromKVJsonVisitor(const std::string& db, const std::string& json, const std::string& prefix)
37         : mStorePtr(new KVStore(db))
38         , mKeyPrefix(prefix)
39     {
40         mObject = json_tokener_parse(json.c_str());
41         if (mObject == nullptr) {
42             throw ConfigException("Json parsing error");
43         }
44     }
45
46     ~FromKVJsonVisitor() {
47         json_object_put(mObject);
48     }
49
50     FromKVJsonVisitor(const FromKVJsonVisitor& v) :
51         mObject(json_object_get(v.mObject)),
52         mStorePtr(v.mStorePtr),
53         mKeyPrefix(v.mKeyPrefix)
54     {
55     }
56     FromKVJsonVisitor& operator=(const FromKVJsonVisitor&) = delete;
57
58     template<typename T>
59     void visit(const std::string& name, T& value) {
60         getValue(name, value);
61     }
62
63 private:
64     std::shared_ptr<KVStore> mStorePtr;
65     std::string mKeyPrefix;
66     json_object* mObject;
67
68     // create visitor for field object (visitable object)
69     FromKVJsonVisitor(const FromKVJsonVisitor& v, const std::string& name) :
70         mStorePtr(v.mStorePtr)
71     {
72         json_object* object;
73         if (!json_object_object_get_ex(v.mObject, name.c_str(), &object)) {
74             throw ConfigException("Missing json field " + key(mKeyPrefix, name));
75         }
76         mObject = json_object_get(object);
77         mKeyPrefix = key(v.mKeyPrefix, name);
78     }
79
80     // create visitor for vector i-th element (visitable object)
81     FromKVJsonVisitor(const FromKVJsonVisitor& v, int i) :
82         mStorePtr(v.mStorePtr)
83     {
84         json_object* object = json_object_array_get_idx(v.mObject, i);
85         checkType(object, json_type_object);
86         mObject = json_object_get(object);
87         mKeyPrefix = key(v.mKeyPrefix, std::to_string(i));
88     }
89
90     template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
91     void getValue(const std::string& name, T& t)
92     {
93         json_object* object;
94         if (!json_object_object_get_ex(mObject, name.c_str(), &object)) {
95             throw ConfigException("Missing json field " + key(mKeyPrefix, name));
96         }
97         std::string k = key(mKeyPrefix, name);
98         if (mStorePtr->exists(k)) {
99             t = mStorePtr->get<T>(k);
100         }
101         else {
102             fromJsonObject(object, t);
103         }
104     }
105
106     template<typename T, typename std::enable_if<isVisitable<T>::value, int>::type = 0>
107     void getValue(const std::string& name, T& t)
108     {
109         FromKVJsonVisitor visitor(*this, name);
110         t.accept(visitor);
111     }
112
113     int getArraySize(std::string& name, json_object* object)
114     {
115         if (mStorePtr->exists(name)) {
116             return mStorePtr->get<int>(name);
117         }
118         return json_object_array_length(object);
119     }
120
121     template<typename T>
122     void getValue(const std::string& name, std::vector<T>& value)
123     {
124         json_object* object;
125         if (!json_object_object_get_ex(mObject, name.c_str(), &object)) {
126             throw ConfigException("Missing json field " + key(mKeyPrefix, name));
127         }
128         checkType(object, json_type_array);
129
130         std::string k = key(mKeyPrefix, name);
131         int length = getArraySize(k, object);
132         value.resize(static_cast<size_t>(length));
133         FromKVJsonVisitor visitor(*this, name);
134         for (int i = 0; i < length; ++i) {
135             visitor.getValue(i, value[i]);
136         }
137     }
138
139     template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
140     void getValue(int i, T& t)
141     {
142         json_object* object = json_object_array_get_idx(mObject, i);
143         std::string k = key(mKeyPrefix, std::to_string(i));
144         if (mStorePtr->exists(k)) {
145             t = mStorePtr->get<T>(k);
146         }
147         else {
148             fromJsonObject(object, t);
149         }
150     }
151
152     template<typename T, typename std::enable_if<isVisitable<T>::value, int>::type = 0>
153     void getValue(int i, T& t)
154     {
155         FromKVJsonVisitor visitor(*this, i);
156         t.accept(visitor);
157     }
158
159     template<typename T>
160     void getValue(int i, std::vector<T>& value)
161     {
162         std::string k = key(mKeyPrefix, std::to_string(i));
163         int length = getArraySize(k, mObject);
164         value.resize(static_cast<size_t>(length));
165         FromKVJsonVisitor visitor(*this, i);
166         for (int i = 0; i < length; ++i) {
167             visitor.getValue(i, value[i]);
168         }
169     }
170
171     static void checkType(json_object* object, json_type type)
172     {
173         if (type != json_object_get_type(object)) {
174             throw ConfigException("Invalid field type " + std::to_string(type));
175         }
176     }
177
178     static void fromJsonObject(json_object* object, int& value)
179     {
180         checkType(object, json_type_int);
181         std::int64_t value64 = json_object_get_int64(object);
182         if (value64 > INT32_MAX || value64 < INT32_MIN) {
183             throw ConfigException("Value out of range");
184         }
185         value = static_cast<int>(value64);
186     }
187
188     static void fromJsonObject(json_object* object, std::int64_t& value)
189     {
190         checkType(object, json_type_int);
191         value = json_object_get_int64(object);
192     }
193
194     static void fromJsonObject(json_object* object, bool& value)
195     {
196         checkType(object, json_type_boolean);
197         value = json_object_get_boolean(object);
198     }
199
200     static void fromJsonObject(json_object* object, double& value)
201     {
202         checkType(object, json_type_double);
203         value = json_object_get_double(object);
204     }
205
206     static void fromJsonObject(json_object* object, std::string& value)
207     {
208         checkType(object, json_type_string);
209         value = json_object_get_string(object);
210     }
211 };
212
213 } // namespace config
214
215 #endif // CONFIG_FROM_KVJSON_VISITOR_HPP