]> Creatis software - bbtk.git/blob - kernel/src/bbtkConnection.cxx
*** empty log message ***
[bbtk.git] / kernel / src / bbtkConnection.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   bbtk
4   Module:    $RCSfile: bbtkConnection.cxx,v $
5   Language:  C++
6   Date:      $Date: 2008/07/25 07:44:12 $
7   Version:   $Revision: 1.14 $
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  *\file
20  *\brief Class bbtk::Connection
21  */
22
23 #include "bbtkConnection.h"
24 #include "bbtkFactory.h"
25 #include "bbtkBlackBox.h"
26 #include "bbtkMessageManager.h"
27
28 namespace bbtk
29 {
30   //==================================================================
31   Connection::Pointer Connection::New(BlackBox::Pointer from, 
32                                       const std::string& output,
33                                       BlackBox::Pointer to, 
34                                       const std::string& input ,
35                                       const Factory::Pointer f  )
36   {
37     bbtkDebugMessage("object",1,"##> Connection::Connection(\""
38                      <<from->bbGetName()<<"\",\""<<output<<"\",\""
39                      <<to->bbGetName()<<"\",\""<<input<<"\")"
40                      <<std::endl);
41     Connection::Pointer p = 
42       MakePointer(new Connection(from,output,to,input,f));
43     bbtkDebugMessage("object",1,"<## Connection::Connection(\""
44                      <<from->bbGetName()<<"\",\""<<output<<"\",\""
45                      <<to->bbGetName()<<"\",\""<<input<<"\")"
46                      <<std::endl);
47     return p;
48   }
49   //==================================================================
50
51   //==================================================================
52   /// Ctor with the black box from and to and their input and output.
53 /// Check the input and output compatibility
54 Connection::Connection(BlackBox::Pointer from, const std::string& output,
55                        BlackBox::Pointer to, const std::string& input ,
56                        const Factory::Pointer f  )
57     : mAdaptor(),
58       mFactory(f),
59       mFromAny(false),
60       mToAny(false)
61   {
62     bbtkDebugMessage("object",2,"==> Connection::Connection(\""
63                      <<from->bbGetName()<<"\",\""<<output<<"\",\""
64                      <<to->bbGetName()<<"\",\""<<input<<"\")"
65                      <<std::endl);    
66
67     bbtkDebugMessage("connection",1,"==> Connection::Connection(\""
68                      <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
69                      <<to->bbGetFullName()<<"\",\""<<input<<"\")"
70                      <<std::endl);    
71
72     
73
74     if (! from->bbHasOutput(output) )
75       {
76         bbtkError("The box \""<<from->bbGetTypeName()<<
77                   "\" has no output \""<<output<<"\"");
78       }
79     if (! to->bbHasInput(input) )
80       {
81         bbtkError("The box \""<<to->bbGetTypeName()<<
82                   "\" has no input \""<<input<<"\"");
83       } 
84
85     if (to->bbGetInputConnectorMap().find(input)->second->IsConnected())
86       {
87         bbtkError("The input \""<<input<<"\" of the box \""<<to->bbGetName()
88                   <<"\" is already connected");
89       }
90     
91     //  std::string t1 ( from->bbGetOutputType(output).name() );
92     //   std::string t2 ( to->bbGetInputType(input).name() );
93     // if  //( t1 != t2 ) 
94     if ( from->bbGetOutputType(output) !=
95          to->bbGetInputType(input) )
96       {
97         if ( from->bbGetOutputType(output) == typeid(Data) )
98           {
99             bbtkWarning("Connection '"
100                         <<GetFullName()
101                         <<"' : '"<<from->bbGetName()<<"."<<output
102                         <<"' is of type <"
103                         <<HumanTypeName<Data>()
104                         <<"> : type compatibility with '"
105                         <<to->bbGetName()<<"."<<input
106                         <<"' will be resolved at run time"
107                         );
108             mFromAny = true;
109           }
110         else if (  to->bbGetInputType(input) == typeid(Data) )
111           {   
112             bbtkDebugMessage("Kernel",8," -> '"<<input<<"' type is "
113                              <<TypeName<Data>()<<" : can receive any data"
114                              <<std::endl);
115             mToAny = true;
116           }
117         else 
118           {
119             //   std::cout << "Adaptive connection "<<std::endl;
120             std::string name;
121             name = from->bbGetName() + "." + output + "-" 
122               + to->bbGetName() + "." + input; 
123             mAdaptor = mFactory.lock()
124               ->NewAdaptor(from->bbGetOutputType(output),
125                            to->bbGetInputType(input),
126                            name);
127             if (!mAdaptor)  
128               {  
129                 bbtkError("did not find any <"
130                           <<TypeName(from->bbGetOutputType(output))
131                           <<"> to <"
132                           <<TypeName(to->bbGetInputType(input))
133                           <<"> adaptor");
134               } 
135           }
136       }
137
138
139     mFrom = from;
140     mOriginalFrom = from;
141     mTo = to;
142     mOriginalTo = to;
143     mInput = mOriginalInput = input;
144     mOutput = mOriginalOutput = output;
145
146      // Lock this pointer !!!
147     //Pointer p = MakePointer(this,true);
148     from->bbConnectOutput(output,this);
149     to->bbConnectInput(input,this);
150
151     
152     bbtkDebugMessage("connection",1,"<== Connection::Connection(\""
153                      <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
154                      <<to->bbGetFullName()<<"\",\""<<input<<"\")"
155                      <<std::endl);    
156
157     bbtkDebugMessage("object",2,"==> Connection::Connection(\""
158                      <<from->bbGetName()<<"\",\""<<output<<"\",\""
159                      <<to->bbGetName()<<"\",\""<<input<<"\")"
160                      <<std::endl);    
161   }
162  //==================================================================
163  
164   //==================================================================
165   Connection::Pointer Connection::New(BlackBox::Pointer from, 
166                                       const std::string& output,
167                                       BlackBox::Pointer to, 
168                                       const std::string& input )
169   {
170     bbtkDebugMessage("object",1,"##> Connection::Connection(\""
171                      <<from->bbGetName()<<"\",\""<<output<<"\",\""
172                      <<to->bbGetName()<<"\",\""<<input<<"\")"
173                      <<std::endl);
174     Connection::Pointer p = 
175       MakePointer(new Connection(from,output,to,input));
176     bbtkDebugMessage("object",1,"<## Connection::Connection(\""
177                      <<from->bbGetName()<<"\",\""<<output<<"\",\""
178                      <<to->bbGetName()<<"\",\""<<input<<"\")"
179                      <<std::endl);
180     return p;
181   }
182   //==================================================================
183
184   //==================================================================
185   /// Ctor with the black box from and to and their input and output.
186 /// Check the input and output compatibility
187 Connection::Connection(BlackBox::Pointer from, const std::string& output,
188                        BlackBox::Pointer to, const std::string& input )
189   : mAdaptor(),
190       mFactory(),
191       mFromAny(false),
192       mToAny(false)
193   {
194     bbtkDebugMessage("object",2,"==> Connection::Connection(\""
195                      <<from->bbGetName()<<"\",\""<<output<<"\",\""
196                      <<to->bbGetName()<<"\",\""<<input<<"\")"
197                      <<std::endl);    
198
199     bbtkDebugMessage("connection",1,"==> Connection::Connection(\""
200                      <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
201                      <<to->bbGetFullName()<<"\",\""<<input<<"\")"
202                      <<std::endl);    
203
204     
205
206     if (! from->bbHasOutput(output) )
207       {
208         bbtkError("The box \""<<from->bbGetTypeName()<<
209                   "\" has no output \""<<output<<"\"");
210       }
211     if (! to->bbHasInput(input) )
212       {
213         bbtkError("The box \""<<to->bbGetTypeName()<<
214                   "\" has no input \""<<input<<"\"");
215       } 
216
217     if (to->bbGetInputConnectorMap().find(input)->second->IsConnected())
218       {
219         bbtkError("The input \""<<input<<"\" of the box \""<<to->bbGetName()
220                   <<"\" is already connected");
221       }
222     
223     //  std::string t1 ( from->bbGetOutputType(output).name() );
224     //   std::string t2 ( to->bbGetInputType(input).name() );
225     // if  //( t1 != t2 ) 
226     if ( from->bbGetOutputType(output) !=
227          to->bbGetInputType(input) )
228       {
229         if ( from->bbGetOutputType(output) == typeid(Data) )
230           {
231             bbtkWarning("Connection '"
232                         <<GetFullName()
233                         <<"' : '"<<from->bbGetName()<<"."<<output
234                         <<"' is of type <"
235                         <<HumanTypeName<Data>()
236                         <<"> : type compatibility with '"
237                         <<to->bbGetName()<<"."<<input
238                         <<"' will be resolved at run time"
239                         );
240             mFromAny = true;
241           }
242         else if (  to->bbGetInputType(input) == typeid(Data) )
243           {   
244             bbtkDebugMessage("Kernel",8," -> '"<<input<<"' type is "
245                              <<TypeName<Data>()<<" : can receive any data"
246                              <<std::endl);
247             mToAny = true;
248           }
249         else 
250           {
251             bbtkError("Connection created between different types without Factory provided");
252           }
253       }
254
255
256     mFrom = from;
257     mOriginalFrom = from;
258     mTo = to;
259     mOriginalTo = to;
260     mInput = mOriginalInput = input;
261     mOutput = mOriginalOutput = output;
262
263      // Lock this pointer !!!
264     //Pointer p = MakePointer(this,true);
265     from->bbConnectOutput(output,this);
266     to->bbConnectInput(input,this);
267
268     
269     bbtkDebugMessage("connection",1,"<== Connection::Connection(\""
270                      <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
271                      <<to->bbGetFullName()<<"\",\""<<input<<"\")"
272                      <<std::endl);    
273
274     bbtkDebugMessage("object",2,"==> Connection::Connection(\""
275                      <<from->bbGetName()<<"\",\""<<output<<"\",\""
276                      <<to->bbGetName()<<"\",\""<<input<<"\")"
277                      <<std::endl);    
278   }
279  //==================================================================
280  
281   //==================================================================
282   /// Dtor 
283   Connection::~Connection()
284   {
285     bbtkDebugMessage("object",2,
286                      "==> Connection::~Connection() ["
287                      <<GetFullName()<<"]"<<std::endl);
288
289     if (mAdaptor) mAdaptor.reset();
290     if (mFrom!=0) 
291       {
292         mFrom->bbDisconnectOutput(mOutput,this);
293         //                                GetThisPointer<Connection>());
294         mFrom.reset();
295       }
296     else 
297       {
298         bbtkInternalError("Connection::~Connection() : invalid initial box pointer");
299       }
300     if (mTo!=0) 
301       {
302         mTo->bbDisconnectInput(mInput,this);//   GetThisPointer<Connection>());
303         mTo.reset();
304       }
305     else 
306       {
307         bbtkInternalError("Connection::~Connection() : invalid final box pointer");
308       }
309
310
311     bbtkDebugMessage("object",2,
312                      "<== Connection::~Connection() ["
313                      <<GetFullName()<<"]"<<std::endl);
314   }
315   //==================================================================
316   
317   //==================================================================
318   /// Backward Update
319   IOStatus Connection::BackwardUpdate()
320   {
321     bbtkDebugMessage("process",5,
322                      "===> Connection::BackwardUpdate() ["
323                      <<GetFullName()<<"]"<<std::endl);
324
325     IOStatus s = UPTODATE;
326     s = mFrom->bbBackwardUpdate(GetThisPointer<Connection>());
327
328     TransferData();
329
330     if (mAdaptor && (s==MODIFIED)) mAdaptor->bbSetModifiedStatus();
331
332     bbtkDebugMessage("process",5,
333                      "<=== Connection::BackwardUpdate() ["
334                      <<GetFullName()<<"]"<<std::endl);
335     return s;
336   }
337   //==================================================================
338
339   /*
340   //==================================================================
341   /// Forward Update
342   void Connection::ForwardUpdate()
343   {
344     bbtkDebugMessageInc("process",2,
345                         "Connection::ForwardUpdate() ["
346                         <<GetFullName()<<"]"<<std::endl);
347
348   
349     TransferData();
350
351     mTo->bbForwardUpdate(this);
352
353     bbtkDebugDecTab("process",2);
354   }
355   //==================================================================
356   */
357
358   //==================================================================
359   /// Transfers the data from the source output to the target input
360   /// doing necessary conversions (adaptation or pointer cast)
361   void Connection::TransferData()
362   {
363     bbtkDebugMessageInc("data",3,
364                         "Connection::TransferData() ["
365                         <<GetFullName()<<"]"<<std::endl);
366     
367     
368     // If an adaptor was created we need to adapt the data
369     if (mAdaptor) 
370       {
371         mAdaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
372         mAdaptor->bbExecute();
373         // LG : Connection Update does not set mTo as modified
374         mTo->bbSetInput(mInput, mAdaptor->bbGetOutput("Out"),false);
375         
376       }
377     // If no adaptor but source type is an any and target is not an any
378     else if ( mFromAny && (! mToAny) )
379       {
380         bbtkDebugMessage("data",3,
381                          " * Source type is an "
382                          <<HumanTypeName<Data>()
383                          <<" which contains a <"
384                          <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
385                          <<">"<<std::endl);
386         bbtkDebugMessage("data",3,
387                          " * Target type is <"
388                          <<HumanTypeName(mTo->bbGetInputType(mInput))
389                          <<">"<<std::endl);
390         
391         // 1) Test strict type matching between any content and target
392         if (mFrom->bbGetOutput(mOutput)
393             .contains( mTo->bbGetInputType(mInput) ) )
394           {
395             bbtkDebugMessage("data",3,
396                              " -> Equal types : transfer ok"<<std::endl);
397             mTo->bbSetInput( mInput, 
398                              mFrom->bbGetOutput(mOutput),
399                              false);
400           }
401         else 
402           {
403             // 2) Look for an adaptor
404             bbtk::BlackBox::Pointer adaptor;
405             try 
406               {
407                 adaptor = mFactory.lock()
408                   ->NewAdaptor(mFrom->bbGetOutput(mOutput).type(),
409                                mTo->bbGetInputType(mInput),
410                                "");
411               }
412             catch (...)
413               {
414               }
415             if (adaptor)  
416               {
417                 bbtkDebugMessage("data",3," -> Adaptor found : using it"
418                                  <<std::endl);
419                   adaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
420                 adaptor->bbExecute();
421                 // LG : Connection Update does not set mTo as modified
422                 mTo->bbSetInput(mInput, adaptor->bbGetOutput("Out"),false);
423                 //      adaptor->bbDelete();
424               }
425             // 3) If no adaptor found but the any content is a pointer
426             //    and target type is also a pointer : we try run-time cast
427             else if ( (mFrom->bbGetOutput(mOutput).contains_pointer()) &&
428                       (mTo->bbGetDescriptor()->GetInputDescriptor(mInput)
429                        ->IsPointerType()) )
430               {
431                 bbtkDebugMessage("data",3,
432                                  " -> No adaptor found but source and target types are both pointers : trying up or down cast"<<std::endl);
433                 
434                 void* nptr = 
435                   mFrom->bbGetOutput(mOutput)
436                   .get_pointer_to(mTo->bbGetInput(mInput).pointed_type());
437                 if (!nptr)  
438                   {
439                     bbtkError("Connection '"
440                               <<GetFullName()
441                               <<"' : <"
442                               <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
443                               <<"> to <"
444                               <<HumanTypeName(mTo->bbGetInputType(mInput))
445                               <<"> : no adaptor available and run-time up and down cast failed");
446                   }
447                 mTo->bbBruteForceSetInputPointer(mInput, nptr, false);
448               }
449             // 4) Nothing worked : error
450             else 
451               {
452                 bbtkError("Connection '"<<GetFullName()<<"' "
453                           <<"no adaptor found to convert <"
454                           <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
455                           <<"> to <"
456                           <<HumanTypeName(mTo->bbGetInputType(mInput))<<">");
457               }
458           }
459       }
460     // EO : mFromAny && ! mToAny
461     // Default case : types are the same; we use simple get-set
462     else 
463       {
464         // LG : Connection Update does not set mTo as modified
465         mTo->bbSetInput(mInput, mFrom->bbGetOutput(mOutput),false);
466       }
467
468   }
469   //==================================================================
470   
471   //==================================================================
472   /// Modified
473   void Connection::SetModifiedStatus()
474   {
475     bbtkDebugMessage("modified",2,
476                      "==> Connection::SetModifiedStatus() ["
477                      <<GetFullName()<<"]"<<std::endl);
478     
479     if (mAdaptor) mAdaptor->bbSetModifiedStatus();
480     
481     mTo->bbSetModifiedStatus(  mTo->bbGetInputConnectorMap().find(mInput)->second );
482     
483     /*
484     bbtkDebugMessage("modified",2,
485                      "==> Connection::SetModifiedStatus() ["
486                      <<GetFullName()<<"]"<<std::endl);
487     */
488   }
489   //==================================================================
490
491   
492   //==================================================================
493   std::string Connection::GetFullName() const {
494     if (mFrom && mTo) 
495       {
496         std::string res = mFrom->bbGetName()+"."+mOutput+"--"
497           +mTo->bbGetName()+"."+mInput;
498         if ((!mOriginalFrom.expired()) && (!mOriginalTo.expired()) &&
499             ((mFrom!=mOriginalFrom.lock())||(mTo!=mOriginalTo.lock())))
500           {
501             res += "("+mOriginalFrom.lock()->bbGetName()
502               +"."+mOriginalOutput+"--"
503               + mOriginalTo.lock()->bbGetName()+"."+mOriginalInput+")";
504           }
505         return res;
506       }
507     return "***Invalid Connection***";
508   }
509   //==================================================================
510
511   //==================================================================
512   void Connection::Check() const
513   {
514     bbtkMessage("debug",1,"** Checking Connection "<<(void*)this<<" ["<<GetFullName()<<"]"
515                 <<std::endl);
516     if (mFrom==0) 
517       {
518         bbtkMessage("debug",2," - From = 0"<<std::endl);
519       }
520     else
521       {
522         bbtkMessage("debug",2," - From : "<<mFrom->bbGetFullName()<<std::endl);
523         if (!mFrom->bbHasOutput(mOutput))
524           {
525             bbtkError("** Checking Connection "<<(void*)this
526                        <<" ["<<GetFullName()<<"] : "
527                       << mFrom->bbGetFullName()<<" does not have output '"
528                       <<mOutput<<"'");
529           }     
530         bbtkMessage("debug",2," - From : Output '"<<mOutput<<"' exists"<<std::endl);
531         BlackBox::OutputConnectorMapType::const_iterator i 
532           = mFrom->bbGetOutputConnectorMap().find(mOutput);
533         if (i== mFrom->bbGetOutputConnectorMap().end())
534           {
535              bbtkError("** Checking Connection "<<(void*)this
536                        <<" ["<<GetFullName()<<"] : "
537                        <<mFrom->bbGetFullName()<<" output '"
538                        <<mOutput<<"' is not in OutputConnectorMap");
539           }
540         bbtkMessage("debug",2," - From : Output '"<<mOutput
541                     <<"' is in OutputConnectorMap"<<std::endl);
542
543         std::vector< Connection* >::const_iterator j;
544         /*
545         for (j  = i->second->GetConnectionVector().begin();
546              j != i->second->GetConnectionVector().end();
547              ++j)
548           {
549             if ((*j)==this) break;
550           }
551         */
552         j = find(i->second->GetConnectionVector().begin(),
553                  i->second->GetConnectionVector().end(),
554                  this);
555        
556         if (j==i->second->GetConnectionVector().end())
557           {
558             bbtkError("** Checking Connection "<<(void*)this
559                       <<" ["<<GetFullName()<<"] : "
560                       << "Connection ["<<GetFullName()<<"] : "
561                       <<" OutputConnector '"
562                       <<mOutput<<"' of "<<mFrom->bbGetFullName()
563                       <<" does not point to this connection");
564             
565           }
566         bbtkMessage("debug",2," - From : This connection is in OutputConnector connection vector"<<std::endl);
567         bbtkMessage("debug",2," * Box from : Check successfull"<<std::endl);
568
569       }
570
571     if (mTo==0) 
572       {
573         bbtkMessage("debug",2," - To   = 0"<<std::endl);
574       }
575     else
576       {
577         bbtkMessage("debug",2," - To   : "<<mTo->bbGetName()<<std::endl);
578         //      std::cout << mTo << std::endl;
579         //      std::cout << mTo->bbGetDescriptor() << std::endl;
580         //      std::cout << mTo->bbGetDescriptor()->GetTypeName() << std::endl;
581         //      mTo->bbGetFullName();
582         bbtkMessage("debug",2," - To   : "<<mTo->bbGetFullName()<<std::endl);
583         if (!mTo->bbHasInput(mInput))
584           {
585             bbtkError("** Checking Connection "<<(void*)this
586                       <<" ["<<GetFullName()<<"] : "
587                       <<mTo->bbGetFullName()<<" does not have input '"
588                       <<mInput<<"'");
589           }     
590         bbtkMessage("debug",2," - To   : Input '"<<mInput<<"' exists"<<std::endl);
591         BlackBox::InputConnectorMapType::const_iterator i 
592           = mTo->bbGetInputConnectorMap().find(mInput);
593         if (i== mTo->bbGetInputConnectorMap().end())
594           {
595              bbtkError("** Checking Connection "<<(void*)this
596                        <<" ["<<GetFullName()<<"] : "
597                        <<mTo->bbGetFullName()<<" input '"
598                        <<mInput<<"' is not in InputConnectorMap");
599           }
600         bbtkMessage("debug",2," - To   : Input '"<<mInput
601                     <<"' is in InputConnectorMap"<<std::endl);
602
603         if (i->second->GetConnection()==0)
604           {
605             bbtkError("** Checking Connection "<<(void*)this
606                       <<" ["<<GetFullName()<<"] : "
607                       <<"Connection "<<GetFullName()<<" : "
608                       <<" InputConnector '"
609                       <<mInput<<"' of "<<mTo->bbGetFullName()
610                       <<" does not point to this connection");
611     
612           }
613         bbtkMessage("debug",2," - To   : This connection is in InputConnector connection vector"<<std::endl);
614         bbtkMessage("debug",2," * Box to   : Check successfull"<<std::endl);
615
616       }
617   }
618   //==================================================================
619  //==========================================================================
620   std::string Connection::GetObjectName() const
621   {
622     std::string s("Connection '");
623     s += GetFullName();
624     s += "'";
625     return s;
626   }
627   //==========================================================================
628   
629   //==========================================================================
630   std::string  Connection::GetObjectInfo() const 
631   {
632     std::stringstream i;
633     return i.str();
634   }
635   //==========================================================================
636
637  //==========================================================================
638 size_t  Connection::GetObjectSize() const 
639 {
640   size_t s = Superclass::GetObjectSize();
641   s += Connection::GetObjectInternalSize();
642   return s;
643   }
644   //==========================================================================
645   //==========================================================================
646 size_t  Connection::GetObjectInternalSize() const 
647 {
648   size_t s = sizeof(Connection);
649   return s;
650   }
651   //==========================================================================
652   //==========================================================================
653   size_t  Connection::GetObjectRecursiveSize() const 
654   {
655     size_t s = Superclass::GetObjectRecursiveSize();
656     s += Connection::GetObjectInternalSize();
657     return s;
658   }
659   //==========================================================================
660
661 }// namespace bbtk
662
663
664
665
666