]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.charts/src/org/simantics/charts/ui/CSVExporter.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.charts / src / org / simantics / charts / ui / CSVExporter.java
diff --git a/bundles/org.simantics.charts/src/org/simantics/charts/ui/CSVExporter.java b/bundles/org.simantics.charts/src/org/simantics/charts/ui/CSVExporter.java
new file mode 100644 (file)
index 0000000..91c8b20
--- /dev/null
@@ -0,0 +1,218 @@
+/*******************************************************************************\r
+ * Copyright (c) 2012 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.charts.ui;\r
+\r
+import java.io.BufferedOutputStream;\r
+import java.io.File;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.PrintStream;\r
+import java.io.RandomAccessFile;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import org.eclipse.core.commands.ExecutionException;\r
+import org.eclipse.core.runtime.IProgressMonitor;\r
+import org.eclipse.core.runtime.IStatus;\r
+import org.eclipse.core.runtime.Status;\r
+import org.eclipse.core.runtime.SubMonitor;\r
+import org.eclipse.core.runtime.preferences.IScopeContext;\r
+import org.eclipse.core.runtime.preferences.InstanceScope;\r
+import org.eclipse.jface.operation.IRunnableWithProgress;\r
+import org.osgi.service.prefs.BackingStoreException;\r
+import org.osgi.service.prefs.Preferences;\r
+import org.simantics.Simantics;\r
+import org.simantics.charts.Activator;\r
+import org.simantics.charts.editor.ChartData;\r
+import org.simantics.charts.editor.ChartKeys;\r
+import org.simantics.databoard.binding.error.BindingException;\r
+import org.simantics.databoard.serialization.SerializationException;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.common.NamedResource;\r
+import org.simantics.db.common.request.UniqueRead;\r
+import org.simantics.db.common.utils.Logger;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.request.PossibleModel;\r
+import org.simantics.history.HistoryException;\r
+import org.simantics.history.csv.CSVFormatter;\r
+import org.simantics.modeling.preferences.CSVPreferences;\r
+import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
+import org.simantics.utils.format.FormattingUtils;\r
+import org.simantics.utils.ui.dialogs.ShowMessage;\r
+\r
+/**\r
+ * @author Antti Villberg\r
+ */\r
+public class CSVExporter implements IRunnableWithProgress {\r
+\r
+    CSVExportPlan exportModel;\r
+\r
+    public CSVExporter(CSVExportPlan exportModel) {\r
+        this.exportModel = exportModel;\r
+    }\r
+\r
+    @Override\r
+    public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {\r
+        SubMonitor progress = SubMonitor.convert(monitor, 50);\r
+        try {\r
+            exportModel(progress.newChild(50, SubMonitor.SUPPRESS_NONE));\r
+        } catch (IOException e) {\r
+            throw new InvocationTargetException(e);\r
+        } catch (DatabaseException e) {\r
+            throw new InvocationTargetException(e);\r
+        } catch (BindingException e) {\r
+            throw new InvocationTargetException(e);\r
+        } finally {\r
+            monitor.done();\r
+        }\r
+    }\r
+\r
+    void exportModel(SubMonitor mon) throws IOException, DatabaseException, SerializationException, BindingException{\r
+       \r
+        try {\r
+            doExport(mon, exportModel.exportLocation, exportModel);\r
+        } catch (ExecutionException e) {\r
+            e.printStackTrace();\r
+            Logger.defaultLogError(e);\r
+            mon.setCanceled(true);\r
+            ShowMessage.showError("Export failed.", "Internal application error in export. See log for details.");\r
+        } finally {\r
+            mon.setWorkRemaining(0);\r
+        }\r
+        \r
+    }\r
+    \r
+    private static Set<Resource> resolveContainingModels(final Collection<NamedResource> res) throws DatabaseException {\r
+        return Simantics.getSession().syncRequest(new UniqueRead<Set<Resource>>() {\r
+            @Override\r
+            public Set<Resource> perform(ReadGraph graph) throws DatabaseException {\r
+                Set<Resource> models = new HashSet<Resource>();\r
+                for (NamedResource r : res) {\r
+                    Resource m = graph.syncRequest(new PossibleModel(r.getResource()));\r
+                    if (m != null)\r
+                        models.add(m);\r
+                }\r
+                return models;\r
+            }\r
+        });\r
+    }\r
+    \r
+    public static void doExport(IProgressMonitor monitor, final File f, final CSVExportPlan plan) throws ExecutionException, IOException {\r
+       \r
+        IScopeContext context = InstanceScope.INSTANCE;\r
+        Preferences node = context.getNode(CSVPreferences.P_NODE);\r
+\r
+        node.putDouble(CSVPreferences.P_CSV_START_TIME, plan.startTime);\r
+        node.putDouble(CSVPreferences.P_CSV_TIME_STEP, plan.timeStep);\r
+        node.put(CSVPreferences.P_CSV_DECIMAL_SEPARATOR, plan.decimalSeparator.toPreference());\r
+        node.put(CSVPreferences.P_CSV_COLUMN_SEPARATOR, plan.columnSeparator.toPreference());\r
+        \r
+        node.putBoolean(CSVPreferences.P_CSV_RESAMPLE, plan.resample);\r
+        node.put(CSVPreferences.P_CSV_SAMPLING_MODE, plan.samplingMode.toPreference());\r
+        \r
+        node.putInt(CSVPreferences.P_CSV_TIME_DIGITS, plan.timeDigits);\r
+        node.putInt(CSVPreferences.P_CSV_FLOAT_DIGITS, plan.floatDigits);\r
+        node.putInt(CSVPreferences.P_CSV_DOUBLE_DIGITS, plan.doubleDigits);\r
+\r
+        try {\r
+            node.flush();\r
+        } catch (BackingStoreException ex) {\r
+            Activator.getDefault().getLog().log(\r
+                    new Status(IStatus.WARNING, Activator.PLUGIN_ID, "Could not store preferences for node " + node.absolutePath()));\r
+        }\r
+\r
+        Set<Resource> models;\r
+        try {\r
+            models = resolveContainingModels(plan.models);\r
+        } catch (DatabaseException e3) {\r
+            throw new ExecutionException("Containing model resolution failed.", e3);\r
+        }\r
+        if (models.isEmpty())\r
+            throw new ExecutionException("Selected resources are not part of any model");\r
+        if (models.size() > 1)\r
+            throw new ExecutionException("Selected resources are part of several models, only subscriptions from a single model can be selected");\r
+        Resource model = models.iterator().next();\r
+        Key chartDataKey = ChartKeys.chartSourceKey(model);\r
+        \r
+        final ChartData data = Simantics.getProject().getHint(chartDataKey);\r
+        if ( data == null ) {\r
+            throw new ExecutionException("There is no "+chartDataKey);\r
+        }\r
+        if ( data.history == null ) {\r
+            throw new ExecutionException("There is no history in "+chartDataKey);\r
+        }\r
+\r
+        final CSVFormatter csv = new CSVFormatter();\r
+\r
+        csv.setStartTime( plan.startTime );\r
+        csv.setTimeStep( plan.timeStep );\r
+        csv.setDecimalSeparator( plan.decimalSeparator );\r
+        csv.setColumnSeparator( plan.columnSeparator  );\r
+        csv.setResample( plan.resample );\r
+        csv.setNumberInterpolation( plan.samplingMode );\r
+        csv.setTimeFormat( FormattingUtils.significantDigitFormat( plan.timeDigits ) );\r
+        csv.setFloatFormat( FormattingUtils.significantDigitFormat( plan.floatDigits ) );\r
+        csv.setNumberFormat( FormattingUtils.significantDigitFormat( plan.doubleDigits ) );\r
+\r
+               try {\r
+                       Session session = Simantics.getSession();\r
+                       List<Resource> list = new ArrayList<Resource>();\r
+                       for(NamedResource nr : plan.models) list.add(nr.getResource());\r
+                       session.sync( new CSVParamsQuery(data.history, csv, list) );\r
+                       csv.sort();\r
+               } catch (DatabaseException e2) {\r
+                       throw new ExecutionException(e2.getMessage(), e2);\r
+               } catch (HistoryException e) {\r
+                       throw new ExecutionException(e.getMessage(), e);\r
+               }\r
+        \r
+                try {\r
+             // Ensure all views are built.\r
+             monitor.beginTask("Exporting Time Series as CSV...", IProgressMonitor.UNKNOWN);\r
+             try {\r
+                 data.collector.flush();\r
+               if ( !f.exists() ) {\r
+                       f.createNewFile();\r
+               } else {\r
+                       RandomAccessFile raf = new RandomAccessFile(f, "rw");\r
+                       raf.setLength(0);\r
+                       raf.close();\r
+               }\r
+               \r
+               FileOutputStream fos = new FileOutputStream(f, true);\r
+               BufferedOutputStream bos = new BufferedOutputStream( fos );\r
+               try {\r
+                       PrintStream ps = new PrintStream( bos );\r
+                       csv.formulate2( new CSVProgressMonitor( monitor ), ps );\r
+                       bos.flush();\r
+                                       } finally {\r
+                       fos.close();\r
+               }\r
+               } catch (HistoryException e) {\r
+               throw new ExecutionException(e.getMessage(), e);\r
+             } catch (IOException e1) {\r
+               throw new ExecutionException(e1.getMessage(), e1);\r
+             }\r
+             monitor.setTaskName("Done");\r
+         } finally {\r
+             monitor.done();\r
+         }\r
+        \r
+    }\r
+    \r
+}\r