// ========================================================================= // @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$