X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=lib%2FcpPlugins%2FPipeline.cxx.d;fp=lib%2FcpPlugins%2FPipeline.cxx.d;h=8ce0e096e1c15b8160d82b5f2e00e0ed344db7f9;hb=2e142df11d6f312a2a2b5097b8da73571ed523e8;hp=0000000000000000000000000000000000000000;hpb=61b3659afe961ed248f30e26f9ca8f28fcfafddc;p=cpPlugins.git diff --git a/lib/cpPlugins/Pipeline.cxx.d b/lib/cpPlugins/Pipeline.cxx.d new file mode 100644 index 0000000..8ce0e09 --- /dev/null +++ b/lib/cpPlugins/Pipeline.cxx.d @@ -0,0 +1,638 @@ +// ========================================================================= +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ========================================================================= + +$include "Value.e" + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::TAdjMatrix:: +TAdjMatrix( ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::TAdjMatrix:: +~TAdjMatrix( ) +{ +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Pipeline::TAdjMatrix:: +HasConnection( + const std::string& oObj, const std::string& dObj, + const std::string& oPort, const std::string& dPort + ) const +{ + TMatrix::const_iterator m = this->m_Matrix.find( oObj ); + if( m != this->m_Matrix.end( ) ) + { + TRow::const_iterator r = m->second.find( dObj ); + if( r != m->second.end( ) ) + return( r->second.find( TEdge( oPort, dPort ) ) != r->second.end( ) ); + else + return( false ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::TAdjMatrix:: +TEdges& cpPlugins::Pipeline::TAdjMatrix:: +operator()( const std::string& o, const std::string& d ) +{ + TMatrix::iterator m = this->m_Matrix.find( o ); + if( m != this->m_Matrix.end( ) ) + { + TRow::iterator r = m->second.find( d ); + if( r != m->second.end( ) ) + return( r->second ); + } // end if + + // If not found... + this->m_Matrix[ o ][ d ] = TEdges( ); + return( this->operator()( o, d ) ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Pipeline::TAdjMatrix:: +TEdges& cpPlugins::Pipeline::TAdjMatrix:: +operator()( const std::string& o, const std::string& d ) const +{ + TMatrix::const_iterator m = this->m_Matrix.find( o ); + if( m != this->m_Matrix.end( ) ) + { + TRow::const_iterator r = m->second.find( d ); + if( r != m->second.end( ) ) + return( r->second ); + } // end if + + // If not found... + cpPluginsErrorMacro( << "Connection not found." ); +} + +// ------------------------------------------------------------------------- +template< > +void cpPlugins::Pipeline::TAdjMatrix:: +SaveXML( boost::property_tree::ptree* node ) const +{ + TMatrix::const_iterator m = this->m_Matrix.begin( ); + for( ; m != this->m_Matrix.end( ); ++m ) + { + TRow::const_iterator r = m->second.begin( ); + for( ; r != m->second.end( ); r++ ) + { + for( const TEdge& e: r->second ) + { + boost::property_tree::ptree c; + c.put( ".from", e.first + "@" + m->first ); + c.put( ".to", e.second + "@" + r->first ); + node->add_child( "pipeline.connection", c ); + + } // end for + } // end for + } // end for +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline:: +Clear( ) +{ + // TODO +} + +// ------------------------------------------------------------------------- +cpPlugins::ProcessObject* cpPlugins::Pipeline:: +CreateNode( const std::string& class_name, const std::string& node_name ) +{ + // Create object + cpPlugins::ProcessObject::SharedPtr p = this->m_Mgr.Create( class_name ); + if( !p ) + cpPluginsErrorMacro( + << "Something went wrong creating an object of type \"" + << class_name << "\"" + ); + + // Assign an unique name to it + std::string u = ( node_name == "" )? class_name: node_name; + while( !( this->m_Nodes.insert( TNodes::value_type( u, p ) ).second ) ) + u += "_"; + p->SetName( u ); + p->SetPipeline( this ); + p->SetExecutionDebug( this->GetExecutionDebug( ) ); + + // Connect parameters + std::set< std::string > names; + {{#t}} + names = p->Get{{t}}ValueNames( ); + for( const std::string& n: names ) + this->Configure{{t}}Value( n + "@" + u, p->Get{{t}}ValueTemplate( n ) ); + names.clear( ); + {{/t}} + + // TODO: connect set/sequences + + return( p.get( ) ); +} + +// ------------------------------------------------------------------------- +cpPlugins::ProcessObject* cpPlugins::Pipeline:: +GetNode( const std::string& name ) +{ + TNodes::iterator i = this->m_Nodes.find( name ); + if( i != this->m_Nodes.end( ) ) + return( i->second.get( ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::ProcessObject* cpPlugins::Pipeline:: +GetNode( const std::string& name ) const +{ + TNodes::const_iterator i = this->m_Nodes.find( name ); + if( i != this->m_Nodes.end( ) ) + return( i->second.get( ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline:: +Connect( + const std::string& oObj, const std::string& dObj, + const std::string& oPort, const std::string& dPort + ) +{ + TNodes::iterator oIt = this->m_Nodes.find( oObj ); + TNodes::iterator dIt = this->m_Nodes.find( dObj ); + TNodes::iterator eIt = this->m_Nodes.end( ); + if( oIt == eIt || dIt == eIt ) + cpPluginsErrorMacro( this, << "Connection not possible." ); + if( this->m_AdjMatrix.HasConnection( oObj, dObj, oPort, dPort ) ) + return; + + // Check destination node + cpPlugins::ProcessObject::SharedPtr dest = dIt->second; + if( !dest ) + cpPluginsErrorMacro( + this, << "Invalid destination \"" << dObj << "\"." + ); + + // Process source node + cpPlugins::Filter* src = oIt->second->Cast< cpPlugins::Filter >( ); + if( src == NULL ) + this->_Connect( + oIt->second->Cast< cpPlugins::Functor >( ), oPort, dest.get( ), dPort + ); + else + this->_Connect( src, oPort, dest.get( ), dPort ); + + // Update adjacency matrix + this->m_AdjMatrix( oObj, dObj ).insert( TEdge( oPort, dPort ) ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline:: +Connect( const std::string& src, const std::string& dest ) +{ + std::string oObj, dObj, oPort, dPort; + Self::_ParseComponentName( src, oObj, oPort ); + Self::_ParseComponentName( dest, dObj, dPort ); + this->Connect( oObj, dObj, oPort, dPort ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline:: +LoadXML( const std::string& fname ) +{ + boost::property_tree::ptree xml; + boost::property_tree::read_xml( fname, xml ); + + // Check for a single pipeline + const boost::property_tree::ptree* pipeline = NULL; + for( const boost::property_tree::ptree::value_type& v: xml ) + { + if( v.first == "pipeline" ) + { + if( pipeline != NULL ) + cpPluginsErrorMacro( << "Multiple pipelines are not supported." ); + pipeline = &( v.second ); + + } // end if + } // end for + + // Ok, seems ok to reset current pipeline + this->Clear( ); + + // Get description + boost::optional< std::string > desc = + pipeline->get_optional< std::string >( ".desc" ); + if( desc ) + this->m_Description = desc.get( ); + + // Load nodes + for( const boost::property_tree::ptree::value_type& node: *pipeline ) + { + if( node.first == "node" ) + { + std::string name = node.second.get< std::string >( ".name" ); + std::string cname = node.second.get< std::string >( ".class" ); + cpPlugins::ProcessObject* n = this->CreateNode( cname, name ); + n->LoadXML( node ); + + } // end if + } // end for + + // Load connections + for( const boost::property_tree::ptree::value_type& c: *pipeline ) + if( c.first == "connection" ) + this->Connect( + c.second.get< std::string >( ".from" ), + c.second.get< std::string >( ".to" ) + ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline:: +SaveXML( const std::string& fname ) const +{ + boost::property_tree::ptree d; + if( this->m_Description != "" ) + d.put( "pipeline..desc", this->m_Description ); + + // Save nodes + TNodes::const_iterator n = this->m_Nodes.begin( ); + for( ; n != this->m_Nodes.end( ); ++n ) + n->second->SaveXML( &d ); + + // Save connections + this->m_AdjMatrix.SaveXML( &d ); + + // Real write + boost::property_tree::xml_writer_settings< std::string > s( ' ', 2 ); + boost::property_tree::write_xml( fname, d, std::locale( ), s ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Pipeline:: +GetExecutionDebug( ) const +{ + return( this->m_PipelineExecutionDebug ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline:: +SetExecutionDebug( bool d ) +{ + this->m_PipelineExecutionDebug = d; + for( TNodes::value_type& n: this->m_Nodes ) + n.second->SetExecutionDebug( d ); +} + +// ------------------------------------------------------------------------- +{{#t}} +void cpPlugins::Pipeline:: +Modified{{t}}Value( const std::string& name ) +{ + // Guess information + std::string n, v; + Self::_ParseComponentName( name, n, v ); + + // Find node + TNodes::iterator node = this->m_Nodes.find( n ); + if( node == this->m_Nodes.end( ) ) + cpPluginsErrorMacro( + this, << "Unknown node \"" << n << "\"." + ); + + // Get configured value and continue + node->second->Set{{t}}Value( v, this->Get{{t}}Value( name ) ); + this->Superclass::Modified{{t}}Value( name ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline:: +Modified{{t}}Set( const std::string& name ) +{ + std::cout << "Modified{{t}}Set: " << name << std::endl; + this->Superclass::Modified{{t}}Set( name ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline:: +Modified{{t}}Sequence( const std::string& name ) +{ + std::cout << "Modified{{t}}Sequence: " << name << std::endl; + this->Superclass::Modified{{t}}Sequence( name ); +} +{{/t}} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline:: +ModifiedChoice( const std::string& name ) +{ + std::cout << "ModifiedChoice: " << name << std::endl; + this->Superclass::ModifiedChoice( name ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline:: +DefineInput( + const std::string& input, const std::string& node, const std::string& port + ) +{ + if( + this->m_InputRelations.insert( + TPortRelations::value_type( input, TEdge( node, port ) ) + ).second + ) + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline:: +SetInput( const std::string& name, cpPlugins::DataObject* data ) +{ + // Guess information + std::string n, o; + TPortRelations::const_iterator rIt = this->m_OutputRelations.find( name ); + if( rIt != this->m_InputRelations.end( ) ) + { + n = rIt->second.first; + o = rIt->second.second; + } + else + Self::_ParseComponentName( name, n, o ); + + // Find node + TNodes::iterator node = this->m_Nodes.find( n ); + if( node == this->m_Nodes.end( ) ) + cpPluginsErrorMacro( + this, << "Unknown node \"" << n << "\"." + ); + node->second->SetInput( o, data ); +} + +// ------------------------------------------------------------------------- +cpPlugins::DataObject* cpPlugins::Pipeline:: +GetInput( const std::string& name, const unsigned int id ) +{ + // Guess information + std::string n, o; + TPortRelations::const_iterator rIt = this->m_OutputRelations.find( name ); + if( rIt != this->m_InputRelations.end( ) ) + { + n = rIt->second.first; + o = rIt->second.second; + } + else + Self::_ParseComponentName( name, n, o ); + + // Find node + TNodes::iterator node = this->m_Nodes.find( n ); + if( node == this->m_Nodes.end( ) ) + cpPluginsErrorMacro( + this, << "Unknown node \"" << n << "\"." + ); + return( node->second->GetInput( o, id ) ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::DataObject* cpPlugins::Pipeline:: +GetInput( const std::string& name, const unsigned int id ) const +{ + // Guess information + std::string n, o; + TPortRelations::const_iterator rIt = this->m_OutputRelations.find( name ); + if( rIt != this->m_InputRelations.end( ) ) + { + n = rIt->second.first; + o = rIt->second.second; + } + else + Self::_ParseComponentName( name, n, o ); + + // Find node + TNodes::const_iterator node = this->m_Nodes.find( n ); + if( node == this->m_Nodes.end( ) ) + cpPluginsErrorMacro( + this, << "Unknown node \"" << n << "\"." + ); + return( node->second->GetInput( o, id ) ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Pipeline:: +HasInput( const std::string& name ) const +{ + // Guess information + std::string n, o; + TPortRelations::const_iterator rIt = this->m_OutputRelations.find( name ); + if( rIt != this->m_InputRelations.end( ) ) + { + n = rIt->second.first; + o = rIt->second.second; + } + else + Self::_ParseComponentName( name, n, o ); + + // Find node + TNodes::const_iterator node = this->m_Nodes.find( n ); + if( node == this->m_Nodes.end( ) ) + cpPluginsErrorMacro( + this, << "Unknown node \"" << n << "\"." + ); + return( node->second->HasInput( n ) ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline:: +DefineOutput( + const std::string& output, const std::string& node, const std::string& port + ) +{ + if( + this->m_OutputRelations.insert( + TPortRelations::value_type( output, TEdge( node, port ) ) + ).second + ) + this->Modified( ); +} + +// ------------------------------------------------------------------------- +cpPlugins::DataObject* cpPlugins::Pipeline:: +GetOutput( const std::string& name ) +{ + // Guess information + std::string n, o; + TPortRelations::const_iterator rIt = this->m_OutputRelations.find( name ); + if( rIt != this->m_OutputRelations.end( ) ) + { + n = rIt->second.first; + o = rIt->second.second; + } + else + Self::_ParseComponentName( name, n, o ); + + // Find node + TNodes::iterator node = this->m_Nodes.find( n ); + if( node == this->m_Nodes.end( ) ) + cpPluginsErrorMacro( + this, << "Unknown node \"" << n << "\"." + ); + cpPlugins::Filter* f = node->second->Cast< cpPlugins::Filter >( ); + if( f != NULL ) + return( f->GetOutput( o ) ); + else + cpPluginsErrorMacro( + this, << "Node \"" << n << "\" does not have outputs." + ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::DataObject* cpPlugins::Pipeline:: +GetOutput( const std::string& name ) const +{ + // Guess information + std::string n, o; + TPortRelations::const_iterator rIt = this->m_OutputRelations.find( name ); + if( rIt != this->m_OutputRelations.end( ) ) + { + n = rIt->second.first; + o = rIt->second.second; + } + else + Self::_ParseComponentName( name, n, o ); + + // Find node + TNodes::const_iterator node = this->m_Nodes.find( n ); + if( node == this->m_Nodes.end( ) ) + cpPluginsErrorMacro( + this, << "Unknown node \"" << n << "\"." + ); + const cpPlugins::Filter* f = node->second->Cast< cpPlugins::Filter >( ); + if( f != NULL ) + return( f->GetOutput( o ) ); + else + cpPluginsErrorMacro( + this, << "Node \"" << n << "\" does not have outputs." + ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline:: +Pipeline( ) + : Superclass( ), + m_Description( "" ), + m_PipelineExecutionDebug( false ) +{ + this->m_Mgr.Configure( ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline:: +~Pipeline( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline:: +_GenerateData( ) +{ + for( TNodes::value_type& v: this->m_Nodes ) + v.second->Cast< cpPlugins::ProcessObject >( )->Update( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline:: +_Connect( + Filter* src, const std::string& srcPort, + ProcessObject* dest, const std::string& destPort + ) +{ + if( src->HasOutValue( srcPort ) && dest->HasInValue( destPort ) ) + { + } + else if( src->HasOutput( srcPort ) && dest->HasInput( destPort ) ) + dest->SetInput( destPort, src->GetOutput( srcPort ) ); + else + cpPluginsErrorMacro( + this, + << "Invalid connection from \"" << src->GetName( ) << "\" to \"" + << dest->GetName( ) << " (" << srcPort << "->" << destPort << ")" + ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline:: +_Connect( + Functor* functor, const std::string& functorValue, + ProcessObject* dest, const std::string& destValue + ) +{ + if( functorValue == "Functor" ) + { + Filter* filter = dynamic_cast< Filter* >( dest ); + if( filter != NULL ) + filter->SetFunctor( destValue, functor ); + else + cpPluginsErrorMacro( this, << "Invalid functor connection." ); + } + else + { + if( + functor->HasOutValue( functorValue ) && dest->HasInValue( destValue ) + ) + dest->SetInValuePtr( + destValue, functor->GetOutValuePtr( functorValue ) + ); + else + cpPluginsErrorMacro( + this, + << "Invalid connection from \"" << functor->GetName( ) << "\" to \"" + << dest->GetName( ) << " (" << functorValue << "->" + << destValue << ")" + ); + } // end if +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline:: +_ParseComponentName( + const std::string& name, + std::string& node, + std::string& component + ) +{ + typedef boost::char_separator< char > _TSep; + typedef boost::tokenizer< _TSep > _TTok; + + // Get parameter info + _TTok tok( name, _TSep( "@" ) ); + std::vector< std::string > tokens; + for( _TTok::const_iterator tIt = tok.begin( ); tIt != tok.end( ); ++tIt ) + tokens.push_back( *tIt ); + + // Try another distribution + if( tokens.size( ) != 2 ) + { + } // end if + + // Nothing else to do? + if( tokens.size( ) != 2 ) + cpPluginsErrorMacro( + << "Unknown input value parameter \"" << name << "\"." + ); + + // Names + component = tokens[ 0 ]; + node = tokens[ 1 ]; +} + +// eof - $RCSfile$