1 /*=========================================================================
3 Module: $RCSfile: bbtkConnection.cxx,v $
5 Date: $Date: 2008/10/17 08:18:13 $
6 Version: $Revision: 1.15 $
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"
43 //==================================================================
44 Connection::Pointer Connection::New(BlackBox::Pointer from,
45 const std::string& output,
47 const std::string& input ,
48 const Factory::Pointer f )
50 bbtkDebugMessage("object",1,"##> Connection::Connection(\""
51 <<from->bbGetName()<<"\",\""<<output<<"\",\""
52 <<to->bbGetName()<<"\",\""<<input<<"\")"
54 Connection::Pointer p =
55 MakePointer(new Connection(from,output,to,input,f));
56 bbtkDebugMessage("object",1,"<## Connection::Connection(\""
57 <<from->bbGetName()<<"\",\""<<output<<"\",\""
58 <<to->bbGetName()<<"\",\""<<input<<"\")"
62 //==================================================================
64 //==================================================================
65 /// Ctor with the black box from and to and their input and output.
66 /// Check the input and output compatibility
67 Connection::Connection(BlackBox::Pointer from, const std::string& output,
68 BlackBox::Pointer to, const std::string& input ,
69 const Factory::Pointer f )
75 bbtkDebugMessage("object",2,"==> Connection::Connection(\""
76 <<from->bbGetName()<<"\",\""<<output<<"\",\""
77 <<to->bbGetName()<<"\",\""<<input<<"\")"
80 bbtkDebugMessage("connection",1,"==> Connection::Connection(\""
81 <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
82 <<to->bbGetFullName()<<"\",\""<<input<<"\")"
87 if (! from->bbHasOutput(output) )
89 bbtkError("The box \""<<from->bbGetTypeName()<<
90 "\" has no output \""<<output<<"\"");
92 if (! to->bbHasInput(input) )
94 bbtkError("The box \""<<to->bbGetTypeName()<<
95 "\" has no input \""<<input<<"\"");
98 if (to->bbGetInputConnectorMap().find(input)->second->IsConnected())
100 bbtkError("The input \""<<input<<"\" of the box \""<<to->bbGetName()
101 <<"\" is already connected");
104 // std::string t1 ( from->bbGetOutputType(output).name() );
105 // std::string t2 ( to->bbGetInputType(input).name() );
107 if ( from->bbGetOutputType(output) !=
108 to->bbGetInputType(input) )
110 if ( from->bbGetOutputType(output) == typeid(Data) )
112 bbtkWarning("Connection '"
114 <<"' : '"<<from->bbGetName()<<"."<<output
116 <<HumanTypeName<Data>()
117 <<"> : type compatibility with '"
118 <<to->bbGetName()<<"."<<input
119 <<"' will be resolved at run time"
123 else if ( to->bbGetInputType(input) == typeid(Data) )
125 bbtkDebugMessage("Kernel",8," -> '"<<input<<"' type is "
126 <<TypeName<Data>()<<" : can receive any data"
132 // std::cout << "Adaptive connection "<<std::endl;
134 name = from->bbGetName() + "." + output + "-"
135 + to->bbGetName() + "." + input;
136 mAdaptor = mFactory.lock()
137 ->NewAdaptor(from->bbGetOutputType(output),
138 to->bbGetInputType(input),
142 bbtkError("did not find any <"
143 <<TypeName(from->bbGetOutputType(output))
145 <<TypeName(to->bbGetInputType(input))
153 mOriginalFrom = from;
156 mInput = mOriginalInput = input;
157 mOutput = mOriginalOutput = output;
159 // Lock this pointer !!!
160 //Pointer p = MakePointer(this,true);
161 from->bbConnectOutput(output,this);
162 to->bbConnectInput(input,this);
165 bbtkDebugMessage("connection",1,"<== Connection::Connection(\""
166 <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
167 <<to->bbGetFullName()<<"\",\""<<input<<"\")"
170 bbtkDebugMessage("object",2,"==> Connection::Connection(\""
171 <<from->bbGetName()<<"\",\""<<output<<"\",\""
172 <<to->bbGetName()<<"\",\""<<input<<"\")"
175 //==================================================================
177 //==================================================================
178 Connection::Pointer Connection::New(BlackBox::Pointer from,
179 const std::string& output,
180 BlackBox::Pointer to,
181 const std::string& input )
183 bbtkDebugMessage("object",1,"##> Connection::Connection(\""
184 <<from->bbGetName()<<"\",\""<<output<<"\",\""
185 <<to->bbGetName()<<"\",\""<<input<<"\")"
187 Connection::Pointer p =
188 MakePointer(new Connection(from,output,to,input));
189 bbtkDebugMessage("object",1,"<## Connection::Connection(\""
190 <<from->bbGetName()<<"\",\""<<output<<"\",\""
191 <<to->bbGetName()<<"\",\""<<input<<"\")"
195 //==================================================================
197 //==================================================================
198 /// Ctor with the black box from and to and their input and output.
199 /// Check the input and output compatibility
200 Connection::Connection(BlackBox::Pointer from, const std::string& output,
201 BlackBox::Pointer to, const std::string& input )
207 bbtkDebugMessage("object",2,"==> Connection::Connection(\""
208 <<from->bbGetName()<<"\",\""<<output<<"\",\""
209 <<to->bbGetName()<<"\",\""<<input<<"\")"
212 bbtkDebugMessage("connection",1,"==> Connection::Connection(\""
213 <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
214 <<to->bbGetFullName()<<"\",\""<<input<<"\")"
219 if (! from->bbHasOutput(output) )
221 bbtkError("The box \""<<from->bbGetTypeName()<<
222 "\" has no output \""<<output<<"\"");
224 if (! to->bbHasInput(input) )
226 bbtkError("The box \""<<to->bbGetTypeName()<<
227 "\" has no input \""<<input<<"\"");
230 if (to->bbGetInputConnectorMap().find(input)->second->IsConnected())
232 bbtkError("The input \""<<input<<"\" of the box \""<<to->bbGetName()
233 <<"\" is already connected");
236 // std::string t1 ( from->bbGetOutputType(output).name() );
237 // std::string t2 ( to->bbGetInputType(input).name() );
239 if ( from->bbGetOutputType(output) !=
240 to->bbGetInputType(input) )
242 if ( from->bbGetOutputType(output) == typeid(Data) )
244 bbtkWarning("Connection '"
246 <<"' : '"<<from->bbGetName()<<"."<<output
248 <<HumanTypeName<Data>()
249 <<"> : type compatibility with '"
250 <<to->bbGetName()<<"."<<input
251 <<"' will be resolved at run time"
255 else if ( to->bbGetInputType(input) == typeid(Data) )
257 bbtkDebugMessage("Kernel",8," -> '"<<input<<"' type is "
258 <<TypeName<Data>()<<" : can receive any data"
264 bbtkError("Connection created between different types without Factory provided");
270 mOriginalFrom = from;
273 mInput = mOriginalInput = input;
274 mOutput = mOriginalOutput = output;
276 // Lock this pointer !!!
277 //Pointer p = MakePointer(this,true);
278 from->bbConnectOutput(output,this);
279 to->bbConnectInput(input,this);
282 bbtkDebugMessage("connection",1,"<== Connection::Connection(\""
283 <<from->bbGetFullName()<<"\",\""<<output<<"\",\""
284 <<to->bbGetFullName()<<"\",\""<<input<<"\")"
287 bbtkDebugMessage("object",2,"==> Connection::Connection(\""
288 <<from->bbGetName()<<"\",\""<<output<<"\",\""
289 <<to->bbGetName()<<"\",\""<<input<<"\")"
292 //==================================================================
294 //==================================================================
296 Connection::~Connection()
298 bbtkDebugMessage("object",2,
299 "==> Connection::~Connection() ["
300 <<GetFullName()<<"]"<<std::endl);
302 if (mAdaptor) mAdaptor.reset();
305 mFrom->bbDisconnectOutput(mOutput,this);
306 // GetThisPointer<Connection>());
311 bbtkInternalError("Connection::~Connection() : invalid initial box pointer");
315 mTo->bbDisconnectInput(mInput,this);// GetThisPointer<Connection>());
320 bbtkInternalError("Connection::~Connection() : invalid final box pointer");
324 bbtkDebugMessage("object",2,
325 "<== Connection::~Connection() ["
326 <<GetFullName()<<"]"<<std::endl);
328 //==================================================================
330 //==================================================================
332 IOStatus Connection::BackwardUpdate()
334 bbtkDebugMessage("process",5,
335 "===> Connection::BackwardUpdate() ["
336 <<GetFullName()<<"]"<<std::endl);
338 IOStatus s = UPTODATE;
339 s = mFrom->bbBackwardUpdate(GetThisPointer<Connection>());
343 if (mAdaptor && (s==MODIFIED)) mAdaptor->bbSetModifiedStatus();
345 bbtkDebugMessage("process",5,
346 "<=== Connection::BackwardUpdate() ["
347 <<GetFullName()<<"]"<<std::endl);
350 //==================================================================
353 //==================================================================
355 void Connection::ForwardUpdate()
357 bbtkDebugMessageInc("process",2,
358 "Connection::ForwardUpdate() ["
359 <<GetFullName()<<"]"<<std::endl);
364 mTo->bbForwardUpdate(this);
366 bbtkDebugDecTab("process",2);
368 //==================================================================
371 //==================================================================
372 /// Transfers the data from the source output to the target input
373 /// doing necessary conversions (adaptation or pointer cast)
374 void Connection::TransferData()
376 bbtkDebugMessageInc("data",3,
377 "Connection::TransferData() ["
378 <<GetFullName()<<"]"<<std::endl);
381 // If an adaptor was created we need to adapt the data
384 mAdaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
385 mAdaptor->bbExecute();
386 // LG : Connection Update does not set mTo as modified
387 mTo->bbSetInput(mInput, mAdaptor->bbGetOutput("Out"),false);
390 // If no adaptor but source type is an any and target is not an any
391 else if ( mFromAny && (! mToAny) )
393 bbtkDebugMessage("data",3,
394 " * Source type is an "
395 <<HumanTypeName<Data>()
396 <<" which contains a <"
397 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
399 bbtkDebugMessage("data",3,
400 " * Target type is <"
401 <<HumanTypeName(mTo->bbGetInputType(mInput))
404 // 1) Test strict type matching between any content and target
405 if (mFrom->bbGetOutput(mOutput)
406 .contains( mTo->bbGetInputType(mInput) ) )
408 bbtkDebugMessage("data",3,
409 " -> Equal types : transfer ok"<<std::endl);
410 mTo->bbSetInput( mInput,
411 mFrom->bbGetOutput(mOutput),
416 // 2) Look for an adaptor
417 bbtk::BlackBox::Pointer adaptor;
420 adaptor = mFactory.lock()
421 ->NewAdaptor(mFrom->bbGetOutput(mOutput).type(),
422 mTo->bbGetInputType(mInput),
430 bbtkDebugMessage("data",3," -> Adaptor found : using it"
432 adaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
433 adaptor->bbExecute();
434 // LG : Connection Update does not set mTo as modified
435 mTo->bbSetInput(mInput, adaptor->bbGetOutput("Out"),false);
436 // adaptor->bbDelete();
438 // 3) If no adaptor found but the any content is a pointer
439 // and target type is also a pointer : we try run-time cast
440 else if ( (mFrom->bbGetOutput(mOutput).contains_pointer()) &&
441 (mTo->bbGetDescriptor()->GetInputDescriptor(mInput)
444 bbtkDebugMessage("data",3,
445 " -> No adaptor found but source and target types are both pointers : trying up or down cast"<<std::endl);
448 mFrom->bbGetOutput(mOutput)
449 .get_pointer_to(mTo->bbGetInput(mInput).pointed_type());
452 bbtkError("Connection '"
455 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
457 <<HumanTypeName(mTo->bbGetInputType(mInput))
458 <<"> : no adaptor available and run-time up and down cast failed");
460 mTo->bbBruteForceSetInputPointer(mInput, nptr, false);
462 // 4) Nothing worked : error
465 bbtkError("Connection '"<<GetFullName()<<"' "
466 <<"no adaptor found to convert <"
467 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
469 <<HumanTypeName(mTo->bbGetInputType(mInput))<<">");
473 // EO : mFromAny && ! mToAny
474 // Default case : types are the same; we use simple get-set
477 // LG : Connection Update does not set mTo as modified
478 mTo->bbSetInput(mInput, mFrom->bbGetOutput(mOutput),false);
482 //==================================================================
484 //==================================================================
486 void Connection::SetModifiedStatus()
488 bbtkDebugMessage("modified",2,
489 "==> Connection::SetModifiedStatus() ["
490 <<GetFullName()<<"]"<<std::endl);
492 if (mAdaptor) mAdaptor->bbSetModifiedStatus();
494 mTo->bbSetModifiedStatus( mTo->bbGetInputConnectorMap().find(mInput)->second );
497 bbtkDebugMessage("modified",2,
498 "==> Connection::SetModifiedStatus() ["
499 <<GetFullName()<<"]"<<std::endl);
502 //==================================================================
505 //==================================================================
506 std::string Connection::GetFullName() const {
509 std::string res = mFrom->bbGetName()+"."+mOutput+"--"
510 +mTo->bbGetName()+"."+mInput;
511 if ((!mOriginalFrom.expired()) && (!mOriginalTo.expired()) &&
512 ((mFrom!=mOriginalFrom.lock())||(mTo!=mOriginalTo.lock())))
514 res += "("+mOriginalFrom.lock()->bbGetName()
515 +"."+mOriginalOutput+"--"
516 + mOriginalTo.lock()->bbGetName()+"."+mOriginalInput+")";
520 return "***Invalid Connection***";
522 //==================================================================
524 //==================================================================
525 void Connection::Check() const
527 bbtkMessage("debug",1,"** Checking Connection "<<(void*)this<<" ["<<GetFullName()<<"]"
531 bbtkMessage("debug",2," - From = 0"<<std::endl);
535 bbtkMessage("debug",2," - From : "<<mFrom->bbGetFullName()<<std::endl);
536 if (!mFrom->bbHasOutput(mOutput))
538 bbtkError("** Checking Connection "<<(void*)this
539 <<" ["<<GetFullName()<<"] : "
540 << mFrom->bbGetFullName()<<" does not have output '"
543 bbtkMessage("debug",2," - From : Output '"<<mOutput<<"' exists"<<std::endl);
544 BlackBox::OutputConnectorMapType::const_iterator i
545 = mFrom->bbGetOutputConnectorMap().find(mOutput);
546 if (i== mFrom->bbGetOutputConnectorMap().end())
548 bbtkError("** Checking Connection "<<(void*)this
549 <<" ["<<GetFullName()<<"] : "
550 <<mFrom->bbGetFullName()<<" output '"
551 <<mOutput<<"' is not in OutputConnectorMap");
553 bbtkMessage("debug",2," - From : Output '"<<mOutput
554 <<"' is in OutputConnectorMap"<<std::endl);
556 std::vector< Connection* >::const_iterator j;
558 for (j = i->second->GetConnectionVector().begin();
559 j != i->second->GetConnectionVector().end();
562 if ((*j)==this) break;
565 j = find(i->second->GetConnectionVector().begin(),
566 i->second->GetConnectionVector().end(),
569 if (j==i->second->GetConnectionVector().end())
571 bbtkError("** Checking Connection "<<(void*)this
572 <<" ["<<GetFullName()<<"] : "
573 << "Connection ["<<GetFullName()<<"] : "
574 <<" OutputConnector '"
575 <<mOutput<<"' of "<<mFrom->bbGetFullName()
576 <<" does not point to this connection");
579 bbtkMessage("debug",2," - From : This connection is in OutputConnector connection vector"<<std::endl);
580 bbtkMessage("debug",2," * Box from : Check successfull"<<std::endl);
586 bbtkMessage("debug",2," - To = 0"<<std::endl);
590 bbtkMessage("debug",2," - To : "<<mTo->bbGetName()<<std::endl);
591 // std::cout << mTo << std::endl;
592 // std::cout << mTo->bbGetDescriptor() << std::endl;
593 // std::cout << mTo->bbGetDescriptor()->GetTypeName() << std::endl;
594 // mTo->bbGetFullName();
595 bbtkMessage("debug",2," - To : "<<mTo->bbGetFullName()<<std::endl);
596 if (!mTo->bbHasInput(mInput))
598 bbtkError("** Checking Connection "<<(void*)this
599 <<" ["<<GetFullName()<<"] : "
600 <<mTo->bbGetFullName()<<" does not have input '"
603 bbtkMessage("debug",2," - To : Input '"<<mInput<<"' exists"<<std::endl);
604 BlackBox::InputConnectorMapType::const_iterator i
605 = mTo->bbGetInputConnectorMap().find(mInput);
606 if (i== mTo->bbGetInputConnectorMap().end())
608 bbtkError("** Checking Connection "<<(void*)this
609 <<" ["<<GetFullName()<<"] : "
610 <<mTo->bbGetFullName()<<" input '"
611 <<mInput<<"' is not in InputConnectorMap");
613 bbtkMessage("debug",2," - To : Input '"<<mInput
614 <<"' is in InputConnectorMap"<<std::endl);
616 if (i->second->GetConnection()==0)
618 bbtkError("** Checking Connection "<<(void*)this
619 <<" ["<<GetFullName()<<"] : "
620 <<"Connection "<<GetFullName()<<" : "
621 <<" InputConnector '"
622 <<mInput<<"' of "<<mTo->bbGetFullName()
623 <<" does not point to this connection");
626 bbtkMessage("debug",2," - To : This connection is in InputConnector connection vector"<<std::endl);
627 bbtkMessage("debug",2," * Box to : Check successfull"<<std::endl);
631 //==================================================================
632 //==========================================================================
633 std::string Connection::GetObjectName() const
635 std::string s("Connection '");
640 //==========================================================================
642 //==========================================================================
643 std::string Connection::GetObjectInfo() const
648 //==========================================================================
650 //==========================================================================
651 size_t Connection::GetObjectSize() const
653 size_t s = Superclass::GetObjectSize();
654 s += Connection::GetObjectInternalSize();
657 //==========================================================================
658 //==========================================================================
659 size_t Connection::GetObjectInternalSize() const
661 size_t s = sizeof(Connection);
664 //==========================================================================
665 //==========================================================================
666 size_t Connection::GetObjectRecursiveSize() const
668 size_t s = Superclass::GetObjectRecursiveSize();
669 s += Connection::GetObjectInternalSize();
672 //==========================================================================