]> Creatis software - bbtk.git/blob - kernel/src/bbtkComplexBlackBox.cxx
no message
[bbtk.git] / kernel / src / bbtkComplexBlackBox.cxx
1 /*=========================================================================                                                                               
2   Program:   bbtk
3   Module:    $RCSfile: bbtkComplexBlackBox.cxx,v $
4   Language:  C++
5   Date:      $Date: 2010/03/19 08:18:41 $
6   Version:   $Revision: 1.32 $
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 #ifdef WIN32
695         std::string currentexecpath("\"\"" + crea::System::GetDllAppPath("bbtk") +"\\dot_embedded\\dot\"");     
696         std::string command1 (currentexecpath + " -Tpng -o " + filename_png2  + " " + filename_dot2 + "\"");
697         std::string command1a(currentexecpath + " -T cmap -o " + filename_cmap2 + " " + filename_dot2 + "\"");          
698 #else
699   #ifdef APPLE
700         std::string command1 ("dot -Tpng:quartz -o " + filename_png2  + " " + filename_dot2  );
701         std::string command1a("dot -T cmap -o " + filename_cmap2 + " " + filename_dot2 );
702   #else
703         std::string command1 ("dot -Tpng:cairo -o " + filename_png2  + " " + filename_dot2  );
704         std::string command1a("dot -T cmap -o " + filename_cmap2 + " " + filename_dot2 );
705   #endif
706 #endif
707
708
709     
710
711     // 1. Generating .dot file
712     FILE *ff;
713     ff = fopen(filename_dot.c_str(),"w");
714     fprintf(ff,"digraph bbtk_graph{\n");
715     fprintf(ff,"rankdir=LR%s\n",";");
716     fprintf(ff,"node [shape=record]%s\n",";");
717
718     this->bbWriteDotFileBlackBox(ff,
719                                  GetThisPointer<ComplexBlackBox>(),
720                                  detail,level,
721                                  instanceOrtype,
722                                  relative_link );
723
724     fprintf(ff,"}\n");
725     fclose(ff);
726
727         std::cout<<"JCP bbtkComplexBlackBox.cxx execute1="<<command1<<std::endl;
728     // 2. Executing .dot file -> png
729     system( command1.c_str() );   
730     // 3. Executing .dot file -> cmap
731         std::cout<<"JCP bbtkComplexBlackBox.cxx execute2="<<command1a<<std::endl;
732     system( command1a.c_str() );  
733     
734     // 4. HTML code insertion
735     // 4.1 image
736     (s) << "<center><img src=\"" << simplefilename_png 
737          <<   "\" border=\"0\" usemap=\"#map_"<< simplefilename 
738          <<"\" alt=\"\"></center>\n";
739
740     // 4.2 map
741     (s) << "<map name=\"map_"<< simplefilename <<"\">\n";
742     FILE *ff2;
743     char c;
744     ff2=fopen(filename_cmap.c_str(),"r");
745         if (ff2!=NULL){
746                 while (!feof(ff2))
747                 {
748                         c=fgetc(ff2);
749                         if (c!=-1)
750                         {
751                                 (s) << c;
752                         } // if 
753                 } // while
754         } // if ff2
755     (s) << "</map>\n\n";
756     
757     // End
758   }
759   //=========================================================================
760
761
762   //=========================================================================
763   /// Write Graphviz-dot description in file 
764   void ComplexBlackBox::bbWriteDotFileBlackBox(FILE *ff,
765                                                BlackBox::Pointer parentblackbox, 
766                                                int detail, int level,
767                                                bool instanceOrtype,
768                                                bool relative_link )   
769   {
770     std::string tmp1;
771     std::string valueStr("");
772     Package::Pointer package = this->bbGetDescriptor()->GetPackage(); 
773
774     if (package!=NULL)
775     {
776       if (relative_link)
777              tmp1 = this->bbGetDescriptor()->GetPackage()->GetDocRelativeURL();
778            else 
779              tmp1 = this->bbGetDescriptor()->GetPackage()->GetDocURL();
780     } 
781     else 
782     {
783            tmp1 = "Caspitas";
784     }
785
786     std::string tmp2=bbGetTypeName();
787     std::string url(tmp1 + "#" + tmp2 );        
788     fprintf( ff , "subgraph cluster_%s_%p {\n",bbGetName().c_str(),this);
789
790     if (!(   (bbGetTypeName()=="workspace") && (bbGetName()=="workspacePrototype")) )
791     {
792            fprintf( ff , "  URL = \"%s\" %s",url.c_str(),";");
793     }
794
795     std::string boxname="["+bbGetTypeName()+"]";
796     if (GetThisPointer<ComplexBlackBox>()!=parentblackbox)
797     {
798        if (detail==0)
799             {
800           boxname=bbGetName();
801        } 
802        else 
803        {
804           boxname = bbGetName();
805           boxname = boxname + "   [" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "]";
806             }
807
808     }
809     fprintf( ff , "  label = \"%s\"%s\n",  boxname.c_str() ,";");
810
811
812
813     //  fprintf( ff , "  style=filled%s\n",";");
814     //  fprintf( ff , "  color=grey%s\n",";");
815     fprintf( ff , "  node [style=filled]%s\n",";");
816     fprintf( ff , "  fillcolor=grey%s\n",";");
817     fprintf( ff , "  edge [color=blue]%s\n",";");
818
819
820     // Labels Salida
821     std::string labelStr1;
822     std::string labelStr2;
823     labelStr1 = boxname + "\\n(output)" ; 
824     labelStr2 = " | {{ ";
825     bool tmp; 
826     tmp=false;
827     OutputConnectorMapType::iterator i;
828
829     const BlackBoxDescriptor::OutputDescriptorMapType& omap = this->bbGetDescriptor()->GetOutputDescriptorMap();
830     BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;      
831     for ( o = omap.begin();  o != omap.end(); ++o ) 
832       {
833         if (tmp==true)
834           {
835             labelStr2=labelStr2+" | ";
836           }
837         tmp=true;
838         if (instanceOrtype==true)
839           {
840             valueStr = this->bbGetOutputAsString(o->second->GetName()/*
841                                                                    ,factory*/) + " = ";
842           } 
843         labelStr2=labelStr2+"<"+o->second->GetName().c_str()+"> " + valueStr + o->second->GetName().c_str();
844       }
845
846     labelStr2 = labelStr2+ " } }";
847
848
849
850     if (detail==1)
851       {
852         labelStr1 = labelStr1 + labelStr2;
853       }
854
855     if (tmp){
856       fprintf(ff,"  " );
857       bbWriteDotInputOutputName(ff,false,detail,level);
858       fprintf( ff , " [shape=record, style=filled,fillcolor=grey,color=red,label=\"%s\"]%s\n",labelStr1.c_str(),";" );
859     }
860
861
862     // label Entrada
863     labelStr1 = boxname + "\\n(input)" ; 
864     labelStr2 = " | {{ "; 
865     tmp=false;
866     InputConnectorMapType::iterator ii;
867
868     const BlackBoxDescriptor::InputDescriptorMapType& imap = this->bbGetDescriptor()->GetInputDescriptorMap();  
869     BlackBoxDescriptor::InputDescriptorMapType::const_iterator iii;
870     for ( iii = imap.begin();  iii != imap.end(); ++iii ) 
871       {
872         if (tmp==true)
873           {
874             labelStr2=labelStr2+" | ";
875           }
876         tmp=true;
877         if (instanceOrtype==true)
878           {
879             valueStr = this->bbGetInputAsString(iii->second->GetName()/*,factory*/) + " = ";
880           } 
881         labelStr2=labelStr2+"<"+iii->second->GetName().c_str()+"> " + valueStr + iii->second->GetName().c_str();
882       }
883
884
885     labelStr2 = labelStr2+ " } }";
886     if (detail==1)
887       {
888         labelStr1 = labelStr1 + labelStr2;
889       }
890     if (tmp){
891       fprintf(ff,"  " );
892       bbWriteDotInputOutputName(ff,true,detail,level);
893       fprintf( ff , " [shape=record, style=filled,fillcolor=grey,color=red,label=\"%s\"]%s\n",labelStr1.c_str(),";" );
894     }
895
896
897     // Body
898     BlackBoxMapType::iterator j;
899     for ( j = mBlackBoxMap.begin(); j != mBlackBoxMap.end(); ++j ) 
900       {
901         if (level>-1)
902           {
903             j->second->bbWriteDotFileBlackBox(ff,
904                                               parentblackbox,
905                                               detail,
906                                               level-1,
907                                               instanceOrtype,
908                                               relative_link);
909           }
910       }
911
912     fprintf( ff , "}\n\n");
913
914     fprintf( ff , "  edge[color=blue]%s\n",";");
915
916     if (level>-1)
917       {
918         // Relation Input  with the inside BlackBox of the this ComplexBlackbox
919         ComplexBlackBoxDescriptor::InputDescriptorMapType::iterator xx;
920         ComplexBlackBoxDescriptor::InputDescriptorMapType idmt=bbGetDescriptor()->GetInputDescriptorMap();
921         for ( xx = idmt.begin(); xx != idmt.end(); ++xx ) 
922           {
923             ComplexBlackBoxInputDescriptor *cbbid = (ComplexBlackBoxInputDescriptor*)xx->second;
924
925             fprintf(ff,"  ");
926             bbWriteDotInputOutputName(ff,true,detail,level);
927             if (detail==1)
928               {
929                 fprintf(ff,":%s",cbbid->GetName().c_str() );
930               }
931             fprintf(ff,"->" );
932             BlackBox::Pointer bb = bbGetBlackBox( cbbid->GetTarget() ); 
933             bb->bbWriteDotInputOutputName(ff,true,detail,level);
934             if (detail==1)
935               {
936                 fprintf(ff,":%s \n", cbbid->GetInput().c_str() );
937               }
938           }// for xx
939
940
941
942         fprintf(ff,"\n \n");
943
944
945
946         // Relation Output ComplexBlackBox
947         ComplexBlackBoxDescriptor::OutputDescriptorMapType::iterator yy;
948         ComplexBlackBoxDescriptor::OutputDescriptorMapType odmt=bbGetDescriptor()->GetOutputDescriptorMap();
949         for ( yy = odmt.begin(); yy != odmt.end(); ++yy ) 
950           {
951             ComplexBlackBoxOutputDescriptor *cbbod = (ComplexBlackBoxOutputDescriptor*)yy->second;
952             fprintf(ff,"  ");
953             BlackBox::Pointer bb = bbGetBlackBox( cbbod->GetTarget() ); 
954             bb->bbWriteDotInputOutputName(ff,false,detail,level);
955             if (detail==1)
956               {
957                 fprintf(ff,":%s", cbbod->GetOutput().c_str() );
958               }
959             fprintf(ff,"->" );
960             bbWriteDotInputOutputName(ff,false,detail,level);
961             if (detail==1)
962               {
963                 fprintf(ff,":%s",cbbod->GetName().c_str() );
964               }
965             fprintf(ff,"\n");
966           } // for yy
967
968       } // if level
969
970
971
972         // Relation from the out side of this ComplexBlackBox with its Inputs
973     if (GetThisPointer<ComplexBlackBox>()!=parentblackbox) {
974       for ( ii = bbGetInputConnectorMap().begin(); 
975             ii != bbGetInputConnectorMap().end(); ++ii ) 
976         {
977           if (ii->second)
978             {
979               Connection* con = ii->second->GetConnection();
980               if (con!=NULL){
981                 BlackBox::Pointer a=con->GetOriginalBlackBoxFrom();
982                 BlackBox::Pointer b=con->GetOriginalBlackBoxTo();
983                 fprintf(ff,"  ");
984                 a->bbWriteDotInputOutputName(ff,false,detail,level);
985                 if (detail==1)
986                   {
987                     fprintf(ff,":%s",con->GetOriginalBlackBoxFromOutput().c_str());
988                   }
989                 fprintf(ff,"->");
990                 b->bbWriteDotInputOutputName(ff,true,detail,level);
991                 if (detail==1)
992                   {
993                     fprintf(ff,":%s",con->GetOriginalBlackBoxToInput().c_str());
994                   }
995                 fprintf(ff,"%s\n",";");
996               } // if con
997             } // if second
998         } // for
999     } // if parentblackbox
1000   }
1001   //=========================================================================
1002   
1003
1004
1005
1006   /*
1007
1008   //=======================================================================
1009   /// Generates the list of the packages of which its depends 
1010   /// (cause an internal box belongs to it)
1011   void ComplexBlackBox::GetPackagesDependencies(std::vector<Package*>& deps)
1012   {
1013     deps.clear;
1014     BlackBoxMapType::iterator i;
1015     for ( i = mBlackBoxMap.begin(); i != mBlackBoxMap.end(); ++i ) 
1016       {
1017         deps.push_back(i->second->bbGetDescriptor()->GetPackage());
1018       }
1019
1020   }
1021   //=======================================================================
1022   */
1023
1024   //=======================================================================
1025   void ComplexBlackBox::Check(bool recursive)
1026   {
1027      bbtkMessage("debug",1,"**** Checking Complex Black Box "<<(void*)this
1028                  <<" ["<<bbGetFullName()<<"]"<<std::endl);
1029      
1030      BlackBoxMapType::const_iterator i;
1031      for ( i = mBlackBoxMap.begin(); i != mBlackBoxMap.end(); ++i ) 
1032        {
1033          i->second->Check(recursive);
1034        }
1035      ConnectionListType::const_iterator j;
1036      for ( j = mConnectionList.begin(); 
1037            j != mConnectionList.end(); ++j ) 
1038        {
1039          (*j)->Check();
1040        }
1041      bbtkMessage("debug",1,"**** Checking Complex Black Box "<<(void*)this
1042                  <<" ["<<bbGetFullName()<<"] ... OK"<<std::endl);
1043   
1044   }
1045   //=======================================================================
1046
1047   //=========================================================================
1048   /// Returns the name with the name of the parent prepended if any
1049   std::string ComplexBlackBox::bbGetNameWithParent() const
1050   {
1051     if (!IsAPrototype()) return BlackBox::bbGetNameWithParent();
1052     if (bbGetDescriptor()) 
1053       {
1054         return bbGetDescriptor()->GetFullTypeName() + ":" + bbGetName();
1055       }
1056     else 
1057       {
1058         return std::string(":") + bbGetName();
1059       }
1060   } 
1061   //=========================================================================
1062
1063   //==========================================================================
1064   std::string ComplexBlackBox::GetObjectName() const
1065   {
1066     return std::string("ComplexBlackBox '")+bbGetNameWithParent()
1067       +std::string("'");
1068   }
1069   //==========================================================================
1070   
1071   //==========================================================================
1072   std::string ComplexBlackBox::GetObjectInfo() const 
1073   {
1074     std::stringstream i;
1075     i << "  - "<<mBlackBoxMap.size() << " boxes / "
1076       <<mConnectionList.size() << " connections" << std::endl;
1077     return i.str();
1078   }
1079   //==========================================================================
1080
1081   //==========================================================================
1082   size_t  ComplexBlackBox::GetObjectSize() const 
1083   {
1084     size_t s = Superclass::GetObjectSize();
1085     s += ComplexBlackBox::GetObjectInternalSize();
1086     return s;
1087   }
1088   //==========================================================================
1089   //==========================================================================
1090   size_t  ComplexBlackBox::GetObjectInternalSize() const 
1091   {
1092     size_t s = sizeof(ComplexBlackBox);
1093     return s;
1094   }
1095   //==========================================================================
1096   //==========================================================================
1097   size_t  ComplexBlackBox::GetObjectRecursiveSize() const 
1098   {
1099     size_t s = Superclass::GetObjectRecursiveSize();
1100     s += ComplexBlackBox::GetObjectInternalSize();
1101     BlackBoxMapType::const_iterator i;
1102     for ( i = mBlackBoxMap.begin(); i != mBlackBoxMap.end(); ++i ) 
1103       {
1104         s += i->second->GetObjectRecursiveSize();
1105       }
1106     ConnectionListType::const_iterator j;
1107     for ( j = mConnectionList.begin(); 
1108           j != mConnectionList.end(); ++j ) 
1109       {
1110         s += (*j)->GetObjectRecursiveSize();
1111       }
1112     return s;
1113   }
1114   //==========================================================================
1115
1116 }