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