com.ggvaidya.scinames.ui.DatasetImporterController.java Source code

Java tutorial

Introduction

Here is the source code for com.ggvaidya.scinames.ui.DatasetImporterController.java

Source

/*
 * Copyright (C) 2017 Gaurav Vaidya <gaurav@ggvaidya.com>
 *
 * 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 com.ggvaidya.scinames.ui;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Logger;
import java.util.stream.Stream;

import org.apache.commons.csv.CSVFormat;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

import com.ggvaidya.scinames.model.Checklist;
import com.ggvaidya.scinames.model.ChecklistDiff;
import com.ggvaidya.scinames.model.Dataset;
import com.ggvaidya.scinames.model.DatasetRow;
import com.ggvaidya.scinames.util.ExcelImporter;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.paint.Paint;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

/**
 * FXML Controller class
 *
 * @author Gaurav Vaidya <gaurav@ggvaidya.com>
 */
public class DatasetImporterController implements Initializable {
    private static final Logger LOGGER = Logger.getLogger(DatasetImporterController.class.getSimpleName());

    private static final Background BACKGROUND_RED = new Background(
            new BackgroundFill(Paint.valueOf("red"), CornerRadii.EMPTY, Insets.EMPTY));

    private File currentFile = null;
    private Dataset currentDataset = null;

    public Stream<Dataset> getImportedDatasets() {
        if (currentDataset == null)
            return Stream.empty();

        return Stream.of(currentDataset);
    }

    private DatasetImporterView datasetImporterView;

    public void setDatasetImporterView(DatasetImporterView div) {
        datasetImporterView = div;
    }

    /**
     * Initializes the controller class.
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // Fill in fileFormatComboBox
        initFileFormatComboBox();
    }

    private void displayPreview() {
        filePreviewTextArea.setText("");
        if (currentFile == null)
            return;

        if (currentFile.getName().endsWith("xls") || currentFile.getName().endsWith("xlsx")) {
            // Excel files are special! We need to load it special and then preview it.
            ExcelImporter imp;

            String excelPreviewText;
            try {
                imp = new ExcelImporter(currentFile);
                List<Sheet> sheets = imp.getWorksheets();

                StringBuffer preview = new StringBuffer();
                preview.append("Excel file version " + imp.getWorkbook().getSpreadsheetVersion() + " containing "
                        + sheets.size() + " sheets.\n");
                for (Sheet sh : sheets) {
                    preview.append(
                            " - " + sh.getSheetName() + " contains " + sh.getPhysicalNumberOfRows() + " rows.\n");

                    // No rows?
                    if (sh.getPhysicalNumberOfRows() == 0)
                        continue;

                    // Header row?
                    Row headerRow = sh.getRow(0);
                    boolean headerEmitted = false;

                    for (int rowIndex = 1; rowIndex < sh.getPhysicalNumberOfRows(); rowIndex++) {
                        if (rowIndex >= 10)
                            break;

                        Row row = sh.getRow(rowIndex);

                        if (!headerEmitted) {
                            preview.append(
                                    "  - " + String.join("\t", ExcelImporter.getCellsAsValues(headerRow)) + "\n");
                            headerEmitted = true;
                        }
                        preview.append("  - " + String.join("\t", ExcelImporter.getCellsAsValues(row)) + "\n");
                    }

                    preview.append("\n");
                }

                excelPreviewText = preview.toString();
            } catch (IOException ex) {
                excelPreviewText = "Could not open '" + currentFile + "': " + ex;
            }

            filePreviewTextArea.setText(excelPreviewText);

            return;
        }

        // If we're here, then this is some sort of text file, so let's preview the text content directly.
        try {
            LineNumberReader reader = new LineNumberReader(new BufferedReader(new FileReader(currentFile)));

            // Load the first ten lines.
            StringBuffer head = new StringBuffer();
            for (int x = 0; x < 10; x++) {
                head.append(reader.readLine());
                head.append('\n');
            }

            reader.close();
            filePreviewTextArea.setText(head.toString());
        } catch (IOException ex) {
            filePreviewTextArea.setBackground(BACKGROUND_RED);
            filePreviewTextArea.setText("ERROR: Could not load file '" + currentFile + "': " + ex);
        }
    }

    @FXML
    private void loadFromFile(ActionEvent e) {
        if (currentFile == null)
            return;

        try {
            currentDataset = loadDataset();
        } catch (IOException ex) {
            statusTextField.setBackground(BACKGROUND_RED);
            statusTextField.setText("ERROR opening file: " + ex);
            new Alert(AlertType.ERROR, "Could not open file '" + currentFile + "': " + ex).showAndWait();
            return;
        }

        datasetNameTextField.setText(currentDataset.asTitle());
        dateTextField.setText(currentDataset.getDate().toString());
        currentDataset.displayInTableView(datasetTableView);
        statusTextField.setText("Displaying " + currentDataset.getRowCount() + " rows from "
                + currentDataset.getColumns().size() + " columns");
    }

    @FXML
    private void importDataset(ActionEvent e) {
        datasetImporterView.getStage().close();
    }

    @FXML
    private void cancelImport(ActionEvent e) {
        // Close this without resetting the controller.
        // From http://stackoverflow.com/a/29711376/27310

        Stage stage = datasetImporterView.getStage();

        stage.fireEvent(new WindowEvent(stage, WindowEvent.WINDOW_CLOSE_REQUEST));
    }

    /* File format management */
    private void initFileFormatComboBox() {
        fileFormatComboBox.getItems().addAll("List of names", "Default CSV", "Microsoft Excel CSV", "RFC 4180 CSV",
                "Oracle MySQL CSV", "Tab-delimited file", "TaxDiff file", "Excel file");
        fileFormatComboBox.getSelectionModel().clearAndSelect(1);
    }

