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