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