]> Creatis software - bbtk.git/blob - kernel/src/bbtkBlackBox.h
*** empty log message ***
[bbtk.git] / kernel / src / bbtkBlackBox.h
1 /*=========================================================================                                                                               
2   Program:   bbtk
3   Module:    $RCSfile: bbtkBlackBox.h,v $
4   Language:  C++
5   Date:      $Date: 2009/04/30 14:31:31 $
6   Version:   $Revision: 1.24 $
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
67
68   class BBTK_EXPORT BlackBox : public Object
69   {
70     BBTK_ABSTRACT_OBJECT_INTERFACE(BlackBox);
71   public: 
72     //==================================================================
73     // INTERFACE
74     //==================================================================
75     typedef boost::signals::trackable OutputChangeObserverType;
76     typedef boost::signal<void (bbtk::BlackBox::Pointer,
77                                 const std::string&,
78                                 IOStatus)>  OutputChangeSignalType;
79     typedef OutputChangeSignalType::slot_function_type 
80     OutputChangeCallbackType;
81  
82     /// The type of map of output connector pointers
83     typedef std::map<std::string, BlackBoxOutputConnector*> 
84     OutputConnectorMapType;
85     /// The type of map of input connector pointers
86     typedef std::map<std::string, BlackBoxInputConnector*> 
87     InputConnectorMapType;
88
89     /// Returns the pointer on the descriptor of the box
90     virtual BlackBoxDescriptor::Pointer bbGetDescriptor() const = 0;
91
92     /// Returns a pointer on a clone of the box with name <name>
93     virtual BlackBox::Pointer bbClone(const std::string& name) = 0;
94
95     /// User overloadable destruction method of a black box
96     virtual void bbUserDelete();
97
98     /// Returns the Name of the Type of the BlackBox
99     const std::string& bbGetTypeName() const 
100       { return bbGetDescriptor()->GetTypeName(); }
101  
102     
103     /// Returns the name of the BlackBox (instance)
104     const std::string& bbGetName() const { return bbmName; }
105
106     /// Returns the full name of the BlackBox (instance+type)
107     virtual std::string bbGetFullName() const;
108
109     /// Returns the name with the name of the parent prepended if any
110     virtual std::string bbGetNameWithParent() const;
111     
112     /// Returns the parent of the BlackBox, i.e the BlackBox that contains it (0 if none)
113     BlackBox::Pointer bbGetParent() const { return bbmParent.lock(); }
114
115
116     /// Main processing method of the box.
117     virtual void bbExecute(bool force = false);
118
119
120  
121     //==================================================================
122     /// System callback which calls bbUserConstructor for all its ancestors 
123     /// and the box itself
124     virtual void bbConstructor() {}
125     /// System callback which calls bbUserDestructor for all its ancestors 
126     /// and the box itself
127     virtual void bbDestructor() {}
128     //==================================================================    
129  
130
131
132     /// Returns true iff the BlackBox has an input of name label
133     virtual bool bbHasInput(const std::string& label) const;
134     /// Returns true iff the BlackBox has an output of name label
135     virtual bool bbHasOutput(const std::string& label) const;
136
137     ///  Gets the input type of a given label
138     virtual TypeInfo bbGetInputType( const std::string &label ) const;
139     ///  Gets the output type of a given label
140     virtual TypeInfo bbGetOutputType( const std::string &label ) const;
141
142     ///  Gets the data of the input called <name>
143     virtual Data bbGetInput( const std::string &name )  = 0;
144     ///  Gets the data of the output called <name>
145     virtual Data bbGetOutput( const std::string &name ) = 0;
146
147     /// Sets the data of the input called <name>.
148     /// If update_time is false then does not update ChangeTime of input
149     virtual void bbSetInput( const std::string &name, Data data,
150                              bool update_time = true ) = 0;
151     virtual void bbBruteForceSetInputPointer( const std::string &name, 
152                                               void* data, 
153                                               bool update_time = true) =0;
154     ///  Sets the data of the output called <name>
155     virtual void bbSetOutput( const std::string &name, Data data) = 0;
156
157
158     /// Gets the status of the input called <name>
159     IOStatus bbGetInputStatus( const std::string &name ) const 
160     { return mInputConnectorMap.find(name)->second->GetStatus(); }
161
162     ///  Returns the input connectors map
163     InputConnectorMapType&  bbGetInputConnectorMap() 
164     { return mInputConnectorMap; }
165     ///  Returns the output connectors map
166     OutputConnectorMapType& bbGetOutputConnectorMap() 
167     { return mOutputConnectorMap; }
168     ///  Returns the input connectors map (const)
169     const InputConnectorMapType&  bbGetInputConnectorMap() const 
170     { return mInputConnectorMap; } 
171     ///  Returns the output connectors map (const)
172     const OutputConnectorMapType& bbGetOutputConnectorMap() const 
173     { return mOutputConnectorMap; }      
174
175     ///  Returns the input connector
176     BlackBoxInputConnector&  bbGetInputConnector(const std::string& n) 
177     { return *(mInputConnectorMap.find(n)->second); }
178     ///  Returns the output connector
179     BlackBoxOutputConnector& bbGetOutputConnector(const std::string& n) 
180     { return *(mOutputConnectorMap.find(n)->second); }
181     ///  Returns the input connector (const)
182     const BlackBoxInputConnector&  bbGetInputConnector(const std::string& n) const
183     { return *(mInputConnectorMap.find(n)->second); }
184     ///  Returns the output connector (const)
185     const BlackBoxOutputConnector& bbGetOutputConnector(const std::string& n) const 
186     { return *(mOutputConnectorMap.find(n)->second); }
187
188  
189     
190
191     /// Prints the Help on the BlackBox type 
192     virtual void bbGetHelp(bool full=true) const;
193
194     //==================================================================
195     /// Adds the function f to the list of functions to call when 
196     /// the output changes.
197     /// f is of type ChangeCallbackType which is basically:
198     /// void (*ChangeCallbackType)(bbtk::BlackBox::Pointer, 
199     ///                            const std::string&,
200     ///                            bbtk::IOStatus)
201     /// To pass a member function 'f' of an instance 'c' of a class 'C' 
202     /// as callback you have to 'bind' it, i.e. call:
203     /// bbAddOutputObserver ( "Out", boost::bind( &C::f , c, _1, _2, _3 ) );
204     /// The convenience macro BBTK_BIND_OUTPUT_OBSERVER ( c, C::f ) does it for you 
205     void bbAddOutputObserver(const std::string& output_name, 
206                              OutputChangeCallbackType f); 
207
208     /// Removes the function f from the list of functions to call when 
209     /// the output changes (TO WRITE)
210     void bbRemoveOutputObserver(const std::string& output_name, 
211                                 OutputChangeCallbackType f); 
212    //==================================================================
213     
214
215     //==================================================================
216     /// Signals that the BlackBox outputs have been modified 
217     /// (without marking the box as MODIFIED because its output state is ok : don't care if you understand : use it !).
218     /// This method should be used by widgets in response 
219     /// to user interaction when **ALL** outputs have been modified
220     /// (after the outputs has been updated !).
221     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
222     /// ** USER INTENDED **
223     virtual void bbSignalOutputModification(bool reaction = true);
224     /// Signals that the BlackBox output "output_name" has been modified 
225     /// (without marking the box as MODIFIED because its output state is ok : don't care if you understand : use it !). 
226     /// This method should be used by widgets in response to user interaction 
227     /// only when **ONE** output has been modified
228     /// (after the output has been updated !)
229     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
230     /// ** USER INTENDED **
231     virtual void bbSignalOutputModification( const std::string& output_name,
232                                              bool reaction = true);
233     /// Signals that the BlackBox vector of outputs "output_name" 
234     /// have been modified.
235     /// Should be used when more than ONE output is modified but not ALL 
236     /// (optimization issue).
237     /// (without marking the box as MODIFIED because its output state is ok). 
238     /// This method should be used by widgets in response to user interaction 
239     /// When more than one output has been changed but not all
240     /// (after the outputs have been updated of course!)
241     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
242     /// ** USER INTENDED **
243     virtual void bbSignalOutputModification( const std::vector<std::string>& 
244                                              output_name,
245                                              bool reaction = true);
246    //==================================================================
247
248
249
250    //==================================================================
251     // Common inputs / outputs to all boxes
252     /// Returns the value of the input "BoxProcessMode"
253     std::string bbGetInputBoxProcessMode() { return bbmBoxProcessMode; }
254     /// Sets the value of the input "BoxProcessMode"
255     void bbSetInputBoxProcessMode(std::string a) { bbmBoxProcessMode = a; }
256     typedef enum
257       {
258         Pipeline,
259         Always,
260         Reactive
261       }
262       BoxProcessModeValue;
263     /// Returns the "decoded" value of the input "BoxProcessMode"
264     BoxProcessModeValue bbGetBoxProcessModeValue() const;
265   
266     virtual bool bbBoxProcessModeIsReactive() const;
267
268     virtual bool bbBoxProcessModeIsAlways() const;
269
270     /// Returns the value of the input "Execute" 
271     Void bbGetInputBoxExecute() { return Void(); }
272     /// Sets the value of the input "Execute"
273     void bbSetInputBoxExecute(Void = 0) {}
274
275     /// Returns the value of the output "Change"
276     Void bbGetOutputBoxChange() { return Void(); }
277     /// Sets the value of the output "Change" : signal a modification
278     void bbSetOutputBoxChange(Void = 0) { } //bbSetModifiedStatus(); }
279
280     //==================================================================    
281
282
283     //==================================================================    
284
285     /// Does nothing here : overloaded in ComplexBlackBox
286     void bbInsertHTMLGraph(  std::ofstream& s, 
287                              int detail, 
288                              int level,
289                              bool instanceOrtype,
290                              const std::string& output_dir,
291                              bool relative_link ) 
292     {}
293
294     /// Write Graphviz-dot description in file. 
295     /// Here dumps a single box description (i/o) but overloaded 
296     /// in ComplexBlackBox to dump the internal pipeline representation 
297     /// recursing into internal boxes descriptions if level>0.
298     /// detail = 1 : draw inputs and outputs (do not draw otherwise)
299     /// instanceOrtype = true : draw inputs and outputs VALUES 
300     ///  (uses bbGetInputAsString / bbGetOutputAsString which use adaptors)
301     /// If relative_link is true then creates relative hrefs
302     virtual void bbWriteDotFileBlackBox(FILE *ff,
303                                         BlackBox::Pointer parentblackbox, 
304                                         int detail, int level, 
305                                         bool instanceOrtype,
306                                         bool relative_link );
307     /// Auxiliary method for bbWriteDotFileBlackBox
308     virtual void bbWriteDotInputOutputName(FILE *ff,
309                                            bool inputoutput, 
310                                            int detail, int level);
311     
312      
313     virtual void bbShowRelations(BlackBox::Pointer parentblackbox, 
314                                  int detail, int level
315                                  );
316     
317     std::string bbGetOutputAsString( const std::string &output ); //,Factory *factory);
318     std::string bbGetInputAsString( const std::string &input); //,Factory *factory);
319     virtual BlackBox::Pointer bbFindBlackBox(const std::string &blackboxname) 
320     { return BlackBox::Pointer();}
321
322     virtual void Check(bool recursive = true);
323
324         virtual void bbUserOnShow() { }
325         void bbUserOnShowWidget(std::string nameInput);
326
327   protected:
328     //==================================================================
329     // PROTECTED PART : ACCESSIBLE TO THE BlackBox DEVELOPER 
330     // (IN INHERITED CLASSES)
331     /// Constructor that take the BlackBox's name
332     BlackBox(const std::string &name);
333     /// Constructor from an existing box (copy) with a new name 
334     BlackBox(BlackBox& from, const std::string &name);
335     //==================================================================
336
337
338     //==================================================================
339     /// Signals that the input whose connector is c has changed 
340     /// and propagates the info downward
341     /// ** NOT USER INTENDED **
342     virtual void bbSetStatusAndPropagate(BlackBoxInputConnector* 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     //@{
373
374     
375     //==================================================================   
376     /// Recursive execution method
377     /// 
378     /// \param caller : The connection which invoked the method; null if called by bbExecute
379     virtual void bbRecursiveExecute(Connection::Pointer caller);
380     //==================================================================
381     
382     //==================================================================
383     /// Updates the BlackBox inputs
384     /// Calls RecursiveExecute on all BlackBoxInputConnector
385     /// \returns The maximum of final IOStatus after each input update
386     IOStatus bbUpdateInputs();
387     //==================================================================
388
389           
390     //==================================================================
391     /// Actual CreateWindow method (vitual)
392     /// Overloaded in AtomicBlacBox and descendants 
393     virtual void bbCreateWindow()
394     {
395       //  bbtkError("BlackBox::bbCreateWidget called : how can this happen ?");
396     }
397     //==================================================================
398     
399     //==================================================================
400     /// Actual ShowWindow method (vitual)
401     /// Overloaded in AtomicBlacBox and descendants 
402     virtual void bbShowWindow()
403     {
404       //  bbtkError("BlackBox::bbShowWidget called : how can this happen ?");
405     }
406     //==================================================================
407     
408                   
409    //==================================================================
410     /// Actual processing method (vitual)
411     /// Overloaded in AtomicBlacBox and descendants 
412     virtual void bbProcess() 
413     {
414       bbtkError("BlackBox::bbProcess called : how can this happen ?");
415 //      this->bbUserProcess(); 
416     }
417     //==================================================================
418
419     //==================================================================
420     /// Computes the final IOStatus of inputs and outputs after processing
421     void bbComputePostProcessStatus();
422     //==================================================================
423
424  
425     //==================================================================
426     /// Specific methods for window creation during pipeline execution
427     /// Creates the window associated to the box (called after bbUpdateInputs)
428     /// Does nothing here. Overloaded in WxBlackBox.
429     // virtual void bbCreateWindow() { }
430     /// Shows the window associated to the box 
431     /// (called after bbProcess during bbExecute)
432     /// Does nothing here but overloaded in WxBlackBox and WxContainerBlackBox
433     //    virtual void bbShowWindow(Connection::Pointer caller) { }
434     //    virtual void bbHideWindow() {}
435     //    virtual void bbCloseWindow() { }
436     //==================================================================
437
438     //@}
439   public: 
440
441     static bool bbGlobalGetSomeBoxExecuting();
442     static void bbGlobalSetSomeBoxExecuting(bool b);
443
444     static void bbGlobalSetFreezeExecution(bool b);
445     static bool bbGlobalGetFreezeExecution();
446
447     /// Returns true if the box can "react",
448     /// which means execute in response to an input change 
449     virtual bool bbCanReact() const;
450     
451     /// Returns true iff the box is executing
452     bool bbGetExecuting() const { return bbmExecuting; }
453
454   protected:  
455     static void bbGlobalAddToExecutionList( BlackBox::Pointer b );
456     static void bbGlobalProcessExecutionList();
457     /// Sets the bbmExecuting bool returned by bbGetExecuting
458     void bbSetExecuting(bool b) { bbmExecuting = b; }
459
460     //==================================================================
461   protected:
462     //==================================================================
463     /// Allocates the i/o connectors of the black box
464     virtual void bbAllocateConnectors();
465     /// Desallocates the i/o connectors of the black box
466     virtual void bbDesallocateConnectors();
467     /// Copies the values of the inputs/output from the BlackBox from
468     virtual void bbCopyIOValues(BlackBox& from);
469     //==================================================================
470
471     //==================================================================
472     // Black box objects have a special deleter 
473     // which must take care of releasing the descriptor 
474     // **AFTER** the box is deleted 
475     // (Releasing it in the destructor may cause dl close and crash)
476     /// Black box deleter 
477     /// 1) Calls the user overloadable bbDelete method
478     /// 2) Releases the box descriptor
479     struct BBTK_EXPORT Deleter : public Object::Deleter
480     { 
481       Deleter(); 
482       int Delete(Object* p);
483     };
484     //==================================================================
485
486     //==================================================================
487     template <class U>
488     static boost::shared_ptr<U> MakeBlackBoxPointer(U* s, bool lock = false)
489     {
490       return MakePointer(s,BlackBox::Deleter(),lock);
491     }
492     //==================================================================
493
494     //==================================================================
495     virtual int bbDelete() { delete this; return 0; }
496     //==================================================================
497
498
499     //==================================================================
500   private:
501     //==================================================================
502  
503     //==================================================================
504     // ATTRIBUTES
505     /// Is the box "constructed" ? (initialized)
506     bool bbmConstructed;
507     /// Is the box executing ?
508     bool bbmExecuting;
509     /// The name of the black-box
510     std::string bbmName;
511     /// The name of the package to which it belongs
512     std::string bbmPackageName;
513     /// The box processing mode
514     /// 0 : "Pipeline" mode 
515     /// 1 : "Always" mode 
516     /// 2 : "Reactive" mode 
517     std::string bbmBoxProcessMode;
518     /// The parent of the black box in the ComplexBlackBox hierarchy
519     BlackBox::WeakPointer bbmParent;
520     //==================================================================
521
522
523    //==================================================================
524     // ATTRIBUTES
525     ///  Map that contains the output connectors of the black box
526     OutputConnectorMapType mOutputConnectorMap; 
527     ///  Map that contains the input connectors of the black box
528     InputConnectorMapType mInputConnectorMap;
529     //==================================================================
530
531
532  };
533   // Class BlackBox
534
535
536
537   /// Convenient macro to create output observer callbacks (freehand functions) from object and method pointer (see samples/SampleOutputObserver)
538 #define BBTK_MAKE_OUTPUT_OBSERVER(OBJECT,METHOD) \
539     boost::bind( METHOD, OBJECT, _1, _2, _3)
540
541
542
543
544  
545 }
546 // namespace bbtk
547 #endif
548