#pragma once #include "dtcore/inc/dtdefinitions.h" #include "dtcore/inc/dtstream.h" #include "dtcore/inc/dttypeinfo.h" #include "dtcore/inc/dtmemory.h" #include "dtcore/inc/dtfunctor.h" namespace dt { class Message : public Serializable { DT_DECLARE_ROOT_TYPE(Message); public: }; ////////////////////////////////////////////////////////////////////////// class ConnectionDescriptor; class MessageFactoryImpl; class MessageCallbackAdapterBase { public: virtual ~MessageCallbackAdapterBase() {} virtual void Thunk(const ConnectionDescriptor& descriptor, const String& route, Message* msg) = 0; }; template class MessageCallbackAdapter : public MessageCallbackAdapterBase { public: MessageCallbackAdapter() {} MessageCallbackAdapter(const Functor2& callback) : m_Callback(callback) { } virtual void Thunk(const ConnectionDescriptor& descriptor, const String& route, Message* msg) override { DT_UNUSED(route); if (m_Callback) { T* casted = DynamicCast(msg); DT_ASSERT(casted); m_Callback(descriptor, casted); } } private: Functor2 m_Callback; }; template class MessageCallbackAdapterWithRoute : public MessageCallbackAdapterBase { public: MessageCallbackAdapterWithRoute() {} MessageCallbackAdapterWithRoute(const Functor3& callback) : m_Callback(callback) { } virtual void Thunk(const ConnectionDescriptor& descriptor, const String& route, Message* msg) override { if (m_Callback) { T* casted = DynamicCast(msg); DT_ASSERT(casted); m_Callback(descriptor, route, casted); } } private: Functor3 m_Callback; }; class MessageFactory { public: MessageFactory(); ~MessageFactory(); typedef Message* (*CreateFunction)(); template void Register() { RegisterInternal( T::GetExactTypeInfo()->GetName(), T::Create, nullptr, 0_s, String::Blank()); } template void Unregister() { UnregisterInternal(T::GetExactTypeInfo()->GetName()); } template void Register(U* self, V func, Seconds cachePeriodInSec = 0_s, const String& defaultRole = GetRoleDefault()) { RegisterInternal( T::GetExactTypeInfo()->GetName(), T::Create, DT_NEW(MessageCallbackAdapter)(Functor2::Bind(func, self)), cachePeriodInSec, defaultRole); } template void RegisterWithRoute(U* self, V func, Seconds cachePeriodInSec = 0_s, const String& defaultRole = GetRoleDefault()) { RegisterInternal( T::GetExactTypeInfo()->GetName(), T::Create, DT_NEW(MessageCallbackAdapterWithRoute)(Functor3::Bind(func, self)), cachePeriodInSec, defaultRole); } template void RegisterAs(U* self, V func, const String& alias, Seconds cachePeriodInSec = 0_s, const String& defaultRole = GetRoleDefault()) { RegisterInternal( alias, T::Create, DT_NEW(MessageCallbackAdapter)(Functor2::Bind(func, self)), cachePeriodInSec, defaultRole); } bool IsKnown(const String& msgType) const; Message* Create(const String& msgType) const; Seconds GetCachePeriodInSec(const String& msgType) const; const String& GetRole(const String& msgType) const; static const String& GetRoleGuest(); static const String& GetRoleReader(); static const String& GetRoleAdmin(); static const String& GetRoleInvalid(); static String GetRoleDefault(); static void SetRoleDefaultGetterFunction(const Functor0R& getter); bool Callback(const ConnectionDescriptor& descriptor, const String& route, Message* msg); private: void RegisterInternal(const String& typeName, CreateFunction createFunc, MessageCallbackAdapterBase* callback, Seconds cachePeriodInSec, const String& defaultRole); void UnregisterInternal(const String& typeName); MessageFactoryImpl* m_Impl; }; }