Java tutorial
/* * Copyright (C) 2014 David A. Parry <d.a.parry@leeds.ac.uk> * * 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.github.autoprimer3; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import static java.lang.System.getProperty; import java.net.MalformedURLException; import java.net.URL; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.ResourceBundle; import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.concurrent.Service; import javafx.concurrent.Task; import javafx.concurrent.WorkerStateEvent; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Button; import javafx.scene.control.ChoiceBox; import javafx.scene.control.ContextMenu; import javafx.scene.control.Hyperlink; import javafx.scene.control.Label; import javafx.scene.control.MenuBar; import javafx.scene.control.MenuItem; import javafx.scene.control.ProgressBar; import javafx.scene.control.SelectionMode; import javafx.scene.control.Tab; import javafx.scene.control.TableColumn; import javafx.scene.control.TablePosition; import javafx.scene.control.TableView; import javafx.scene.control.TextArea; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.input.Clipboard; import javafx.scene.input.ClipboardContent; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCodeCombination; import javafx.scene.input.KeyCombination; import javafx.scene.input.KeyEvent; import javafx.scene.layout.AnchorPane; import javafx.stage.FileChooser; import javafx.stage.Stage; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.controlsfx.control.action.Action; import org.controlsfx.dialog.Dialog; import org.controlsfx.dialog.Dialogs; import org.apache.poi.ss.usermodel.CreationHelper; /** * FXML Controller class * * @author david */ public class Primer3ResultViewController implements Initializable { @FXML AnchorPane resultPane; @FXML MenuBar menuBar; @FXML MenuItem writeFileMenuItem; @FXML MenuItem writeDesignMenuItem; @FXML MenuItem writeRefsMenuItem; @FXML MenuItem closeMenuItem; @FXML TableView<Primer3Result> primerTable; @FXML TableColumn indexCol; @FXML TableColumn nameCol; @FXML TableColumn idCol; @FXML TableColumn leftPrimerCol; @FXML TableColumn rightPrimerCol; @FXML TableColumn productSizeCol; @FXML TableColumn regionCol; @FXML TableColumn ispcrCol; @FXML TableColumn ispcrResCol; @FXML Button checkIsPcrButton; @FXML Button closeButton; @FXML Label summaryLabel; @FXML TextArea designTextSummary; @FXML TextArea referenceTextArea; @FXML Tab refTab; @FXML ChoiceBox refChoiceBox; @FXML ProgressBar progressBar; NumberFormat nf = NumberFormat.getNumberInstance(); CoordComparator coordCompare = new CoordComparator(); HashMap<String, String> refSeqs; String summary = null; private final ObservableList<Primer3Result> data = FXCollections.observableArrayList(); @Override public void initialize(URL url, ResourceBundle rb) { menuBar.setUseSystemMenuBar(true); progressBar.setVisible(false); indexCol.setCellValueFactory(new PropertyValueFactory<Primer3Result, Integer>("index")); leftPrimerCol.setCellValueFactory(new PropertyValueFactory<Primer3Result, String>("leftPrimer")); nameCol.setCellValueFactory(new PropertyValueFactory<Primer3Result, String>("name")); idCol.setCellValueFactory(new PropertyValueFactory<Primer3Result, String>("transcripts")); rightPrimerCol.setCellValueFactory(new PropertyValueFactory<Primer3Result, String>("rightPrimer")); productSizeCol.setCellValueFactory(new PropertyValueFactory<Primer3Result, Integer>("productSize")); regionCol.setCellValueFactory(new PropertyValueFactory<Primer3Result, String>("regionLink")); ispcrCol.setCellValueFactory(new PropertyValueFactory<Primer3Result, Hyperlink>("isPcrLink")); ispcrResCol.setCellValueFactory(new PropertyValueFactory<Primer3Result, Hyperlink>("isPcrResults")); ispcrResCol.setVisible(false); primerTable.getSortOrder().add(indexCol); primerTable.getSortOrder().add(regionCol); primerTable.getSortOrder().add(productSizeCol); regionCol.setComparator(coordCompare); primerTable.getSelectionModel().setCellSelectionEnabled(true); primerTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); refTab.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue ov, Boolean value, final Boolean newValue) { Platform.runLater(new Runnable() { @Override public void run() { refChoiceBox.setVisible(newValue); } }); } }); writeFileMenuItem.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { try { writePrimersToFile(); } catch (final IOException ex) { Platform.runLater(new Runnable() { @Override public void run() { Action writeFailed = Dialogs.create().title("Writing failed") .masthead("Could not write primers to file") .message("Exception encountered when attempting to write " + "primers to file. See below:") .styleClass(Dialog.STYLE_CLASS_NATIVE).showException(ex); } }); } } }); writeDesignMenuItem.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { try { writeDesignToFile(); } catch (final IOException ex) { Platform.runLater(new Runnable() { @Override public void run() { Action writeFailed = Dialogs.create().title("Writing failed") .masthead("Could not write primer designs to file") .message("Exception encountered when attempting to write " + "design details to file. See below:") .styleClass(Dialog.STYLE_CLASS_NATIVE).showException(ex); } }); } } }); writeRefsMenuItem.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { try { writeRefSeqsToFile(); } catch (final IOException ex) { Platform.runLater(new Runnable() { @Override public void run() { Action writeFailed = Dialogs.create().title("Writing failed") .masthead("Could not write reference sequences to file") .message("Exception encountered when attempting to write " + "reference sequences to file. See below:") .styleClass(Dialog.STYLE_CLASS_NATIVE).showException(ex); } }); } } }); setCheckIsPcrButton(); closeMenuItem.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent e) { Platform.runLater(new Runnable() { @Override public void run() { Stage stage = (Stage) resultPane.getScene().getWindow(); stage.close(); } }); } }); if (System.getProperty("os.name").equals("Mac OS X")) { closeMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.W, KeyCombination.SHORTCUT_DOWN)); } MenuItem copyItem = new MenuItem("Copy"); copyItem.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { ObservableList<TablePosition> posList = primerTable.getSelectionModel().getSelectedCells(); int old_r = -1; StringBuilder clipboardString = new StringBuilder(); for (TablePosition p : posList) { int r = p.getRow(); int c = p.getColumn(); Object cell = primerTable.getColumns().get(c).getCellData(r); if (cell instanceof Hyperlink) { Hyperlink link = (Hyperlink) cell; cell = link.getText(); } if (cell == null) cell = ""; if (old_r == r) clipboardString.append('\t'); else if (old_r != -1) clipboardString.append('\n'); clipboardString.append(cell); old_r = r; } final ClipboardContent content = new ClipboardContent(); content.putString(clipboardString.toString()); Clipboard.getSystemClipboard().setContent(content); } }); ContextMenu menu = new ContextMenu(); menu.getItems().add(copyItem); copyItem.setAccelerator(new KeyCodeCombination(KeyCode.C, KeyCombination.SHORTCUT_DOWN)); primerTable.setContextMenu(menu); closeButton.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent e) { Platform.runLater(new Runnable() { @Override public void run() { Stage stage = (Stage) closeButton.getScene().getWindow(); stage.close(); } }); } }); } public void displayData(ArrayList<Primer3Result> regions, ArrayList<String> design, final HashMap<String, String> ref) { int totalPairs = 0; int failures = 0; refSeqs = ref; if (ref != null) { refTab.setDisable(false); writeRefsMenuItem.setDisable(false); refChoiceBox.getItems().clear(); refChoiceBox.getItems().addAll(ref.keySet()); refChoiceBox.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>() { @Override public void changed(ObservableValue ov, Number value, final Number new_value) { if (new_value.intValue() >= 0) { final String id = (String) refChoiceBox.getItems().get(new_value.intValue()); Platform.runLater(new Runnable() { @Override public void run() { //System.out.println("Selecting " + id ); //System.out.println("Seq = " + ref.get(id) ); referenceTextArea.setText(splitStringOnLength(ref.get(id), 60, "\n")); } }); } } }); refChoiceBox.getSelectionModel().selectFirst(); } else { refTab.setDisable(true); writeRefsMenuItem.setDisable(true); } StringBuilder designString = new StringBuilder(); for (Primer3Result r : regions) { data.add(r); primerTable.setItems(data); if (r.getProductSize() > 0) { totalPairs++; } else { failures++; } } for (String s : design) { designString.append(s).append("\n"); } designTextSummary.setText(designString.toString()); StringBuilder labelText = new StringBuilder(totalPairs + " primer pairs designed"); if (failures > 0) { labelText.append(". ").append(failures).append(" design"); if (failures > 1) { labelText.append("s"); } labelText.append(" failed."); } summary = labelText.toString(); summaryLabel.setText(summary); } private String splitStringOnLength(String s, Integer n, String sep) { StringBuilder split = new StringBuilder(); for (int i = 0; i < s.length(); i += n) { split.append(s.substring(i, Math.min(i + n, s.length()))); split.append(sep); } return split.toString(); } private void writePrimersToFile() throws IOException { if (data.isEmpty()) { Dialogs noPrimersError = Dialogs.create().title("Nothing to save").masthead("No primers to save") .message("No primers were designed, no file can be saved.") .styleClass(Dialog.STYLE_CLASS_NATIVE); noPrimersError.showError(); return; } FileChooser fileChooser = new FileChooser(); fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Excel (*.xlsx)", "*.xlsx"), new FileChooser.ExtensionFilter("CSV (*.csv)", "*.csv"), new FileChooser.ExtensionFilter("Text (*.txt)", "*.txt")); fileChooser.setTitle("Write primers to file..."); fileChooser.setInitialDirectory(new File(getProperty("user.home"))); File wFile = fileChooser.showSaveDialog(resultPane.getScene().getWindow()); if (wFile == null) { return; } else if (!wFile.getName().endsWith(".xlsx") && !wFile.getName().endsWith(".csv") && !wFile.getName().endsWith(".txt")) { String ext = //annoying bug with filechooser means extension might not be appended fileChooser.selectedExtensionFilterProperty().get().getExtensions().get(0).substring(1); wFile = new File(wFile.getAbsolutePath() + ext); } if (wFile.getName().endsWith(".xlsx")) { writePrimersToExcel(wFile); } else if (wFile.getName().endsWith(".csv")) { writePrimersToCsv(wFile); } else { writePrimersToTsv(wFile); } } private void writePrimersToExcel(final File f) throws IOException { final Service<Void> service = new Service<Void>() { @Override protected Task<Void> createTask() { return new Task<Void>() { @Override protected Void call() throws IOException { BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(f)); Workbook wb = new XSSFWorkbook(); CellStyle hlink_style = wb.createCellStyle(); Font hlink_font = wb.createFont(); hlink_font.setUnderline(Font.U_SINGLE); hlink_font.setColor(IndexedColors.BLUE.getIndex()); hlink_style.setFont(hlink_font); CreationHelper createHelper = wb.getCreationHelper(); Sheet listSheet = wb.createSheet(); Sheet detailsSheet = wb.createSheet(); Row row = null; int rowNo = 0; int sheetNo = 0; wb.setSheetName(sheetNo++, "List"); wb.setSheetName(sheetNo++, "Details"); row = listSheet.createRow(rowNo++); String header[] = { "Primer", "Sequence", "Product Size (bp)" }; for (int col = 0; col < header.length; col++) { Cell cell = row.createCell(col); cell.setCellValue(header[col]); } updateMessage("Writing primers . . ."); updateProgress(0, data.size() * 3); int n = 0; for (Primer3Result r : data) { n++; updateMessage("Writing primer list " + n + " . . ."); row = listSheet.createRow(rowNo++); int col = 0; Cell cell = row.createCell(col++); cell.setCellValue(r.getName() + "F"); cell = row.createCell(col++); cell.setCellValue(r.getLeftPrimer()); cell = row.createCell(col++); cell.setCellValue(r.getProductSize()); updateProgress(n, data.size() * 3); updateMessage("Writing primer list " + n + " . . ."); row = listSheet.createRow(rowNo++); col = 0; cell = row.createCell(col++); cell.setCellValue(r.getName() + "R"); cell = row.createCell(col++); cell.setCellValue(r.getRightPrimer()); cell = row.createCell(col++); cell.setCellValue(r.getProductSize()); n++; updateProgress(n, data.size() * 3); } rowNo = 0; row = detailsSheet.createRow(rowNo++); ArrayList<String> detailsHeader = new ArrayList<>(Arrays.asList("Name", "Other IDs", "Left Primer", "Right Primer", "Product Size (bp)", "Region", "in-silico PCR")); if (ispcrResCol.isVisible()) { detailsHeader.add("in-silico PCR Results"); } for (int col = 0; col < detailsHeader.size(); col++) { Cell cell = row.createCell(col); cell.setCellValue(detailsHeader.get(col)); } int m = 0; for (Primer3Result r : data) { m++; updateMessage("Writing details for pair " + m + " . . ."); row = detailsSheet.createRow(rowNo++); int col = 0; Cell cell = row.createCell(col++); cell.setCellValue(r.getName()); cell = row.createCell(col++); cell.setCellValue(r.getTranscripts()); cell = row.createCell(col++); cell.setCellValue(r.getLeftPrimer()); cell = row.createCell(col++); cell.setCellValue(r.getRightPrimer()); cell = row.createCell(col++); cell.setCellValue(r.getProductSize()); cell = row.createCell(col++); cell.setCellValue(r.getRegion()); cell = row.createCell(col++); if (r.getIsPcrUrl() != null) { cell.setCellValue("isPCR"); org.apache.poi.ss.usermodel.Hyperlink hl = createHelper .createHyperlink(org.apache.poi.ss.usermodel.Hyperlink.LINK_URL); hl.setAddress(r.getIsPcrUrl()); cell.setHyperlink(hl); cell.setCellStyle(hlink_style); } else { cell.setCellValue(""); } if (ispcrResCol.isVisible()) { cell = row.createCell(col++); if (r.getIsPcrResults() != null) { cell.setCellValue(r.getIsPcrResults()); } else { cell.setCellValue(""); } } updateProgress(n + m, data.size() * 3); } updateMessage("Wrote " + data.size() + " primer pairs to file."); wb.write(bo); bo.close(); return null; } }; } }; service.setOnSucceeded(new EventHandler<WorkerStateEvent>() { @Override public void handle(WorkerStateEvent e) { Action response = Dialogs.create().title("Done").masthead("Finished writing") .message("Primers successfully written to " + f.getAbsolutePath() + "\n\nDo you want to open " + "this file now?") .actions(Dialog.ACTION_YES, Dialog.ACTION_NO).styleClass(Dialog.STYLE_CLASS_NATIVE) .showConfirm(); if (response == Dialog.ACTION_YES) { try { openFile(f); } catch (IOException ex) { Action openFailed = Dialogs.create().title("Open failed") .masthead("Could not open output file") .message("Exception encountered when attempting to open " + "the saved file. See below:") .styleClass(Dialog.STYLE_CLASS_NATIVE).showException(ex); } } progressBar.progressProperty().unbind(); progressBar.setVisible(false); summaryLabel.textProperty().unbind(); summaryLabel.setText(summary); closeButton.setDisable(false); closeMenuItem.setDisable(false); setCheckIsPcrButton(); } }); service.setOnCancelled(new EventHandler<WorkerStateEvent>() { @Override public void handle(WorkerStateEvent e) { Dialogs writeCancelled = Dialogs.create().title("Writing Cancelled") .masthead("Cancelled writing to file").message("User cancelled writing primers to file.") .styleClass(Dialog.STYLE_CLASS_NATIVE); writeCancelled.showInformation(); progressBar.progressProperty().unbind(); progressBar.setVisible(false); summaryLabel.textProperty().unbind(); summaryLabel.setText(summary); closeButton.setDisable(false); closeMenuItem.setDisable(false); setCheckIsPcrButton(); } }); service.setOnFailed(new EventHandler<WorkerStateEvent>() { @Override public void handle(WorkerStateEvent e) { Action writeFailed = Dialogs.create().title("Writing failed") .masthead("Could not write primers to file") .message("Exception encountered when attempting to write " + "primers to file. See below:") .styleClass(Dialog.STYLE_CLASS_NATIVE).showException(e.getSource().getException()); progressBar.progressProperty().unbind(); progressBar.setVisible(false); summaryLabel.textProperty().unbind(); summaryLabel.setText(summary); closeButton.setDisable(false); closeMenuItem.setDisable(false); setCheckIsPcrButton(); } }); progressBar.setVisible(true); progressBar.progressProperty().bind(service.progressProperty()); summaryLabel.textProperty().bind(service.messageProperty()); closeButton.setDisable(true); closeMenuItem.setDisable(true); checkIsPcrButton.setText("Cancel"); checkIsPcrButton.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent actionEvent) { service.cancel(); } }); service.start(); } private void writePrimersToCsv(final File f) throws IOException { writePrimersToText(f, ","); } private void writePrimersToTsv(final File f) throws IOException { writePrimersToText(f, "\t"); } //takes output file and delimiter string as arguments private void writePrimersToText(final File f, final String d) throws IOException { final Service<Void> service = new Service<Void>() { @Override protected Task<Void> createTask() { return new Task<Void>() { @Override protected Void call() throws IOException { FileWriter fw = new FileWriter(f.getAbsoluteFile()); BufferedWriter bw = new BufferedWriter(fw); updateMessage("Writing primers . . ."); updateProgress(0, data.size() * 2); int n = 0; for (Primer3Result r : data) { n++; updateMessage("Writing primer " + n + " . . ."); updateProgress(n, data.size()); bw.write(r.getName() + "F" + d + r.getLeftPrimer()); bw.newLine(); n++; updateMessage("Writing primer " + n + " . . ."); updateProgress(n, data.size()); bw.write(r.getName() + "R" + d + r.getRightPrimer()); bw.newLine(); } updateMessage("Wrote " + n + " primers to file."); bw.close(); return null; } }; } }; service.setOnSucceeded(new EventHandler<WorkerStateEvent>() { @Override public void handle(WorkerStateEvent e) { /* Dialogs.create().title("Done"). masthead("Finished writing"). message("Primers successfully written to " + f.getAbsolutePath()). styleClass(Dialog.STYLE_CLASS_NATIVE). showInformation(); */ Action response = Dialogs.create().title("Done").masthead("Finished writing") .message("Primers successfully written to " + f.getAbsolutePath() + "\n\nDo you want to open " + "this file now?") .actions(Dialog.ACTION_YES, Dialog.ACTION_NO).styleClass(Dialog.STYLE_CLASS_NATIVE) .showConfirm(); if (response == Dialog.ACTION_YES) { try { //Desktop.getDesktop().open(f); openFile(f); } catch (IOException ex) { Action openFailed = Dialogs.create().title("Open failed") .masthead("Could not open output file") .message("Exception encountered when attempting to open " + "the saved file. See below:") .styleClass(Dialog.STYLE_CLASS_NATIVE).showException(ex); } } progressBar.progressProperty().unbind(); progressBar.setVisible(false); summaryLabel.textProperty().unbind(); summaryLabel.setText(summary); closeButton.setDisable(false); closeMenuItem.setDisable(false); setCheckIsPcrButton(); } }); service.setOnCancelled(new EventHandler<WorkerStateEvent>() { @Override public void handle(WorkerStateEvent e) { Dialogs writeCancelled = Dialogs.create().title("Writing Cancelled") .masthead("Cancelled writing to file").message("User cancelled writing primers to file.") .styleClass(Dialog.STYLE_CLASS_NATIVE); writeCancelled.showInformation(); progressBar.progressProperty().unbind(); progressBar.setVisible(false); summaryLabel.textProperty().unbind(); summaryLabel.setText(summary); closeButton.setDisable(false); closeMenuItem.setDisable(false); setCheckIsPcrButton(); } }); service.setOnFailed(new EventHandler<WorkerStateEvent>() { @Override public void handle(WorkerStateEvent e) { Action writeFailed = Dialogs.create().title("Writing failed") .masthead("Could not write primers to file") .message("Exception encountered when attempting to write " + "primers to file. See below:") .styleClass(Dialog.STYLE_CLASS_NATIVE).showException(e.getSource().getException()); progressBar.progressProperty().unbind(); progressBar.setVisible(false); summaryLabel.textProperty().unbind(); summaryLabel.setText(summary); closeButton.setDisable(false); closeMenuItem.setDisable(false); setCheckIsPcrButton(); } }); progressBar.setVisible(true); progressBar.progressProperty().bind(service.progressProperty()); summaryLabel.textProperty().bind(service.messageProperty()); closeButton.setDisable(true); closeMenuItem.setDisable(true); checkIsPcrButton.setText("Cancel"); checkIsPcrButton.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent actionEvent) { service.cancel(); } }); service.start(); } private void writeDesignToFile() throws IOException { if (designTextSummary.getText().isEmpty()) { Dialogs noPrimersError = Dialogs.create().title("Nothing to save").masthead("No designs to save") .message("No primer designs were made, no file can be saved.") .styleClass(Dialog.STYLE_CLASS_NATIVE); noPrimersError.showError(); return; } FileChooser fileChooser = new FileChooser(); fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Text (*.txt)", "*.txt")); fileChooser.setTitle("Write primer designs to file..."); fileChooser.setInitialDirectory(new File(getProperty("user.home"))); File wFile = fileChooser.showSaveDialog(resultPane.getScene().getWindow()); if (wFile == null) { return; } else if (!wFile.getName().endsWith(".txt")) { //annoying bug with filechooser means extension might not be appended wFile = new File(wFile.getAbsolutePath() + ".txt"); } String des[] = designTextSummary.getText().split("\n");//want platform agnostic newlines FileWriter fw = new FileWriter(wFile.getAbsoluteFile()); BufferedWriter bw = new BufferedWriter(fw); for (String d : des) { bw.write(d); bw.newLine(); } bw.close(); Action response = Dialogs.create().title("Done").masthead("Finished writing") .message("Primer designs successfully written to " + wFile.getAbsolutePath() + "\n\nDo you want to open " + "this file now?") .actions(Dialog.ACTION_YES, Dialog.ACTION_NO).styleClass(Dialog.STYLE_CLASS_NATIVE).showConfirm(); if (response == Dialog.ACTION_YES) { try { //Desktop.getDesktop().open(f); openFile(wFile); } catch (IOException ex) { Action openFailed = Dialogs.create().title("Open failed").masthead("Could not open output file") .message("Exception encountered when attempting to open " + "the saved file. See below:") .styleClass(Dialog.STYLE_CLASS_NATIVE).showException(ex); } } } private void writeRefSeqsToFile() throws IOException { if (refSeqs.isEmpty()) { Dialogs noPrimersError = Dialogs.create().title("Nothing to save") .masthead("No reference sequences to save") .message("No reference sequences created, no file to be saved.") .styleClass(Dialog.STYLE_CLASS_NATIVE); noPrimersError.showError(); return; } FileChooser fileChooser = new FileChooser(); fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Text (*.txt)", "*.txt")); fileChooser.setTitle("Write reference sequences to file..."); fileChooser.setInitialDirectory(new File(getProperty("user.home"))); File wFile = fileChooser.showSaveDialog(resultPane.getScene().getWindow()); if (wFile == null) { return; } else if (!wFile.getName().endsWith(".txt")) { //annoying bug with filechooser means extension might not be appended wFile = new File(wFile.getAbsolutePath() + ".txt"); } FileWriter fw = new FileWriter(wFile.getAbsoluteFile()); BufferedWriter bw = new BufferedWriter(fw); for (String id : refSeqs.keySet()) { bw.write(">" + id); bw.newLine(); bw.write(splitStringOnLength(refSeqs.get(id), 60, System.getProperty("line.separator"))); bw.newLine(); } bw.close(); Action response = Dialogs.create().title("Done").masthead("Finished writing") .message("Reference sequences successfully written to " + wFile.getAbsolutePath() + "\n\nDo you want to open " + "this file now?") .actions(Dialog.ACTION_YES, Dialog.ACTION_NO).styleClass(Dialog.STYLE_CLASS_NATIVE).showConfirm(); if (response == Dialog.ACTION_YES) { try { //Desktop.getDesktop().open(f); openFile(wFile); } catch (IOException ex) { Action openFailed = Dialogs.create().title("Open failed").masthead("Could not open output file") .message("Exception encountered when attempting to open " + "the saved file. See below:") .styleClass(Dialog.STYLE_CLASS_NATIVE).showException(ex); } } } private void checkIsPcrResults() throws MalformedURLException, IOException { final Service<ObservableList<Primer3Result>> service = new Service<ObservableList<Primer3Result>>() { @Override protected Task<ObservableList<Primer3Result>> createTask() { return new Task<ObservableList<Primer3Result>>() { @Override protected ObservableList<Primer3Result> call() throws IOException { final ObservableList<Primer3Result> newData = FXCollections.observableArrayList(); updateProgress(0, data.size()); int p = 0; for (Primer3Result r : data) { p++; updateMessage("Checking primer pair " + p + " . . ."); r.setIsPcrResults(0); if (r.getIsPcrUrl() != null) { URL url = new URL(r.getIsPcrUrl()); BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream())); String inputLine; while ((inputLine = in.readLine()) != null) { if (inputLine.contains("PcrResult=pack")) { Integer n = r.getIsPcrResults(); r.setIsPcrResults(++n); } } } updateProgress(p, data.size()); newData.add(r); } return newData; } }; } }; service.setOnSucceeded(new EventHandler<WorkerStateEvent>() { @Override public void handle(WorkerStateEvent e) { ObservableList<Primer3Result> d = (ObservableList<Primer3Result>) e.getSource().getValue(); data.removeAll(data); data.addAll(d); final ArrayList<Primer3Result> nonSpecific = new ArrayList<>(); for (Primer3Result r : data) { if (r.getIsPcrResults() > 1) { nonSpecific.add(r); } } StringBuilder msg = new StringBuilder(); if (nonSpecific.size() > 0) { msg.append("WARNING: ").append(nonSpecific.size()).append(" primer pair"); if (nonSpecific.size() == 1) { msg.append(" appears "); } else { msg.append("s appear "); } msg.append("to amplify more than one genomic region.\n\n"); } msg.append(d.size()).append(" total primer pairs checked by in-silico PCR"); final String message = msg.toString(); Platform.runLater(new Runnable() { @Override public void run() { ispcrResCol.setVisible(true); progressBar.progressProperty().unbind(); progressBar.setVisible(false); summaryLabel.textProperty().unbind(); summaryLabel.setText(summary); writeFileMenuItem.setDisable(false); closeButton.setDisable(false); closeMenuItem.setDisable(false); setCheckIsPcrButton(); Dialogs inf = Dialogs.create().title("Done").masthead("Finished Checking isPCR Results") .message(message).styleClass(Dialog.STYLE_CLASS_NATIVE); if (nonSpecific.isEmpty()) { inf.showInformation(); } else { inf.showWarning(); } } }); } }); service.setOnFailed(new EventHandler<WorkerStateEvent>() { @Override public void handle(WorkerStateEvent e) { Action writeFailed = Dialogs.create().title("isPCR failed") .masthead("Could not check primer pairs by in-silico PCR") .message("Exception encountered when attempting to check " + "primers by in-silico PCR. See below:") .styleClass(Dialog.STYLE_CLASS_NATIVE).showException(e.getSource().getException()); progressBar.progressProperty().unbind(); progressBar.setProgress(0); progressBar.setVisible(false); summaryLabel.textProperty().unbind(); summaryLabel.setText(summary); writeFileMenuItem.setDisable(false); closeButton.setDisable(false); closeMenuItem.setDisable(false); setCheckIsPcrButton(); } }); service.setOnCancelled(new EventHandler<WorkerStateEvent>() { @Override public void handle(WorkerStateEvent e) { Dialogs writeCancelled = Dialogs.create().title("isPCR Cancelled") .masthead("Primer pair checks cancelled") .message("isPCR checks by in-silico PCR were cancelled by user.") .styleClass(Dialog.STYLE_CLASS_NATIVE); writeCancelled.showInformation(); progressBar.progressProperty().unbind(); progressBar.setProgress(0); progressBar.setVisible(false); summaryLabel.textProperty().unbind(); summaryLabel.setText(summary); writeFileMenuItem.setDisable(false); closeButton.setDisable(false); closeMenuItem.setDisable(false); setCheckIsPcrButton(); } }); checkIsPcrButton.setText("Cancel"); checkIsPcrButton.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent actionEvent) { service.cancel(); } }); progressBar.setVisible(true); progressBar.progressProperty().bind(service.progressProperty()); summaryLabel.textProperty().bind(service.messageProperty()); writeFileMenuItem.setDisable(true); closeButton.setDisable(true); closeMenuItem.setDisable(true); service.start(); } private void setCheckIsPcrButton() { checkIsPcrButton.setText("Check isPCR Results"); checkIsPcrButton.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent e) { try { checkIsPcrResults(); } catch (final IOException ex) { Platform.runLater(new Runnable() { @Override public void run() { Action writeFailed = Dialogs.create().title("isPCR Check Failed") .masthead("Error performing in-silico PCR checks on primers.") .message("Exception encountered when attempting perform in-silico " + "PCR checks via UCSC webiste. See below:") .styleClass(Dialog.STYLE_CLASS_NATIVE).showException(ex); } }); } } }); } private void openFile(File f) throws IOException { String command; //Desktop.getDesktop().open(f); if (System.getProperty("os.name").equals("Linux")) { command = "xdg-open " + f; } else if (System.getProperty("os.name").equals("Mac OS X")) { command = "open " + f; } else if (System.getProperty("os.name").contains("Windows")) { command = "cmd /C start " + f; } else { return; } Runtime.getRuntime().exec(command); } }