--- /dev/null
+package org.simantics.simulation.export;\r
+\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.text.DecimalFormatSymbols;\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.Locale;\r
+\r
+import org.eclipse.core.runtime.preferences.InstanceScope;\r
+import org.eclipse.jface.preference.IPreferenceStore;\r
+import org.eclipse.ui.preferences.ScopedPreferenceStore;\r
+import org.osgi.service.prefs.Preferences;\r
+import org.simantics.databoard.Accessors;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.Datatypes;\r
+import org.simantics.databoard.accessor.RecordAccessor;\r
+import org.simantics.databoard.accessor.error.AccessorConstructionException;\r
+import org.simantics.databoard.accessor.error.AccessorException;\r
+import org.simantics.databoard.accessor.reference.ChildReference;\r
+import org.simantics.databoard.binding.mutable.Variant;\r
+import org.simantics.databoard.type.Datatype;\r
+import org.simantics.databoard.type.DoubleType;\r
+import org.simantics.databoard.type.RecordType;\r
+import org.simantics.export.core.ExportContext;\r
+import org.simantics.export.core.error.ExportException;\r
+import org.simantics.export.core.intf.FormatClass;\r
+import org.simantics.export.core.manager.Content;\r
+import org.simantics.history.HistoryException;\r
+import org.simantics.history.csv.ColumnSeparator;\r
+import org.simantics.history.csv.DecimalSeparator;\r
+\r
+/**\r
+ * This class represents the CSV (Comma Separated Value) file format.\r
+ *\r
+ * @author toni.kalajainen@semantum.fi\r
+ */\r
+public class CSVFormat implements FormatClass {\r
+\r
+ // Accessor paths\r
+ public static ChildReference P_CSV_COLUMN_SEPARATOR = ChildReference.parsePath("Comma Separated Value (CSV)/Column Separator");\r
+ public static ChildReference P_CSV_DECIMAL_SEPARATOR = ChildReference.parsePath("Comma Separated Value (CSV)/Decimal Separator");\r
+ public static ChildReference P_CSV_TIME_STEP = ChildReference.parsePath("Comma Separated Value (CSV)/Time Step"); \r
+ \r
+ static RecordType options;\r
+ static RecordType csvOptions;\r
+ \r
+ static {\r
+ Datatype second = new DoubleType("s");\r
+ \r
+ csvOptions = new RecordType();\r
+ csvOptions.addComponent("Time Step", second);\r
+ csvOptions.addComponent("Column Separator", Datatypes.STRING);\r
+ csvOptions.addComponent("Decimal Separator", Datatypes.STRING);\r
+\r
+ options = new RecordType();\r
+ options.addComponent("Comma Separated Value (CSV)", csvOptions);\r
+ }\r
+ \r
+ @Override\r
+ public RecordType options(ExportContext context)\r
+ throws ExportException {\r
+ return options;\r
+ }\r
+\r
+ @Override\r
+ public List<String> validate(ExportContext context, Variant options) throws ExportException {\r
+ return Collections.emptyList();\r
+ }\r
+ \r
+\r
+ @Override\r
+ public void fillDefaultPrefs( ExportContext ctx, Variant options ) throws ExportException {\r
+ // 1. Figure out suitable default values\r
+ IPreferenceStore csvnode = new ScopedPreferenceStore( InstanceScope.INSTANCE, CSVPreferences.P_NODE );\r
+ \r
+ Double timeStep = CSVPreferences.DEFAULT_CSV_TIME_STEP;\r
+ String decimalSeparator = ".";\r
+ String columnSeparator = "\t";\r
+ \r
+ Locale locale = Locale.getDefault();\r
+ DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance( locale );\r
+ decimalSeparator = symbols.getDecimalSeparator()+""; \r
+ columnSeparator = decimalSeparator.equals(",")?"\\t":",";\r
+\r
+ if (csvnode != null) {\r
+ if ( csvnode.contains(CSVPreferences.P_CSV_TIME_STEP) ) timeStep = csvnode.getDouble(CSVPreferences.P_CSV_TIME_STEP);\r
+ if ( csvnode.contains(CSVPreferences.P_CSV_DECIMAL_SEPARATOR) ) decimalSeparator = csvnode.getString(CSVPreferences.P_CSV_DECIMAL_SEPARATOR);\r
+ if ( csvnode.contains(CSVPreferences.P_CSV_COLUMN_SEPARATOR) ) columnSeparator = csvnode.getString(CSVPreferences.P_CSV_COLUMN_SEPARATOR);\r
+ }\r
+ \r
+ // 2. Write default values\r
+ try {\r
+ RecordAccessor ra = Accessors.getAccessor(options);\r
+ ra.setValue(P_CSV_COLUMN_SEPARATOR, Bindings.STRING, columnSeparator);\r
+ ra.setValue(P_CSV_DECIMAL_SEPARATOR, Bindings.STRING, decimalSeparator);\r
+ ra.setValue(P_CSV_TIME_STEP, Bindings.DOUBLE, timeStep);\r
+ \r
+ } catch (AccessorConstructionException e) {\r
+ throw new ExportException(e);\r
+ } catch (AccessorException e) {\r
+ throw new ExportException(e);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void savePref(Variant options, Preferences contentScopeNode, Preferences workbenchScopeNode) throws ExportException {\r
+ try {\r
+ RecordAccessor ra = Accessors.getAccessor(options);\r
+ \r
+ String columnSeparator = (String) ra.getValue( P_CSV_COLUMN_SEPARATOR, Bindings.STRING );\r
+ if ( columnSeparator != null ) workbenchScopeNode.put(CSVPreferences.P_CSV_COLUMN_SEPARATOR, columnSeparator); \r
+ \r
+ String decimalSeparator = (String) ra.getValue(P_CSV_DECIMAL_SEPARATOR, Bindings.STRING );\r
+ if ( decimalSeparator != null ) workbenchScopeNode.put(CSVPreferences.P_CSV_DECIMAL_SEPARATOR, decimalSeparator); \r
+ \r
+ Double timeStep = (Double) ra.getValue(P_CSV_TIME_STEP, Bindings.DOUBLE );\r
+ if ( timeStep != null ) contentScopeNode.putDouble(CSVPreferences.P_CSV_TIME_STEP, timeStep); \r
+\r
+ } catch (AccessorConstructionException e) {\r
+ throw new ExportException(e);\r
+ } catch (AccessorException e) {\r
+ throw new ExportException(e);\r
+ } \r
+ }\r
+\r
+ @Override\r
+ public void loadPref(Variant options, Preferences contentScopeNode, Preferences workbenchScopeNode) throws ExportException {\r
+ try {\r
+ RecordAccessor ra = Accessors.getAccessor(options);\r
+ \r
+ String columnSeparator = workbenchScopeNode.get(CSVPreferences.P_CSV_COLUMN_SEPARATOR, null);\r
+ if ( columnSeparator != null ) ra.setValue(P_CSV_COLUMN_SEPARATOR, Bindings.STRING, columnSeparator ); \r
+ \r
+ String decimalSeparator = workbenchScopeNode.get(CSVPreferences.P_CSV_DECIMAL_SEPARATOR, null);\r
+ if ( decimalSeparator != null ) ra.setValue(P_CSV_DECIMAL_SEPARATOR, Bindings.STRING, decimalSeparator );\r
+ \r
+ Double timeStep = contentScopeNode.getDouble(CSVPreferences.P_CSV_TIME_STEP, 0);\r
+ if ( timeStep != null ) ra.setValue(P_CSV_TIME_STEP, Bindings.DOUBLE, timeStep ); \r
+\r
+ } catch (AccessorConstructionException e) {\r
+ throw new ExportException(e);\r
+ } catch (AccessorException e) {\r
+ throw new ExportException(e);\r
+ } \r
+ }\r
+ \r
+ @Override\r
+ public Object createFile(ExportContext context, File outputFile, Variant options) throws ExportException {\r
+ CSVWriter writer = new CSVWriter();\r
+ writer.file = outputFile;\r
+\r
+ try {\r
+ /// Read configurations \r
+ RecordAccessor ra = Accessors.getAccessor(options);\r
+ \r
+ // Start, End time\r
+ Double startTime = (Double) ra.getValue( ExperimentExportClass.P_EXPERIMENT_START, Bindings.DOUBLE );\r
+ Double endTime = (Double) ra.getValue( ExperimentExportClass.P_EXPERIMENT_END, Bindings.DOUBLE );\r
+ writer.setTimeRange(startTime, endTime);\r
+ \r
+ // Separators\r
+ String columnSeparator = (String) ra.getValue( CSVFormat.P_CSV_COLUMN_SEPARATOR, Bindings.STRING );\r
+ writer.setColumnSeparator(ColumnSeparator.fromPreference(columnSeparator));\r
+ \r
+ String decimalSeparator = (String) ra.getValue( CSVFormat.P_CSV_DECIMAL_SEPARATOR, Bindings.STRING );\r
+ writer.setDecimalSeparator(DecimalSeparator.fromPreference(decimalSeparator));\r
+ \r
+ Double timeStep = (Double) ra.getValue( CSVFormat.P_CSV_TIME_STEP, Bindings.DOUBLE );\r
+ writer.setTimeStep(timeStep);\r
+ \r
+ } catch (AccessorConstructionException e) {\r
+ throw new ExportException(e);\r
+ } catch (AccessorException e) {\r
+ throw new ExportException(e);\r
+ } \r
+ \r
+ return writer;\r
+ }\r
+\r
+ @Override\r
+ public Object openFile(ExportContext context, File inputFile, Variant options) throws ExportException {\r
+ throw new ExportException("Not implemented");\r
+ }\r
+\r
+ @Override\r
+ public void closeFile(ExportContext context, Object handle_) throws ExportException {\r
+ CSVWriter handle = (CSVWriter) handle_;\r
+ try {\r
+ handle.write();\r
+ } catch (IOException e) {\r
+ throw new ExportException(e);\r
+ } catch (HistoryException e) {\r
+ throw new ExportException(e);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void addAttachment(ExportContext context, Object handle, List<Content> attachments) throws ExportException {\r
+ throw new ExportException( "Cannot add attachments to a CSV file." );\r
+ }\r
+\r
+}\r