]> Creatis software - bbtk.git/blob - kernel/src/bbtkBlackBox.h
* Viewer2D now works !!!
[bbtk.git] / kernel / src / bbtkBlackBox.h
1 /*=========================================================================                                                                               
2   Program:   bbtk
3   Module:    $RCSfile: bbtkBlackBox.h,v $
4   Language:  C++
5   Date:      $Date: 2008/12/09 12:54:02 $
6   Version:   $Revision: 1.18 $
7 =========================================================================*/
8
9 /* ---------------------------------------------------------------------
10
11 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
12 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
13 *
14 *  This software is governed by the CeCILL-B license under French law and 
15 *  abiding by the rules of distribution of free software. You can  use, 
16 *  modify and/ or redistribute the software under the terms of the CeCILL-B 
17 *  license as circulated by CEA, CNRS and INRIA at the following URL 
18 *  http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html 
19 *  or in the file LICENSE.txt.
20 *
21 *  As a counterpart to the access to the source code and  rights to copy,
22 *  modify and redistribute granted by the license, users are provided only
23 *  with a limited warranty  and the software's author,  the holder of the
24 *  economic rights,  and the successive licensors  have only  limited
25 *  liability. 
26 *
27 *  The fact that you are presently reading this means that you have had
28 *  knowledge of the CeCILL-B license and that you accept its terms.
29 * ------------------------------------------------------------------------ */                                                                         
30
31
32
33 /**
34  *  \file 
35  *  \brief Class bbtk::BlackBox : abstract black-box interface. 
36  */
37
38 /**
39  * \class bbtk::BlackBox
40  * \brief Abstract black-box interface 
41  */
42  
43 #ifndef __bbtkBlackBox_h__
44 #define __bbtkBlackBox_h__
45
46 #include "bbtkSystem.h"
47 #include "bbtkBlackBoxDescriptor.h"
48 #include "bbtkBlackBoxInputConnector.h"
49 //#include "bbtkBlackBoxOutputConnector.h"
50 #include <set>
51
52 // Signal/slot mechanism for output change events
53 #include <boost/signal.hpp>
54 #include <boost/bind.hpp>
55
56 namespace bbtk
57 {
58
59   
60   struct Void { Void(int = 0) {} };
61   
62   class Factory;
63   class Connection;
64   class BlackBoxOutputConnector;
65
66   class BBTK_EXPORT BlackBox : public Object
67   {
68     BBTK_ABSTRACT_OBJECT_INTERFACE(BlackBox);
69   public: 
70     //==================================================================
71     // INTERFACE
72     //==================================================================
73     typedef boost::signals::trackable OutputChangeObserverType;
74     typedef boost::signal<void (bbtk::BlackBox::Pointer,
75                                 const std::string&,
76                                 IOStatus)>  OutputChangeSignalType;
77     typedef OutputChangeSignalType::slot_function_type 
78     OutputChangeCallbackType;
79  
80     /// The type of map of output connector pointers
81     typedef std::map<std::string, BlackBoxOutputConnector*> 
82     OutputConnectorMapType;
83     /// The type of map of input connector pointers
84     typedef std::map<std::string, BlackBoxInputConnector*> 
85     InputConnectorMapType;
86
87     /// Returns the pointer on the descriptor of the box
88     virtual BlackBoxDescriptor::Pointer bbGetDescriptor() const = 0;
89
90     /// Returns a pointer on a clone of the box with name <name>
91     virtual BlackBox::Pointer bbClone(const std::string& name) = 0;
92
93     /// User overloadable destruction method of a black box
94     virtual void bbUserDelete();
95
96     /// Returns the Name of the Type of the BlackBox
97     const std::string& bbGetTypeName() const 
98       { return bbGetDescriptor()->GetTypeName(); }
99  
100     
101     /// Returns the name of the BlackBox (instance)
102     const std::string& bbGetName() const { return bbmName; }
103
104     /// Returns the full name of the BlackBox (instance+type)
105     virtual std::string bbGetFullName() const;
106
107     /// Returns the name with the name of the parent prepended if any
108     virtual std::string bbGetNameWithParent() const;
109     
110     /// Returns the parent of the BlackBox, i.e the BlackBox that contains it (0 if none)
111     BlackBox::Pointer bbGetParent() const { return bbmParent.lock(); }
112
113
114     /// Main processing method of the box.
115     virtual void bbExecute(bool force = false);
116
117
118     /// The type of callback function when an output changes
119     //   typedef BlackBoxOutputConnector::ChangeCallbackType OutputChangeCallbackType;
120
121     /// Adds the function f to the list of functions to call when 
122     /// the output changes.
123     /// f is of type ChangeCallbackType which is basically:
124     /// void (*ChangeCallbackType)(BlackBoxOutputConnector*)
125     /// To pass a member function 'f' of an instance 'c' of a class 'C' 
126     /// as callback you have to 'bind' it, i.e. call:
127     /// AddChangeObserver ( "Out", boost::bind( &C::f , c, _1 ) );
128     void AddChangeObserver(const std::string& output_name, 
129                            OutputChangeCallbackType f); 
130
131     /// Removes the function f from the list of functions to call when 
132     /// the output changes (TO WRITE)
133     void RemoveChangeObserver(const std::string& output_name, 
134                               OutputChangeCallbackType f); 
135     
136
137     /// Signals that the BlackBox outputs have been modified 
138     /// (without marking the box as MODIFIED because its output state is ok : don't care if you understand : use it !).
139     /// This method should be used by widgets in response 
140     /// to user interaction when **ALL** outputs have been modified
141     /// (after the outputs has been updated !).
142     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
143     /// ** USER INTENDED **
144     virtual void bbSignalOutputModification(bool reaction = true);
145     /// Signals that the BlackBox output "output_name" has been modified 
146     /// (without marking the box as MODIFIED because its output state is ok : don't care if you understand : use it !). 
147     /// This method should be used by widgets in response to user interaction 
148     /// only when **ONE** output has been modified
149     /// (after the output has been updated !)
150     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
151     /// ** USER INTENDED **
152     virtual void bbSignalOutputModification( const std::string& output_name,
153                                              bool reaction = true);
154     /// Signals that the BlackBox vector of outputs "output_name" 
155     /// have been modified.
156     /// Should be used when more than ONE output is modified but not ALL 
157     /// (optimization issue).
158     /// (without marking the box as MODIFIED because its output state is ok). 
159     /// This method should be used by widgets in response to user interaction 
160     /// When more than one output has been changed but not all
161     /// (after the outputs have been updated of course!)
162     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
163     /// ** USER INTENDED **
164     virtual void bbSignalOutputModification( const std::vector<std::string>& 
165                                              output_name,
166                                              bool reaction = true);
167
168     /// Gets the status of the box
169     //    virtual const IOStatus& bbGetStatus() const { return bbmStatus; }
170
171
172     /// Returns true iff the BlackBox has an input of name label
173     virtual bool bbHasInput(const std::string& label) const;
174     /// Returns true iff the BlackBox has an output of name label
175     virtual bool bbHasOutput(const std::string& label) const;
176
177     ///  Gets the input type of a given label
178     virtual TypeInfo bbGetInputType( const std::string &label ) const;
179     ///  Gets the output type of a given label
180     virtual TypeInfo bbGetOutputType( const std::string &label ) const;
181
182     ///  Gets the data of the input called <name>
183     virtual Data bbGetInput( const std::string &name )  = 0;
184     ///  Gets the data of the output called <name>
185     virtual Data bbGetOutput( const std::string &name ) = 0;
186
187     /// Sets the data of the input called <name>.
188     /// If update_time is false then does not update ChangeTime of input
189     virtual void bbSetInput( const std::string &name, Data data,
190                              bool update_time = true ) = 0;
191     virtual void bbBruteForceSetInputPointer( const std::string &name, 
192                                               void* data, 
193                                               bool update_time = true) =0;
194     ///  Sets the data of the output called <name>
195     virtual void bbSetOutput( const std::string &name, Data data) = 0;
196
197
198     /// Gets the status of the input called <name>
199     IOStatus bbGetInputStatus( const std::string &name ) const 
200     { return mInputConnectorMap.find(name)->second->GetStatus(); }
201
202     ///  Returns the input connectors map
203     InputConnectorMapType&  bbGetInputConnectorMap() 
204     { return mInputConnectorMap; }
205     ///  Returns the output connectors map
206     OutputConnectorMapType& bbGetOutputConnectorMap() 
207     { return mOutputConnectorMap; }
208     ///  Returns the input connectors map (const)
209     const InputConnectorMapType&  bbGetInputConnectorMap() const 
210     { return mInputConnectorMap; } 
211     ///  Returns the output connectors map (const)
212     const OutputConnectorMapType& bbGetOutputConnectorMap() const 
213     { return mOutputConnectorMap; }      
214
215     ///  Returns the input connector
216     BlackBoxInputConnector&  bbGetInputConnector(const std::string& n) 
217     { return *(mInputConnectorMap.find(n)->second); }
218     ///  Returns the output connector
219     BlackBoxOutputConnector& bbGetOutputConnector(const std::string& n) 
220     { return *(mOutputConnectorMap.find(n)->second); }
221     ///  Returns the input connector (const)
222     const BlackBoxInputConnector&  bbGetInputConnector(const std::string& n) const
223     { return *(mInputConnectorMap.find(n)->second); }
224     ///  Returns the output connector (const)
225     const BlackBoxOutputConnector& bbGetOutputConnector(const std::string& n) const 
226     { return *(mOutputConnectorMap.find(n)->second); }
227
228  
229     
230
231     /// Prints the Help on the BlackBox type 
232     virtual void bbGetHelp(bool full=true) const;
233
234
235     // Returns true iff the box is up-to-date 
236     // (ChangeTime of inputs are all lower strictly to ChangeTime of outputs -
237     //  i.e. max(inputs)<=min(outputs) )
238     //   bool bbIsUpToDate() { return mMaxInputChangeTime < mMinOutputChangeTime; }
239     // Returns true iff the box is out-of-date 
240     // (At least one ChangeTime of an input is greater than one ChangeTime 
241     //  of an output - i.e. max(inputs)>min(outputs))
242     // == !IsUpToDate()
243     //    bool bbIsOutOfDate() { return mMaxInputChangeTime >= mMinOutputChangeTime; }
244
245    //==================================================================
246     // Common inputs / outputs to all boxes
247     /// Returns the value of the input "BoxProcessMode"
248     std::string bbGetInputBoxProcessMode() { return bbmBoxProcessMode; }
249     /// Sets the value of the input "BoxProcessMode"
250     void bbSetInputBoxProcessMode(std::string a) { bbmBoxProcessMode = a; }
251     typedef enum
252       {
253         Pipeline,
254         Always,
255         Reactive
256       }
257       BoxProcessModeValue;
258     /// Returns the "decoded" value of the input "BoxProcessMode"
259     BoxProcessModeValue bbGetBoxProcessModeValue() const;
260   
261     virtual bool bbBoxProcessModeIsReactive() const;
262
263     virtual bool bbBoxProcessModeIsAlways() const;
264
265     /// Returns the value of the input "Execute" 
266     Void bbGetInputBoxExecute() { return Void(); }
267     /// Sets the value of the input "Execute"
268     void bbSetInputBoxExecute(Void = 0) {}
269
270     /// Returns the value of the output "Change"
271     Void bbGetOutputBoxChange() { return Void(); }
272     /// Sets the value of the output "Change" : signal a modification
273     void bbSetOutputBoxChange(Void = 0) { } //bbSetModifiedStatus(); }
274
275     //==================================================================    
276
277
278     //==================================================================    
279
280     /// Does nothing here : overloaded in ComplexBlackBox
281     void bbInsertHTMLGraph(  std::ofstream& s, 
282                              int detail, 
283                              int level,
284                              bool instanceOrtype,
285                              const std::string& output_dir,
286                              bool relative_link ) 
287     {}
288
289     /// Write Graphviz-dot description in file. 
290     /// Here dumps a single box description (i/o) but overloaded 
291     /// in ComplexBlackBox to dump the internal pipeline representation 
292     /// recursing into internal boxes descriptions if level>0.
293     /// detail = 1 : draw inputs and outputs (do not draw otherwise)
294     /// instanceOrtype = true : draw inputs and outputs VALUES 
295     ///  (uses bbGetInputAsString / bbGetOutputAsString which use adaptors)
296     /// If relative_link is true then creates relative hrefs
297     virtual void bbWriteDotFileBlackBox(FILE *ff,
298                                         BlackBox::Pointer parentblackbox, 
299                                         int detail, int level, 
300                                         bool instanceOrtype,
301                                         bool relative_link );
302     /// Auxiliary method for bbWriteDotFileBlackBox
303     virtual void bbWriteDotInputOutputName(FILE *ff,
304                                            bool inputoutput, 
305                                            int detail, int level);
306     
307      
308     virtual void bbShowRelations(BlackBox::Pointer parentblackbox, 
309                                  int detail, int level
310                                  );
311     
312     std::string bbGetOutputAsString( const std::string &output ); //,Factory *factory);
313     std::string bbGetInputAsString( const std::string &input); //,Factory *factory);
314     virtual BlackBox::Pointer bbFindBlackBox(const std::string &blackboxname) 
315     { return BlackBox::Pointer();}
316
317     virtual void Check(bool recursive = true);
318
319         virtual void bbUserOnShow() { }
320         void bbUserOnShowWidget(std::string nameInput);
321
322   protected:
323     //==================================================================
324     // PROTECTED PART : ACCESSIBLE TO THE BlackBox DEVELOPER 
325     // (IN INHERITED CLASSES)
326     /// Constructor that take the BlackBox's name
327     BlackBox(const std::string &name);
328     /// Constructor from an existing box (copy) with a new name 
329     BlackBox(BlackBox& from, const std::string &name);
330     //==================================================================
331
332
333     //==================================================================
334     /// Signals that the input whose connector is c has changed 
335     /// and propagates the info downward
336     /// ** NOT USER INTENDED **
337     virtual void bbSetStatusAndPropagate(BlackBoxInputConnector* c,
338                                          IOStatus s);
339     /// Signals that the output whose connector is c has changed 
340     /// and propagates the info downward
341     /// ** NOT USER INTENDED **
342     virtual void bbSetStatusAndPropagate(BlackBoxOutputConnector* c,
343                                          IOStatus s);
344     //==================================================================
345     
346   private:
347     //==================================================================
348     friend class Connection;
349     friend class ComplexBlackBox;
350
351     /// Sets the parent of the BlackBox
352     void bbSetParent(BlackBox::Pointer p) { bbmParent = p; }
353     
354
355     /// Connects the input <name> to the connection c
356     virtual void bbConnectInput( const std::string& name, 
357                                  Connection* c);
358     /// Connects the output <name> to the connection c
359     virtual void bbConnectOutput( const std::string& name, 
360                                   Connection* c);
361     /// Disconnects the input <name> from the connection c
362     virtual void bbDisconnectInput( const std::string& name, 
363                                     Connection* c);
364     /// Disconnects the output <name> from the connection c
365     virtual void bbDisconnectOutput( const std::string& name, 
366                                      Connection* c);
367
368     //==================================================================
369   protected: 
370     /// @name Pipeline processing methods
371     ///  Methods which participate to pipeline processing.
372     ///  Some are pure virtual and prepare particular update mechanism which are implemented by descendents 
373     /// The main method is bbBackwardUpdate which is called by bbExecute and implemented in UserBlackBox and ComplexBlackBox.
374     /// 
375     //@{
376
377     
378     //==================================================================   
379     /// Recursive pipeline processing in backward direction 
380     /// (recursion is in backward direction however execution always 
381     /// goes forward).
382     /// Pure virtual; defined in AtomicBlackBox and ComplexBlackBox
383     /// 
384     /// \param caller : The connection which invoked the method; null if called by bbExecute
385     virtual void bbBackwardUpdate(Connection::Pointer caller) = 0;
386     //==================================================================
387     
388     //==================================================================
389     /// Updates the BlackBox inputs
390     /// Calls BackwardUpdate on all BlackBoxInputConnector
391     /// \returns The maximum of final IOStatus after each input update
392     IOStatus bbUpdateInputs();
393     //==================================================================
394
395     //==================================================================
396     /// Computes the final IOStatus of inputs and outputs after processing
397     void bbComputePostProcessStatus();
398     //==================================================================
399
400  
401     //==================================================================
402     /// Specific methods for window creation during pipeline execution
403     /// Creates the window associated to the box (called after bbUpdateInputs)
404     /// Does nothing here. Overloaded in WxBlackBox.
405     // virtual void bbCreateWindow() { }
406     /// Shows the window associated to the box 
407     /// (called after bbProcess during bbExecute)
408     /// Does nothing here but overloaded in WxBlackBox and WxContainerBlackBox
409     virtual void bbShowWindow(Connection::Pointer caller) { }
410
411     virtual void bbHideWindow() {}
412     virtual void bbCloseWindow() { }
413    //==================================================================
414
415     //@}
416   public: 
417
418     static bool bbGlobalGetSomeBoxExecuting();
419     static void bbGlobalSetSomeBoxExecuting(bool b);
420
421     static void bbGlobalSetFreezeExecution(bool b);
422     static bool bbGlobalGetFreezeExecution();
423
424     /// Returns true if the box can "react",
425     /// which means execute in response to an input change 
426     virtual bool bbCanReact() const;
427     
428     /// Returns true iff the box is executing
429     bool bbGetExecuting() const { return bbmExecuting; }
430
431   protected:  
432     static void bbGlobalAddToExecutionList( BlackBox::Pointer b );
433     static void bbGlobalProcessExecutionList();
434     /// Sets the bbmExecuting bool returned by bbGetExecuting
435     void bbSetExecuting(bool b) { bbmExecuting = b; }
436
437     //==================================================================
438   protected:
439     //==================================================================
440     /// Allocates the i/o connectors of the black box
441     virtual void bbAllocateConnectors();
442     /// Desallocates the i/o connectors of the black box
443     virtual void bbDesallocateConnectors();
444     /// Copies the values of the inputs/output from the BlackBox from
445     virtual void bbCopyIOValues(BlackBox& from);
446     //==================================================================
447
448     //==================================================================
449     // Black box objects have a special deleter 
450     // which must take care of releasing the descriptor 
451     // **AFTER** the box is deleted 
452     // (Releasing it in the destructor may cause dl close and crash)
453     /// Black box deleter 
454     /// 1) Calls the user overloadable bbDelete method
455     /// 2) Releases the box descriptor
456     struct BBTK_EXPORT Deleter : public Object::Deleter
457     { 
458       Deleter();
459       void Delete(Object* p);
460     };
461     //==================================================================
462
463     //==================================================================
464     template <class U>
465     static boost::shared_ptr<U> MakeBlackBoxPointer(U* s, bool lock = false)
466     {
467       return MakePointer(s,BlackBox::Deleter(),lock);
468     }
469     //==================================================================
470
471     //==================================================================
472     virtual void bbDelete() { delete this; }
473     //==================================================================
474
475
476     //==================================================================
477   private:
478     //==================================================================
479  
480     //==================================================================
481     // ATTRIBUTES
482     /// The status of the box
483     //    IOStatus bbmStatus;
484     /// Is the box executing ?
485     bool bbmExecuting;
486     /// The name of the black-box
487     std::string bbmName;
488     /// The name of the package to which it belongs
489     std::string bbmPackageName;
490     /// The box processing mode
491     /// 0 : "Pipeline" mode 
492     /// 1 : "Always" mode 
493     /// 2 : "Reactive" mode 
494     std::string bbmBoxProcessMode;
495     /// The parent of the black box in the ComplexBlackBox hierarchy
496     BlackBox::WeakPointer bbmParent;
497     //==================================================================
498
499
500    //==================================================================
501     // ATTRIBUTES
502     ///  Map that contains the output connectors of the black box
503     OutputConnectorMapType mOutputConnectorMap; 
504     ///  Map that contains the input connectors of the black box
505     InputConnectorMapType mInputConnectorMap;
506     //==================================================================
507
508     /// The maximum ChangeTime of the inputs
509     //    ChangeTime mMaxInputChangeTime;
510     /// The minimum ChangeTime of the outputs
511     //    ChangeTime mMinOutputChangeTime;
512
513
514   protected:
515     //=========================================================================
516     ///  Sets the ChangeTime of input 
517     /*
518     void bbSetInputChangeTime(BlackBoxInputConnector* c, 
519                               const ChangeTime& t);
520     ///  Sets the ChangeTime of output 
521     void bbSetOutputChangeTime(BlackBoxOutputConnector* c, 
522                                const ChangeTime& t);
523     */
524     //   void bbUpdateMaxInputChangeTime(const ChangeTime& t);
525     //    void bbUpdateMinOutputChangeTime(const ChangeTime& t);
526
527     ///  Set the change time of the input 
528     //    void bbSetInputChangeTime(const std::string& n, ChangeTime);
529     ///  Set the change time of the output 
530     //    void bbSetOutputChangeTime(const std::string& n, ChangeTime);
531
532
533
534  };
535   // Class BlackBox
536
537
538
539
540
541
542
543  
544 }
545 // namespace bbtk
546 #endif
547