]> Creatis software - bbtk.git/blob - kernel/src/bbtkBlackBox.cxx
Try to display planes (from Image Planes)
[bbtk.git] / kernel / src / bbtkBlackBox.cxx
1 /*=========================================================================                                                                               
2   Program:   bbtk
3   Module:    $RCSfile: bbtkBlackBox.cxx,v $
4   Language:  C++
5   Date:      $Date: 2008/12/03 09:34:37 $
6   Version:   $Revision: 1.30 $
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  *  \file 
33  *  \brief Class bbtk::BlackBox : abstract black-box interface. 
34  */
35 #include "bbtkBlackBox.h"
36 #include "bbtkPackage.h"
37 #include "bbtkMessageManager.h"
38 #include "bbtkFactory.h"
39
40 #include "bbtkConfigurationFile.h"
41 #include "bbtkWxBlackBox.h"
42
43 #include <fstream>
44 //#include <vector>
45
46
47 namespace bbtk
48 {
49
50
51   static bool bbmgSomeBoxExecuting = false;
52   static bool bbmgFreezeExecution = false;
53   static std::set<BlackBox::WeakPointer> bbmgExecutionList;
54
55   //=========================================================================
56   BlackBox::Deleter::Deleter()
57   {
58   }
59   //=========================================================================
60   
61   //=========================================================================
62   void BlackBox::Deleter::Delete(Object* p)
63   {
64     BlackBox* b = dynamic_cast<BlackBox*>(p);
65     if (!b)
66       {
67         bbtkInternalError("BlackBox::Deleter::Delete("<<p->GetObjectName()
68                           <<"["<<p<<"]) : "
69                           <<"dynamic cast to BlackBox* failed !");
70       }
71     std::string name = p->GetObjectName();//b->bbGetNameWithParent();
72     bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\")"<<std::endl);
73
74
75     BlackBoxDescriptor::WeakPointer desc = b->bbGetDescriptor();
76     bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\") : deleting black box"<<std::endl);
77     
78     b->bbDelete();
79
80     bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\") : releasing descriptor ["<<desc.lock()<<"]"<<std::endl);
81     
82     if (!desc.expired()) 
83       {
84         Package::WeakPointer pack = desc.lock()->GetPackage();
85         if (!pack.expired()) 
86           {
87             Package::ReleaseBlackBoxDescriptor(pack,desc);
88           }
89         else 
90           {
91             bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\") : descriptor package expired (was not held by a package and the box was the last instance)"<<std::endl);
92           }
93       }
94     else
95       {
96         bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\") : descriptor expired : nothing to do (was not held by a package or the box is a complex black box prototype)"<<std::endl);
97       }
98     bbtkDebugMessage("object",2,"<## BlackBox::Deleter(\""<<name<<"\")"<<std::endl);
99   }
100   //=========================================================================
101
102   //=========================================================================
103   BlackBox::BlackBox(const std::string &name) 
104     : 
105     bbmStatus(MODIFIED), 
106     bbmExecuting(false),
107     bbmName(name),
108     bbmBoxProcessMode("Pipeline"),
109     bbmParent()
110     
111   {
112     bbtkDebugMessage("object",4,"==> BlackBox::BlackBox(\""
113                      <<name<<"\")"<<std::endl);
114     bbtkDebugMessage("object",4,"<== BlackBox::BlackBox(\""
115                      <<name<<"\")"<<std::endl);
116   }
117   //=========================================================================
118
119   //=========================================================================
120   BlackBox::BlackBox(const BlackBox&)
121   {}
122
123   //=========================================================================
124   BlackBox::BlackBox(BlackBox& from, const std::string &name) 
125     :
126       bbmStatus(from.bbmStatus), 
127       bbmExecuting(false),
128       bbmName(name), 
129       bbmBoxProcessMode(from.bbmBoxProcessMode),
130       bbmParent()
131
132   {
133     bbtkDebugMessage("object",4,"==> BlackBox::BlackBox("
134                      <<from.bbGetFullName()<<",\""
135                      <<name<<"\")"<<std::endl);
136     bbtkDebugMessage("object",4,"<== BlackBox::BlackBox("
137                      <<from.bbGetFullName()<<",\""
138                      <<name<<"\")"<<std::endl);
139   }
140   //=========================================================================
141
142
143   //=========================================================================
144   BlackBox::~BlackBox()
145   {
146     bbtkDebugMessage("object",4,"==> BlackBox::~BlackBox() ["<<bbmName
147                      <<"]"<<std::endl);
148     this->bbDesallocateConnectors();
149     bbtkDebugMessage("object",4,"<== BlackBox::~BlackBox() ["<<bbmName
150                      <<"]"<<std::endl);
151   }
152   //=========================================================================
153
154
155   //=========================================================================
156   /// Main processing method of the box.
157   void BlackBox::bbExecute(bool force)
158   {
159     bbtkDebugMessageInc("process",2,
160                         "=> BlackBox::bbExecute("<<(int)force<<") ["
161                         <<bbGetFullName()<<"]"<<std::endl);
162  
163     // If already executing : return
164     if (bbGetExecuting()) 
165       {
166         bbtkDebugMessage("process",2,
167                          " -> already executing : bailing out"<<std::endl);
168         return;
169       }
170
171     // If execution frozen : return
172     if (bbGlobalGetFreezeExecution()) 
173       {
174         bbtkDebugMessage("process",2,
175                          " -> FreezeExecution global flag is 'true' : abort execution"<<std::endl);
176       }
177
178     BBTK_BUSY_CURSOR;
179
180     // If force is true then update is triggered even if the box is UPTODATE
181     if (force) bbSetModifiedStatus();
182
183     // Calls the main recursive update method 
184     bbBackwardUpdate(Connection::Pointer());
185
186     bbtkDebugMessageDec("process",2,
187                         "<= BlackBox::bbExecute() ["
188                         <<bbGetFullName()<<"]"<<std::endl);
189   }
190   //=========================================================================
191
192   //=========================================================================
193   std::string BlackBox::bbGetFullName() const
194   { 
195     return this->bbGetNameWithParent()+"<"+this->bbGetDescriptor()->GetTypeName()+">";
196   }
197   //=========================================================================
198      
199
200
201   //=========================================================================
202   /// Returns the name with the name of the parent prepended if any
203   std::string BlackBox::bbGetNameWithParent() const
204   {
205     if (bbmParent.lock()) 
206       {
207         return bbmParent.lock()->bbGetNameWithParent() + ":" + bbmName;
208       }
209     else 
210       {
211         return bbmName;
212       }
213   } 
214   //=========================================================================
215
216   //=========================================================================
217   /// Prints the Help on the BlackBox type 
218   void BlackBox::bbGetHelp(bool full) const
219   {
220     bbGetDescriptor()->GetHelp(full); 
221   }
222   //=========================================================================
223
224
225   //=========================================================================
226   /// Returns true if the UserBlackBox has an input of name name
227   bool BlackBox::bbHasInput(const std::string& name) const
228   {
229     bbtkDebugMessageInc("Kernel",8,
230                         "BlackBox::bbHasInput(\""
231                         <<name<<"\") ["<<bbGetFullName()<<"]"
232                         <<std::endl);
233     bool r = ( bbGetDescriptor()->GetInputDescriptorMap().find(name)
234                != bbGetDescriptor()->GetInputDescriptorMap().end());
235     bbtkDebugDecTab("Kernel",8);
236     return r;
237   }
238   //=========================================================================
239
240
241   //=========================================================================  
242   /// Returns true if the UserBlackBox has an output of name name
243   bool BlackBox::bbHasOutput(const std::string& name) const
244   {
245     bbtkDebugMessageInc("Kernel",8,"BlackBox::bbHasOutput(\""
246                         <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
247     bool r = ( bbGetDescriptor()->GetOutputDescriptorMap().find(name)
248                != bbGetDescriptor()->GetOutputDescriptorMap().end());
249     bbtkDebugDecTab("Kernel",8);
250     return r;
251   }
252   //=========================================================================
253
254
255   //=========================================================================  
256   ///  Gets the output type of a given name
257   TypeInfo BlackBox::bbGetOutputType( const std::string &name ) const 
258   {
259     bbtkDebugMessageInc("Kernel",8,
260                         "BlackBox::bbGetOutputType(\""
261                         <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
262     TypeInfo r = bbGetDescriptor()->GetOutputDescriptor(name)->GetTypeInfo();
263     bbtkDebugDecTab("Kernel",8); 
264     return r;
265   }
266   //=========================================================================
267
268   //=========================================================================
269   ///  Gets the input type of a given name
270   TypeInfo BlackBox::bbGetInputType( const std::string &name ) const
271   {
272     bbtkDebugMessageInc("Kernel",8,
273                         "BlackBox::bbGetInputType(\""
274                         <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
275     TypeInfo r = bbGetDescriptor()->GetInputDescriptor(name)->GetTypeInfo();
276     bbtkDebugDecTab("Kernel",8);
277     return r;
278   }
279   //=========================================================================
280
281
282   //=========================================================================
283   /// Allocates the i/o connectors of the black box
284   void BlackBox::bbAllocateConnectors()
285   {  
286     bbtkDebugMessageInc("Kernel",8,
287                         "BlackBox::bbAllocateConnectors() ["
288                         <<bbGetFullName()<<"]"
289                         <<std::endl);                                   
290     const BlackBoxDescriptor::InputDescriptorMapType& imap 
291       = bbGetDescriptor()->GetInputDescriptorMap(); 
292     BlackBoxDescriptor::InputDescriptorMapType::const_iterator i;       
293     for ( i = imap.begin(); i != imap.end(); ++i )                      
294       {                                                                 
295         bbtkDebugMessage("Kernel",8,"* Allocate \""<<i->first<<"\""<<std::endl);
296         bbGetInputConnectorMap()[i->second->GetName()] 
297           = new BlackBoxInputConnector(GetThisPointer<BlackBox>());
298       }                                                                 
299     const BlackBoxDescriptor::OutputDescriptorMapType& omap 
300       = bbGetDescriptor()->GetOutputDescriptorMap();                   
301     BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o; 
302     for ( o = omap.begin(); o != omap.end(); ++o )
303       {                                                 
304         bbtkDebugMessage("Kernel",8,"* Allocate \""<<o->first<<"\""<<std::endl);
305         bbGetOutputConnectorMap()[o->second->GetName()] 
306           = new BlackBoxOutputConnector();
307       }
308     bbtkDebugDecTab("Kernel",8);  
309   }
310   //=========================================================================
311
312
313   //=========================================================================
314   /// Desallocates the i/o connectors of the black box
315   void BlackBox::bbDesallocateConnectors()
316   {
317     bbtkDebugMessageInc("Kernel",8,
318                         "BlackBox::bbDesallocateConnectors()"
319                         <<std::endl);                                   
320
321     InputConnectorMapType::const_iterator i;
322     for ( i = bbGetInputConnectorMap().begin();
323           i != bbGetInputConnectorMap().end(); ++i )                   
324       {                                                                 
325         bbtkDebugMessage("Kernel",8,"* Delete \""<<i->first<<"\""<<std::endl);
326         delete (i->second);
327       }                                                                 
328     OutputConnectorMapType::const_iterator o;   
329     for ( o = bbGetOutputConnectorMap().begin(); 
330           o != bbGetOutputConnectorMap().end(); ++o )                   
331       {                                                                 
332         bbtkDebugMessage("Kernel",8,"* Delete \""<<o->first<<"\""<<std::endl);         
333         delete (o->second);
334       }                                                                 
335    
336     bbtkDebugDecTab("Kernel",8);  
337
338   }
339   //=========================================================================
340
341
342   //=========================================================================
343   /// Copies the input / output values from another box
344   void BlackBox::bbCopyIOValues(BlackBox& from)
345   {
346     bbtkDebugMessageInc("Kernel",1,
347                         "BlackBox::bbCopyIOValues("
348                         <<from.bbGetFullName()<<") ["
349                         <<bbGetFullName()<<"]"<<std::endl);
350     // copies the input values
351     const BlackBoxDescriptor::InputDescriptorMapType& imap 
352       = bbGetDescriptor()->GetInputDescriptorMap(); 
353     BlackBoxDescriptor::InputDescriptorMapType::const_iterator i;       
354     for ( i = imap.begin(); i != imap.end(); ++i )                      
355       {         
356         if (! i->second->GetCopyConstruct() ) continue;
357         std::string input = i->second->GetName();
358         bbtkDebugMessage("Kernel",2,"* Copying input "<<input<<std::endl);
359         this->bbSetInput(input, from.bbGetInput(input) );
360       }                                                                 
361     // copies the output values
362     const BlackBoxDescriptor::OutputDescriptorMapType& omap 
363       = bbGetDescriptor()->GetOutputDescriptorMap();                   
364     BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o; 
365     for ( o = omap.begin(); o != omap.end(); ++o )
366       {                                                 
367         if (! o->second->GetCopyConstruct() ) continue;
368         std::string output = o->second->GetName();
369         bbtkDebugMessage("Kernel",2,"* Copying output "<<output<<std::endl);
370         this->bbSetOutput(output, from.bbGetOutput(output) );
371       }
372
373     bbtkDebugDecTab("Kernel",9);
374
375   }
376   //=========================================================================
377
378
379
380   //=========================================================================
381   bool BlackBox::bbCanReact() const 
382   { 
383     return ( bbGlobalGetSomeBoxExecuting() 
384 #ifdef _USE_WXWIDGETS_
385              || Wx::IsSomeWindowAlive() 
386 #endif
387              ); 
388   }
389   //=========================================================================
390
391
392
393   //=========================================================================
394   /// User overloadable destruction method of a black box
395   void BlackBox::bbUserDelete() 
396   {   
397     bbtkDebugMessage("process",5,
398                      "=> BlackBox::bbUserDelete() ["
399                      <<bbGetFullName()<<"]"
400                      <<" : not overloaded; using standard deletion"
401                      <<std::endl);
402     delete this;
403   }
404   //=========================================================================
405
406
407   //=========================================================================
408   BlackBox::BoxProcessModeValue BlackBox::bbGetBoxProcessModeValue() const
409   {
410     const std::string& p = bbmBoxProcessMode;
411     if ( (p == "0") ||
412          (p == "P") || (p == "p") ||
413          (p == "Pipeline") || (p == "pipeline") ) return Pipeline;
414     if ( (p == "1") ||
415          (p == "A") || (p == "a") ||
416          (p == "Always") || (p == "always") ) return Always;
417     if ( (p == "2") ||
418          (p == "R") || (p == "r") ||
419          (p == "Reactive") || (p == "reactive") ) return Reactive;
420     bbtkError(bbGetFullName()<<" : BoxProcessMode value '"<<p
421               <<"' unknown. Possible values : "
422               <<"'0'/'P'/'p'/'Pipeline'/'pipeline' | "
423               <<"'1'/'A'/'a'/'Always'/'always' | "
424               <<"'2'/'R'/'r'/'Reactive'/'reactive'"<<std::endl);
425   }
426   //=========================================================================
427   
428   //=========================================================================
429   bool  BlackBox::bbBoxProcessModeIsReactive() const
430   {
431     return (bbGetBoxProcessModeValue() == Reactive);
432   }
433   //=========================================================================
434
435   //=========================================================================
436   bool  BlackBox::bbBoxProcessModeIsAlways() const
437   {
438     return (bbGetBoxProcessModeValue() == Always);
439   }
440   //=========================================================================
441
442   //=========================================================================
443   ///  Signals that the BlackBox has been modified
444   void BlackBox::bbSetModifiedStatus(BlackBoxInputConnector* c)
445   {
446     bbtkDebugMessage("modified",1,
447                      "==> BlackBox::bbSetModifiedStatus("<<c<<") ["
448                      <<bbGetFullName()<<"]"<<std::endl);
449     
450     if ( (c==bbGetInputConnectorMap().find("WinHide")->second) )
451       //         && (bbCanReact()))
452       {
453         bbtkDebugMessage("modified",2,
454                          "-> Hide triggered by WinHide input change"
455                          <<std::endl);
456         this->bbHideWindow();
457         this->bbSetStatus(MODIFIED); 
458         return;
459       }
460     if ( (c==bbGetInputConnectorMap().find("WinClose")->second) )
461       //         && (bbCanReact()))
462       {
463         bbtkDebugMessage("modified",2,
464                          "-> Close triggered by WinClose input change"
465                          <<std::endl);
466         this->bbHideWindow();
467         this->bbSetStatus(MODIFIED); 
468         return;
469       }
470     
471     if ( ( bbBoxProcessModeIsReactive()  ||
472            (c==bbGetInputConnectorMap().find("BoxExecute")->second))
473          && (bbCanReact() ) )
474       {
475         bbtkDebugMessage("modified",2,
476                          "-> Execution triggered by Reactive mode or BoxExecute input change"<<std::endl);
477         this->bbSetStatus(MODIFIED); 
478         bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
479       }
480     /*
481     else if ( bbGetStatus() == MODIFIED ) //! this->bbIsUptodate()) 
482       { 
483         bbtkDebugMessage("modified",2,"-> Already modified"<<std::endl);
484         return;
485       }
486     */
487     else 
488       {
489         bbtkDebugMessage("modified",2,"-> Status set to modified"<<std::endl);
490         this->bbSetStatus(MODIFIED); 
491         std::cout << "Status set to modified" <<std::endl;
492       }
493  
494     this->bbSignalOutputModification(false);
495
496     /* 
497   bbtkDebugMessageDec("process",5,
498                         "<= BlackBox::bbSetModifiedStatus("<<c<<") ["
499                         <<bbGetFullName()<<"]"<<std::endl);
500     */
501   }  
502   //=========================================================================
503
504   //=========================================================================  
505   void BlackBox::bbSignalOutputModification(bool reaction)
506   {
507     bbtkDebugMessageInc("process",5,
508                         "=> BlackBox::bbSignalOutputModification() ["
509                         <<bbGetFullName()<<"]"<<std::endl);
510     
511     OutputConnectorMapType::iterator change = bbGetOutputConnectorMap().end();
512     OutputConnectorMapType::iterator i;
513     for ( i  = bbGetOutputConnectorMap().begin(); 
514           i != bbGetOutputConnectorMap().end(); ++i) {
515       /*     if ( i->first == "BoxChange" ) 
516         {
517           change = i;
518           continue;
519         }
520       */
521       i->second->SetModifiedStatus();
522     } 
523     //    if (change != bbGetOutputConnectorMap().end()) 
524     // change->second->SetModifiedStatus();
525
526     if (reaction) bbGlobalProcessExecutionList();
527
528     bbtkDebugMessageDec("process",5,
529                         "<= BlackBox::bbSignalOutputModification() ["
530                         <<bbGetFullName()<<"]"<<std::endl);
531     
532   }  
533   //=========================================================================   
534   //=========================================================================  
535   void BlackBox::bbSignalOutputModification(const std::string& output,
536         bool reaction)
537   {
538     bbtkDebugMessageInc("process",5,
539                         "=> BlackBox::bbSignalOutputModification("
540                         <<output<<") ["
541                         <<bbGetFullName()<<"]"<<std::endl);
542     
543     OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(output);
544     if ( i == bbGetOutputConnectorMap().end() ) 
545         {
546           bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<output<<") : unknown output");
547         }
548     i->second->SetModifiedStatus();
549     // Has to notify the output "BoxChange" also
550     if (output != "BoxChange") 
551       {
552         i = bbGetOutputConnectorMap().find("BoxChange");
553         if ( i != bbGetOutputConnectorMap().end() ) 
554           {
555             i->second->SetModifiedStatus();
556           }
557       }
558   if (reaction) bbGlobalProcessExecutionList();
559
560   bbtkDebugMessageDec("process",5,
561                       "<= BlackBox::bbSignalOutputModification("
562                       <<output<<") ["
563                       <<bbGetFullName()<<"]"<<std::endl);
564
565   }  
566   //=========================================================================   
567   //=========================================================================  
568   void BlackBox::bbSignalOutputModification(const std::vector<std::string>& output,
569         bool reaction)
570   {
571     bbtkDebugMessageInc("process",5,
572                         "=> BlackBox::bbSignalOutputModification(vector of outputs) ["
573                         <<bbGetFullName()<<"]"<<std::endl);
574     OutputConnectorMapType::iterator i;
575     std::vector<std::string>::const_iterator o;
576     for (o=output.begin();o!=output.end();++o) 
577       {
578         // the output "BoxChange" must be signaled **AFTER** all others
579         if (*o == "BoxChange") continue;
580         // Look for the connector
581         i = bbGetOutputConnectorMap().find(*o);
582         if ( i == bbGetOutputConnectorMap().end() ) 
583           {
584             bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<*o<<") : unknown output");
585           }
586         i->second->SetModifiedStatus();
587       }
588     // Has to notify the output "BoxChange" also
589     i = bbGetOutputConnectorMap().find("BoxChange");
590     if ( i != bbGetOutputConnectorMap().end() ) 
591       {
592         i->second->SetModifiedStatus();
593       }
594   if (reaction) bbGlobalProcessExecutionList();
595
596    bbtkDebugMessageDec("process",5,
597                        "<= BlackBox::bbSignalOutputModification(vector of outputs) ["
598                         <<bbGetFullName()<<"]"<<std::endl);
599
600   }  
601   //=========================================================================   
602
603   //=========================================================================
604   /// Updates the BlackBox inputs
605   /// \returns UPTODATE if all inputs are in UPTODATE status after update
606   ///          else MODIFIED 
607   IOStatus BlackBox::bbUpdateInputs(bool excludeParent)
608   {
609     bbtkDebugMessageInc("process",4,
610                         "=> BlackBox::bbUpdateInputs() ["
611                         <<bbGetFullName()<<"]"
612                         <<std::endl);   
613
614     IOStatus s = UPTODATE;
615
616     InputConnectorMapType::iterator i;
617     for ( i = bbGetInputConnectorMap().begin(); 
618           i!= bbGetInputConnectorMap().end(); ++i) 
619       {
620         if (excludeParent && (i->first=="WinParent")) continue;
621         if (i->first=="WinHide") continue;
622         // If input type is Void : no recurse
623         //if (  bbGetDescriptor()->GetInputDescriptor(i->first)->GetTypeInfo() 
624         //      == typeid(Void) ) 
625         //  continue;
626
627         IOStatus t = i->second->BackwardUpdate();
628         if (t==MODIFIED) s = MODIFIED;
629       }
630     
631    bbtkDebugMessageDec("process",4,
632                         "<= BlackBox::bbUpdateInputs() ["
633                         <<bbGetFullName()<<"]"
634                         <<std::endl);   
635
636
637     return s;
638   }
639   //=========================================================================
640
641  
642   //=========================================================================
643   /// Connects the input <name> to the connection c
644   void BlackBox::bbConnectInput( const std::string& name, Connection* c)
645   {
646     bbtkDebugMessage("connection",2,
647                         "==> BlackBox::bbConnectInput(\""
648                         <<name<<"\","<<c->GetFullName()<<") ["
649                         <<bbGetFullName()<<"]"
650                         <<std::endl);       
651
652
653     InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
654     if (i==bbGetInputConnectorMap().end())
655       {
656         bbtkError("no input called '"<<name<<"'");
657       }
658     i->second->SetConnection(c);
659     
660     bbtkDebugMessage("connection",2,
661                         "<== BlackBox::bbConnectInput(\""
662                         <<name<<"\","<<c->GetFullName()<<") ["
663                         <<bbGetFullName()<<"]"
664                         <<std::endl);       
665     //  bbSetModifiedStatus();
666
667   }
668   //=========================================================================
669
670
671   //=========================================================================  
672   /// Connects the output <name> to the connection c
673   void BlackBox::bbConnectOutput( const std::string& name, Connection* c)
674   {
675     bbtkDebugMessage("connection",2,
676                      "==> BlackBox::bbConnectOutput(\""<<name<<"\","
677                      <<c->GetFullName()<<") ["
678                      <<bbGetFullName()<<"]"<<std::endl);       
679     
680     OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
681     if (i==bbGetOutputConnectorMap().end())
682       {
683         bbtkError("no output called '"<<name<<"'");
684       }
685     i->second->SetConnection(c);
686
687     bbtkDebugMessage("connection",2,
688                      "<== BlackBox::bbConnectOutput(\""<<name<<"\","
689                      <<c->GetFullName()<<") ["
690                      <<bbGetFullName()<<"]"<<std::endl);       
691
692   }
693   //=========================================================================
694
695
696   //=========================================================================
697   /// Disconnects the input <name> from the connection c
698   void BlackBox::bbDisconnectInput( const std::string& name, Connection* c)
699   {
700
701     bbtkDebugMessage("connection",2,
702                      "==> BlackBox::bbDisconnectInput(\""<<name
703                      <<"\","<<c->GetFullName()<<") ["
704                      <<bbGetFullName()<<"]"
705                      <<std::endl);      
706
707     if (!c) 
708       {
709
710         bbtkDebugMessage("connection",2,"c==0"<<std::endl);     
711         return;
712       }
713
714     InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
715     if (i==bbGetInputConnectorMap().end())
716       {
717         bbtkError("no input called '"<<name<<"'");
718       }
719     i->second->UnsetConnection(c);
720
721     bbtkDebugMessage("connection",2,
722                      "<== BlackBox::bbDisconnectInput(\""<<name
723                      <<"\","<<c->GetFullName()<<") ["
724                      <<bbGetFullName()<<"]"
725                      <<std::endl);      
726
727   }
728   //=========================================================================
729
730
731   //=========================================================================
732   /// Disconnects the output <name> from the connection c
733   void BlackBox::bbDisconnectOutput( const std::string& name, Connection* c)
734   {
735     bbtkDebugMessage("connection",2,
736                      "==> BlackBox::bbDisconnectOutput(\""<<name
737                      <<"\","<<c->GetFullName()<<") ["
738                      <<bbGetFullName()<<"]"
739                      <<std::endl);       
740     if (!c) 
741       {
742
743         bbtkDebugMessage("connection",2,"c==0"<<std::endl);     
744         return;
745       }
746
747     OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
748     if (i==bbGetOutputConnectorMap().end())
749       {
750         bbtkError("no output called '"<<name<<"'");
751       }
752     i->second->UnsetConnection(c);
753
754     bbtkDebugMessage("connection",2,
755                      "<== BlackBox::bbDisconnectOutput(\""<<name
756                      <<"\","<<c->GetFullName()<<") ["
757                      <<bbGetFullName()<<"]"
758                      <<std::endl);       
759   } 
760   //=========================================================================
761  
762
763   //=========================================================================
764   /// Virtual
765   void BlackBox::bbWriteDotInputOutputName(FILE *ff,bool inputoutput,int detail, int level)
766   {
767     fprintf(ff,"%s%p",bbGetTypeName().c_str(),this);
768   }
769   //=========================================================================
770
771
772   //=========================================================================
773   std::string BlackBox::bbGetOutputAsString( const std::string &output ) 
774   {
775     std::string v;
776     // Looks for the adaptor
777     if (bbGetOutputType(output).name() != typeid(std::string).name() ) 
778       {
779         // Look for factory 
780         Package::Pointer p = bbGetDescriptor()->GetPackage();
781         if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
782           {
783             Factory::Pointer f = p->GetFactorySet().begin()->lock();
784             BlackBox::Pointer a;
785             try
786               {
787                 a = f->NewAdaptor(  
788                                   bbGetOutputType(output),
789                                   typeid(std::string),
790                                   "");
791               } catch (bbtk::Exception e) 
792               {
793               }
794             if (a){
795               //                        bbUpdate();
796               a->bbSetInput("In",bbGetOutput(output));
797               a->bbExecute();
798               v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
799             } else {
800               v="? (no adaptor found)";
801             }
802           }
803         else 
804           {
805             v="? (no factory found)";
806           }
807       } 
808     else 
809       {
810         //         bbUpdate();
811         v = bbGetOutput(output).unsafe_get<std::string>() ;
812       }
813     return v;
814   }
815   //=========================================================================
816
817   //=========================================================================
818   std::string BlackBox::bbGetInputAsString( const std::string &input ) 
819   {
820     std::string v;
821     // Looks for the adaptor
822     if (bbGetInputType(input) != typeid(std::string)) 
823       {
824         // Look for factory 
825         Package::Pointer p = bbGetDescriptor()->GetPackage();
826         if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
827           {
828             Factory::Pointer f = p->GetFactorySet().begin()->lock();
829             BlackBox::Pointer a;
830             try
831               {
832                 a = f->NewAdaptor(  
833                                bbGetInputType(input),
834                                typeid(std::string),
835                                "");
836               }catch (bbtk::Exception e) 
837               {
838               }
839             if (a)
840               {
841                 //                      bbUpdate();
842                 a->bbSetInput("In",bbGetInput(input));
843                 a->bbExecute();
844                 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
845               } 
846             else 
847               {
848                 v="? (no adaptor found)";
849               }
850           } 
851         else 
852           {
853             v="? (no factory found)";
854           }
855       }
856     else 
857       {
858         v = bbGetInput(input).unsafe_get<std::string>() ;
859       }
860     return v;
861   }
862   //=======================================================================
863
864   //=======================================================================
865   // Replaces substrings "<" by "["
866   void SubsBrackets ( std::string& s )
867   {
868     //   std::cout << "BEFORE=["<<s<<"]"<<std::endl;
869     std::string ss("<");
870     std::string::size_type pos = 0;
871     pos = s.find(ss,0);
872     char* cr = "[";
873     while ( pos != std::string::npos )
874       {
875         //      std::cout << "*** find one "<<std::endl;
876         s.replace(pos,1,cr,1);
877         pos = s.find(ss, pos);
878       } 
879     ss = ">";
880     pos = 0;
881     pos = s.find(ss,0);
882     cr = "]";
883     while ( pos != std::string::npos )
884       {
885         //      std::cout << "*** find one "<<std::endl;
886         s.replace(pos,1,cr,1);
887         pos = s.find(ss, pos);
888       } 
889     ss = ",";
890     pos = 0;
891     pos = s.find(ss,0);
892     cr = "-";
893     while ( pos != std::string::npos )
894       {
895         //      std::cout << "*** find one "<<std::endl;
896         s.replace(pos,1,cr,1);
897         pos = s.find(ss, pos);
898       }     //    std::cout << "AFTER=["<<s<<"]"<<std::endl;
899   }
900   //=======================================================================
901
902   //=========================================================================
903   /// Write Graphviz-dot description in file
904   void BlackBox::bbWriteDotFileBlackBox(FILE *ff,
905                                         BlackBox::Pointer parentblackbox, 
906                                         int detail, int level,
907                                         bool instanceOrtype,
908                                         bool relative_link )
909
910   { 
911     InputConnectorMapType::iterator i;
912     // label
913     std::string labelStr;
914     std::string valueStr("");
915
916         if (detail==0) {
917                 labelStr = bbGetName() ; 
918 //EED 18 Fev 2008
919                 labelStr = labelStr + "\\n[" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "]";
920         } else {
921                 labelStr = bbGetName();
922                 labelStr = labelStr + "   [" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "]  ";
923     }
924
925     SubsBrackets(labelStr);
926     if (detail==1)
927       {
928         labelStr = labelStr + " | {{ "; 
929         std::string tempStrTypeName;
930         bool tmp; 
931         tmp=false;
932         for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i ) 
933           {
934             if (tmp==true)
935               {
936                 labelStr=labelStr+" | ";
937               }
938             tmp=true;
939             if (instanceOrtype==true)
940               {
941                 valueStr = this->bbGetInputAsString(i->first) + " = ";
942               } 
943             const BlackBoxInputDescriptor* id = bbGetDescriptor()->GetInputDescriptor(i->first);
944             tempStrTypeName=id->GetTypeName();
945             SubsBrackets(tempStrTypeName);
946             std::string Name(i->first);
947             SubsBrackets(Name);
948             labelStr=labelStr + "<"+i->first.c_str()+"> "  + valueStr +  Name.c_str() + "  [" + tempStrTypeName.c_str() + "]";
949           }
950         labelStr=labelStr+ " } | {";
951         tmp = false;
952         OutputConnectorMapType::iterator ii;
953         for ( ii = mOutputConnectorMap.begin(); ii != mOutputConnectorMap.end(); ++ii ) 
954         {
955            if (tmp==true)
956            {
957                    labelStr=labelStr+" | ";
958            }
959            tmp = true;
960            if (instanceOrtype==true)
961            {
962                    valueStr = this->bbGetOutputAsString(ii->first) + " = ";
963            }
964            const BlackBoxOutputDescriptor* id = bbGetDescriptor()->GetOutputDescriptor(ii->first); 
965            tempStrTypeName=id->GetTypeName();
966            SubsBrackets(tempStrTypeName);
967             std::string Name(ii->first);
968             SubsBrackets(Name);
969            labelStr=labelStr+"<"+ii->first.c_str()+"> " + valueStr + Name.c_str() + "  ["+tempStrTypeName+"]";
970         }
971         labelStr = labelStr+ "      } }" ;
972 } // detail
973
974     fprintf(ff,"  " );
975     bbWriteDotInputOutputName(ff,true,detail,level);
976     std::string tmp ( bbGetTypeName() );
977     SubsBrackets(tmp);
978     std::string url;
979     if (relative_link) 
980       url = this->bbGetDescriptor()->GetPackage()->GetDocRelativeURL() + "#" + tmp;
981     else 
982       url = this->bbGetDescriptor()->GetPackage()->GetDocURL() + "#" + tmp;
983   
984     fprintf( ff , " [shape=record, URL=\"%s\",label=\"%s\"]%s\n",url.c_str(),labelStr.c_str(),";" );
985     //    std::cout  << labelStr << std::endl;
986
987     // Relation Input
988     if (GetThisPointer<BlackBox>()!=parentblackbox){
989       for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i ) 
990         {
991           if (i->second)
992             {
993               Connection* con = i->second->GetConnection();
994               if (con!=NULL){
995                 BlackBox::Pointer a=con->GetOriginalBlackBoxFrom();
996                 BlackBox::Pointer b=con->GetOriginalBlackBoxTo();
997                 fprintf(ff,"  ");
998                 a->bbWriteDotInputOutputName(ff,false,detail,level);
999                 if (detail==1)
1000                   {
1001                     fprintf(ff,":%s",con->GetOriginalBlackBoxFromOutput().c_str());
1002                   }
1003                 fprintf(ff,"->");
1004                 b->bbWriteDotInputOutputName(ff,true,detail,level);
1005                 if (detail==1)
1006                   {
1007                     fprintf(ff,":%s",con->GetOriginalBlackBoxToInput().c_str());
1008                   }
1009                 fprintf(ff,"%s\n",";");
1010               }  // if con
1011             } // if second
1012         } // for
1013     } // if parentblackbox
1014   }
1015   //=========================================================================
1016
1017
1018
1019
1020   //=========================================================================
1021   void BlackBox::bbShowRelations(BlackBox::Pointer parentblackbox, 
1022                                  int detail, int level
1023                                  /*,Factory *factory*/ )
1024   {
1025      
1026     if (this->bbGetDescriptor()->GetPackage()) 
1027       {
1028         bbtkMessage("Help",1,"Black Box '"<<bbGetName()<<"' <"<<
1029                     this->bbGetDescriptor()->GetPackage()->GetName()
1030                     <<"::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1031       }
1032     else 
1033       {
1034         bbtkMessage("Help",1,"Black Box <::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1035       }
1036     //    bbtkMessage("Help",1," "<<GetDescription()<<std::endl);
1037     //    bbtkMessage("Help",1," By : "<<GetAuthor()<<std::endl);
1038
1039     std::vector<std::string> iname;
1040     std::vector<std::string> ivalue;
1041     std::vector<std::string> iconn;
1042
1043     InputConnectorMapType::iterator i;
1044     unsigned int namelmax = 0;
1045     unsigned int valuelmax = 0;
1046     //   unsigned int connlmax = 0;
1047     for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i ) 
1048       {
1049         iname.push_back(i->first);
1050         if (iname.back().size()>namelmax) namelmax = iname.back().size();
1051         ivalue.push_back(bbGetInputAsString(i->first));
1052         if (ivalue.back().size()>valuelmax) valuelmax = ivalue.back().size();
1053         std::string s("");
1054         Connection* con = i->second->GetConnection();
1055         if (con!=0){
1056           s = con->GetOriginalBlackBoxFrom()->bbGetName();
1057           s += ".";
1058           s += con->GetOriginalBlackBoxFromOutput();
1059         }  // if con
1060         iconn.push_back(s);
1061       }
1062     OutputConnectorMapType::iterator o;
1063     std::vector<std::string> oname;
1064     std::vector<std::string> ovalue;
1065     std::vector<std::vector<std::string> > oconn;
1066     for ( o = mOutputConnectorMap.begin(); o != mOutputConnectorMap.end(); ++o ) 
1067       {
1068         oname.push_back(o->first);
1069         if (oname.back().size()>namelmax) namelmax = oname.back().size();
1070         ovalue.push_back(bbGetOutputAsString(o->first));
1071         if (ovalue.back().size()>valuelmax) valuelmax = ovalue.back().size();
1072         std::vector<std::string> ss;
1073         const std::vector<Connection*>& con 
1074           = o->second->GetConnectionVector();
1075         std::vector<Connection*>::const_iterator c;
1076         for (c=con.begin();c!=con.end();++c) 
1077           {
1078             std::string s;
1079             s = (*c)->GetOriginalBlackBoxTo()->bbGetName();
1080             s += ".";
1081             s += (*c)->GetOriginalBlackBoxToInput();
1082             ss.push_back(s);
1083         }  // if con
1084         oconn.push_back(ss);
1085       }
1086
1087     if (iname.size()) 
1088       bbtkMessage("Help",1," * Inputs : "<<std::endl);
1089     else 
1090       bbtkMessage("Help",1," * No inputs"<<std::endl);
1091
1092     std::vector<std::string>::iterator i1,i2,i3;
1093     for (i1=iname.begin(),i2=ivalue.begin(),i3=iconn.begin();
1094          i1!=iname.end(),i2!=ivalue.end(),i3!=iconn.end();
1095          ++i1,++i2,++i3)
1096       {
1097         std::string name(*i1);
1098         name += "'";
1099         name.append(1+namelmax-name.size(),' ');
1100         std::string value(*i2);
1101         value += "'";
1102         value.append(1+valuelmax-value.size(),' ');
1103         if (i3->size()) 
1104           bbtkMessage("Help",1,"    '"<<name<<" = '"<<value<<" <-- '"<<*i3<<"'"<<std::endl);
1105         else 
1106           bbtkMessage("Help",1,"    '"<<name<<" = '"<<value<<std::endl);
1107       }
1108
1109     if (oname.size()) 
1110       bbtkMessage("Help",1," * Outputs : "<<std::endl);
1111     else 
1112       bbtkMessage("Help",1," * No outputs"<<std::endl);
1113
1114     std::vector<std::vector<std::string> >::iterator i4;
1115
1116     for (i1=oname.begin(),i2=ovalue.begin(),i4=oconn.begin();
1117          i1!=oname.end(),i2!=ovalue.end(),i4!=oconn.end();
1118          ++i1,++i2,++i4)
1119       {
1120         std::string name(*i1);
1121         name += "'";
1122         name.append(1+namelmax-name.size(),' ');
1123         std::string value(*i2);
1124         value += "'";
1125         value.append(1+valuelmax-value.size(),' ');
1126         if (!(*i4).size())
1127           bbtkMessage("Help",1,"    '"<<name<<" = '"<<value<<std::endl);
1128         else 
1129           {
1130             std::string pref = "    '"+name+" = '"+value;
1131             for (i3=i4->begin();i3!=i4->end();++i3)
1132               {
1133                 bbtkMessage("Help",1,pref<<" --> '"<<*i3<<"'"<<std::endl);
1134                 pref.replace(0,pref.size(),pref.size(),' ');
1135               }
1136           }
1137       }
1138
1139    }
1140   //=========================================================================
1141
1142   static bool bbmgGlobalProcessingExecutionList = false;
1143
1144   //=========================================================================
1145    void BlackBox::bbGlobalProcessExecutionList()
1146    {   
1147      bbtkDebugMessageInc("process",3,
1148                          "=> BlackBox::bbGlobalProcessExecutionList()"
1149                          <<std::endl);    
1150      if (bbmgGlobalProcessingExecutionList) 
1151        {
1152          bbtkDebugMessage("process",3,"BlackBox::bbGlobalProcessExecutionList() reentered !");
1153          return;
1154        }
1155      bbmgGlobalProcessingExecutionList = true;
1156
1157      std::set<BlackBox::WeakPointer>::iterator i; 
1158      while (bbmgExecutionList.size()>0)
1159        {
1160          i = bbmgExecutionList.begin();
1161          BlackBox::WeakPointer p = *i;
1162          bbmgExecutionList.erase(i);
1163          if (p.lock())
1164            {
1165              bbtkDebugMessage("process",4,
1166                               " -> Executing "<<
1167                               p.lock()->bbGetFullName()<<std::endl);
1168              p.lock()->bbExecute(true);
1169            }
1170          else 
1171            {
1172              bbtkGlobalError("Strange error in BlackBox::bbGlobalProcessExecutionList() : Weak bb pointer in bbmgExecutionList is no more valid...");
1173            }
1174        }
1175      
1176      bbmgExecutionList.clear();
1177      bbtkDebugMessageDec("process",3,
1178                          "<= BlackBox::bbGlobalProcessExecutionList()"
1179                          <<std::endl);     
1180      
1181      bbmgGlobalProcessingExecutionList = false;
1182      
1183    }
1184   //=========================================================================
1185
1186     bool BlackBox::bbGlobalGetSomeBoxExecuting()
1187         { 
1188                 return bbmgSomeBoxExecuting; 
1189         }
1190
1191     void BlackBox::bbGlobalSetSomeBoxExecuting(bool b) 
1192         { 
1193                 bbmgSomeBoxExecuting = b; 
1194         }
1195
1196     void BlackBox::bbGlobalSetFreezeExecution(bool b) 
1197         { 
1198                 bbmgFreezeExecution = b;
1199         }
1200
1201     bool BlackBox::bbGlobalGetFreezeExecution() 
1202         { 
1203                 return bbmgFreezeExecution; 
1204         }
1205
1206   void BlackBox::bbGlobalAddToExecutionList( BlackBox::Pointer b )
1207   {  
1208     bbtkDebugMessage("process",3,"* bbGlobalAddToExecutionList("<<b->bbGetFullName()<<")"<<std::endl);
1209     if (bbmgGlobalProcessingExecutionList) 
1210       {
1211         bbtkDebugMessage("process",3,"bbGlobalAddToExecutionList called inside bbGlobalProcessExecutionList !");
1212       }
1213     bbmgExecutionList.insert(b); 
1214   } 
1215
1216
1217    //=========================================================================
1218
1219   //=========================================================================
1220   void BlackBox::Check(bool recursive)
1221   {
1222     bbtkMessage("debug",1,"*** Checking Black Box "<<(void*)this<<" ["<<bbGetFullName()
1223                 <<"] ... OK"<<std::endl);
1224   }
1225   //=========================================================================
1226
1227   void BlackBox::bbUserOnShowWidget(std::string nameInput)
1228   {
1229           bbtk::BlackBoxInputConnector *cc;
1230           cc = this->bbGetInputConnectorMap().find( nameInput.c_str() )->second;
1231           if (cc->GetConnection()!=NULL) 
1232           {
1233                   cc->GetConnection()->GetBlackBoxFrom()->bbUserOnShow();
1234           }
1235   }
1236
1237
1238
1239 }  // EO namespace bbtk
1240
1241 // EOF
1242