]> 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/01/22 15:02:00 $
7   Version:   $Revision: 1.1 $
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     : mAdaptor(0),
37       mFromAny(false),
38       mToAny(false)
39   {
40     bbtkDebugMessageInc("Core",7,"Connection::Connection(\""
41                         <<from->bbGetName()<<"\",\""<<output<<"\",\""
42                         <<to->bbGetName()<<"\",\""<<input<<"\")"
43                         <<std::endl);    
44
45     mFrom = from;
46     mTo = to;
47     mInput = input;
48     mOutput = output;
49     
50
51     if (! from->bbHasOutput(output) )
52       {
53         bbtkError("The box \""<<from->bbGetTypeName()<<
54                   "\" has no output \""<<output<<"\"");
55       }
56     if (! to->bbHasInput(input) )
57       {
58         bbtkError("The box \""<<to->bbGetTypeName()<<
59                   "\" has no input \""<<input<<"\"");
60       } 
61
62     if (to->bbGetInputConnectorMap().find(input)->second->IsConnected())
63       {
64         bbtkError("The input \""<<input<<"\" of the box \""<<to->bbGetTypeName()
65                   <<"\" is already connected");
66       }
67     
68     //  std::string t1 ( from->bbGetOutputType(output).name() );
69     //   std::string t2 ( to->bbGetInputType(input).name() );
70     // if  //( t1 != t2 ) 
71     if ( from->bbGetOutputType(output) !=
72          to->bbGetInputType(input) )
73       {
74         if ( from->bbGetOutputType(output) == typeid(Data) )
75           {
76             bbtkWarning("Connection '"
77                         <<GetFullName()
78                         <<"' : '"<<from->bbGetName()<<"."<<output
79                         <<"' is of type <"
80                         <<HumanTypeName<Data>()
81                         <<"> : type compatibility with '"
82                         <<to->bbGetName()<<"."<<input
83                         <<"' will be resolved at run time"
84                         );
85             mFromAny = true;
86           }
87         else if (  to->bbGetInputType(input) == typeid(Data) )
88           {   
89             bbtkDebugMessage("Core",8," -> '"<<input<<"' type is "
90                              <<TypeName<Data>()<<" : can receive any data"
91                              <<std::endl);
92             mToAny = true;
93           }
94         else 
95           {
96             //   std::cout << "Adaptive connection "<<std::endl;
97             std::string name;
98             name = from->bbGetName() + "." + output + "-" 
99               + to->bbGetName() + "." + input; 
100             mAdaptor = NewAdaptor(from->bbGetOutputType(output),
101                                   to->bbGetInputType(input),
102                                   name);
103             if (!mAdaptor)  
104               {  
105                 bbtkError("did not find any <"
106                           <<TypeName(from->bbGetOutputType(output))
107                           <<"> to <"
108                           <<TypeName(to->bbGetInputType(input))
109                           <<"> adaptor");
110               } 
111           }
112       }
113
114      // 
115     from->bbConnectOutput(output,this);
116     to->bbConnectInput(input,this);
117     
118     bbtkDebugDecTab("Core",7);
119   }
120
121   //==================================================================
122   
123   
124   //==================================================================
125   /// Dtor 
126   Connection::~Connection()
127   {
128     bbtkDebugMessageInc("Core",7,
129                         "Connection::~Connection() ["
130                         <<GetFullName()<<"]"<<std::endl);
131
132     mFrom->bbDisconnectOutput(mOutput,this);
133     mTo->bbDisconnectInput(mInput,this);
134     if (mAdaptor) mAdaptor->bbDelete();
135
136     bbtkDebugDecTab("Core",7);
137   }
138   //==================================================================
139   
140   //==================================================================
141   /// Backward Update
142   IOStatus Connection::BackwardUpdate()
143   {
144     bbtkDebugMessageInc("Process",2,
145                         "Connection::BackwardUpdate() ["
146                         <<GetFullName()<<"]"<<std::endl);
147
148     IOStatus s = UPTODATE;
149     s = mFrom->bbBackwardUpdate(this);
150
151     TransferData();
152
153     if (mAdaptor && (s==MODIFIED)) mAdaptor->bbSetModifiedStatus();
154
155     bbtkDebugDecTab("Process",2);
156
157     return s;
158   }
159   //==================================================================
160
161   /*
162   //==================================================================
163   /// Forward Update
164   void Connection::ForwardUpdate()
165   {
166     bbtkDebugMessageInc("Process",2,
167                         "Connection::ForwardUpdate() ["
168                         <<GetFullName()<<"]"<<std::endl);
169
170   
171     TransferData();
172
173     mTo->bbForwardUpdate(this);
174
175     bbtkDebugDecTab("Process",2);
176   }
177   //==================================================================
178   */
179
180   //==================================================================
181   /// Transfers the data from the source output to the target input
182   /// doing necessary conversions (adaptation or pointer cast)
183   void Connection::TransferData()
184   {
185     bbtkDebugMessageInc("Process",3,
186                         "Connection::TransferData() ["
187                         <<GetFullName()<<"]"<<std::endl);
188     
189     
190     // If an adaptor was created we need to adapt the data
191     if (mAdaptor) 
192       {
193         mAdaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
194         mAdaptor->bbExecute();
195         // LG : Connection Update does not set mTo as modified
196         mTo->bbSetInput(mInput, mAdaptor->bbGetOutput("Out"),false);
197         
198       }
199     // If no adaptor but source type is an any and target is not an any
200     else if ( mFromAny && (! mToAny) )
201       {
202         bbtkDebugMessage("Data",3,
203                          "Connection::TransferData() ["
204                          <<GetFullName()<<"]"<<std::endl);
205         bbtkDebugMessage("Data",3,
206                          " * Source type is an "
207                          <<HumanTypeName<Data>()
208                          <<" which contains a <"
209                          <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
210                          <<">"<<std::endl);
211         bbtkDebugMessage("Data",3,
212                          " * Target type is <"
213                          <<HumanTypeName(mTo->bbGetInputType(mInput))
214                          <<">"<<std::endl);
215         
216         // 1) Test strict type matching between any content and target
217         if (mFrom->bbGetOutput(mOutput)
218             .contains( mTo->bbGetInputType(mInput) ) )
219           {
220             bbtkDebugMessage("Data",3,
221                              " -> Equal types : transfer ok"<<std::endl);
222             mTo->bbSetInput( mInput, 
223                              mFrom->bbGetOutput(mOutput),
224                              false);
225           }
226         else 
227           {
228             // 2) Look for an adaptor
229             bbtk::BlackBox* adaptor = 0;
230             try 
231               {
232                 adaptor = NewAdaptor(mFrom->bbGetOutput(mOutput).type(),
233                                      mTo->bbGetInputType(mInput),
234                                      "");
235               }
236             catch (...)
237               {
238               }
239             if (adaptor)  
240               {
241                 bbtkDebugMessage("Data",3," -> Adaptor found : using it"
242                                  <<std::endl);
243                   adaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
244                 adaptor->bbExecute();
245                 // LG : Connection Update does not set mTo as modified
246                 mTo->bbSetInput(mInput, adaptor->bbGetOutput("Out"),false);
247                 adaptor->bbDelete();
248               }
249             // 3) If no adaptor found but the any content is a pointer
250             //    and target type is also a pointer : we try run-time cast
251             else if ( (mFrom->bbGetOutput(mOutput).contains_pointer()) &&
252                       (mTo->bbGetDescriptor()->GetInputDescriptor(mInput)
253                        ->IsPointerType()) )
254               {
255                 bbtkDebugMessage("Data",3,
256                                  " -> No adaptor found but source and target types are both pointers : trying up or down cast"<<std::endl);
257                 
258                 void* nptr = 
259                   mFrom->bbGetOutput(mOutput)
260                   .get_pointer_to(mTo->bbGetInput(mInput).pointed_type());
261                 if (!nptr)  
262                   {
263                     bbtkError("Connection '"
264                               <<GetFullName()
265                               <<"' : <"
266                               <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
267                               <<"> to <"
268                               <<HumanTypeName(mTo->bbGetInputType(mInput))
269                               <<"> : no adaptor available and run-time up and down cast failed");
270                   }
271                 mTo->bbBruteForceSetInputPointer(mInput, nptr, false);
272               }
273             // 4) Nothing worked : error
274             else 
275               {
276                 bbtkError("Connection '"<<GetFullName()<<"' "
277                           <<"no adaptor found to convert <"
278                           <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
279                           <<"> to <"
280                           <<HumanTypeName(mTo->bbGetInputType(mInput))<<">");
281               }
282           }
283       }
284     // EO : mFromAny && ! mToAny
285     // Default case : types are the same; we use simple get-set
286     else 
287       {
288         // LG : Connection Update does not set mTo as modified
289         mTo->bbSetInput(mInput, mFrom->bbGetOutput(mOutput),false);
290       }
291
292     bbtkDebugDecTab("Process",3);
293   }
294   //==================================================================
295   
296   //==================================================================
297   /// Modified
298   void Connection::SetModifiedStatus()
299   {
300     bbtkDebugMessageInc("Process",5,
301                         "Connection::SetModifiedStatus() ["
302                         <<GetFullName()<<"]"<<std::endl);
303     
304     if (mAdaptor) mAdaptor->bbSetModifiedStatus();
305     
306     mTo->bbSetModifiedStatus(  mTo->bbGetInputConnectorMap().find(mInput)->second );
307     
308     bbtkDebugDecTab("Process",5);
309   }
310   //==================================================================
311
312   
313   //==================================================================
314   std::string Connection::GetFullName() const {
315     if (mFrom && mTo)
316       return  mFrom->bbGetName()+"."+mOutput+"--"
317         +mTo->bbGetName()+"."+mInput;
318     return "***Invalid Connection***";
319   }
320   //==================================================================
321
322
323
324 }// namespace bbtk
325
326
327
328
329