]> Creatis software - cpPlugins.git/blobdiff - lib/cpPlugins/Pipeline.cxx.d
Moved to version 1.0
[cpPlugins.git] / lib / cpPlugins / Pipeline.cxx.d
diff --git a/lib/cpPlugins/Pipeline.cxx.d b/lib/cpPlugins/Pipeline.cxx.d
new file mode 100644 (file)
index 0000000..8ce0e09
--- /dev/null
@@ -0,0 +1,638 @@
+// =========================================================================
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// =========================================================================
+
+$include "Value.e"
+
+#include <cpPlugins/Pipeline.h>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/xml_parser.hpp>
+#include <boost/tokenizer.hpp>
+
+// -------------------------------------------------------------------------
+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( "<xmlattr>.from", e.first + "@" + m->first );
+        c.put( "<xmlattr>.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 >( "<xmlattr>.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 >( "<xmlattr>.name" );
+      std::string cname = node.second.get< std::string >( "<xmlattr>.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 >( "<xmlattr>.from" ),
+        c.second.get< std::string >( "<xmlattr>.to" )
+        );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::
+SaveXML( const std::string& fname ) const
+{
+  boost::property_tree::ptree d;
+  if( this->m_Description != "" )
+    d.put( "pipeline.<xmlattr>.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$