1 /*=========================================================================
3 Module: $RCSfile: bbtkBlackBox.h,v $
5 Date: $Date: 2008/12/03 13:35:22 $
6 Version: $Revision: 1.16 $
7 =========================================================================*/
9 /* ---------------------------------------------------------------------
11 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
12 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
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.
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
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 * ------------------------------------------------------------------------ */
35 * \brief Class bbtk::BlackBox : abstract black-box interface.
39 * \class bbtk::BlackBox
40 * \brief Abstract black-box interface
43 #ifndef __bbtkBlackBox_h__
44 #define __bbtkBlackBox_h__
46 #include "bbtkSystem.h"
47 #include "bbtkBlackBoxDescriptor.h"
48 #include "bbtkBlackBoxInputConnector.h"
49 #include "bbtkBlackBoxOutputConnector.h"
56 struct Void { Void(int = 0) {} };
61 class BBTK_EXPORT BlackBox : public Object
63 BBTK_ABSTRACT_OBJECT_INTERFACE(BlackBox);
65 //==================================================================
67 //==================================================================
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;
76 /// Returns the pointer on the descriptor of the box
77 virtual BlackBoxDescriptor::Pointer bbGetDescriptor() const = 0;
79 /// Returns a pointer on a clone of the box with name <name>
80 virtual BlackBox::Pointer bbClone(const std::string& name) = 0;
82 /// User overloadable destruction method of a black box
83 virtual void bbUserDelete();
85 /// Returns the Name of the Type of the BlackBox
86 const std::string& bbGetTypeName() const
87 { return bbGetDescriptor()->GetTypeName(); }
90 /// Returns the name of the BlackBox (instance)
91 const std::string& bbGetName() const { return bbmName; }
93 /// Returns the full name of the BlackBox (instance+type)
94 virtual std::string bbGetFullName() const;
96 /// Returns the name with the name of the parent prepended if any
97 virtual std::string bbGetNameWithParent() const;
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(); }
103 /// Main processing method of the box.
104 virtual void bbExecute(bool force = false);
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);
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);
141 /// Gets the status of the box
142 virtual const IOStatus& bbGetStatus() const { return bbmStatus; }
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;
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;
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;
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,
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;
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; }
185 /// Prints the Help on the BlackBox type
186 virtual void bbGetHelp(bool full=true) const;
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; }
202 /// Returns the "decoded" value of the input "BoxProcessMode"
203 BoxProcessModeValue bbGetBoxProcessModeValue() const;
205 virtual bool bbBoxProcessModeIsReactive() const;
207 virtual bool bbBoxProcessModeIsAlways() const;
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) {}
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(); }
219 //==================================================================
222 //==================================================================
224 /// Does nothing here : overloaded in ComplexBlackBox
225 void bbInsertHTMLGraph( std::ofstream& s,
229 const std::string& output_dir,
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,
245 bool relative_link );
246 /// Auxiliary method for bbWriteDotFileBlackBox
247 virtual void bbWriteDotInputOutputName(FILE *ff,
249 int detail, int level);
252 virtual void bbShowRelations(BlackBox::Pointer parentblackbox,
253 int detail, int level
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();}
261 virtual void Check(bool recursive = true);
263 virtual void bbUserOnShow() { }
264 void bbUserOnShowWidget(std::string nameInput);
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 //==================================================================
277 //==================================================================
278 /// Sets the status of the box
279 void bbSetStatus( IOStatus t) { bbmStatus = t; }
280 //==================================================================
283 friend class Connection;
284 friend class ComplexBlackBox;
286 /// Sets the parent of the BlackBox
287 void bbSetParent(BlackBox::Pointer p) { bbmParent = p; }
290 /// Connects the input <name> to the connection c
291 virtual void bbConnectInput( const std::string& name,
293 /// Connects the output <name> to the connection c
294 virtual void bbConnectOutput( const std::string& name,
296 /// Disconnects the input <name> from the connection c
297 virtual void bbDisconnectInput( const std::string& name,
299 /// Disconnects the output <name> from the connection c
300 virtual void bbDisconnectOutput( const std::string& name,
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.
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
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
320 /// First checks that re-processing is needed (either Status==MODIFIED or InputProcessMode==Always)
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)
328 virtual IOStatus bbBackwardUpdate(Connection::Pointer caller) = 0;
329 //==================================================================
331 //==================================================================
332 /// Recursive pipeline processing in forward direction along "Child"-"Parent" connections
333 /// Pure virtual; defined in UserBlackBox and ComplexBlackBox
335 /// \param caller : The connection which invoked the method
337 /// First checks that re-processing is needed (either Status==MODIFIED or InputProcessMode==Always)
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 //==================================================================
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 //==================================================================
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 //==================================================================
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) { }
368 virtual void bbHideWindow() {}
369 virtual void bbCloseWindow() { }
370 //==================================================================
375 static bool bbGlobalGetSomeBoxExecuting();
376 static void bbGlobalSetSomeBoxExecuting(bool b);
378 static void bbGlobalSetFreezeExecution(bool b);
379 static bool bbGlobalGetFreezeExecution();
381 /// Returns true if the box can "react",
382 /// which means execute in response to an input change
383 virtual bool bbCanReact() const;
385 /// Returns true iff the box is executing
386 bool bbGetExecuting() const { return bbmExecuting; }
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; }
394 //==================================================================
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 //==================================================================
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
415 void Delete(Object* p);
419 static boost::shared_ptr<U> MakeBlackBoxPointer(U* s, bool lock = false)
421 return MakePointer(s,BlackBox::Deleter(),lock);
424 virtual void bbDelete() { delete this; }
428 //==================================================================
430 /// The status of the box
432 /// Is the box executing ?
434 /// The name of the black-box
436 /// The name of the package to which it belongs
437 std::string bbmPackageName;
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;
444 /// The parent of the black box in the ComplexBlackBox hierarchy
445 BlackBox::WeakPointer bbmParent;
446 //==================================================================
449 //==================================================================
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 //==================================================================