174bbad8ad504c3287f9af751212e1a738a33c86
[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) :
37         mStorePtr(new KVStore(db))
38     {
39         mObject = json_tokener_parse(json.c_str());
40         if (mObject == nullptr) {
41             throw ConfigException("Json parsing error");
42         }
43     }
44
45     ~FromKVJsonVisitor() {
46         json_object_put(mObject);
47     }
48
49     FromKVJsonVisitor(const FromKVJsonVisitor& v) :
50         mObject(json_object_get(v.mObject)),
51         mStorePtr(v.mStorePtr),
52         mKeyPrefix(v.mKeyPrefix)
53     {
54     }
55     FromKVJsonVisitor& operator=(const FromKVJsonVisitor&) = delete;
56
57     template<typename T>
58     void visit(const std::string& name, T& value) {
59         getValue(name, value);
60     }
61
62 private:
63     std::shared_ptr<KVStore> mStorePtr;
64     std::string mKeyPrefix;
65     json_object* mObject;
66
67     // create visitor for field object (visitable object)
68     FromKVJsonVisitor(const FromKVJsonVisitor& v, const std::string& name) :
69         mStorePtr(v.mStorePtr)
70     {
71         json_object* object;
72         if (!json_object_object_get_ex(v.mObject, name.c_str(), &object)) {
73             throw ConfigException("Missing json field " + key(mKeyPrefix, name));
74         }
75         mObject = json_object_get(object);
76         mKeyPrefix = key(v.mKeyPrefix, name);
77     }
78
79     // create visitor for vector i-th element (visitable object)
80     FromKVJsonVisitor(const FromKVJsonVisitor& v, int i) :
81         mStorePtr(v.mStorePtr)
82     {
83         json_object* object = json_object_array_get_idx(v.mObject, i);
84         checkType(object, json_type_object);
85         mObject = json_object_get(object);
86         mKeyPrefix = key(v.mKeyPrefix, std::to_string(i));
87     }
88
89     template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
90     void getValue(const std::string& name, T& t)
91     {
92         json_object* object;
93         if (!json_object_object_get_ex(mObject, name.c_str(), &object)) {
94             throw ConfigException("Missing json field " + key(mKeyPrefix, name));
95         }
96         std::string k = key(mKeyPrefix, name);
97         if (mStorePtr->exists(k)) {
98             t = mStorePtr->get<T>(k);
99         }
100         else {
101             fromJsonObject(object, t);
102         }
103     }
104
105     template<typename T, typename std::enable_if<isVisitable<T>::value, int>::type = 0>
106     void getValue(const std::string& name, T& t)
107     {
108         FromKVJsonVisitor visitor(*this, name);
109         t.accept(visitor);
110     }
111
112     int getArraySize(std::string& name, json_object* object)
113     {
114         int length = -1, jlength = json_object_array_length(object);
115         if (mStorePtr->exists(name)) {
116             length = mStorePtr->get<int>(name);
117         }
118         return length != jlength ? jlength : length;
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