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