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