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