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