/*========================================================================= Program: bbtk Module: $RCSfile: bbtkBlackBox.cxx,v $ Language: C++ Date: $Date: 2010/01/21 16:03:17 $ Version: $Revision: 1.49 $ =========================================================================*/ /* --------------------------------------------------------------------- * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale) * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux * * This software is governed by the CeCILL-B license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL-B * license as circulated by CEA, CNRS and INRIA at the following URL * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html * or in the file LICENSE.txt. * * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL-B license and that you accept its terms. * ------------------------------------------------------------------------ */ /** * \file * \brief Class bbtk::BlackBox : abstract black-box interface. */ #include "bbtkBlackBox.h" #include "bbtkPackage.h" #include "bbtkMessageManager.h" #include "bbtkFactory.h" #include "bbtkBlackBoxOutputConnector.h" #include "bbtkConfigurationFile.h" #include "bbtkWxBlackBox.h" #include "bbtkWx.h" #include //#include namespace bbtk { static bool bbmgSomeBoxExecuting = false; static bool bbmgFreezeExecution = false; static std::set bbmgExecutionList; //========================================================================= BlackBox::Deleter::Deleter() { } //========================================================================= //========================================================================= int BlackBox::Deleter::Delete(Object* p) { BlackBox* b = dynamic_cast(p); if (!b) { bbtkInternalError("BlackBox::Deleter::Delete("<GetObjectName() <<"["<GetObjectName();//b->bbGetNameWithParent(); bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<bbGetDescriptor(); bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<bbDelete(); bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<GetPackage(); if (!pack.expired()) { Package::ReleaseBlackBoxDescriptor(pack,desc); } else { bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""< BlackBox::Deleter(\""< BlackBox::BlackBox(\"" < BlackBox::BlackBox(" < BlackBox::~BlackBox() ["<bbDesallocateConnectors(); bbtkBlackBoxDebugMessage("object",4,"<== BlackBox::~BlackBox() ["<bbGetNameWithParent()+"<"+this->bbGetDescriptor()->GetTypeName()+">"; } //========================================================================= //========================================================================= std::string BlackBox::bbGetNameWithParent() const { if (bbmParent.lock()) { return bbmParent.lock()->bbGetNameWithParent() + ":" + bbmName; } else { return bbmName; } } //========================================================================= //========================================================================= void BlackBox::bbGetHelp(bool full) const { bbGetDescriptor()->GetHelp(full); } //========================================================================= //========================================================================= bool BlackBox::bbHasInput(const std::string& name) const { bbtkBlackBoxDebugMessage("kernel",8, "BlackBox::bbHasInput(\"" <GetInputDescriptorMap().find(name) != bbGetDescriptor()->GetInputDescriptorMap().end()); bbtkDebugDecTab("kernel",8); return r; } //========================================================================= //========================================================================= bool BlackBox::bbHasOutput(const std::string& name) const { bbtkBlackBoxDebugMessage("kernel",8,"BlackBox::bbHasOutput(\"" <GetOutputDescriptorMap().find(name) != bbGetDescriptor()->GetOutputDescriptorMap().end()); bbtkDebugDecTab("kernel",8); return r; } //========================================================================= //========================================================================= TypeInfo BlackBox::bbGetOutputType( const std::string &name ) const { bbtkBlackBoxDebugMessage("kernel",8, "BlackBox::bbGetOutputType(\"" <GetOutputDescriptor(name)->GetTypeInfo(); bbtkDebugDecTab("kernel",8); return r; } //========================================================================= //========================================================================= TypeInfo BlackBox::bbGetInputType( const std::string &name ) const { bbtkBlackBoxDebugMessage("kernel",8, "BlackBox::bbGetInputType(\"" <GetInputDescriptor(name)->GetTypeInfo(); bbtkDebugDecTab("kernel",8); return r; } //========================================================================= //========================================================================= void BlackBox::bbAllocateConnectors() { bbtkBlackBoxDebugMessage("kernel",8, "BlackBox::bbAllocateConnectors()" <GetInputDescriptorMap(); BlackBoxDescriptor::InputDescriptorMapType::const_iterator i; for ( i = imap.begin(); i != imap.end(); ++i ) { bbtkBlackBoxDebugMessage("kernel",8,"* Allocate \""<first<<"\""<second->GetName()] = new BlackBoxInputConnector(GetThisPointer()); } const BlackBoxDescriptor::OutputDescriptorMapType& omap = bbGetDescriptor()->GetOutputDescriptorMap(); BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o; for ( o = omap.begin(); o != omap.end(); ++o ) { bbtkBlackBoxDebugMessage("kernel",8,"* Allocate \""<first<<"\""<second->GetName()] = new BlackBoxOutputConnector(GetThisPointer()); } } //========================================================================= //========================================================================= void BlackBox::bbDesallocateConnectors() { bbtkBlackBoxDebugMessage("kernel",8, "BlackBox::bbDesallocateConnectors()" <first<<"\""<second); } OutputConnectorMapType::const_iterator o; for ( o = bbGetOutputConnectorMap().begin(); o != bbGetOutputConnectorMap().end(); ++o ) { bbtkBlackBoxDebugMessage("kernel",8,"* Delete \""<first<<"\""<second); } bbtkDebugDecTab("kernel",8); } //========================================================================= //========================================================================= void BlackBox::bbCopyIOValues(BlackBox& from) { bbtkBlackBoxDebugMessage("kernel",1, "BlackBox::bbCopyIOValues(" <GetInputDescriptorMap(); BlackBoxDescriptor::InputDescriptorMapType::const_iterator i; for ( i = imap.begin(); i != imap.end(); ++i ) { if (! i->second->GetCopyConstruct() ) continue; std::string input = i->second->GetName(); bbtkBlackBoxDebugMessage("kernel",2,"* Copying input "<bbSetInput(input, from.bbGetInput(input) ); } // copies the output values const BlackBoxDescriptor::OutputDescriptorMapType& omap = bbGetDescriptor()->GetOutputDescriptorMap(); BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o; for ( o = omap.begin(); o != omap.end(); ++o ) { if (! o->second->GetCopyConstruct() ) continue; std::string output = o->second->GetName(); bbtkBlackBoxDebugMessage("kernel",2,"* Copying output "<bbSetOutput(output, from.bbGetOutput(output) ); } bbtkDebugDecTab("kernel",9); } //========================================================================= //========================================================================= bool BlackBox::bbCanReact() const { return ( bbGlobalGetSomeBoxExecuting() #ifdef USE_WXWIDGETS || Wx::IsSomeWindowAlive() #endif ); } //========================================================================= //========================================================================= BlackBox::BoxProcessModeValue BlackBox::bbGetBoxProcessModeValue() const { const std::string& p = bbmBoxProcessMode; if ( (p == "0") || (p == "P") || (p == "p") || (p == "Pipeline") || (p == "pipeline") ) return Pipeline; if ( (p == "1") || (p == "A") || (p == "a") || (p == "Always") || (p == "always") ) return Always; if ( (p == "2") || (p == "R") || (p == "r") || (p == "Reactive") || (p == "reactive") ) return Reactive; /* if ( (p == "3") || (p == "F") || (p == "f") || (p == "Flash") || (p == "flash") ) return Flash; */ bbtkError(bbGetFullName()<<" : BoxProcessMode value '"<

