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