]> Creatis software - bbtk.git/blob - kernel/src/bbtkBlackBox.cxx
*** empty log message ***
[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 14:46:43 $
6   Version:   $Revision: 1.28 $
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",9,
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         this->bbSetInput(input, from.bbGetInput(input) );
359       }                                                                 
360     // copies the output values
361     const BlackBoxDescriptor::OutputDescriptorMapType& omap 
362       = bbGetDescriptor()->GetOutputDescriptorMap();                   
363     BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o; 
364     for ( o = omap.begin(); o != omap.end(); ++o )
365       {                                                 
366         if (! o->second->GetCopyConstruct() ) continue;
367         std::string output = o->second->GetName();
368         this->bbSetOutput(output, from.bbGetOutput(output) );
369       }
370
371     bbtkDebugDecTab("Kernel",9);
372
373   }
374   //=========================================================================
375
376
377
378   //=========================================================================
379   bool BlackBox::bbCanReact() const 
380   { 
381     return ( bbGlobalGetSomeBoxExecuting() 
382 #ifdef _USE_WXWIDGETS_
383              || Wx::IsSomeWindowAlive() 
384 #endif
385              ); 
386   }
387   //=========================================================================
388
389
390
391   //=========================================================================
392   /// User overloadable destruction method of a black box
393   void BlackBox::bbUserDelete() 
394   {   
395     bbtkDebugMessage("process",5,
396                      "=> BlackBox::bbUserDelete() ["
397                      <<bbGetFullName()<<"]"
398                      <<" : not overloaded; using standard deletion"
399                      <<std::endl);
400     delete this;
401   }
402   //=========================================================================
403
404
405   //=========================================================================
406   BlackBox::BoxProcessModeValue BlackBox::bbGetBoxProcessModeValue() const
407   {
408     const std::string& p = bbmBoxProcessMode;
409     if ( (p == "0") ||
410          (p == "P") || (p == "p") ||
411          (p == "Pipeline") || (p == "pipeline") ) return Pipeline;
412     if ( (p == "1") ||
413          (p == "A") || (p == "a") ||
414          (p == "Always") || (p == "always") ) return Always;
415     if ( (p == "2") ||
416          (p == "R") || (p == "r") ||
417          (p == "Reactive") || (p == "reactive") ) return Reactive;
418     bbtkError(bbGetFullName()<<" : BoxProcessMode value '"<<p
419               <<"' unknown. Possible values : "
420               <<"'0'/'P'/'p'/'Pipeline'/'pipeline' | "
421               <<"'1'/'A'/'a'/'Always'/'always' | "
422               <<"'2'/'R'/'r'/'Reactive'/'reactive'"<<std::endl);
423   }
424   //=========================================================================
425   
426   //=========================================================================
427   bool  BlackBox::bbBoxProcessModeIsReactive() const
428   {
429     return (bbGetBoxProcessModeValue() == Reactive);
430   }
431   //=========================================================================
432
433   //=========================================================================
434   bool  BlackBox::bbBoxProcessModeIsAlways() const
435   {
436     return (bbGetBoxProcessModeValue() == Always);
437   }
438   //=========================================================================
439
440   //=========================================================================
441   ///  Signals that the BlackBox has been modified
442   void BlackBox::bbSetModifiedStatus(BlackBoxInputConnector* c)
443   {
444     bbtkDebugMessage("modified",1,
445                      "==> BlackBox::bbSetModifiedStatus("<<c<<") ["
446                      <<bbGetFullName()<<"]"<<std::endl);
447     
448     if ( (c==bbGetInputConnectorMap().find("WinHide")->second) )
449       //         && (bbCanReact()))
450       {
451         bbtkDebugMessage("modified",2,
452                          "-> Hide triggered by WinHide input change"
453                          <<std::endl);
454         this->bbHideWindow();
455         this->bbSetStatus(MODIFIED); 
456         return;
457       }
458     if ( (c==bbGetInputConnectorMap().find("WinClose")->second) )
459       //         && (bbCanReact()))
460       {
461         bbtkDebugMessage("modified",2,
462                          "-> Close triggered by WinClose input change"
463                          <<std::endl);
464         this->bbHideWindow();
465         this->bbSetStatus(MODIFIED); 
466         return;
467       }
468     
469     if ( ( bbBoxProcessModeIsReactive()  ||
470            (c==bbGetInputConnectorMap().find("BoxExecute")->second))
471          && (bbCanReact() ) )
472       {
473         bbtkDebugMessage("modified",2,
474                          "-> Execution triggered by Reactive mode or BoxExecute input change"<<std::endl);
475         this->bbSetStatus(MODIFIED); 
476         bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
477       }
478     /*
479     else if ( bbGetStatus() == MODIFIED ) //! this->bbIsUptodate()) 
480       { 
481         bbtkDebugMessage("modified",2,"-> Already modified"<<std::endl);
482         return;
483       }
484     */
485     else 
486       {
487         bbtkDebugMessage("modified",2,"-> Status set to modified"<<std::endl);
488         this->bbSetStatus(MODIFIED); 
489       }
490  
491     this->bbSignalOutputModification(false);
492
493     /* 
494   bbtkDebugMessageDec("process",5,
495                         "<= BlackBox::bbSetModifiedStatus("<<c<<") ["
496                         <<bbGetFullName()<<"]"<<std::endl);
497     */
498   }  
499   //=========================================================================
500
501   //=========================================================================  
502   void BlackBox::bbSignalOutputModification(bool reaction)
503   {
504     bbtkDebugMessageInc("process",5,
505                         "=> BlackBox::bbSignalOutputModification() ["
506                         <<bbGetFullName()<<"]"<<std::endl);
507     
508     OutputConnectorMapType::iterator change = bbGetOutputConnectorMap().end();
509     OutputConnectorMapType::iterator i;
510     for ( i  = bbGetOutputConnectorMap().begin(); 
511           i != bbGetOutputConnectorMap().end(); ++i) {
512       /*     if ( i->first == "BoxChange" ) 
513         {
514           change = i;
515           continue;
516         }
517       */
518       i->second->SetModifiedStatus();
519     } 
520     //    if (change != bbGetOutputConnectorMap().end()) 
521     // change->second->SetModifiedStatus();
522
523     if (reaction) bbGlobalProcessExecutionList();
524
525     bbtkDebugMessageDec("process",5,
526                         "<= BlackBox::bbSignalOutputModification() ["
527                         <<bbGetFullName()<<"]"<<std::endl);
528     
529   }  
530   //=========================================================================   
531   //=========================================================================  
532   void BlackBox::bbSignalOutputModification(const std::string& output,
533         bool reaction)
534   {
535     bbtkDebugMessageInc("process",5,
536                         "=> BlackBox::bbSignalOutputModification("
537                         <<output<<") ["
538                         <<bbGetFullName()<<"]"<<std::endl);
539     
540     OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(output);
541     if ( i == bbGetOutputConnectorMap().end() ) 
542         {
543           bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<output<<") : unknown output");
544         }
545     i->second->SetModifiedStatus();
546     // Has to notify the output "BoxChange" also
547     if (output != "BoxChange") 
548       {
549         i = bbGetOutputConnectorMap().find("BoxChange");
550         if ( i != bbGetOutputConnectorMap().end() ) 
551           {
552             i->second->SetModifiedStatus();
553           }
554       }
555   if (reaction) bbGlobalProcessExecutionList();
556
557   bbtkDebugMessageDec("process",5,
558                       "<= BlackBox::bbSignalOutputModification("
559                       <<output<<") ["
560                       <<bbGetFullName()<<"]"<<std::endl);
561
562   }  
563   //=========================================================================   
564   //=========================================================================  
565   void BlackBox::bbSignalOutputModification(const std::vector<std::string>& output,
566         bool reaction)
567   {
568     bbtkDebugMessageInc("process",5,
569                         "=> BlackBox::bbSignalOutputModification(vector of outputs) ["
570                         <<bbGetFullName()<<"]"<<std::endl);
571     OutputConnectorMapType::iterator i;
572     std::vector<std::string>::const_iterator o;
573     for (o=output.begin();o!=output.end();++o) 
574       {
575         // the output "BoxChange" must be signaled **AFTER** all others
576         if (*o == "BoxChange") continue;
577         // Look for the connector
578         i = bbGetOutputConnectorMap().find(*o);
579         if ( i == bbGetOutputConnectorMap().end() ) 
580           {
581             bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<*o<<") : unknown output");
582           }
583         i->second->SetModifiedStatus();
584       }
585     // Has to notify the output "BoxChange" also
586     i = bbGetOutputConnectorMap().find("BoxChange");
587     if ( i != bbGetOutputConnectorMap().end() ) 
588       {
589         i->second->SetModifiedStatus();
590       }
591   if (reaction) bbGlobalProcessExecutionList();
592
593    bbtkDebugMessageDec("process",5,
594                        "<= BlackBox::bbSignalOutputModification(vector of outputs) ["
595                         <<bbGetFullName()<<"]"<<std::endl);
596
597   }  
598   //=========================================================================   
599
600   //=========================================================================
601   /// Updates the BlackBox inputs
602   /// \returns UPTODATE if all inputs are in UPTODATE status after update
603   ///          else MODIFIED 
604   IOStatus BlackBox::bbUpdateInputs(bool excludeParent)
605   {
606     bbtkDebugMessageInc("process",4,
607                         "=> BlackBox::bbUpdateInputs() ["
608                         <<bbGetFullName()<<"]"
609                         <<std::endl);   
610
611     IOStatus s = UPTODATE;
612
613     InputConnectorMapType::iterator i;
614     for ( i = bbGetInputConnectorMap().begin(); 
615           i!= bbGetInputConnectorMap().end(); ++i) 
616       {
617         if (excludeParent && (i->first=="WinParent")) continue;
618         if (i->first=="WinHide") continue;
619         // If input type is Void : no recurse
620         //if (  bbGetDescriptor()->GetInputDescriptor(i->first)->GetTypeInfo() 
621         //      == typeid(Void) ) 
622         //  continue;
623
624         IOStatus t = i->second->BackwardUpdate();
625         if (t==MODIFIED) s = MODIFIED;
626       }
627     
628    bbtkDebugMessageDec("process",4,
629                         "<= BlackBox::bbUpdateInputs() ["
630                         <<bbGetFullName()<<"]"
631                         <<std::endl);   
632
633
634     return s;
635   }
636   //=========================================================================
637
638  
639   //=========================================================================
640   /// Connects the input <name> to the connection c
641   void BlackBox::bbConnectInput( const std::string& name, Connection* c)
642   {
643     bbtkDebugMessage("connection",2,
644                         "==> BlackBox::bbConnectInput(\""
645                         <<name<<"\","<<c->GetFullName()<<") ["
646                         <<bbGetFullName()<<"]"
647                         <<std::endl);       
648
649
650     InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
651     if (i==bbGetInputConnectorMap().end())
652       {
653         bbtkError("no input called '"<<name<<"'");
654       }
655     i->second->SetConnection(c);
656     
657     bbtkDebugMessage("connection",2,
658                         "<== BlackBox::bbConnectInput(\""
659                         <<name<<"\","<<c->GetFullName()<<") ["
660                         <<bbGetFullName()<<"]"
661                         <<std::endl);       
662     //  bbSetModifiedStatus();
663
664   }
665   //=========================================================================
666
667
668   //=========================================================================  
669   /// Connects the output <name> to the connection c
670   void BlackBox::bbConnectOutput( const std::string& name, Connection* c)
671   {
672     bbtkDebugMessage("connection",2,
673                      "==> BlackBox::bbConnectOutput(\""<<name<<"\","
674                      <<c->GetFullName()<<") ["
675                      <<bbGetFullName()<<"]"<<std::endl);       
676     
677     OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
678     if (i==bbGetOutputConnectorMap().end())
679       {
680         bbtkError("no output called '"<<name<<"'");
681       }
682     i->second->SetConnection(c);
683
684     bbtkDebugMessage("connection",2,
685                      "<== BlackBox::bbConnectOutput(\""<<name<<"\","
686                      <<c->GetFullName()<<") ["
687                      <<bbGetFullName()<<"]"<<std::endl);       
688
689   }
690   //=========================================================================
691
692
693   //=========================================================================
694   /// Disconnects the input <name> from the connection c
695   void BlackBox::bbDisconnectInput( const std::string& name, Connection* c)
696   {
697
698     bbtkDebugMessage("connection",2,
699                      "==> BlackBox::bbDisconnectInput(\""<<name
700                      <<"\","<<c->GetFullName()<<") ["
701                      <<bbGetFullName()<<"]"
702                      <<std::endl);      
703
704     if (!c) 
705       {
706
707         bbtkDebugMessage("connection",2,"c==0"<<std::endl);     
708         return;
709       }
710
711     InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
712     if (i==bbGetInputConnectorMap().end())
713       {
714         bbtkError("no input called '"<<name<<"'");
715       }
716     i->second->UnsetConnection(c);
717
718     bbtkDebugMessage("connection",2,
719                      "<== BlackBox::bbDisconnectInput(\""<<name
720                      <<"\","<<c->GetFullName()<<") ["
721                      <<bbGetFullName()<<"]"
722                      <<std::endl);      
723
724   }
725   //=========================================================================
726
727
728   //=========================================================================
729   /// Disconnects the output <name> from the connection c
730   void BlackBox::bbDisconnectOutput( const std::string& name, Connection* c)
731   {
732     bbtkDebugMessage("connection",2,
733                      "==> BlackBox::bbDisconnectOutput(\""<<name
734                      <<"\","<<c->GetFullName()<<") ["
735                      <<bbGetFullName()<<"]"
736                      <<std::endl);       
737     if (!c) 
738       {
739
740         bbtkDebugMessage("connection",2,"c==0"<<std::endl);     
741         return;
742       }
743
744     OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
745     if (i==bbGetOutputConnectorMap().end())
746       {
747         bbtkError("no output called '"<<name<<"'");
748       }
749     i->second->UnsetConnection(c);
750
751     bbtkDebugMessage("connection",2,
752                      "<== BlackBox::bbDisconnectOutput(\""<<name
753                      <<"\","<<c->GetFullName()<<") ["
754                      <<bbGetFullName()<<"]"
755                      <<std::endl);       
756   } 
757   //=========================================================================
758  
759
760   //=========================================================================
761   /// Virtual
762   void BlackBox::bbWriteDotInputOutputName(FILE *ff,bool inputoutput,int detail, int level)
763   {
764     fprintf(ff,"%s%p",bbGetTypeName().c_str(),this);
765   }
766   //=========================================================================
767
768
769   //=========================================================================
770   std::string BlackBox::bbGetOutputAsString( const std::string &output ) 
771   {
772     std::string v;
773     // Looks for the adaptor
774     if (bbGetOutputType(output).name() != typeid(std::string).name() ) 
775       {
776         // Look for factory 
777         Package::Pointer p = bbGetDescriptor()->GetPackage();
778         if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
779           {
780             Factory::Pointer f = p->GetFactorySet().begin()->lock();
781             BlackBox::Pointer a;
782             try
783               {
784                 a = f->NewAdaptor(  
785                                   bbGetOutputType(output),
786                                   typeid(std::string),
787                                   "");
788               } catch (bbtk::Exception e) 
789               {
790               }
791             if (a){
792               //                        bbUpdate();
793               a->bbSetInput("In",bbGetOutput(output));
794               a->bbExecute();
795               v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
796             } else {
797               v="? (no adaptor found)";
798             }
799           }
800         else 
801           {
802             v="? (no factory found)";
803           }
804       } 
805     else 
806       {
807         //         bbUpdate();
808         v = bbGetOutput(output).unsafe_get<std::string>() ;
809       }
810     return v;
811   }
812   //=========================================================================
813
814   //=========================================================================
815   std::string BlackBox::bbGetInputAsString( const std::string &input ) 
816   {
817     std::string v;
818     // Looks for the adaptor
819     if (bbGetInputType(input) != typeid(std::string)) 
820       {
821         // Look for factory 
822         Package::Pointer p = bbGetDescriptor()->GetPackage();
823         if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
824           {
825             Factory::Pointer f = p->GetFactorySet().begin()->lock();
826             BlackBox::Pointer a;
827             try
828               {
829                 a = f->NewAdaptor(  
830                                bbGetInputType(input),
831                                typeid(std::string),
832                                "");
833               }catch (bbtk::Exception e) 
834               {
835               }
836             if (a)
837               {
838                 //                      bbUpdate();
839                 a->bbSetInput("In",bbGetInput(input));
840                 a->bbExecute();
841                 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
842               } 
843             else 
844               {
845                 v="? (no adaptor found)";
846               }
847           } 
848         else 
849           {
850             v="? (no factory found)";
851           }
852       }
853     else 
854       {
855         v = bbGetInput(input).unsafe_get<std::string>() ;
856       }
857     return v;
858   }
859   //=======================================================================
860
861   //=======================================================================
862   // Replaces substrings "<" by "["
863   void SubsBrackets ( std::string& s )
864   {
865     //   std::cout << "BEFORE=["<<s<<"]"<<std::endl;
866     std::string ss("<");
867     std::string::size_type pos = 0;
868     pos = s.find(ss,0);
869     char* cr = "[";
870     while ( pos != std::string::npos )
871       {
872         //      std::cout << "*** find one "<<std::endl;
873         s.replace(pos,1,cr,1);
874         pos = s.find(ss, pos);
875       } 
876     ss = ">";
877     pos = 0;
878     pos = s.find(ss,0);
879     cr = "]";
880     while ( pos != std::string::npos )
881       {
882         //      std::cout << "*** find one "<<std::endl;
883         s.replace(pos,1,cr,1);
884         pos = s.find(ss, pos);
885       } 
886     ss = ",";
887     pos = 0;
888     pos = s.find(ss,0);
889     cr = "-";
890     while ( pos != std::string::npos )
891       {
892         //      std::cout << "*** find one "<<std::endl;
893         s.replace(pos,1,cr,1);
894         pos = s.find(ss, pos);
895       }     //    std::cout << "AFTER=["<<s<<"]"<<std::endl;
896   }
897   //=======================================================================
898
899   //=========================================================================
900   /// Write Graphviz-dot description in file
901   void BlackBox::bbWriteDotFileBlackBox(FILE *ff,
902                                         BlackBox::Pointer parentblackbox, 
903                                         int detail, int level,
904                                         bool instanceOrtype,
905                                         bool relative_link )
906
907   { 
908     InputConnectorMapType::iterator i;
909     // label
910     std::string labelStr;
911     std::string valueStr("");
912
913         if (detail==0) {
914                 labelStr = bbGetName() ; 
915 //EED 18 Fev 2008
916                 labelStr = labelStr + "\\n[" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "]";
917         } else {
918                 labelStr = bbGetName();
919                 labelStr = labelStr + "   [" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "]  ";
920     }
921
922     SubsBrackets(labelStr);
923     if (detail==1)
924       {
925         labelStr = labelStr + " | {{ "; 
926         std::string tempStrTypeName;
927         bool tmp; 
928         tmp=false;
929         for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i ) 
930           {
931             if (tmp==true)
932               {
933                 labelStr=labelStr+" | ";
934               }
935             tmp=true;
936             if (instanceOrtype==true)
937               {
938                 valueStr = this->bbGetInputAsString(i->first) + " = ";
939               } 
940             const BlackBoxInputDescriptor* id = bbGetDescriptor()->GetInputDescriptor(i->first);
941             tempStrTypeName=id->GetTypeName();
942             SubsBrackets(tempStrTypeName);
943             std::string Name(i->first);
944             SubsBrackets(Name);
945             labelStr=labelStr + "<"+i->first.c_str()+"> "  + valueStr +  Name.c_str() + "  [" + tempStrTypeName.c_str() + "]";
946           }
947         labelStr=labelStr+ " } | {";
948         tmp = false;
949         OutputConnectorMapType::iterator ii;
950         for ( ii = mOutputConnectorMap.begin(); ii != mOutputConnectorMap.end(); ++ii ) 
951         {
952            if (tmp==true)
953            {
954                    labelStr=labelStr+" | ";
955            }
956            tmp = true;
957            if (instanceOrtype==true)
958            {
959                    valueStr = this->bbGetOutputAsString(ii->first) + " = ";
960            }
961            const BlackBoxOutputDescriptor* id = bbGetDescriptor()->GetOutputDescriptor(ii->first); 
962            tempStrTypeName=id->GetTypeName();
963            SubsBrackets(tempStrTypeName);
964             std::string Name(ii->first);
965             SubsBrackets(Name);
966            labelStr=labelStr+"<"+ii->first.c_str()+"> " + valueStr + Name.c_str() + "  ["+tempStrTypeName+"]";
967         }
968         labelStr = labelStr+ "      } }" ;
969 } // detail
970
971     fprintf(ff,"  " );
972     bbWriteDotInputOutputName(ff,true,detail,level);
973     std::string tmp ( bbGetTypeName() );
974     SubsBrackets(tmp);
975     std::string url;
976     if (relative_link) 
977       url = this->bbGetDescriptor()->GetPackage()->GetDocRelativeURL() + "#" + tmp;
978     else 
979       url = this->bbGetDescriptor()->GetPackage()->GetDocURL() + "#" + tmp;
980   
981     fprintf( ff , " [shape=record, URL=\"%s\",label=\"%s\"]%s\n",url.c_str(),labelStr.c_str(),";" );
982     //    std::cout  << labelStr << std::endl;
983
984     // Relation Input
985     if (GetThisPointer<BlackBox>()!=parentblackbox){
986       for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i ) 
987         {
988           if (i->second)
989             {
990               Connection* con = i->second->GetConnection();
991               if (con!=NULL){
992                 BlackBox::Pointer a=con->GetOriginalBlackBoxFrom();
993                 BlackBox::Pointer b=con->GetOriginalBlackBoxTo();
994                 fprintf(ff,"  ");
995                 a->bbWriteDotInputOutputName(ff,false,detail,level);
996                 if (detail==1)
997                   {
998                     fprintf(ff,":%s",con->GetOriginalBlackBoxFromOutput().c_str());
999                   }
1000                 fprintf(ff,"->");
1001                 b->bbWriteDotInputOutputName(ff,true,detail,level);
1002                 if (detail==1)
1003                   {
1004                     fprintf(ff,":%s",con->GetOriginalBlackBoxToInput().c_str());
1005                   }
1006                 fprintf(ff,"%s\n",";");
1007               }  // if con
1008             } // if second
1009         } // for
1010     } // if parentblackbox
1011   }
1012   //=========================================================================
1013
1014
1015
1016
1017   //=========================================================================
1018   void BlackBox::bbShowRelations(BlackBox::Pointer parentblackbox, 
1019                                  int detail, int level
1020                                  /*,Factory *factory*/ )
1021   {
1022      
1023     if (this->bbGetDescriptor()->GetPackage()) 
1024       {
1025         bbtkMessage("Help",1,"Black Box '"<<bbGetName()<<"' <"<<
1026                     this->bbGetDescriptor()->GetPackage()->GetName()
1027                     <<"::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1028       }
1029     else 
1030       {
1031         bbtkMessage("Help",1,"Black Box <::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1032       }
1033     //    bbtkMessage("Help",1," "<<GetDescription()<<std::endl);
1034     //    bbtkMessage("Help",1," By : "<<GetAuthor()<<std::endl);
1035
1036     std::vector<std::string> iname;
1037     std::vector<std::string> ivalue;
1038     std::vector<std::string> iconn;
1039
1040     InputConnectorMapType::iterator i;
1041     unsigned int namelmax = 0;
1042     unsigned int valuelmax = 0;
1043     //   unsigned int connlmax = 0;
1044     for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i ) 
1045       {
1046         iname.push_back(i->first);
1047         if (iname.back().size()>namelmax) namelmax = iname.back().size();
1048         ivalue.push_back(bbGetInputAsString(i->first));
1049         if (ivalue.back().size()>valuelmax) valuelmax = ivalue.back().size();
1050         std::string s("");
1051         Connection* con = i->second->GetConnection();
1052         if (con!=0){
1053           s = con->GetOriginalBlackBoxFrom()->bbGetName();
1054           s += ".";
1055           s += con->GetOriginalBlackBoxFromOutput();
1056         }  // if con
1057         iconn.push_back(s);
1058       }
1059     OutputConnectorMapType::iterator o;
1060     std::vector<std::string> oname;
1061     std::vector<std::string> ovalue;
1062     std::vector<std::vector<std::string> > oconn;
1063     for ( o = mOutputConnectorMap.begin(); o != mOutputConnectorMap.end(); ++o ) 
1064       {
1065         oname.push_back(o->first);
1066         if (oname.back().size()>namelmax) namelmax = oname.back().size();
1067         ovalue.push_back(bbGetOutputAsString(o->first));
1068         if (ovalue.back().size()>valuelmax) valuelmax = ovalue.back().size();
1069         std::vector<std::string> ss;
1070         const std::vector<Connection*>& con 
1071           = o->second->GetConnectionVector();
1072         std::vector<Connection*>::const_iterator c;
1073         for (c=con.begin();c!=con.end();++c) 
1074           {
1075             std::string s;
1076             s = (*c)->GetOriginalBlackBoxTo()->bbGetName();
1077             s += ".";
1078             s += (*c)->GetOriginalBlackBoxToInput();
1079             ss.push_back(s);
1080         }  // if con
1081         oconn.push_back(ss);
1082       }
1083
1084     if (iname.size()) 
1085       bbtkMessage("Help",1," * Inputs : "<<std::endl);
1086     else 
1087       bbtkMessage("Help",1," * No inputs"<<std::endl);
1088
1089     std::vector<std::string>::iterator i1,i2,i3;
1090     for (i1=iname.begin(),i2=ivalue.begin(),i3=iconn.begin();
1091          i1!=iname.end(),i2!=ivalue.end(),i3!=iconn.end();
1092          ++i1,++i2,++i3)
1093       {
1094         std::string name(*i1);
1095         name += "'";
1096         name.append(1+namelmax-name.size(),' ');
1097         std::string value(*i2);
1098         value += "'";
1099         value.append(1+valuelmax-value.size(),' ');
1100         if (i3->size()) 
1101           bbtkMessage("Help",1,"    '"<<name<<" = '"<<value<<" <-- '"<<*i3<<"'"<<std::endl);
1102         else 
1103           bbtkMessage("Help",1,"    '"<<name<<" = '"<<value<<std::endl);
1104       }
1105
1106     if (oname.size()) 
1107       bbtkMessage("Help",1," * Outputs : "<<std::endl);
1108     else 
1109       bbtkMessage("Help",1," * No outputs"<<std::endl);
1110
1111     std::vector<std::vector<std::string> >::iterator i4;
1112
1113     for (i1=oname.begin(),i2=ovalue.begin(),i4=oconn.begin();
1114          i1!=oname.end(),i2!=ovalue.end(),i4!=oconn.end();
1115          ++i1,++i2,++i4)
1116       {
1117         std::string name(*i1);
1118         name += "'";
1119         name.append(1+namelmax-name.size(),' ');
1120         std::string value(*i2);
1121         value += "'";
1122         value.append(1+valuelmax-value.size(),' ');
1123         if (!(*i4).size())
1124           bbtkMessage("Help",1,"    '"<<name<<" = '"<<value<<std::endl);
1125         else 
1126           {
1127             std::string pref = "    '"+name+" = '"+value;
1128             for (i3=i4->begin();i3!=i4->end();++i3)
1129               {
1130                 bbtkMessage("Help",1,pref<<" --> '"<<*i3<<"'"<<std::endl);
1131                 pref.replace(0,pref.size(),pref.size(),' ');
1132               }
1133           }
1134       }
1135
1136    }
1137   //=========================================================================
1138
1139   static bool bbmgGlobalProcessingExecutionList = false;
1140
1141   //=========================================================================
1142    void BlackBox::bbGlobalProcessExecutionList()
1143    {   
1144      bbtkDebugMessageInc("process",3,
1145                          "=> BlackBox::bbGlobalProcessExecutionList()"
1146                          <<std::endl);    
1147      if (bbmgGlobalProcessingExecutionList) 
1148        {
1149          bbtkDebugMessage("process",3,"BlackBox::bbGlobalProcessExecutionList() reentered !");
1150          return;
1151        }
1152      bbmgGlobalProcessingExecutionList = true;
1153
1154      std::set<BlackBox::WeakPointer>::iterator i; 
1155      while (bbmgExecutionList.size()>0)
1156        {
1157          i = bbmgExecutionList.begin();
1158          BlackBox::WeakPointer p = *i;
1159          bbmgExecutionList.erase(i);
1160          if (p.lock())
1161            {
1162              bbtkDebugMessage("process",4,
1163                               " -> Executing "<<
1164                               p.lock()->bbGetFullName()<<std::endl);
1165              p.lock()->bbExecute(true);
1166            }
1167          else 
1168            {
1169              bbtkGlobalError("Strange error in BlackBox::bbGlobalProcessExecutionList() : Weak bb pointer in bbmgExecutionList is no more valid...");
1170            }
1171        }
1172      
1173      bbmgExecutionList.clear();
1174      bbtkDebugMessageDec("process",3,
1175                          "<= BlackBox::bbGlobalProcessExecutionList()"
1176                          <<std::endl);     
1177      
1178      bbmgGlobalProcessingExecutionList = false;
1179      
1180    }
1181   //=========================================================================
1182
1183     bool BlackBox::bbGlobalGetSomeBoxExecuting()
1184         { 
1185                 return bbmgSomeBoxExecuting; 
1186         }
1187
1188     void BlackBox::bbGlobalSetSomeBoxExecuting(bool b) 
1189         { 
1190                 bbmgSomeBoxExecuting = b; 
1191         }
1192
1193     void BlackBox::bbGlobalSetFreezeExecution(bool b) 
1194         { 
1195                 bbmgFreezeExecution = b;
1196         }
1197
1198     bool BlackBox::bbGlobalGetFreezeExecution() 
1199         { 
1200                 return bbmgFreezeExecution; 
1201         }
1202
1203   void BlackBox::bbGlobalAddToExecutionList( BlackBox::Pointer b )
1204   {  
1205     bbtkDebugMessage("process",3,"* bbGlobalAddToExecutionList("<<b->bbGetFullName()<<")"<<std::endl);
1206     if (bbmgGlobalProcessingExecutionList) 
1207       {
1208         bbtkDebugMessage("process",3,"bbGlobalAddToExecutionList called inside bbGlobalProcessExecutionList !");
1209       }
1210     bbmgExecutionList.insert(b); 
1211   } 
1212
1213
1214    //=========================================================================
1215
1216   //=========================================================================
1217   void BlackBox::Check(bool recursive)
1218   {
1219     bbtkMessage("debug",1,"*** Checking Black Box "<<(void*)this<<" ["<<bbGetFullName()
1220                 <<"] ... OK"<<std::endl);
1221   }
1222   //=========================================================================
1223
1224   void BlackBox::bbUserOnShowWidget(std::string nameInput)
1225   {
1226           bbtk::BlackBoxInputConnector *cc;
1227           cc = this->bbGetInputConnectorMap().find( nameInput.c_str() )->second;
1228           if (cc->GetConnection()!=NULL) 
1229           {
1230                   cc->GetConnection()->GetBlackBoxFrom()->bbUserOnShow();
1231           }
1232   }
1233
1234
1235
1236 }  // EO namespace bbtk
1237
1238 // EOF
1239