1 /*=========================================================================
4 Module: $RCSfile: bbtkConnection.cxx,v $
6 Date: $Date: 2008/04/22 06:59:31 $
7 Version: $Revision: 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.
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<<"\")"
65 bbtkDebugMessage("connection",1,"==> Connection::Connection(\""
66 <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
67 <<to->bbGetFullName()<<"\",\""<<input<<"\")"
72 if (! from->bbHasOutput(output) )
74 bbtkError("The box \""<<from->bbGetTypeName()<<
75 "\" has no output \""<<output<<"\"");
77 if (! to->bbHasInput(input) )
79 bbtkError("The box \""<<to->bbGetTypeName()<<
80 "\" has no input \""<<input<<"\"");
83 if (to->bbGetInputConnectorMap().find(input)->second->IsConnected())
85 bbtkError("The input \""<<input<<"\" of the box \""<<to->bbGetName()
86 <<"\" is already connected");
89 // std::string t1 ( from->bbGetOutputType(output).name() );
90 // std::string t2 ( to->bbGetInputType(input).name() );
92 if ( from->bbGetOutputType(output) !=
93 to->bbGetInputType(input) )
95 if ( from->bbGetOutputType(output) == typeid(Data) )
97 bbtkWarning("Connection '"
99 <<"' : '"<<from->bbGetName()<<"."<<output
101 <<HumanTypeName<Data>()
102 <<"> : type compatibility with '"
103 <<to->bbGetName()<<"."<<input
104 <<"' will be resolved at run time"
108 else if ( to->bbGetInputType(input) == typeid(Data) )
110 bbtkDebugMessage("Kernel",8," -> '"<<input<<"' type is "
111 <<TypeName<Data>()<<" : can receive any data"
117 // std::cout << "Adaptive connection "<<std::endl;
119 name = from->bbGetName() + "." + output + "-"
120 + to->bbGetName() + "." + input;
121 mAdaptor = mFactory.lock()
122 ->NewAdaptor(from->bbGetOutputType(output),
123 to->bbGetInputType(input),
127 bbtkError("did not find any <"
128 <<TypeName(from->bbGetOutputType(output))
130 <<TypeName(to->bbGetInputType(input))
138 mOriginalFrom = from;
141 mInput = mOriginalInput = input;
142 mOutput = mOriginalOutput = output;
144 // Lock this pointer !!!
145 Pointer p = MakePointer(this,true);
146 from->bbConnectOutput(output,p);
147 to->bbConnectInput(input,p);
150 bbtkDebugMessage("connection",1,"<== Connection::Connection(\""
151 <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
152 <<to->bbGetFullName()<<"\",\""<<input<<"\")"
155 bbtkDebugMessage("object",2,"==> Connection::Connection(\""
156 <<from->bbGetName()<<"\",\""<<output<<"\",\""
157 <<to->bbGetName()<<"\",\""<<input<<"\")"
160 //==================================================================
162 //==================================================================
164 Connection::~Connection()
166 bbtkDebugMessage("object",2,
167 "==> Connection::~Connection() ["
168 <<GetFullName()<<"]"<<std::endl);
170 if (mAdaptor) mAdaptor.reset();
171 mOriginalFrom.reset();
175 mFrom->bbDisconnectOutput(mOutput,
176 GetThisPointer<Connection>());
180 bbtkInternalError("Connection::~Connection() : invalid initial box pointer");
184 mTo->bbDisconnectInput(mInput,
185 GetThisPointer<Connection>());
189 bbtkInternalError("Connection::~Connection() : invalid final box pointer");
194 bbtkDebugMessage("object",2,
195 "<== Connection::~Connection() ["
196 <<GetFullName()<<"]"<<std::endl);
198 //==================================================================
200 //==================================================================
202 IOStatus Connection::BackwardUpdate()
204 bbtkDebugMessageInc("Process",2,
205 "Connection::BackwardUpdate() ["
206 <<GetFullName()<<"]"<<std::endl);
208 IOStatus s = UPTODATE;
209 s = mFrom->bbBackwardUpdate(GetThisPointer<Connection>());
213 if (mAdaptor && (s==MODIFIED)) mAdaptor->bbSetModifiedStatus();
215 bbtkDebugDecTab("Process",2);
219 //==================================================================
222 //==================================================================
224 void Connection::ForwardUpdate()
226 bbtkDebugMessageInc("Process",2,
227 "Connection::ForwardUpdate() ["
228 <<GetFullName()<<"]"<<std::endl);
233 mTo->bbForwardUpdate(this);
235 bbtkDebugDecTab("Process",2);
237 //==================================================================
240 //==================================================================
241 /// Transfers the data from the source output to the target input
242 /// doing necessary conversions (adaptation or pointer cast)
243 void Connection::TransferData()
245 bbtkDebugMessageInc("Process",3,
246 "Connection::TransferData() ["
247 <<GetFullName()<<"]"<<std::endl);
250 // If an adaptor was created we need to adapt the data
253 mAdaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
254 mAdaptor->bbExecute();
255 // LG : Connection Update does not set mTo as modified
256 mTo->bbSetInput(mInput, mAdaptor->bbGetOutput("Out"),false);
259 // If no adaptor but source type is an any and target is not an any
260 else if ( mFromAny && (! mToAny) )
262 bbtkDebugMessage("Data",3,
263 "Connection::TransferData() ["
264 <<GetFullName()<<"]"<<std::endl);
265 bbtkDebugMessage("Data",3,
266 " * Source type is an "
267 <<HumanTypeName<Data>()
268 <<" which contains a <"
269 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
271 bbtkDebugMessage("Data",3,
272 " * Target type is <"
273 <<HumanTypeName(mTo->bbGetInputType(mInput))
276 // 1) Test strict type matching between any content and target
277 if (mFrom->bbGetOutput(mOutput)
278 .contains( mTo->bbGetInputType(mInput) ) )
280 bbtkDebugMessage("Data",3,
281 " -> Equal types : transfer ok"<<std::endl);
282 mTo->bbSetInput( mInput,
283 mFrom->bbGetOutput(mOutput),
288 // 2) Look for an adaptor
289 bbtk::BlackBox::Pointer adaptor;
292 adaptor = mFactory.lock()
293 ->NewAdaptor(mFrom->bbGetOutput(mOutput).type(),
294 mTo->bbGetInputType(mInput),
302 bbtkDebugMessage("Data",3," -> Adaptor found : using it"
304 adaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
305 adaptor->bbExecute();
306 // LG : Connection Update does not set mTo as modified
307 mTo->bbSetInput(mInput, adaptor->bbGetOutput("Out"),false);
308 // adaptor->bbDelete();
310 // 3) If no adaptor found but the any content is a pointer
311 // and target type is also a pointer : we try run-time cast
312 else if ( (mFrom->bbGetOutput(mOutput).contains_pointer()) &&
313 (mTo->bbGetDescriptor()->GetInputDescriptor(mInput)
316 bbtkDebugMessage("Data",3,
317 " -> No adaptor found but source and target types are both pointers : trying up or down cast"<<std::endl);
320 mFrom->bbGetOutput(mOutput)
321 .get_pointer_to(mTo->bbGetInput(mInput).pointed_type());
324 bbtkError("Connection '"
327 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
329 <<HumanTypeName(mTo->bbGetInputType(mInput))
330 <<"> : no adaptor available and run-time up and down cast failed");
332 mTo->bbBruteForceSetInputPointer(mInput, nptr, false);
334 // 4) Nothing worked : error
337 bbtkError("Connection '"<<GetFullName()<<"' "
338 <<"no adaptor found to convert <"
339 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
341 <<HumanTypeName(mTo->bbGetInputType(mInput))<<">");
345 // EO : mFromAny && ! mToAny
346 // Default case : types are the same; we use simple get-set
349 // LG : Connection Update does not set mTo as modified
350 mTo->bbSetInput(mInput, mFrom->bbGetOutput(mOutput),false);
353 bbtkDebugDecTab("Process",3);
355 //==================================================================
357 //==================================================================
359 void Connection::SetModifiedStatus()
361 bbtkDebugMessageInc("Process",5,
362 "Connection::SetModifiedStatus() ["
363 <<GetFullName()<<"]"<<std::endl);
365 if (mAdaptor) mAdaptor->bbSetModifiedStatus();
367 mTo->bbSetModifiedStatus( mTo->bbGetInputConnectorMap().find(mInput)->second );
369 bbtkDebugDecTab("Process",5);
371 //==================================================================
374 //==================================================================
375 std::string Connection::GetFullName() const {
378 std::string res = mFrom->bbGetName()+"."+mOutput+"--"
379 +mTo->bbGetName()+"."+mInput;
380 if ((!mOriginalFrom.expired()) && (!mOriginalTo.expired()) &&
381 ((mFrom!=mOriginalFrom.lock())||(mTo!=mOriginalTo.lock())))
383 res += "("+mOriginalFrom.lock()->bbGetName()
384 +"."+mOriginalOutput+"--"
385 + mOriginalTo.lock()->bbGetName()+"."+mOriginalInput+")";
389 return "***Invalid Connection***";
391 //==================================================================
393 //==================================================================
394 void Connection::Check() const
396 bbtkMessage("Debug",1,"** Checking Connection "<<(void*)this<<" ["<<GetFullName()<<"]"
400 bbtkMessage("Debug",2," - From = 0"<<std::endl);
404 bbtkMessage("Debug",2," - From : "<<mFrom->bbGetFullName()<<std::endl);
405 if (!mFrom->bbHasOutput(mOutput))
407 bbtkError("** Checking Connection "<<(void*)this
408 <<" ["<<GetFullName()<<"] : "
409 << mFrom->bbGetFullName()<<" does not have output '"
412 bbtkMessage("Debug",2," - From : Output '"<<mOutput<<"' exists"<<std::endl);
413 BlackBox::OutputConnectorMapType::const_iterator i
414 = mFrom->bbGetOutputConnectorMap().find(mOutput);
415 if (i== mFrom->bbGetOutputConnectorMap().end())
417 bbtkError("** Checking Connection "<<(void*)this
418 <<" ["<<GetFullName()<<"] : "
419 <<mFrom->bbGetFullName()<<" output '"
420 <<mOutput<<"' is not in OutputConnectorMap");
422 bbtkMessage("Debug",2," - From : Output '"<<mOutput
423 <<"' is in OutputConnectorMap"<<std::endl);
425 std::vector< Connection::WeakPointer >::const_iterator j;
426 for (j = i->second->GetConnectionVector().begin();
427 j != i->second->GetConnectionVector().end();
430 if ((*j).lock()==GetThisPointer<Connection>()) break;
433 j = find(i->second->GetConnectionVector().begin(),
434 i->second->GetConnectionVector().end(),
435 GetThisPointer<Connection>());
437 if (j==i->second->GetConnectionVector().end())
439 bbtkError("** Checking Connection "<<(void*)this
440 <<" ["<<GetFullName()<<"] : "
441 << "Connection ["<<GetFullName()<<"] : "
442 <<" OutputConnector '"
443 <<mOutput<<"' of "<<mFrom->bbGetFullName()
444 <<" does not point to this connection");
447 bbtkMessage("Debug",2," - From : This connection is in OutputConnector connection vector"<<std::endl);
448 bbtkMessage("Debug",1," * Box from : Check successfull"<<std::endl);
454 bbtkMessage("Debug",2," - To = 0"<<std::endl);
458 bbtkMessage("Debug",2," - To : "<<mTo->bbGetName()<<std::endl);
459 // std::cout << mTo << std::endl;
460 // std::cout << mTo->bbGetDescriptor() << std::endl;
461 // std::cout << mTo->bbGetDescriptor()->GetTypeName() << std::endl;
462 // mTo->bbGetFullName();
463 bbtkMessage("Debug",2," - To : "<<mTo->bbGetFullName()<<std::endl);
464 if (!mTo->bbHasInput(mInput))
466 bbtkError("** Checking Connection "<<(void*)this
467 <<" ["<<GetFullName()<<"] : "
468 <<mTo->bbGetFullName()<<" does not have input '"
471 bbtkMessage("Debug",2," - To : Input '"<<mInput<<"' exists"<<std::endl);
472 BlackBox::InputConnectorMapType::const_iterator i
473 = mTo->bbGetInputConnectorMap().find(mInput);
474 if (i== mTo->bbGetInputConnectorMap().end())
476 bbtkError("** Checking Connection "<<(void*)this
477 <<" ["<<GetFullName()<<"] : "
478 <<mTo->bbGetFullName()<<" input '"
479 <<mInput<<"' is not in InputConnectorMap");
481 bbtkMessage("Debug",2," - To : Input '"<<mInput
482 <<"' is in InputConnectorMap"<<std::endl);
484 if (i->second->GetConnection()==0)
486 bbtkError("** Checking Connection "<<(void*)this
487 <<" ["<<GetFullName()<<"] : "
488 <<"Connection "<<GetFullName()<<" : "
489 <<" InputConnector '"
490 <<mInput<<"' of "<<mTo->bbGetFullName()
491 <<" does not point to this connection");
494 bbtkMessage("Debug",2," - To : This connection is in InputConnector connection vector"<<std::endl);
495 bbtkMessage("Debug",1," * Box to : Check successfull"<<std::endl);
499 //==================================================================
500 //==========================================================================
501 std::string Connection::GetObjectName() const
503 std::string s("Connection '");
508 //==========================================================================
510 //==========================================================================
511 std::string Connection::GetObjectInfo() const
516 //==========================================================================
518 //==========================================================================
519 size_t Connection::GetObjectSize() const
521 size_t s = Superclass::GetObjectSize();
522 s += Connection::GetObjectInternalSize();
525 //==========================================================================
526 //==========================================================================
527 size_t Connection::GetObjectInternalSize() const
529 size_t s = sizeof(Connection);
532 //==========================================================================
533 //==========================================================================
534 size_t Connection::GetObjectRecursiveSize() const
536 size_t s = Superclass::GetObjectRecursiveSize();
537 s += Connection::GetObjectInternalSize();
540 //==========================================================================