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