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