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