]> Creatis software - bbtk.git/blob - kernel/src/bbtkComplexBlackBox.cxx
* Major changes on IOStatus update / propagation
[bbtk.git] / kernel / src / bbtkComplexBlackBox.cxx
1 /*=========================================================================                                                                               
2   Program:   bbtk
3   Module:    $RCSfile: bbtkComplexBlackBox.cxx,v $
4   Language:  C++
5   Date:      $Date: 2008/12/08 12:54:09 $
6   Version:   $Revision: 1.22 $
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   //==================================================================
284   void ComplexBlackBox::bbSetModifiedStatus(BlackBoxInputConnector* c)
285   {
286     bbtkDebugMessage("modified",1,
287                         "==> ComplexBlackBox::bbSetModifiedStatus("
288                      <<c<<") ["<<bbGetFullName()<<"]"<<std::endl);
289
290     c->GetBlackBox()->bbSetModifiedStatus(c);
291
292   }
293   //==================================================================
294 */
295
296   //==================================================================
297   void ComplexBlackBox::bbAddToExecutionList( const std::string& name )
298   {
299         bbtkDebugMessageInc("Kernel",9,
300                         "ComplexBlackBox::bbAddToExecutionList(\""
301                         <<name<<"\") ["
302                         <<bbGetFullName()<<"]"<<std::endl);
303
304         mExecutionList.push_back( name );
305
306      bbtkDebugDecTab("Kernel",9);   
307
308   }
309   //==================================================================
310
311   //==================================================================
312   void ComplexBlackBox::bbBackwardUpdate(Connection::Pointer caller)
313   {
314     bbtkDebugMessageInc("process",3,
315                         "==> ComplexBlackBox::bbBackwardUpdate("
316                         <<(caller?caller->GetFullName():"0")<<") ["
317                         <<bbGetFullName()<<"]"<<std::endl);
318     //    bbtkInternalError("ComplexBlackBox::bbBackwardUpdate should never be called !");
319     
320     if (caller==0)
321       {
322         bbtkInternalError("ComplexBlackBox::bbBackwardUpdate called with caller=0");
323       }
324
325     /*
326     std::cout << "CBB BUP : "<<caller->GetBlackBoxFrom()->bbGetFullName()
327               <<"."<<caller->GetBlackBoxFromOutput()<<"----"
328               <<caller->GetOriginalBlackBoxFrom()->bbGetFullName()
329               <<"."<<caller->GetOriginalBlackBoxFromOutput()<<std::endl;
330     */
331       
332
333
334     //    IOStatus s = UPTODATE;
335     const BlackBoxDescriptor::OutputDescriptorMapType& omap 
336       = bbGetDescriptor()->GetOutputDescriptorMap(); 
337     BlackBoxDescriptor::OutputDescriptorMapType::const_iterator i 
338       = omap.find(caller->GetBlackBoxFromOutput());
339     if (i!=omap.end())
340       { 
341         // Cast the BBOutputDescriptor into a ComplexBBOutputDescriptor
342         ComplexBlackBoxOutputDescriptor* d = 
343           (ComplexBlackBoxOutputDescriptor*)i->second;
344         // Get the internal box 
345         BlackBox::Pointer b = bbUnsafeGetBlackBox ( d->GetTarget() );
346         // Calls BackwardUpdate on it
347         bbtkDebugMessageInc("process",4,"Internal box connected to output : "<<d->GetTarget()<<std::endl);
348         // Because internal box can also be a complex box we have to 
349         // temporarily change the connection BlackBoxFromOutput to the 
350         // mapped one
351         
352         //      std::string oldout = caller->GetBlackBoxFromOutput();
353         //      std::cout << "oldout = "<<oldout<<std::endl;
354         //      std::cout << "tmpout = "<<d->GetOutput()<<std::endl;
355         //      caller->SetBlackBoxFromOutput(d->GetOutput());
356         //
357         //Connection newcaller(*caller);
358         //newcaller.SetBlackBoxFromOutput(d->GetOutput());
359         //IOStatus s1 = b->bbBackwardUpdate(&newcaller);
360         //IOStatus s1 =
361         b->bbBackwardUpdate(caller);
362         //newcaller.Clear();
363         // restore old output
364         //      caller->SetBlackBoxFromOutput(oldout);
365
366         // ??? STATUS OF CBBs ???
367         // ??? Here it is only the final status of the boxes connected to the output 
368         //      if (s1==MODIFIED) s=MODIFIED;
369       }
370     else 
371       {
372         bbtkError("Connection '"<<caller->GetFullName()<<"' does not point to a valid output of the complex box !");
373       }
374
375     return; // s;
376     
377   }
378   //==================================================================
379
380
381   //==================================================================
382   Data ComplexBlackBox::bbGetOutput( const std::string &name )
383   {
384     bbtkDebugMessageInc("Data",7,
385                         "ComplexBlackBox::bbGetOutput(\""<<name<<"\") ["
386                         <<bbGetFullName()<<"]"<<std::endl);
387
388     ComplexBlackBoxOutputDescriptor* d = 
389       (ComplexBlackBoxOutputDescriptor*)
390       bbGetDescriptor()->GetOutputDescriptor(name);
391     
392     Data p = bbGetBlackBox(d->GetTarget())->bbGetOutput(d->GetOutput());
393
394
395     bbtkDebugDecTab("Data",7);
396     return p;
397   }
398   //==================================================================
399
400   //==================================================================
401   ///  Gets the input Data of a given name
402   Data ComplexBlackBox::bbGetInput( const std::string &name ) 
403   {
404     bbtkDebugMessageInc("Data",7,
405                         "ComplexBlackBox::bbGetInput(\""<<name<<"\") ["
406                         <<bbGetFullName()<<"]"<<std::endl);  
407
408     ComplexBlackBoxInputDescriptor* d = 
409       (ComplexBlackBoxInputDescriptor*)
410       bbGetDescriptor()->GetInputDescriptor(name);
411
412     Data p = bbGetBlackBox(d->GetTarget())->bbGetInput(d->GetInput());
413
414     bbtkDebugDecTab("Data",7);
415     return p;
416   }
417   //==================================================================
418
419   //==================================================================
420   ///  Sets the data of the output called <name>
421   void ComplexBlackBox::bbSetOutput( const std::string &name, Data data)
422   {
423     bbtkDebugMessageInc("Data",7,
424                         "ComplexBlackBox::bbSetOutput(\""<<name<<"\",data) ["
425                         <<bbGetFullName()<<"]"<<std::endl); 
426
427     ComplexBlackBoxOutputDescriptor* d = 
428       (ComplexBlackBoxOutputDescriptor*)
429       bbGetDescriptor()->GetOutputDescriptor(name);
430     
431     bbGetBlackBox(d->GetTarget())->bbSetOutput(d->GetOutput(),data);
432
433     bbtkDebugDecTab("Data",7);
434   }
435   //==================================================================
436   
437   //==================================================================
438   ///  Sets the data of the input called <name>
439   void ComplexBlackBox::bbSetInput( const std::string &name, Data data,
440                                     bool setModified)
441   {
442     bbtkDebugMessageInc("Data",7,
443                         "ComplexBlackBox::bbSetInput(\""<<name<<"\",data) ["
444                         <<bbGetFullName()<<"]"<<std::endl);  
445
446     ComplexBlackBoxInputDescriptor* d = (ComplexBlackBoxInputDescriptor*)
447       bbGetDescriptor()->GetInputDescriptor(name);
448
449     bbGetBlackBox(d->GetTarget())->bbSetInput(d->GetInput(),data,setModified);
450
451     bbtkDebugDecTab("Data",7);
452   }
453   //==================================================================
454
455  
456   //==================================================================
457   ///  Sets the data of the input called <name>
458   void ComplexBlackBox::bbBruteForceSetInputPointer( const std::string &name, 
459                                                      void* data,
460                                                      bool setModified)
461   {
462     bbtkDebugMessageInc("Data",7,
463                         "ComplexBlackBox::bbBruteForceSetInputPointer('"
464                         <<name<<"',"<<data<<") ["
465                         <<bbGetFullName()<<"]"<<std::endl);  
466
467     ComplexBlackBoxInputDescriptor* d = (ComplexBlackBoxInputDescriptor*)
468       bbGetDescriptor()->GetInputDescriptor(name);
469
470     bbGetBlackBox(d->GetTarget())->bbBruteForceSetInputPointer(d->GetInput(),
471                                                                data,
472                                                                setModified);
473
474     bbtkDebugDecTab("Data",7);
475   }
476   //==================================================================
477
478   //=========================================================================
479   /// Connects the input <name> to the connection c
480   void ComplexBlackBox::bbConnectInput( const std::string& name, Connection* c)
481   {
482     bbtkDebugMessage("connection",2,
483                      "==> ComplexBlackBox::bbConnectInput(\""
484                      <<name<<"\","<<c->GetFullName()<<") ["
485                      <<bbGetFullName()<<"]"
486                      <<std::endl);       
487     
488    ComplexBlackBoxInputDescriptor* d = (ComplexBlackBoxInputDescriptor*)
489       bbGetDescriptor()->GetInputDescriptor(name);
490
491
492    BlackBox::Pointer t = bbGetBlackBox(d->GetTarget());
493
494    bbtkDebugMessage("connection",2," - Target = "<<d->GetTarget()<<" = "<<t->bbGetFullName()<<std::endl);
495
496    c->SetBlackBoxTo(t);
497    c->SetBlackBoxToInput(d->GetInput());
498
499    bbtkDebugMessage("connection",2," - New conn = "<<c->GetFullName()<<std::endl);
500    t->bbConnectInput(d->GetInput(),c);
501
502    bbtkDebugMessage("connection",2,
503                      "<== ComplexBlackBox::bbConnectInput(\""
504                      <<name<<"\","<<c->GetFullName()<<") ["
505                      <<bbGetFullName()<<"]"
506                      <<std::endl);       
507   }
508   //=========================================================================
509
510
511   //=========================================================================  
512   /// Connects the output <name> to the connection c
513   void ComplexBlackBox::bbConnectOutput( const std::string& name, Connection* c)
514   {
515     bbtkDebugMessage("connection",2,
516                      "==> ComplexBlackBox::bbConnectOutput(\""
517                      <<name<<"\","<<c->GetFullName()<<") ["
518                      <<bbGetFullName()<<"]"<<std::endl);       
519
520    ComplexBlackBoxOutputDescriptor* d = (ComplexBlackBoxOutputDescriptor*)
521       bbGetDescriptor()->GetOutputDescriptor(name);
522
523    BlackBox::Pointer t = bbGetBlackBox(d->GetTarget());
524  
525   bbtkDebugMessage("connection",2," - Target = "<<d->GetTarget()<<" = "<<t->bbGetFullName()<<std::endl);
526
527    c->SetBlackBoxFrom(t);
528    c->SetBlackBoxFromOutput(d->GetOutput());
529
530    bbtkDebugMessage("connection",2," - New conn = "<<c->GetFullName()<<std::endl);
531
532    t->bbConnectOutput(d->GetOutput(),c);
533   
534     bbtkDebugMessage("connection",2,
535                      "<== ComplexBlackBox::bbConnectOutput(\""
536                      <<name<<"\","<<c->GetFullName()<<") ["
537                      <<bbGetFullName()<<"]"<<std::endl);       
538   }
539   //=========================================================================
540
541
542   //==================================================================
543   /// Adds the black box to the complex box
544   void ComplexBlackBox::bbAddBlackBox( BlackBox::Pointer b)
545   {
546     bbtkDebugMessageInc("Kernel",7,
547                         "ComplexBlackBox::AddBlackBox(\""<<b->bbGetName()
548                         <<"\") ["
549                         <<bbGetFullName()<<"]"<<std::endl);  
550     
551     if ( bbUnsafeGetBlackBox(b->bbGetName()) ) 
552       {
553         bbtkError("a black box called \""<<b->bbGetName()
554                   <<"\" already exists");
555       }
556     b->bbSetParent(GetThisPointer<ComplexBlackBox>());
557     mBlackBoxMap[b->bbGetName()] = b;
558
559     bbtkDebugDecTab("Kernel",7);
560   }
561   //==================================================================
562
563   //==================================================================
564   /// Adds the black box to the complex box (unsafe)
565   void ComplexBlackBox::bbUnsafeAddBlackBox( BlackBox::Pointer b)
566   {
567     bbtkDebugMessageInc("Kernel",7,
568                         "ComplexBlackBox::UnsafeAddBlackBox(\""<<b->bbGetName()
569                         <<"\") ["
570                         <<bbGetFullName()<<"]"<<std::endl);  
571     
572     b->bbSetParent(GetThisPointer<ComplexBlackBox>());
573     mBlackBoxMap[b->bbGetName()] = b;
574
575     bbtkDebugDecTab("Kernel",7);
576   }
577   //==================================================================
578
579   //==================================================================
580   /// Removes the black box from the complex box
581   void ComplexBlackBox::bbRemoveBlackBox( const std::string& name, 
582                                           bool remove_connections )
583   {
584     bbtkDebugMessageInc("Kernel",7,
585                         "ComplexBlackBox::RemoveBlackBox(\""<<name<<"\") ["
586                         <<bbGetFullName()<<"]"<<std::endl);  
587
588     BlackBoxMapType::iterator i = mBlackBoxMap.find(name);
589     if ( i == mBlackBoxMap.end() ) 
590       {
591         bbtkError("the black box \""<<name<<"\" does not exist");
592       }
593     BlackBox::WeakPointer p = i->second;
594     
595     if (remove_connections)
596       {
597         ConnectionListType::const_iterator j;
598         for ( j = mConnectionList.begin(); 
599               j != mConnectionList.end(); ++j ) 
600           {
601             (*j)->Check();
602           }
603       }
604     if (p.use_count()!=1) 
605       {
606         bbtkError("the black box \""<<name<<"\" is still connected");
607       }
608     
609     mBlackBoxMap.erase(i);
610     
611
612     // Unload orphan dl packages 
613     Package::UnLoadReleasedDynamicallyLoadedPackages();
614
615     bbtkDebugDecTab("Kernel",7);
616   }
617   //==================================================================
618
619   //==================================================================
620   /// Adds the connection to the complex box
621   void ComplexBlackBox::bbAddConnection( Connection::Pointer c)
622   {
623     bbtkDebugMessageInc("Kernel",7,
624                         "ComplexBlackBox::AddConnection(\""<<"..."<<"\") ["
625                         <<bbGetFullName()<<"]"<<std::endl);  
626
627     mConnectionList.push_back(c);
628
629     bbtkDebugDecTab("Kernel",7);
630   }
631   //==================================================================
632   //    void RemoveConnection( );
633
634   //==================================================================
635   /// Returns the black box with name <name>
636   BlackBox::Pointer ComplexBlackBox::bbGetBlackBox( const std::string& name )
637   {
638     bbtkDebugMessageInc("Kernel",9,
639                         "ComplexBlackBox::GetBlackBox(\""<<name<<"\") ["
640                         <<bbGetFullName()<<"]"<<std::endl);  
641
642     BlackBoxMapType::iterator i = mBlackBoxMap.find(name);
643     if ( i == mBlackBoxMap.end() ) 
644       {
645         bbtkError("the black box \""<<name<<"\" does not exist");
646       }
647
648     bbtkDebugDecTab("Kernel",9);
649     return i->second;
650   }
651   //==================================================================
652
653   //==================================================================
654   /// Returns the black box with name <name> : does not throw an exception 
655   /// if it does not exist but return a null pointer
656   BlackBox::Pointer ComplexBlackBox::bbUnsafeGetBlackBox( const std::string& name )
657   {
658     bbtkDebugMessageInc("Kernel",9,
659                         "ComplexBlackBox::UnsafeGetBlackBox(\""<<name<<"\") ["
660                         <<bbGetFullName()<<"]"
661                         <<std::endl);  
662
663     BlackBoxMapType::iterator i = mBlackBoxMap.find(name);
664     if ( i == mBlackBoxMap.end() ) 
665       {
666         bbtkDebugDecTab("Kernel",9);
667         return BlackBox::Pointer();
668       }
669
670     bbtkDebugDecTab("Kernel",9);
671     return i->second;
672     
673   }
674   //==================================================================
675
676   //==================================================================
677   void ComplexBlackBox::bbPrintBlackBoxes()
678   {
679     bbtkDebugMessageInc("Kernel",9,
680                         "ComplexBlackBox::PrintBlackBoxes() ["
681                         <<bbGetFullName()<<"]"
682                         <<std::endl);  
683
684     BlackBoxMapType::iterator i;
685     for ( i = mBlackBoxMap.begin(); i != mBlackBoxMap.end(); ++i ) 
686       {
687         bbtkMessage("Help",1,i->second->bbGetFullName()<<std::endl);
688       }
689
690     bbtkDebugDecTab("Kernel",9);
691   }
692   //==================================================================
693
694
695  
696   //=========================================================================
697   /// Virtual
698   void ComplexBlackBox::bbWriteDotInputOutputName(FILE *ff,bool inputoutput,int detail, int level)
699   {
700     if (inputoutput)
701       {
702         fprintf(ff,"%s_IN_%p",bbGetTypeName().c_str(),this);
703       } else {
704       fprintf(ff,"%s_OUT_%p",bbGetTypeName().c_str(),this);
705     } // if inputoutput
706   }
707   //=========================================================================
708
709
710   //=========================================================================
711   BlackBox::Pointer ComplexBlackBox::bbFindBlackBox(const std::string &blackboxname)
712   {
713     BlackBox::Pointer blackbox;
714     std::string subname="";
715     std::string restname="";
716     std::string delimiters(">");
717     // Skip delimiters at beginning.
718     std::string::size_type lastPos = blackboxname.find_first_not_of(delimiters, 0);
719     // Find first "non-delimiter".
720     std::string::size_type pos     = blackboxname.find_first_of(delimiters, lastPos);
721             
722     // Found a token, add it to the vector.
723     subname = blackboxname.substr(lastPos, pos - lastPos);
724     restname = blackboxname.substr(lastPos+pos - lastPos+1, 999);
725
726     if (restname==subname)
727     {
728            restname="";
729     }
730
731     BlackBoxMapType::iterator i = mBlackBoxMap.find(subname);
732     if ( i != mBlackBoxMap.end() ) 
733     {
734        blackbox = i->second;
735        if (restname!="")
736             {
737              blackbox = blackbox->bbFindBlackBox(restname);
738             }
739     }
740     return blackbox;
741   }
742   //=========================================================================
743
744   //=========================================================================
745   void ComplexBlackBox::bbInsertHTMLGraph(  std::ofstream& s, 
746                                             int detail, 
747                                             int level,
748                                             bool instanceOrtype,
749                                             const std::string& output_dir,
750                                             bool relative_link )
751   {
752     
753     std::string directory(output_dir);
754
755     if (output_dir.length() == 0) 
756     {
757            // Don't pollute the file store with  "temp_dir" directories ... 
758            std::string default_temp_dir = ConfigurationFile::GetInstance().Get_default_temp_dir();
759            directory =  default_temp_dir + "/" + "temp_dir";
760     }
761     
762     std::string simplefilename  (this->bbGetTypeName()+"_"+this->bbGetName());
763     std::string simplefilename_png (simplefilename+".png");
764     std::string filename           (directory+"/"+simplefilename);
765     std::string filename_png       (filename+".png");
766     std::string filename_cmap      (filename+".cmap");
767     std::string filename_dot       (filename+".dot");
768
769     std::string filename_png2   ("\""   + filename_png  + "\"");
770     std::string filename_cmap2  ("\""   + filename_cmap + "\"");
771     std::string filename_dot2   ("\""   + filename_dot  + "\"");
772     
773
774     std::string command1 ("dot -T png -o "  
775                           + filename_png2  + " " + filename_dot2);
776     std::string command1a("dot -T cmap -o " 
777                           + filename_cmap2 + " " + filename_dot2);
778
779     // 1. Generating .dot file
780     FILE *ff;
781     ff = fopen(filename_dot.c_str(),"w");
782     fprintf(ff,"digraph bbtk_graph{\n");
783     fprintf(ff,"rankdir=LR%s\n",";");
784     fprintf(ff,"node [shape=record]%s\n",";");
785
786     this->bbWriteDotFileBlackBox(ff,
787                                  GetThisPointer<ComplexBlackBox>(),
788                                  detail,level,
789                                  instanceOrtype,
790                                  relative_link );
791
792     fprintf(ff,"}\n");
793     fclose(ff);
794
795     // 2. Executing .dot file -> png
796     system( command1.c_str() );   
797     // 3. Executing .dot file -> cmap
798     system( command1a.c_str() );  
799     
800     // 4. HTML code insertion
801     // 4.1 image
802     (s) << "<center><img src=\"" << simplefilename_png 
803          <<   "\" border=\"0\" usemap=\"#map_"<< simplefilename 
804          <<"\" alt=\"\"></center>\n";
805
806     // 4.2 map
807     (s) << "<map name=\"map_"<< simplefilename <<"\">\n";
808     FILE *ff2;
809     char c;
810     ff2=fopen(filename_cmap.c_str(),"r");
811     while (!feof(ff2))
812     {
813            c=fgetc(ff2);
814            if (c!=-1)
815            {
816               (s) << c;
817            }
818     }
819     (s) << "</map>\n\n";
820     
821     // End
822   }
823   //=========================================================================
824
825
826   //=========================================================================
827   /// Write Graphviz-dot description in file 
828   void ComplexBlackBox::bbWriteDotFileBlackBox(FILE *ff,
829                                                BlackBox::Pointer parentblackbox, 
830                                                int detail, int level,
831                                                bool instanceOrtype,
832                                                bool relative_link )   
833   {
834     std::string tmp1;
835     std::string valueStr("");
836     Package::Pointer package = this->bbGetDescriptor()->GetPackage(); 
837
838     if (package!=NULL)
839     {
840       if (relative_link)
841              tmp1 = this->bbGetDescriptor()->GetPackage()->GetDocRelativeURL();
842            else 
843              tmp1 = this->bbGetDescriptor()->GetPackage()->GetDocURL();
844     } 
845     else 
846     {
847            tmp1 = "Caspitas";
848     }
849
850     std::string tmp2=bbGetTypeName();
851     std::string url(tmp1 + "#" + tmp2 );        
852     fprintf( ff , "subgraph cluster_%s_%p {\n",bbGetName().c_str(),this);
853
854     if (!(   (bbGetTypeName()=="workspace") && (bbGetName()=="workspacePrototype")) )
855     {
856            fprintf( ff , "  URL = \"%s\" %s",url.c_str(),";");
857     }
858
859     std::string boxname="["+bbGetTypeName()+"]";
860     if (GetThisPointer<ComplexBlackBox>()!=parentblackbox)
861     {
862        if (detail==0)
863             {
864           boxname=bbGetName();
865        } 
866        else 
867        {
868           boxname = bbGetName();
869           boxname = boxname + "   [" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "]";
870             }
871
872     }
873     fprintf( ff , "  label = \"%s\"%s\n",  boxname.c_str() ,";");
874
875
876
877     //  fprintf( ff , "  style=filled%s\n",";");
878     //  fprintf( ff , "  color=grey%s\n",";");
879     fprintf( ff , "  node [style=filled]%s\n",";");
880     fprintf( ff , "  fillcolor=grey%s\n",";");
881     fprintf( ff , "  edge [color=blue]%s\n",";");
882
883
884     // Labels Salida
885     std::string labelStr1;
886     std::string labelStr2;
887     labelStr1 = boxname + "\\n(output)" ; 
888     labelStr2 = " | {{ ";
889     bool tmp; 
890     tmp=false;
891     OutputConnectorMapType::iterator i;
892
893     const BlackBoxDescriptor::OutputDescriptorMapType& omap = this->bbGetDescriptor()->GetOutputDescriptorMap();
894     BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;      
895     for ( o = omap.begin();  o != omap.end(); ++o ) 
896       {
897         if (tmp==true)
898           {
899             labelStr2=labelStr2+" | ";
900           }
901         tmp=true;
902         if (instanceOrtype==true)
903           {
904             valueStr = this->bbGetOutputAsString(o->second->GetName()/*
905                                                                    ,factory*/) + " = ";
906           } 
907         labelStr2=labelStr2+"<"+o->second->GetName().c_str()+"> " + valueStr + o->second->GetName().c_str();
908       }
909
910     labelStr2 = labelStr2+ " } }";
911
912
913
914     if (detail==1)
915       {
916         labelStr1 = labelStr1 + labelStr2;
917       }
918
919     if (tmp){
920       fprintf(ff,"  " );
921       bbWriteDotInputOutputName(ff,false,detail,level);
922       fprintf( ff , " [shape=record, style=filled,fillcolor=grey,color=red,label=\"%s\"]%s\n",labelStr1.c_str(),";" );
923     }
924
925
926     // label Entrada
927     labelStr1 = boxname + "\\n(input)" ; 
928     labelStr2 = " | {{ "; 
929     tmp=false;
930     InputConnectorMapType::iterator ii;
931
932     const BlackBoxDescriptor::InputDescriptorMapType& imap = this->bbGetDescriptor()->GetInputDescriptorMap();  
933     BlackBoxDescriptor::InputDescriptorMapType::const_iterator iii;
934     for ( iii = imap.begin();  iii != imap.end(); ++iii ) 
935       {
936         if (tmp==true)
937           {
938             labelStr2=labelStr2+" | ";
939           }
940         tmp=true;
941         if (instanceOrtype==true)
942           {
943             valueStr = this->bbGetInputAsString(iii->second->GetName()/*,factory*/) + " = ";
944           } 
945         labelStr2=labelStr2+"<"+iii->second->GetName().c_str()+"> " + valueStr + iii->second->GetName().c_str();
946       }
947
948
949     labelStr2 = labelStr2+ " } }";
950     if (detail==1)
951       {
952         labelStr1 = labelStr1 + labelStr2;
953       }
954     if (tmp){
955       fprintf(ff,"  " );
956       bbWriteDotInputOutputName(ff,true,detail,level);
957       fprintf( ff , " [shape=record, style=filled,fillcolor=grey,color=red,label=\"%s\"]%s\n",labelStr1.c_str(),";" );
958     }
959
960
961     // Body
962     BlackBoxMapType::iterator j;
963     for ( j = mBlackBoxMap.begin(); j != mBlackBoxMap.end(); ++j ) 
964       {
965         if (level>-1)
966           {
967             j->second->bbWriteDotFileBlackBox(ff,
968                                               parentblackbox,
969                                               detail,
970                                               level-1,
971                                               instanceOrtype,
972                                               relative_link);
973           }
974       }
975
976     fprintf( ff , "}\n\n");
977
978     fprintf( ff , "  edge[color=blue]%s\n",";");
979
980     if (level>-1)
981       {
982         // Relation Input  with the inside BlackBox of the this ComplexBlackbox
983         ComplexBlackBoxDescriptor::InputDescriptorMapType::iterator xx;
984         ComplexBlackBoxDescriptor::InputDescriptorMapType idmt=bbGetDescriptor()->GetInputDescriptorMap();
985         for ( xx = idmt.begin(); xx != idmt.end(); ++xx ) 
986           {
987             ComplexBlackBoxInputDescriptor *cbbid = (ComplexBlackBoxInputDescriptor*)xx->second;
988
989             fprintf(ff,"  ");
990             bbWriteDotInputOutputName(ff,true,detail,level);
991             if (detail==1)
992               {
993                 fprintf(ff,":%s",cbbid->GetName().c_str() );
994               }
995             fprintf(ff,"->" );
996             BlackBox::Pointer bb = bbGetBlackBox( cbbid->GetTarget() ); 
997             bb->bbWriteDotInputOutputName(ff,true,detail,level);
998             if (detail==1)
999               {
1000                 fprintf(ff,":%s \n", cbbid->GetInput().c_str() );
1001               }
1002           }// for xx
1003
1004
1005
1006         fprintf(ff,"\n \n");
1007
1008
1009
1010         // Relation Output ComplexBlackBox
1011         ComplexBlackBoxDescriptor::OutputDescriptorMapType::iterator yy;
1012         ComplexBlackBoxDescriptor::OutputDescriptorMapType odmt=bbGetDescriptor()->GetOutputDescriptorMap();
1013         for ( yy = odmt.begin(); yy != odmt.end(); ++yy ) 
1014           {
1015             ComplexBlackBoxOutputDescriptor *cbbod = (ComplexBlackBoxOutputDescriptor*)yy->second;
1016             fprintf(ff,"  ");
1017             BlackBox::Pointer bb = bbGetBlackBox( cbbod->GetTarget() ); 
1018             bb->bbWriteDotInputOutputName(ff,false,detail,level);
1019             if (detail==1)
1020               {
1021                 fprintf(ff,":%s", cbbod->GetOutput().c_str() );
1022               }
1023             fprintf(ff,"->" );
1024             bbWriteDotInputOutputName(ff,false,detail,level);
1025             if (detail==1)
1026               {
1027                 fprintf(ff,":%s",cbbod->GetName().c_str() );
1028               }
1029             fprintf(ff,"\n");
1030           } // for yy
1031
1032       } // if level
1033
1034
1035
1036         // Relation from the out side of this ComplexBlackBox with its Inputs
1037     if (GetThisPointer<ComplexBlackBox>()!=parentblackbox) {
1038       for ( ii = bbGetInputConnectorMap().begin(); 
1039             ii != bbGetInputConnectorMap().end(); ++ii ) 
1040         {
1041           if (ii->second)
1042             {
1043               Connection* con = ii->second->GetConnection();
1044               if (con!=NULL){
1045                 BlackBox::Pointer a=con->GetOriginalBlackBoxFrom();
1046                 BlackBox::Pointer b=con->GetOriginalBlackBoxTo();
1047                 fprintf(ff,"  ");
1048                 a->bbWriteDotInputOutputName(ff,false,detail,level);
1049                 if (detail==1)
1050                   {
1051                     fprintf(ff,":%s",con->GetOriginalBlackBoxFromOutput().c_str());
1052                   }
1053                 fprintf(ff,"->");
1054                 b->bbWriteDotInputOutputName(ff,true,detail,level);
1055                 if (detail==1)
1056                   {
1057                     fprintf(ff,":%s",con->GetOriginalBlackBoxToInput().c_str());
1058                   }
1059                 fprintf(ff,"%s\n",";");
1060               } // if con
1061             } // if second
1062         } // for
1063     } // if parentblackbox
1064   }
1065   //=========================================================================
1066   
1067
1068
1069
1070   /*
1071
1072   //=======================================================================
1073   /// Generates the list of the packages of which its depends 
1074   /// (cause an internal box belongs to it)
1075   void ComplexBlackBox::GetPackagesDependencies(std::vector<Package*>& deps)
1076   {
1077     deps.clear;
1078     BlackBoxMapType::iterator i;
1079     for ( i = mBlackBoxMap.begin(); i != mBlackBoxMap.end(); ++i ) 
1080       {
1081         deps.push_back(i->second->bbGetDescriptor()->GetPackage());
1082       }
1083
1084   }
1085   //=======================================================================
1086   */
1087
1088   //=======================================================================
1089   void ComplexBlackBox::Check(bool recursive)
1090   {
1091      bbtkMessage("debug",1,"**** Checking Complex Black Box "<<(void*)this
1092                  <<" ["<<bbGetFullName()<<"]"<<std::endl);
1093      
1094      BlackBoxMapType::const_iterator i;
1095      for ( i = mBlackBoxMap.begin(); i != mBlackBoxMap.end(); ++i ) 
1096        {
1097          i->second->Check(recursive);
1098        }
1099      ConnectionListType::const_iterator j;
1100      for ( j = mConnectionList.begin(); 
1101            j != mConnectionList.end(); ++j ) 
1102        {
1103          (*j)->Check();
1104        }
1105      bbtkMessage("debug",1,"**** Checking Complex Black Box "<<(void*)this
1106                  <<" ["<<bbGetFullName()<<"] ... OK"<<std::endl);
1107   
1108   }
1109   //=======================================================================
1110
1111   //=========================================================================
1112   /// Returns the name with the name of the parent prepended if any
1113   std::string ComplexBlackBox::bbGetNameWithParent() const
1114   {
1115     if (!IsAPrototype()) return BlackBox::bbGetNameWithParent();
1116     if (bbGetDescriptor()) 
1117       {
1118         return bbGetDescriptor()->GetFullTypeName() + ":" + bbGetName();
1119       }
1120     else 
1121       {
1122         return std::string(":") + bbGetName();
1123       }
1124   } 
1125   //=========================================================================
1126
1127   //==========================================================================
1128   std::string ComplexBlackBox::GetObjectName() const
1129   {
1130     return std::string("ComplexBlackBox '")+bbGetNameWithParent()
1131       +std::string("'");
1132   }
1133   //==========================================================================
1134   
1135   //==========================================================================
1136   std::string ComplexBlackBox::GetObjectInfo() const 
1137   {
1138     std::stringstream i;
1139     i << "  - "<<mBlackBoxMap.size() << " boxes / "
1140       <<mConnectionList.size() << " connections" << std::endl;
1141     return i.str();
1142   }
1143   //==========================================================================
1144
1145   //==========================================================================
1146   size_t  ComplexBlackBox::GetObjectSize() const 
1147   {
1148     size_t s = Superclass::GetObjectSize();
1149     s += ComplexBlackBox::GetObjectInternalSize();
1150     return s;
1151   }
1152   //==========================================================================
1153   //==========================================================================
1154   size_t  ComplexBlackBox::GetObjectInternalSize() const 
1155   {
1156     size_t s = sizeof(ComplexBlackBox);
1157     return s;
1158   }
1159   //==========================================================================
1160   //==========================================================================
1161   size_t  ComplexBlackBox::GetObjectRecursiveSize() const 
1162   {
1163     size_t s = Superclass::GetObjectRecursiveSize();
1164     s += ComplexBlackBox::GetObjectInternalSize();
1165     BlackBoxMapType::const_iterator i;
1166     for ( i = mBlackBoxMap.begin(); i != mBlackBoxMap.end(); ++i ) 
1167       {
1168         s += i->second->GetObjectRecursiveSize();
1169       }
1170     ConnectionListType::const_iterator j;
1171     for ( j = mConnectionList.begin(); 
1172           j != mConnectionList.end(); ++j ) 
1173       {
1174         s += (*j)->GetObjectRecursiveSize();
1175       }
1176     return s;
1177   }
1178   //==========================================================================
1179
1180 }