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