]> Creatis software - cpPlugins.git/blob - lib/cpPlugins/Interface/WorkspaceIO.cxx
9a019ebafe4643b68295cd0cea2c92a0ee8bb88a
[cpPlugins.git] / lib / cpPlugins / Interface / WorkspaceIO.cxx
1 #include <cpPlugins/Interface/Workspace.h>
2 #include <tinyxml2/tinyxml2.h>
3
4 // -------------------------------------------------------------------------
5 void cpPlugins::Interface::Workspace::
6 Load( const std::string& fname )
7 {
8   this->Clear( );
9   TInterface::Pointer interface = TInterface::New( );
10
11   // Read from disk
12   tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument( );
13   doc->LoadFile( fname.c_str( ) );
14   tinyxml2::XMLElement* root = doc->RootElement( );
15   if( root == NULL )
16   {
17     delete doc;
18     throw std::runtime_error( "cpPlugins::Workspace: No valid file" );
19
20   } // fi
21   if( std::string( root->Value( ) ) != "cpPlugins_Workspace" )
22   {
23     delete doc;
24     throw std::runtime_error( "cpPlugins::Workspace: Not a valid workspace" );
25
26   } // fi
27
28   // Load plugins
29   auto loaded_plugins = interface->GetPlugins( );
30   tinyxml2::XMLElement* plugins = root->FirstChildElement( "Plugins" );
31   std::string plugins_errors = "";
32   while( plugins != NULL )
33   {
34     tinyxml2::XMLElement* plugin = plugins->FirstChildElement( "Plugin" );
35     while( plugin != NULL )
36     {
37       std::string name = plugin->Attribute( "Name" );
38       if( loaded_plugins.find( name ) == loaded_plugins.end( ) )
39       {
40         try
41         {
42           interface->LoadPlugin( name );
43         }
44         catch( std::exception& err )
45         {
46           plugins_errors += err.what( ) + std::string( "\n" );
47
48         } // yrt
49
50       } // fi
51       plugin = plugin->NextSiblingElement( "Plugin" );
52
53     } // elihw
54     plugins = plugins->NextSiblingElement( "Plugins" );
55
56   } // elihw
57   if( plugins_errors != "" )
58   {
59     delete doc;
60     throw std::runtime_error(
61       std::string( "cpPlugins::Workspace: " ) + plugins_errors
62       );
63
64   } // fi
65
66   // Read filters
67   std::stringstream err;
68   tinyxml2::XMLElement* filter = root->FirstChildElement( "Filter" );
69   while( filter != NULL )
70   {
71     const char* category_value = filter->Attribute( "Category" );
72     const char* class_value = filter->Attribute( "Class" );
73     const char* name_value = filter->Attribute( "Name" );
74     float viewX = float( 0 ), viewY = float( 0 );
75     filter->QueryFloatAttribute( "ViewX", &viewX );
76     filter->QueryFloatAttribute( "ViewY", &viewY );
77     int explicit_execution = 0;
78     filter->QueryIntAttribute(
79       "ExplicitExecution", &explicit_execution
80       );
81     if( class_value != NULL && name_value != NULL )
82     {
83       auto new_filter =
84         this->CreateFilter( category_value, class_value, name_value );
85       if( new_filter != NULL )
86       {
87         new_filter->SetViewCoords( viewX, viewY );
88         new_filter->SetExplicitExecution( explicit_execution == 1 );
89         new_filter->GetParameters( )->FromXML( filter );
90       }
91       else
92         err
93           << "No valid class \"" << class_value << "\" with name \""
94           << name_value << "\"" << std::endl;
95     }
96     else
97       err << "Incomplete data." << std::endl;
98     filter = filter->NextSiblingElement( "Filter" );
99
100   } // elihw
101
102   // Read connections
103   tinyxml2::XMLElement* connection = root->FirstChildElement( "Connection" );
104   while( connection != NULL )
105   {
106     tinyxml2::XMLElement* orig = connection->FirstChildElement( "Origin" );
107     tinyxml2::XMLElement* dest = connection->FirstChildElement( "Destination" );
108     if( orig != NULL && dest != NULL )
109     {
110       const char* orig_filter = orig->Attribute( "Filter" );
111       const char* dest_filter = dest->Attribute( "Filter" );
112       const char* orig_name = orig->Attribute( "Name" );
113       const char* dest_name = dest->Attribute( "Name" );
114       if(
115         orig_filter != NULL && dest_filter != NULL &&
116         orig_name != NULL && dest_name != NULL
117         )
118       {
119         try
120         {
121           this->Connect( orig_filter, dest_filter, orig_name, dest_name );
122         }
123         catch( std::exception& exc )
124         {
125           err << exc.what( ) << std::endl;
126
127         } // yrt
128
129       } // fi
130
131     } // fi
132     connection = connection->NextSiblingElement( "Connection" );
133
134   } // elihw
135
136   // Read exposed inputs
137   tinyxml2::XMLElement* port = root->FirstChildElement( "ExposedInput" );
138   while( port != NULL )
139   {
140     this->ExposeInput(
141       port->Attribute( "Name" ),
142       port->Attribute( "Filter" ),
143       port->Attribute( "Input" )
144       );
145     port = port->NextSiblingElement( "ExposedInput" );
146
147   } // elihw
148
149   // Read exposed outputs
150   port = root->FirstChildElement( "ExposedOutput" );
151   while( port != NULL )
152   {
153     this->ExposeOutput(
154       port->Attribute( "Name" ),
155       port->Attribute( "Filter" ),
156       port->Attribute( "Output" )
157       );
158     port = port->NextSiblingElement( "ExposedOutput" );
159
160   } // elihw
161
162   // Throw errors
163   std::string err_str = err.str( );
164   if( err_str != "" )
165   {
166     delete doc;
167     throw std::runtime_error(
168       std::string( "cpPlugins::Workspace " ) + err_str
169       );
170
171   } // fi
172
173   // Finish
174   delete doc;
175 }
176
177 // -------------------------------------------------------------------------
178 void cpPlugins::Interface::Workspace::
179 Save( const std::string& fname ) const
180 {
181   tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument( );
182   tinyxml2::XMLElement* root = doc->NewElement( "cpPlugins_Workspace" );
183   std::set< std::string > used_plugins;
184
185   // Save filter data
186   for( auto i = this->m_Filters.begin( ); i != this->m_Filters.end( ); ++i )
187   {
188     auto filter = i->second;
189     used_plugins.insert( filter->GetPluginName( ) );
190     tinyxml2::XMLElement* e = doc->NewElement( "Filter" );
191     e->SetAttribute( "Category", filter->GetClassCategory( ) );
192     e->SetAttribute( "Class", filter->GetClassName( ) );
193     e->SetAttribute( "Name", filter->GetName( ) );
194     e->SetAttribute( "ViewX", filter->GetViewX( ) );
195     e->SetAttribute( "ViewY", filter->GetViewY( ) );
196     e->SetAttribute(
197       "ExplicitExecution", ( filter->GetExplicitExecution( ) )? 1: 0
198       );
199
200     auto params = filter->GetParameters( );
201     params->ToXML( doc, e );
202     root->LinkEndChild( e );
203
204   } // rof
205
206   // Save used plugins
207   tinyxml2::XMLElement* plugins = doc->NewElement( "Plugins" );
208   for( auto pIt = used_plugins.begin( ); pIt != used_plugins.end( ); ++pIt )
209   {
210     tinyxml2::XMLElement* e = doc->NewElement( "Plugin" );
211     e->SetAttribute( "Name", pIt->c_str( ) );
212     plugins->LinkEndChild( e );
213
214   } // rof
215   root->LinkEndChild( plugins );
216
217   // Save connections
218   for( auto i = this->m_Filters.begin( ); i != this->m_Filters.end( ); ++i )
219   {
220     auto orig = i->second;
221     auto outputs = orig->GetOutputsNames( );
222     if( outputs.size( ) == 0 )
223       continue;
224     for( auto j = this->m_Filters.begin( ); j != this->m_Filters.end( ); ++j )
225     {
226       if( i == j )
227         continue;
228       auto dest = j->second;
229       auto inputs = dest->GetInputsNames( );
230       if( inputs.size( ) == 0 )
231         continue;
232
233       for( auto oIt = outputs.begin( ); oIt != outputs.end( ); ++oIt )
234       {
235         auto od = orig->GetOutput( *oIt );
236         for( auto iIt = inputs.begin( ); iIt != inputs.end( ); ++iIt )
237         {
238           unsigned int nInputs = dest->GetInputSize( *iIt );
239           for( unsigned int k = 0; k < nInputs; ++k )
240           {
241             auto id = dest->GetInput( *iIt, k );
242             if( od != NULL && od == id )
243             {
244               tinyxml2::XMLElement* e_conn = doc->NewElement( "Connection" );
245               tinyxml2::XMLElement* e_orig = doc->NewElement( "Origin" );
246               tinyxml2::XMLElement* e_dest = doc->NewElement( "Destination" );
247               e_orig->SetAttribute( "Filter", orig->GetName( ) );
248               e_orig->SetAttribute( "Name", oIt->c_str( ) );
249               e_dest->SetAttribute( "Filter", dest->GetName( ) );
250               e_dest->SetAttribute( "Name", iIt->c_str( ) );
251               e_conn->LinkEndChild( e_orig );
252               e_conn->LinkEndChild( e_dest );
253               root->LinkEndChild( e_conn );
254
255             } // fi
256
257           } // rof
258
259         } // rof
260
261       } // rof
262       
263     } // rof
264
265   } // rof
266
267
268   // Save exposed ports
269   auto eipIt = this->m_ExposedInputs.begin( );
270   for( ; eipIt != this->m_ExposedInputs.end( ); ++eipIt )
271   {
272     tinyxml2::XMLElement* port = doc->NewElement( "ExposedInput" );
273     port->SetAttribute( "Name", eipIt->first.c_str( ) );
274     port->SetAttribute( "Filter", eipIt->second.first.c_str( ) );
275     port->SetAttribute( "Input", eipIt->second.second.c_str( ) );
276     root->LinkEndChild( port );
277
278   } // rof
279
280   auto eopIt = this->m_ExposedOutputs.begin( );
281   for( ; eopIt != this->m_ExposedOutputs.end( ); ++eopIt )
282   {
283     tinyxml2::XMLElement* port = doc->NewElement( "ExposedOutput" );
284     port->SetAttribute( "Name", eopIt->first.c_str( ) );
285     port->SetAttribute( "Filter", eopIt->second.first.c_str( ) );
286     port->SetAttribute( "Output", eopIt->second.second.c_str( ) );
287     root->LinkEndChild( port );
288
289   } // rof
290
291   // Physical write and return
292   doc->LinkEndChild( root );
293   auto error = doc->SaveFile( fname.c_str( ) );
294   delete doc;
295   if( error != tinyxml2::XML_SUCCESS )
296   {
297     std::string m;
298     switch( error )
299     {
300     case tinyxml2::XML_NO_ATTRIBUTE:
301       m = "No attribute."; break;
302     case tinyxml2::XML_WRONG_ATTRIBUTE_TYPE:
303       m = "Wrong attribute."; break;
304     case tinyxml2::XML_ERROR_FILE_NOT_FOUND:
305       m = "File not found."; break;
306     case tinyxml2::XML_ERROR_FILE_COULD_NOT_BE_OPENED:
307       m = "File not opened."; break;
308     case tinyxml2::XML_ERROR_FILE_READ_ERROR:
309       m = "File not read."; break;
310     case tinyxml2::XML_ERROR_ELEMENT_MISMATCH:
311       m = "Element mismatch."; break;
312     case tinyxml2::XML_ERROR_PARSING_ELEMENT:
313       m = "Parsing element."; break;
314     case tinyxml2::XML_ERROR_PARSING_ATTRIBUTE:
315       m = "Parsing attribute."; break;
316     case tinyxml2::XML_ERROR_IDENTIFYING_TAG:
317       m = "Tag Id."; break;
318     case tinyxml2::XML_ERROR_PARSING_TEXT:
319       m = "Parsing text."; break;
320     case tinyxml2::XML_ERROR_PARSING_CDATA:
321       m = "Parsing cdata."; break;
322     case tinyxml2::XML_ERROR_PARSING_COMMENT:
323       m = "Parsing comment."; break;
324     case tinyxml2::XML_ERROR_PARSING_DECLARATION:
325       m = "Parsing declaration."; break;
326     case tinyxml2::XML_ERROR_PARSING_UNKNOWN:
327       m = "Parsing unknown."; break;
328     case tinyxml2::XML_ERROR_EMPTY_DOCUMENT:
329       m = "Empty document."; break;
330     case tinyxml2::XML_ERROR_MISMATCHED_ELEMENT:
331       m = "Mismatched element."; break;
332     case tinyxml2::XML_ERROR_PARSING:
333       m = "Parsing."; break;
334     case tinyxml2::XML_CAN_NOT_CONVERT_TEXT:
335       m = "Cannot convert."; break;
336     case tinyxml2::XML_NO_TEXT_NODE:
337       m = "No text."; break;
338     default:
339       m = "Unknown error."; break;
340     } // hctiws
341     throw std::runtime_error(
342       std::string( "cpPlugins::Workspace: Error while saving \"" ) +
343       fname + std::string( "\": " ) + m
344       );
345
346   } // fi
347 }
348
349 // eof - $RCSfile$