]> Creatis software - bbtk.git/blob - kernel/src/bbtkComplexBlackBox.cxx
c06e715270299414e754be1022d8947c1075cc8b
[bbtk.git] / kernel / src / bbtkComplexBlackBox.cxx
1 /*=========================================================================
2                                                                                 
3 Program:   bbtk
4 Module:    $RCSfile: bbtkComplexBlackBox.cxx,v $
5 Language:  C++
6 Date:      $Date: 2008/04/24 10:24:58 $
7 Version:   $Revision: 1.18 $
8                                                                                 
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details.
12                                                                                 
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE.  See the above copyright notices for more information.
16                                                                                
17 =========================================================================*/
18
19
20 /**
21  *  \file 
22  *  \brief class bbtk::ComplexBlackBox : user defined complex black boxes
23  */
24 #include "bbtkComplexBlackBox.h"
25 #include "bbtkBlackBoxDescriptor.h"
26 #include "bbtkFactory.h"
27 #include "bbtkConfigurationFile.h"
28
29 namespace bbtk
30 {
31
32   //==========================================================================
33   /// Creates a new complex black box
34   ComplexBlackBox::Pointer ComplexBlackBox::New(const std::string& name,
35                                                 ComplexBlackBoxDescriptor::Pointer desc)
36   {
37     bbtkDebugMessage("object",1,"##> ComplexBlackBox::New('"<<name<<"','"<<
38                      desc->GetTypeName()<<"')" <<bbtkendl);
39     ComplexBlackBox::Pointer p = 
40       MakeBlackBoxPointer(new ComplexBlackBox(name,desc));
41     bbtkDebugMessage("object",2,"<## ComplexBlackBox::New('"<<name<<"','"<<
42                      desc->GetTypeName()<<"')" <<bbtkendl);
43     return p;
44   }
45   //==========================================================================
46
47   //=======================================================================
48   /// Usefull constructor 
49   ComplexBlackBox::ComplexBlackBox(const std::string &name,
50                                    ComplexBlackBoxDescriptor::Pointer desc)
51     : 
52     BlackBox(name),
53     mLockedDescriptor(desc),
54     mDescriptor(desc)
55   {
56     bbtkDebugMessage("object",3,
57                      "##> ComplexBlackBox::ComplexBlackBox(\""
58                      <<name<<"\")"<<std::endl);
59     bbAllocateConnectors();
60     bbtkDebugMessage("object",3,
61                      "<## ComplexBlackBox::ComplexBlackBox(\""
62                      <<name<<"\")"<<std::endl);
63   }
64   //=======================================================================
65
66   //=======================================================================
67   /// Constructor from an existing box (copy) with a new name 
68   ComplexBlackBox::ComplexBlackBox(ComplexBlackBox& from, 
69                                    const std::string &name)
70     : BlackBox(from,name),
71       // The locked descriptor is copied from the unlocked one 
72       // to make the box a non-prototype !!
73       mLockedDescriptor(from.mDescriptor),
74       mDescriptor(from.mDescriptor),
75      mExecutionList(from.mExecutionList)    
76   {
77     bbtkDebugMessage("object",3,
78                         "##> ComplexBlackBox::ComplexBlackBox(\""
79                         <<from.bbGetName()<<"\",\""
80                         <<name<<"\")"<<std::endl);
81     bbtkDebugMessage("object",4,"  * Cloning Black Boxes"<<std::endl);
82
83     // We have to make the shared_ptr on this because it is used 
84     // in bbUnsafeAddBlackBox !
85     MakePointer(this,true);
86
87     BlackBoxMapType::const_iterator i;
88     for ( i = from.mBlackBoxMap.begin(); i != from.mBlackBoxMap.end(); ++i ) 
89       {
90         bbtkDebugMessageInc("object",5,"    * Cloning \""<<i->first<<"\""<<std::endl);
91         BlackBox::Pointer B = i->second->bbClone(i->second->bbGetName());
92         bbUnsafeAddBlackBox(B);
93       }
94    
95     bbtkDebugMessage("object",4,"  * Cloning Connections"<<std::endl);
96     ConnectionListType::const_iterator j;
97     for ( j = from.mConnectionList.begin(); j != from.mConnectionList.end(); ++j ) 
98       {
99         bbtkDebugMessage("object",5,"    * Cloning \""<<
100                          (*j)->GetFullName()<<"\""<<std::endl);
101
102         BlackBox::Pointer bbfrom = bbGetBlackBox( (*j)->GetOriginalBlackBoxFrom()->bbGetName() );
103         BlackBox::Pointer bbto = bbGetBlackBox( (*j)->GetOriginalBlackBoxTo()->bbGetName() );
104
105         Connection::Pointer c = mDescriptor.lock()->GetFactory()-> 
106           NewConnection( bbfrom, 
107                          (*j)->GetOriginalBlackBoxFromOutput(), 
108                          bbto, 
109                          (*j)->GetOriginalBlackBoxToInput() );
110         
111         //c->Check();
112         bbAddConnection(c);
113
114       }
115
116     bbAllocateConnectors();
117     bbtkDebugMessage("object",3,
118                         "<## ComplexBlackBox::ComplexBlackBox(\""
119                         <<from.bbGetName()<<"\",\""
120                         <<name<<"\")"<<std::endl);
121   }
122   //=======================================================================
123
124   //======================================================================= 
125   ///  Destructor
126   ComplexBlackBox::~ComplexBlackBox()
127   {
128     bbtkDebugMessage("object",3,
129                      "==> ComplexBlackBox::~ComplexBlackBox() ["
130                      <<bbGetName()<<"]"<<std::endl);
131
132     bbtkDebugMessage("object",4,
133                      " -> Releasing connections"<<std::endl);
134     mConnectionList.clear();
135     bbtkDebugMessage("object",4,
136                      " -> Releasing boxes"<<std::endl);
137     mBlackBoxMap.clear();
138
139     //    Clear();
140     this->bbDesallocateConnectors();
141
142     bbtkDebugMessage("object",3,
143                      "<== ComplexBlackBox::~ComplexBlackBox() ["
144                      <<bbGetName()<<"]"<<std::endl);
145   } 
146   //=======================================================================
147  
148
149   //=========================================================================
150   /// Allocates the i/o connectors of the black box
151   void ComplexBlackBox::bbAllocateConnectors()
152   {  
153     bbtkDebugMessageInc("Kernel",8,
154                         "ComplexBlackBox::bbAllocateConnectors() ["
155                         <<bbGetFullName()<<"]"
156                         <<std::endl);   
157     
158     // Input connectors
159     const BlackBoxDescriptor::InputDescriptorMapType& imap 
160       = bbGetDescriptor()->GetInputDescriptorMap(); 
161     BlackBoxDescriptor::InputDescriptorMapType::const_iterator i;       
162     for ( i = imap.begin(); i != imap.end(); ++i )                      
163       {                                                                 
164         bbtkDebugMessage("Kernel",8,"* Allocate \""<<i->first<<"\""<<std::endl);
165         // Redirect the connector to the internal box connector
166         // Cast the BBInputDescriptor into a ComplexBBInputDescriptor
167         ComplexBlackBoxInputDescriptor* d = 
168           (ComplexBlackBoxInputDescriptor*)i->second;
169         // Get the internal box connector
170         BlackBoxInputConnector* c = 
171           bbUnsafeGetBlackBox ( d->GetTarget() )
172           ->bbGetInputConnectorMap()[ d->GetInput() ];
173         
174         bbGetInputConnectorMap()[i->second->GetName()] = c;
175       }                                                                 
176
177     // Output connectors
178     const BlackBoxDescriptor::OutputDescriptorMapType& omap 
179       = bbGetDescriptor()->GetOutputDescriptorMap();                   
180     BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o; 
181     for ( o = omap.begin(); o != omap.end(); ++o )
182       {                                                 
183         bbtkDebugMessage("Kernel",8,"* Allocate \""<<o->first<<"\""<<std::endl);
184         // Redirect the connector to the internal box connector
185         // Cast the BBOutputDescriptor into a ComplexBBOutputDescriptor
186         ComplexBlackBoxOutputDescriptor* d = 
187           (ComplexBlackBoxOutputDescriptor*)o->second;
188         // Get the internal box connector
189         BlackBoxOutputConnector* c = 
190           bbUnsafeGetBlackBox ( d->GetTarget() )
191           ->bbGetOutputConnectorMap()[ d->GetOutput() ];
192
193         bbGetOutputConnectorMap()[o->second->GetName()] = c;
194       }
195     
196     bbtkDebugDecTab("Kernel",8);  
197   }
198   //=========================================================================
199
200
201   //=========================================================================
202   /// Desallocates the i/o connectors of the black box
203   void ComplexBlackBox::bbDesallocateConnectors()
204   {
205     bbtkDebugMessageInc("Kernel",8,
206                         "ComplexBlackBox::DesallocateConnectors()"
207                         <<std::endl);                                   
208
209     // The connectors have not been allocated by the complex box 
210     // but by the internal boxes. Hence **DO NOT** desallocate !
211     // just clear the maps to avoid that 
212     // BlackBox::bbDesallocateConnectors delete the connectors
213     bbGetInputConnectorMap().clear();
214     bbGetOutputConnectorMap().clear();
215
216     bbtkDebugDecTab("Kernel",8);  
217
218   }
219   //=========================================================================
220
221   //=======================================================================
222   BlackBox::Pointer ComplexBlackBox::bbClone(const std::string& name)
223   {
224     bbtkDebugMessageInc("Kernel",9,
225                         "ComplexBlackBox::bbClone(\""<<name<<"\") ["
226                         <<bbGetFullName()<<"]"<<std::endl);
227     
228     ComplexBlackBox* CBB = new ComplexBlackBox(*this,name);
229     return MakeBlackBoxPointer(CBB);
230   }
231   //=======================================================================
232
233   //=======================================================================
234   /// Main processing method of the box.
235   /// Executes the box so that its outputs are up-to-date on exit
236   void ComplexBlackBox::bbExecute(bool force)
237   {
238     bbtkDebugMessageInc("process",2,
239                         "=> ComplexBlackBox::bbExecute() ["
240                         <<bbGetFullName()<<"]"<<std::endl);
241
242
243     Wx::BeginBusyCursor();
244     
245     if (mExecutionList.size() != 0) 
246       {
247         
248         std::vector<std::string>::const_iterator i;
249         for (i=mExecutionList.begin(); 
250              i!=mExecutionList.end();
251              ++i) 
252           {
253             bbtkDebugMessage("process",3," -> Executing '"<<*i<<"'"<<std::endl);
254             mBlackBoxMap[*i]->bbExecute(force);
255           }
256       }
257     else 
258       {
259         std::map<std::string, BlackBox::Pointer>::iterator i;
260         for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i)
261           {
262             i->second->bbExecute(force);
263           }
264       } 
265
266     Wx::EndBusyCursor();
267     
268     
269   }
270   //==================================================================
271
272   //==================================================================
273   void ComplexBlackBox::bbSetModifiedStatus(BlackBoxInputConnector* c)
274   {
275     bbtkDebugMessage("modified",1,
276                         "==> ComplexBlackBox::bbSetModifiedStatus("
277                      <<c<<") ["<<bbGetFullName()<<"]"<<std::endl);
278
279     c->GetBlackBox()->bbSetModifiedStatus(c);
280
281     /*
282     bbtkDebugMessage("modified",1,
283                      "<== ComplexBlackBox::bbSetModifiedStatus("
284                      <<c<<") ["<<bbGetFullName()<<"]"<<std::endl);
285     */
286   }
287   //==================================================================
288
289   //==================================================================
290   void ComplexBlackBox::bbAddToExecutionList( const std::string& name )
291   {
292         bbtkDebugMessageInc("Kernel",9,
293                         "ComplexBlackBox::bbAddToExecutionList(\""
294                         <<name<<"\") ["
295                         <<bbGetFullName()<<"]"<<std::endl);
296
297         mExecutionList.push_back( name );
298
299      bbtkDebugDecTab("Kernel",9);   
300
301   }
302   //==================================================================
303
304   //==================================================================
305   IOStatus ComplexBlackBox::bbBackwardUpdate(Connection::Pointer caller)
306   {
307     bbtkDebugMessageInc("process",3,
308                         "==> ComplexBlackBox::bbBackwardUpdate("
309                         <<(caller?caller->GetFullName():"0")<<") ["
310                         <<bbGetFullName()<<"]"<<std::endl);
311     //    bbtkInternalError("ComplexBlackBox::bbBackwardUpdate should never be called !");
312     
313     if (caller==0)
314       {
315         bbtkInternalError("ComplexBlackBox::bbBackwardUpdate called with caller=0");
316       }
317
318     /*
319     std::cout << "CBB BUP : "<<caller->GetBlackBoxFrom()->bbGetFullName()
320               <<"."<<caller->GetBlackBoxFromOutput()<<"----"
321               <<caller->GetOriginalBlackBoxFrom()->bbGetFullName()
322               <<"."<<caller->GetOriginalBlackBoxFromOutput()<<std::endl;
323     */
324       
325
326
327     IOStatus s = UPTODATE;
328     const BlackBoxDescriptor::OutputDescriptorMapType& omap 
329       = bbGetDescriptor()->GetOutputDescriptorMap(); 
330     BlackBoxDescriptor::OutputDescriptorMapType::const_iterator i 
331       = omap.find(caller->GetBlackBoxFromOutput());
332     if (i!=omap.end())
333       { 
334         // Cast the BBOutputDescriptor into a ComplexBBOutputDescriptor
335         ComplexBlackBoxOutputDescriptor* d = 
336           (ComplexBlackBoxOutputDescriptor*)i->second;
337         // Get the internal box 
338         BlackBox::Pointer b = bbUnsafeGetBlackBox ( d->GetTarget() );
339         // Calls BackwardUpdate on it
340         bbtkDebugMessageInc("process",4,"Internal box connected to output : "<<d->GetTarget()<<std::endl);
341         // Because internal box can also be a complex box we have to 
342         // temporarily change the connection BlackBoxFromOutput to the 
343         // mapped one
344         
345         //      std::string oldout = caller->GetBlackBoxFromOutput();
346         //      std::cout << "oldout = "<<oldout<<std::endl;
347         //      std::cout << "tmpout = "<<d->GetOutput()<<std::endl;
348         //      caller->SetBlackBoxFromOutput(d->GetOutput());
349         //
350         //Connection newcaller(*caller);
351         //newcaller.SetBlackBoxFromOutput(d->GetOutput());
352         //IOStatus s1 = b->bbBackwardUpdate(&newcaller);
353         IOStatus s1 = b->bbBackwardUpdate(caller);
354         //newcaller.Clear();
355         // restore old output
356         //      caller->SetBlackBoxFromOutput(oldout);
357
358         // ??? STATUS OF CBBs ???
359         // ??? Here it is only the final status of the boxes connected to the output 
360         if (s1==MODIFIED) s=MODIFIED;
361       }
362     else 
363       {
364         bbtkError("Connection '"<<caller->GetFullName()<<"' does not point to a valid output of the complex box !");
365       }
366
367     return s;
368     
369   }
370   //==================================================================
371
372
373   //==================================================================
374   Data ComplexBlackBox::bbGetOutput( const std::string &name )
375   {
376     bbtkDebugMessageInc("Data",7,
377                         "ComplexBlackBox::bbGetOutput(\""<<name<<"\") ["
378                         <<bbGetFullName()<<"]"<<std::endl);
379
380     ComplexBlackBoxOutputDescriptor* d = 
381       (ComplexBlackBoxOutputDescriptor*)
382       bbGetDescriptor()->GetOutputDescriptor(name);
383     
384     Data p = bbGetBlackBox(d->GetTarget())->bbGetOutput(d->GetOutput());
385
386
387     bbtkDebugDecTab("Data",7);
388     return p;
389   }
390   //==================================================================
391
392   //==================================================================
393   ///  Gets the input Data of a given name
394   Data ComplexBlackBox::bbGetInput( const std::string &name ) 
395   {
396     bbtkDebugMessageInc("Data",7,
397                         "ComplexBlackBox::bbGetInput(\""<<name<<"\") ["
398                         <<bbGetFullName()<<"]"<<std::endl);  
399
400     ComplexBlackBoxInputDescriptor* d = 
401       (ComplexBlackBoxInputDescriptor*)
402       bbGetDescriptor()->GetInputDescriptor(name);
403
404     Data p = bbGetBlackBox(d->GetTarget())->bbGetInput(d->GetInput());
405
406     bbtkDebugDecTab("Data",7);
407     return p;
408   }
409   //==================================================================
410
411   //==================================================================
412   ///  Sets the data of the output called <name>
413   void ComplexBlackBox::bbSetOutput( const std::string &name, Data data)
414   {
415     bbtkDebugMessageInc("Data",7,
416                         "ComplexBlackBox::bbSetOutput(\""<<name<<"\",data) ["
417                         <<bbGetFullName()<<"]"<<std::endl); 
418
419     ComplexBlackBoxOutputDescriptor* d = 
420       (ComplexBlackBoxOutputDescriptor*)
421       bbGetDescriptor()->GetOutputDescriptor(name);
422     
423     bbGetBlackBox(d->GetTarget())->bbSetOutput(d->GetOutput(),data);
424
425     bbtkDebugDecTab("Data",7);
426   }
427   //==================================================================
428   
429   //==================================================================
430   ///  Sets the data of the input called <name>
431   void ComplexBlackBox::bbSetInput( const std::string &name, Data data,
432                                     bool setModified)
433   {
434     bbtkDebugMessageInc("Data",7,
435                         "ComplexBlackBox::bbSetInput(\""<<name<<"\",data) ["
436                         <<bbGetFullName()<<"]"<<std::endl);  
437
438     ComplexBlackBoxInputDescriptor* d = (ComplexBlackBoxInputDescriptor*)
439       bbGetDescriptor()->GetInputDescriptor(name);
440
441     bbGetBlackBox(d->GetTarget())->bbSetInput(d->GetInput(),data,setModified);
442
443     bbtkDebugDecTab("Data",7);
444   }
445   //==================================================================
446
447  
448   //==================================================================
449   ///  Sets the data of the input called <name>
450   void ComplexBlackBox::bbBruteForceSetInputPointer( const std::string &name, 
451                                                      void* data,
452                                                      bool setModified)
453   {
454     bbtkDebugMessageInc("Data",7,
455                         "ComplexBlackBox::bbBruteForceSetInputPointer('"
456                         <<name<<"',"<<data<<") ["
457                         <<bbGetFullName()<<"]"<<std::endl);  
458
459     ComplexBlackBoxInputDescriptor* d = (ComplexBlackBoxInputDescriptor*)
460       bbGetDescriptor()->GetInputDescriptor(name);
461
462     bbGetBlackBox(d->GetTarget())->bbBruteForceSetInputPointer(d->GetInput(),
463                                                                data,
464                                                                setModified);
465
466     bbtkDebugDecTab("Data",7);
467   }
468   //==================================================================
469
470   //=========================================================================
471   /// Connects the input <name> to the connection c
472   void ComplexBlackBox::bbConnectInput( const std::string& name, Connection* c)
473   {
474     bbtkDebugMessage("connection",2,
475                      "==> ComplexBlackBox::bbConnectInput(\""
476                      <<name<<"\","<<c->GetFullName()<<") ["
477                      <<bbGetFullName()<<"]"
478                      <<std::endl);       
479     
480    ComplexBlackBoxInputDescriptor* d = (ComplexBlackBoxInputDescriptor*)
481       bbGetDescriptor()->GetInputDescriptor(name);
482
483
484    BlackBox::Pointer t = bbGetBlackBox(d->GetTarget());
485
486    bbtkDebugMessage("connection",2," - Target = "<<d->GetTarget()<<" = "<<t->bbGetFullName()<<std::endl);
487
488    c->SetBlackBoxTo(t);
489    c->SetBlackBoxToInput(d->GetInput());
490
491    bbtkDebugMessage("connection",2," - New conn = "<<c->GetFullName()<<std::endl);
492    t->bbConnectInput(d->GetInput(),c);
493
494    bbtkDebugMessage("connection",2,
495                      "<== ComplexBlackBox::bbConnectInput(\""
496                      <<name<<"\","<<c->GetFullName()<<") ["
497                      <<bbGetFullName()<<"]"
498                      <<std::endl);       
499   }
500   //=========================================================================
501
502
503   //=========================================================================  
504   /// Connects the output <name> to the connection c
505   void ComplexBlackBox::bbConnectOutput( const std::string& name, Connection* c)
506   {
507     bbtkDebugMessage("connection",2,
508                      "==> ComplexBlackBox::bbConnectOutput(\""
509                      <<name<<"\","<<c->GetFullName()<<") ["
510                      <<bbGetFullName()<<"]"<<std::endl);       
511
512    ComplexBlackBoxOutputDescriptor* d = (ComplexBlackBoxOutputDescriptor*)
513       bbGetDescriptor()->GetOutputDescriptor(name);
514
515    BlackBox::Pointer t = bbGetBlackBox(d->GetTarget());
516  
517   bbtkDebugMessage("connection",2," - Target = "<<d->GetTarget()<<" = "<<t->bbGetFullName()<<std::endl);
518
519    c->SetBlackBoxFrom(t);
520    c->SetBlackBoxFromOutput(d->GetOutput());
521
522    bbtkDebugMessage("connection",2," - New conn = "<<c->GetFullName()<<std::endl);
523
524    t->bbConnectOutput(d->GetOutput(),c);
525   
526     bbtkDebugMessage("connection",2,
527                      "<== ComplexBlackBox::bbConnectOutput(\""
528                      <<name<<"\","<<c->GetFullName()<<") ["
529                      <<bbGetFullName()<<"]"<<std::endl);       
530   }
531   //=========================================================================
532
533
534   //==================================================================
535   /// Adds the black box to the complex box
536   void ComplexBlackBox::bbAddBlackBox( BlackBox::Pointer b)
537   {
538     bbtkDebugMessageInc("Kernel",7,
539                         "ComplexBlackBox::AddBlackBox(\""<<b->bbGetName()
540                         <<"\") ["
541                         <<bbGetFullName()<<"]"<<std::endl);  
542     
543     if ( bbUnsafeGetBlackBox(b->bbGetName()) ) 
544       {
545         bbtkError("a black box called \""<<b->bbGetName()
546                   <<"\" already exists");
547       }
548     b->bbSetParent(GetThisPointer<ComplexBlackBox>());
549     mBlackBoxMap[b->bbGetName()] = b;
550
551     bbtkDebugDecTab("Kernel",7);
552   }
553   //==================================================================
554
555   //==================================================================
556   /// Adds the black box to the complex box (unsafe)
557   void ComplexBlackBox::bbUnsafeAddBlackBox( BlackBox::Pointer b)
558   {
559     bbtkDebugMessageInc("Kernel",7,
560                         "ComplexBlackBox::UnsafeAddBlackBox(\""<<b->bbGetName()
561                         <<"\") ["
562                         <<bbGetFullName()<<"]"<<std::endl);  
563     
564     b->bbSetParent(GetThisPointer<ComplexBlackBox>());
565     mBlackBoxMap[b->bbGetName()] = b;
566
567     bbtkDebugDecTab("Kernel",7);
568   }
569   //==================================================================
570
571   //==================================================================
572   /// Removes the black box from the complex box
573   void ComplexBlackBox::bbRemoveBlackBox( const std::string& name, 
574                                           bool remove_connections )
575   {
576     bbtkDebugMessageInc("Kernel",7,
577                         "ComplexBlackBox::RemoveBlackBox(\""<<name<<"\") ["
578                         <<bbGetFullName()<<"]"<<std::endl);  
579
580     BlackBoxMapType::iterator i = mBlackBoxMap.find(name);
581     if ( i == mBlackBoxMap.end() ) 
582       {
583         bbtkError("the black box \""<<name<<"\" does not exist");
584       }
585     BlackBox::WeakPointer p = i->second;
586     
587     if (remove_connections)
588       {
589         ConnectionListType::const_iterator j;
590         for ( j = mConnectionList.begin(); 
591               j != mConnectionList.end(); ++j ) 
592           {
593             (*j)->Check();
594           }
595       }
596     if (p.use_count()!=1) 
597       {
598         bbtkError("the black box \""<<name<<"\" is still connected");
599       }
600     
601     mBlackBoxMap.erase(i);
602     
603
604     // Unload orphan dl packages 
605     Package::UnLoadReleasedDynamicallyLoadedPackages();
606
607     bbtkDebugDecTab("Kernel",7);
608   }
609   //==================================================================
610
611   //==================================================================
612   /// Adds the connection to the complex box
613   void ComplexBlackBox::bbAddConnection( Connection::Pointer c)
614   {
615     bbtkDebugMessageInc("Kernel",7,
616                         "ComplexBlackBox::AddConnection(\""<<"..."<<"\") ["
617                         <<bbGetFullName()<<"]"<<std::endl);  
618
619     mConnectionList.push_back(c);
620
621     bbtkDebugDecTab("Kernel",7);
622   }
623   //==================================================================
624   //    void RemoveConnection( );
625
626   //==================================================================
627   /// Returns the black box with name <name>
628   BlackBox::Pointer ComplexBlackBox::bbGetBlackBox( const std::string& name )
629   {
630     bbtkDebugMessageInc("Kernel",9,
631                         "ComplexBlackBox::GetBlackBox(\""<<name<<"\") ["
632                         <<bbGetFullName()<<"]"<<std::endl);  
633
634     BlackBoxMapType::iterator i = mBlackBoxMap.find(name);
635     if ( i == mBlackBoxMap.end() ) 
636       {
637         bbtkError("the black box \""<<name<<"\" does not exist");
638       }
639
640     bbtkDebugDecTab("Kernel",9);
641     return i->second;
642   }
643   //==================================================================
644
645   //==================================================================
646   /// Returns the black box with name <name> : does not throw an exception 
647   /// if it does not exist but return a null pointer
648   BlackBox::Pointer ComplexBlackBox::bbUnsafeGetBlackBox( const std::string& name )
649   {
650     bbtkDebugMessageInc("Kernel",9,
651                         "ComplexBlackBox::UnsafeGetBlackBox(\""<<name<<"\") ["
652                         <<bbGetFullName()<<"]"
653                         <<std::endl);  
654
655     BlackBoxMapType::iterator i = mBlackBoxMap.find(name);
656     if ( i == mBlackBoxMap.end() ) 
657       {
658         bbtkDebugDecTab("Kernel",9);
659         return BlackBox::Pointer();
660       }
661
662     bbtkDebugDecTab("Kernel",9);
663     return i->second;
664     
665   }
666   //==================================================================
667
668   //==================================================================
669   void ComplexBlackBox::bbPrintBlackBoxes()
670   {
671     bbtkDebugMessageInc("Kernel",9,
672                         "ComplexBlackBox::PrintBlackBoxes() ["
673                         <<bbGetFullName()<<"]"
674                         <<std::endl);  
675
676     BlackBoxMapType::iterator i;
677     for ( i = mBlackBoxMap.begin(); i != mBlackBoxMap.end(); ++i ) 
678       {
679         bbtkMessage("Help",1,i->second->bbGetFullName()<<std::endl);
680       }
681
682     bbtkDebugDecTab("Kernel",9);
683   }
684   //==================================================================
685
686
687  
688   //=========================================================================
689   /// Virtual
690   void ComplexBlackBox::bbWriteDotInputOutputName(FILE *ff,bool inputoutput,int detail, int level)
691   {
692     if (inputoutput)
693       {
694         fprintf(ff,"%s_IN_%p",bbGetTypeName().c_str(),this);
695       } else {
696       fprintf(ff,"%s_OUT_%p",bbGetTypeName().c_str(),this);
697     } // if inputoutput
698   }
699   //=========================================================================
700
701
702   //=========================================================================
703   BlackBox::Pointer ComplexBlackBox::bbFindBlackBox(const std::string &blackboxname)
704   {
705     BlackBox::Pointer blackbox;
706     std::string subname="";
707     std::string restname="";
708     std::string delimiters(">");
709     // Skip delimiters at beginning.
710     std::string::size_type lastPos = blackboxname.find_first_not_of(delimiters, 0);
711     // Find first "non-delimiter".
712     std::string::size_type pos     = blackboxname.find_first_of(delimiters, lastPos);
713             
714     // Found a token, add it to the vector.
715     subname = blackboxname.substr(lastPos, pos - lastPos);
716     restname = blackboxname.substr(lastPos+pos - lastPos+1, 999);
717
718     if (restname==subname)
719     {
720            restname="";
721     }
722
723     BlackBoxMapType::iterator i = mBlackBoxMap.find(subname);
724     if ( i != mBlackBoxMap.end() ) 
725     {
726        blackbox = i->second;
727        if (restname!="")
728             {
729              blackbox = blackbox->bbFindBlackBox(restname);
730             }
731     }
732     return blackbox;
733   }
734   //=========================================================================
735
736   //=========================================================================
737   void ComplexBlackBox::bbInsertHTMLGraph(  std::ofstream& s, 
738                                             int detail, 
739                                             int level,
740                                             bool instanceOrtype,
741                                             const std::string& output_dir,
742                                             bool relative_link )
743   {
744     
745     std::string directory(output_dir);
746
747     if (output_dir.length() == 0) 
748     {
749            // Don't pollute the file store with  "temp_dir" directories ... 
750            std::string default_temp_dir = ConfigurationFile::GetInstance().Get_default_temp_dir();
751            directory =  default_temp_dir + "/" + "temp_dir";
752     }
753     
754     std::string simplefilename  (this->bbGetTypeName()+"_"+this->bbGetName());
755     std::string simplefilename_png (simplefilename+".png");
756     std::string filename           (directory+"/"+simplefilename);
757     std::string filename_png       (filename+".png");
758     std::string filename_cmap      (filename+".cmap");
759     std::string filename_dot       (filename+".dot");
760
761     std::string filename_png2   ("\""   + filename_png  + "\"");
762     std::string filename_cmap2  ("\""   + filename_cmap + "\"");
763     std::string filename_dot2   ("\""   + filename_dot  + "\"");
764     
765
766     std::string command1 ("dot -T png -o "  
767                           + filename_png2  + " " + filename_dot2);
768     std::string command1a("dot -T cmap -o " 
769                           + filename_cmap2 + " " + filename_dot2);
770
771     // 1. Generating .dot file
772     FILE *ff;
773     ff = fopen(filename_dot.c_str(),"w");
774     fprintf(ff,"digraph bbtk_graph{\n");
775     fprintf(ff,"rankdir=LR%s\n",";");
776     fprintf(ff,"node [shape=record]%s\n",";");
777
778     this->bbWriteDotFileBlackBox(ff,
779                                  GetThisPointer<ComplexBlackBox>(),
780                                  detail,level,
781                                  instanceOrtype,
782                                  relative_link );
783
784     fprintf(ff,"}\n");
785     fclose(ff);
786
787     // 2. Executing .dot file -> png
788     system( command1.c_str() );   
789     // 3. Executing .dot file -> cmap
790     system( command1a.c_str() );  
791     
792     // 4. HTML code insertion
793     // 4.1 image
794     (s) << "<center><img src=\"" << simplefilename_png 
795          <<   "\" border=\"0\" usemap=\"#map_"<< simplefilename 
796          <<"\" alt=\"\"></center>\n";
797
798     // 4.2 map
799     (s) << "<map name=\"map_"<< simplefilename <<"\">\n";
800     FILE *ff2;
801     char c;
802     ff2=fopen(filename_cmap.c_str(),"r");
803     while (!feof(ff2))
804     {
805            c=fgetc(ff2);
806            if (c!=-1)
807            {
808               (s) << c;
809            }
810     }
811     (s) << "</map>\n\n";
812     
813     // End
814   }
815   //=========================================================================
816
817
818   //=========================================================================
819   /// Write Graphviz-dot description in file 
820   void ComplexBlackBox::bbWriteDotFileBlackBox(FILE *ff,
821                                                BlackBox::Pointer parentblackbox, 
822                                                int detail, int level,
823                                                bool instanceOrtype,
824                                                bool relative_link )   
825   {
826     std::string tmp1;
827     std::string valueStr("");
828     Package::Pointer package = this->bbGetDescriptor()->GetPackage(); 
829
830     if (package!=NULL)
831     {
832       if (relative_link)
833              tmp1 = this->bbGetDescriptor()->GetPackage()->GetDocRelativeURL();
834            else 
835              tmp1 = this->bbGetDescriptor()->GetPackage()->GetDocURL();
836     } 
837     else 
838     {
839            tmp1 = "Caspitas";
840     }
841
842     std::string tmp2=bbGetTypeName();
843     std::string url(tmp1 + "#" + tmp2 );        
844     fprintf( ff , "subgraph cluster_%s_%p {\n",bbGetName().c_str(),this);
845
846     if (!(   (bbGetTypeName()=="workspace") && (bbGetName()=="workspacePrototype")) )
847     {
848            fprintf( ff , "  URL = \"%s\" %s",url.c_str(),";");
849     }
850
851     std::string boxname="["+bbGetTypeName()+"]";
852     if (GetThisPointer<ComplexBlackBox>()!=parentblackbox)
853     {
854        if (detail==0)
855             {
856           boxname=bbGetName();
857        } 
858        else 
859        {
860           boxname = bbGetName();
861           boxname = boxname + "   [" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "]";
862             }
863
864     }
865     fprintf( ff , "  label = \"%s\"%s\n",  boxname.c_str() ,";");
866
867
868
869     //  fprintf( ff , "  style=filled%s\n",";");
870     //  fprintf( ff , "  color=grey%s\n",";");
871     fprintf( ff , "  node [style=filled]%s\n",";");
872     fprintf( ff , "  fillcolor=grey%s\n",";");
873     fprintf( ff , "  edge [color=blue]%s\n",";");
874
875
876     // Labels Salida
877     std::string labelStr1;
878     std::string labelStr2;
879     labelStr1 = boxname + "\\n(output)" ; 
880     labelStr2 = " | {{ ";
881     bool tmp; 
882     tmp=false;
883     OutputConnectorMapType::iterator i;
884
885     const BlackBoxDescriptor::OutputDescriptorMapType& omap = this->bbGetDescriptor()->GetOutputDescriptorMap();
886     BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;      
887     for ( o = omap.begin();  o != omap.end(); ++o ) 
888       {
889         if (tmp==true)
890           {
891             labelStr2=labelStr2+" | ";
892           }
893         tmp=true;
894         if (instanceOrtype==true)
895           {
896             valueStr = this->bbGetOutputAsString(o->second->GetName()/*
897                                                                    ,factory*/) + " = ";
898           } 
899         labelStr2=labelStr2+"<"+o->second->GetName().c_str()+"> " + valueStr + o->second->GetName().c_str();
900       }
901
902     labelStr2 = labelStr2+ " } }";
903
904
905
906     if (detail==1)
907       {
908         labelStr1 = labelStr1 + labelStr2;
909       }
910
911     if (tmp){
912       fprintf(ff,"  " );
913       bbWriteDotInputOutputName(ff,false,detail,level);
914       fprintf( ff , " [shape=record, style=filled,fillcolor=grey,color=red,label=\"%s\"]%s\n",labelStr1.c_str(),";" );
915     }
916
917
918     // label Entrada
919     labelStr1 = boxname + "\\n(input)" ; 
920     labelStr2 = " | {{ "; 
921     tmp=false;
922     InputConnectorMapType::iterator ii;
923
924     const BlackBoxDescriptor::InputDescriptorMapType& imap = this->bbGetDescriptor()->GetInputDescriptorMap();  
925     BlackBoxDescriptor::InputDescriptorMapType::const_iterator iii;
926     for ( iii = imap.begin();  iii != imap.end(); ++iii ) 
927       {
928         if (tmp==true)
929           {
930             labelStr2=labelStr2+" | ";
931           }
932         tmp=true;
933         if (instanceOrtype==true)
934           {
935             valueStr = this->bbGetInputAsString(iii->second->GetName()/*,factory*/) + " = ";
936           } 
937         labelStr2=labelStr2+"<"+iii->second->GetName().c_str()+"> " + valueStr + iii->second->GetName().c_str();
938       }
939
940
941     labelStr2 = labelStr2+ " } }";
942     if (detail==1)
943       {
944         labelStr1 = labelStr1 + labelStr2;
945       }
946     if (tmp){
947       fprintf(ff,"  " );
948       bbWriteDotInputOutputName(ff,true,detail,level);
949       fprintf( ff , " [shape=record, style=filled,fillcolor=grey,color=red,label=\"%s\"]%s\n",labelStr1.c_str(),";" );
950     }
951
952
953     // Body
954     BlackBoxMapType::iterator j;
955     for ( j = mBlackBoxMap.begin(); j != mBlackBoxMap.end(); ++j ) 
956       {
957         if (level>-1)
958           {
959             j->second->bbWriteDotFileBlackBox(ff,
960                                               parentblackbox,
961                                               detail,
962                                               level-1,
963                                               instanceOrtype,
964                                               relative_link);
965           }
966       }
967
968     fprintf( ff , "}\n\n");
969
970     fprintf( ff , "  edge[color=blue]%s\n",";");
971
972     if (level>-1)
973       {
974         // Relation Input  with the inside BlackBox of the this ComplexBlackbox
975         ComplexBlackBoxDescriptor::InputDescriptorMapType::iterator xx;
976         ComplexBlackBoxDescriptor::InputDescriptorMapType idmt=bbGetDescriptor()->GetInputDescriptorMap();
977         for ( xx = idmt.begin(); xx != idmt.end(); ++xx ) 
978           {
979             ComplexBlackBoxInputDescriptor *cbbid = (ComplexBlackBoxInputDescriptor*)xx->second;
980
981             fprintf(ff,"  ");
982             bbWriteDotInputOutputName(ff,true,detail,level);
983             if (detail==1)
984               {
985                 fprintf(ff,":%s",cbbid->GetName().c_str() );
986               }
987             fprintf(ff,"->" );
988             BlackBox::Pointer bb = bbGetBlackBox( cbbid->GetTarget() ); 
989             bb->bbWriteDotInputOutputName(ff,true,detail,level);
990             if (detail==1)
991               {
992                 fprintf(ff,":%s \n", cbbid->GetInput().c_str() );
993               }
994           }// for xx
995
996
997
998         fprintf(ff,"\n \n");
999
1000
1001
1002         // Relation Output ComplexBlackBox
1003         ComplexBlackBoxDescriptor::OutputDescriptorMapType::iterator yy;
1004         ComplexBlackBoxDescriptor::OutputDescriptorMapType odmt=bbGetDescriptor()->GetOutputDescriptorMap();
1005         for ( yy = odmt.begin(); yy != odmt.end(); ++yy ) 
1006           {
1007             ComplexBlackBoxOutputDescriptor *cbbod = (ComplexBlackBoxOutputDescriptor*)yy->second;
1008             fprintf(ff,"  ");
1009             BlackBox::Pointer bb = bbGetBlackBox( cbbod->GetTarget() ); 
1010             bb->bbWriteDotInputOutputName(ff,false,detail,level);
1011             if (detail==1)
1012               {
1013                 fprintf(ff,":%s", cbbod->GetOutput().c_str() );
1014               }
1015             fprintf(ff,"->" );
1016             bbWriteDotInputOutputName(ff,false,detail,level);
1017             if (detail==1)
1018               {
1019                 fprintf(ff,":%s",cbbod->GetName().c_str() );
1020               }
1021             fprintf(ff,"\n");
1022           } // for yy
1023
1024       } // if level
1025
1026
1027
1028         // Relation from the out side of this ComplexBlackBox with its Inputs
1029     if (GetThisPointer<ComplexBlackBox>()!=parentblackbox) {
1030       for ( ii = bbGetInputConnectorMap().begin(); 
1031             ii != bbGetInputConnectorMap().end(); ++ii ) 
1032         {
1033           if (ii->second)
1034             {
1035               Connection* con = ii->second->GetConnection();
1036               if (con!=NULL){
1037                 BlackBox::Pointer a=con->GetOriginalBlackBoxFrom();
1038                 BlackBox::Pointer b=con->GetOriginalBlackBoxTo();
1039                 fprintf(ff,"  ");
1040                 a->bbWriteDotInputOutputName(ff,false,detail,level);
1041                 if (detail==1)
1042                   {
1043                     fprintf(ff,":%s",con->GetOriginalBlackBoxFromOutput().c_str());
1044                   }
1045                 fprintf(ff,"->");
1046                 b->bbWriteDotInputOutputName(ff,true,detail,level);
1047                 if (detail==1)
1048                   {
1049                     fprintf(ff,":%s",con->GetOriginalBlackBoxToInput().c_str());
1050                   }
1051                 fprintf(ff,"%s\n",";");
1052               } // if con
1053             } // if second
1054         } // for
1055     } // if parentblackbox
1056   }
1057   //=========================================================================
1058   
1059
1060
1061
1062   /*
1063
1064   //=======================================================================
1065   /// Generates the list of the packages of which its depends 
1066   /// (cause an internal box belongs to it)
1067   void ComplexBlackBox::GetPackagesDependencies(std::vector<Package*>& deps)
1068   {
1069     deps.clear;
1070     BlackBoxMapType::iterator i;
1071     for ( i = mBlackBoxMap.begin(); i != mBlackBoxMap.end(); ++i ) 
1072       {
1073         deps.push_back(i->second->bbGetDescriptor()->GetPackage());
1074       }
1075
1076   }
1077   //=======================================================================
1078   */
1079
1080   //=======================================================================
1081   void ComplexBlackBox::Check(bool recursive)
1082   {
1083      bbtkMessage("debug",1,"**** Checking Complex Black Box "<<(void*)this
1084                  <<" ["<<bbGetFullName()<<"]"<<std::endl);
1085      
1086      BlackBoxMapType::const_iterator i;
1087      for ( i = mBlackBoxMap.begin(); i != mBlackBoxMap.end(); ++i ) 
1088        {
1089          i->second->Check(recursive);
1090        }
1091      ConnectionListType::const_iterator j;
1092      for ( j = mConnectionList.begin(); 
1093            j != mConnectionList.end(); ++j ) 
1094        {
1095          (*j)->Check();
1096        }
1097      bbtkMessage("debug",1,"**** Checking Complex Black Box "<<(void*)this
1098                  <<" ["<<bbGetFullName()<<"] ... OK"<<std::endl);
1099   
1100   }
1101   //=======================================================================
1102
1103   //=========================================================================
1104   /// Returns the name with the name of the parent prepended if any
1105   std::string ComplexBlackBox::bbGetNameWithParent() const
1106   {
1107     if (!IsAPrototype()) return BlackBox::bbGetNameWithParent();
1108     if (bbGetDescriptor()) 
1109       {
1110         return bbGetDescriptor()->GetFullTypeName() + ":" + bbGetName();
1111       }
1112     else 
1113       {
1114         return std::string(":") + bbGetName();
1115       }
1116   } 
1117   //=========================================================================
1118
1119   //==========================================================================
1120   std::string ComplexBlackBox::GetObjectName() const
1121   {
1122     return std::string("ComplexBlackBox '")+bbGetNameWithParent()
1123       +std::string("'");
1124   }
1125   //==========================================================================
1126   
1127   //==========================================================================
1128   std::string ComplexBlackBox::GetObjectInfo() const 
1129   {
1130     std::stringstream i;
1131     i << "  - "<<mBlackBoxMap.size() << " boxes / "
1132       <<mConnectionList.size() << " connections" << std::endl;
1133     return i.str();
1134   }
1135   //==========================================================================
1136
1137   //==========================================================================
1138   size_t  ComplexBlackBox::GetObjectSize() const 
1139   {
1140     size_t s = Superclass::GetObjectSize();
1141     s += ComplexBlackBox::GetObjectInternalSize();
1142     return s;
1143   }
1144   //==========================================================================
1145   //==========================================================================
1146   size_t  ComplexBlackBox::GetObjectInternalSize() const 
1147   {
1148     size_t s = sizeof(ComplexBlackBox);
1149     return s;
1150   }
1151   //==========================================================================
1152   //==========================================================================
1153   size_t  ComplexBlackBox::GetObjectRecursiveSize() const 
1154   {
1155     size_t s = Superclass::GetObjectRecursiveSize();
1156     s += ComplexBlackBox::GetObjectInternalSize();
1157     BlackBoxMapType::const_iterator i;
1158     for ( i = mBlackBoxMap.begin(); i != mBlackBoxMap.end(); ++i ) 
1159       {
1160         s += i->second->GetObjectRecursiveSize();
1161       }
1162     ConnectionListType::const_iterator j;
1163     for ( j = mConnectionList.begin(); 
1164           j != mConnectionList.end(); ++j ) 
1165       {
1166         s += (*j)->GetObjectRecursiveSize();
1167       }
1168     return s;
1169   }
1170   //==========================================================================
1171
1172 }