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