1 /*=========================================================================
4 Module: $RCSfile: bbtkConnection.cxx,v $
6 Date: $Date: 2008/07/25 07:44:12 $
7 Version: $Revision: 1.14 $
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 //==================================================================
31 Connection::Pointer Connection::New(BlackBox::Pointer from,
32 const std::string& output,
34 const std::string& input ,
35 const Factory::Pointer f )
37 bbtkDebugMessage("object",1,"##> Connection::Connection(\""
38 <<from->bbGetName()<<"\",\""<<output<<"\",\""
39 <<to->bbGetName()<<"\",\""<<input<<"\")"
41 Connection::Pointer p =
42 MakePointer(new Connection(from,output,to,input,f));
43 bbtkDebugMessage("object",1,"<## Connection::Connection(\""
44 <<from->bbGetName()<<"\",\""<<output<<"\",\""
45 <<to->bbGetName()<<"\",\""<<input<<"\")"
49 //==================================================================
51 //==================================================================
52 /// Ctor with the black box from and to and their input and output.
53 /// Check the input and output compatibility
54 Connection::Connection(BlackBox::Pointer from, const std::string& output,
55 BlackBox::Pointer to, const std::string& input ,
56 const Factory::Pointer f )
62 bbtkDebugMessage("object",2,"==> Connection::Connection(\""
63 <<from->bbGetName()<<"\",\""<<output<<"\",\""
64 <<to->bbGetName()<<"\",\""<<input<<"\")"
67 bbtkDebugMessage("connection",1,"==> Connection::Connection(\""
68 <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
69 <<to->bbGetFullName()<<"\",\""<<input<<"\")"
74 if (! from->bbHasOutput(output) )
76 bbtkError("The box \""<<from->bbGetTypeName()<<
77 "\" has no output \""<<output<<"\"");
79 if (! to->bbHasInput(input) )
81 bbtkError("The box \""<<to->bbGetTypeName()<<
82 "\" has no input \""<<input<<"\"");
85 if (to->bbGetInputConnectorMap().find(input)->second->IsConnected())
87 bbtkError("The input \""<<input<<"\" of the box \""<<to->bbGetName()
88 <<"\" is already connected");
91 // std::string t1 ( from->bbGetOutputType(output).name() );
92 // std::string t2 ( to->bbGetInputType(input).name() );
94 if ( from->bbGetOutputType(output) !=
95 to->bbGetInputType(input) )
97 if ( from->bbGetOutputType(output) == typeid(Data) )
99 bbtkWarning("Connection '"
101 <<"' : '"<<from->bbGetName()<<"."<<output
103 <<HumanTypeName<Data>()
104 <<"> : type compatibility with '"
105 <<to->bbGetName()<<"."<<input
106 <<"' will be resolved at run time"
110 else if ( to->bbGetInputType(input) == typeid(Data) )
112 bbtkDebugMessage("Kernel",8," -> '"<<input<<"' type is "
113 <<TypeName<Data>()<<" : can receive any data"
119 // std::cout << "Adaptive connection "<<std::endl;
121 name = from->bbGetName() + "." + output + "-"
122 + to->bbGetName() + "." + input;
123 mAdaptor = mFactory.lock()
124 ->NewAdaptor(from->bbGetOutputType(output),
125 to->bbGetInputType(input),
129 bbtkError("did not find any <"
130 <<TypeName(from->bbGetOutputType(output))
132 <<TypeName(to->bbGetInputType(input))
140 mOriginalFrom = from;
143 mInput = mOriginalInput = input;
144 mOutput = mOriginalOutput = output;
146 // Lock this pointer !!!
147 //Pointer p = MakePointer(this,true);
148 from->bbConnectOutput(output,this);
149 to->bbConnectInput(input,this);
152 bbtkDebugMessage("connection",1,"<== Connection::Connection(\""
153 <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
154 <<to->bbGetFullName()<<"\",\""<<input<<"\")"
157 bbtkDebugMessage("object",2,"==> Connection::Connection(\""
158 <<from->bbGetName()<<"\",\""<<output<<"\",\""
159 <<to->bbGetName()<<"\",\""<<input<<"\")"
162 //==================================================================
164 //==================================================================
165 Connection::Pointer Connection::New(BlackBox::Pointer from,
166 const std::string& output,
167 BlackBox::Pointer to,
168 const std::string& input )
170 bbtkDebugMessage("object",1,"##> Connection::Connection(\""
171 <<from->bbGetName()<<"\",\""<<output<<"\",\""
172 <<to->bbGetName()<<"\",\""<<input<<"\")"
174 Connection::Pointer p =
175 MakePointer(new Connection(from,output,to,input));
176 bbtkDebugMessage("object",1,"<## Connection::Connection(\""
177 <<from->bbGetName()<<"\",\""<<output<<"\",\""
178 <<to->bbGetName()<<"\",\""<<input<<"\")"
182 //==================================================================
184 //==================================================================
185 /// Ctor with the black box from and to and their input and output.
186 /// Check the input and output compatibility
187 Connection::Connection(BlackBox::Pointer from, const std::string& output,
188 BlackBox::Pointer to, const std::string& input )
194 bbtkDebugMessage("object",2,"==> Connection::Connection(\""
195 <<from->bbGetName()<<"\",\""<<output<<"\",\""
196 <<to->bbGetName()<<"\",\""<<input<<"\")"
199 bbtkDebugMessage("connection",1,"==> Connection::Connection(\""
200 <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
201 <<to->bbGetFullName()<<"\",\""<<input<<"\")"
206 if (! from->bbHasOutput(output) )
208 bbtkError("The box \""<<from->bbGetTypeName()<<
209 "\" has no output \""<<output<<"\"");
211 if (! to->bbHasInput(input) )
213 bbtkError("The box \""<<to->bbGetTypeName()<<
214 "\" has no input \""<<input<<"\"");
217 if (to->bbGetInputConnectorMap().find(input)->second->IsConnected())
219 bbtkError("The input \""<<input<<"\" of the box \""<<to->bbGetName()
220 <<"\" is already connected");
223 // std::string t1 ( from->bbGetOutputType(output).name() );
224 // std::string t2 ( to->bbGetInputType(input).name() );
226 if ( from->bbGetOutputType(output) !=
227 to->bbGetInputType(input) )
229 if ( from->bbGetOutputType(output) == typeid(Data) )
231 bbtkWarning("Connection '"
233 <<"' : '"<<from->bbGetName()<<"."<<output
235 <<HumanTypeName<Data>()
236 <<"> : type compatibility with '"
237 <<to->bbGetName()<<"."<<input
238 <<"' will be resolved at run time"
242 else if ( to->bbGetInputType(input) == typeid(Data) )
244 bbtkDebugMessage("Kernel",8," -> '"<<input<<"' type is "
245 <<TypeName<Data>()<<" : can receive any data"
251 bbtkError("Connection created between different types without Factory provided");
257 mOriginalFrom = from;
260 mInput = mOriginalInput = input;
261 mOutput = mOriginalOutput = output;
263 // Lock this pointer !!!
264 //Pointer p = MakePointer(this,true);
265 from->bbConnectOutput(output,this);
266 to->bbConnectInput(input,this);
269 bbtkDebugMessage("connection",1,"<== Connection::Connection(\""
270 <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
271 <<to->bbGetFullName()<<"\",\""<<input<<"\")"
274 bbtkDebugMessage("object",2,"==> Connection::Connection(\""
275 <<from->bbGetName()<<"\",\""<<output<<"\",\""
276 <<to->bbGetName()<<"\",\""<<input<<"\")"
279 //==================================================================
281 //==================================================================
283 Connection::~Connection()
285 bbtkDebugMessage("object",2,
286 "==> Connection::~Connection() ["
287 <<GetFullName()<<"]"<<std::endl);
289 if (mAdaptor) mAdaptor.reset();
292 mFrom->bbDisconnectOutput(mOutput,this);
293 // GetThisPointer<Connection>());
298 bbtkInternalError("Connection::~Connection() : invalid initial box pointer");
302 mTo->bbDisconnectInput(mInput,this);// GetThisPointer<Connection>());
307 bbtkInternalError("Connection::~Connection() : invalid final box pointer");
311 bbtkDebugMessage("object",2,
312 "<== Connection::~Connection() ["
313 <<GetFullName()<<"]"<<std::endl);
315 //==================================================================
317 //==================================================================
319 IOStatus Connection::BackwardUpdate()
321 bbtkDebugMessage("process",5,
322 "===> Connection::BackwardUpdate() ["
323 <<GetFullName()<<"]"<<std::endl);
325 IOStatus s = UPTODATE;
326 s = mFrom->bbBackwardUpdate(GetThisPointer<Connection>());
330 if (mAdaptor && (s==MODIFIED)) mAdaptor->bbSetModifiedStatus();
332 bbtkDebugMessage("process",5,
333 "<=== Connection::BackwardUpdate() ["
334 <<GetFullName()<<"]"<<std::endl);
337 //==================================================================
340 //==================================================================
342 void Connection::ForwardUpdate()
344 bbtkDebugMessageInc("process",2,
345 "Connection::ForwardUpdate() ["
346 <<GetFullName()<<"]"<<std::endl);
351 mTo->bbForwardUpdate(this);
353 bbtkDebugDecTab("process",2);
355 //==================================================================
358 //==================================================================
359 /// Transfers the data from the source output to the target input
360 /// doing necessary conversions (adaptation or pointer cast)
361 void Connection::TransferData()
363 bbtkDebugMessageInc("data",3,
364 "Connection::TransferData() ["
365 <<GetFullName()<<"]"<<std::endl);
368 // If an adaptor was created we need to adapt the data
371 mAdaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
372 mAdaptor->bbExecute();
373 // LG : Connection Update does not set mTo as modified
374 mTo->bbSetInput(mInput, mAdaptor->bbGetOutput("Out"),false);
377 // If no adaptor but source type is an any and target is not an any
378 else if ( mFromAny && (! mToAny) )
380 bbtkDebugMessage("data",3,
381 " * Source type is an "
382 <<HumanTypeName<Data>()
383 <<" which contains a <"
384 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
386 bbtkDebugMessage("data",3,
387 " * Target type is <"
388 <<HumanTypeName(mTo->bbGetInputType(mInput))
391 // 1) Test strict type matching between any content and target
392 if (mFrom->bbGetOutput(mOutput)
393 .contains( mTo->bbGetInputType(mInput) ) )
395 bbtkDebugMessage("data",3,
396 " -> Equal types : transfer ok"<<std::endl);
397 mTo->bbSetInput( mInput,
398 mFrom->bbGetOutput(mOutput),
403 // 2) Look for an adaptor
404 bbtk::BlackBox::Pointer adaptor;
407 adaptor = mFactory.lock()
408 ->NewAdaptor(mFrom->bbGetOutput(mOutput).type(),
409 mTo->bbGetInputType(mInput),
417 bbtkDebugMessage("data",3," -> Adaptor found : using it"
419 adaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
420 adaptor->bbExecute();
421 // LG : Connection Update does not set mTo as modified
422 mTo->bbSetInput(mInput, adaptor->bbGetOutput("Out"),false);
423 // adaptor->bbDelete();
425 // 3) If no adaptor found but the any content is a pointer
426 // and target type is also a pointer : we try run-time cast
427 else if ( (mFrom->bbGetOutput(mOutput).contains_pointer()) &&
428 (mTo->bbGetDescriptor()->GetInputDescriptor(mInput)
431 bbtkDebugMessage("data",3,
432 " -> No adaptor found but source and target types are both pointers : trying up or down cast"<<std::endl);
435 mFrom->bbGetOutput(mOutput)
436 .get_pointer_to(mTo->bbGetInput(mInput).pointed_type());
439 bbtkError("Connection '"
442 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
444 <<HumanTypeName(mTo->bbGetInputType(mInput))
445 <<"> : no adaptor available and run-time up and down cast failed");
447 mTo->bbBruteForceSetInputPointer(mInput, nptr, false);
449 // 4) Nothing worked : error
452 bbtkError("Connection '"<<GetFullName()<<"' "
453 <<"no adaptor found to convert <"
454 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
456 <<HumanTypeName(mTo->bbGetInputType(mInput))<<">");
460 // EO : mFromAny && ! mToAny
461 // Default case : types are the same; we use simple get-set
464 // LG : Connection Update does not set mTo as modified
465 mTo->bbSetInput(mInput, mFrom->bbGetOutput(mOutput),false);
469 //==================================================================
471 //==================================================================
473 void Connection::SetModifiedStatus()
475 bbtkDebugMessage("modified",2,
476 "==> Connection::SetModifiedStatus() ["
477 <<GetFullName()<<"]"<<std::endl);
479 if (mAdaptor) mAdaptor->bbSetModifiedStatus();
481 mTo->bbSetModifiedStatus( mTo->bbGetInputConnectorMap().find(mInput)->second );
484 bbtkDebugMessage("modified",2,
485 "==> Connection::SetModifiedStatus() ["
486 <<GetFullName()<<"]"<<std::endl);
489 //==================================================================
492 //==================================================================
493 std::string Connection::GetFullName() const {
496 std::string res = mFrom->bbGetName()+"."+mOutput+"--"
497 +mTo->bbGetName()+"."+mInput;
498 if ((!mOriginalFrom.expired()) && (!mOriginalTo.expired()) &&
499 ((mFrom!=mOriginalFrom.lock())||(mTo!=mOriginalTo.lock())))
501 res += "("+mOriginalFrom.lock()->bbGetName()
502 +"."+mOriginalOutput+"--"
503 + mOriginalTo.lock()->bbGetName()+"."+mOriginalInput+")";
507 return "***Invalid Connection***";
509 //==================================================================
511 //==================================================================
512 void Connection::Check() const
514 bbtkMessage("debug",1,"** Checking Connection "<<(void*)this<<" ["<<GetFullName()<<"]"
518 bbtkMessage("debug",2," - From = 0"<<std::endl);
522 bbtkMessage("debug",2," - From : "<<mFrom->bbGetFullName()<<std::endl);
523 if (!mFrom->bbHasOutput(mOutput))
525 bbtkError("** Checking Connection "<<(void*)this
526 <<" ["<<GetFullName()<<"] : "
527 << mFrom->bbGetFullName()<<" does not have output '"
530 bbtkMessage("debug",2," - From : Output '"<<mOutput<<"' exists"<<std::endl);
531 BlackBox::OutputConnectorMapType::const_iterator i
532 = mFrom->bbGetOutputConnectorMap().find(mOutput);
533 if (i== mFrom->bbGetOutputConnectorMap().end())
535 bbtkError("** Checking Connection "<<(void*)this
536 <<" ["<<GetFullName()<<"] : "
537 <<mFrom->bbGetFullName()<<" output '"
538 <<mOutput<<"' is not in OutputConnectorMap");
540 bbtkMessage("debug",2," - From : Output '"<<mOutput
541 <<"' is in OutputConnectorMap"<<std::endl);
543 std::vector< Connection* >::const_iterator j;
545 for (j = i->second->GetConnectionVector().begin();
546 j != i->second->GetConnectionVector().end();
549 if ((*j)==this) break;
552 j = find(i->second->GetConnectionVector().begin(),
553 i->second->GetConnectionVector().end(),
556 if (j==i->second->GetConnectionVector().end())
558 bbtkError("** Checking Connection "<<(void*)this
559 <<" ["<<GetFullName()<<"] : "
560 << "Connection ["<<GetFullName()<<"] : "
561 <<" OutputConnector '"
562 <<mOutput<<"' of "<<mFrom->bbGetFullName()
563 <<" does not point to this connection");
566 bbtkMessage("debug",2," - From : This connection is in OutputConnector connection vector"<<std::endl);
567 bbtkMessage("debug",2," * Box from : Check successfull"<<std::endl);
573 bbtkMessage("debug",2," - To = 0"<<std::endl);
577 bbtkMessage("debug",2," - To : "<<mTo->bbGetName()<<std::endl);
578 // std::cout << mTo << std::endl;
579 // std::cout << mTo->bbGetDescriptor() << std::endl;
580 // std::cout << mTo->bbGetDescriptor()->GetTypeName() << std::endl;
581 // mTo->bbGetFullName();
582 bbtkMessage("debug",2," - To : "<<mTo->bbGetFullName()<<std::endl);
583 if (!mTo->bbHasInput(mInput))
585 bbtkError("** Checking Connection "<<(void*)this
586 <<" ["<<GetFullName()<<"] : "
587 <<mTo->bbGetFullName()<<" does not have input '"
590 bbtkMessage("debug",2," - To : Input '"<<mInput<<"' exists"<<std::endl);
591 BlackBox::InputConnectorMapType::const_iterator i
592 = mTo->bbGetInputConnectorMap().find(mInput);
593 if (i== mTo->bbGetInputConnectorMap().end())
595 bbtkError("** Checking Connection "<<(void*)this
596 <<" ["<<GetFullName()<<"] : "
597 <<mTo->bbGetFullName()<<" input '"
598 <<mInput<<"' is not in InputConnectorMap");
600 bbtkMessage("debug",2," - To : Input '"<<mInput
601 <<"' is in InputConnectorMap"<<std::endl);
603 if (i->second->GetConnection()==0)
605 bbtkError("** Checking Connection "<<(void*)this
606 <<" ["<<GetFullName()<<"] : "
607 <<"Connection "<<GetFullName()<<" : "
608 <<" InputConnector '"
609 <<mInput<<"' of "<<mTo->bbGetFullName()
610 <<" does not point to this connection");
613 bbtkMessage("debug",2," - To : This connection is in InputConnector connection vector"<<std::endl);
614 bbtkMessage("debug",2," * Box to : Check successfull"<<std::endl);
618 //==================================================================
619 //==========================================================================
620 std::string Connection::GetObjectName() const
622 std::string s("Connection '");
627 //==========================================================================
629 //==========================================================================
630 std::string Connection::GetObjectInfo() const
635 //==========================================================================
637 //==========================================================================
638 size_t Connection::GetObjectSize() const
640 size_t s = Superclass::GetObjectSize();
641 s += Connection::GetObjectInternalSize();
644 //==========================================================================
645 //==========================================================================
646 size_t Connection::GetObjectInternalSize() const
648 size_t s = sizeof(Connection);
651 //==========================================================================
652 //==========================================================================
653 size_t Connection::GetObjectRecursiveSize() const
655 size_t s = Superclass::GetObjectRecursiveSize();
656 s += Connection::GetObjectInternalSize();
659 //==========================================================================