BlackBox::bbSetStatusAndPropagate(input," <SetStatus(s); // Flash reaction /* if (bbGetBoxProcessModeValue() == Flash) { this->bbExecute(); } */ OutputConnectorMapType::const_iterator o; for ( o = bbGetOutputConnectorMap().begin(); o != bbGetOutputConnectorMap().end(); ++o ) { if (o->second->GetStatus()==UPTODATE) { o->second->SetStatus(OUTOFDATE); o->second->SignalChange(GetThisPointer(),o->first); } } if ( ( bbBoxProcessModeIsReactive() || (c==bbGetInputConnectorMap().find("BoxExecute")->second)) && (bbCanReact() ) ) { bbtkBlackBoxDebugMessage("change",2, "-> Execution triggered by Reactive mode or BoxExecute input change"<() ); } bbtkBlackBoxDebugMessage("change",5, "<= BlackBox::bbSetStatusAndPropagate(input)" < BlackBox::bbSignalOutputModification(" < BlackBox::bbSignalOutputModification(" <second->GetStatus()==UPTODATE) // { i->second->SignalChange(GetThisPointer(),i->first); // Has to notify the output "BoxChange" also if (output != "BoxChange") { i = bbGetOutputConnectorMap().find("BoxChange"); if ( i != bbGetOutputConnectorMap().end() ) { i->second->SignalChange(GetThisPointer(),i->first); } } if (reaction) bbGlobalProcessExecutionList(); // } bbtkBlackBoxDebugMessage("change",5, "<= BlackBox::bbSignalOutputModification(" <& output, bool reaction) { bbtkBlackBoxDebugMessage("change",5, "=> BlackBox::bbSignalOutputModification(vector of outputs)" <::const_iterator o; bool changed = false; for (o=output.begin();o!=output.end();++o) { // the output "BoxChange" must be signaled **AFTER** all others if (*o == "BoxChange") continue; // Look for the connector i = bbGetOutputConnectorMap().find(*o); if ( i == bbGetOutputConnectorMap().end() ) { bbtkError("BlackBox["<second->GetStatus()==UPTODATE) // { i->second->SignalChange(GetThisPointer(),i->first); changed = true; // } } // Has to notify the output "BoxChange" also i = bbGetOutputConnectorMap().find("BoxChange"); if ( changed && (i != bbGetOutputConnectorMap().end())) { // if (i->second->GetStatus()==UPTODATE) // { i->second->SignalChange(GetThisPointer(),i->first); if (reaction) bbGlobalProcessExecutionList(); // } } bbtkBlackBoxDebugMessage("change",5, "<= BlackBox::bbSignalOutputModification(vector of outputs)" < BlackBox::bbExecute("<<(int)force<<")" < already executing : abort"< FreezeExecution global flag is 'true' : abort execution"<bbRecursiveInitializeProcessing(); bbmInitialized = true; } } //========================================================================= //========================================================================= void BlackBox::bbFinalizeProcessing() { if (bbmInitialized) { bbtkBlackBoxDebugMessage("process",2,"** Finalize processing" <bbRecursiveFinalizeProcessing(); bbmInitialized = false; } } //========================================================================= //========================================================================= void BlackBox::bbRecursiveExecute( Connection::Pointer caller ) { bbtkBlackBoxDebugMessage("process",3, "=> BlackBox::bbRecursiveExecute(" <<(caller?caller->GetFullName():"0")<<")" < already executing : abort"<bbCreateWindow(); // Updates its inputs IOStatus s = bbUpdateInputs(); if ( (s != UPTODATE) || bbBoxProcessModeIsAlways() ) { // Displays the window (WxBlackbox) // bbShowWindow(caller); // Actual processing (virtual) this->bbProcess(); // Update the I/O statuses bbComputePostProcessStatus(); } else { // Test output status... OutputConnectorMapType::iterator o; for ( o = bbGetOutputConnectorMap().begin(); o!= bbGetOutputConnectorMap().end(); ++o) { if (o->second->GetStatus() != UPTODATE) { bbtkWarning("BlackBox::bbRecursiveExecute: " <<"all inputs are Up-to-date but output '" <first<<"' is Out-of-date ???"); } } bbtkBlackBoxDebugMessage("process",3," -> Up-to-date : nothing to do" <bbShowWindow(); bbtkBlackBoxDebugMessage("process",3, "<= BlackBox::bbRecursiveExecute()" < BlackBox::bbUpdateInputs()" <first=="WinHide") continue; // If input type is Void : no recurse //if ( bbGetDescriptor()->GetInputDescriptor(i->first)->GetTypeInfo() // == typeid(Void) ) // continue; bbtkBlackBoxDebugMessage("change",2, "Input '"<first <<"': status before update = '" <second->GetStatus()) <<"'"<second->RecursiveExecute(); IOStatus t = i->second->GetStatus(); if (t > s) s = t; bbtkBlackBoxDebugMessage("change",2, "Input '"<first <<"': status before process = '" <second->GetStatus()) <<"'"< BlackBox::bbComputePostProcessStatus()" <second->GetStatus(); if (t == OUTOFDATE) new_output_status = OUTOFDATE; // A previously MODIFIED status turns to UPTODATE if (t==MODIFIED) i->second->SetStatus(UPTODATE); bbtkBlackBoxDebugMessage("change",2, "Input '"<first<<"' : " << GetIOStatusString(t) << " -> " << GetIOStatusString(i->second->GetStatus()) << std::endl); } bbtkBlackBoxDebugMessage("change",2, "New output status : " << GetIOStatusString(new_output_status) <second->SetStatus(new_output_status); } bbtkBlackBoxDebugMessage("process",4, "<= BlackBox::bbComputePostProcessStatus()" < BlackBox::bbConnectInput(\"" <GetFullName()<<")" <second->SetConnection(c); // The input *MUST* be set OUTOFDATE to update its input on next execution bbSetStatusAndPropagate(i->second,OUTOFDATE); bbtkBlackBoxDebugMessage("connection",2, "<== BlackBox::bbConnectInput(\"" <GetFullName()<<")" < BlackBox::bbConnectOutput(\""<GetFullName()<<")" <second->SetConnection(c); bbtkBlackBoxDebugMessage("connection",2, "<== BlackBox::bbConnectOutput(\""<GetFullName()<<")" < BlackBox::bbDisconnectInput(\""<GetFullName()<<")" <second->UnsetConnection(c); bbtkBlackBoxDebugMessage("connection",2, "<== BlackBox::bbDisconnectInput(\""<GetFullName()<<")" < BlackBox::bbDisconnectOutput(\""<GetFullName()<<")" <second->UnsetConnection(c); bbtkBlackBoxDebugMessage("connection",2, "<== BlackBox::bbDisconnectOutput(\""<GetFullName()<<")" <GetPackage(); if ((p != 0) && ( ! p->GetFactorySet().empty() ) ) { Factory::Pointer f = p->GetFactorySet().begin()->lock(); BlackBox::Pointer a; try { a = f->NewAdaptor( bbGetOutputType(output), typeid(std::string), ""); } catch (bbtk::Exception e) { } if (a){ // bbUpdate(); a->bbSetInput("In",bbGetOutput(output)); a->bbExecute(); v = a->bbGetOutput("Out").unsafe_get() ; } else { v="? (no adaptor found)"; } } else { v="? (no factory found)"; } } else { // bbUpdate(); v = bbGetOutput(output).unsafe_get() ; } return v; } //========================================================================= //========================================================================= std::string BlackBox::bbGetInputAsString( const std::string &input ) { std::string v; // Looks for the adaptor if (bbGetInputType(input) != typeid(std::string)) { // Look for factory Package::Pointer p = bbGetDescriptor()->GetPackage(); if ((p != 0) && ( ! p->GetFactorySet().empty() ) ) { Factory::Pointer f = p->GetFactorySet().begin()->lock(); BlackBox::Pointer a; try { a = f->NewAdaptor( bbGetInputType(input), typeid(std::string), ""); }catch (bbtk::Exception e) { } if (a) { // bbUpdate(); a->bbSetInput("In",bbGetInput(input)); a->bbExecute(); v = a->bbGetOutput("Out").unsafe_get() ; } else { v="? (no adaptor found)"; } } else { v="? (no factory found)"; } } else { v = bbGetInput(input).unsafe_get() ; } return v; } //======================================================================= //======================================================================= // Replaces substrings "<" by "[" void SubsBrackets ( std::string& s ) { // std::cout << "BEFORE=["<bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "]"; } else { labelStr = bbGetName(); labelStr = labelStr + " [" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "] "; } SubsBrackets(labelStr); if (detail==1) { labelStr = labelStr + " | {{ "; std::string tempStrTypeName; bool tmp; tmp=false; for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i ) { if (tmp==true) { labelStr=labelStr+" | "; } tmp=true; if (instanceOrtype==true) { valueStr = this->bbGetInputAsString(i->first) + " = "; } const BlackBoxInputDescriptor* id = bbGetDescriptor()->GetInputDescriptor(i->first); tempStrTypeName=id->GetTypeName(); SubsBrackets(tempStrTypeName); std::string Name(i->first); SubsBrackets(Name); labelStr=labelStr + "<"+i->first.c_str()+"> " + valueStr + Name.c_str() + " [" + tempStrTypeName.c_str() + "]"; } labelStr=labelStr+ " } | {"; tmp = false; OutputConnectorMapType::iterator ii; for ( ii = mOutputConnectorMap.begin(); ii != mOutputConnectorMap.end(); ++ii ) { if (tmp==true) { labelStr=labelStr+" | "; } tmp = true; if (instanceOrtype==true) { valueStr = this->bbGetOutputAsString(ii->first) + " = "; } const BlackBoxOutputDescriptor* id = bbGetDescriptor()->GetOutputDescriptor(ii->first); tempStrTypeName=id->GetTypeName(); SubsBrackets(tempStrTypeName); std::string Name(ii->first); SubsBrackets(Name); labelStr=labelStr+"<"+ii->first.c_str()+"> " + valueStr + Name.c_str() + " ["+tempStrTypeName+"]"; } labelStr = labelStr+ " } }" ; } // detail fprintf(ff," " ); bbWriteDotInputOutputName(ff,true,detail,level); std::string tmp ( bbGetTypeName() ); SubsBrackets(tmp); std::string url; if (relative_link) url = this->bbGetDescriptor()->GetPackage()->GetDocRelativeURL() + "#" + tmp; else url = this->bbGetDescriptor()->GetPackage()->GetDocURL() + "#" + tmp; fprintf( ff , " [shape=record, URL=\"%s\",label=\"%s\"]%s\n",url.c_str(),labelStr.c_str(),";" ); // std::cout << labelStr << std::endl; // Relation Input if (GetThisPointer()!=parentblackbox){ for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i ) { if (i->second) { Connection* con = i->second->GetConnection(); if (con!=NULL){ BlackBox::Pointer a=con->GetOriginalBlackBoxFrom(); BlackBox::Pointer b=con->GetOriginalBlackBoxTo(); fprintf(ff," "); a->bbWriteDotInputOutputName(ff,false,detail,level); if (detail==1) { fprintf(ff,":%s",con->GetOriginalBlackBoxFromOutput().c_str()); } fprintf(ff,"->"); b->bbWriteDotInputOutputName(ff,true,detail,level); if (detail==1) { fprintf(ff,":%s",con->GetOriginalBlackBoxToInput().c_str()); } fprintf(ff,"%s\n",";"); } // if con } // if second } // for } // if parentblackbox } //========================================================================= //========================================================================= void BlackBox::bbPrintHelp(BlackBox::Pointer parentblackbox, int detail, int level /*,Factory *factory*/ ) { if (this->bbGetDescriptor()->GetPackage()) { bbtkBlackBoxMessage("help",1,"Black Box '"<bbGetDescriptor()->GetPackage()->GetName() <<"::"<bbGetDescriptor()->GetTypeName()<<">"<bbGetDescriptor()->GetTypeName()<<">"< iname; std::vector ivalue; std::vector iconn; std::vector istatus; InputConnectorMapType::iterator i; unsigned int namelmax = 0; unsigned int valuelmax = 0; // unsigned int connlmax = 0; for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i ) { iname.push_back(i->first); if (iname.back().size()>namelmax) namelmax = iname.back().size(); ivalue.push_back(bbGetInputAsString(i->first)); if (ivalue.back().size()>valuelmax) valuelmax = ivalue.back().size(); std::string s(""); Connection* con = i->second->GetConnection(); if (con!=0){ s = con->GetOriginalBlackBoxFrom()->bbGetName(); s += "."; s += con->GetOriginalBlackBoxFromOutput(); } // if con iconn.push_back(s); istatus.push_back(GetIOStatusString(i->second->GetStatus())); } OutputConnectorMapType::iterator o; std::vector oname; std::vector ovalue; std::vector > oconn; std::vector ostatus; for ( o = mOutputConnectorMap.begin(); o != mOutputConnectorMap.end(); ++o ) { oname.push_back(o->first); if (oname.back().size()>namelmax) namelmax = oname.back().size(); ovalue.push_back(bbGetOutputAsString(o->first)); if (ovalue.back().size()>valuelmax) valuelmax = ovalue.back().size(); std::vector ss; const std::vector& con = o->second->GetConnectionVector(); std::vector::const_iterator c; for (c=con.begin();c!=con.end();++c) { std::string s; s = (*c)->GetOriginalBlackBoxTo()->bbGetName(); s += "."; s += (*c)->GetOriginalBlackBoxToInput(); ss.push_back(s); } // if con oconn.push_back(ss); ostatus.push_back(GetIOStatusString(o->second->GetStatus())); } if (iname.size()) bbtkBlackBoxMessage("help",1," * Inputs : "<::iterator i1,i2,i3,i4; for (i1=iname.begin(),i2=ivalue.begin(),i3=iconn.begin(),i4=istatus.begin(); i1!=iname.end(),i2!=ivalue.end(),i3!=iconn.end(),i4!=istatus.end(); ++i1,++i2,++i3,++i4) { std::string name(*i1); name += "'"; name.append(1+namelmax-name.size(),' '); std::string value(*i2); value += "'"; value.append(1+valuelmax-value.size(),' '); if (i3->size()) bbtkBlackBoxMessage("help",1," '"< BlackBox::bbGlobalProcessExecutionList()" <::iterator i; while (bbmgExecutionList.size()>0) { i = bbmgExecutionList.begin(); BlackBox::WeakPointer p = *i; bbmgExecutionList.erase(i); if (p.lock()) { bbtkDebugMessage("process",4, " -> Executing '"<< p.lock()->bbGetName()<<"'"<bbExecute(true); } else { bbtkGlobalError("Strange error in BlackBox::bbGlobalProcessExecutionList() : Weak bb pointer in bbmgExecutionList is no more valid..."); } } bbmgExecutionList.clear(); bbtkDebugMessage("process",3, "<= BlackBox::bbGlobalProcessExecutionList()" <bbGetName()<<")"<