/* * Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see http://www.gnu.org/licenses/ */ package org.esa.snap.ui.diagram; import org.esa.snap.core.util.PropertyMap; import org.esa.snap.core.util.io.CsvReader; import org.esa.snap.core.util.io.SnapFileFilter; import org.esa.snap.ui.SnapFileChooser; import javax.swing.JOptionPane; import java.awt.Component; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.Reader; import java.io.Writer; import java.util.ArrayList; import java.util.List; public class DiagramGraphIO { public static final SnapFileFilter CSV_FILE_FILTER = new SnapFileFilter("CSV", ".csv", "CSV (plain text)"); public static final SnapFileFilter SPECTRA_CSV_FILE_FILTER = new SnapFileFilter("Spectra-CSV", ".csv", "Spectra CSV"); public static final String DIAGRAM_GRAPH_IO_LAST_DIR_KEY = "diagramGraphIO.lastDir"; public static DiagramGraph[] readGraphs(Reader reader) throws IOException { CsvReader csvReader = new CsvReader(reader, new char[]{'\t'}); List<DiagramGraph> graphGroup = new ArrayList<DiagramGraph>(5); List<double[]> dataRecords = new ArrayList<double[]>(20); String[] headerRecord = csvReader.readRecord(); while (true) { if (headerRecord.length < 2) { throw new IOException("Invalid format."); } String[] record = csvReader.readRecord(); if (record == null) { break; } double[] dataRecord = toDoubles(record); if (dataRecord != null) { if (dataRecord.length != headerRecord.length) { throw new IOException("Invalid format."); } dataRecords.add(dataRecord); } else { readGraphGroup(headerRecord, dataRecords, graphGroup); headerRecord = record; } } readGraphGroup(headerRecord, dataRecords, graphGroup); return graphGroup.toArray(new DiagramGraph[0]); } public static void writeGraphs(DiagramGraph[] graphs, Writer writer) throws IOException { List<List<DiagramGraph>> graphGroups = computeGraphGroups(graphs); for (List<DiagramGraph> graphGroup : graphGroups) { writeGraphGroup(graphGroup, writer); } } private static void readGraphGroup(String[] headerRecord, List<double[]> dataRecords, List<DiagramGraph> graphs) { if (dataRecords.size() > 0) { double[] xValues = new double[dataRecords.size()]; for (int j = 0; j < dataRecords.size(); j++) { xValues[j] = dataRecords.get(j)[0]; } double[] dataRecord0 = dataRecords.get(0); for (int i = 1; i < dataRecord0.length; i++) { double[] yValues = new double[dataRecords.size()]; for (int j = 0; j < dataRecords.size(); j++) { yValues[j] = dataRecords.get(j)[i]; } graphs.add(new DefaultDiagramGraph(headerRecord[0], xValues, headerRecord[i], yValues)); } } dataRecords.clear(); } public static double[] toDoubles(String[] textRecord) throws IOException { double[] doubleRecord = new double[textRecord.length]; for (int i = 0; i < textRecord.length; i++) { try { doubleRecord[i] = Double.valueOf(textRecord[i]); } catch (NumberFormatException e) { return null; } } return doubleRecord; } private static List<List<DiagramGraph>> computeGraphGroups(DiagramGraph[] graphs) { List<List<DiagramGraph>> graphGroups = new ArrayList<List<DiagramGraph>>(3); for (DiagramGraph graph : graphs) { boolean found = false; for (List<DiagramGraph> graphGroup : graphGroups) { if (equalXValues(graph, graphGroup.get(0))) { graphGroup.add(graph); found = true; break; } } if (!found) { ArrayList<DiagramGraph> graphGroup = new ArrayList<DiagramGraph>(3); graphGroup.add(graph); graphGroups.add(graphGroup); } } return graphGroups; } private static void writeGraphGroup(List<DiagramGraph> graphGroup, Writer writer) throws IOException { DiagramGraph graph0 = graphGroup.get(0); writer.write(graph0.getXName()); for (DiagramGraph graph : graphGroup) { writer.write((int) '\t'); writer.write(graph.getYName()); } writer.write((int) '\n'); int numValues = graph0.getNumValues(); for (int i = 0; i < numValues; i++) { writer.write(String.valueOf(graph0.getXValueAt(i))); for (DiagramGraph graph : graphGroup) { writer.write((int) '\t'); writer.write(String.valueOf(graph.getYValueAt(i))); } writer.write((int) '\n'); } } public static boolean equalXValues(DiagramGraph g1, DiagramGraph g2) { if (g1.getNumValues() != g2.getNumValues()) { return false; } for (int i = 0; i < g1.getNumValues(); i++) { if (Math.abs(g1.getXValueAt(i) - g2.getXValueAt(i)) > 1.0e-10) { return false; } } return true; } public static DiagramGraph[] readGraphs(Component parentComponent, String title, SnapFileFilter[] fileFilters, PropertyMap preferences) { File selectedFile = selectGraphFile(parentComponent, title, fileFilters, preferences, true); if (selectedFile != null) { try { FileReader fileReader = new FileReader(selectedFile); try { return readGraphs(fileReader); } finally { fileReader.close(); } } catch (IOException e) { JOptionPane.showMessageDialog(parentComponent, "I/O error: " + e.getMessage()); } } return new DiagramGraph[0]; } public static void writeGraphs(Component parentComponent, String title, SnapFileFilter[] fileFilters, PropertyMap preferences, DiagramGraph[] graphs) { if (graphs.length == 0) { JOptionPane.showMessageDialog(parentComponent, "Nothing to save."); return; } File selectedFile = selectGraphFile(parentComponent, title, fileFilters, preferences, false); if (selectedFile != null) { try { FileWriter fileWriter = new FileWriter(selectedFile); try { writeGraphs(graphs, fileWriter); } finally { fileWriter.close(); } } catch (IOException e) { JOptionPane.showMessageDialog(parentComponent, "I/O error: " + e.getMessage()); } } } private static File selectGraphFile(Component parentComponent, String title, SnapFileFilter[] fileFilters, PropertyMap preferences, boolean open) { String lastDirPath = preferences.getPropertyString(DIAGRAM_GRAPH_IO_LAST_DIR_KEY, "."); SnapFileChooser fileChooser = new SnapFileChooser(new File(lastDirPath)); fileChooser.setAcceptAllFileFilterUsed(true); fileChooser.setDialogTitle(title); for (SnapFileFilter fileFilter : fileFilters) { fileChooser.addChoosableFileFilter(fileFilter); } fileChooser.setFileFilter(fileFilters[0]); if (open) { fileChooser.setDialogType(SnapFileChooser.OPEN_DIALOG); } else { fileChooser.setDialogType(SnapFileChooser.SAVE_DIALOG); } File selectedFile; while (true) { int i = fileChooser.showDialog(parentComponent, null); if (i == SnapFileChooser.APPROVE_OPTION) { selectedFile = fileChooser.getSelectedFile(); if (open || !selectedFile.exists()) { break; } i = JOptionPane.showConfirmDialog(parentComponent, "The file\n" + selectedFile + "\nalready exists.\nOverwrite?", "File exists", JOptionPane.YES_NO_CANCEL_OPTION); if (i == JOptionPane.CANCEL_OPTION) { // Canceled selectedFile = null; break; } else if (i == JOptionPane.YES_OPTION) { // Overwrite existing file break; } } else { // Canceled selectedFile = null; break; } } if (selectedFile != null) { preferences.setPropertyString(DIAGRAM_GRAPH_IO_LAST_DIR_KEY, selectedFile.getParent()); } return selectedFile; } }