/******************************************************************************* * Copyright (c) 2007, 2011 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 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.issues.ui.handler; import java.io.File; import java.io.PrintStream; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.TreeMap; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.handlers.HandlerUtil; import org.osgi.service.prefs.BackingStoreException; import org.osgi.service.prefs.Preferences; import org.simantics.Simantics; import org.simantics.browsing.ui.common.ErrorLogger; import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.request.ObjectsWithType; import org.simantics.db.common.request.ReadRequest; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.request.Read; import org.simantics.issues.common.AllVisibleIssues; import org.simantics.issues.common.DynamicIssueSources; import org.simantics.issues.ui.internal.Activator; import org.simantics.operation.Layer0X; import org.simantics.simulation.ontology.SimulationResource; import org.simantics.utils.DataContainer; import org.simantics.utils.FileUtils; import org.simantics.utils.strings.StringUtils; import org.simantics.utils.ui.ExceptionUtils; /** * @author Tuukka Lehtonen */ public class ExportIssuesAsCsv extends AbstractHandler { private static final String PROP_LAST_VALIDATION_REPORT_PATH= "validation.report.path"; //$NON-NLS-1$ @Override public Object execute(ExecutionEvent event) throws ExecutionException { IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindow(event); try { String fileName = generateFileName(); validate(window, fileName); } catch (DatabaseException e) { ErrorLogger.defaultLogError(e); } return null; } private String generateFileName() throws DatabaseException { String generatedName = Simantics.getSession().syncRequest(new Read() { @Override public String perform(ReadGraph graph) throws DatabaseException { Layer0X L0X = Layer0X.getInstance(graph); SimulationResource SIMU = SimulationResource.getInstance(graph); for (Resource model : graph.syncRequest(new ObjectsWithType(Simantics.getProjectResource(), L0X.Activates, SIMU.Model))) { return NameUtils.getSafeName(graph, model) + ".txt"; //$NON-NLS-1$ } return "issues.txt"; //$NON-NLS-1$ } }); if (!FileUtils.isValidFileName(generatedName)) generatedName = (String) Bindings.STR_VARIANT.createUnchecked(Bindings.STRING, generatedName); return generatedName; } public void validate(IWorkbenchWindow window, String fileName) { Preferences prefs = InstanceScope.INSTANCE.getNode(Activator.PLUGIN_ID); String lastReportPath = prefs.get(PROP_LAST_VALIDATION_REPORT_PATH, null); // Query for output path Shell parentShell = null; if (window != null) parentShell = window.getShell(); final DataContainer externalOutput = new DataContainer(); FileDialog fd = new FileDialog(parentShell, SWT.SAVE); fd.setText(Messages.ExportIssuesAsCsv_SelectValidationOutput); fd.setFilterExtensions(new String[] { "*.txt", "*.*" }); //$NON-NLS-1$ //$NON-NLS-2$ fd.setFilterNames(new String[] { Messages.ExportIssuesAsCsv_CommaSeparatedValues, Messages.ExportIssuesAsCsv_AllFiles }); if (lastReportPath != null) fd.setFilterPath(lastReportPath); fd.setFileName(fileName); final String path = fd.open(); if (path != null) { prefs.put(PROP_LAST_VALIDATION_REPORT_PATH, path); try { prefs.flush(); } catch (BackingStoreException e) { ExceptionUtils.logError(e); } } else { return; } try { window.getWorkbench().getProgressService().busyCursorWhile(monitor -> { try (PrintStream out = new PrintStream(new File(path))) { export(monitor, out); } catch (Exception e) { throw new InvocationTargetException(e); } finally { monitor.done(); } }); } catch (InvocationTargetException e) { ExceptionUtils.logAndShowError(e.getTargetException()); } catch (InterruptedException e) { // Operation cancelled, ignore. } } private void export(IProgressMonitor monitor, PrintStream out) throws DatabaseException { SubMonitor progress = SubMonitor.convert(monitor, Messages.ExportIssuesAsCsv_ExportIssues, IProgressMonitor.UNKNOWN); Simantics.getSession().syncRequest(new ReadRequest() { @Override public void run(ReadGraph graph) throws DatabaseException { Collection activeIssues = graph.syncRequest(new AllVisibleIssues(Simantics.getProjectResource())); out.println("# Exported issues (" + activeIssues.size() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ for (Variable issue : activeIssues) { exportIssue(graph, issue, out, 0); progress.worked(1); } Map dynamicIssueSources = nameMap(graph, graph.syncRequest(new DynamicIssueSources(Simantics.getProjectResource()))); if (!dynamicIssueSources.isEmpty()) { out.println(); out.println("# Dynamic Issues"); //$NON-NLS-1$ for (Variable source : dynamicIssueSources.values()) { exportDynamicIssueSource(progress, graph, source, out, 0); } } } }); } private Map nameMap(ReadGraph graph, Set sources) throws DatabaseException { TreeMap sorted = new TreeMap<>(); for (Variable v : sources) { String name = v.getPossiblePropertyValue(graph, "HasDescription", Bindings.STRING); //$NON-NLS-1$ if (name == null) name = v.getName(graph); sorted.put(name, v); } return sorted; } protected void exportDynamicIssueSource(IProgressMonitor monitor, ReadGraph graph, Variable issue, PrintStream out, int startColumn) throws DatabaseException { exportIssue(graph, issue, out, startColumn); for (Variable child : issue.getChildren(graph)) { exportDynamicIssueSource(monitor, graph, child, out, startColumn+1); monitor.worked(1); } } private void exportIssue(ReadGraph graph, Variable issue, PrintStream out, int startColumn) throws DatabaseException { String description = StringUtils.safeString( (String) issue.getPossiblePropertyValue(graph, "HasDescription") ); //$NON-NLS-1$ String severity = StringUtils.safeString( (String) issue.getPossiblePropertyValue(graph, "severity") ); //$NON-NLS-1$ String resource = StringUtils.safeString( (String) issue.getPossiblePropertyValue(graph, "resource") ); //$NON-NLS-1$ String path = StringUtils.safeString( (String) issue.getPossiblePropertyValue(graph, "path") ); //$NON-NLS-1$ for (int i = 0; i < startColumn; ++i) out.print(";"); //$NON-NLS-1$ out.println(description + ";" + severity + ";" + resource + ";" + path); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } }