/*========================================================================= Program: bbtk Module: $RCSfile: bbtkBlackBox.h,v $ Language: C++ Date: $Date: 2008/01/22 15:02:00 $ Version: $Revision: 1.1 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See doc/license.txt or http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ /** * \file * \brief Class bbtk::BlackBox : abstract black-box interface. */ /** * \class bbtk::BlackBox * \brief Abstract black-box interface */ #ifndef __bbtkBlackBox_h__ #define __bbtkBlackBox_h__ #include "bbtkBlackBoxDescriptor.h" //#include "bbtkConnection.h" #include "bbtkBlackBoxInputConnector.h" #include "bbtkBlackBoxOutputConnector.h" #include namespace bbtk { struct Void { Void(int = 0) {} }; class Factory; class BBTK_EXPORT BlackBox { public: //================================================================== // INTERFACE //================================================================== /// The type of pointer on a BlackBox typedef BlackBox* Pointer; /// The type of map of output connector pointers typedef std::map OutputConnectorMapType; /// The type of map of input connector pointers typedef std::map InputConnectorMapType; /// Returns the pointer on the descriptor of the box virtual BlackBoxDescriptor* bbGetDescriptor() const = 0; /// Returns a pointer on a clone of the box with name virtual BlackBox* bbClone(const std::string& name) = 0; /// Destruction method of a black box virtual void bbDelete(); /// User overloadable destruction method of a black box virtual void bbUserDelete(); /// Returns the Name of the Type of the BlackBox const std::string& bbGetTypeName() const { return bbGetDescriptor()->GetTypeName(); } /// Returns the name of the BlackBox (instance) const std::string& bbGetName() const { return bbmName; } /// Returns the full name of the BlackBox (instance+type) virtual std::string bbGetFullName() const; /// Returns the name with the name of the parent prepended if any std::string bbGetNameWithParent() const; /// Sets the parent of the BlackBox void bbSetParent(BlackBox::Pointer p) { bbmParent = p; } /// Returns the parent of the BlackBox, i.e the BlackBox that contains it (0 if none) BlackBox::Pointer bbGetParent() const { return bbmParent; } /// Main processing method of the box. virtual void bbExecute(bool force = false); /// Signals that the BlackBox has been modified through the input connector c /// and propagates it downward virtual void bbSetModifiedStatus(BlackBoxInputConnector* c = 0); /// Signals that the BlackBox outputs have been modified /// without marking the box as MODIFIED because its output state is ok. /// This method should be used by widgets in response /// to user interaction when **ALL** outputs have been modified /// (after the outputs has been updated !) virtual void bbSignalOutputModification(bool reaction = true); /// Signals that the BlackBox output "output_name" have been modified /// without marking the box as MODIFIED because its output state is ok. /// This method should be used by widgets in response to user interaction /// only when **ONE** output has been modified /// (after the output has been updated !) virtual void bbSignalOutputModification( const std::string& output_name, bool reaction = true); /// Signals that the BlackBox vector of outputs "output_name" /// have been modified /// without marking the box as MODIFIED because its output state is ok. /// This method should be used by widgets in response to user interaction /// When more than one output has been changed but not all /// (after the outputs have been updated of course!) virtual void bbSignalOutputModification( const std::vector& output_name, bool reaction = true); /// Gets the status of the box virtual const IOStatus& bbGetStatus() const { return bbmStatus; } /// Returns true iff the BlackBox has an input of name label virtual bool bbHasInput(const std::string& label) const; /// Returns true iff the BlackBox has an output of name label virtual bool bbHasOutput(const std::string& label) const; /// Gets the input type of a given label virtual TypeInfo bbGetInputType( const std::string &label ) const; /// Gets the output type of a given label virtual TypeInfo bbGetOutputType( const std::string &label ) const; /// Gets the data of the input called virtual Data bbGetInput( const std::string &name ) = 0; /// Gets the data of the output called virtual Data bbGetOutput( const std::string &name ) = 0; /// Sets the data of the input called . /// If setModified is false then does not call bbSetModifiedStatus() virtual void bbSetInput( const std::string &name, Data data, bool setModified = true ) = 0; virtual void bbBruteForceSetInputPointer( const std::string &name, void* data, bool setModified = true) =0; /// Sets the data of the output called virtual void bbSetOutput( const std::string &name, Data data) = 0; /// Connects the input to the connection c virtual void bbConnectInput( const std::string& name, Connection* c); /// Connects the output to the connection c virtual void bbConnectOutput( const std::string& name, Connection* c); /// Disconnects the input from the connection c virtual void bbDisconnectInput( const std::string& name, Connection* c); /// Disconnects the output from the connection c virtual void bbDisconnectOutput( const std::string& name, Connection* c); /// Returns the input connectors map InputConnectorMapType& bbGetInputConnectorMap() { return mInputConnectorMap; } /// Returns the output connectors map OutputConnectorMapType& bbGetOutputConnectorMap() { return mOutputConnectorMap; } /// Returns the input connectors map (const) const InputConnectorMapType& bbGetInputConnectorMap() const { return mInputConnectorMap; } /// Returns the output connectors map (const) const OutputConnectorMapType& bbGetOutputConnectorMap() const { return mOutputConnectorMap; } /// Prints the Help on the BlackBox type virtual void bbGetHelp(bool full=true) const; //================================================================== // Common inputs / outputs to all boxes /// Returns the value of the input "BoxProcessMode" std::string bbGetInputBoxProcessMode() { return bbmBoxProcessMode; } /// Sets the value of the input "BoxProcessMode" void bbSetInputBoxProcessMode(std::string a) { bbmBoxProcessMode = a; } typedef enum { Pipeline, Always, Reactive } BoxProcessModeValue; /// Returns the "decoded" value of the input "BoxProcessMode" BoxProcessModeValue bbGetBoxProcessModeValue() const; virtual bool bbBoxProcessModeIsReactive() const; virtual bool bbBoxProcessModeIsAlways() const; /// Returns the value of the input "Execute" Void bbGetInputBoxExecute() { return Void(); } /// Sets the value of the input "Execute" void bbSetInputBoxExecute(Void = 0) {} /// Returns the value of the output "Change" Void bbGetOutputBoxChange() { return Void(); } /// Sets the value of the output "Change" : signal a modification void bbSetOutputBoxChange(Void = 0) { bbSetModifiedStatus(); } //================================================================== //================================================================== /// Does nothing here : overloaded in ComplexBlackBox void bbInsertHTMLGraph( std::ofstream& s, int detail, int level, bool instanceOrtype, const std::string& output_dir, bool relative_link ) {} /// Write Graphviz-dot description in file. /// Here dumps a single box description (i/o) but overloaded /// in ComplexBlackBox to dump the internal pipeline representation /// recursing into internal boxes descriptions if level>0. /// detail = 1 : draw inputs and outputs (do not draw otherwise) /// instanceOrtype = true : draw inputs and outputs VALUES /// (uses bbGetInputAsString / bbGetOutputAsString which use adaptors) /// If relative_link is true then creates relative hrefs virtual void bbWriteDotFileBlackBox(FILE *ff, BlackBox *parentblackbox, int detail, int level, bool instanceOrtype, bool relative_link ); /// Auxiliary method for bbWriteDotFileBlackBox virtual void bbWriteDotInputOutputName(FILE *ff, bool inputoutput, int detail, int level); virtual void bbShowRelations(BlackBox *parentblackbox, int detail, int level ); std::string bbGetOutputAsString( const std::string &output ); //,Factory *factory); std::string bbGetInputAsString( const std::string &input); //,Factory *factory); virtual BlackBox *bbFindBlackBox(const std::string &blackboxname) { return NULL;} protected: //================================================================== // PROTECTED PART : ACCESSIBLE TO THE BlackBox DEVELOPER // (IN INHERITED CLASSES) /// Constructor that take the BlackBox's name BlackBox(const std::string &name); /// Constructor from an existing box (copy) with a new name BlackBox(BlackBox& from, const std::string &name); /// Destructor virtual ~BlackBox(); //================================================================== //================================================================== /// Sets the status of the box void bbSetStatus( IOStatus t) { bbmStatus = t; } //================================================================== /// @name Pipeline processing methods /// Methods which participate to (forward or backward) pipeline processing. /// Some are pure virtual and prepare particular update mechanism which are implemented by descendents (e.g. ForwardUpdate and UpdateChildren are made for WxContainerBlackBox particular update mechanism which must recurse a piece of the pipeline top-down). /// The main method is bbBackwardUpdate which is called by bbExecute and implemented in UserBlackBox and ComplexBlackBox. /// //@{ //================================================================== /// Recursive pipeline processing in backward direction /// (recursion is in backward direction however execution always goes forward). /// Pure virtual; defined in UserBlackBox and ComplexBlackBox /// /// \returns The final status of the box (UPTODATE or MODIFIED) /// \param caller : The connection which invoked the method; null if called by bbExecute /// /// First checks that re-processing is needed (either Status==MODIFIED or InputProcessMode==Always) /// then : /// - updates its inputs by calling bbUpdateInputs (which recursively calls bbBackwardUpdate on amont boxes) /// - calls bbCreateWidget /// - calls bbProcess which is the user callback which does the actual processing /// - calls bbUpdateChildren /// - calls bbShowWidget which shows the widget associated to the box (if any) public: virtual IOStatus bbBackwardUpdate(Connection* caller) = 0; //================================================================== //================================================================== /// Recursive pipeline processing in forward direction along "Child"-"Parent" connections /// Pure virtual; defined in UserBlackBox and ComplexBlackBox /// /// \param caller : The connection which invoked the method /// /// First checks that re-processing is needed (either Status==MODIFIED or InputProcessMode==Always) /// then : /// - calls bbCreateWidget /// - calls bbProcess which is the user callback which does the actual processing /// - calls bbUpdateChildren which recursively calls bbForwardUpdate on connections attached the "Child" output // virtual void bbForwardUpdate(Connection* caller) = 0; //================================================================== protected: //================================================================== /// Updates the BlackBox inputs and returns the final status of the inputs /// (==UPTODATE iff all inputs are UPTODATE) // If excludeParent == true then excludes the amont box connected to input 'Parent' from recursive update IOStatus bbUpdateInputs(bool excludeParent=false); //================================================================== //================================================================== /// Updates the pipeline in amont-aval direction along the "Child"-"Parent" connections only. /// Does nothing here. Overloaded in WxContainerBlackbox //virtual void bbUpdateChildren( Connection* caller ) { } //================================================================== //================================================================== /// Specific methods for window creation during pipeline execution /// Creates the window associated to the box (called after bbUpdateInputs) /// Does nothing here. Overloaded in WxBlackBox. // virtual void bbCreateWindow() { } /// Shows the window associated to the box /// (called after bbProcess during bbExecute) /// Does nothing here but overloaded in WxBlackBox and WxContainerBlackBox virtual void bbShowWindow(Connection* caller) { } virtual void bbHideWindow() {} //================================================================== //@} public: static bool bbGlobalGetSomeBoxExecuting() { return bbmgSomeBoxExecuting; } static void bbGlobalSetSomeBoxExecuting(bool b) { bbmgSomeBoxExecuting = b; } static void bbGlobalSetFreezeExecution(bool b) { bbmgFreezeExecution = b;} static bool bbGlobalGetFreezeExecution() { return bbmgFreezeExecution; } /// Returns true if the box can "react", /// which means execute in response to an input change virtual bool bbCanReact() const; static void bbGlobalAddToExecutionList( BlackBox* b ) { bbmgExecutionList.insert(b); } static void bbGlobalProcessExecutionList(); //================================================================== protected: //================================================================== /// Allocates the i/o connectors of the black box virtual void bbAllocateConnectors(); /// Desallocates the i/o connectors of the black box virtual void bbDesallocateConnectors(); /// Copies the values of the inputs/output from the BlackBox from virtual void bbCopyIOValues(BlackBox& from); //================================================================== private: //================================================================== // PRIVATE PART /// Default constructor is private : derived classes must use the constructor with the BlackBox's name BlackBox() {} /// The status of the box IOStatus bbmStatus; /// The name of the black-box std::string bbmName; /// The name of the package to which it belongs std::string bbmPackageName; /// 0 : "Pipeline" mode : bbUpdate() only calls Process if Status == MODIFIED (normal pipeline processing) /// 1 : "Always" mode : bbUpdate() always calls Process /// 2 : "Reactive" mode : bbSetModifiedStatus() calls bbUpdate() std::string bbmBoxProcessMode; /// The parent of the black box in the ComplexBlackBox hierarchy BlackBox::Pointer bbmParent; //================================================================== //================================================================== // ATTRIBUTES /// Map that contains the output connectors of the black box OutputConnectorMapType mOutputConnectorMap; /// Map that contains the input connectors of the black box InputConnectorMapType mInputConnectorMap; //================================================================== static bool bbmgSomeBoxExecuting; static bool bbmgFreezeExecution; static std::set bbmgExecutionList; }; // Class BlackBox } // namespace bbtk #endif