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