]> Creatis software - bbtk.git/blob - kernel/src/bbtkBlackBox.h
Another ugly bug fixed in pipeline executing (bad transfer to parent in some cases...
[bbtk.git] / kernel / src / bbtkBlackBox.h
1 /*=========================================================================                                                                               
2   Program:   bbtk
3   Module:    $RCSfile: bbtkBlackBox.h,v $
4   Language:  C++
5   Date:      $Date: 2008/11/13 14:46:43 $
6   Version:   $Revision: 1.14 $
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 namespace bbtk
53 {
54
55   
56   struct Void { Void(int = 0) {} };
57   
58   class Factory;
59   class Connection;
60
61   class BBTK_EXPORT BlackBox : public Object
62   {
63     BBTK_ABSTRACT_OBJECT_INTERFACE(BlackBox);
64   public: 
65     //==================================================================
66     // INTERFACE
67     //==================================================================
68  
69     /// The type of map of output connector pointers
70     typedef std::map<std::string, BlackBoxOutputConnector*> 
71     OutputConnectorMapType;
72     /// The type of map of input connector pointers
73     typedef std::map<std::string, BlackBoxInputConnector*> 
74     InputConnectorMapType;
75
76     /// Returns the pointer on the descriptor of the box
77     virtual BlackBoxDescriptor::Pointer bbGetDescriptor() const = 0;
78
79     /// Returns a pointer on a clone of the box with name <name>
80     virtual BlackBox::Pointer bbClone(const std::string& name) = 0;
81
82     /// User overloadable destruction method of a black box
83     virtual void bbUserDelete();
84
85     /// Returns the Name of the Type of the BlackBox
86     const std::string& bbGetTypeName() const 
87       { return bbGetDescriptor()->GetTypeName(); }
88  
89     
90     /// Returns the name of the BlackBox (instance)
91     const std::string& bbGetName() const { return bbmName; }
92
93     /// Returns the full name of the BlackBox (instance+type)
94     virtual std::string bbGetFullName() const;
95
96     /// Returns the name with the name of the parent prepended if any
97     virtual std::string bbGetNameWithParent() const;
98     
99     /// Returns the parent of the BlackBox, i.e the BlackBox that contains it (0 if none)
100     BlackBox::Pointer bbGetParent() const { return bbmParent.lock(); }
101
102
103     /// Main processing method of the box.
104     virtual void bbExecute(bool force = false);
105
106     ///  Signals that the BlackBox has been modified through the input connector c
107     /// and propagates it downward
108     virtual void bbSetModifiedStatus(BlackBoxInputConnector* c = 0);
109     /// Signals that the BlackBox outputs have been modified 
110     /// without marking the box as MODIFIED because its output state is ok. 
111     /// This method should be used by widgets in response 
112     /// to user interaction when **ALL** outputs have been modified
113     /// (after the outputs has been updated !)
114     virtual void bbSignalOutputModification(bool reaction = true);
115     ///  Signals that the BlackBox output "output_name" have been modified 
116     /// without marking the box as MODIFIED because its output state is ok. 
117     /// This method should be used by widgets in response to user interaction 
118     /// only when **ONE** output has been modified
119     /// (after the output has been updated !)
120     virtual void bbSignalOutputModification( const std::string& output_name,
121 bool reaction = true);
122     ///  Signals that the BlackBox vector of outputs "output_name" 
123     ///  have been modified 
124     /// without marking the box as MODIFIED because its output state is ok. 
125     /// This method should be used by widgets in response to user interaction 
126     /// When more than one output has been changed but not all
127     /// (after the outputs have been updated of course!)
128     virtual void bbSignalOutputModification( const std::vector<std::string>& output_name,
129 bool reaction = true);
130
131     /// Gets the status of the box
132     virtual const IOStatus& bbGetStatus() const { return bbmStatus; }
133
134
135     /// Returns true iff the BlackBox has an input of name label
136     virtual bool bbHasInput(const std::string& label) const;
137     /// Returns true iff the BlackBox has an output of name label
138     virtual bool bbHasOutput(const std::string& label) const;
139
140     ///  Gets the input type of a given label
141     virtual TypeInfo bbGetInputType( const std::string &label ) const;
142     ///  Gets the output type of a given label
143     virtual TypeInfo bbGetOutputType( const std::string &label ) const;
144
145     ///  Gets the data of the input called <name>
146     virtual Data bbGetInput( const std::string &name )  = 0;
147     ///  Gets the data of the output called <name>
148     virtual Data bbGetOutput( const std::string &name ) = 0;
149
150     /// Sets the data of the input called <name>.
151     /// If setModified is false then does not call bbSetModifiedStatus()
152     virtual void bbSetInput( const std::string &name, Data data,
153                              bool setModified = true ) = 0;
154     virtual void bbBruteForceSetInputPointer( const std::string &name, 
155                                               void* data, 
156                                               bool setModified = true) =0;
157     ///  Sets the data of the output called <name>
158     virtual void bbSetOutput( const std::string &name, Data data) = 0;
159
160
161     ///  Returns the input connectors map
162     InputConnectorMapType&  bbGetInputConnectorMap() 
163     { return mInputConnectorMap; }
164     ///  Returns the output connectors map
165     OutputConnectorMapType& bbGetOutputConnectorMap() 
166     { return mOutputConnectorMap; }
167     ///  Returns the input connectors map (const)
168     const InputConnectorMapType&  bbGetInputConnectorMap() const 
169     { return mInputConnectorMap; } 
170     ///  Returns the output connectors map (const)
171     const OutputConnectorMapType& bbGetOutputConnectorMap() const 
172     { return mOutputConnectorMap; }      
173  
174
175     /// Prints the Help on the BlackBox type 
176     virtual void bbGetHelp(bool full=true) const;
177
178
179     //==================================================================
180     // Common inputs / outputs to all boxes
181     /// Returns the value of the input "BoxProcessMode"
182     std::string bbGetInputBoxProcessMode() { return bbmBoxProcessMode; }
183     /// Sets the value of the input "BoxProcessMode"
184     void bbSetInputBoxProcessMode(std::string a) { bbmBoxProcessMode = a; }
185     typedef enum
186       {
187         Pipeline,
188         Always,
189         Reactive
190       }
191       BoxProcessModeValue;
192     /// Returns the "decoded" value of the input "BoxProcessMode"
193     BoxProcessModeValue bbGetBoxProcessModeValue() const;
194   
195     virtual bool bbBoxProcessModeIsReactive() const;
196
197     virtual bool bbBoxProcessModeIsAlways() const;
198
199     /// Returns the value of the input "Execute" 
200     Void bbGetInputBoxExecute() { return Void(); }
201     /// Sets the value of the input "Execute"
202     void bbSetInputBoxExecute(Void = 0) {}
203
204     /// Returns the value of the output "Change"
205     Void bbGetOutputBoxChange() { return Void(); }
206     /// Sets the value of the output "Change" : signal a modification
207     void bbSetOutputBoxChange(Void = 0) { bbSetModifiedStatus(); }
208
209     //==================================================================    
210
211
212     //==================================================================    
213
214     /// Does nothing here : overloaded in ComplexBlackBox
215     void bbInsertHTMLGraph(  std::ofstream& s, 
216                              int detail, 
217                              int level,
218                              bool instanceOrtype,
219                              const std::string& output_dir,
220                              bool relative_link ) 
221     {}
222
223     /// Write Graphviz-dot description in file. 
224     /// Here dumps a single box description (i/o) but overloaded 
225     /// in ComplexBlackBox to dump the internal pipeline representation 
226     /// recursing into internal boxes descriptions if level>0.
227     /// detail = 1 : draw inputs and outputs (do not draw otherwise)
228     /// instanceOrtype = true : draw inputs and outputs VALUES 
229     ///  (uses bbGetInputAsString / bbGetOutputAsString which use adaptors)
230     /// If relative_link is true then creates relative hrefs
231     virtual void bbWriteDotFileBlackBox(FILE *ff,
232                                         BlackBox::Pointer parentblackbox, 
233                                         int detail, int level, 
234                                         bool instanceOrtype,
235                                         bool relative_link );
236     /// Auxiliary method for bbWriteDotFileBlackBox
237     virtual void bbWriteDotInputOutputName(FILE *ff,
238                                            bool inputoutput, 
239                                            int detail, int level);
240     
241      
242     virtual void bbShowRelations(BlackBox::Pointer parentblackbox, 
243                                  int detail, int level
244                                  );
245     
246     std::string bbGetOutputAsString( const std::string &output ); //,Factory *factory);
247     std::string bbGetInputAsString( const std::string &input); //,Factory *factory);
248     virtual BlackBox::Pointer bbFindBlackBox(const std::string &blackboxname) 
249     { return BlackBox::Pointer();}
250
251     virtual void Check(bool recursive = true);
252
253         virtual void bbUserOnShow() { }
254         void bbUserOnShowWidget(std::string nameInput);
255
256
257   protected:
258     //==================================================================
259     // PROTECTED PART : ACCESSIBLE TO THE BlackBox DEVELOPER 
260     // (IN INHERITED CLASSES)
261     /// Constructor that take the BlackBox's name
262     BlackBox(const std::string &name);
263     /// Constructor from an existing box (copy) with a new name 
264     BlackBox(BlackBox& from, const std::string &name);
265     //==================================================================
266
267
268     //==================================================================
269     ///  Sets the status of the box
270     void bbSetStatus( IOStatus t) { bbmStatus = t; } 
271     //==================================================================
272     
273   private:
274     friend class Connection;
275     friend class ComplexBlackBox;
276
277     /// Sets the parent of the BlackBox
278     void bbSetParent(BlackBox::Pointer p) { bbmParent = p; }
279     
280
281     /// Connects the input <name> to the connection c
282     virtual void bbConnectInput( const std::string& name, 
283                                  Connection* c);
284     /// Connects the output <name> to the connection c
285     virtual void bbConnectOutput( const std::string& name, 
286                                   Connection* c);
287     /// Disconnects the input <name> from the connection c
288     virtual void bbDisconnectInput( const std::string& name, 
289                                     Connection* c);
290     /// Disconnects the output <name> from the connection c
291     virtual void bbDisconnectOutput( const std::string& name, 
292                                      Connection* c);
293
294
295  
296     /// @name Pipeline processing methods
297     ///  Methods which participate to (forward or backward) pipeline processing.
298     ///  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).
299     /// The main method is bbBackwardUpdate which is called by bbExecute and implemented in UserBlackBox and ComplexBlackBox.
300     /// 
301     //@{
302
303     //==================================================================   
304     /// Recursive pipeline processing in backward direction 
305     /// (recursion is in backward direction however execution always goes forward).
306     /// Pure virtual; defined in UserBlackBox and ComplexBlackBox
307     /// 
308     /// \returns The final status of the box (UPTODATE or MODIFIED)
309     /// \param caller : The connection which invoked the method; null if called by bbExecute
310     ///
311     /// First checks that re-processing is needed (either Status==MODIFIED or InputProcessMode==Always)
312     /// then : 
313     /// - updates its inputs by calling bbUpdateInputs (which recursively calls bbBackwardUpdate on upstream boxes)
314     /// - calls bbCreateWidget
315     /// - calls bbProcess which is the user callback which does the actual processing
316     /// - calls bbUpdateChildren
317     /// - calls bbShowWidget which shows the widget associated to the box (if any)
318   protected:
319     virtual IOStatus bbBackwardUpdate(Connection::Pointer caller) = 0;
320     //==================================================================
321
322     //==================================================================
323     /// Recursive pipeline processing in forward direction along "Child"-"Parent" connections
324     /// Pure virtual; defined in UserBlackBox and ComplexBlackBox
325     /// 
326     /// \param caller : The connection which invoked the method
327     ///
328     /// First checks that re-processing is needed (either Status==MODIFIED or InputProcessMode==Always)
329     /// then : 
330     /// - calls bbCreateWidget
331     /// - calls bbProcess which is the user callback which does the actual processing
332     /// - calls bbUpdateChildren which recursively calls bbForwardUpdate on connections attached the "Child" output
333     // virtual void bbForwardUpdate(Connection::Pointer caller) = 0;
334     //==================================================================
335   protected:
336     //==================================================================
337     /// Updates the BlackBox inputs and returns the final status of the inputs 
338     /// (==UPTODATE iff all inputs are UPTODATE)  
339     // If excludeParent == true then excludes the upstream box connected to input 'Parent' from recursive update
340     IOStatus bbUpdateInputs(bool excludeParent=false);
341     //==================================================================
342
343     //==================================================================
344     /// Updates the pipeline in upstream-downstream direction along the "Child"-"Parent" connections only.
345     /// Does nothing here. Overloaded in WxContainerBlackbox
346     //virtual void bbUpdateChildren( Connection::Pointer caller ) { }
347     //==================================================================
348
349     //==================================================================
350     /// Specific methods for window creation during pipeline execution
351     /// Creates the window associated to the box (called after bbUpdateInputs)
352     /// Does nothing here. Overloaded in WxBlackBox.
353     // virtual void bbCreateWindow() { }
354     /// Shows the window associated to the box 
355     /// (called after bbProcess during bbExecute)
356     /// Does nothing here but overloaded in WxBlackBox and WxContainerBlackBox
357     virtual void bbShowWindow(Connection::Pointer caller) { }
358
359     virtual void bbHideWindow() {}
360     virtual void bbCloseWindow() { }
361    //==================================================================
362
363     //@}
364   public: 
365
366     static bool bbGlobalGetSomeBoxExecuting();
367     static void bbGlobalSetSomeBoxExecuting(bool b);
368
369     static void bbGlobalSetFreezeExecution(bool b);
370     static bool bbGlobalGetFreezeExecution();
371
372     /// Returns true if the box can "react",
373     /// which means execute in response to an input change 
374     virtual bool bbCanReact() const;
375     
376     /// Returns true iff the box is executing
377     bool bbGetExecuting() const { return bbmExecuting; }
378
379   protected:  
380     static void bbGlobalAddToExecutionList( BlackBox::Pointer b );
381     static void bbGlobalProcessExecutionList();
382     /// Sets the bbmExecuting bool returned by bbGetExecuting
383     void bbSetExecuting(bool b) { bbmExecuting = b; }
384
385     //==================================================================
386   protected:
387     //==================================================================
388     /// Allocates the i/o connectors of the black box
389     virtual void bbAllocateConnectors();
390     /// Desallocates the i/o connectors of the black box
391     virtual void bbDesallocateConnectors();
392     /// Copies the values of the inputs/output from the BlackBox from
393     virtual void bbCopyIOValues(BlackBox& from);
394     //==================================================================
395
396     // Black box objects have a special deleter 
397     // which must take care of releasing the descriptor 
398     // **AFTER** the box is deleted 
399     // (Releasing it in the destructor may cause dl close and crash)
400     /// Black box deleter 
401     /// 1) Calls the user overloadable bbDelete method
402     /// 2) Releases the box descriptor
403     struct BBTK_EXPORT Deleter : public Object::Deleter
404     { 
405       Deleter();
406       void Delete(Object* p);
407     };
408
409     template <class U>
410     static boost::shared_ptr<U> MakeBlackBoxPointer(U* s, bool lock = false)
411     {
412       return MakePointer(s,BlackBox::Deleter(),lock);
413     }
414
415     virtual void bbDelete() { delete this; }
416   private:
417     
418  
419     //==================================================================
420     // PRIVATE PART 
421     /// The status of the box
422     IOStatus bbmStatus;
423     /// Is the box executing ?
424     bool bbmExecuting;
425     /// The name of the black-box
426     std::string bbmName;
427     /// The name of the package to which it belongs
428     std::string bbmPackageName;
429         
430     /// 0 : "Pipeline" mode : bbBackwardUpdate() only calls Process if Status == MODIFIED (normal pipeline processing)
431     /// 1 : "Always" mode : bbUpdate() always calls Process  
432     /// 2 : "Reactive" mode : bbSetModifiedStatus() calls bbUpdate()
433     std::string bbmBoxProcessMode;
434
435     /// The parent of the black box in the ComplexBlackBox hierarchy
436     BlackBox::WeakPointer bbmParent;
437     //==================================================================
438
439
440    //==================================================================
441     // ATTRIBUTES
442     ///  Map that contains the output connectors of the black box
443     OutputConnectorMapType mOutputConnectorMap; 
444     ///  Map that contains the input connectors of the black box
445     InputConnectorMapType mInputConnectorMap;
446     //==================================================================
447
448
449  };
450   // Class BlackBox
451
452
453
454
455
456
457
458  
459 }
460 // namespace bbtk
461 #endif
462