1 /*=========================================================================
4 Module: $RCSfile: bbtkConnection.cxx,v $
6 Date: $Date: 2008/04/18 12:59:15 $
7 Version: $Revision: 1.7 $
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.
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.
17 =========================================================================*/
20 *\brief Class bbtk::Connection
23 #include "bbtkConnection.h"
24 #include "bbtkFactory.h"
25 #include "bbtkBlackBox.h"
26 #include "bbtkMessageManager.h"
30 Connection::Pointer Connection::New(BlackBox::Pointer from,
31 const std::string& output,
33 const std::string& input ,
34 const Factory::Pointer f )
36 bbtkDebugMessage("object",1,"##> Connection::Connection(\""
37 <<from->bbGetName()<<"\",\""<<output<<"\",\""
38 <<to->bbGetName()<<"\",\""<<input<<"\")"
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<<"\")"
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 )
60 bbtkDebugMessage("object",2,"==> Connection::Connection(\""
61 <<from->bbGetName()<<"\",\""<<output<<"\",\""
62 <<to->bbGetName()<<"\",\""<<input<<"\")"
67 if (! from->bbHasOutput(output) )
69 bbtkError("The box \""<<from->bbGetTypeName()<<
70 "\" has no output \""<<output<<"\"");
72 if (! to->bbHasInput(input) )
74 bbtkError("The box \""<<to->bbGetTypeName()<<
75 "\" has no input \""<<input<<"\"");
78 if (to->bbGetInputConnectorMap().find(input)->second->IsConnected())
80 bbtkError("The input \""<<input<<"\" of the box \""<<to->bbGetName()
81 <<"\" is already connected");
84 // std::string t1 ( from->bbGetOutputType(output).name() );
85 // std::string t2 ( to->bbGetInputType(input).name() );
87 if ( from->bbGetOutputType(output) !=
88 to->bbGetInputType(input) )
90 if ( from->bbGetOutputType(output) == typeid(Data) )
92 bbtkWarning("Connection '"
94 <<"' : '"<<from->bbGetName()<<"."<<output
96 <<HumanTypeName<Data>()
97 <<"> : type compatibility with '"
98 <<to->bbGetName()<<"."<<input
99 <<"' will be resolved at run time"
103 else if ( to->bbGetInputType(input) == typeid(Data) )
105 bbtkDebugMessage("Kernel",8," -> '"<<input<<"' type is "
106 <<TypeName<Data>()<<" : can receive any data"
112 // std::cout << "Adaptive connection "<<std::endl;
114 name = from->bbGetName() + "." + output + "-"
115 + to->bbGetName() + "." + input;
116 mAdaptor = mFactory.lock()
117 ->NewAdaptor(from->bbGetOutputType(output),
118 to->bbGetInputType(input),
122 bbtkError("did not find any <"
123 <<TypeName(from->bbGetOutputType(output))
125 <<TypeName(to->bbGetInputType(input))
131 // Lock this pointer !!!
132 Pointer p = MakePointer(this,true);
133 from->bbConnectOutput(output,p);
134 to->bbConnectInput(input,p);
136 mOriginalFrom = from;
139 mInput = mOriginalInput = input;
140 mOutput = mOriginalOutput = output;
143 bbtkDebugMessage("object",2,"==> Connection::Connection(\""
144 <<from->bbGetName()<<"\",\""<<output<<"\",\""
145 <<to->bbGetName()<<"\",\""<<input<<"\")"
148 //==================================================================
150 //==================================================================
152 Connection::~Connection()
154 bbtkDebugMessage("object",2,
155 "==> Connection::~Connection() ["
156 <<GetFullName()<<"]"<<std::endl);
158 if (mAdaptor) mAdaptor.reset();
159 mOriginalFrom.reset();
163 mFrom->bbDisconnectOutput(mOutput,
164 GetThisPointer<Connection>());
168 bbtkInternalError("Connection::~Connection() : invalid initial box pointer");
172 mTo->bbDisconnectInput(mInput,
173 GetThisPointer<Connection>());
177 bbtkInternalError("Connection::~Connection() : invalid final box pointer");
182 bbtkDebugMessage("object",2,
183 "<== Connection::~Connection() ["
184 <<GetFullName()<<"]"<<std::endl);
186 //==================================================================
188 //==================================================================
190 IOStatus Connection::BackwardUpdate()
192 bbtkDebugMessageInc("Process",2,
193 "Connection::BackwardUpdate() ["
194 <<GetFullName()<<"]"<<std::endl);
196 IOStatus s = UPTODATE;
197 s = mFrom->bbBackwardUpdate(GetThisPointer<Connection>());
201 if (mAdaptor && (s==MODIFIED)) mAdaptor->bbSetModifiedStatus();
203 bbtkDebugDecTab("Process",2);
207 //==================================================================
210 //==================================================================
212 void Connection::ForwardUpdate()
214 bbtkDebugMessageInc("Process",2,
215 "Connection::ForwardUpdate() ["
216 <<GetFullName()<<"]"<<std::endl);
221 mTo->bbForwardUpdate(this);
223 bbtkDebugDecTab("Process",2);
225 //==================================================================
228 //==================================================================
229 /// Transfers the data from the source output to the target input
230 /// doing necessary conversions (adaptation or pointer cast)
231 void Connection::TransferData()
233 bbtkDebugMessageInc("Process",3,
234 "Connection::TransferData() ["
235 <<GetFullName()<<"]"<<std::endl);
238 // If an adaptor was created we need to adapt the data
241 mAdaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
242 mAdaptor->bbExecute();
243 // LG : Connection Update does not set mTo as modified
244 mTo->bbSetInput(mInput, mAdaptor->bbGetOutput("Out"),false);
247 // If no adaptor but source type is an any and target is not an any
248 else if ( mFromAny && (! mToAny) )
250 bbtkDebugMessage("Data",3,
251 "Connection::TransferData() ["
252 <<GetFullName()<<"]"<<std::endl);
253 bbtkDebugMessage("Data",3,
254 " * Source type is an "
255 <<HumanTypeName<Data>()
256 <<" which contains a <"
257 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
259 bbtkDebugMessage("Data",3,
260 " * Target type is <"
261 <<HumanTypeName(mTo->bbGetInputType(mInput))
264 // 1) Test strict type matching between any content and target
265 if (mFrom->bbGetOutput(mOutput)
266 .contains( mTo->bbGetInputType(mInput) ) )
268 bbtkDebugMessage("Data",3,
269 " -> Equal types : transfer ok"<<std::endl);
270 mTo->bbSetInput( mInput,
271 mFrom->bbGetOutput(mOutput),
276 // 2) Look for an adaptor
277 bbtk::BlackBox::Pointer adaptor;
280 adaptor = mFactory.lock()
281 ->NewAdaptor(mFrom->bbGetOutput(mOutput).type(),
282 mTo->bbGetInputType(mInput),
290 bbtkDebugMessage("Data",3," -> Adaptor found : using it"
292 adaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
293 adaptor->bbExecute();
294 // LG : Connection Update does not set mTo as modified
295 mTo->bbSetInput(mInput, adaptor->bbGetOutput("Out"),false);
296 // adaptor->bbDelete();
298 // 3) If no adaptor found but the any content is a pointer
299 // and target type is also a pointer : we try run-time cast
300 else if ( (mFrom->bbGetOutput(mOutput).contains_pointer()) &&
301 (mTo->bbGetDescriptor()->GetInputDescriptor(mInput)
304 bbtkDebugMessage("Data",3,
305 " -> No adaptor found but source and target types are both pointers : trying up or down cast"<<std::endl);
308 mFrom->bbGetOutput(mOutput)
309 .get_pointer_to(mTo->bbGetInput(mInput).pointed_type());
312 bbtkError("Connection '"
315 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
317 <<HumanTypeName(mTo->bbGetInputType(mInput))
318 <<"> : no adaptor available and run-time up and down cast failed");
320 mTo->bbBruteForceSetInputPointer(mInput, nptr, false);
322 // 4) Nothing worked : error
325 bbtkError("Connection '"<<GetFullName()<<"' "
326 <<"no adaptor found to convert <"
327 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
329 <<HumanTypeName(mTo->bbGetInputType(mInput))<<">");
333 // EO : mFromAny && ! mToAny
334 // Default case : types are the same; we use simple get-set
337 // LG : Connection Update does not set mTo as modified
338 mTo->bbSetInput(mInput, mFrom->bbGetOutput(mOutput),false);
341 bbtkDebugDecTab("Process",3);
343 //==================================================================
345 //==================================================================
347 void Connection::SetModifiedStatus()
349 bbtkDebugMessageInc("Process",5,
350 "Connection::SetModifiedStatus() ["
351 <<GetFullName()<<"]"<<std::endl);
353 if (mAdaptor) mAdaptor->bbSetModifiedStatus();
355 mTo->bbSetModifiedStatus( mTo->bbGetInputConnectorMap().find(mInput)->second );
357 bbtkDebugDecTab("Process",5);
359 //==================================================================
362 //==================================================================
363 std::string Connection::GetFullName() const {
366 std::string res = mFrom->bbGetName()+"."+mOutput+"--"
367 +mTo->bbGetName()+"."+mInput;
368 if ((!mOriginalFrom.expired()) && (!mOriginalTo.expired()) &&
369 ((mFrom!=mOriginalFrom.lock())||(mTo!=mOriginalTo.lock())))
371 res += "("+mOriginalFrom.lock()->bbGetName()
372 +"."+mOriginalOutput+"--"
373 + mOriginalTo.lock()->bbGetName()+"."+mOriginalInput+")";
377 return "***Invalid Connection***";
379 //==================================================================
381 //==================================================================
382 void Connection::Check() const
384 bbtkMessage("Debug",1,"** Checking Connection "<<(void*)this<<" ["<<GetFullName()<<"]"
388 bbtkMessage("Debug",2," - From = 0"<<std::endl);
392 bbtkMessage("Debug",2," - From : "<<mFrom->bbGetFullName()<<std::endl);
393 if (!mFrom->bbHasOutput(mOutput))
395 bbtkError("** Checking Connection "<<(void*)this
396 <<" ["<<GetFullName()<<"] : "
397 << mFrom->bbGetFullName()<<" does not have output '"
400 bbtkMessage("Debug",2," - From : Output '"<<mOutput<<"' exists"<<std::endl);
401 BlackBox::OutputConnectorMapType::const_iterator i
402 = mFrom->bbGetOutputConnectorMap().find(mOutput);
403 if (i== mFrom->bbGetOutputConnectorMap().end())
405 bbtkError("** Checking Connection "<<(void*)this
406 <<" ["<<GetFullName()<<"] : "
407 <<mFrom->bbGetFullName()<<" output '"
408 <<mOutput<<"' is not in OutputConnectorMap");
410 bbtkMessage("Debug",2," - From : Output '"<<mOutput
411 <<"' is in OutputConnectorMap"<<std::endl);
413 std::vector< Connection::WeakPointer >::const_iterator j;
414 for (j = i->second->GetConnectionVector().begin();
415 j != i->second->GetConnectionVector().end();
418 if ((*j).lock()==GetThisPointer<Connection>()) break;
421 j = find(i->second->GetConnectionVector().begin(),
422 i->second->GetConnectionVector().end(),
423 GetThisPointer<Connection>());
425 if (j==i->second->GetConnectionVector().end())
427 bbtkError("** Checking Connection "<<(void*)this
428 <<" ["<<GetFullName()<<"] : "
429 << "Connection ["<<GetFullName()<<"] : "
430 <<" OutputConnector '"
431 <<mOutput<<"' of "<<mFrom->bbGetFullName()
432 <<" does not point to this connection");
435 bbtkMessage("Debug",2," - From : This connection is in OutputConnector connection vector"<<std::endl);
436 bbtkMessage("Debug",1," * Box from : Check successfull"<<std::endl);
442 bbtkMessage("Debug",2," - To = 0"<<std::endl);
446 bbtkMessage("Debug",2," - To : "<<mTo->bbGetName()<<std::endl);
447 // std::cout << mTo << std::endl;
448 // std::cout << mTo->bbGetDescriptor() << std::endl;
449 // std::cout << mTo->bbGetDescriptor()->GetTypeName() << std::endl;
450 // mTo->bbGetFullName();
451 bbtkMessage("Debug",2," - To : "<<mTo->bbGetFullName()<<std::endl);
452 if (!mTo->bbHasInput(mInput))
454 bbtkError("** Checking Connection "<<(void*)this
455 <<" ["<<GetFullName()<<"] : "
456 <<mTo->bbGetFullName()<<" does not have input '"
459 bbtkMessage("Debug",2," - To : Input '"<<mInput<<"' exists"<<std::endl);
460 BlackBox::InputConnectorMapType::const_iterator i
461 = mTo->bbGetInputConnectorMap().find(mInput);
462 if (i== mTo->bbGetInputConnectorMap().end())
464 bbtkError("** Checking Connection "<<(void*)this
465 <<" ["<<GetFullName()<<"] : "
466 <<mTo->bbGetFullName()<<" input '"
467 <<mInput<<"' is not in InputConnectorMap");
469 bbtkMessage("Debug",2," - To : Input '"<<mInput
470 <<"' is in InputConnectorMap"<<std::endl);
472 if (i->second->GetConnection()==0)
474 bbtkError("** Checking Connection "<<(void*)this
475 <<" ["<<GetFullName()<<"] : "
476 <<"Connection "<<GetFullName()<<" : "
477 <<" InputConnector '"
478 <<mInput<<"' of "<<mTo->bbGetFullName()
479 <<" does not point to this connection");
482 bbtkMessage("Debug",2," - To : This connection is in InputConnector connection vector"<<std::endl);
483 bbtkMessage("Debug",1," * Box to : Check successfull"<<std::endl);
487 //==================================================================
488 //==========================================================================
489 std::string Connection::GetObjectName() const
491 std::string s("Connection '");
496 //==========================================================================
498 //==========================================================================
499 std::string Connection::GetObjectInfo() const
504 //==========================================================================
506 //==========================================================================
507 size_t Connection::GetObjectSize() const
509 size_t s = Superclass::GetObjectSize();
510 s += Connection::GetObjectInternalSize();
513 //==========================================================================
514 //==========================================================================
515 size_t Connection::GetObjectInternalSize() const
517 size_t s = sizeof(Connection);
520 //==========================================================================
521 //==========================================================================
522 size_t Connection::GetObjectRecursiveSize() const
524 size_t s = Superclass::GetObjectRecursiveSize();
525 s += Connection::GetObjectInternalSize();
528 //==========================================================================