00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00036 #include "bbtkConnection.h"
00037 #include "bbtkFactory.h"
00038 #include "bbtkBlackBox.h"
00039 #include "bbtkMessageManager.h"
00040 #include "bbtkBlackBoxOutputConnector.h"
00041
00042 #define bbtkCMessage(key,level,mess) \
00043 bbtkMessage(key,level,"["<<GetFullName()<<"] "<<mess)
00044 #define bbtkCDebugMessage(key,level,mess) \
00045 bbtkDebugMessage(key,level,"["<<GetFullName()<<"] "<<mess)
00046
00047 namespace bbtk
00048 {
00049 const std::string IOSTATUS_STRING[3] =
00050 {"Up-to-date","Modified","Out-of-date"};
00051
00052 const std::string& GetIOStatusString(IOStatus s)
00053 { return IOSTATUS_STRING[s]; }
00054
00055
00056 Connection::Pointer Connection::New(BlackBox::Pointer from,
00057 const std::string& output,
00058 BlackBox::Pointer to,
00059 const std::string& input ,
00060 const Factory::Pointer f )
00061 {
00062 bbtkDebugMessage("object",1,"##> Connection(\""
00063 <<from->bbGetName()<<"\",\""<<output<<"\",\""
00064 <<to->bbGetName()<<"\",\""<<input<<"\")"
00065 <<std::endl);
00066 Connection::Pointer p =
00067 MakePointer(new Connection(from,output,to,input,f));
00068 bbtkDebugMessage("object",1,"<## Connection(\""
00069 <<from->bbGetName()<<"\",\""<<output<<"\",\""
00070 <<to->bbGetName()<<"\",\""<<input<<"\")"
00071 <<std::endl);
00072 return p;
00073 }
00074
00075
00076
00079 Connection::Connection(BlackBox::Pointer from, const std::string& output,
00080 BlackBox::Pointer to, const std::string& input ,
00081 const Factory::Pointer f )
00082 : mAdaptor(),
00083 mFactory(f),
00084 mFromAny(false),
00085 mToAny(false)
00086 {
00087 bbtkDebugMessage("object",2,"==> Connection(\""
00088 <<from->bbGetName()<<"\",\""<<output<<"\",\""
00089 <<to->bbGetName()<<"\",\""<<input<<"\")"
00090 <<std::endl);
00091
00092 bbtkDebugMessage("connection",1,"==> Connection(\""
00093 <<from->bbGetName()<<"\",\""<<output<<"\",\""
00094 <<to->bbGetName()<<"\",\""<<input<<"\")"
00095 <<std::endl);
00096
00097
00098
00099 if (! from->bbHasOutput(output) )
00100 {
00101 bbtkError("The box \""<<from->bbGetTypeName()<<
00102 "\" has no output \""<<output<<"\"");
00103 }
00104 if (! to->bbHasInput(input) )
00105 {
00106 bbtkError("The box \""<<to->bbGetTypeName()<<
00107 "\" has no input \""<<input<<"\"");
00108 }
00109
00110 if (to->bbGetInputConnectorMap().find(input)->second->IsConnected())
00111 {
00112 bbtkError("The input \""<<input<<"\" of the box \""<<to->bbGetName()
00113 <<"\" is already connected");
00114 }
00115
00116
00117
00118
00119 if ( from->bbGetOutputType(output) !=
00120 to->bbGetInputType(input) )
00121 {
00122 if ( from->bbGetOutputType(output) == typeid(Data) )
00123 {
00124 bbtkWarning("Connection: '"<<from->bbGetName()<<"."<<output
00125 <<"' is of type <"
00126 <<HumanTypeName<Data>()
00127 <<"> : type compatibility with '"
00128 <<to->bbGetName()<<"."<<input
00129 <<"' will be resolved at run time"
00130 );
00131 mFromAny = true;
00132 }
00133 else if ( to->bbGetInputType(input) == typeid(Data) )
00134 {
00135 bbtkDebugMessage("kernel",8," -> '"<<input<<"' type is "
00136 <<TypeName<Data>()<<" : can receive any data"
00137 <<std::endl);
00138 mToAny = true;
00139 }
00140 else
00141 {
00142
00143 std::string name;
00144 name = from->bbGetName() + "." + output + "-"
00145 + to->bbGetName() + "." + input;
00146 mAdaptor = mFactory.lock()
00147 ->NewAdaptor(from->bbGetOutputType(output),
00148 to->bbGetInputType(input),
00149 name);
00150 if (!mAdaptor)
00151 {
00152 bbtkError("did not find any <"
00153 <<TypeName(from->bbGetOutputType(output))
00154 <<"> to <"
00155 <<TypeName(to->bbGetInputType(input))
00156 <<"> adaptor");
00157 }
00158 }
00159 }
00160
00161
00162 mFrom = from;
00163 mOriginalFrom = from;
00164 mTo = to;
00165 mOriginalTo = to;
00166 mInput = mOriginalInput = input;
00167 mOutput = mOriginalOutput = output;
00168
00169
00170
00171 from->bbConnectOutput(output,this);
00172 to->bbConnectInput(input,this);
00173
00174 from->bbGetOutputConnector(output).AddChangeObserver(boost::bind(&bbtk::Connection::OnOutputChange,this, _1, _2, _3));
00175
00176
00177 bbtkDebugMessage("connection",1,"<== Connection(\""
00178 <<from->bbGetName()<<"\",\""<<output<<"\",\""
00179 <<to->bbGetName()<<"\",\""<<input<<"\")"
00180 <<std::endl);
00181
00182 bbtkDebugMessage("object",2,"<== Connection(\""
00183 <<from->bbGetName()<<"\",\""<<output<<"\",\""
00184 <<to->bbGetName()<<"\",\""<<input<<"\")"
00185 <<std::endl);
00186 }
00187
00188
00189
00190 Connection::Pointer Connection::New(BlackBox::Pointer from,
00191 const std::string& output,
00192 BlackBox::Pointer to,
00193 const std::string& input )
00194 {
00195 bbtkDebugMessage("object",1,"##> Connection(\""
00196 <<from->bbGetName()<<"\",\""<<output<<"\",\""
00197 <<to->bbGetName()<<"\",\""<<input<<"\")"
00198 <<std::endl);
00199 Connection::Pointer p =
00200 MakePointer(new Connection(from,output,to,input));
00201 bbtkDebugMessage("object",1,"<## Connection(\""
00202 <<from->bbGetName()<<"\",\""<<output<<"\",\""
00203 <<to->bbGetName()<<"\",\""<<input<<"\")"
00204 <<std::endl);
00205 return p;
00206 }
00207
00208
00209
00212 Connection::Connection(BlackBox::Pointer from, const std::string& output,
00213 BlackBox::Pointer to, const std::string& input )
00214 : mAdaptor(),
00215 mFactory(),
00216 mFromAny(false),
00217 mToAny(false)
00218 {
00219 bbtkDebugMessage("object",2,"==> Connection(\""
00220 <<from->bbGetName()<<"\",\""<<output<<"\",\""
00221 <<to->bbGetName()<<"\",\""<<input<<"\")"
00222 <<std::endl);
00223
00224 bbtkDebugMessage("connection",1,"==> Connection(\""
00225 <<from->bbGetName()<<"\",\""<<output<<"\",\""
00226 <<to->bbGetName()<<"\",\""<<input<<"\")"
00227 <<std::endl);
00228
00229
00230
00231 if (! from->bbHasOutput(output) )
00232 {
00233 bbtkError("The box \""<<from->bbGetTypeName()<<
00234 "\" has no output \""<<output<<"\"");
00235 }
00236 if (! to->bbHasInput(input) )
00237 {
00238 bbtkError("The box \""<<to->bbGetTypeName()<<
00239 "\" has no input \""<<input<<"\"");
00240 }
00241
00242 if (to->bbGetInputConnectorMap().find(input)->second->IsConnected())
00243 {
00244 bbtkError("The input \""<<input<<"\" of the box \""<<to->bbGetName()
00245 <<"\" is already connected");
00246 }
00247
00248
00249
00250
00251 if ( from->bbGetOutputType(output) !=
00252 to->bbGetInputType(input) )
00253 {
00254 if ( from->bbGetOutputType(output) == typeid(Data) )
00255 {
00256 bbtkWarning("Connection '"
00257 <<GetFullName()
00258 <<"' : '"<<from->bbGetName()<<"."<<output
00259 <<"' is of type <"
00260 <<HumanTypeName<Data>()
00261 <<"> : type compatibility with '"
00262 <<to->bbGetName()<<"."<<input
00263 <<"' will be resolved at run time"
00264 );
00265 mFromAny = true;
00266 }
00267 else if ( to->bbGetInputType(input) == typeid(Data) )
00268 {
00269 bbtkDebugMessage("kernel",8," -> '"<<input<<"' type is "
00270 <<TypeName<Data>()<<" : can receive any data"
00271 <<std::endl);
00272 mToAny = true;
00273 }
00274 else
00275 {
00276 bbtkError("Connection created between different types without Factory provided");
00277 }
00278 }
00279
00280
00281 mFrom = from;
00282 mOriginalFrom = from;
00283 mTo = to;
00284 mOriginalTo = to;
00285 mInput = mOriginalInput = input;
00286 mOutput = mOriginalOutput = output;
00287
00288
00289
00290 from->bbConnectOutput(output,this);
00291 to->bbConnectInput(input,this);
00292
00293 from->bbGetOutputConnector(output).AddChangeObserver(boost::bind(&bbtk::Connection::OnOutputChange,this, _1, _2, _3));
00294
00295 bbtkDebugMessage("connection",1,"<== Connection(\""
00296 <<from->bbGetName()<<"\",\""<<output<<"\",\""
00297 <<to->bbGetName()<<"\",\""<<input<<"\")"
00298 <<std::endl);
00299
00300 bbtkDebugMessage("object",2,"==> Connection(\""
00301 <<from->bbGetName()<<"\",\""<<output<<"\",\""
00302 <<to->bbGetName()<<"\",\""<<input<<"\")"
00303 <<std::endl);
00304 }
00305
00306
00307
00309 Connection::~Connection()
00310 {
00311 bbtkCDebugMessage("object",4,
00312 "==> ~Connection()"
00313 <<std::endl);
00314
00315 if (mAdaptor) mAdaptor.reset();
00316 if (mFrom!=0)
00317 {
00318 mFrom->bbDisconnectOutput(mOutput,this);
00319
00320 mFrom.reset();
00321 }
00322 else
00323 {
00324 bbtkInternalError("~Connection() : invalid initial box pointer");
00325 }
00326 if (mTo!=0)
00327 {
00328 mTo->bbDisconnectInput(mInput,this);
00329 mTo.reset();
00330 }
00331 else
00332 {
00333 bbtkInternalError("~Connection() : invalid final box pointer");
00334 }
00335
00336
00337 bbtkCDebugMessage("object",4,
00338 "<== ~Connection()"
00339 <<std::endl);
00340 }
00341
00342
00343
00345 void Connection::RecursiveExecute()
00346 {
00347 bbtkCDebugMessage("process",4,
00348 "===> Connection::RecursiveExecute()"
00349 <<std::endl);
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 mFrom->bbRecursiveExecute(GetThisPointer<Connection>());
00364
00365 TransferData();
00366
00367
00368 IOStatus s = MODIFIED;
00369 if ( mFrom->bbGetOutputConnector(mOutput).GetStatus() == OUTOFDATE)
00370 {
00371 s = OUTOFDATE;
00372 }
00373 mTo->bbGetInputConnector(mInput).SetStatus(s);
00374
00375 bbtkCDebugMessage("process",4,
00376 " --> '"<<mTo->bbGetName()<<"."<<mInput
00377 <<" ["<<&mTo->bbGetInputConnector(mInput)<<"] "
00378 <<"' new status '"
00379 <<GetIOStatusString(s)
00380 <<"'"
00381 << std::endl);
00382
00383 bbtkCDebugMessage("process",4,
00384 "<=== Connection::RecursiveExecute()"
00385 <<std::endl);
00386 return;
00387 }
00388
00389
00390
00391
00392
00395 void Connection::TransferData()
00396 {
00397 bbtkCDebugMessage("data",3,
00398 "Connection::TransferData()"
00399 <<std::endl);
00400
00401
00402
00403 if (mAdaptor)
00404 {
00405 mAdaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
00406 mAdaptor->bbExecute();
00407
00408 mTo->bbSetInput(mInput, mAdaptor->bbGetOutput("Out"),false);
00409
00410 }
00411
00412 else if ( mFromAny && (! mToAny) )
00413 {
00414 bbtkCDebugMessage("data",3,
00415 " * Source type is an "
00416 <<HumanTypeName<Data>()
00417 <<" which contains a <"
00418 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
00419 <<">"<<std::endl);
00420 bbtkCDebugMessage("data",3,
00421 " * Target type is <"
00422 <<HumanTypeName(mTo->bbGetInputType(mInput))
00423 <<">"<<std::endl);
00424
00425
00426 if (mFrom->bbGetOutput(mOutput).type() == typeid(void))
00427 {
00428 bbtkCDebugMessage("data",3,
00429 " -> Source is void : nothing to transfer!"<<std::endl);
00430 }
00431
00432 else if (mFrom->bbGetOutput(mOutput)
00433 .contains( mTo->bbGetInputType(mInput) ) )
00434 {
00435 bbtkCDebugMessage("data",3,
00436 " -> Equal types : transfer ok"<<std::endl);
00437 mTo->bbSetInput( mInput,
00438 mFrom->bbGetOutput(mOutput),
00439 false);
00440 }
00441 else
00442 {
00443
00444 bbtk::BlackBox::Pointer adaptor;
00445 try
00446 {
00447 adaptor = mFactory.lock()
00448 ->NewAdaptor(mFrom->bbGetOutput(mOutput).type(),
00449 mTo->bbGetInputType(mInput),
00450 "");
00451 }
00452 catch (...)
00453 {
00454 }
00455 if (adaptor)
00456 {
00457 bbtkCDebugMessage("data",3," -> Adaptor found : using it"
00458 <<std::endl);
00459 adaptor->bbSetInput("In",mFrom->bbGetOutput(mOutput),false);
00460 adaptor->bbExecute();
00461
00462 mTo->bbSetInput(mInput, adaptor->bbGetOutput("Out"),false);
00463
00464 }
00465
00466
00467 else if ( (mFrom->bbGetOutput(mOutput).contains_pointer()) &&
00468 (mTo->bbGetDescriptor()->GetInputDescriptor(mInput)
00469 ->IsPointerType()) )
00470 {
00471 bbtkCDebugMessage("data",3,
00472 " -> No adaptor found but source and target types are both pointers : trying up or down cast"<<std::endl);
00473
00474 void* nptr =
00475 mFrom->bbGetOutput(mOutput)
00476 .get_pointer_to(mTo->bbGetInput(mInput).pointed_type());
00477 if (!nptr)
00478 {
00479 bbtkError("Connection '"
00480 <<GetFullName()
00481 <<"' : <"
00482 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
00483 <<"> to <"
00484 <<HumanTypeName(mTo->bbGetInputType(mInput))
00485 <<"> : no adaptor available and run-time up and down cast failed");
00486 }
00487 mTo->bbBruteForceSetInputPointer(mInput, nptr, false);
00488 }
00489
00490 else
00491 {
00492 bbtkError("Connection '"<<GetFullName()<<"' "
00493 <<"no adaptor found to convert <"
00494 <<HumanTypeName(mFrom->bbGetOutput(mOutput).type())
00495 <<"> to <"
00496 <<HumanTypeName(mTo->bbGetInputType(mInput))<<">");
00497 }
00498 }
00499 }
00500
00501
00502 else
00503 {
00504
00505 mTo->bbSetInput(mInput, mFrom->bbGetOutput(mOutput),false);
00506 }
00507
00508 }
00509
00510
00511
00513 void Connection::OnOutputChange(bbtk::BlackBox::Pointer, const std::string&,
00514 IOStatus status)
00515 {
00516 bbtkCDebugMessage("change",2,
00517 "==> Connection::OnOutputChange("
00518 <<GetIOStatusString(status)<<")"
00519 <<std::endl);
00520 if (mAdaptor)
00521 {
00522 BlackBoxInputConnector* ac = mAdaptor->bbGetInputConnectorMap().find("In")->second;
00523 mAdaptor->bbSetStatusAndPropagate(ac,status);
00524 }
00525
00526 mTo->bbSetStatusAndPropagate( mTo->bbGetInputConnectorMap().find(mInput)->second, status);
00527
00528
00529 }
00530
00531
00532
00533
00534 std::string Connection::GetFullName() const {
00535 if (mFrom && mTo)
00536 {
00537 std::string res = mFrom->bbGetName()+"."+mOutput+"--"
00538 +mTo->bbGetName()+"."+mInput;
00539 if ((!mOriginalFrom.expired()) && (!mOriginalTo.expired()) &&
00540 ((mFrom!=mOriginalFrom.lock())||(mTo!=mOriginalTo.lock())))
00541 {
00542 res += "("+mOriginalFrom.lock()->bbGetName()
00543 +"."+mOriginalOutput+"--"
00544 + mOriginalTo.lock()->bbGetName()+"."+mOriginalInput+")";
00545 }
00546 return res;
00547 }
00548 return "***Invalid Connection***";
00549 }
00550
00551
00552
00553 void Connection::Check() const
00554 {
00555 bbtkMessage("debug",1,"** Checking Connection "<<(void*)this<<" ["
00556 <<GetFullName()<<"]"
00557 <<std::endl);
00558 if (mFrom==0)
00559 {
00560 bbtkMessage("debug",2," - From = 0"<<std::endl);
00561 }
00562 else
00563 {
00564 bbtkMessage("debug",2," - From : "<<mFrom->bbGetName()<<std::endl);
00565 if (!mFrom->bbHasOutput(mOutput))
00566 {
00567 bbtkError("** Checking Connection "<<(void*)this
00568 <<" ["<<GetFullName()<<"] : "
00569 << mFrom->bbGetName()<<" does not have output '"
00570 <<mOutput<<"'");
00571 }
00572 bbtkMessage("debug",2," - From : Output '"<<mOutput<<"' exists"<<std::endl);
00573 BlackBox::OutputConnectorMapType::const_iterator i
00574 = mFrom->bbGetOutputConnectorMap().find(mOutput);
00575 if (i== mFrom->bbGetOutputConnectorMap().end())
00576 {
00577 bbtkError("** Checking Connection "<<(void*)this
00578 <<" ["<<GetFullName()<<"] : "
00579 <<mFrom->bbGetName()<<" output '"
00580 <<mOutput<<"' is not in OutputConnectorMap");
00581 }
00582 bbtkMessage("debug",2," - From : Output '"<<mOutput
00583 <<"' is in OutputConnectorMap"<<std::endl);
00584
00585 std::vector< Connection* >::const_iterator j;
00586
00587
00588
00589
00590
00591
00592
00593
00594 j = find(i->second->GetConnectionVector().begin(),
00595 i->second->GetConnectionVector().end(),
00596 this);
00597
00598 if (j==i->second->GetConnectionVector().end())
00599 {
00600 bbtkError("** Checking Connection "<<(void*)this
00601 <<" ["<<GetFullName()<<"] : "
00602 <<" OutputConnector '"
00603 <<mOutput<<"' of "<<mFrom->bbGetName()
00604 <<" does not point to this connection");
00605
00606 }
00607 bbtkMessage("debug",2," - From : This connection is in OutputConnector connection vector"<<std::endl);
00608 bbtkMessage("debug",2," * Box from : Check successfull"<<std::endl);
00609
00610 }
00611
00612 if (mTo==0)
00613 {
00614 bbtkMessage("debug",2," - To = 0"<<std::endl);
00615 }
00616 else
00617 {
00618 bbtkMessage("debug",2," - To : "<<mTo->bbGetName()<<std::endl);
00619
00620
00621
00622
00623 bbtkMessage("debug",2," - To : "<<mTo->bbGetName()<<std::endl);
00624 if (!mTo->bbHasInput(mInput))
00625 {
00626 bbtkError("** Checking Connection "<<(void*)this
00627 <<" ["<<GetFullName()<<"] : "
00628 <<mTo->bbGetName()<<" does not have input '"
00629 <<mInput<<"'");
00630 }
00631 bbtkMessage("debug",2," - To : Input '"<<mInput<<"' exists"<<std::endl);
00632 BlackBox::InputConnectorMapType::const_iterator i
00633 = mTo->bbGetInputConnectorMap().find(mInput);
00634 if (i== mTo->bbGetInputConnectorMap().end())
00635 {
00636 bbtkError("** Checking Connection "<<(void*)this
00637 <<" ["<<GetFullName()<<"] : "
00638 <<mTo->bbGetName()<<" input '"
00639 <<mInput<<"' is not in InputConnectorMap");
00640 }
00641 bbtkMessage("debug",2," - To : Input '"<<mInput
00642 <<"' is in InputConnectorMap"<<std::endl);
00643
00644 if (i->second->GetConnection()==0)
00645 {
00646 bbtkError("** Checking Connection "<<(void*)this
00647 <<" ["<<GetFullName()<<"] : "
00648 <<" InputConnector '"
00649 <<mInput<<"' of "<<mTo->bbGetName()
00650 <<" does not point to this connection");
00651
00652 }
00653 bbtkMessage("debug",2," - To : This connection is in InputConnector connection vector"<<std::endl);
00654 bbtkMessage("debug",2," * Box to : Check successfull"<<std::endl);
00655
00656 }
00657 }
00658
00659
00660 std::string Connection::GetObjectName() const
00661 {
00662 std::string s("Connection '");
00663 s += GetFullName();
00664 s += "'";
00665 return s;
00666 }
00667
00668
00669
00670 std::string Connection::GetObjectInfo() const
00671 {
00672 std::stringstream i;
00673 return i.str();
00674 }
00675
00676
00677
00678 size_t Connection::GetObjectSize() const
00679 {
00680 size_t s = Superclass::GetObjectSize();
00681 s += Connection::GetObjectInternalSize();
00682 return s;
00683 }
00684
00685
00686 size_t Connection::GetObjectInternalSize() const
00687 {
00688 size_t s = sizeof(Connection);
00689 return s;
00690 }
00691
00692
00693 size_t Connection::GetObjectRecursiveSize() const
00694 {
00695 size_t s = Superclass::GetObjectRecursiveSize();
00696 s += Connection::GetObjectInternalSize();
00697 return s;
00698 }
00699
00700
00701 }
00702
00703
00704
00705
00706