/*========================================================================= Program: bbtk Module: $RCSfile: bbtkBlackBox.h,v $ Language: C++ Date: $Date: 2008/11/13 14:46:43 $ Version: $Revision: 1.14 $ =========================================================================*/ /* --------------------------------------------------------------------- * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale) * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux * * This software is governed by the CeCILL-B license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL-B * license as circulated by CEA, CNRS and INRIA at the following URL * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html * or in the file LICENSE.txt. * * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL-B license and that you accept its terms. * ------------------------------------------------------------------------ */ /** * \file * \brief Class bbtk::BlackBox : abstract black-box interface. */ /** * \class bbtk::BlackBox * \brief Abstract black-box interface */ #ifndef __bbtkBlackBox_h__ #define __bbtkBlackBox_h__ #include "bbtkSystem.h" #include "bbtkBlackBoxDescriptor.h" #include "bbtkBlackBoxInputConnector.h" #include "bbtkBlackBoxOutputConnector.h" #include namespace bbtk { struct Void { Void(int = 0) {} }; class Factory; class Connection; class BBTK_EXPORT BlackBox : public Object { BBTK_ABSTRACT_OBJECT_INTERFACE(BlackBox); public: //================================================================== // INTERFACE //================================================================== /// 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::Pointer bbGetDescriptor() const = 0; /// Returns a pointer on a clone of the box with name virtual BlackBox::Pointer bbClone(const std::string& name) = 0; /// 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 virtual std::string bbGetNameWithParent() const; /// Returns the parent of the BlackBox, i.e the BlackBox that contains it (0 if none) BlackBox::Pointer bbGetParent() const { return bbmParent.lock(); } /// 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; /// 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::Pointer 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::Pointer 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::Pointer bbFindBlackBox(const std::string &blackboxname) { return BlackBox::Pointer();} virtual void Check(bool recursive = true); virtual void bbUserOnShow() { } void bbUserOnShowWidget(std::string nameInput); 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); //================================================================== //================================================================== /// Sets the status of the box void bbSetStatus( IOStatus t) { bbmStatus = t; } //================================================================== private: friend class Connection; friend class ComplexBlackBox; /// Sets the parent of the BlackBox void bbSetParent(BlackBox::Pointer p) { bbmParent = p; } /// 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); /// @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 upstream 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) protected: virtual IOStatus bbBackwardUpdate(Connection::Pointer 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::Pointer 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 upstream box connected to input 'Parent' from recursive update IOStatus bbUpdateInputs(bool excludeParent=false); //================================================================== //================================================================== /// Updates the pipeline in upstream-downstream direction along the "Child"-"Parent" connections only. /// Does nothing here. Overloaded in WxContainerBlackbox //virtual void bbUpdateChildren( Connection::Pointer 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::Pointer caller) { } virtual void bbHideWindow() {} virtual void bbCloseWindow() { } //================================================================== //@} public: static bool bbGlobalGetSomeBoxExecuting(); static void bbGlobalSetSomeBoxExecuting(bool b); static void bbGlobalSetFreezeExecution(bool b); static bool bbGlobalGetFreezeExecution(); /// Returns true if the box can "react", /// which means execute in response to an input change virtual bool bbCanReact() const; /// Returns true iff the box is executing bool bbGetExecuting() const { return bbmExecuting; } protected: static void bbGlobalAddToExecutionList( BlackBox::Pointer b ); static void bbGlobalProcessExecutionList(); /// Sets the bbmExecuting bool returned by bbGetExecuting void bbSetExecuting(bool b) { bbmExecuting = b; } //================================================================== 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); //================================================================== // Black box objects have a special deleter // which must take care of releasing the descriptor // **AFTER** the box is deleted // (Releasing it in the destructor may cause dl close and crash) /// Black box deleter /// 1) Calls the user overloadable bbDelete method /// 2) Releases the box descriptor struct BBTK_EXPORT Deleter : public Object::Deleter { Deleter(); void Delete(Object* p); }; template static boost::shared_ptr MakeBlackBoxPointer(U* s, bool lock = false) { return MakePointer(s,BlackBox::Deleter(),lock); } virtual void bbDelete() { delete this; } private: //================================================================== // PRIVATE PART /// The status of the box IOStatus bbmStatus; /// Is the box executing ? bool bbmExecuting; /// The name of the black-box std::string bbmName; /// The name of the package to which it belongs std::string bbmPackageName; /// 0 : "Pipeline" mode : bbBackwardUpdate() 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::WeakPointer 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; //================================================================== }; // Class BlackBox } // namespace bbtk #endif