Initial import to Git
[profile/ivi/common-api-dbus-runtime.git] / src / CommonAPI / DBus / DBusStubAdapterHelper.h
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 #ifndef COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_
5 #define COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_
6
7 #include "DBusStubAdapter.h"
8 #include "DBusInputStream.h"
9 #include "DBusOutputStream.h"
10 #include "DBusHelper.h"
11
12 #include <iostream>
13 #include <memory>
14 #include <initializer_list>
15 #include <tuple>
16 #include <unordered_map>
17
18 namespace CommonAPI {
19 namespace DBus {
20
21 template <typename _StubClass>
22 class DBusStubAdapterHelper: public DBusStubAdapter, public std::enable_shared_from_this<typename _StubClass::StubAdapterType> {
23  public:
24     typedef typename _StubClass::StubAdapterType StubAdapterType;
25     typedef typename _StubClass::RemoteEventHandlerType RemoteEventHandlerType;
26
27     class StubDispatcher {
28      public:
29         virtual ~StubDispatcher() { }
30         virtual bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelper<_StubClass>& dbusStubAdapterHelper) = 0;
31     };
32
33  public:
34     DBusStubAdapterHelper(const std::string& dbusBusName,
35                           const std::string& dbusObjectPath,
36                           const std::string& interfaceName,
37                           const std::shared_ptr<DBusProxyConnection>& dbusConnection,
38                           std::shared_ptr<_StubClass> stub):
39                     DBusStubAdapter(dbusBusName, dbusObjectPath, interfaceName, dbusConnection),
40                     stub_(stub) {
41     }
42
43     virtual ~DBusStubAdapterHelper() { }
44
45     virtual void init() {
46         DBusStubAdapter::init();
47         remoteEventHandler_ = stub_->initStubAdapter(getStubAdapter());
48     }
49
50     inline std::shared_ptr<StubAdapterType> getStubAdapter() {
51         return this->shared_from_this();
52     }
53
54     inline const std::shared_ptr<_StubClass>& getStub() {
55         return stub_;
56     }
57
58     inline RemoteEventHandlerType* getRemoteEventHandler() {
59         return remoteEventHandler_;
60     }
61
62  protected:
63     // interfaceMemberName, interfaceMemberSignature
64     typedef std::pair<const char*, const char*> DBusInterfaceMemberPath;
65     typedef std::unordered_map<DBusInterfaceMemberPath, StubDispatcher*> StubDispatcherTable;
66
67     virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage) {
68         const char* interfaceMemberName = dbusMessage.getMemberName();
69         const char* interfaceMemberSignature = dbusMessage.getSignatureString();
70
71         assert(interfaceMemberName);
72         assert(interfaceMemberSignature);
73
74         DBusInterfaceMemberPath dbusInterfaceMemberPath(interfaceMemberName, interfaceMemberSignature);
75         auto findIterator = this->stubDispatcherTable_.find(dbusInterfaceMemberPath);
76         const bool foundInterfaceMemberHandler = (findIterator != this->stubDispatcherTable_.end());
77         bool dbusMessageHandled = false;
78
79         if (foundInterfaceMemberHandler) {
80             StubDispatcher* stubDispatcher = findIterator->second;
81             dbusMessageHandled = stubDispatcher->dispatchDBusMessage(dbusMessage, *this);
82         }
83
84         return dbusMessageHandled;
85     }
86
87     std::shared_ptr<_StubClass> stub_;
88     RemoteEventHandlerType* remoteEventHandler_;
89     static const StubDispatcherTable stubDispatcherTable_;
90 };
91
92 template< class >
93 struct DBusStubSignalHelper;
94
95 template<template<class ...> class _In, class... _InArgs>
96 struct DBusStubSignalHelper<_In<_InArgs...>> {
97     template <typename _DBusStub = DBusStubAdapter>
98     static bool sendSignal(const _DBusStub& dbusStub,
99                     const char* signalName,
100                     const char* signalSignature,
101                     const _InArgs&... inArgs) {
102         DBusMessage dbusMessage = DBusMessage::createSignal(
103                         dbusStub.getObjectPath().c_str(),
104                         dbusStub.getInterfaceName(),
105                         signalName,
106                         signalSignature);
107
108         if (sizeof...(_InArgs) > 0) {
109             DBusOutputStream outputStream(dbusMessage);
110             const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...);
111             if (!success) {
112                 return false;
113             }
114             outputStream.flush();
115         }
116
117         const bool dbusMessageSent = dbusStub.getDBusConnection()->sendDBusMessage(dbusMessage);
118         return dbusMessageSent;
119     }
120 };
121
122
123
124 template< class, class >
125 class DBusMethodStubDispatcher;
126
127 template <
128     typename _StubClass,
129     template <class...> class _In, class... _InArgs>
130 class DBusMethodStubDispatcher<_StubClass, _In<_InArgs...> >: public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
131  public:
132     typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
133     typedef void (_StubClass::*_StubFunctor)(_InArgs...);
134
135     DBusMethodStubDispatcher(_StubFunctor stubFunctor):
136             stubFunctor_(stubFunctor) {
137     }
138
139     bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
140         return handleDBusMessage(dbusMessage, dbusStubAdapterHelper, typename make_sequence<sizeof...(_InArgs)>::type());
141     }
142
143  private:
144     template <int... _InArgIndices, int... _OutArgIndices>
145     inline bool handleDBusMessage(const DBusMessage& dbusMessage,
146                                   DBusStubAdapterHelperType& dbusStubAdapterHelper,
147                                   index_sequence<_InArgIndices...>) const {
148         std::tuple<_InArgs...> argTuple;
149
150         if (sizeof...(_InArgs) > 0) {
151             DBusInputStream dbusInputStream(dbusMessage);
152             const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...);
153             if (!success)
154                 return false;
155         }
156
157         (dbusStubAdapterHelper.getStub().get()->*stubFunctor_)(std::move(std::get<_InArgIndices>(argTuple))...);
158
159         return true;
160     }
161
162     _StubFunctor stubFunctor_;
163 };
164
165
166 template< class, class, class >
167 class DBusMethodWithReplyStubDispatcher;
168
169 template <
170     typename _StubClass,
171     template <class...> class _In, class... _InArgs,
172     template <class...> class _Out, class... _OutArgs>
173 class DBusMethodWithReplyStubDispatcher<_StubClass, _In<_InArgs...>, _Out<_OutArgs...> >:
174             public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
175  public:
176     typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
177     typedef void (_StubClass::*_StubFunctor)(_InArgs..., _OutArgs&...);
178
179     DBusMethodWithReplyStubDispatcher(_StubFunctor stubFunctor, const char* dbusReplySignature):
180             stubFunctor_(stubFunctor),
181             dbusReplySignature_(dbusReplySignature) {
182     }
183
184     bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
185         return handleDBusMessage(
186                         dbusMessage,
187                         dbusStubAdapterHelper,
188                         typename make_sequence_range<sizeof...(_InArgs), 0>::type(),
189                         typename make_sequence_range<sizeof...(_OutArgs), sizeof...(_InArgs)>::type());
190     }
191
192  private:
193     template <int... _InArgIndices, int... _OutArgIndices>
194     inline bool handleDBusMessage(const DBusMessage& dbusMessage,
195                                   DBusStubAdapterHelperType& dbusStubAdapterHelper,
196                                   index_sequence<_InArgIndices...>,
197                                   index_sequence<_OutArgIndices...>) const {
198         std::tuple<_InArgs..., _OutArgs...> argTuple;
199
200         if (sizeof...(_InArgs) > 0) {
201             DBusInputStream dbusInputStream(dbusMessage);
202             const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...);
203             if (!success)
204                 return false;
205         }
206
207         (dbusStubAdapterHelper.getStub().get()->*stubFunctor_)(std::move(std::get<_InArgIndices>(argTuple))..., std::get<_OutArgIndices>(argTuple)...);
208
209         DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(dbusReplySignature_);
210
211         if (sizeof...(_OutArgs) > 0) {
212             DBusOutputStream dbusOutputStream(dbusMessageReply);
213             const bool success = DBusSerializableArguments<_OutArgs...>::serialize(dbusOutputStream, std::get<_OutArgIndices>(argTuple)...);
214             if (!success)
215                 return false;
216
217             dbusOutputStream.flush();
218         }
219
220         return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply);
221     }
222
223     _StubFunctor stubFunctor_;
224     const char* dbusReplySignature_;
225 };
226
227
228 template <typename _StubClass, typename _AttributeType>
229 class DBusGetAttributeStubDispatcher: public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
230  public:
231     typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
232     typedef const _AttributeType& (_StubClass::*GetStubFunctor)();
233
234     DBusGetAttributeStubDispatcher(GetStubFunctor getStubFunctor, const char* dbusSignature):
235         getStubFunctor_(getStubFunctor),
236         dbusSignature_(dbusSignature) {
237     }
238
239     bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
240         return sendAttributeValueReply(dbusMessage, dbusStubAdapterHelper);
241     }
242
243  protected:
244     inline bool sendAttributeValueReply(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
245         DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(dbusSignature_);
246         DBusOutputStream dbusOutputStream(dbusMessageReply);
247
248         dbusOutputStream << (dbusStubAdapterHelper.getStub().get()->*getStubFunctor_)();
249         dbusOutputStream.flush();
250
251         return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply);
252     }
253
254     GetStubFunctor getStubFunctor_;
255     const char* dbusSignature_;
256 };
257
258
259 template <typename _StubClass, typename _AttributeType>
260 class DBusSetAttributeStubDispatcher: public DBusGetAttributeStubDispatcher<_StubClass, _AttributeType> {
261  public:
262     typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
263     typedef typename DBusStubAdapterHelperType::RemoteEventHandlerType RemoteEventHandlerType;
264
265     typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor;
266     typedef bool (RemoteEventHandlerType::*OnRemoteSetFunctor)(_AttributeType);
267     typedef void (RemoteEventHandlerType::*OnRemoteChangedFunctor)();
268
269     DBusSetAttributeStubDispatcher(GetStubFunctor getStubFunctor,
270                                    OnRemoteSetFunctor onRemoteSetFunctor,
271                                    OnRemoteChangedFunctor onRemoteChangedFunctor,
272                                    const char* dbusSignature) :
273                     DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor, dbusSignature),
274                     onRemoteSetFunctor_(onRemoteSetFunctor),
275                     onRemoteChangedFunctor_(onRemoteChangedFunctor) {
276     }
277
278     bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
279         bool attributeValueChanged;
280
281         if (!setAttributeValue(dbusMessage, dbusStubAdapterHelper, attributeValueChanged))
282             return false;
283
284         if (attributeValueChanged)
285             notifyOnRemoteChanged(dbusStubAdapterHelper);
286
287         return true;
288     }
289
290  protected:
291     inline bool setAttributeValue(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper, bool& attributeValueChanged) {
292         DBusInputStream dbusInputStream(dbusMessage);
293         _AttributeType attributeValue;
294         dbusInputStream >> attributeValue;
295         if (dbusInputStream.hasError())
296             return false;
297
298         attributeValueChanged = (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteSetFunctor_)(std::move(attributeValue));
299
300         return this->sendAttributeValueReply(dbusMessage, dbusStubAdapterHelper);
301     }
302
303     inline void notifyOnRemoteChanged(DBusStubAdapterHelperType& dbusStubAdapterHelper) {
304         (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteChangedFunctor_)();
305     }
306
307     inline const _AttributeType& getAttributeValue(DBusStubAdapterHelperType& dbusStubAdapterHelper) {
308         return (dbusStubAdapterHelper.getStub().get()->*(this->getStubFunctor_))();
309     }
310
311     const OnRemoteSetFunctor onRemoteSetFunctor_;
312     const OnRemoteChangedFunctor onRemoteChangedFunctor_;
313 };
314
315
316 template <typename _StubClass, typename _AttributeType>
317 class DBusSetObservableAttributeStubDispatcher: public DBusSetAttributeStubDispatcher<_StubClass, _AttributeType> {
318  public:
319     typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
320     typedef typename DBusStubAdapterHelperType::StubAdapterType StubAdapterType;
321
322     typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor;
323     typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteSetFunctor OnRemoteSetFunctor;
324     typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteChangedFunctor OnRemoteChangedFunctor;
325     typedef void (StubAdapterType::*FireChangedFunctor)(const _AttributeType&);
326
327     DBusSetObservableAttributeStubDispatcher(GetStubFunctor getStubFunctor,
328                                              OnRemoteSetFunctor onRemoteSetFunctor,
329                                              OnRemoteChangedFunctor onRemoteChangedFunctor,
330                                              FireChangedFunctor fireChangedFunctor,
331                                              const char* dbusSignature) :
332                     DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor,
333                                                                                onRemoteSetFunctor,
334                                                                                onRemoteChangedFunctor,
335                                                                                dbusSignature),
336                     fireChangedFunctor_(fireChangedFunctor) {
337     }
338
339     bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
340         bool attributeValueChanged;
341         if (!this->setAttributeValue(dbusMessage, dbusStubAdapterHelper, attributeValueChanged))
342             return false;
343
344         if (attributeValueChanged) {
345             fireAttributeValueChanged(dbusStubAdapterHelper);
346             this->notifyOnRemoteChanged(dbusStubAdapterHelper);
347         }
348         return true;
349     }
350
351  private:
352     inline void fireAttributeValueChanged(DBusStubAdapterHelperType& dbusStubAdapterHelper) {
353         (dbusStubAdapterHelper.getStubAdapter().get()->*fireChangedFunctor_)(this->getAttributeValue(dbusStubAdapterHelper));
354     }
355
356     const FireChangedFunctor fireChangedFunctor_;
357 };
358
359 } // namespace DBus
360 } // namespace CommonAPI
361
362 #endif // COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_