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