]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 /*******************************************************************************\r
2  * Copyright (c) 2012 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.charts.ui;\r
13 \r
14 import java.io.BufferedOutputStream;\r
15 import java.io.File;\r
16 import java.io.FileOutputStream;\r
17 import java.io.IOException;\r
18 import java.io.PrintStream;\r
19 import java.io.RandomAccessFile;\r
20 import java.lang.reflect.InvocationTargetException;\r
21 import java.util.ArrayList;\r
22 import java.util.Collection;\r
23 import java.util.HashSet;\r
24 import java.util.List;\r
25 import java.util.Set;\r
26 \r
27 import org.eclipse.core.commands.ExecutionException;\r
28 import org.eclipse.core.runtime.IProgressMonitor;\r
29 import org.eclipse.core.runtime.IStatus;\r
30 import org.eclipse.core.runtime.Status;\r
31 import org.eclipse.core.runtime.SubMonitor;\r
32 import org.eclipse.core.runtime.preferences.IScopeContext;\r
33 import org.eclipse.core.runtime.preferences.InstanceScope;\r
34 import org.eclipse.jface.operation.IRunnableWithProgress;\r
35 import org.osgi.service.prefs.BackingStoreException;\r
36 import org.osgi.service.prefs.Preferences;\r
37 import org.simantics.Simantics;\r
38 import org.simantics.charts.Activator;\r
39 import org.simantics.charts.editor.ChartData;\r
40 import org.simantics.charts.editor.ChartKeys;\r
41 import org.simantics.databoard.binding.error.BindingException;\r
42 import org.simantics.databoard.serialization.SerializationException;\r
43 import org.simantics.db.ReadGraph;\r
44 import org.simantics.db.Resource;\r
45 import org.simantics.db.Session;\r
46 import org.simantics.db.common.NamedResource;\r
47 import org.simantics.db.common.request.UniqueRead;\r
48 import org.simantics.db.common.utils.Logger;\r
49 import org.simantics.db.exception.DatabaseException;\r
50 import org.simantics.db.layer0.request.PossibleModel;\r
51 import org.simantics.history.HistoryException;\r
52 import org.simantics.history.csv.CSVFormatter;\r
53 import org.simantics.modeling.preferences.CSVPreferences;\r
54 import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
55 import org.simantics.utils.format.FormattingUtils;\r
56 import org.simantics.utils.ui.dialogs.ShowMessage;\r
57 \r
58 /**\r
59  * @author Antti Villberg\r
60  */\r
61 public class CSVExporter implements IRunnableWithProgress {\r
62 \r
63     CSVExportPlan exportModel;\r
64 \r
65     public CSVExporter(CSVExportPlan exportModel) {\r
66         this.exportModel = exportModel;\r
67     }\r
68 \r
69     @Override\r
70     public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {\r
71         SubMonitor progress = SubMonitor.convert(monitor, 50);\r
72         try {\r
73             exportModel(progress.newChild(50, SubMonitor.SUPPRESS_NONE));\r
74         } catch (IOException e) {\r
75             throw new InvocationTargetException(e);\r
76         } catch (DatabaseException e) {\r
77             throw new InvocationTargetException(e);\r
78         } catch (BindingException e) {\r
79             throw new InvocationTargetException(e);\r
80         } finally {\r
81             monitor.done();\r
82         }\r
83     }\r
84 \r
85     void exportModel(SubMonitor mon) throws IOException, DatabaseException, SerializationException, BindingException{\r
86         \r
87         try {\r
88             doExport(mon, exportModel.exportLocation, exportModel);\r
89         } catch (ExecutionException e) {\r
90             e.printStackTrace();\r
91             Logger.defaultLogError(e);\r
92             mon.setCanceled(true);\r
93             ShowMessage.showError("Export failed.", "Internal application error in export. See log for details.");\r
94         } finally {\r
95             mon.setWorkRemaining(0);\r
96         }\r
97         \r
98     }\r
99     \r
100     private static Set<Resource> resolveContainingModels(final Collection<NamedResource> res) throws DatabaseException {\r
101         return Simantics.getSession().syncRequest(new UniqueRead<Set<Resource>>() {\r
102             @Override\r
103             public Set<Resource> perform(ReadGraph graph) throws DatabaseException {\r
104                 Set<Resource> models = new HashSet<Resource>();\r
105                 for (NamedResource r : res) {\r
106                     Resource m = graph.syncRequest(new PossibleModel(r.getResource()));\r
107                     if (m != null)\r
108                         models.add(m);\r
109                 }\r
110                 return models;\r
111             }\r
112         });\r
113     }\r
114     \r
115     public static void doExport(IProgressMonitor monitor, final File f, final CSVExportPlan plan) throws ExecutionException, IOException {\r
116         \r
117         IScopeContext context = InstanceScope.INSTANCE;\r
118         Preferences node = context.getNode(CSVPreferences.P_NODE);\r
119 \r
120         node.putDouble(CSVPreferences.P_CSV_START_TIME, plan.startTime);\r
121         node.putDouble(CSVPreferences.P_CSV_TIME_STEP, plan.timeStep);\r
122         node.put(CSVPreferences.P_CSV_DECIMAL_SEPARATOR, plan.decimalSeparator.toPreference());\r
123         node.put(CSVPreferences.P_CSV_COLUMN_SEPARATOR, plan.columnSeparator.toPreference());\r
124         \r
125         node.putBoolean(CSVPreferences.P_CSV_RESAMPLE, plan.resample);\r
126         node.put(CSVPreferences.P_CSV_SAMPLING_MODE, plan.samplingMode.toPreference());\r
127         \r
128         node.putInt(CSVPreferences.P_CSV_TIME_DIGITS, plan.timeDigits);\r
129         node.putInt(CSVPreferences.P_CSV_FLOAT_DIGITS, plan.floatDigits);\r
130         node.putInt(CSVPreferences.P_CSV_DOUBLE_DIGITS, plan.doubleDigits);\r
131 \r
132         try {\r
133             node.flush();\r
134         } catch (BackingStoreException ex) {\r
135             Activator.getDefault().getLog().log(\r
136                     new Status(IStatus.WARNING, Activator.PLUGIN_ID, "Could not store preferences for node " + node.absolutePath()));\r
137         }\r
138 \r
139         Set<Resource> models;\r
140         try {\r
141             models = resolveContainingModels(plan.models);\r
142         } catch (DatabaseException e3) {\r
143             throw new ExecutionException("Containing model resolution failed.", e3);\r
144         }\r
145         if (models.isEmpty())\r
146             throw new ExecutionException("Selected resources are not part of any model");\r
147         if (models.size() > 1)\r
148             throw new ExecutionException("Selected resources are part of several models, only subscriptions from a single model can be selected");\r
149         Resource model = models.iterator().next();\r
150         Key chartDataKey = ChartKeys.chartSourceKey(model);\r
151         \r
152         final ChartData data = Simantics.getProject().getHint(chartDataKey);\r
153         if ( data == null ) {\r
154             throw new ExecutionException("There is no "+chartDataKey);\r
155         }\r
156         if ( data.history == null ) {\r
157             throw new ExecutionException("There is no history in "+chartDataKey);\r
158         }\r
159 \r
160         final CSVFormatter csv = new CSVFormatter();\r
161 \r
162         csv.setStartTime( plan.startTime );\r
163         csv.setTimeStep( plan.timeStep );\r
164         csv.setDecimalSeparator( plan.decimalSeparator );\r
165         csv.setColumnSeparator( plan.columnSeparator  );\r
166         csv.setResample( plan.resample );\r
167         csv.setNumberInterpolation( plan.samplingMode );\r
168         csv.setTimeFormat( FormattingUtils.significantDigitFormat( plan.timeDigits ) );\r
169         csv.setFloatFormat( FormattingUtils.significantDigitFormat( plan.floatDigits ) );\r
170         csv.setNumberFormat( FormattingUtils.significantDigitFormat( plan.doubleDigits ) );\r
171 \r
172                 try {\r
173                         Session session = Simantics.getSession();\r
174                         List<Resource> list = new ArrayList<Resource>();\r
175                         for(NamedResource nr : plan.models) list.add(nr.getResource());\r
176                         session.sync( new CSVParamsQuery(data.history, csv, list) );\r
177                         csv.sort();\r
178                 } catch (DatabaseException e2) {\r
179                         throw new ExecutionException(e2.getMessage(), e2);\r
180                 } catch (HistoryException e) {\r
181                         throw new ExecutionException(e.getMessage(), e);\r
182                 }\r
183         \r
184                  try {\r
185              // Ensure all views are built.\r
186              monitor.beginTask("Exporting Time Series as CSV...", IProgressMonitor.UNKNOWN);\r
187              try {\r
188                  data.collector.flush();\r
189                 if ( !f.exists() ) {\r
190                         f.createNewFile();\r
191                 } else {\r
192                         RandomAccessFile raf = new RandomAccessFile(f, "rw");\r
193                         raf.setLength(0);\r
194                         raf.close();\r
195                 }\r
196                 \r
197                 FileOutputStream fos = new FileOutputStream(f, true);\r
198                 BufferedOutputStream bos = new BufferedOutputStream( fos );\r
199                 try {\r
200                         PrintStream ps = new PrintStream( bos );\r
201                         csv.formulate2( new CSVProgressMonitor( monitor ), ps );\r
202                         bos.flush();\r
203                                         } finally {\r
204                         fos.close();\r
205                 }\r
206                 } catch (HistoryException e) {\r
207                 throw new ExecutionException(e.getMessage(), e);\r
208              } catch (IOException e1) {\r
209                 throw new ExecutionException(e1.getMessage(), e1);\r
210              }\r
211              monitor.setTaskName("Done");\r
212          } finally {\r
213              monitor.done();\r
214          }\r
215         \r
216     }\r
217     \r
218 }\r