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