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