/*========================================================================= Program: bbtk Module: $RCSfile: bbtkConnection.cxx,v $ Language: C++ Date: $Date: 2008/04/09 11:16:57 $ Version: $Revision: 1.6 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See doc/license.txt or http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ /** *\file *\brief Class bbtk::Connection */ #include "bbtkConnection.h" #include "bbtkFactory.h" #include "bbtkBlackBox.h" #include "bbtkMessageManager.h" namespace bbtk { //================================================================== /// Ctor with the black box from and to and their input and output. /// Check the input and output compatibility Connection::Connection(BlackBox* from, const std::string& output, BlackBox* to, const std::string& input , const Factory* f ) : mAdaptor(0), mFactory(f), mFromAny(false), mToAny(false) { bbtkDebugMessageInc("Kernel",7,"Connection::Connection(\"" <bbGetName()<<"\",\""<bbGetName()<<"\",\""<bbHasOutput(output) ) { bbtkError("The box \""<bbGetTypeName()<< "\" has no output \""<bbHasInput(input) ) { bbtkError("The box \""<bbGetTypeName()<< "\" has no input \""<bbGetInputConnectorMap().find(input)->second->IsConnected()) { bbtkError("The input \""<bbGetName() <<"\" is already connected"); } // std::string t1 ( from->bbGetOutputType(output).name() ); // std::string t2 ( to->bbGetInputType(input).name() ); // if //( t1 != t2 ) if ( from->bbGetOutputType(output) != to->bbGetInputType(input) ) { if ( from->bbGetOutputType(output) == typeid(Data) ) { bbtkWarning("Connection '" <bbGetName()<<"."<() <<"> : type compatibility with '" <bbGetName()<<"."<bbGetInputType(input) == typeid(Data) ) { bbtkDebugMessage("Kernel",8," -> '"<()<<" : can receive any data" <bbGetName() + "." + output + "-" + to->bbGetName() + "." + input; mAdaptor = mFactory->NewAdaptor(from->bbGetOutputType(output), to->bbGetInputType(input), name); if (!mAdaptor) { bbtkError("did not find any <" <bbGetOutputType(output)) <<"> to <" <bbGetInputType(input)) <<"> adaptor"); } } } // from->bbConnectOutput(output,this); to->bbConnectInput(input,this); bbtkDebugDecTab("Kernel",7); } //================================================================== void Connection::Clear() { mFrom = mOriginalFrom = 0; mTo = mOriginalTo = 0; mAdaptor = 0; } //================================================================== /// Dtor Connection::~Connection() { bbtkDebugMessageInc("Kernel",7, "Connection::~Connection() [" <bbDisconnectOutput(mOutput,this); if (mTo!=0) mTo->bbDisconnectInput(mInput,this); if (mAdaptor!=0) mAdaptor->bbDelete(); bbtkDebugDecTab("Kernel",7); } //================================================================== //================================================================== /// Backward Update IOStatus Connection::BackwardUpdate() { bbtkDebugMessageInc("Process",2, "Connection::BackwardUpdate() [" <bbBackwardUpdate(this); TransferData(); if (mAdaptor && (s==MODIFIED)) mAdaptor->bbSetModifiedStatus(); bbtkDebugDecTab("Process",2); return s; } //================================================================== /* //================================================================== /// Forward Update void Connection::ForwardUpdate() { bbtkDebugMessageInc("Process",2, "Connection::ForwardUpdate() [" <bbForwardUpdate(this); bbtkDebugDecTab("Process",2); } //================================================================== */ //================================================================== /// Transfers the data from the source output to the target input /// doing necessary conversions (adaptation or pointer cast) void Connection::TransferData() { bbtkDebugMessageInc("Process",3, "Connection::TransferData() [" <bbSetInput("In",mFrom->bbGetOutput(mOutput),false); mAdaptor->bbExecute(); // LG : Connection Update does not set mTo as modified mTo->bbSetInput(mInput, mAdaptor->bbGetOutput("Out"),false); } // If no adaptor but source type is an any and target is not an any else if ( mFromAny && (! mToAny) ) { bbtkDebugMessage("Data",3, "Connection::TransferData() [" <() <<" which contains a <" <bbGetOutput(mOutput).type()) <<">"<bbGetInputType(mInput)) <<">"<bbGetOutput(mOutput) .contains( mTo->bbGetInputType(mInput) ) ) { bbtkDebugMessage("Data",3, " -> Equal types : transfer ok"<bbSetInput( mInput, mFrom->bbGetOutput(mOutput), false); } else { // 2) Look for an adaptor bbtk::BlackBox* adaptor = 0; try { adaptor = mFactory->NewAdaptor(mFrom->bbGetOutput(mOutput).type(), mTo->bbGetInputType(mInput), ""); } catch (...) { } if (adaptor) { bbtkDebugMessage("Data",3," -> Adaptor found : using it" <bbSetInput("In",mFrom->bbGetOutput(mOutput),false); adaptor->bbExecute(); // LG : Connection Update does not set mTo as modified mTo->bbSetInput(mInput, adaptor->bbGetOutput("Out"),false); adaptor->bbDelete(); } // 3) If no adaptor found but the any content is a pointer // and target type is also a pointer : we try run-time cast else if ( (mFrom->bbGetOutput(mOutput).contains_pointer()) && (mTo->bbGetDescriptor()->GetInputDescriptor(mInput) ->IsPointerType()) ) { bbtkDebugMessage("Data",3, " -> No adaptor found but source and target types are both pointers : trying up or down cast"<bbGetOutput(mOutput) .get_pointer_to(mTo->bbGetInput(mInput).pointed_type()); if (!nptr) { bbtkError("Connection '" <bbGetOutput(mOutput).type()) <<"> to <" <bbGetInputType(mInput)) <<"> : no adaptor available and run-time up and down cast failed"); } mTo->bbBruteForceSetInputPointer(mInput, nptr, false); } // 4) Nothing worked : error else { bbtkError("Connection '"<bbGetOutput(mOutput).type()) <<"> to <" <bbGetInputType(mInput))<<">"); } } } // EO : mFromAny && ! mToAny // Default case : types are the same; we use simple get-set else { // LG : Connection Update does not set mTo as modified mTo->bbSetInput(mInput, mFrom->bbGetOutput(mOutput),false); } bbtkDebugDecTab("Process",3); } //================================================================== //================================================================== /// Modified void Connection::SetModifiedStatus() { bbtkDebugMessageInc("Process",5, "Connection::SetModifiedStatus() [" <bbSetModifiedStatus(); mTo->bbSetModifiedStatus( mTo->bbGetInputConnectorMap().find(mInput)->second ); bbtkDebugDecTab("Process",5); } //================================================================== //================================================================== std::string Connection::GetFullName() const { if (mFrom && mTo) { std::string res = mFrom->bbGetName()+"."+mOutput+"--" +mTo->bbGetName()+"."+mInput; if ((mFrom!=mOriginalFrom)||(mTo!=mOriginalTo)) { res += "("+mOriginalFrom->bbGetName()+"."+mOriginalOutput+"--" + mOriginalTo->bbGetName()+"."+mOriginalInput+")"; } return res; } return "***Invalid Connection***"; } //================================================================== //================================================================== void Connection::Check() const { bbtkMessage("Debug",1,"** Checking Connection "<<(void*)this<<" ["<bbGetFullName()<bbHasOutput(mOutput)) { bbtkError(mFrom->bbGetFullName()<<" does not have output '" <bbGetOutputConnectorMap().find(mOutput); if (i== mFrom->bbGetOutputConnectorMap().end()) { bbtkError(mFrom->bbGetFullName()<<" output '" <::const_iterator j; j = find(i->second->GetConnectionVector().begin(), i->second->GetConnectionVector().end(), this); if (j==i->second->GetConnectionVector().end()) { bbtkError("Connection ["<bbGetFullName() <<" does not point to this connection"); } bbtkMessage("Debug",2," - From : This connection is in OutputConnector connection vector"<bbGetName()<bbGetDescriptor() << std::endl; std::cout << mTo->bbGetDescriptor()->GetTypeName() << std::endl; mTo->bbGetFullName(); bbtkMessage("Debug",2," - To : "<bbGetFullName()<bbHasInput(mInput)) { bbtkError(mTo->bbGetFullName()<<" does not have input '" <bbGetInputConnectorMap().find(mInput); if (i== mTo->bbGetInputConnectorMap().end()) { bbtkError(mTo->bbGetFullName()<<" input '" <second->GetConnection()==0) { bbtkError("Connection "<bbGetFullName() <<" does not point to this connection"); } bbtkMessage("Debug",2," - To : This connection is in InputConnector connection vector"<