// Copyright (C) 2015-2020 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. #if !defined (COMMONAPI_INTERNAL_COMPILATION) #error "Only can be included directly, this file may disappear or change contents." #endif #ifndef COMMONAPI_DBUS_DBUSFREEDESKTOPSTUBADAPTERHELPER_HPP_ #define COMMONAPI_DBUS_DBUSFREEDESKTOPSTUBADAPTERHELPER_HPP_ #include #include # if _MSC_VER >= 1300 /* * Diamond inheritance is used for the DBusSetAttributeStubDispatcher base class. * The Microsoft compiler put warning (C4250) using a desired c++ feature: "Delegating to a sister class" * A powerful technique that arises from using virtual inheritance is to delegate a method from a class in another class * by using a common abstract base class. This is also called cross delegation. */ # pragma warning( disable : 4250 ) # endif namespace CommonAPI { namespace DBus { template class DBusGetFreedesktopAttributeStubDispatcherBase { public: virtual ~DBusGetFreedesktopAttributeStubDispatcherBase() {} virtual void dispatchDBusMessageAndAppendReply(const DBusMessage &_message, const std::shared_ptr &_stub, DBusOutputStream &_output, const std::shared_ptr &_clientId) = 0; }; template class DBusGetFreedesktopAttributeStubDispatcher : public virtual DBusGetAttributeStubDispatcher, public virtual DBusGetFreedesktopAttributeStubDispatcherBase { public: typedef typename DBusGetAttributeStubDispatcher::LockStubFunctor LockStubFunctor; typedef typename DBusGetAttributeStubDispatcher::GetStubFunctor GetStubFunctor; DBusGetFreedesktopAttributeStubDispatcher(LockStubFunctor _lockStubFunctor, GetStubFunctor _getStubFunctor, const bool _isImplemented, AttributeDepl_ *_depl = nullptr) : DBusGetAttributeStubDispatcher(_lockStubFunctor, _getStubFunctor, "v", _isImplemented, _depl) { } virtual ~DBusGetFreedesktopAttributeStubDispatcher() {}; void dispatchDBusMessageAndAppendReply(const DBusMessage &_message, const std::shared_ptr &_stub, DBusOutputStream &_output, const std::shared_ptr &_clientId) { (void)_message; VariantDeployment actualDepl(true, DBusGetAttributeStubDispatcher::depl_); CommonAPI::Deployable, VariantDeployment> deployedVariant( (_stub.get()->*(DBusGetAttributeStubDispatcher::getStubFunctor_))(_clientId), &actualDepl); _output << deployedVariant; } protected: virtual bool sendAttributeValueReply(const DBusMessage &_message, const std::shared_ptr &_stub, std::weak_ptr connection_) { DBusMessage reply = _message.createMethodReturn(DBusGetAttributeStubDispatcher::signature_); VariantDeployment actualDepl(true, DBusGetAttributeStubDispatcher::depl_); std::shared_ptr clientId = std::make_shared(std::string(_message.getSender())); CommonAPI::Deployable, VariantDeployment> deployedVariant( (_stub.get()->*(DBusGetAttributeStubDispatcher::getStubFunctor_))(clientId), &actualDepl); DBusOutputStream output(reply); output << deployedVariant; output.flush(); if (std::shared_ptr connection = connection_.lock()) { return connection->sendDBusMessage(reply); } else { return false; } } }; template class DBusSetFreedesktopAttributeStubDispatcher : public virtual DBusGetFreedesktopAttributeStubDispatcher, public virtual DBusSetAttributeStubDispatcher { public: typedef typename DBusGetAttributeStubDispatcher::LockStubFunctor LockStubFunctor; typedef typename DBusGetAttributeStubDispatcher::GetStubFunctor GetStubFunctor; typedef typename StubClass_::RemoteEventHandlerType RemoteEventHandlerType; typedef bool (RemoteEventHandlerType::*OnRemoteSetFunctor)(std::shared_ptr, AttributeType_); typedef void (RemoteEventHandlerType::*OnRemoteChangedFunctor)(); DBusSetFreedesktopAttributeStubDispatcher(LockStubFunctor _lockStubFunctor, GetStubFunctor _getStubFunctor, OnRemoteSetFunctor _onRemoteSetFunctor, OnRemoteChangedFunctor _onRemoteChangedFunctor, const bool _isImplemented, AttributeDepl_ * _depl = nullptr) : DBusGetAttributeStubDispatcher(_lockStubFunctor, _getStubFunctor, "v", _isImplemented, _depl), DBusGetFreedesktopAttributeStubDispatcher(_lockStubFunctor, _getStubFunctor, _isImplemented, _depl), DBusSetAttributeStubDispatcher(_lockStubFunctor, _getStubFunctor, _onRemoteSetFunctor, _onRemoteChangedFunctor, "v", _isImplemented, _depl) { } virtual ~DBusSetFreedesktopAttributeStubDispatcher() {}; protected: virtual AttributeType_ retrieveAttributeValue(const DBusMessage &_message, bool &_error) { std::string interfaceName, attributeName; DBusInputStream input(_message); VariantDeployment actualDepl(true, DBusGetAttributeStubDispatcher::depl_); CommonAPI::Deployable, VariantDeployment> deployedVariant(&actualDepl); input >> interfaceName; // skip over interface and attribute name input >> attributeName; input >> deployedVariant; _error = input.hasError(); AttributeType_ attributeValue = deployedVariant.getValue().template get() ; return attributeValue; } }; template class DBusSetFreedesktopObservableAttributeStubDispatcher : public virtual DBusSetFreedesktopAttributeStubDispatcher, public virtual DBusSetObservableAttributeStubDispatcher { public: typedef typename DBusSetFreedesktopAttributeStubDispatcher::LockStubFunctor LockStubFunctor; typedef typename DBusSetFreedesktopAttributeStubDispatcher::GetStubFunctor GetStubFunctor; typedef typename DBusSetFreedesktopAttributeStubDispatcher::OnRemoteSetFunctor OnRemoteSetFunctor; typedef typename DBusSetFreedesktopAttributeStubDispatcher::OnRemoteChangedFunctor OnRemoteChangedFunctor; typedef typename StubClass_::StubAdapterType StubAdapterType; typedef void (StubAdapterType::*FireChangedFunctor)(const AttributeType_&); DBusSetFreedesktopObservableAttributeStubDispatcher(LockStubFunctor _lockStubFunctor, GetStubFunctor _getStubFunctor, OnRemoteSetFunctor _onRemoteSetFunctor, OnRemoteChangedFunctor _onRemoteChangedFunctor, FireChangedFunctor _fireChangedFunctor, const bool _isImplemented, AttributeDepl_ *_depl = nullptr) : DBusGetAttributeStubDispatcher(_lockStubFunctor, _getStubFunctor, "v", _isImplemented, _depl), DBusGetFreedesktopAttributeStubDispatcher(_lockStubFunctor, _getStubFunctor, _isImplemented, _depl), DBusSetAttributeStubDispatcher(_lockStubFunctor, _getStubFunctor, _onRemoteSetFunctor, _onRemoteChangedFunctor, "v", _isImplemented, _depl), DBusSetFreedesktopAttributeStubDispatcher(_lockStubFunctor, _getStubFunctor, _onRemoteSetFunctor, _onRemoteChangedFunctor, _isImplemented, _depl), DBusSetObservableAttributeStubDispatcher(_lockStubFunctor, _getStubFunctor, _onRemoteSetFunctor, _onRemoteChangedFunctor, _fireChangedFunctor, "v", _isImplemented, _depl) { } }; template struct DBusStubFreedesktopPropertiesSignalHelper; template struct DBusStubFreedesktopPropertiesSignalHelper { typedef std::unordered_map> PropertyMap; typedef MapDeployment> PropertyMapDeployment; typedef Deployable DeployedPropertyMap; template static bool sendPropertiesChangedSignal(const StubClass_ &_stub, const std::string &_propertyName, const DataType_ &_inArg, DeplType_ *_depl) { const std::vector invalidatedProperties; // fill out property map PropertyMap changedProperties; changedProperties[_propertyName] = _inArg; VariantDeployment actualDepl(true, _depl); PropertyMapDeployment changedPropertiesDeployment(nullptr, &actualDepl); DeployedPropertyMap deployedChangedProperties(changedProperties, &changedPropertiesDeployment); return DBusStubSignalHelper< DBusSerializableArguments< const std::string, DeployedPropertyMap, std::vector > >::sendSignal( _stub.getDBusAddress().getObjectPath().c_str(), "org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", _stub.getDBusConnection(), _stub.getDBusAddress().getInterface(), deployedChangedProperties, invalidatedProperties); } }; } // namespace DBus } // namespace CommonAPI #endif // COMMONAPI_DBUS_DBUSFREEDESKTOPSTUBADAPTERHELPER_HPP_