/* HANDLILNG-PATTERNS.hpp - Collection of predefined command handling patterns Copyright (C) Lumiera.org 2009, Hermann Vosseler This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file handling-patterns.hpp ** A hard wired collection of predefined command handling patterns. ** There is a small number of different possibilities to handle execution ** and UNDO of proc-Layer commands. Each of these is defined as a subclass ** in this header and then hard wired into a small table. Handling patterns ** are stateless singleton objects, thus we build using multiple Singleton ** factory objects and configure them hard wired with the respective ** implementation classes. The index positions in this table match ** the sequence within the enum HandlingPattern::ID; all of this ** is done hard wired and without any dynamic configuration. ** ** @see ProcDispatcher ** @see Session ** */ #ifndef CONTROL_HANDLING_PATTERNS_DEF_H #define CONTROL_HANDLING_PATTERNS_DEF_H #include "lib/error.hpp" #include "lib/multifact.hpp" #include "proc/control/handling-pattern.hpp" #include "proc/control/command-impl.hpp" namespace proc { namespace control { namespace { // concrete command handling patterns /** * Handling Pattern Foundation: invoke command directly and without * any external intervention. This pattern is intended as implementation * base class, but can be used as-is for unit tests. */ class BasicHandlingPattern : public HandlingPattern { bool isValid() const { return true; } void exec (CommandImpl& command) const { REQUIRE (command.canExec()); command.invokeCapture(); command.invokeOperation(); } void undo (CommandImpl& command) const { REQUIRE (command.canUndo()); command.invokeUndo(); } /* == invoking operation or undo == */ void perform (CommandImpl& command) const { return exec(command); } class UndoProxyPattern ///< standard UNDO implementation by reconfiguring a base Pattern : public HandlingPattern { BasicHandlingPattern& basePatt_; bool isValid() const { return basePatt_.isValid(); } void exec (CommandImpl& command) const { return basePatt_.exec(command); } void undo (CommandImpl& command) const { return basePatt_.undo(command); } void perform (CommandImpl& command) const { return undo(command); } HandlingPattern const& getUndoPatt() const { return basePatt_; } public: UndoProxyPattern (BasicHandlingPattern& refPattern) : basePatt_(refPattern) { } }; HandlingPattern const& getUndoPatt() const { return standardUndoPattern_; } UndoProxyPattern standardUndoPattern_; friend class UndoProxyPattern; public: BasicHandlingPattern() : standardUndoPattern_(*this) { } }; /** * Handling Pattern: invoke blocking, translate exceptions into an error state * @todo describe this pattern in more detail.... * @todo unimplemented... */ class InvokeSyncNoThrow : public BasicHandlingPattern { void exec (CommandImpl& command) const { UNIMPLEMENTED ("actually invoke a command, according to this pattern"); } void undo (CommandImpl& command) const { UNIMPLEMENTED ("actually undo the effect of a command, according to this pattern"); } bool isValid() const { UNIMPLEMENTED ("is this pattern currently able to handle commands?"); } }; /** * Handling Pattern: invoke blocking, propagating any exceptions immediately * @todo is throwing here helpful, and how to integrate it into ExecResult...? * @todo describe this pattern in more detail.... * @todo unimplemented... */ class InvokeSyncThrow : public BasicHandlingPattern { void exec (CommandImpl& command) const { UNIMPLEMENTED ("actually invoke a command, according to this pattern"); } void undo (CommandImpl& command) const { UNIMPLEMENTED ("actually undo the effect of a command, according to this pattern"); } bool isValid() const { UNIMPLEMENTED ("is this pattern currently able to handle commands?"); } }; /** * Handling Pattern: just schedule command to be invoked asynchronously * @todo clarify what "async" means and if we need it..... * @todo describe this pattern in more detail.... * @todo unimplemented... */ class InvokeAsync : public BasicHandlingPattern { void exec (CommandImpl& command) const { UNIMPLEMENTED ("actually invoke a command, according to this pattern"); } void undo (CommandImpl& command) const { UNIMPLEMENTED ("actually undo the effect of a command, according to this pattern"); } bool isValid() const { UNIMPLEMENTED ("is this pattern currently able to handle commands?"); } }; /* ======== Handling Pattern Table ========== */ typedef lib::MultiFact HandlingPatternFactory; /** holds singleton pattern instances by ID */ HandlingPatternFactory patternTable; HandlingPatternFactory::Singleton holder1 (patternTable, HandlingPattern::SYNC); HandlingPatternFactory::Singleton holder2 (patternTable, HandlingPattern::SYNC_THROW); HandlingPatternFactory::Singleton holder3 (patternTable, HandlingPattern::ASYNC); HandlingPatternFactory::Singleton holder4 (patternTable, HandlingPattern::DUMMY); /** access the singleton instance for a given ID */ inline HandlingPattern const& getPatternInstance (HandlingPattern::ID id) { REQUIRE (patternTable.contains(id)); return patternTable (id); } } // (END) definition of concrete handling patterns }} // namespace proc::control #endif