[AMBClient] - fixed json stream handling
[profile/ivi/automotive-message-broker.git] / plugins / common / jsonprotocol.h
1 /*
2 Copyright (C) 2015 Intel Corporation
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18
19 #ifndef AMB_JSON_PROTOCOL_H_
20 #define AMB_JSON_PROTOCOL_H_
21
22 #include <functional>
23 #include <memory>
24 #include <string>
25 #include <unordered_map>
26 #include <vector>
27
28 #include <abstractroutingengine.h>
29 #include <mappropertytype.hpp>
30 #include <picojson.h>
31 #include <uuidhelper.h>
32 #include <vehicleproperty.h>
33
34 #include "abstractio.hpp"
35
36
37 namespace amb
38 {
39
40 class Object : public std::unordered_map<std::string, std::shared_ptr<AbstractPropertyType>>
41 {
42 public:
43         Object(): std::unordered_map<std::string, std::shared_ptr<AbstractPropertyType>>() { }
44         Object(const std::string & ifaceName): std::unordered_map<std::string, std::shared_ptr<AbstractPropertyType>>(),
45                 interfaceName(ifaceName)
46         {
47
48         }
49
50         static Object fromJson(const picojson::object & obj);
51
52         static picojson::value toJson(const Object & obj);
53
54         std::string interfaceName;
55
56 };
57
58 class BaseMessage
59 {
60 public:
61         BaseMessage() { }
62
63         BaseMessage(std::string n, std::string t)
64                 : name(n), type(t)
65         {
66                 messageId = amb::createUuid();
67         }
68
69         BaseMessage(const BaseMessage & other)
70                 : name(other.name), type(other.type), data(other.data)
71         {
72
73         }
74
75         std::string name;
76         std::string type;
77
78         std::string messageId;
79
80         virtual picojson::value toJson();
81         virtual bool fromJson(const picojson::value & json);
82
83         template <typename T>
84         bool is()
85         {
86                 return T::is(this);
87         }
88
89         static bool validate(const picojson::value & json)
90         {
91                 return json.is<picojson::object>() && json.contains("type") && json.contains("name") && json.contains("messageId");
92         }
93
94         template <typename T>
95         static bool is(const picojson::value & json)
96         {
97                 return T::is(json);
98         }
99
100 protected:
101
102         picojson::value data;
103
104 private:
105 };
106
107 class MethodCall : public BaseMessage
108 {
109 public:
110         MethodCall(std::string name)
111                 :BaseMessage(name, "method"), zone(Zone::None), success(false)
112         {
113
114         }
115
116         MethodCall(const BaseMessage & other)
117                 :BaseMessage(other), zone(Zone::None), success(false)
118         {
119                 name = other.name;
120         }
121
122         MethodCall(const MethodCall & other)
123                 :MethodCall(other.name)
124         {
125                 sourceUuid = other.sourceUuid;
126                 zone = other.zone;
127                 success = other.success;
128         }
129
130         static bool is(const BaseMessage * msg)
131         {
132                 return (msg->type == "method");
133         }
134
135         /*!
136          * \brief is checks if json message is of this message type
137          * Assumes that json is already a valid \ref BaseMessage
138          * \param json
139          * \return
140          */
141         static bool is(const picojson::value & json)
142         {
143                 return json.contains("source") && json.get("source").is<std::string>()
144                                 && json.contains("zone") && json.get("zone").is<double>();
145         }
146
147         virtual picojson::value toJson();
148         virtual bool fromJson(const picojson::value &json);
149
150         std::string sourceUuid;
151         Zone::Type zone;
152         bool success;
153 };
154
155 class ListMethodCall : public MethodCall
156 {
157 public:
158         ListMethodCall(): MethodCall("list") {}
159         ListMethodCall(const MethodCall & other)
160                 :MethodCall(other)
161         {
162                 if(!is(&other))
163                         throw std::runtime_error("type not list");
164         }
165
166         picojson::value toJson();
167         bool fromJson(const picojson::value &json);
168
169         std::vector<Object> objectNames;
170
171         static bool is(const BaseMessage * msg)
172         {
173                 return msg->name == "list";
174         }
175
176         static bool is(const picojson::value & json)
177         {
178                 return json.get("name").to_str() == "list";
179         }
180 };
181
182 class GetMethodCall : public MethodCall
183 {
184 public:
185         GetMethodCall()
186                 : MethodCall("get")
187         {
188
189         }
190
191         picojson::value toJson();
192         bool fromJson(const picojson::value &json);
193
194         static bool is(const BaseMessage * msg)
195         {
196                 return msg->name == "get";
197         }
198
199         static bool is(const picojson::value & json)
200         {
201                 return json.get("name").to_str() == "get";
202         }
203
204         Object value;
205 };
206
207 class SetMethodCall : public MethodCall
208 {
209 public:
210         SetMethodCall()
211                 : MethodCall("set")
212         {
213
214         }
215
216         picojson::value toJson();
217         bool fromJson(const picojson::value &json);
218
219         static bool is(const BaseMessage * msg)
220         {
221                 return msg->name == "set";
222         }
223
224         static bool is(const picojson::value & json)
225         {
226                 return json.get("name").to_str() != "set";
227         }
228
229         Object value;
230 };
231
232 class BaseJsonMessageReader
233 {
234 public:
235         BaseJsonMessageReader(AbstractIo* io);
236
237         void canHasData();
238
239 protected:
240
241         virtual void hasJsonMessage(const picojson::value & message) = 0;
242
243         template <class T>
244         void send(T & msg)
245         {
246                 std::string buff = msg.toJson().serialize()+"\n";
247                 DebugOut() << "writing: " << buff << endl;
248                 mIo->write(buff);
249         }
250
251         std::shared_ptr<AbstractIo> mIo;
252
253 private:
254
255         bool hasJson();
256
257         std::string incompleteMessage;
258
259 };
260
261 class AmbRemoteClient: public BaseJsonMessageReader
262 {
263 public:
264         typedef std::function<void (std::vector<Object>)> ListCallback;
265         typedef std::function<void (Object&)> ObjectCallback;
266         typedef std::function<void (bool)> SetCallback;
267
268         AmbRemoteClient(AbstractIo* io);
269
270         void list(ListCallback cb);
271
272         void get(const std::string & objectName, ObjectCallback cb);
273
274         void get(const std::string & objectName, const std::string & sourceUuid, ObjectCallback cb);
275
276         void get(const std::string & objectName, Zone::Type zone, ObjectCallback cb);
277
278         void get(const std::string & objectName, const std::string & sourceUuid, Zone::Type zone, ObjectCallback cb);
279
280         void set(const std::string & objectName, const Object & value, SetCallback cb);
281
282         void set(const std::string & objectName, const Object & value, const std::string & sourceUuid, Zone::Type zone, SetCallback cb);
283
284         void listen(const std::string & objectName, const std::string & sourceUuid, Zone::Type zone, ObjectCallback cb);
285
286         void listen(const std::string & objectName, ObjectCallback cb);
287
288 protected:
289
290 private:
291
292         void hasJsonMessage(const picojson::value & message);
293
294         std::string createSubscriptionId(const std::string & objectName,  const std::string & sourceUuid, Zone::Type zone);
295         std::unordered_map<std::string, ListCallback> mListCalls;
296         std::unordered_map<std::string, ObjectCallback> mGetMethodCalls;
297         std::unordered_map<std::string, SetCallback> mSetMethodCalls;
298         std::unordered_map<std::string, std::vector<ObjectCallback>> mSubsriptions;
299 };
300
301 class AmbRemoteServer : public BaseJsonMessageReader
302 {
303 public:
304         AmbRemoteServer(AbstractIo* io, AbstractRoutingEngine* routingEngine);
305
306 protected:
307
308         /*!
309          * \brief list called when a ListMessageCall was received
310          */
311         virtual void list(ListMethodCall & call);
312
313         /*!
314          * \brief get called when a GetMessageCall was received
315          */
316         virtual void get(GetMethodCall &get);
317
318         /*!
319          * \brief set called when SetMessageCall was received
320          */
321         virtual void set();
322         /*!
323          * \brief listen called when ListenMessageCall was received
324          */
325         virtual void listen();
326
327         void hasJsonMessage(const picojson::value & json);
328
329 protected:
330         AbstractRoutingEngine* routingEngine;
331
332
333 };
334
335 } //namespace amb
336
337 #endif