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