::value[createChartGroup]
+## Export subscription data as CSV
+
+::data[CSVExportPlan]
+
+::data[SubscriptionCSVExportPlan]
+
+::value[exportSubscriptionsCSV]
+
+::value[columnSeparatorFromString]
+
+::value[decimalSeparatorFromString ]
+
+::value[exportInterpolationFromString ]
+
# Undocumented entities
::undocumented[]
\ No newline at end of file
charts + concatMap recurse chartGrp
isChart r = isInstanceOf r CHART.TimeSeriesChart
isChartGroup r = isInstanceOf r CHART.ChartGroup
+
+//-----------------------------------------------------------------------------
+// Support for exporting subscription data in CSV format
+
+import "UI/Progress" as Progress
+import "File"
+
+importJava "org.simantics.history.csv.DecimalSeparator" where
+ data DecimalSeparator
+
+ @JavaName fromPreference
+ """
+ Possible arguments are:
+
+ Dot (.)
+ Comma (,)
+ """
+ decimalSeparatorFromString :: String -> <Proc> DecimalSeparator
+
+importJava "org.simantics.history.csv.ColumnSeparator" where
+ data ColumnSeparator
+
+ @JavaName fromPreference
+ """
+ Possible arguments are:
+
+ Comma (,)
+ Tabulator (\\t)
+ Semicolon (;)
+ Colon (:)
+ Space ( )
+ """
+ columnSeparatorFromString :: String -> <Proc> ColumnSeparator
+
+importJava "org.simantics.history.csv.ExportInterpolation" where
+ data ExportInterpolation
+
+ @JavaName fromPreference
+ """
+ Possible arguments are:
+
+ Linear Interpolation (lerp)
+ Previous Sample (previous)
+ """
+ exportInterpolationFromString :: String -> <Proc> ExportInterpolation
+
+importJava "org.simantics.charts.ui.CSVExportPlan" where
+ @FieldNames [startTime, timeStep, decimalSeparator, columnSeparator, resample, samplingMode, timeDigits, floatDigits, doubleDigits]
+
+ """
+ Example of construction:
+
+ plan = CSVExportPlan {
+ startTime = 0.0,
+ timeStep = 1.0,
+ decimalSeparator = decimalSeparatorFromString ".",
+ columnSeparator = columnSeparatorFromString ",",
+ resample = True,
+ samplingMode = exportInterpolationFromString "lerp",
+ timeDigits = 7,
+ floatDigits = 9,
+ doubleDigits = 15
+ }
+ """
+ data CSVExportPlan = CSVExportPlan {
+ startTime :: Double,
+ timeStep :: Double,
+ decimalSeparator :: DecimalSeparator,
+ columnSeparator :: ColumnSeparator,
+ resample :: Boolean,
+ samplingMode :: ExportInterpolation ,
+ timeDigits :: Integer,
+ floatDigits :: Integer,
+ doubleDigits :: Integer
+ }
+
+ @JavaName setItems
+ @private
+ setCSVExportPlanItems :: CSVExportPlan -> [Resource] -> <Proc> ()
+
+"""
+Example of construction:
+
+ plan = SubscriptionCSVExportPlan {
+ modelName = "Model",
+ filePath = "D:/folder/output.csv",
+ subscriptionNames = ["Default"],
+ exportPlan = CSVExportPlan {}
+ }
+"""
+data SubscriptionCSVExportPlan = SubscriptionCSVExportPlan {
+ modelName :: String,
+ subscriptionNames :: [String],
+ filePath :: String,
+ exportPlan :: CSVExportPlan
+}
+
+@private
+modelNameOf SubscriptionCSVExportPlan { modelName } = modelName
+@private
+subscriptionNamesOf SubscriptionCSVExportPlan { subscriptionNames } = subscriptionNames
+@private
+filePathOf SubscriptionCSVExportPlan { filePath } = filePath
+@private
+exportPlanOf SubscriptionCSVExportPlan { exportPlan } = exportPlan
+
+importJava "org.simantics.charts.ui.CSVExporter" where
+ @JavaName doExport
+ @private
+ exportSubscriptionsCSVInternal :: Progress.ProgressMonitor -> File -> CSVExportPlan -> <Proc> ()
+
+"""
+Exports subscription data as CSV values in a similar manner as the CSV Exporter provided by the user interface
+
+Example of usage:
+
+ exportSubscriptionsCSV SubscriptionCSVExportPlan {
+ modelName = "Model",
+ filePath = "D:/folder/output.csv",
+ subscriptionNames = ["Default"],
+ exportPlan = CSVExportPlan {
+ startTime = 0.0,
+ timeStep = 1.0,
+ decimalSeparator = decimalSeparatorFromString ".",
+ columnSeparator = columnSeparatorFromString ",",
+ resample = True,
+ samplingMode = exportInterpolationFromString "lerp",
+ timeDigits = 7,
+ floatDigits = 9,
+ doubleDigits = 15
+ }
+ }
+"""
+exportSubscriptionsCSV :: SubscriptionCSVExportPlan -> <Proc> ()
+exportSubscriptionsCSV subscriptionExportPlan = do
+ items = syncRead (\_ -> resolveSubscriptionItems (modelNameOf subscriptionExportPlan) (subscriptionNamesOf subscriptionExportPlan))
+ csvExportPlan = exportPlanOf subscriptionExportPlan
+ setCSVExportPlanItems csvExportPlan items
+ exportSubscriptionsCSVInternal (Progress.createNullProgressMonitor ()) (file (filePathOf subscriptionExportPlan)) csvExportPlan
+
+@private
+resolveSubscriptionItems :: String -> [String] -> <Proc, ReadGraph> [Resource]
+resolveSubscriptionItems modelName subscriptionNames = concatMap itemsOf (filter nameFilter subscriptions)
+ where
+ nameFilter sub = elem (relatedValue2 sub L0.HasLabel) subscriptionNames
+ subscriptions = (objectsWithType (model modelName) L0.ConsistsOf MOD.Subscription)
+ itemsOf subscription = objectsWithType subscription L0.ConsistsOf MOD.Subscription.Item
if(hasInitial) {
model.select(i);
item.removeAll();
- exportModel.models.clear();
+ exportModel.items.clear();
int index = 0;
int firstIndex = 0;
for(NamedResource nr : p.second) {
ti.setText(nr.getName());
ti.setData(nr);
if(selected.contains(nr)) {
- exportModel.models.add(nr);
+ exportModel.items.add(nr.getResource());
ti.setChecked(true);
if(firstIndex == 0) firstIndex = index;
}
Pair<NamedResource,List<NamedResource>> p = getModel(selectedModel);
if(p != null) {
- HashSet<NamedResource> checked = new HashSet<>();
+ Set<Resource> checked = new HashSet<>();
NamedResource existing = (NamedResource)item.getData();
if(!p.first.equals(existing)) {
}
for(TableItem ti : item.getItems()) {
- if(ti.getChecked()) checked.add((NamedResource)ti.getData());
+ if(ti.getChecked()) checked.add(((NamedResource)ti.getData()).getResource());
}
- exportModel.models = checked;
+ exportModel.items = checked;
}
} else {
- if(exportModel.models.size() > 1) {
+ if(exportModel.items.size() > 1) {
setErrorMessage("Recorded samples can only be exported for a single subscription item.");
setPageComplete(false);
return;
return;
}
- if (exportModel.models.isEmpty()) {
+ if (exportModel.items.isEmpty()) {
setErrorMessage("No items selected for export.");
setPageComplete(false);
return;
package org.simantics.charts.ui;
import java.io.File;
+import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;
import java.util.HashSet;
+import java.util.List;
-import org.simantics.db.common.NamedResource;
+import org.simantics.Simantics;
+import org.simantics.db.Resource;
import org.simantics.db.management.ISessionContext;
import org.simantics.history.csv.ColumnSeparator;
import org.simantics.history.csv.DecimalSeparator;
Deque<String> recentLocations;
// Output
- Collection<NamedResource> models = new HashSet<NamedResource>();
- File exportLocation;
+ Collection<Resource> items = new HashSet<>();
+ File exportLocation;
- double startTime;
- double timeStep;
- DecimalSeparator decimalSeparator;
- ColumnSeparator columnSeparator;
- boolean resample;
- ExportInterpolation samplingMode;
- int timeDigits;
- int floatDigits;
- int doubleDigits;
+ public double startTime;
+ public double timeStep;
+ public DecimalSeparator decimalSeparator;
+ public ColumnSeparator columnSeparator;
+ public boolean resample;
+ public ExportInterpolation samplingMode;
+ public int timeDigits;
+ public int floatDigits;
+ public int doubleDigits;
/**
*/
boolean overwrite;
+ /**
+ * Constructor for SCL support
+ */
+ public CSVExportPlan(double startTime, double timeStep, DecimalSeparator dsep, ColumnSeparator csep, boolean resample, ExportInterpolation mode, int timeDigits, int floatDigits, int doubleDigits) {
+ this.sessionContext = Simantics.getSessionContext();
+ this.recentLocations = new ArrayDeque<>();
+
+ this.startTime = startTime;
+ this.timeStep = timeStep;
+ this.decimalSeparator = dsep;
+ this.columnSeparator = csep;
+ this.resample = resample;
+ this.samplingMode = mode;
+ this.timeDigits = timeDigits;
+ this.floatDigits = floatDigits;
+ this.doubleDigits = doubleDigits;
+ }
+
+ public void setItems(List<Resource> items) {
+ this.items = items;
+ }
+
CSVExportPlan(ISessionContext sessionContext, Deque<String> recentLocations) {
this.sessionContext = sessionContext;
this.recentLocations = recentLocations;
/*******************************************************************************
- * Copyright (c) 2012 Association for Decentralized Information Management in
+ * Copyright (c) 2012,2017 Association for Decentralized Information Management in
* Industry THTH ry.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
import org.eclipse.core.commands.ExecutionException;
import org.simantics.databoard.serialization.SerializationException;
import org.simantics.db.ReadGraph;
import org.simantics.db.Resource;
-import org.simantics.db.Session;
-import org.simantics.db.common.NamedResource;
import org.simantics.db.common.request.UniqueRead;
import org.simantics.db.common.utils.Logger;
import org.simantics.db.exception.DatabaseException;
}
void exportModel(SubMonitor mon) throws IOException, DatabaseException, SerializationException, BindingException{
-
try {
doExport(mon, exportModel.exportLocation, exportModel);
} catch (ExecutionException e) {
} finally {
mon.setWorkRemaining(0);
}
-
}
-
- private static Set<Resource> resolveContainingModels(final Collection<NamedResource> res) throws DatabaseException {
+
+ private static Set<Resource> resolveContainingModels(Collection<Resource> res) throws DatabaseException {
return Simantics.getSession().syncRequest(new UniqueRead<Set<Resource>>() {
@Override
public Set<Resource> perform(ReadGraph graph) throws DatabaseException {
- Set<Resource> models = new HashSet<Resource>();
- for (NamedResource r : res) {
- Resource m = graph.syncRequest(new PossibleModel(r.getResource()));
+ Set<Resource> models = new HashSet<>();
+ for (Resource r : res) {
+ Resource m = graph.syncRequest(new PossibleModel(r));
if (m != null)
models.add(m);
}
}
});
}
-
+
public static void doExport(IProgressMonitor monitor, final File f, final CSVExportPlan plan) throws ExecutionException, IOException {
-
IScopeContext context = InstanceScope.INSTANCE;
Preferences node = context.getNode(CSVPreferences.P_NODE);
Set<Resource> models;
try {
- models = resolveContainingModels(plan.models);
+ models = resolveContainingModels(plan.items);
} catch (DatabaseException e3) {
throw new ExecutionException("Containing model resolution failed.", e3);
}
throw new ExecutionException("Selected resources are part of several models, only subscriptions from a single model can be selected");
Resource model = models.iterator().next();
Key chartDataKey = ChartKeys.chartSourceKey(model);
-
+
final ChartData data = Simantics.getProject().getHint(chartDataKey);
if ( data == null ) {
throw new ExecutionException("There is no "+chartDataKey);
csv.setFloatFormat( FormattingUtils.significantDigitFormat( plan.floatDigits ) );
csv.setNumberFormat( FormattingUtils.significantDigitFormat( plan.doubleDigits ) );
- try {
- Session session = Simantics.getSession();
- List<Resource> list = new ArrayList<Resource>();
- for(NamedResource nr : plan.models) list.add(nr.getResource());
- session.sync( new CSVParamsQuery(data.history, csv, list) );
- csv.sort();
- } catch (DatabaseException e2) {
- throw new ExecutionException(e2.getMessage(), e2);
- } catch (HistoryException e) {
- throw new ExecutionException(e.getMessage(), e);
- }
-
- try {
- // Ensure all views are built.
- monitor.beginTask("Exporting Time Series as CSV...", IProgressMonitor.UNKNOWN);
- try {
- data.collector.flush();
- if ( !f.exists() ) {
- f.createNewFile();
- } else {
- RandomAccessFile raf = new RandomAccessFile(f, "rw");
- raf.setLength(0);
- raf.close();
- }
-
- FileOutputStream fos = new FileOutputStream(f, true);
- BufferedOutputStream bos = new BufferedOutputStream( fos );
- try {
- PrintStream ps = new PrintStream( bos );
- csv.formulate2( new CSVProgressMonitor( monitor ), ps );
- bos.flush();
- } finally {
- fos.close();
- }
- } catch (HistoryException e) {
- throw new ExecutionException(e.getMessage(), e);
- } catch (IOException e1) {
- throw new ExecutionException(e1.getMessage(), e1);
- }
- monitor.setTaskName("Done");
- } finally {
- monitor.done();
- }
-
+ try {
+ Simantics.getSession().syncRequest(
+ new CSVParamsQuery(data.history, csv,
+ new ArrayList<>(plan.items)) );
+ csv.sort();
+
+ // Ensure all views are built.
+ monitor.beginTask("Exporting Time Series as CSV...", IProgressMonitor.UNKNOWN);
+ data.collector.flush();
+
+ // Truncate existing file it if happens to exist.
+ try (RandomAccessFile raf = new RandomAccessFile(f, "rw")) {
+ raf.setLength(0);
+ }
+
+ // Write CSV
+ try (PrintStream ps = new PrintStream(
+ new BufferedOutputStream(
+ new FileOutputStream(f, true) )))
+ {
+ csv.formulate2( new CSVProgressMonitor( monitor ), ps );
+ ps.flush();
+ }
+
+ monitor.setTaskName("Done");
+ } catch (DatabaseException e2) {
+ throw new ExecutionException(e2.getMessage(), e2);
+ } catch (HistoryException e) {
+ throw new ExecutionException(e.getMessage(), e);
+ } finally {
+ monitor.done();
+ }
}
-
+
}