]> Creatis software - bbtk.git/blob - kernel/src/bbtkBlackBox.h
*** MAJOR CHANGE *** NOT WORKING YET !!!
[bbtk.git] / kernel / src / bbtkBlackBox.h
1 /*=========================================================================                                                                               
2   Program:   bbtk
3   Module:    $RCSfile: bbtkBlackBox.h,v $
4   Language:  C++
5   Date:      $Date: 2009/05/14 14:43:33 $
6   Version:   $Revision: 1.25 $
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
123
124     /// Returns true iff the BlackBox has an input of name label
125     virtual bool bbHasInput(const std::string& label) const;
126     /// Returns true iff the BlackBox has an output of name label
127     virtual bool bbHasOutput(const std::string& label) const;
128
129     ///  Gets the input type of a given label
130     virtual TypeInfo bbGetInputType( const std::string &label ) const;
131     ///  Gets the output type of a given label
132     virtual TypeInfo bbGetOutputType( const std::string &label ) const;
133
134     ///  Gets the data of the input called <name>
135     virtual Data bbGetInput( const std::string &name )  = 0;
136     ///  Gets the data of the output called <name>
137     virtual Data bbGetOutput( const std::string &name ) = 0;
138
139     /// Sets the data of the input called <name>.
140     /// If update_time is false then does not update ChangeTime of input
141     virtual void bbSetInput( const std::string &name, Data data,
142                              bool update_time = true ) = 0;
143     virtual void bbBruteForceSetInputPointer( const std::string &name, 
144                                               void* data, 
145                                               bool update_time = true) =0;
146     ///  Sets the data of the output called <name>
147     virtual void bbSetOutput( const std::string &name, Data data) = 0;
148
149
150     /// Gets the status of the input called <name>
151     IOStatus bbGetInputStatus( const std::string &name ) const 
152     { return mInputConnectorMap.find(name)->second->GetStatus(); }
153
154     ///  Returns the input connectors map
155     InputConnectorMapType&  bbGetInputConnectorMap() 
156     { return mInputConnectorMap; }
157     ///  Returns the output connectors map
158     OutputConnectorMapType& bbGetOutputConnectorMap() 
159     { return mOutputConnectorMap; }
160     ///  Returns the input connectors map (const)
161     const InputConnectorMapType&  bbGetInputConnectorMap() const 
162     { return mInputConnectorMap; } 
163     ///  Returns the output connectors map (const)
164     const OutputConnectorMapType& bbGetOutputConnectorMap() const 
165     { return mOutputConnectorMap; }      
166
167     ///  Returns the input connector
168     BlackBoxInputConnector&  bbGetInputConnector(const std::string& n) 
169     { return *(mInputConnectorMap.find(n)->second); }
170     ///  Returns the output connector
171     BlackBoxOutputConnector& bbGetOutputConnector(const std::string& n) 
172     { return *(mOutputConnectorMap.find(n)->second); }
173     ///  Returns the input connector (const)
174     const BlackBoxInputConnector&  bbGetInputConnector(const std::string& n) const
175     { return *(mInputConnectorMap.find(n)->second); }
176     ///  Returns the output connector (const)
177     const BlackBoxOutputConnector& bbGetOutputConnector(const std::string& n) const 
178     { return *(mOutputConnectorMap.find(n)->second); }
179
180  
181     
182
183     /// Prints the Help on the BlackBox type 
184     virtual void bbGetHelp(bool full=true) const;
185
186     //==================================================================
187     /// Adds the function f to the list of functions to call when 
188     /// the output changes.
189     /// f is of type ChangeCallbackType which is basically:
190     /// void (*ChangeCallbackType)(bbtk::BlackBox::Pointer, 
191     ///                            const std::string&,
192     ///                            bbtk::IOStatus)
193     /// To pass a member function 'f' of an instance 'c' of a class 'C' 
194     /// as callback you have to 'bind' it, i.e. call:
195     /// bbAddOutputObserver ( "Out", boost::bind( &C::f , c, _1, _2, _3 ) );
196     /// The convenience macro BBTK_BIND_OUTPUT_OBSERVER ( c, C::f ) does it for you 
197     void bbAddOutputObserver(const std::string& output_name, 
198                              OutputChangeCallbackType f); 
199
200     /// Removes the function f from the list of functions to call when 
201     /// the output changes (TO WRITE)
202     void bbRemoveOutputObserver(const std::string& output_name, 
203                                 OutputChangeCallbackType f); 
204    //==================================================================
205     
206
207     //==================================================================
208     /// Signals that the BlackBox outputs have been modified 
209     /// (without marking the box as MODIFIED because its output state is ok : don't care if you understand : use it !).
210     /// This method should be used by widgets in response 
211     /// to user interaction when **ALL** outputs have been modified
212     /// (after the outputs has been updated !).
213     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
214     /// ** USER INTENDED **
215     virtual void bbSignalOutputModification(bool reaction = true);
216     /// Signals that the BlackBox output "output_name" has 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 to user interaction 
219     /// only when **ONE** output has been modified
220     /// (after the output has been updated !)
221     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
222     /// ** USER INTENDED **
223     virtual void bbSignalOutputModification( const std::string& output_name,
224                                              bool reaction = true);
225     /// Signals that the BlackBox vector of outputs "output_name" 
226     /// have been modified.
227     /// Should be used when more than ONE output is modified but not ALL 
228     /// (optimization issue).
229     /// (without marking the box as MODIFIED because its output state is ok). 
230     /// This method should be used by widgets in response to user interaction 
231     /// When more than one output has been changed but not all
232     /// (after the outputs have been updated of course!)
233     /// DO NOT PASS reaction = false OR WILL NOT WORK PROPERLY
234     /// ** USER INTENDED **
235     virtual void bbSignalOutputModification( const std::vector<std::string>& 
236                                              output_name,
237                                              bool reaction = true);
238    //==================================================================
239
240
241
242     //==================================================================
243    /// User can redefine this method to set 
244     /// the default values of the box inputs and outputs
245     /// (it is called in the box constructor)
246     virtual void bbUserSetDefaultValues() {}
247
248     /// User can redefine this method to initialize what must be 
249     /// initialized for the box to work, for example allocate dynamic data.
250     /// It is called once and only once before any call to bbUserCreateWidget
251     /// or bbUserProcess.
252     /// What has been allocated here must be desalocated in 
253     /// bbFinalizeProcessing
254     virtual void bbUserInitializeProcessing() {}
255
256     /// User must redefine this method to uninitialize what has been
257     /// initialized in bbUserInitializeProcessing,
258     /// typically desallocate memory that has been allocated dynamically.
259     /// It is called in the box destructor if and only if (iff) 
260     /// bbUserInitializeProcessing has been called previously.
261     virtual void bbUserFinalizeProcessing() {}
262
263
264     /// Initializes processing IF NEEDED. 
265     /// Calls bbRecursiveInitializeProcessing if the box is in 
266     /// "uninitialized" state and put it in "initialized" state.
267     /// On construction, boxes are "uninitialized".
268     /// See also bbFinalizeProcessing
269     void bbInitializeProcessing();
270
271     /// Finalizes processing IF NEEDED.
272     /// Calls bbRecursiveFinalizeProcessing if the box is in 
273     /// "initialized" state and put it in "uninitialized" state.
274     /// On construction, boxes are "uninitialized".
275     /// See also bbInitializeProcessing
276     void bbFinalizeProcessing();
277
278     /// Abstract prototype of the method which 
279     /// Recursively calls itself for the parent black box and then
280     /// calls bbUserInitializeProcessing for its own class. 
281     /// It is redefined in each black box descendant.
282     /// Allows to call bbUserInitializeProcessing for all inherited classes
283     /// (like a constructor does)
284     virtual void bbRecursiveInitializeProcessing() {}
285
286
287     /// Abstract prototype of the method which 
288     /// calls bbUserFinalizeProcessing for its own class and then 
289     /// recursively calls itself for the parent black box.
290     /// It is redefined in each black box descendant.
291     /// Allows to call bbUserFinalizeProcessing for all inherited classes
292     /// (like a destructor does)
293    virtual void bbRecursiveFinalizeProcessing() {}
294
295     //==================================================================
296
297
298    //==================================================================
299     // Common inputs / outputs to all boxes
300     /// Returns the value of the input "BoxProcessMode"
301     std::string bbGetInputBoxProcessMode() { return bbmBoxProcessMode; }
302     /// Sets the value of the input "BoxProcessMode"
303     void bbSetInputBoxProcessMode(std::string a) { bbmBoxProcessMode = a; }
304     typedef enum
305       {
306         Pipeline,
307         Always,
308         Reactive
309       }
310       BoxProcessModeValue;
311     /// Returns the "decoded" value of the input "BoxProcessMode"
312     BoxProcessModeValue bbGetBoxProcessModeValue() const;
313   
314     virtual bool bbBoxProcessModeIsReactive() const;
315
316     virtual bool bbBoxProcessModeIsAlways() const;
317
318     /// Returns the value of the input "Execute" 
319     Void bbGetInputBoxExecute() { return Void(); }
320     /// Sets the value of the input "Execute"
321     void bbSetInputBoxExecute(Void = 0) {}
322
323     /// Returns the value of the output "Change"
324     Void bbGetOutputBoxChange() { return Void(); }
325     /// Sets the value of the output "Change" : signal a modification
326     void bbSetOutputBoxChange(Void = 0) { } //bbSetModifiedStatus(); }
327
328     //==================================================================    
329
330
331     //==================================================================    
332
333     /// Does nothing here : overloaded in ComplexBlackBox
334     void bbInsertHTMLGraph(  std::ofstream& s, 
335                              int detail, 
336                              int level,
337                              bool instanceOrtype,
338                              const std::string& output_dir,
339                              bool relative_link ) 
340     {}
341
342     /// Write Graphviz-dot description in file. 
343     /// Here dumps a single box description (i/o) but overloaded 
344     /// in ComplexBlackBox to dump the internal pipeline representation 
345     /// recursing into internal boxes descriptions if level>0.
346     /// detail = 1 : draw inputs and outputs (do not draw otherwise)
347     /// instanceOrtype = true : draw inputs and outputs VALUES 
348     ///  (uses bbGetInputAsString / bbGetOutputAsString which use adaptors)
349     /// If relative_link is true then creates relative hrefs
350     virtual void bbWriteDotFileBlackBox(FILE *ff,
351                                         BlackBox::Pointer parentblackbox, 
352                                         int detail, int level, 
353                                         bool instanceOrtype,
354                                         bool relative_link );
355     /// Auxiliary method for bbWriteDotFileBlackBox
356     virtual void bbWriteDotInputOutputName(FILE *ff,
357                                            bool inputoutput, 
358                                            int detail, int level);
359     
360      
361     virtual void bbShowRelations(BlackBox::Pointer parentblackbox, 
362                                  int detail, int level
363                                  );
364     
365     std::string bbGetOutputAsString( const std::string &output ); //,Factory *factory);
366     std::string bbGetInputAsString( const std::string &input); //,Factory *factory);
367     virtual BlackBox::Pointer bbFindBlackBox(const std::string &blackboxname) 
368     { return BlackBox::Pointer();}
369
370     virtual void Check(bool recursive = true);
371
372         virtual void bbUserOnShow() { }
373         void bbUserOnShowWidget(std::string nameInput);
374
375   protected:
376     //==================================================================
377     // PROTECTED PART : ACCESSIBLE TO THE BlackBox DEVELOPER 
378     // (IN INHERITED CLASSES)
379     /// Constructor that take the BlackBox's name
380     BlackBox(const std::string &name);
381     /// Constructor from an existing box (copy) with a new name 
382     BlackBox(BlackBox& from, const std::string &name);
383     //==================================================================
384
385
386     //==================================================================
387     /// Signals that the input whose connector is c has changed 
388     /// and propagates the info downward
389     /// ** NOT USER INTENDED **
390     virtual void bbSetStatusAndPropagate(BlackBoxInputConnector* c,
391                                          IOStatus s);
392     //==================================================================
393     
394   private:
395     //==================================================================
396     friend class Connection;
397     friend class ComplexBlackBox;
398
399     /// Sets the parent of the BlackBox
400     void bbSetParent(BlackBox::Pointer p) { bbmParent = p; }
401     
402
403     /// Connects the input <name> to the connection c
404     virtual void bbConnectInput( const std::string& name, 
405                                  Connection* c);
406     /// Connects the output <name> to the connection c
407     virtual void bbConnectOutput( const std::string& name, 
408                                   Connection* c);
409     /// Disconnects the input <name> from the connection c
410     virtual void bbDisconnectInput( const std::string& name, 
411                                     Connection* c);
412     /// Disconnects the output <name> from the connection c
413     virtual void bbDisconnectOutput( const std::string& name, 
414                                      Connection* c);
415
416     //==================================================================
417   protected: 
418     /// @name Pipeline processing methods
419     ///  Methods which participate to pipeline processing.
420     //@{
421
422     
423     //==================================================================   
424     /// Recursive execution method
425     /// 
426     /// \param caller : The connection which invoked the method; null if called by bbExecute
427     virtual void bbRecursiveExecute(Connection::Pointer caller);
428     //==================================================================
429     
430     //==================================================================
431     /// Updates the BlackBox inputs
432     /// Calls RecursiveExecute on all BlackBoxInputConnector
433     /// \returns The maximum of final IOStatus after each input update
434     IOStatus bbUpdateInputs();
435     //==================================================================
436
437           
438     //==================================================================
439     /// Actual CreateWindow method (vitual)
440     /// Overloaded in AtomicBlacBox and descendants 
441     virtual void bbCreateWindow()
442     {
443       //  bbtkError("BlackBox::bbCreateWidget called : how can this happen ?");
444     }
445     //==================================================================
446     
447     //==================================================================
448     /// Actual ShowWindow method (vitual)
449     /// Overloaded in AtomicBlacBox and descendants 
450     virtual void bbShowWindow()
451     {
452       //  bbtkError("BlackBox::bbShowWidget called : how can this happen ?");
453     }
454     //==================================================================
455     
456                   
457    //==================================================================
458     /// Actual processing method (vitual)
459     /// Overloaded in AtomicBlacBox and descendants 
460     virtual void bbProcess() 
461     {
462       bbtkError("BlackBox::bbProcess called : how can this happen ?");
463 //      this->bbUserProcess(); 
464     }
465     //==================================================================
466
467     //==================================================================
468     /// Computes the final IOStatus of inputs and outputs after processing
469     void bbComputePostProcessStatus();
470     //==================================================================
471
472  
473     //==================================================================
474     /// Specific methods for window creation during pipeline execution
475     /// Creates the window associated to the box (called after bbUpdateInputs)
476     /// Does nothing here. Overloaded in WxBlackBox.
477     // virtual void bbCreateWindow() { }
478     /// Shows the window associated to the box 
479     /// (called after bbProcess during bbExecute)
480     /// Does nothing here but overloaded in WxBlackBox and WxContainerBlackBox
481     //    virtual void bbShowWindow(Connection::Pointer caller) { }
482     //    virtual void bbHideWindow() {}
483     //    virtual void bbCloseWindow() { }
484     //==================================================================
485
486     //@}
487   public: 
488
489     static bool bbGlobalGetSomeBoxExecuting();
490     static void bbGlobalSetSomeBoxExecuting(bool b);
491
492     static void bbGlobalSetFreezeExecution(bool b);
493     static bool bbGlobalGetFreezeExecution();
494
495     /// Returns true if the box can "react",
496     /// which means execute in response to an input change 
497     virtual bool bbCanReact() const;
498     
499     /// Returns true iff the box is executing
500     bool bbGetExecuting() const { return bbmExecuting; }
501
502   protected:  
503     static void bbGlobalAddToExecutionList( BlackBox::Pointer b );
504     static void bbGlobalProcessExecutionList();
505     /// Sets the bbmExecuting bool returned by bbGetExecuting
506     void bbSetExecuting(bool b) { bbmExecuting = b; }
507
508     //==================================================================
509   protected:
510     //==================================================================
511     /// Allocates the i/o connectors of the black box
512     virtual void bbAllocateConnectors();
513     /// Desallocates the i/o connectors of the black box
514     virtual void bbDesallocateConnectors();
515     /// Copies the values of the inputs/output from the BlackBox from
516     virtual void bbCopyIOValues(BlackBox& from);
517     //==================================================================
518
519     //==================================================================
520     // Black box objects have a special deleter 
521     // which must take care of releasing the descriptor 
522     // **AFTER** the box is deleted 
523     // (Releasing it in the destructor may cause dl close and crash)
524     /// Black box deleter 
525     /// 1) Calls the user overloadable bbDelete method
526     /// 2) Releases the box descriptor
527     struct BBTK_EXPORT Deleter : public Object::Deleter
528     { 
529       Deleter(); 
530       int Delete(Object* p);
531     };
532     //==================================================================
533
534     //==================================================================
535     template <class U>
536     static boost::shared_ptr<U> MakeBlackBoxPointer(U* s, bool lock = false)
537     {
538       return MakePointer(s,BlackBox::Deleter(),lock);
539     }
540     //==================================================================
541
542     //==================================================================
543     virtual int bbDelete() { delete this; return 0; }
544     //==================================================================
545
546
547     //==================================================================
548   private:
549     //==================================================================
550  
551     //==================================================================
552     // ATTRIBUTES
553     /// Is the box initialized ?
554     bool bbmInitialized;
555     /// Is the box executing ?
556     bool bbmExecuting;
557     /// The name of the black-box
558     std::string bbmName;
559     /// The name of the package to which it belongs
560     std::string bbmPackageName;
561     /// The box processing mode
562     /// 0 : "Pipeline" mode 
563     /// 1 : "Always" mode 
564     /// 2 : "Reactive" mode 
565     std::string bbmBoxProcessMode;
566     /// The parent of the black box in the ComplexBlackBox hierarchy
567     BlackBox::WeakPointer bbmParent;
568     //==================================================================
569
570
571    //==================================================================
572     // ATTRIBUTES
573     ///  Map that contains the output connectors of the black box
574     OutputConnectorMapType mOutputConnectorMap; 
575     ///  Map that contains the input connectors of the black box
576     InputConnectorMapType mInputConnectorMap;
577     //==================================================================
578
579
580  };
581   // Class BlackBox
582
583
584
585   /// Convenient macro to create output observer callbacks (freehand functions) from object and method pointer (see samples/SampleOutputObserver)
586 #define BBTK_MAKE_OUTPUT_OBSERVER(OBJECT,METHOD) \
587     boost::bind( METHOD, OBJECT, _1, _2, _3)
588
589
590
591
592  
593 }
594 // namespace bbtk
595 #endif
596