    private Dataset loadDataset() throws IOException {
        String format = fileFormatComboBox.getSelectionModel().getSelectedItem();
        CSVFormat csvFormat = null;
        if (format == null) {
            csvFormat = CSVFormat.DEFAULT;
        } else {
            switch (format) {
            case "List of names":
                return Checklist.fromListInFile(currentFile);
            case "Default CSV":
                csvFormat = CSVFormat.DEFAULT;
                break;
            case "Microsoft Excel CSV":
                csvFormat = CSVFormat.EXCEL;
                break;
            case "RFC 4180 CSV":
                csvFormat = CSVFormat.RFC4180;
                break;
            case "Oracle MySQL CSV":
                csvFormat = CSVFormat.MYSQL;
                break;
            case "Tab-delimited file":
                csvFormat = CSVFormat.TDF;
                break;
            case "TaxDiff file":
                return ChecklistDiff.fromTaxDiffFile(currentFile);
            case "Excel file":
                return new ExcelImporter(currentFile).asDataset(0);
            }
        }

        if (csvFormat == null) {
            LOGGER.info("Could not determine CSV format from format '" + format + "', using CSV default.");
            csvFormat = CSVFormat.DEFAULT;
        }

        return Dataset.fromCSV(csvFormat, currentFile);
    }

    @FXML
    private void chooseFile(ActionEvent e) {
        FileChooser chooser = new FileChooser();
        chooser.getExtensionFilters().addAll(
                new FileChooser.ExtensionFilter("Comma-separated values (CSV) file", "*.csv"),
                new FileChooser.ExtensionFilter("Tab-delimited values file", "*.txt", "*.tab", "*.tsv"),
                new FileChooser.ExtensionFilter("List of names", "*.txt"),
                new FileChooser.ExtensionFilter("TaxDiff file", "*.taxdiff"),
                new FileChooser.ExtensionFilter("Excel file", "*.xls", "*.xlsx"));

        currentFile = chooser.showOpenDialog(datasetImporterView.getStage());
        if (currentFile == null)
            return;

        filePathTextField.setText(currentFile.getAbsolutePath());
        String filterDesc = chooser.getSelectedExtensionFilter().getDescription();

        if (filterDesc.startsWith("Comma")) {
            fileFormatComboBox.getSelectionModel().select("Default CSV");
        } else if (filterDesc.startsWith("Tab")) {
            fileFormatComboBox.getSelectionModel().select("Tab-delimited file");
        } else if (filterDesc.startsWith("List of names")) {
            fileFormatComboBox.getSelectionModel().select("List of names");
        } else if (filterDesc.startsWith("TaxDiff")) {
            fileFormatComboBox.getSelectionModel().select("TaxDiff file");
        } else if (filterDesc.startsWith("Excel")) {
            fileFormatComboBox.getSelectionModel().select("Excel file");
        }

        displayPreview();
    }

    /* FXML objects */
    @FXML
    private TextField filePathTextField;
    @FXML
    private TextArea filePreviewTextArea;
    @FXML
    private ComboBox<String> fileFormatComboBox;
    @FXML
    private TextField datasetNameTextField;
    @FXML
    private TextField dateTextField;
    @FXML
    private TableView<DatasetRow> datasetTableView;
    @FXML
    private TextField statusTextField;
}