1 /* Copyright (C) 2013 BMW Group
2 * Author: Manfred Bathelt (manfred.bathelt@bmw.de)
3 * Author: Juergen Gehring (juergen.gehring@bmw.de)
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_
8 #define COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_
10 #include "DBusStubAdapter.h"
11 #include "DBusInputStream.h"
12 #include "DBusOutputStream.h"
13 #include "DBusHelper.h"
16 #include <initializer_list>
18 #include <unordered_map>
23 template <typename _StubClass>
24 class DBusStubAdapterHelper: public DBusStubAdapter, public std::enable_shared_from_this<typename _StubClass::StubAdapterType> {
26 typedef typename _StubClass::StubAdapterType StubAdapterType;
27 typedef typename _StubClass::RemoteEventHandlerType RemoteEventHandlerType;
29 class StubDispatcher {
31 virtual ~StubDispatcher() { }
32 virtual bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelper<_StubClass>& dbusStubAdapterHelper) = 0;
36 DBusStubAdapterHelper(const std::string& commonApiAddress,
37 const std::string& dbusInterfaceName,
38 const std::string& dbusBusName,
39 const std::string& dbusObjectPath,
40 const std::shared_ptr<DBusProxyConnection>& dbusConnection,
41 const std::shared_ptr<_StubClass>& stub):
42 DBusStubAdapter(commonApiAddress, dbusInterfaceName, dbusBusName, dbusObjectPath, dbusConnection),
46 virtual ~DBusStubAdapterHelper() {
47 stub_->deinitStubAdapter();
51 DBusStubAdapter::init();
52 remoteEventHandler_ = stub_->initStubAdapter(getStubAdapter());
55 virtual void deinit() {
56 DBusStubAdapter::deinit();
57 stub_->deinitStubAdapter();
60 inline std::shared_ptr<StubAdapterType> getStubAdapter() {
61 return this->shared_from_this();
64 inline const std::shared_ptr<_StubClass>& getStub() {
68 inline RemoteEventHandlerType* getRemoteEventHandler() {
69 return remoteEventHandler_;
73 // interfaceMemberName, interfaceMemberSignature
74 typedef std::pair<const char*, const char*> DBusInterfaceMemberPath;
75 typedef std::unordered_map<DBusInterfaceMemberPath, StubDispatcher*> StubDispatcherTable;
77 virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage) {
78 const char* interfaceMemberName = dbusMessage.getMemberName();
79 const char* interfaceMemberSignature = dbusMessage.getSignatureString();
81 assert(interfaceMemberName);
82 assert(interfaceMemberSignature);
84 DBusInterfaceMemberPath dbusInterfaceMemberPath(interfaceMemberName, interfaceMemberSignature);
85 auto findIterator = this->stubDispatcherTable_.find(dbusInterfaceMemberPath);
86 const bool foundInterfaceMemberHandler = (findIterator != this->stubDispatcherTable_.end());
87 bool dbusMessageHandled = false;
89 if (foundInterfaceMemberHandler) {
90 StubDispatcher* stubDispatcher = findIterator->second;
91 dbusMessageHandled = stubDispatcher->dispatchDBusMessage(dbusMessage, *this);
94 return dbusMessageHandled;
97 std::shared_ptr<_StubClass> stub_;
98 RemoteEventHandlerType* remoteEventHandler_;
99 static const StubDispatcherTable stubDispatcherTable_;
103 struct DBusStubSignalHelper;
105 template<template<class ...> class _In, class... _InArgs>
106 struct DBusStubSignalHelper<_In<_InArgs...>> {
107 template <typename _DBusStub = DBusStubAdapter>
108 static bool sendSignal(const _DBusStub& dbusStub,
109 const char* signalName,
110 const char* signalSignature,
111 const _InArgs&... inArgs) {
112 DBusMessage dbusMessage = DBusMessage::createSignal(
113 dbusStub.getObjectPath().c_str(),
114 dbusStub.getInterfaceName(),
118 if (sizeof...(_InArgs) > 0) {
119 DBusOutputStream outputStream(dbusMessage);
120 const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...);
124 outputStream.flush();
127 const bool dbusMessageSent = dbusStub.getDBusConnection()->sendDBusMessage(dbusMessage);
128 return dbusMessageSent;
134 template< class, class >
135 class DBusMethodStubDispatcher;
139 template <class...> class _In, class... _InArgs>
140 class DBusMethodStubDispatcher<_StubClass, _In<_InArgs...> >: public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
142 typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
143 typedef void (_StubClass::*_StubFunctor)(_InArgs...);
145 DBusMethodStubDispatcher(_StubFunctor stubFunctor):
146 stubFunctor_(stubFunctor) {
149 bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
150 return handleDBusMessage(dbusMessage, dbusStubAdapterHelper, typename make_sequence<sizeof...(_InArgs)>::type());
154 template <int... _InArgIndices, int... _OutArgIndices>
155 inline bool handleDBusMessage(const DBusMessage& dbusMessage,
156 DBusStubAdapterHelperType& dbusStubAdapterHelper,
157 index_sequence<_InArgIndices...>) const {
158 std::tuple<_InArgs...> argTuple;
160 if (sizeof...(_InArgs) > 0) {
161 DBusInputStream dbusInputStream(dbusMessage);
162 const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...);
167 (dbusStubAdapterHelper.getStub().get()->*stubFunctor_)(std::move(std::get<_InArgIndices>(argTuple))...);
172 _StubFunctor stubFunctor_;
176 template< class, class, class >
177 class DBusMethodWithReplyStubDispatcher;
181 template <class...> class _In, class... _InArgs,
182 template <class...> class _Out, class... _OutArgs>
183 class DBusMethodWithReplyStubDispatcher<_StubClass, _In<_InArgs...>, _Out<_OutArgs...> >:
184 public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
186 typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
187 typedef void (_StubClass::*_StubFunctor)(_InArgs..., _OutArgs&...);
189 DBusMethodWithReplyStubDispatcher(_StubFunctor stubFunctor, const char* dbusReplySignature):
190 stubFunctor_(stubFunctor),
191 dbusReplySignature_(dbusReplySignature) {
194 bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
195 return handleDBusMessage(
197 dbusStubAdapterHelper,
198 typename make_sequence_range<sizeof...(_InArgs), 0>::type(),
199 typename make_sequence_range<sizeof...(_OutArgs), sizeof...(_InArgs)>::type());
203 template <int... _InArgIndices, int... _OutArgIndices>
204 inline bool handleDBusMessage(const DBusMessage& dbusMessage,
205 DBusStubAdapterHelperType& dbusStubAdapterHelper,
206 index_sequence<_InArgIndices...>,
207 index_sequence<_OutArgIndices...>) const {
208 std::tuple<_InArgs..., _OutArgs...> argTuple;
210 if (sizeof...(_InArgs) > 0) {
211 DBusInputStream dbusInputStream(dbusMessage);
212 const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...);
217 (dbusStubAdapterHelper.getStub().get()->*stubFunctor_)(std::move(std::get<_InArgIndices>(argTuple))..., std::get<_OutArgIndices>(argTuple)...);
219 DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(dbusReplySignature_);
221 if (sizeof...(_OutArgs) > 0) {
222 DBusOutputStream dbusOutputStream(dbusMessageReply);
223 const bool success = DBusSerializableArguments<_OutArgs...>::serialize(dbusOutputStream, std::get<_OutArgIndices>(argTuple)...);
227 dbusOutputStream.flush();
230 return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply);
233 _StubFunctor stubFunctor_;
234 const char* dbusReplySignature_;
238 template <typename _StubClass, typename _AttributeType>
239 class DBusGetAttributeStubDispatcher: public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
241 typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
242 typedef const _AttributeType& (_StubClass::*GetStubFunctor)();
244 DBusGetAttributeStubDispatcher(GetStubFunctor getStubFunctor, const char* dbusSignature):
245 getStubFunctor_(getStubFunctor),
246 dbusSignature_(dbusSignature) {
249 bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
250 return sendAttributeValueReply(dbusMessage, dbusStubAdapterHelper);
254 inline bool sendAttributeValueReply(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
255 DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(dbusSignature_);
256 DBusOutputStream dbusOutputStream(dbusMessageReply);
258 dbusOutputStream << (dbusStubAdapterHelper.getStub().get()->*getStubFunctor_)();
259 dbusOutputStream.flush();
261 return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply);
264 GetStubFunctor getStubFunctor_;
265 const char* dbusSignature_;
269 template <typename _StubClass, typename _AttributeType>
270 class DBusSetAttributeStubDispatcher: public DBusGetAttributeStubDispatcher<_StubClass, _AttributeType> {
272 typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
273 typedef typename DBusStubAdapterHelperType::RemoteEventHandlerType RemoteEventHandlerType;
275 typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor;
276 typedef bool (RemoteEventHandlerType::*OnRemoteSetFunctor)(_AttributeType);
277 typedef void (RemoteEventHandlerType::*OnRemoteChangedFunctor)();
279 DBusSetAttributeStubDispatcher(GetStubFunctor getStubFunctor,
280 OnRemoteSetFunctor onRemoteSetFunctor,
281 OnRemoteChangedFunctor onRemoteChangedFunctor,
282 const char* dbusSignature) :
283 DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor, dbusSignature),
284 onRemoteSetFunctor_(onRemoteSetFunctor),
285 onRemoteChangedFunctor_(onRemoteChangedFunctor) {
288 bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
289 bool attributeValueChanged;
291 if (!setAttributeValue(dbusMessage, dbusStubAdapterHelper, attributeValueChanged))
294 if (attributeValueChanged)
295 notifyOnRemoteChanged(dbusStubAdapterHelper);
301 inline bool setAttributeValue(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper, bool& attributeValueChanged) {
302 DBusInputStream dbusInputStream(dbusMessage);
303 _AttributeType attributeValue;
304 dbusInputStream >> attributeValue;
305 if (dbusInputStream.hasError())
308 attributeValueChanged = (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteSetFunctor_)(std::move(attributeValue));
310 return this->sendAttributeValueReply(dbusMessage, dbusStubAdapterHelper);
313 inline void notifyOnRemoteChanged(DBusStubAdapterHelperType& dbusStubAdapterHelper) {
314 (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteChangedFunctor_)();
317 inline const _AttributeType& getAttributeValue(DBusStubAdapterHelperType& dbusStubAdapterHelper) {
318 return (dbusStubAdapterHelper.getStub().get()->*(this->getStubFunctor_))();
321 const OnRemoteSetFunctor onRemoteSetFunctor_;
322 const OnRemoteChangedFunctor onRemoteChangedFunctor_;
326 template <typename _StubClass, typename _AttributeType>
327 class DBusSetObservableAttributeStubDispatcher: public DBusSetAttributeStubDispatcher<_StubClass, _AttributeType> {
329 typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
330 typedef typename DBusStubAdapterHelperType::StubAdapterType StubAdapterType;
332 typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor;
333 typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteSetFunctor OnRemoteSetFunctor;
334 typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteChangedFunctor OnRemoteChangedFunctor;
335 typedef void (StubAdapterType::*FireChangedFunctor)(const _AttributeType&);
337 DBusSetObservableAttributeStubDispatcher(GetStubFunctor getStubFunctor,
338 OnRemoteSetFunctor onRemoteSetFunctor,
339 OnRemoteChangedFunctor onRemoteChangedFunctor,
340 FireChangedFunctor fireChangedFunctor,
341 const char* dbusSignature) :
342 DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor,
344 onRemoteChangedFunctor,
346 fireChangedFunctor_(fireChangedFunctor) {
349 bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
350 bool attributeValueChanged;
351 if (!this->setAttributeValue(dbusMessage, dbusStubAdapterHelper, attributeValueChanged))
354 if (attributeValueChanged) {
355 fireAttributeValueChanged(dbusStubAdapterHelper);
356 this->notifyOnRemoteChanged(dbusStubAdapterHelper);
362 inline void fireAttributeValueChanged(DBusStubAdapterHelperType& dbusStubAdapterHelper) {
363 (dbusStubAdapterHelper.getStubAdapter().get()->*fireChangedFunctor_)(this->getAttributeValue(dbusStubAdapterHelper));
366 const FireChangedFunctor fireChangedFunctor_;
370 } // namespace CommonAPI
372 #endif // COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_