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