/******************************************************************************** * Copyright (C) 2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * * * * This software is distributed under the terms of the * * GNU Lesser General Public Licence (LGPL) version 3, * * copied verbatim in the file "LICENSE" * ********************************************************************************/ #ifndef FAIR_MQ_SDK_COMMANDFACTORY #define FAIR_MQ_SDK_COMMANDFACTORY #include #include #include #include #include #include #include namespace fair { namespace mq { namespace sdk { namespace cmd { enum class Format : int { Binary, JSON }; enum class Result : int { Ok, Failure }; enum class Type : int { check_state, // args: { } change_state, // args: { transition } dump_config, // args: { } subscribe_to_heartbeats, // args: { } unsubscribe_from_heartbeats, // args: { } subscribe_to_state_change, // args: { } unsubscribe_from_state_change, // args: { } state_change_exiting_received, // args: { } current_state, // args: { device_id, current_state } transition_status, // args: { device_id, Result, transition } config, // args: { device_id, config_string } heartbeat_subscription, // args: { device_id, Result } heartbeat_unsubscription, // args: { device_id, Result } heartbeat, // args: { device_id } state_change_subscription, // args: { device_id, Result } state_change_unsubscription, // args: { device_id, Result } state_change // args: { device_id, task_id, last_state, current_state } }; struct Cmd { explicit Cmd(const Type type) : fType(type) {} Type GetType() const { return fType; } private: Type fType; }; struct CheckState : Cmd { explicit CheckState() : Cmd(Type::check_state) {} }; struct ChangeState : Cmd { explicit ChangeState(Transition transition) : Cmd(Type::change_state) , fTransition(transition) {} Transition GetTransition() const { return fTransition; } void SetTransition(Transition transition) { fTransition = transition; } private: Transition fTransition; }; struct DumpConfig : Cmd { explicit DumpConfig() : Cmd(Type::dump_config) {} }; struct SubscribeToHeartbeats : Cmd { explicit SubscribeToHeartbeats() : Cmd(Type::subscribe_to_heartbeats) {} }; struct UnsubscribeFromHeartbeats : Cmd { explicit UnsubscribeFromHeartbeats() : Cmd(Type::unsubscribe_from_heartbeats) {} }; struct SubscribeToStateChange : Cmd { explicit SubscribeToStateChange() : Cmd(Type::subscribe_to_state_change) {} }; struct UnsubscribeFromStateChange : Cmd { explicit UnsubscribeFromStateChange() : Cmd(Type::unsubscribe_from_state_change) {} }; struct StateChangeExitingReceived : Cmd { explicit StateChangeExitingReceived() : Cmd(Type::state_change_exiting_received) {} }; struct CurrentState : Cmd { explicit CurrentState(const std::string& id, State currentState) : Cmd(Type::current_state) , fDeviceId(id) , fCurrentState(currentState) {} std::string GetDeviceId() const { return fDeviceId; } void SetDeviceId(const std::string& deviceId) { fDeviceId = deviceId; } fair::mq::State GetCurrentState() const { return fCurrentState; } void SetCurrentState(fair::mq::State state) { fCurrentState = state; } private: std::string fDeviceId; fair::mq::State fCurrentState; }; struct TransitionStatus : Cmd { explicit TransitionStatus(const std::string& id, const Result result, const Transition transition) : Cmd(Type::transition_status) , fDeviceId(id) , fResult(result) , fTransition(transition) {} std::string GetDeviceId() const { return fDeviceId; } void SetDeviceId(const std::string& deviceId) { fDeviceId = deviceId; } Result GetResult() const { return fResult; } void SetResult(const Result result) { fResult = result; } Transition GetTransition() const { return fTransition; } void SetTransition(const Transition transition) { fTransition = transition; } private: std::string fDeviceId; Result fResult; Transition fTransition; }; struct Config : Cmd { explicit Config(const std::string& id, const std::string& config) : Cmd(Type::config) , fDeviceId(id) , fConfig(config) {} std::string GetDeviceId() const { return fDeviceId; } void SetDeviceId(const std::string& deviceId) { fDeviceId = deviceId; } std::string GetConfig() const { return fConfig; } void SetConfig(const std::string& config) { fConfig = config; } private: std::string fDeviceId; std::string fConfig; }; struct HeartbeatSubscription : Cmd { explicit HeartbeatSubscription(const std::string& id, const Result result) : Cmd(Type::heartbeat_subscription) , fDeviceId(id) , fResult(result) {} std::string GetDeviceId() const { return fDeviceId; } void SetDeviceId(const std::string& deviceId) { fDeviceId = deviceId; } Result GetResult() const { return fResult; } void SetResult(const Result result) { fResult = result; } private: std::string fDeviceId; Result fResult; }; struct HeartbeatUnsubscription : Cmd { explicit HeartbeatUnsubscription(const std::string& id, const Result result) : Cmd(Type::heartbeat_unsubscription) , fDeviceId(id) , fResult(result) {} std::string GetDeviceId() const { return fDeviceId; } void SetDeviceId(const std::string& deviceId) { fDeviceId = deviceId; } Result GetResult() const { return fResult; } void SetResult(const Result result) { fResult = result; } private: std::string fDeviceId; Result fResult; }; struct Heartbeat : Cmd { explicit Heartbeat(const std::string& id) : Cmd(Type::heartbeat) , fDeviceId(id) {} std::string GetDeviceId() const { return fDeviceId; } void SetDeviceId(const std::string& deviceId) { fDeviceId = deviceId; } private: std::string fDeviceId; }; struct StateChangeSubscription : Cmd { explicit StateChangeSubscription(const std::string& id, const Result result) : Cmd(Type::state_change_subscription) , fDeviceId(id) , fResult(result) {} std::string GetDeviceId() const { return fDeviceId; } void SetDeviceId(const std::string& deviceId) { fDeviceId = deviceId; } Result GetResult() const { return fResult; } void SetResult(const Result result) { fResult = result; } private: std::string fDeviceId; Result fResult; }; struct StateChangeUnsubscription : Cmd { explicit StateChangeUnsubscription(const std::string& id, const Result result) : Cmd(Type::state_change_unsubscription) , fDeviceId(id) , fResult(result) {} std::string GetDeviceId() const { return fDeviceId; } void SetDeviceId(const std::string& deviceId) { fDeviceId = deviceId; } Result GetResult() const { return fResult; } void SetResult(const Result result) { fResult = result; } private: std::string fDeviceId; Result fResult; }; struct StateChange : Cmd { explicit StateChange(const std::string& deviceId, const uint64_t taskId, const State lastState, const State currentState) : Cmd(Type::state_change) , fDeviceId(deviceId) , fTaskId(taskId) , fLastState(lastState) , fCurrentState(currentState) {} std::string GetDeviceId() const { return fDeviceId; } void SetDeviceId(const std::string& deviceId) { fDeviceId = deviceId; } uint64_t GetTaskId() const { return fTaskId; } void SetTaskId(const uint64_t taskId) { fTaskId = taskId; } fair::mq::State GetLastState() const { return fLastState; } void SetLastState(const fair::mq::State state) { fLastState = state; } fair::mq::State GetCurrentState() const { return fCurrentState; } void SetCurrentState(const fair::mq::State state) { fCurrentState = state; } private: std::string fDeviceId; uint64_t fTaskId; fair::mq::State fLastState; fair::mq::State fCurrentState; }; template std::unique_ptr make(Args&&... args) { return fair::mq::tools::make_unique(std::forward(args)...); } struct Cmds { using container = std::vector>; struct CommandFormatError : std::runtime_error { using std::runtime_error::runtime_error; }; explicit Cmds() {} template explicit Cmds(std::unique_ptr&& first, Rest&&... rest) { Unpack(std::forward&&>(first), std::forward(rest)...); } void Add(std::unique_ptr&& cmd) { fCmds.emplace_back(std::move(cmd)); } template void Add(Args&&... args) { static_assert(std::is_base_of::value, "Only types derived from fair::mq::cmd::Cmd are allowed"); Add(make(std::forward(args)...)); } Cmd& At(size_t i) { return *(fCmds.at(i)); } size_t Size() const { return fCmds.size(); } void Reset() { fCmds.clear(); } std::string Serialize(const Format type = Format::Binary) const; void Deserialize(const std::string&, const Format type = Format::Binary); private: container fCmds; void Unpack() {} template void Unpack(std::unique_ptr&& first, Rest&&... rest) { fCmds.emplace_back(std::move(first)); Unpack(std::forward(rest)...); } public: using iterator = container::iterator; using const_iterator = container::const_iterator; auto begin() -> decltype(fCmds.begin()) { return fCmds.begin(); } auto end() -> decltype(fCmds.end()) { return fCmds.end(); } auto cbegin() -> decltype(fCmds.cbegin()) { return fCmds.cbegin(); } auto cend() -> decltype(fCmds.cend()) { return fCmds.cend(); } }; std::string GetResultName(const Result result); std::string GetTypeName(const Type type); inline std::ostream& operator<<(std::ostream& os, const Result& result) { return os << GetResultName(result); } inline std::ostream& operator<<(std::ostream& os, const Type& type) { return os << GetTypeName(type); } } /* namespace cmd */ } /* namespace sdk */ } /* namespace mq */ } /* namespace fair */ #endif /* FAIR_MQ_SDK_COMMANDFACTORY */