1 /*=========================================================================
3 Module: $RCSfile: bbtkConnection.cxx,v $
5 Date: $Date: 2008/12/09 11:48:31 $
6 Version: $Revision: 1.18 $
7 =========================================================================*/
9 /* ---------------------------------------------------------------------
11 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
12 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
14 * This software is governed by the CeCILL-B license under French law and
15 * abiding by the rules of distribution of free software. You can use,
16 * modify and/ or redistribute the software under the terms of the CeCILL-B
17 * license as circulated by CEA, CNRS and INRIA at the following URL
18 * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
19 * or in the file LICENSE.txt.
21 * As a counterpart to the access to the source code and rights to copy,
22 * modify and redistribute granted by the license, users are provided only
23 * with a limited warranty and the software's author, the holder of the
24 * economic rights, and the successive licensors have only limited
27 * The fact that you are presently reading this means that you have had
28 * knowledge of the CeCILL-B license and that you accept its terms.
29 * ------------------------------------------------------------------------ */
33 *\brief Class bbtk::Connection
36 #include "bbtkConnection.h"
37 #include "bbtkFactory.h"
38 #include "bbtkBlackBox.h"
39 #include "bbtkMessageManager.h"
40 #include "bbtkBlackBoxOutputConnector.h"
44 const std::string IOSTATUS_STRING[3] =
45 {"Up-to-date","Modified","Out-of-date"};
47 const std::string& GetIOStatusString(IOStatus s)
48 { return IOSTATUS_STRING[s]; }
50 //==================================================================
51 Connection::Pointer Connection::New(BlackBox::Pointer from,
52 const std::string& output,
54 const std::string& input ,
55 const Factory::Pointer f )
57 bbtkDebugMessage("object",1,"##> Connection::Connection(\""
58 <<from->bbGetName()<<"\",\""<<output<<"\",\""
59 <<to->bbGetName()<<"\",\""<<input<<"\")"
61 Connection::Pointer p =
62 MakePointer(new Connection(from,output,to,input,f));
63 bbtkDebugMessage("object",1,"<## Connection::Connection(\""
64 <<from->bbGetName()<<"\",\""<<output<<"\",\""
65 <<to->bbGetName()<<"\",\""<<input<<"\")"
69 //==================================================================
71 //==================================================================
72 /// Ctor with the black box from and to and their input and output.
73 /// Check the input and output compatibility
74 Connection::Connection(BlackBox::Pointer from, const std::string& output,
75 BlackBox::Pointer to, const std::string& input ,
76 const Factory::Pointer f )
82 bbtkDebugMessage("object",2,"==> Connection::Connection(\""
83 <<from->bbGetName()<<"\",\""<<output<<"\",\""
84 <<to->bbGetName()<<"\",\""<<input<<"\")"
87 bbtkDebugMessage("connection",1,"==> Connection::Connection(\""
88 <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
89 <<to->bbGetFullName()<<"\",\""<<input<<"\")"
94 if (! from->bbHasOutput(output) )
96 bbtkError("The box \""<<from->bbGetTypeName()<<
97 "\" has no output \""<<output<<"\"");
99 if (! to->bbHasInput(input) )
101 bbtkError("The box \""<<to->bbGetTypeName()<<
102 "\" has no input \""<<input<<"\"");
105 if (to->bbGetInputConnectorMap().find(input)->second->IsConnected())
107 bbtkError("The input \""<<input<<"\" of the box \""<<to->bbGetName()
108 <<"\" is already connected");
111 // std::string t1 ( from->bbGetOutputType(output).name() );
112 // std::string t2 ( to->bbGetInputType(input).name() );
114 if ( from->bbGetOutputType(output) !=
115 to->bbGetInputType(input) )
117 if ( from->bbGetOutputType(output) == typeid(Data) )
119 bbtkWarning("Connection '"
121 <<"' : '"<<from->bbGetName()<<"."<<output
123 <<HumanTypeName<Data>()
124 <<"> : type compatibility with '"
125 <<to->bbGetName()<<"."<<input
126 <<"' will be resolved at run time"
130 else if ( to->bbGetInputType(input) == typeid(Data) )
132 bbtkDebugMessage("Kernel",8," -> '"<<input<<"' type is "
133 <<TypeName<Data>()<<" : can receive any data"
139 // std::cout << "Adaptive connection "<<std::endl;
141 name = from->bbGetName() + "." + output + "-"
142 + to->bbGetName() + "." + input;
143 mAdaptor = mFactory.lock()
144 ->NewAdaptor(from->bbGetOutputType(output),
145 to->bbGetInputType(input),
149 bbtkError("did not find any <"
150 <<TypeName(from->bbGetOutputType(output))
152 <<TypeName(to->bbGetInputType(input))
160 mOriginalFrom = from;
163 mInput = mOriginalInput = input;
164 mOutput = mOriginalOutput = output;
166 // Lock this pointer !!!
167 //Pointer p = MakePointer(this,true);
168 from->bbConnectOutput(output,this);
169 to->bbConnectInput(input,this);
171 from->bbGetOutputConnector(output).AddChangeObserver(boost::bind(&bbtk::Connection::OnOutputChange,this, _1, _2, _3));
174 bbtkDebugMessage("connection",1,"<== Connection::Connection(\""
175 <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
176 <<to->bbGetFullName()<<"\",\""<<input<<"\")"
179 bbtkDebugMessage("object",2,"==> Connection::Connection(\""
180 <<from->bbGetName()<<"\",\""<<output<<"\",\""
181 <<to->bbGetName()<<"\",\""<<input<<"\")"
184 //==================================================================
186 //==================================================================
187 Connection::Pointer Connection::New(BlackBox::Pointer from,
188 const std::string& output,
189 BlackBox::Pointer to,
190 const std::string& input )
192 bbtkDebugMessage("object",1,"##> Connection::Connection(\""
193 <<from->bbGetName()<<"\",\""<<output<<"\",\""
194 <<to->bbGetName()<<"\",\""<<input<<"\")"
196 Connection::Pointer p =
197 MakePointer(new Connection(from,output,to,input));
198 bbtkDebugMessage("object",1,"<## Connection::Connection(\""
199 <<from->bbGetName()<<"\",\""<<output<<"\",\""
200 <<to->bbGetName()<<"\",\""<<input<<"\")"
204 //==================================================================
206 //==================================================================
207 /// Ctor with the black box from and to and their input and output.
208 /// Check the input and output compatibility
209 Connection::Connection(BlackBox::Pointer from, const std::string& output,
210 BlackBox::Pointer to, const std::string& input )
216 bbtkDebugMessage("object",2,"==> Connection::Connection(\""
217 <<from->bbGetName()<<"\",\""<<output<<"\",\""
218 <<to->bbGetName()<<"\",\""<<input<<"\")"
221 bbtkDebugMessage("connection",1,"==> Connection::Connection(\""
222 <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
223 <<to->bbGetFullName()<<"\",\""<<input<<"\")"
228 if (! from->bbHasOutput(output) )
230 bbtkError("The box \""<<from->bbGetTypeName()<<
231 "\" has no output \""<<output<<"\"");
233 if (! to->bbHasInput(input) )
235 bbtkError("The box \""<<to->bbGetTypeName()<<
236 "\" has no input \""<<input<<"\"");
239 if (to->bbGetInputConnectorMap().find(input)->second->IsConnected())
241 bbtkError("The input \""<<input<<"\" of the box \""<<to->bbGetName()
242 <<"\" is already connected");
245 // std::string t1 ( from->bbGetOutputType(output).name() );
246 // std::string t2 ( to->bbGetInputType(input).name() );
248 if ( from->bbGetOutputType(output) !=
249 to->bbGetInputType(input) )
251 if ( from->bbGetOutputType(output) == typeid(Data) )
253 bbtkWarning("Connection '"
255 <<"' : '"<<from->bbGetName()<<"."<<output
257 <<HumanTypeName<Data>()
258 <<"> : type compatibility with '"
259 <<to->bbGetName()<<"."<<input
260 <<"' will be resolved at run time"
264 else if ( to->bbGetInputType(input) == typeid(Data) )
266 bbtkDebugMessage("Kernel",8," -> '"<<input<<"' type is "
267 <<TypeName<Data>()<<" : can receive any data"
273 bbtkError("Connection created between different types without Factory provided");
279 mOriginalFrom = from;
282 mInput = mOriginalInput = input;
283 mOutput = mOriginalOutput = output;
285 // Lock this pointer !!!
286 //Pointer p = MakePointer(this,true);
287 from->bbConnectOutput(output,this);
288 to->bbConnectInput(input,this);
290 from->bbGetOutputConnector(output).AddChangeObserver(boost::bind(&bbtk::Connection::OnOutputChange,this, _1, _2, _3));
292 bbtkDebugMessage("connection",1,"<== Connection::Connection(\""
293 <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
294 <<to->bbGetFullName()<<"\",\""<<input<<"\")"
297 bbtkDebugMessage("object",2,"==> Connection::Connection(\""
298 <<from->bbGetName()<<"\",\""<<output<<"\",\""
299 <<to->bbGetName()<<"\",\""<<input<<"\")"
302 //==================================================================
304 //==================================================================
306 Connection::~Connection()
308 bbtkDebugMessage("object",2,
309 "==> Connection::~Connection() ["
310 <<GetFullName()<<"]"<<std::endl);
312 if (mAdaptor) mAdaptor.reset();
315 mFrom->bbDisconnectOutput(mOutput,this);
316 // GetThisPointer<Connection>());
321 bbtkInternalError("Connection::~Connection() : invalid initial box pointer");
325 mTo->bbDisconnectInput(mInput,this);// GetThisPointer<Connection>());
330 bbtkInternalError("Connection::~Connection() : invalid final box pointer");
334 bbtkDebugMessage("object",2,
335 "<== Connection::~Connection() ["
336 <<GetFullName()<<"]"<<std::endl);
338 //==================================================================
340 //==================================================================
342 void Connection::BackwardUpdate()
344 bbtkDebugMessage("process",3,
345 "===> Connection::BackwardUpdate() ["
346 <<GetFullName()<<"]"<<std::endl);
348 mFrom->bbBackwardUpdate(GetThisPointer<Connection>());
353 IOStatus s = MODIFIED;
354 if ( mFrom->bbGetOutputConnector(mOutput).GetStatus() == OUTOFDATE)
358 mTo->bbGetInputConnector(mInput).SetStatus(s);
360 bbtkDebugMessage("process",3,
361 " --> '"<<mTo->bbGetName()<<"."<<mInput
362 <<" ["<<&mTo->bbGetInputConnector(mInput)<<"] "
364 <<GetIOStatusString(s)
368 bbtkDebugMessage("process",3,
369 "<=== Connection::BackwardUpdate() ["
370 <<GetFullName()<<"]"<<std::endl);
373 //==================================================================
376 //==================================================================
378 void Connection::ForwardUpdate()
380 bbtkDebugMessageInc("process",2,
381 "Connection::ForwardUpdate() ["
382 <<GetFullName()<<"]"<<std::endl);
387 mTo->bbForwardUpdate(this);
389 bbtkDebugDecTab("process",2);
391 //==================================================================
394 //==================================================================
395 /// Transfers the data from the source output to the target input
396 /// doing necessary conversions (adaptation or pointer cast)
397 void Connection::TransferData()
399 bbtkDebugMessageInc("data",3,
400 "Connection::TransferData() ["
401 <<GetFullName()<<"]"<<std::endl);
404 // If an adaptor was created we need to adapt the data
407 mAdaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
408 mAdaptor->bbExecute();
409 // LG : Connection Update does not set mTo as modified
410 mTo->bbSetInput(mInput, mAdaptor->bbGetOutput("Out"),false);
413 // If no adaptor but source type is an any and target is not an any
414 else if ( mFromAny && (! mToAny) )
416 bbtkDebugMessage("data",3,
417 " * Source type is an "
418 <<HumanTypeName<Data>()
419 <<" which contains a <"
420 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
422 bbtkDebugMessage("data",3,
423 " * Target type is <"
424 <<HumanTypeName(mTo->bbGetInputType(mInput))
427 // 1) Test strict type matching between any content and target
428 if (mFrom->bbGetOutput(mOutput)
429 .contains( mTo->bbGetInputType(mInput) ) )
431 bbtkDebugMessage("data",3,
432 " -> Equal types : transfer ok"<<std::endl);
433 mTo->bbSetInput( mInput,
434 mFrom->bbGetOutput(mOutput),
439 // 2) Look for an adaptor
440 bbtk::BlackBox::Pointer adaptor;
443 adaptor = mFactory.lock()
444 ->NewAdaptor(mFrom->bbGetOutput(mOutput).type(),
445 mTo->bbGetInputType(mInput),
453 bbtkDebugMessage("data",3," -> Adaptor found : using it"
455 adaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
456 adaptor->bbExecute();
457 // LG : Connection Update does not set mTo as modified
458 mTo->bbSetInput(mInput, adaptor->bbGetOutput("Out"),false);
459 // adaptor->bbDelete();
461 // 3) If no adaptor found but the any content is a pointer
462 // and target type is also a pointer : we try run-time cast
463 else if ( (mFrom->bbGetOutput(mOutput).contains_pointer()) &&
464 (mTo->bbGetDescriptor()->GetInputDescriptor(mInput)
467 bbtkDebugMessage("data",3,
468 " -> No adaptor found but source and target types are both pointers : trying up or down cast"<<std::endl);
471 mFrom->bbGetOutput(mOutput)
472 .get_pointer_to(mTo->bbGetInput(mInput).pointed_type());
475 bbtkError("Connection '"
478 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
480 <<HumanTypeName(mTo->bbGetInputType(mInput))
481 <<"> : no adaptor available and run-time up and down cast failed");
483 mTo->bbBruteForceSetInputPointer(mInput, nptr, false);
485 // 4) Nothing worked : error
488 bbtkError("Connection '"<<GetFullName()<<"' "
489 <<"no adaptor found to convert <"
490 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
492 <<HumanTypeName(mTo->bbGetInputType(mInput))<<">");
496 // EO : mFromAny && ! mToAny
497 // Default case : types are the same; we use simple get-set
500 // LG : Connection Update does not set mTo as modified
501 mTo->bbSetInput(mInput, mFrom->bbGetOutput(mOutput),false);
505 //==================================================================
508 //==================================================================
510 void Connection::SetModifiedStatus()
512 bbtkDebugMessage("modified",2,
513 "==> Connection::SetModifiedStatus() ["
514 <<GetFullName()<<"]"<<std::endl);
516 if (mAdaptor) mAdaptor->bbSetModifiedStatus();
518 mTo->bbSetModifiedStatus( mTo->bbGetInputConnectorMap().find(mInput)->second );
522 //==================================================================
524 //==================================================================
525 /// From.Output change propagation
526 void Connection::OnOutputChange(bbtk::BlackBox::Pointer, const std::string&,
529 bbtkDebugMessage("change",2,
530 "==> Connection::OnOutputChange("
531 <<GetIOStatusString(status)<<") ["
532 <<GetFullName()<<"]"<<std::endl);
535 BlackBoxInputConnector* ac = mAdaptor->bbGetInputConnectorMap().find("In")->second;
536 mAdaptor->bbSetStatusAndPropagate(ac,status);
539 mTo->bbSetStatusAndPropagate( mTo->bbGetInputConnectorMap().find(mInput)->second, status);
543 //==================================================================
546 //==================================================================
547 std::string Connection::GetFullName() const {
550 std::string res = mFrom->bbGetName()+"."+mOutput+"--"
551 +mTo->bbGetName()+"."+mInput;
552 if ((!mOriginalFrom.expired()) && (!mOriginalTo.expired()) &&
553 ((mFrom!=mOriginalFrom.lock())||(mTo!=mOriginalTo.lock())))
555 res += "("+mOriginalFrom.lock()->bbGetName()
556 +"."+mOriginalOutput+"--"
557 + mOriginalTo.lock()->bbGetName()+"."+mOriginalInput+")";
561 return "***Invalid Connection***";
563 //==================================================================
565 //==================================================================
566 void Connection::Check() const
568 bbtkMessage("debug",1,"** Checking Connection "<<(void*)this<<" ["<<GetFullName()<<"]"
572 bbtkMessage("debug",2," - From = 0"<<std::endl);
576 bbtkMessage("debug",2," - From : "<<mFrom->bbGetFullName()<<std::endl);
577 if (!mFrom->bbHasOutput(mOutput))
579 bbtkError("** Checking Connection "<<(void*)this
580 <<" ["<<GetFullName()<<"] : "
581 << mFrom->bbGetFullName()<<" does not have output '"
584 bbtkMessage("debug",2," - From : Output '"<<mOutput<<"' exists"<<std::endl);
585 BlackBox::OutputConnectorMapType::const_iterator i
586 = mFrom->bbGetOutputConnectorMap().find(mOutput);
587 if (i== mFrom->bbGetOutputConnectorMap().end())
589 bbtkError("** Checking Connection "<<(void*)this
590 <<" ["<<GetFullName()<<"] : "
591 <<mFrom->bbGetFullName()<<" output '"
592 <<mOutput<<"' is not in OutputConnectorMap");
594 bbtkMessage("debug",2," - From : Output '"<<mOutput
595 <<"' is in OutputConnectorMap"<<std::endl);
597 std::vector< Connection* >::const_iterator j;
599 for (j = i->second->GetConnectionVector().begin();
600 j != i->second->GetConnectionVector().end();
603 if ((*j)==this) break;
606 j = find(i->second->GetConnectionVector().begin(),
607 i->second->GetConnectionVector().end(),
610 if (j==i->second->GetConnectionVector().end())
612 bbtkError("** Checking Connection "<<(void*)this
613 <<" ["<<GetFullName()<<"] : "
614 << "Connection ["<<GetFullName()<<"] : "
615 <<" OutputConnector '"
616 <<mOutput<<"' of "<<mFrom->bbGetFullName()
617 <<" does not point to this connection");
620 bbtkMessage("debug",2," - From : This connection is in OutputConnector connection vector"<<std::endl);
621 bbtkMessage("debug",2," * Box from : Check successfull"<<std::endl);
627 bbtkMessage("debug",2," - To = 0"<<std::endl);
631 bbtkMessage("debug",2," - To : "<<mTo->bbGetName()<<std::endl);
632 // std::cout << mTo << std::endl;
633 // std::cout << mTo->bbGetDescriptor() << std::endl;
634 // std::cout << mTo->bbGetDescriptor()->GetTypeName() << std::endl;
635 // mTo->bbGetFullName();
636 bbtkMessage("debug",2," - To : "<<mTo->bbGetFullName()<<std::endl);
637 if (!mTo->bbHasInput(mInput))
639 bbtkError("** Checking Connection "<<(void*)this
640 <<" ["<<GetFullName()<<"] : "
641 <<mTo->bbGetFullName()<<" does not have input '"
644 bbtkMessage("debug",2," - To : Input '"<<mInput<<"' exists"<<std::endl);
645 BlackBox::InputConnectorMapType::const_iterator i
646 = mTo->bbGetInputConnectorMap().find(mInput);
647 if (i== mTo->bbGetInputConnectorMap().end())
649 bbtkError("** Checking Connection "<<(void*)this
650 <<" ["<<GetFullName()<<"] : "
651 <<mTo->bbGetFullName()<<" input '"
652 <<mInput<<"' is not in InputConnectorMap");
654 bbtkMessage("debug",2," - To : Input '"<<mInput
655 <<"' is in InputConnectorMap"<<std::endl);
657 if (i->second->GetConnection()==0)
659 bbtkError("** Checking Connection "<<(void*)this
660 <<" ["<<GetFullName()<<"] : "
661 <<"Connection "<<GetFullName()<<" : "
662 <<" InputConnector '"
663 <<mInput<<"' of "<<mTo->bbGetFullName()
664 <<" does not point to this connection");
667 bbtkMessage("debug",2," - To : This connection is in InputConnector connection vector"<<std::endl);
668 bbtkMessage("debug",2," * Box to : Check successfull"<<std::endl);
672 //==================================================================
673 //==========================================================================
674 std::string Connection::GetObjectName() const
676 std::string s("Connection '");
681 //==========================================================================
683 //==========================================================================
684 std::string Connection::GetObjectInfo() const
689 //==========================================================================
691 //==========================================================================
692 size_t Connection::GetObjectSize() const
694 size_t s = Superclass::GetObjectSize();
695 s += Connection::GetObjectInternalSize();
698 //==========================================================================
699 //==========================================================================
700 size_t Connection::GetObjectInternalSize() const
702 size_t s = sizeof(Connection);
705 //==========================================================================
706 //==========================================================================
707 size_t Connection::GetObjectRecursiveSize() const
709 size_t s = Superclass::GetObjectRecursiveSize();
710 s += Connection::GetObjectInternalSize();
713 //==========================================================================