/******************************************************************************* * Copyright (c) 2012-2015 INRIA. * 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: * Youenn Corre - initial API and implementation ******************************************************************************/ package fr.inria.soctrace.framesoc.ui.eventtable.view; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.widgets.Display; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import fr.inria.soctrace.framesoc.core.FramesocConstants; import fr.inria.soctrace.framesoc.ui.eventtable.model.EventTableColumn; import fr.inria.soctrace.framesoc.ui.eventtable.model.EventTableRow; import fr.inria.soctrace.lib.model.utils.SoCTraceException; /** * This class implements the generation of a CSV file from the currently * displayed events in the table event view * * Event custom parameters are added on the fly at the end of the CSV header. * Custom parameters with the same name are added into the same column * * @author "Youenn Corre <youenn.corre@inria.fr>" */ public class CSVExport { /** * Logger */ private final static Logger logger = LoggerFactory.getLogger(CSVExport.class); private final Object exportSyncObj = new Object(); private StringBuilder csvExport = new StringBuilder(); private StringBuilder csvHeader = new StringBuilder(); private Map<EventTableColumn, Boolean> exportColumn = new HashMap<EventTableColumn, Boolean>(); private int currentMaxNumberOfParameter = 0; private Map<String, Integer> parameterTypes = new HashMap<String, Integer>(); private String filePath; private boolean stop = false; private int monitorCheck = 20000; private EventTableCache cache; public CSVExport(String filePath, Map<EventTableColumn, Boolean> exportColumn, EventTableCache cache) { this.filePath = filePath; this.exportColumn = exportColumn; this.cache = cache; } /** * Export the events currently displayed in the table to csv format * * @param filePath * name of the file in which the csv export will be written * @throws SoCTraceException */ public void exportToCSV() { final String title = "Exporting to CSV"; final Job job = new Job(title) { @Override protected IStatus run(final IProgressMonitor monitor) { PrintWriter writer = null; int countEvents = 0; boolean exportParameters = exportColumn .get(EventTableColumn.PARAMS); monitor.beginTask(title, cache.getIndexedRowCount() / monitorCheck + 1); // Get columns selected for export in the same order that // they are displayed List<EventTableColumn> selectedColumns = new ArrayList<EventTableColumn>(); for (EventTableColumn column : EventTableColumn.values()) // Ignore Param column as it is a special case if (exportColumn.get(column) && (column != EventTableColumn.PARAMS)) selectedColumns.add(column); try { writer = new PrintWriter(filePath, System.getProperty("file.encoding")); for (EventTableColumn column : selectedColumns) { csvHeader.append(column.toString() + FramesocConstants.CSV_SEPARATOR); } // Delete last CSV_SEPARATOR if (!exportParameters) csvHeader.delete(csvHeader.length() - FramesocConstants.CSV_SEPARATOR.length(), csvHeader.length()); String newLine = System.getProperty("line.separator"); for (int i = 0; i < cache.getIndexedRowCount(); i++) { EventTableRow currentRow = cache.get(i); for (EventTableColumn column : selectedColumns) { csvExport.append(currentRow.get(column) + FramesocConstants.CSV_SEPARATOR); } if (exportParameters) handleParameters(currentRow); else { // remove last CSV_SEPARATOR if (!selectedColumns.isEmpty()) csvExport .delete(csvExport.length() - FramesocConstants.CSV_SEPARATOR .length(), csvExport.length()); } // New line csvExport.append(newLine); countEvents++; if (countEvents % monitorCheck == 0) { monitor.worked(1); if (monitor.isCanceled() || stop) { writer.flush(); writer.close(); return Status.CANCEL_STATUS; } } } csvHeader.append(newLine); // Write data into the file writer.write(csvHeader.toString()); writer.write(csvExport.toString()); monitor.worked(1); monitor.done(); return Status.OK_STATUS; } catch (FileNotFoundException e) { MessageDialog.openError(Display.getDefault() .getActiveShell(), "Exception", "File " + filePath + " could not be created (" + e.getMessage() + ")"); } catch (UnsupportedEncodingException e) { MessageDialog.openError( Display.getDefault().getActiveShell(), "Exception", "Unsupported encoding " + System.getProperty("file.encoding") + " (" + e.getMessage() + ")"); } catch (SoCTraceException e) { MessageDialog.openError(Display.getDefault() .getActiveShell(), "Exception", e.getMessage()); } finally { if (writer != null) { // Close the fd writer.flush(); writer.close(); } synchronized (exportSyncObj) { csvExport = null; } } return Status.CANCEL_STATUS; } }; job.setUser(true); job.schedule(); } private void handleParameters(EventTableRow currentRow) throws SoCTraceException { String tmpParameters = currentRow.get(EventTableColumn.PARAMS); // Keep the parameter value Map<Integer, String> currentParameterValue = new HashMap<Integer, String>(); String[] parameters = tmpParameters .split(EventTableRow.PARAMETER_SEPARATOR); // Parse parameter for (int i = 0; i < parameters.length; i++) { String[] aParameter = parameters[i] .split(EventTableRow.PARAMETER_VALUE_SEPARATOR); if (aParameter.length < 2) { logger.error("Incorrect element encountered during the parsing of parameters: " + parameters[i]); continue; } // Remove white space String paramType = aParameter[0].trim(); // If we have not yet met this type of parameter if (!parameterTypes.containsKey(paramType)) { parameterTypes.put(paramType, currentMaxNumberOfParameter); if (currentMaxNumberOfParameter == 0) // Extend the header with it csvHeader.append(paramType); else // Extend the header with it csvHeader.append(FramesocConstants.CSV_SEPARATOR + paramType); currentMaxNumberOfParameter++; } // Remove white space and quote String paramValue = aParameter[1].trim(); // Check that the parameter ends with a quote if (paramValue.endsWith(EventTableRow.PARAMETER_VALUE_ESCAPE)) paramValue = paramValue.substring(1, paramValue.length() - 1); else { // The param value contained at least one // PARAMETER_SEPARATOR paramValue = paramValue.substring(1, paramValue.length()); while (true) { if (i + 1 < parameters.length) { String nextValue = parameters[i + 1].trim(); // Are we at the end of the parameter if (nextValue .endsWith(EventTableRow.PARAMETER_VALUE_ESCAPE)) { paramValue = paramValue + nextValue.substring(0, nextValue.length() - 1); i++; break; } else { paramValue = paramValue + parameters[i + 1]; } i++; } else { break; } } } currentParameterValue .put(parameterTypes.get(paramType), paramValue); } // Complete csv with existing parameter values or blank otherwise for (int i = 0; i < currentMaxNumberOfParameter; i++) { if (i != 0) csvExport.append(FramesocConstants.CSV_SEPARATOR); if (currentParameterValue.containsKey(i)) { csvExport.append(currentParameterValue.get(i)); } } } /** * Cancel the export. */ public void cancel() { stop = true; } }