]> Creatis software - cpPlugins.git/blobdiff - lib/cpPlugins/Interface/WorkspaceIO.cxx
...
[cpPlugins.git] / lib / cpPlugins / Interface / WorkspaceIO.cxx
index dcf6c6852f17af9a26f509d494d1bf852ebcac0a..9a019ebafe4643b68295cd0cea2c92a0ee8bb88a 100644 (file)
@@ -1,38 +1,92 @@
 #include <cpPlugins/Interface/Workspace.h>
-#include <third_party/tinyxml/tinyxml.h>
+#include <tinyxml2/tinyxml2.h>
 
 // -------------------------------------------------------------------------
-std::string cpPlugins::Interface::Workspace::
-LoadWorkspace( const std::string& fname )
+void cpPlugins::Interface::Workspace::
+Load( const std::string& fname )
 {
-  TiXmlDocument* doc = new TiXmlDocument( fname.c_str( ) );
-  doc->LoadFile( );
-  TiXmlElement* root = doc->RootElement( );
+  this->Clear( );
+  TInterface::Pointer interface = TInterface::New( );
+
+  // Read from disk
+  tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument( );
+  doc->LoadFile( fname.c_str( ) );
+  tinyxml2::XMLElement* root = doc->RootElement( );
   if( root == NULL )
-    return( "cpPlugins::Interface::Workspace: No valid file" );
+  {
+    delete doc;
+    throw std::runtime_error( "cpPlugins::Workspace: No valid file" );
+
+  } // fi
   if( std::string( root->Value( ) ) != "cpPlugins_Workspace" )
-    return( "cpPlugins::Interface::Workspace: No valid workspace" );
-  std::stringstream err;
+  {
+    delete doc;
+    throw std::runtime_error( "cpPlugins::Workspace: Not a valid workspace" );
+
+  } // fi
+
+  // Load plugins
+  auto loaded_plugins = interface->GetPlugins( );
+  tinyxml2::XMLElement* plugins = root->FirstChildElement( "Plugins" );
+  std::string plugins_errors = "";
+  while( plugins != NULL )
+  {
+    tinyxml2::XMLElement* plugin = plugins->FirstChildElement( "Plugin" );
+    while( plugin != NULL )
+    {
+      std::string name = plugin->Attribute( "Name" );
+      if( loaded_plugins.find( name ) == loaded_plugins.end( ) )
+      {
+        try
+        {
+          interface->LoadPlugin( name );
+        }
+        catch( std::exception& err )
+        {
+          plugins_errors += err.what( ) + std::string( "\n" );
+
+        } // yrt
+
+      } // fi
+      plugin = plugin->NextSiblingElement( "Plugin" );
+
+    } // elihw
+    plugins = plugins->NextSiblingElement( "Plugins" );
+
+  } // elihw
+  if( plugins_errors != "" )
+  {
+    delete doc;
+    throw std::runtime_error(
+      std::string( "cpPlugins::Workspace: " ) + plugins_errors
+      );
+
+  } // fi
 
   // Read filters
-  TiXmlElement* filter = root->FirstChildElement( "filter" );
+  std::stringstream err;
+  tinyxml2::XMLElement* filter = root->FirstChildElement( "Filter" );
   while( filter != NULL )
   {
-    const char* class_value = filter->Attribute( "class" );
-    const char* name_value = filter->Attribute( "name" );
+    const char* category_value = filter->Attribute( "Category" );
+    const char* class_value = filter->Attribute( "Class" );
+    const char* name_value = filter->Attribute( "Name" );
     float viewX = float( 0 ), viewY = float( 0 );
     filter->QueryFloatAttribute( "ViewX", &viewX );
     filter->QueryFloatAttribute( "ViewY", &viewY );
+    int explicit_execution = 0;
+    filter->QueryIntAttribute(
+      "ExplicitExecution", &explicit_execution
+      );
     if( class_value != NULL && name_value != NULL )
     {
-      if( this->CreateFilter( class_value, name_value ) )
+      auto new_filter =
+        this->CreateFilter( category_value, class_value, name_value );
+      if( new_filter != NULL )
       {
-        TFilter* new_filter = this->GetFilter( name_value );
         new_filter->SetViewCoords( viewX, viewY );
-
-        // Read parameters
-        TParameters* parameters = new_filter->GetParameters( );
-        parameters->FromXML( filter );
+        new_filter->SetExplicitExecution( explicit_execution == 1 );
+        new_filter->GetParameters( )->FromXML( filter );
       }
       else
         err
@@ -41,154 +95,255 @@ LoadWorkspace( const std::string& fname )
     }
     else
       err << "Incomplete data." << std::endl;
-    filter = filter->NextSiblingElement( "filter" );
+    filter = filter->NextSiblingElement( "Filter" );
 
   } // elihw
 
   // Read connections
-  TiXmlElement* connection = root->FirstChildElement( "connection" );
+  tinyxml2::XMLElement* connection = root->FirstChildElement( "Connection" );
   while( connection != NULL )
   {
-    TiXmlElement* orig = connection->FirstChildElement( "origin" );
-    TiXmlElement* dest = connection->FirstChildElement( "destination" );
+    tinyxml2::XMLElement* orig = connection->FirstChildElement( "Origin" );
+    tinyxml2::XMLElement* dest = connection->FirstChildElement( "Destination" );
     if( orig != NULL && dest != NULL )
     {
-      const char* orig_filter = orig->Attribute( "filter" );
-      const char* dest_filter = dest->Attribute( "filter" );
-      const char* orig_name = orig->Attribute( "name" );
-      const char* dest_name = dest->Attribute( "name" );
+      const char* orig_filter = orig->Attribute( "Filter" );
+      const char* dest_filter = dest->Attribute( "Filter" );
+      const char* orig_name = orig->Attribute( "Name" );
+      const char* dest_name = dest->Attribute( "Name" );
       if(
         orig_filter != NULL && dest_filter != NULL &&
         orig_name != NULL && dest_name != NULL
         )
-        this->Connect( orig_filter, dest_filter, orig_name, dest_name );
+      {
+        try
+        {
+          this->Connect( orig_filter, dest_filter, orig_name, dest_name );
+        }
+        catch( std::exception& exc )
+        {
+          err << exc.what( ) << std::endl;
+
+        } // yrt
+
+      } // fi
 
     } // fi
-    connection = connection->NextSiblingElement( "connection" );
+    connection = connection->NextSiblingElement( "Connection" );
 
   } // elihw
 
   // Read exposed inputs
-  TiXmlElement* port = root->FirstChildElement( "exposed_input_port" );
+  tinyxml2::XMLElement* port = root->FirstChildElement( "ExposedInput" );
   while( port != NULL )
   {
-    this->ExposeInputPort(
-      port->Attribute( "port_name" ),
-      port->Attribute( "filter" ),
-      port->Attribute( "filter_port_name" )
+    this->ExposeInput(
+      port->Attribute( "Name" ),
+      port->Attribute( "Filter" ),
+      port->Attribute( "Input" )
       );
-    port = port->NextSiblingElement( "exposed_input_port" );
+    port = port->NextSiblingElement( "ExposedInput" );
 
   } // elihw
 
   // Read exposed outputs
-  port = root->FirstChildElement( "exposed_output_port" );
+  port = root->FirstChildElement( "ExposedOutput" );
   while( port != NULL )
   {
-    this->ExposeOutputPort(
-      port->Attribute( "port_name" ),
-      port->Attribute( "filter" ),
-      port->Attribute( "filter_port_name" )
+    this->ExposeOutput(
+      port->Attribute( "Name" ),
+      port->Attribute( "Filter" ),
+      port->Attribute( "Output" )
       );
-    port = port->NextSiblingElement( "exposed_output_port" );
+    port = port->NextSiblingElement( "ExposedOutput" );
 
   } // elihw
 
-  // Finish and return
+  // Throw errors
+  std::string err_str = err.str( );
+  if( err_str != "" )
+  {
+    delete doc;
+    throw std::runtime_error(
+      std::string( "cpPlugins::Workspace " ) + err_str
+      );
+
+  } // fi
+
+  // Finish
   delete doc;
-  return( err.str( ) );
 }
 
 // -------------------------------------------------------------------------
-std::string cpPlugins::Interface::Workspace::
-SaveWorkspace( const std::string& fname ) const
+void cpPlugins::Interface::Workspace::
+Save( const std::string& fname ) const
 {
-  std::stringstream err;
-  TiXmlDocument* doc = new TiXmlDocument( );
-  TiXmlElement* root = new TiXmlElement( "cpPlugins_Workspace" );
+  tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument( );
+  tinyxml2::XMLElement* root = doc->NewElement( "cpPlugins_Workspace" );
+  std::set< std::string > used_plugins;
 
-  // Save vertices
-  auto vIt = this->m_Graph->BeginVertices( );
-  for( ; vIt != this->m_Graph->EndVertices( ); ++vIt )
+  // Save filter data
+  for( auto i = this->m_Filters.begin( ); i != this->m_Filters.end( ); ++i )
   {
-    auto filter = dynamic_cast< TFilter* >( vIt->second.GetPointer( ) );
-    auto data = dynamic_cast< TData* >( vIt->second.GetPointer( ) );
-    if( filter != NULL )
-    {
-      TiXmlElement* e = new TiXmlElement( "filter" );
-      e->SetAttribute( "class", filter->GetClassName( ) );
-      e->SetAttribute( "name", filter->GetName( ) );
-      e->SetAttribute( "ViewX", filter->GetViewX( ) );
-      e->SetAttribute( "ViewY", filter->GetViewY( ) );
+    auto filter = i->second;
+    used_plugins.insert( filter->GetPluginName( ) );
+    tinyxml2::XMLElement* e = doc->NewElement( "Filter" );
+    e->SetAttribute( "Category", filter->GetClassCategory( ) );
+    e->SetAttribute( "Class", filter->GetClassName( ) );
+    e->SetAttribute( "Name", filter->GetName( ) );
+    e->SetAttribute( "ViewX", filter->GetViewX( ) );
+    e->SetAttribute( "ViewY", filter->GetViewY( ) );
+    e->SetAttribute(
+      "ExplicitExecution", ( filter->GetExplicitExecution( ) )? 1: 0
+      );
 
-      const TParameters* params = filter->GetParameters( );
-      params->ToXML( e );
+    auto params = filter->GetParameters( );
+    params->ToXML( doc, e );
+    root->LinkEndChild( e );
 
-      root->LinkEndChild( e );
-    }
-    else if( data != NULL )
-    {
-      // TODO
-    } // fi
+  } // rof
+
+  // Save used plugins
+  tinyxml2::XMLElement* plugins = doc->NewElement( "Plugins" );
+  for( auto pIt = used_plugins.begin( ); pIt != used_plugins.end( ); ++pIt )
+  {
+    tinyxml2::XMLElement* e = doc->NewElement( "Plugin" );
+    e->SetAttribute( "Name", pIt->c_str( ) );
+    plugins->LinkEndChild( e );
 
   } // rof
+  root->LinkEndChild( plugins );
 
   // Save connections
-  auto mIt = this->m_Graph->BeginEdgesRows( );
-  for( ; mIt != this->m_Graph->EndEdgesRows( ); ++mIt )
+  for( auto i = this->m_Filters.begin( ); i != this->m_Filters.end( ); ++i )
   {
-    auto rIt = mIt->second.begin( );
-    for( ; rIt != mIt->second.end( ); ++rIt )
+    auto orig = i->second;
+    auto outputs = orig->GetOutputsNames( );
+    if( outputs.size( ) == 0 )
+      continue;
+    for( auto j = this->m_Filters.begin( ); j != this->m_Filters.end( ); ++j )
     {
-      auto eIt = rIt->second.begin( );
-      for( ; eIt != rIt->second.end( ); ++eIt )
+      if( i == j )
+        continue;
+      auto dest = j->second;
+      auto inputs = dest->GetInputsNames( );
+      if( inputs.size( ) == 0 )
+        continue;
+
+      for( auto oIt = outputs.begin( ); oIt != outputs.end( ); ++oIt )
       {
-        TiXmlElement* conn = new TiXmlElement( "connection" );
-        TiXmlElement* orig = new TiXmlElement( "origin" );
-        TiXmlElement* dest = new TiXmlElement( "destination" );
-        orig->SetAttribute( "filter", mIt->first.c_str( ) );
-        orig->SetAttribute( "name", eIt->first.c_str( ) );
-        dest->SetAttribute( "filter", rIt->first.c_str( ) );
-        dest->SetAttribute( "name", eIt->second.c_str( ) );
-
-        conn->LinkEndChild( orig );
-        conn->LinkEndChild( dest );
-        root->LinkEndChild( conn );
+        auto od = orig->GetOutput( *oIt );
+        for( auto iIt = inputs.begin( ); iIt != inputs.end( ); ++iIt )
+        {
+          unsigned int nInputs = dest->GetInputSize( *iIt );
+          for( unsigned int k = 0; k < nInputs; ++k )
+          {
+            auto id = dest->GetInput( *iIt, k );
+            if( od != NULL && od == id )
+            {
+              tinyxml2::XMLElement* e_conn = doc->NewElement( "Connection" );
+              tinyxml2::XMLElement* e_orig = doc->NewElement( "Origin" );
+              tinyxml2::XMLElement* e_dest = doc->NewElement( "Destination" );
+              e_orig->SetAttribute( "Filter", orig->GetName( ) );
+              e_orig->SetAttribute( "Name", oIt->c_str( ) );
+              e_dest->SetAttribute( "Filter", dest->GetName( ) );
+              e_dest->SetAttribute( "Name", iIt->c_str( ) );
+              e_conn->LinkEndChild( e_orig );
+              e_conn->LinkEndChild( e_dest );
+              root->LinkEndChild( e_conn );
 
-      } // rof
+            } // fi
 
+          } // rof
+
+        } // rof
+
+      } // rof
+      
     } // rof
 
   } // rof
 
+
   // Save exposed ports
-  auto eipIt = this->m_ExposedInputPorts.begin( );
-  for( ; eipIt != this->m_ExposedInputPorts.end( ); ++eipIt )
+  auto eipIt = this->m_ExposedInputs.begin( );
+  for( ; eipIt != this->m_ExposedInputs.end( ); ++eipIt )
   {
-    TiXmlElement* port = new TiXmlElement( "exposed_input_port" );
-    port->SetAttribute( "port_name", eipIt->first.c_str( ) );
-    port->SetAttribute( "filter", eipIt->second.first.c_str( ) );
-    port->SetAttribute( "filter_port_name", eipIt->second.second.c_str( ) );
+    tinyxml2::XMLElement* port = doc->NewElement( "ExposedInput" );
+    port->SetAttribute( "Name", eipIt->first.c_str( ) );
+    port->SetAttribute( "Filter", eipIt->second.first.c_str( ) );
+    port->SetAttribute( "Input", eipIt->second.second.c_str( ) );
     root->LinkEndChild( port );
 
   } // rof
 
-  auto eopIt = this->m_ExposedOutputPorts.begin( );
-  for( ; eopIt != this->m_ExposedOutputPorts.end( ); ++eopIt )
+  auto eopIt = this->m_ExposedOutputs.begin( );
+  for( ; eopIt != this->m_ExposedOutputs.end( ); ++eopIt )
   {
-    TiXmlElement* port = new TiXmlElement( "exposed_output_port" );
-    port->SetAttribute( "port_name", eopIt->first.c_str( ) );
-    port->SetAttribute( "filter", eopIt->second.first.c_str( ) );
-    port->SetAttribute( "filter_port_name", eopIt->second.second.c_str( ) );
+    tinyxml2::XMLElement* port = doc->NewElement( "ExposedOutput" );
+    port->SetAttribute( "Name", eopIt->first.c_str( ) );
+    port->SetAttribute( "Filter", eopIt->second.first.c_str( ) );
+    port->SetAttribute( "Output", eopIt->second.second.c_str( ) );
     root->LinkEndChild( port );
 
   } // rof
 
   // Physical write and return
   doc->LinkEndChild( root );
-  doc->SaveFile( fname.c_str( ) );
+  auto error = doc->SaveFile( fname.c_str( ) );
   delete doc;
-  return( err.str( ) );
+  if( error != tinyxml2::XML_SUCCESS )
+  {
+    std::string m;
+    switch( error )
+    {
+    case tinyxml2::XML_NO_ATTRIBUTE:
+      m = "No attribute."; break;
+    case tinyxml2::XML_WRONG_ATTRIBUTE_TYPE:
+      m = "Wrong attribute."; break;
+    case tinyxml2::XML_ERROR_FILE_NOT_FOUND:
+      m = "File not found."; break;
+    case tinyxml2::XML_ERROR_FILE_COULD_NOT_BE_OPENED:
+      m = "File not opened."; break;
+    case tinyxml2::XML_ERROR_FILE_READ_ERROR:
+      m = "File not read."; break;
+    case tinyxml2::XML_ERROR_ELEMENT_MISMATCH:
+      m = "Element mismatch."; break;
+    case tinyxml2::XML_ERROR_PARSING_ELEMENT:
+      m = "Parsing element."; break;
+    case tinyxml2::XML_ERROR_PARSING_ATTRIBUTE:
+      m = "Parsing attribute."; break;
+    case tinyxml2::XML_ERROR_IDENTIFYING_TAG:
+      m = "Tag Id."; break;
+    case tinyxml2::XML_ERROR_PARSING_TEXT:
+      m = "Parsing text."; break;
+    case tinyxml2::XML_ERROR_PARSING_CDATA:
+      m = "Parsing cdata."; break;
+    case tinyxml2::XML_ERROR_PARSING_COMMENT:
+      m = "Parsing comment."; break;
+    case tinyxml2::XML_ERROR_PARSING_DECLARATION:
+      m = "Parsing declaration."; break;
+    case tinyxml2::XML_ERROR_PARSING_UNKNOWN:
+      m = "Parsing unknown."; break;
+    case tinyxml2::XML_ERROR_EMPTY_DOCUMENT:
+      m = "Empty document."; break;
+    case tinyxml2::XML_ERROR_MISMATCHED_ELEMENT:
+      m = "Mismatched element."; break;
+    case tinyxml2::XML_ERROR_PARSING:
+      m = "Parsing."; break;
+    case tinyxml2::XML_CAN_NOT_CONVERT_TEXT:
+      m = "Cannot convert."; break;
+    case tinyxml2::XML_NO_TEXT_NODE:
+      m = "No text."; break;
+    default:
+      m = "Unknown error."; break;
+    } // hctiws
+    throw std::runtime_error(
+      std::string( "cpPlugins::Workspace: Error while saving \"" ) +
+      fname + std::string( "\": " ) + m
+      );
+
+  } // fi
 }
 
 // eof - $RCSfile$