]> Creatis software - bbtk.git/blob - kernel/src/bbtkConnection.cxx
8d60b38699afa0f73b65fa34d6243c95155a5d09
[bbtk.git] / kernel / src / bbtkConnection.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   bbtk
4   Module:    $RCSfile: bbtkConnection.cxx,v $
5   Language:  C++
6   Date:      $Date: 2008/03/18 12:51:26 $
7   Version:   $Revision: 1.4 $
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 = from;
48     mTo = to;
49     mInput = input;
50     mOutput = 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   
126   //==================================================================
127   /// Dtor 
128   Connection::~Connection()
129   {
130     bbtkDebugMessageInc("Kernel",7,
131                         "Connection::~Connection() ["
132                         <<GetFullName()<<"]"<<std::endl);
133
134     mFrom->bbDisconnectOutput(mOutput,this);
135     mTo->bbDisconnectInput(mInput,this);
136     if (mAdaptor) mAdaptor->bbDelete();
137
138     bbtkDebugDecTab("Kernel",7);
139   }
140   //==================================================================
141   
142   //==================================================================
143   /// Backward Update
144   IOStatus Connection::BackwardUpdate()
145   {
146     bbtkDebugMessageInc("Process",2,
147                         "Connection::BackwardUpdate() ["
148                         <<GetFullName()<<"]"<<std::endl);
149
150     IOStatus s = UPTODATE;
151     s = mFrom->bbBackwardUpdate(this);
152
153     TransferData();
154
155     if (mAdaptor && (s==MODIFIED)) mAdaptor->bbSetModifiedStatus();
156
157     bbtkDebugDecTab("Process",2);
158
159     return s;
160   }
161   //==================================================================
162
163   /*
164   //==================================================================
165   /// Forward Update
166   void Connection::ForwardUpdate()
167   {
168     bbtkDebugMessageInc("Process",2,
169                         "Connection::ForwardUpdate() ["
170                         <<GetFullName()<<"]"<<std::endl);
171
172   
173     TransferData();
174
175     mTo->bbForwardUpdate(this);
176
177     bbtkDebugDecTab("Process",2);
178   }
179   //==================================================================
180   */
181
182   //==================================================================
183   /// Transfers the data from the source output to the target input
184   /// doing necessary conversions (adaptation or pointer cast)
185   void Connection::TransferData()
186   {
187     bbtkDebugMessageInc("Process",3,
188                         "Connection::TransferData() ["
189                         <<GetFullName()<<"]"<<std::endl);
190     
191     
192     // If an adaptor was created we need to adapt the data
193     if (mAdaptor) 
194       {
195         mAdaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
196         mAdaptor->bbExecute();
197         // LG : Connection Update does not set mTo as modified
198         mTo->bbSetInput(mInput, mAdaptor->bbGetOutput("Out"),false);
199         
200       }
201     // If no adaptor but source type is an any and target is not an any
202     else if ( mFromAny && (! mToAny) )
203       {
204         bbtkDebugMessage("Data",3,
205                          "Connection::TransferData() ["
206                          <<GetFullName()<<"]"<<std::endl);
207         bbtkDebugMessage("Data",3,
208                          " * Source type is an "
209                          <<HumanTypeName<Data>()
210                          <<" which contains a <"
211                          <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
212                          <<">"<<std::endl);
213         bbtkDebugMessage("Data",3,
214                          " * Target type is <"
215                          <<HumanTypeName(mTo->bbGetInputType(mInput))
216                          <<">"<<std::endl);
217         
218         // 1) Test strict type matching between any content and target
219         if (mFrom->bbGetOutput(mOutput)
220             .contains( mTo->bbGetInputType(mInput) ) )
221           {
222             bbtkDebugMessage("Data",3,
223                              " -> Equal types : transfer ok"<<std::endl);
224             mTo->bbSetInput( mInput, 
225                              mFrom->bbGetOutput(mOutput),
226                              false);
227           }
228         else 
229           {
230             // 2) Look for an adaptor
231             bbtk::BlackBox* adaptor = 0;
232             try 
233               {
234                 adaptor = mFactory->NewAdaptor(mFrom->bbGetOutput(mOutput).type(),
235                                      mTo->bbGetInputType(mInput),
236                                      "");
237               }
238             catch (...)
239               {
240               }
241             if (adaptor)  
242               {
243                 bbtkDebugMessage("Data",3," -> Adaptor found : using it"
244                                  <<std::endl);
245                   adaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
246                 adaptor->bbExecute();
247                 // LG : Connection Update does not set mTo as modified
248                 mTo->bbSetInput(mInput, adaptor->bbGetOutput("Out"),false);
249                 adaptor->bbDelete();
250               }
251             // 3) If no adaptor found but the any content is a pointer
252             //    and target type is also a pointer : we try run-time cast
253             else if ( (mFrom->bbGetOutput(mOutput).contains_pointer()) &&
254                       (mTo->bbGetDescriptor()->GetInputDescriptor(mInput)
255                        ->IsPointerType()) )
256               {
257                 bbtkDebugMessage("Data",3,
258                                  " -> No adaptor found but source and target types are both pointers : trying up or down cast"<<std::endl);
259                 
260                 void* nptr = 
261                   mFrom->bbGetOutput(mOutput)
262                   .get_pointer_to(mTo->bbGetInput(mInput).pointed_type());
263                 if (!nptr)  
264                   {
265                     bbtkError("Connection '"
266                               <<GetFullName()
267                               <<"' : <"
268                               <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
269                               <<"> to <"
270                               <<HumanTypeName(mTo->bbGetInputType(mInput))
271                               <<"> : no adaptor available and run-time up and down cast failed");
272                   }
273                 mTo->bbBruteForceSetInputPointer(mInput, nptr, false);
274               }
275             // 4) Nothing worked : error
276             else 
277               {
278                 bbtkError("Connection '"<<GetFullName()<<"' "
279                           <<"no adaptor found to convert <"
280                           <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
281                           <<"> to <"
282                           <<HumanTypeName(mTo->bbGetInputType(mInput))<<">");
283               }
284           }
285       }
286     // EO : mFromAny && ! mToAny
287     // Default case : types are the same; we use simple get-set
288     else 
289       {
290         // LG : Connection Update does not set mTo as modified
291         mTo->bbSetInput(mInput, mFrom->bbGetOutput(mOutput),false);
292       }
293
294     bbtkDebugDecTab("Process",3);
295   }
296   //==================================================================
297   
298   //==================================================================
299   /// Modified
300   void Connection::SetModifiedStatus()
301   {
302     bbtkDebugMessageInc("Process",5,
303                         "Connection::SetModifiedStatus() ["
304                         <<GetFullName()<<"]"<<std::endl);
305     
306     if (mAdaptor) mAdaptor->bbSetModifiedStatus();
307     
308     mTo->bbSetModifiedStatus(  mTo->bbGetInputConnectorMap().find(mInput)->second );
309     
310     bbtkDebugDecTab("Process",5);
311   }
312   //==================================================================
313
314   
315   //==================================================================
316   std::string Connection::GetFullName() const {
317     if (mFrom && mTo)
318       return  mFrom->bbGetName()+"."+mOutput+"--"
319         +mTo->bbGetName()+"."+mInput;
320     return "***Invalid Connection***";
321   }
322   //==================================================================
323
324
325
326 }// namespace bbtk
327
328
329
330
331