From: Ben Soares Date: Mon, 6 Jul 2020 15:27:36 +0000 (+0100) Subject: Merge branch 'bug/JAL-3628_Unable_to_save_update_to_existing_file_in_Windows' of... X-Git-Tag: Release_2_11_1_1~13^2~26^2~6^2~3 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=675482469991097cc5b0021fa052027f5270c8f5;hp=2b6a74893883a246d40a99a2e981ef6cad4fed5a;p=jalview.git Merge branch 'bug/JAL-3628_Unable_to_save_update_to_existing_file_in_Windows' of https://source.jalview.org/git/jalview into bug/JAL-3628_Unable_to_save_update_to_existing_file_in_Windows --- diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index a4b24ed..96cc7d9 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -1412,3 +1412,7 @@ label.include_linked_features = Include {0} features label.include_linked_tooltip = Include visible {0} features
converted to local sequence coordinates label.features_not_shown = {0} feature(s) not shown label.no_features_to_sort_by = No features to sort by +label.log_level = Log level +label.log_level_tooltip = Temporarily set the log level for this console +label.copy_to_clipboard = Copy to clipboard +label.copy_to_clipboard_tooltip = Copy all of the log text in this console to the system clipboard diff --git a/resources/lang/Messages_es.properties b/resources/lang/Messages_es.properties index 4e0fb1f..dfb8dd6 100644 --- a/resources/lang/Messages_es.properties +++ b/resources/lang/Messages_es.properties @@ -1407,3 +1407,7 @@ label.include_linked_features = Incluir caracter label.include_linked_tooltip = Incluir características de {0}
convertidas a coordenadas de secuencia local label.features_not_shown = {0} característica(s) no mostradas label.no_features_to_sort_by = No hay características para ordenar +label.log_level = Nivel del registro +label.log_level_tooltip = Establezca temporalmente el nivel de registro para esta consola +label.copy_to_clipboard = Copiar en el portapapeles +label.copy_to_clipboard_tooltip = Copie todo el texto de registro en esta consola al portapapeles del sistema diff --git a/src/jalview/datamodel/SearchResults.java b/src/jalview/datamodel/SearchResults.java index 31736e5..0074d2a 100755 --- a/src/jalview/datamodel/SearchResults.java +++ b/src/jalview/datamodel/SearchResults.java @@ -175,11 +175,15 @@ public class SearchResults implements SearchResultsI @Override public boolean involvesSequence(SequenceI sequence) { + final int start = sequence.getStart(); + final int end = sequence.getEnd(); + SequenceI ds = sequence.getDatasetSequence(); - for (SearchResultMatchI _m : matches) + for (SearchResultMatchI m : matches) { - SequenceI matched = _m.getSequence(); - if (matched != null && (matched == sequence || matched == ds)) + SequenceI matched = m.getSequence(); + if (matched != null && (matched == sequence || matched == ds) + && (m.getEnd() >= start) && (m.getStart() <= end)) { return true; } diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index b7d8b3a..79c67ac 100644 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -20,6 +20,54 @@ */ package jalview.gui; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetEvent; +import java.awt.dnd.DropTargetListener; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.print.PageFormat; +import java.awt.print.PrinterJob; +import java.beans.PropertyChangeEvent; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Deque; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.List; +import java.util.Vector; + +import javax.swing.ButtonGroup; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JEditorPane; +import javax.swing.JInternalFrame; +import javax.swing.JLayeredPane; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; + import jalview.analysis.AlignmentSorter; import jalview.analysis.AlignmentUtils; import jalview.analysis.CrossRef; @@ -91,6 +139,7 @@ import jalview.schemes.ColourSchemes; import jalview.schemes.ResidueColourScheme; import jalview.schemes.TCoffeeColourScheme; import jalview.util.MessageManager; +import jalview.util.Platform; import jalview.viewmodel.AlignmentViewport; import jalview.viewmodel.ViewportRanges; import jalview.ws.DBRefFetcher; @@ -100,53 +149,6 @@ import jalview.ws.jws2.Jws2Discoverer; import jalview.ws.jws2.jabaws2.Jws2Instance; import jalview.ws.seqfetcher.DbSourceProxy; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Rectangle; -import java.awt.Toolkit; -import java.awt.datatransfer.Clipboard; -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.StringSelection; -import java.awt.datatransfer.Transferable; -import java.awt.dnd.DnDConstants; -import java.awt.dnd.DropTargetDragEvent; -import java.awt.dnd.DropTargetDropEvent; -import java.awt.dnd.DropTargetEvent; -import java.awt.dnd.DropTargetListener; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.FocusAdapter; -import java.awt.event.FocusEvent; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.awt.print.PageFormat; -import java.awt.print.PrinterJob; -import java.beans.PropertyChangeEvent; -import java.io.File; -import java.io.FileWriter; -import java.io.PrintWriter; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Deque; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.List; -import java.util.Vector; - -import javax.swing.ButtonGroup; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JEditorPane; -import javax.swing.JInternalFrame; -import javax.swing.JLayeredPane; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JScrollPane; -import javax.swing.SwingUtilities; - /** * DOCUMENT ME! * @@ -1197,39 +1199,65 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, else { // create backupfiles object and get new temp filename destination + Cache.log.debug("ALIGNFRAME making backupfiles object for " + file); BackupFiles backupfiles = new BackupFiles(file); try { + Cache.log.debug("ALIGNFRAME setting PrintWriter"); PrintWriter out = new PrintWriter( new FileWriter(backupfiles.getTempFilePath())); + Cache.log.debug("ALIGNFRAME about to write to temp file " + + backupfiles.getTempFilePath()); + out.print(output); + Cache.log.debug("ALIGNFRAME about to close file"); out.close(); + Cache.log.debug("ALIGNFRAME closed file"); this.setTitle(file); statusBar.setText(MessageManager.formatMessage( "label.successfully_saved_to_file_in_format", new Object[] { fileName, format.getName() })); + } catch (IOException e) + { + success = false; + Cache.log.error( + "ALIGNFRAME Something happened writing the temp file"); + Cache.log.error(e.getMessage()); + Cache.log.debug(e.getStackTrace()); + } catch (Exception ex) { success = false; - ex.printStackTrace(); + Cache.log.error( + "ALIGNFRAME Something else happened writing the temp file"); + Cache.log.error(ex.getMessage()); + Cache.log.debug(ex.getStackTrace()); } backupfiles.setWriteSuccess(success); + Cache.log.debug("ALIGNFRAME writing temp file was " + + (success ? "" : "NOT ") + "successful"); // do the backup file roll and rename the temp file to actual file + Cache.log.debug("ALIGNFRAME about to rollBackupsAndRenameTempFile"); success = backupfiles.rollBackupsAndRenameTempFile(); + Cache.log.debug("ALIGNFRAME performed rollBackupsAndRenameTempFile " + + (success ? "" : "un") + "successfully"); } } if (!success) { - JvOptionPane.showInternalMessageDialog(this, MessageManager - .formatMessage("label.couldnt_save_file", new Object[] - { fileName }), - MessageManager.getString("label.error_saving_file"), - JvOptionPane.WARNING_MESSAGE); + if (!Platform.isHeadless()) + { + JvOptionPane.showInternalMessageDialog(this, MessageManager + .formatMessage("label.couldnt_save_file", new Object[] + { fileName }), + MessageManager.getString("label.error_saving_file"), + JvOptionPane.WARNING_MESSAGE); + } } return success; @@ -2736,8 +2764,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, if (viewport.getViewName() == null) { - viewport.setViewName(MessageManager - .getString("label.view_name_original")); + viewport.setViewName( + MessageManager.getString("label.view_name_original")); } /* @@ -3366,8 +3394,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, * otherwise set the chosen colour scheme (or null for 'None') */ ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name, - viewport, - viewport.getAlignment(), viewport.getHiddenRepSequences()); + viewport, viewport.getAlignment(), + viewport.getHiddenRepSequences()); changeColour(cs); } @@ -5694,6 +5722,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, } private Rectangle lastFeatureSettingsBounds = null; + @Override public void setFeatureSettingsGeometry(Rectangle bounds) { diff --git a/src/jalview/gui/Console.java b/src/jalview/gui/Console.java index 4c019a6..a493640 100644 --- a/src/jalview/gui/Console.java +++ b/src/jalview/gui/Console.java @@ -20,15 +20,20 @@ */ package jalview.gui; -import jalview.util.MessageManager; - import java.awt.BorderLayout; +import java.awt.Color; import java.awt.Dimension; import java.awt.GraphicsEnvironment; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; import java.awt.Rectangle; import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; @@ -38,12 +43,19 @@ import java.io.PipedOutputStream; import java.io.PrintStream; import javax.swing.JButton; +import javax.swing.JComboBox; import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; +import org.apache.log4j.Level; import org.apache.log4j.SimpleLayout; +import jalview.bin.Cache; +import jalview.util.MessageManager; + /** * Simple Jalview Java Console. Version 1 - allows viewing of console output * after desktop is created. Acquired with thanks from RJHM's site @@ -88,6 +100,8 @@ public class Console extends WindowAdapter private int MIN_HEIGHT = 250; + private JComboBox logLevelCombo = new JComboBox(); + public Console() { // create all components and add them @@ -115,17 +129,104 @@ public class Console extends WindowAdapter // textArea = cpt.getTextArea(); textArea = new JTextArea(); textArea.setEditable(false); - JButton button = new JButton(MessageManager.getString("action.clear")); + JButton clearButton = new JButton( + MessageManager.getString("action.clear")); + JButton copyToClipboardButton = new JButton( + MessageManager.getString("label.copy_to_clipboard")); + copyToClipboardButton.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + copyConsoleTextToClipboard(); + } + }); + copyToClipboardButton.addMouseListener(new MouseAdapter() + { + private Color bg = textArea.getBackground(); + + private Color fg = textArea.getForeground(); + + public void mousePressed(MouseEvent e) + { + textArea.setBackground(textArea.getSelectionColor()); + textArea.setForeground(textArea.getSelectedTextColor()); + } + + public void mouseReleased(MouseEvent e) + { + textArea.setBackground(bg); + textArea.setForeground(fg); + } + + }); + copyToClipboardButton.setToolTipText( + MessageManager.getString("label.copy_to_clipboard_tooltip")); + + JLabel logLevelLabel = new JLabel( + MessageManager.getString("label.log_level") + ":"); + + // logLevelCombo.addItem(Level.ALL); + logLevelCombo.addItem(Level.TRACE); + logLevelCombo.addItem(Level.DEBUG); + logLevelCombo.addItem(Level.INFO); + logLevelCombo.addItem(Level.WARN); + // logLevelCombo.addItem(Level.ERROR); + // logLevelCombo.addItem(Level.FATAL); + // logLevelCombo.addItem(Level.OFF); + setChosenLogLevelCombo(); + logLevelCombo.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + if (Cache.log != null) + { + Cache.log.setLevel((Level) logLevelCombo.getSelectedItem()); + } + } + + }); // frame = cpt; frame.getContentPane().setLayout(new BorderLayout()); frame.getContentPane().add(new JScrollPane(textArea), BorderLayout.CENTER); - frame.getContentPane().add(button, BorderLayout.SOUTH); + JPanel southPanel = new JPanel(); + southPanel.setLayout(new GridBagLayout()); + + JPanel logLevelPanel = new JPanel(); + logLevelPanel.setAlignmentX(JPanel.LEFT_ALIGNMENT); + logLevelPanel.add(logLevelLabel); + logLevelPanel.add(logLevelCombo); + logLevelLabel.setToolTipText( + MessageManager.getString("label.log_level_tooltip")); + logLevelCombo.setToolTipText( + MessageManager.getString("label.log_level_tooltip")); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.gridwidth = 1; + gbc.gridheight = 1; + gbc.weightx = 0.1; + southPanel.add(logLevelPanel, gbc); + + gbc.gridx++; + gbc.weightx = 0.8; + gbc.fill = GridBagConstraints.HORIZONTAL; + southPanel.add(clearButton, gbc); + + gbc.gridx++; + gbc.weightx = 0.1; + gbc.fill = GridBagConstraints.NONE; + southPanel.add(copyToClipboardButton, gbc); + + southPanel.setVisible(true); + frame.getContentPane().add(southPanel, BorderLayout.SOUTH); frame.setVisible(visible); updateConsole = visible; frame.addWindowListener(this); - button.addActionListener(this); + clearButton.addActionListener(this); + if (redirect) { redirectStreams(); @@ -151,6 +252,50 @@ public class Console extends WindowAdapter textAppender.start(); } + private void setChosenLogLevelCombo() + { + Level currentLogLevel = Cache.log == null ? Level.INFO + : Cache.log.getLevel(); + logLevelCombo.setSelectedItem(currentLogLevel); + if (!logLevelCombo.getSelectedItem().equals(currentLogLevel)) // currentLogLevel + // not in list + { + if (currentLogLevel != null && currentLogLevel instanceof Level) + { + // add new item to list (might be set via .jalview_properties) + boolean added = false; + for (int i = 0; i < logLevelCombo.getItemCount(); i++) + { + Level l = (Level) logLevelCombo.getItemAt(i); + if (l.isGreaterOrEqual(currentLogLevel)) + { + logLevelCombo.insertItemAt(currentLogLevel, i); + added = true; + break; + } + } + if (!added) // lower priority than others or some confusion -- add to + // end of list + { + logLevelCombo.addItem(currentLogLevel); + } + logLevelCombo.setSelectedItem(currentLogLevel); + } + else + { + logLevelCombo.setSelectedItem(Level.INFO); + } + } + } + + private void copyConsoleTextToClipboard() + { + String consoleText = textArea.getText(); + StringSelection consoleTextSelection = new StringSelection(consoleText); + Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); + cb.setContents(consoleTextSelection, null); + } + PipedOutputStream pout = null, perr = null; public void redirectStreams() @@ -644,12 +789,21 @@ public class Console extends WindowAdapter frame.setVisible(selected); if (selected == true) { + setChosenLogLevelCombo(); redirectStreams(); updateConsole = true; frame.toFront(); } else { + // reset log level to user preference + if (Cache.log != null) + { + String userLogLevel = Cache.getDefault("logs.Jalview.level", + Level.INFO.toString()); + Cache.log.setLevel(Level.toLevel(userLogLevel)); + } + unredirectStreams(); updateConsole = false; } diff --git a/src/jalview/gui/SeqPanel.java b/src/jalview/gui/SeqPanel.java index cd974a4..def4be1 100644 --- a/src/jalview/gui/SeqPanel.java +++ b/src/jalview/gui/SeqPanel.java @@ -1200,7 +1200,7 @@ public class SeqPanel extends JPanel { char sequenceChar = sequence.getCharAt(column); int pos = sequence.findPosition(column); - setStatusMessage(sequence, seqIndex, sequenceChar, pos); + setStatusMessage(sequence.getName(), seqIndex, sequenceChar, pos); return pos; } @@ -1216,7 +1216,7 @@ public class SeqPanel extends JPanel * Sequence 6 ID: O.niloticus.3 Nucleotide: Uracil (2) * * - * @param sequence + * @param seqName * @param seqIndex * sequence position in the alignment (1..) * @param sequenceChar @@ -1224,7 +1224,7 @@ public class SeqPanel extends JPanel * @param residuePos * the sequence residue position (if not over a gap) */ - protected void setStatusMessage(SequenceI sequence, int seqIndex, + protected void setStatusMessage(String seqName, int seqIndex, char sequenceChar, int residuePos) { StringBuilder text = new StringBuilder(32); @@ -1234,7 +1234,7 @@ public class SeqPanel extends JPanel */ String seqno = seqIndex == -1 ? "" : " " + (seqIndex + 1); text.append("Sequence").append(seqno).append(" ID: ") - .append(sequence.getName()); + .append(seqName); String residue = null; @@ -1279,7 +1279,8 @@ public class SeqPanel extends JPanel { return; } - SequenceI ds = al.getSequenceAt(sequenceIndex).getDatasetSequence(); + SequenceI alignedSeq = al.getSequenceAt(sequenceIndex); + SequenceI ds = alignedSeq.getDatasetSequence(); for (SearchResultMatchI m : results.getResults()) { SequenceI seq = m.getSequence(); @@ -1291,8 +1292,8 @@ public class SeqPanel extends JPanel if (seq == ds) { int start = m.getStart(); - setStatusMessage(seq, sequenceIndex, seq.getCharAt(start - 1), - start); + setStatusMessage(alignedSeq.getName(), sequenceIndex, + seq.getCharAt(start - 1), start); return; } } diff --git a/src/jalview/io/BackupFiles.java b/src/jalview/io/BackupFiles.java index 0150579..c41bd36 100644 --- a/src/jalview/io/BackupFiles.java +++ b/src/jalview/io/BackupFiles.java @@ -20,19 +20,24 @@ */ package jalview.io; -import jalview.bin.Cache; -import jalview.gui.Desktop; -import jalview.gui.JvOptionPane; -import jalview.util.MessageManager; - import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.TreeMap; +import jalview.bin.Cache; +import jalview.gui.Desktop; +import jalview.gui.JvOptionPane; +import jalview.util.MessageManager; +import jalview.util.Platform; + /* * BackupFiles used for manipulating (naming rolling/deleting) backup/version files when an alignment or project file is saved. * User configurable options are: @@ -95,6 +100,10 @@ public class BackupFiles private static final SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss"); + private static final String newTempFileSuffix = "_newfile"; + + private static final String oldTempFileSuffix = "_oldfile_tobedeleted"; + public BackupFiles(String filename) { this(new File(filename)); @@ -106,7 +115,8 @@ public class BackupFiles { classInit(); this.file = file; - BackupFilesPresetEntry bfpe = BackupFilesPresetEntry.getSavedBackupEntry(); + BackupFilesPresetEntry bfpe = BackupFilesPresetEntry + .getSavedBackupEntry(); this.suffix = bfpe.suffix; this.noMax = bfpe.keepAll; this.max = bfpe.rollMax; @@ -121,30 +131,47 @@ public class BackupFiles { String tempfilename = file.getName(); File tempdir = file.getParentFile(); - temp = File.createTempFile(tempfilename, TEMP_FILE_EXT + "_newfile", - tempdir); + Cache.log.debug( + "BACKUPFILES [file!=null] attempting to create temp file for " + + tempfilename + " in dir " + tempdir); + temp = File.createTempFile(tempfilename, + TEMP_FILE_EXT + newTempFileSuffix, tempdir); + Cache.log.debug( + "BACKUPFILES using temp file " + temp.getAbsolutePath()); } else { + Cache.log.debug( + "BACKUPFILES [file==null] attempting to create default temp file " + + DEFAULT_TEMP_FILE + " with extension " + + TEMP_FILE_EXT); temp = File.createTempFile(DEFAULT_TEMP_FILE, TEMP_FILE_EXT); } } catch (IOException e) { - System.out.println( - "Could not create temp file to save into (IOException)"); + Cache.log + .error("Could not create temp file to save to (IOException)"); + Cache.log.error(e.getMessage()); + Cache.log.debug(e.getStackTrace()); } catch (Exception e) { - System.out.println("Exception ctreating temp file for saving"); + Cache.log.error("Exception ctreating temp file for saving"); + Cache.log.debug(e.getStackTrace()); } this.setTempFile(temp); } public static void classInit() { - setEnabled(Cache.getDefault(ENABLED, true)); + Cache.log.debug("BACKUPFILES classInit"); + boolean e = Cache.getDefault(ENABLED, true); + setEnabled(e); + Cache.log.debug("BACKUPFILES " + (e ? "enabled" : "disabled")); BackupFilesPresetEntry bfpe = BackupFilesPresetEntry .getSavedBackupEntry(); + Cache.log.debug("BACKUPFILES preset scheme " + bfpe.toString()); setConfirmDelete(bfpe.confirmDelete); + Cache.log.debug("BACKUPFILES confirm delete " + bfpe.confirmDelete); } public static void setEnabled(boolean flag) @@ -188,9 +215,10 @@ public class BackupFiles path = this.getTempFile().getCanonicalPath(); } catch (IOException e) { - System.out.println( + Cache.log.error( "IOException when getting Canonical Path of temp file '" + this.getTempFile().getName() + "'"); + Cache.log.debug(e.getStackTrace()); } return path; } @@ -209,7 +237,7 @@ public class BackupFiles public boolean renameTempFile() { - return tempFile.renameTo(file); + return moveFileToFile(tempFile, file); } // roll the backupfiles @@ -226,24 +254,35 @@ public class BackupFiles || suffix.length() == 0) { // nothing to do + Cache.log.debug("BACKUPFILES rollBackupFiles nothing to do." + ", " + + "filename: " + (file != null ? file.getName() : "null") + + ", " + "file exists: " + file.exists() + ", " + "enabled: " + + enabled + ", " + "max: " + max + ", " + "suffix: '" + suffix + + "'"); return true; } + Cache.log.debug("BACKUPFILES rollBackupFiles starting"); + String dir = ""; File dirFile; try { dirFile = file.getParentFile(); dir = dirFile.getCanonicalPath(); + Cache.log.debug("BACKUPFILES dir: " + dir); } catch (Exception e) { - System.out.println( + Cache.log.error( "Could not get canonical path for file '" + file + "'"); + Cache.log.error(e.getMessage()); + Cache.log.debug(e.getStackTrace()); return false; } String filename = file.getName(); String basename = filename; + Cache.log.debug("BACKUPFILES filename is " + filename); boolean ret = true; // Create/move backups up one @@ -255,9 +294,13 @@ public class BackupFiles File[] backupFiles = dirFile.listFiles(bff); int nextIndexNum = 0; + Cache.log + .debug("BACKUPFILES backupFiles.length: " + backupFiles.length); if (backupFiles.length == 0) { // No other backup files. Just need to move existing file to backupfile_1 + Cache.log.debug( + "BACKUPFILES no existing backup files, setting index to 1"); nextIndexNum = 1; } else @@ -270,7 +313,7 @@ public class BackupFiles if (reverseOrder) { // backup style numbering - + Cache.log.debug("BACKUPFILES rolling files in reverse order"); int tempMax = noMax ? -1 : max; // noMax == true means no limits @@ -287,7 +330,7 @@ public class BackupFiles tempMax = i; } } - + File previousFile = null; File fileToBeDeleted = null; for (int n = tempMax; n > 0; n--) @@ -302,6 +345,7 @@ public class BackupFiles // no "oldest" file to delete previousFile = backupfile_n; fileToBeDeleted = null; + Cache.log.debug("BACKUPFILES No oldest file to delete"); continue; } @@ -312,19 +356,23 @@ public class BackupFiles File replacementFile = backupfile_n; long fileToBeDeletedLMT = fileToBeDeleted.lastModified(); long replacementFileLMT = replacementFile.lastModified(); + Cache.log.debug("BACKUPFILES fileToBeDeleted is " + + fileToBeDeleted.getAbsolutePath()); + Cache.log.debug("BACKUPFILES replacementFile is " + + backupfile_n.getAbsolutePath()); try { File oldestTempFile = nextTempFile(fileToBeDeleted.getName(), dirFile); - + if (fileToBeDeletedLMT > replacementFileLMT) { String fileToBeDeletedLMTString = sdf .format(fileToBeDeletedLMT); String replacementFileLMTString = sdf .format(replacementFileLMT); - System.out.println("WARNING! I am set to delete backupfile " + Cache.log.warn("WARNING! I am set to delete backupfile " + fileToBeDeleted.getName() + " has modification time " + fileToBeDeletedLMTString @@ -335,6 +383,11 @@ public class BackupFiles boolean delete = confirmNewerDeleteFile(fileToBeDeleted, replacementFile, true); + Cache.log.debug("BACKUPFILES " + + (delete ? "confirmed" : "not") + " deleting file " + + fileToBeDeleted.getAbsolutePath() + + " which is newer than " + + replacementFile.getAbsolutePath()); if (delete) { @@ -343,21 +396,27 @@ public class BackupFiles } else { - fileToBeDeleted.renameTo(oldestTempFile); + Cache.log.debug("BACKUPFILES moving " + + fileToBeDeleted.getAbsolutePath() + " to " + + oldestTempFile.getAbsolutePath()); + moveFileToFile(fileToBeDeleted, oldestTempFile); } } else { - fileToBeDeleted.renameTo(oldestTempFile); + Cache.log.debug("BACKUPFILES going to move " + + fileToBeDeleted.getAbsolutePath() + " to " + + oldestTempFile.getAbsolutePath()); + moveFileToFile(fileToBeDeleted, oldestTempFile); addDeleteFile(oldestTempFile); } } catch (Exception e) { - System.out.println( + Cache.log.error( "Error occurred, probably making new temp file for '" + fileToBeDeleted.getName() + "'"); - e.printStackTrace(); + Cache.log.error(e.getStackTrace()); } // reset @@ -372,7 +431,9 @@ public class BackupFiles { if (previousFile != null) { - ret = ret && backupfile_n.renameTo(previousFile); + // using boolean '&' instead of '&&' as don't want moveFileToFile + // attempt to be conditional (short-circuit) + ret = ret & moveFileToFile(backupfile_n, previousFile); } } @@ -382,19 +443,37 @@ public class BackupFiles // index to use for the latest backup nextIndexNum = 1; } - else + else // not reverse numbering { // version style numbering (with earliest file deletion if max files // reached) bfTreeMap.values().toArray(backupFiles); + StringBuilder bfsb = new StringBuilder(); + for (int i = 0; i < backupFiles.length; i++) + { + if (bfsb.length() > 0) + { + bfsb.append(", "); + } + bfsb.append(backupFiles[i].getName()); + } + Cache.log.debug("BACKUPFILES backupFiles: " + bfsb.toString()); // noMax == true means keep all backup files if ((!noMax) && bfTreeMap.size() >= max) { + Cache.log.debug("BACKUPFILES noMax: " + noMax + ", " + "max: " + + max + ", " + "bfTreeMap.size(): " + bfTreeMap.size()); // need to delete some files to keep number of backups to designated - // max - int numToDelete = bfTreeMap.size() - max + 1; + // max. + // Note that if the suffix is not numbered then do not delete any + // backup files later or we'll delete the new backup file (there can + // be only one). + int numToDelete = suffix.indexOf(NUM_PLACEHOLDER) > -1 + ? bfTreeMap.size() - max + 1 + : 0; + Cache.log.debug("BACKUPFILES numToDelete: " + numToDelete); // the "replacement" file is the latest backup file being kept (it's // not replacing though) File replacementFile = numToDelete < backupFiles.length @@ -407,6 +486,9 @@ public class BackupFiles File fileToBeDeleted = backupFiles[i]; boolean delete = true; + Cache.log.debug( + "BACKUPFILES fileToBeDeleted: " + fileToBeDeleted); + boolean newer = false; if (replacementFile != null) { @@ -421,14 +503,13 @@ public class BackupFiles String replacementFileLMTString = sdf .format(replacementFileLMT); - System.out - .println("WARNING! I am set to delete backupfile '" - + fileToBeDeleted.getName() - + "' has modification time " + Cache.log.warn("WARNING! I am set to delete backupfile '" + + fileToBeDeleted.getName() + + "' has modification time " + fileToBeDeletedLMTString - + " which is newer than the oldest backupfile being kept '" + + " which is newer than the oldest backupfile being kept '" + replacementFile.getName() - + "' with modification time " + + "' with modification time " + replacementFileLMTString); delete = confirmNewerDeleteFile(fileToBeDeleted, @@ -437,17 +518,23 @@ public class BackupFiles { // User has confirmed delete -- no need to add it to the list fileToBeDeleted.delete(); + Cache.log.debug("BACKUPFILES deleting fileToBeDeleted: " + + fileToBeDeleted); delete = false; } else { // keeping file, nothing to do! + Cache.log.debug("BACKUPFILES keeping fileToBeDeleted: " + + fileToBeDeleted); } } } if (delete) { addDeleteFile(fileToBeDeleted); + Cache.log.debug("BACKUPFILES addDeleteFile(fileToBeDeleted): " + + fileToBeDeleted); } } @@ -462,10 +549,17 @@ public class BackupFiles String latestBackupFilename = dir + File.separatorChar + BackupFilenameParts.getBackupFilename(nextIndexNum, basename, suffix, digits); - ret |= file.renameTo(new File(latestBackupFilename)); - + Cache.log.debug("BACKUPFILES Moving old file [" + file + + "] to latestBackupFilename [" + latestBackupFilename + "]"); + // using boolean '&' instead of '&&' as don't want moveFileToFile attempt to + // be conditional (short-circuit) + ret = ret & moveFileToFile(file, new File(latestBackupFilename)); + Cache.log.debug( + "BACKUPFILES moving " + file + " to " + latestBackupFilename + + " was " + (ret ? "" : "NOT ") + "successful"); if (tidyUp) { + Cache.log.debug("BACKUPFILES tidying up files"); tidyUpFiles(); } @@ -521,7 +615,7 @@ public class BackupFiles saveFile = nextTempFile(ftbd.getName(), ftbd.getParentFile()); } catch (Exception e) { - System.out.println( + Cache.log.error( "Error when confirming to keep backup file newer than other backup files."); e.printStackTrace(); } @@ -529,19 +623,27 @@ public class BackupFiles "label.newerdelete_replacement_line", new String[] { ftbd.getName(), rf.getName(), ftbdLMT, rfLMT, ftbdSize, rfSize })); + // "Backup file\n''{0}''\t(modified {2}, size {4})\nis to be deleted and + // replaced by apparently older file \n''{1}''\t(modified {3}, size + // {5})."" messageSB.append("\n\n"); messageSB.append(MessageManager.formatMessage( "label.confirm_deletion_or_rename", new String[] { ftbd.getName(), saveFile.getName() })); + // "Confirm deletion of ''{0}'' or rename to ''{1}''?" String[] options = new String[] { MessageManager.getString("label.delete"), MessageManager.getString("label.rename") }; - confirmButton = JvOptionPane.showOptionDialog(Desktop.desktop, - messageSB.toString(), - MessageManager.getString("label.backupfiles_confirm_delete"), - JvOptionPane.YES_NO_OPTION, JvOptionPane.WARNING_MESSAGE, - null, options, options[0]); + confirmButton = Platform.isHeadless() ? JvOptionPane.YES_OPTION + : JvOptionPane.showOptionDialog(Desktop.desktop, + messageSB.toString(), + MessageManager.getString( + "label.backupfiles_confirm_delete"), + // "Confirm delete" + JvOptionPane.YES_NO_OPTION, + JvOptionPane.WARNING_MESSAGE, null, options, + options[0]); } else { @@ -549,22 +651,29 @@ public class BackupFiles .formatMessage("label.newerdelete_line", new String[] { ftbd.getName(), rf.getName(), ftbdLMT, rfLMT, ftbdSize, rfSize })); + // "Backup file\n''{0}''\t(modified {2}, size {4})\nis to be deleted but + // is newer than the oldest remaining backup file \n''{1}''\t(modified + // {3}, size {5})." messageSB.append("\n\n"); messageSB.append(MessageManager .formatMessage("label.confirm_deletion", new String[] { ftbd.getName() })); + // "Confirm deletion of ''{0}''?" String[] options = new String[] { MessageManager.getString("label.delete"), MessageManager.getString("label.keep") }; - confirmButton = JvOptionPane.showOptionDialog(Desktop.desktop, - messageSB.toString(), - MessageManager.getString("label.backupfiles_confirm_delete"), - JvOptionPane.YES_NO_OPTION, JvOptionPane.WARNING_MESSAGE, - null, options, options[0]); + confirmButton = Platform.isHeadless() ? JvOptionPane.YES_OPTION + : JvOptionPane.showOptionDialog(Desktop.desktop, + messageSB.toString(), + MessageManager.getString( + "label.backupfiles_confirm_delete"), + // "Confirm delete" + JvOptionPane.YES_NO_OPTION, + JvOptionPane.WARNING_MESSAGE, null, options, + options[0]); } - // return should be TRUE if file is to be deleted return (confirmButton == JvOptionPane.YES_OPTION); } @@ -580,6 +689,8 @@ public class BackupFiles messageSB = new StringBuilder(); messageSB.append(MessageManager .getString("label.backupfiles_confirm_delete_old_files")); + // "Delete the following older backup files? (see the Backups tab in + // Preferences for more options)" for (int i = 0; i < deleteFiles.size(); i++) { File df = deleteFiles.get(i); @@ -590,13 +701,17 @@ public class BackupFiles new String[] { sdf.format(df.lastModified()), Long.toString(df.length()) })); + // "(modified {0}, size {1})" } - int confirmButton = JvOptionPane.showConfirmDialog(Desktop.desktop, - messageSB.toString(), - MessageManager - .getString("label.backupfiles_confirm_delete"), - JvOptionPane.YES_NO_OPTION, JvOptionPane.WARNING_MESSAGE); + int confirmButton = Platform.isHeadless() ? JvOptionPane.YES_OPTION + : JvOptionPane.showConfirmDialog(Desktop.desktop, + messageSB.toString(), + MessageManager.getString( + "label.backupfiles_confirm_delete"), + // "Confirm delete" + JvOptionPane.YES_NO_OPTION, + JvOptionPane.WARNING_MESSAGE); doDelete = (confirmButton == JvOptionPane.YES_OPTION); } @@ -610,8 +725,10 @@ public class BackupFiles for (int i = 0; i < deleteFiles.size(); i++) { File fileToDelete = deleteFiles.get(i); + Cache.log.debug( + "BACKUPFILES deleting fileToDelete:" + fileToDelete); fileToDelete.delete(); - System.out.println("DELETING '" + fileToDelete.getName() + "'"); + Cache.log.warn("deleting '" + fileToDelete.getName() + "'"); } } @@ -621,8 +738,7 @@ public class BackupFiles } private TreeMap sortBackupFilesAsTreeMap( - File[] backupFiles, - String basename) + File[] backupFiles, String basename) { // sort the backup files (based on integer found in the suffix) using a // precomputed Hashmap for speed @@ -647,7 +763,7 @@ public class BackupFiles boolean rename = false; if (write) { - roll = this.rollBackupFiles(false); + roll = this.rollBackupFiles(false); // tidyUpFiles at the end rename = this.renameTempFile(); } @@ -660,8 +776,11 @@ public class BackupFiles boolean okay = roll && rename; if (!okay) { + boolean yesno = false; StringBuilder messageSB = new StringBuilder(); - messageSB.append(MessageManager.getString( "label.backupfiles_confirm_save_file_backupfiles_roll_wrong")); + messageSB.append(MessageManager.getString( + "label.backupfiles_confirm_save_file_backupfiles_roll_wrong")); + // "Something possibly went wrong with the backups of this file." if (rename) { if (messageSB.length() > 0) @@ -670,6 +789,7 @@ public class BackupFiles } messageSB.append(MessageManager.getString( "label.backupfiles_confirm_save_new_saved_file_ok")); + // "The new saved file seems okay." } else { @@ -679,13 +799,16 @@ public class BackupFiles } messageSB.append(MessageManager.getString( "label.backupfiles_confirm_save_new_saved_file_not_ok")); + // "The new saved file might not be okay." } - int confirmButton = JvOptionPane.showConfirmDialog(Desktop.desktop, - messageSB.toString(), - MessageManager - .getString("label.backupfiles_confirm_save_file"), - JvOptionPane.OK_OPTION, JvOptionPane.WARNING_MESSAGE); + int confirmButton = Platform.isHeadless() ? JvOptionPane.OK_OPTION + : JvOptionPane.showConfirmDialog(Desktop.desktop, + messageSB.toString(), + MessageManager.getString( + "label.backupfiles_confirm_save_file"), + // "Confirm save file" + JvOptionPane.OK_OPTION, JvOptionPane.WARNING_MESSAGE); okay = confirmButton == JvOptionPane.OK_OPTION; } if (okay) @@ -709,7 +832,7 @@ public class BackupFiles dirFile = file.getParentFile(); } catch (Exception e) { - System.out.println( + Cache.log.error( "Could not get canonical path for file '" + file + "'"); return new TreeMap<>(); } @@ -751,13 +874,48 @@ public class BackupFiles int pos = deleteFiles.indexOf(fileToBeDeleted); if (pos > -1) { + Cache.log.debug("BACKUPFILES not adding file " + + fileToBeDeleted.getAbsolutePath() + + " to the delete list (already at index" + pos + ")"); return true; } else { + Cache.log.debug("BACKUPFILES adding file " + + fileToBeDeleted.getAbsolutePath() + " to the delete list"); deleteFiles.add(fileToBeDeleted); } return ret; } + public static boolean moveFileToFile(File oldFile, File newFile) + { + boolean ret = false; + Path oldPath = Paths.get(oldFile.getAbsolutePath()); + Path newPath = Paths.get(newFile.getAbsolutePath()); + try + { + // delete destination file - not usually necessary but Just In Case... + Cache.log.debug("BACKUPFILES deleting " + newFile.getAbsolutePath()); + newFile.delete(); + Cache.log.debug("BACKUPFILES moving " + oldFile.getAbsolutePath() + + " to " + newFile.getAbsolutePath()); + Files.move(oldPath, newPath, StandardCopyOption.REPLACE_EXISTING); + ret = true; + Cache.log.debug("BACKUPFILES move seems to have succeeded"); + } catch (IOException e) + { + Cache.log.warn("Could not move file '" + oldPath.toString() + "' to '" + + newPath.toString() + "'"); + Cache.log.error(e.getMessage()); + Cache.log.debug(e.getStackTrace()); + ret = false; + } catch (Exception e) + { + Cache.log.error(e.getMessage()); + Cache.log.debug(e.getStackTrace()); + ret = false; + } + return ret; + } } diff --git a/src/jalview/io/BackupFilesPresetEntry.java b/src/jalview/io/BackupFilesPresetEntry.java index 69130d0..0734665 100644 --- a/src/jalview/io/BackupFilesPresetEntry.java +++ b/src/jalview/io/BackupFilesPresetEntry.java @@ -20,13 +20,13 @@ */ package jalview.io; -import jalview.bin.Cache; -import jalview.util.MessageManager; - import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; +import jalview.bin.Cache; +import jalview.util.MessageManager; + public class BackupFilesPresetEntry { @@ -135,6 +135,8 @@ public class BackupFilesPresetEntry { String savedPresetString = Cache .getDefault(BackupFilesPresetEntry.SAVEDCONFIG, null); + Cache.log.debug("BACKUPFILESPRESETENTRY saved preset string is " + + savedPresetString); BackupFilesPresetEntry savedPreset = BackupFilesPresetEntry .createBackupFilesPresetEntry(savedPresetString); if (savedPreset == null) diff --git a/src/jalview/ws/sifts/SiftsClient.java b/src/jalview/ws/sifts/SiftsClient.java index b5f9653..9790f79 100644 --- a/src/jalview/ws/sifts/SiftsClient.java +++ b/src/jalview/ws/sifts/SiftsClient.java @@ -20,28 +20,6 @@ */ package jalview.ws.sifts; -import jalview.analysis.AlignSeq; -import jalview.analysis.scoremodels.ScoreMatrix; -import jalview.analysis.scoremodels.ScoreModels; -import jalview.api.DBRefEntryI; -import jalview.api.SiftsClientI; -import jalview.datamodel.DBRefEntry; -import jalview.datamodel.DBRefSource; -import jalview.datamodel.SequenceI; -import jalview.io.StructureFile; -import jalview.schemes.ResidueProperties; -import jalview.structure.StructureMapping; -import jalview.util.Comparison; -import jalview.util.DBRefUtils; -import jalview.util.Format; -import jalview.xml.binding.sifts.Entry; -import jalview.xml.binding.sifts.Entry.Entity; -import jalview.xml.binding.sifts.Entry.Entity.Segment; -import jalview.xml.binding.sifts.Entry.Entity.Segment.ListMapRegion.MapRegion; -import jalview.xml.binding.sifts.Entry.Entity.Segment.ListResidue.Residue; -import jalview.xml.binding.sifts.Entry.Entity.Segment.ListResidue.Residue.CrossRefDb; -import jalview.xml.binding.sifts.Entry.Entity.Segment.ListResidue.Residue.ResidueDetail; - import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -73,6 +51,28 @@ import javax.xml.stream.XMLStreamReader; import MCview.Atom; import MCview.PDBChain; +import jalview.analysis.AlignSeq; +import jalview.analysis.scoremodels.ScoreMatrix; +import jalview.analysis.scoremodels.ScoreModels; +import jalview.api.DBRefEntryI; +import jalview.api.SiftsClientI; +import jalview.datamodel.DBRefEntry; +import jalview.datamodel.DBRefSource; +import jalview.datamodel.SequenceI; +import jalview.io.BackupFiles; +import jalview.io.StructureFile; +import jalview.schemes.ResidueProperties; +import jalview.structure.StructureMapping; +import jalview.util.Comparison; +import jalview.util.DBRefUtils; +import jalview.util.Format; +import jalview.xml.binding.sifts.Entry; +import jalview.xml.binding.sifts.Entry.Entity; +import jalview.xml.binding.sifts.Entry.Entity.Segment; +import jalview.xml.binding.sifts.Entry.Entity.Segment.ListMapRegion.MapRegion; +import jalview.xml.binding.sifts.Entry.Entity.Segment.ListResidue.Residue; +import jalview.xml.binding.sifts.Entry.Entity.Segment.ListResidue.Residue.CrossRefDb; +import jalview.xml.binding.sifts.Entry.Entity.Segment.ListResidue.Residue.ResidueDetail; public class SiftsClient implements SiftsClientI { @@ -123,6 +123,7 @@ public class SiftsClient implements SiftsClientI private enum CoordinateSys { UNIPROT("UniProt"), PDB("PDBresnum"), PDBe("PDBe"); + private String name; private CoordinateSys(String name) @@ -140,6 +141,7 @@ public class SiftsClient implements SiftsClientI { NAME_SEC_STRUCTURE("nameSecondaryStructure"), CODE_SEC_STRUCTURE("codeSecondaryStructure"), ANNOTATION("Annotation"); + private String code; private ResidueDetailType(String code) @@ -225,7 +227,7 @@ public class SiftsClient implements SiftsClientI SiftsSettings.getCacheThresholdInDays())) { File oldSiftsFile = new File(siftsFileName + "_old"); - siftsFile.renameTo(oldSiftsFile); + BackupFiles.moveFileToFile(siftsFile, oldSiftsFile); try { siftsFile = downloadSiftsFile(pdbId.toLowerCase()); @@ -234,7 +236,7 @@ public class SiftsClient implements SiftsClientI } catch (IOException e) { e.printStackTrace(); - oldSiftsFile.renameTo(siftsFile); + BackupFiles.moveFileToFile(oldSiftsFile, siftsFile); return new File(siftsFileName); } } @@ -461,7 +463,7 @@ public class SiftsClient implements SiftsClientI SequenceI seq, java.io.PrintStream os) throws SiftsException { List omitNonObserved = new ArrayList<>(); - int nonObservedShiftIndex = 0,pdbeNonObserved=0; + int nonObservedShiftIndex = 0, pdbeNonObserved = 0; // System.out.println("Generating mappings for : " + entityId); Entity entity = null; entity = getEntityById(entityId); @@ -492,7 +494,7 @@ public class SiftsClient implements SiftsClientI TreeMap resNumMap = new TreeMap(); List segments = entity.getSegment(); SegmentHelperPojo shp = new SegmentHelperPojo(seq, mapping, resNumMap, - omitNonObserved, nonObservedShiftIndex,pdbeNonObserved); + omitNonObserved, nonObservedShiftIndex, pdbeNonObserved); processSegments(segments, shp); try { @@ -514,18 +516,20 @@ public class SiftsClient implements SiftsClientI { throw new SiftsException("SIFTS mapping failed"); } - // also construct a mapping object between the seq-coord sys and the PDB seq's coord sys + // also construct a mapping object between the seq-coord sys and the PDB + // seq's coord sys Integer[] keys = mapping.keySet().toArray(new Integer[0]); Arrays.sort(keys); seqStart = keys[0]; seqEnd = keys[keys.length - 1]; - List from=new ArrayList<>(),to=new ArrayList<>(); - int[]_cfrom=null,_cto=null; + List from = new ArrayList<>(), to = new ArrayList<>(); + int[] _cfrom = null, _cto = null; String matchedSeq = originalSeq; - if (seqStart != UNASSIGNED) // fixme! seqStart can map to -1 for a pdb sequence that starts <-1 + if (seqStart != UNASSIGNED) // fixme! seqStart can map to -1 for a pdb + // sequence that starts <-1 { - for (int seqps:keys) + for (int seqps : keys) { int pdbpos = mapping.get(seqps)[PDBE_POS]; if (pdbpos == UNASSIGNED) @@ -533,19 +537,23 @@ public class SiftsClient implements SiftsClientI // not correct - pdbpos might be -1, but leave it for now continue; } - if (_cfrom==null || seqps!=_cfrom[1]+1) + if (_cfrom == null || seqps != _cfrom[1] + 1) { - _cfrom = new int[] { seqps,seqps}; + _cfrom = new int[] { seqps, seqps }; from.add(_cfrom); _cto = null; // discontinuity - } else { - _cfrom[1]= seqps; } - if (_cto==null || pdbpos!=1+_cto[1]) + else + { + _cfrom[1] = seqps; + } + if (_cto == null || pdbpos != 1 + _cto[1]) { - _cto = new int[] { pdbpos,pdbpos}; + _cto = new int[] { pdbpos, pdbpos }; to.add(_cto); - } else { + } + else + { _cto[1] = pdbpos; } } @@ -567,8 +575,7 @@ public class SiftsClient implements SiftsClientI ; seqFromPdbMapping = new jalview.datamodel.Mapping(null, _cto, _cfrom, - 1, - 1); + 1, 1); pdbStart = mapping.get(seqStart)[PDB_RES_POS]; pdbEnd = mapping.get(seqEnd)[PDB_RES_POS]; int orignalSeqStart = seq.getStart(); @@ -699,12 +706,12 @@ public class SiftsClient implements SiftsClientI } // if (currSeqIndex >= seq.getStart() && currSeqIndex <= seqlength) // // true - // numbering - // is - // not - // up - // to - // seq.getEnd() + // numbering + // is + // not + // up + // to + // seq.getEnd() { int resNum = (pdbRefDb == null) @@ -1044,6 +1051,7 @@ public class SiftsClient implements SiftsClientI { return pdbeNonObserved; } + public SequenceI getSeq() { return seq; diff --git a/test/jalview/datamodel/SearchResultsTest.java b/test/jalview/datamodel/SearchResultsTest.java index 349b5d1..a302d6e 100644 --- a/test/jalview/datamodel/SearchResultsTest.java +++ b/test/jalview/datamodel/SearchResultsTest.java @@ -25,14 +25,14 @@ import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertSame; import static org.testng.AssertJUnit.assertTrue; -import jalview.gui.JvOptionPane; - import java.util.BitSet; import org.junit.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import jalview.gui.JvOptionPane; + public class SearchResultsTest { @@ -303,4 +303,68 @@ public class SearchResultsTest sr.addResult(seq1, 3, 6); assertEquals(2, sr.getSize()); } + + /** + * Test for method that checks if search results matches a sequence region + */ + @Test(groups = { "Functional" }) + public void testInvolvesSequence() + { + SequenceI dataset = new Sequence("genome", "ATGGCCCTTTAAGCAACATTT"); + // first 'exon': + SequenceI cds1 = new Sequence("cds1/1-12", "ATGGCCCTTTAA"); + cds1.setDatasetSequence(dataset); + // overlapping second 'exon': + SequenceI cds2 = new Sequence("cds2/7-18", "CTTTAAGCAACA"); + cds2.setDatasetSequence(dataset); + // unrelated sequence + SequenceI cds3 = new Sequence("cds3", "ATGGCCCTTTAAGCAACA"); + + SearchResults sr = new SearchResults(); + assertFalse(sr.involvesSequence(cds1)); + + /* + * cds1 and cds2 share the same dataset sequence, but + * only cds1 overlaps match 4:6 (fixes bug JAL-3613) + */ + sr.addResult(dataset, 4, 6); + assertTrue(sr.involvesSequence(cds1)); + assertFalse(sr.involvesSequence(cds2)); + assertFalse(sr.involvesSequence(cds3)); + + /* + * search results overlap cds2 only + */ + sr = new SearchResults(); + sr.addResult(dataset, 18, 18); + assertFalse(sr.involvesSequence(cds1)); + assertTrue(sr.involvesSequence(cds2)); + + /* + * add a search result overlapping cds1 + */ + sr.addResult(dataset, 1, 1); + assertTrue(sr.involvesSequence(cds1)); + assertTrue(sr.involvesSequence(cds2)); + + /* + * single search result overlapping both + */ + sr = new SearchResults(); + sr.addResult(dataset, 10, 12); + assertTrue(sr.involvesSequence(cds1)); + assertTrue(sr.involvesSequence(cds2)); + + /* + * search results matching aligned sequence + */ + sr = new SearchResults(); + sr.addResult(cds1, 10, 12); + assertTrue(sr.involvesSequence(cds1)); + assertFalse(sr.involvesSequence(cds2)); + sr.addResult(cds2, 1, 3); // no start-end overlap + assertFalse(sr.involvesSequence(cds2)); + sr.addResult(cds2, 7, 9); // start-end overlap + assertTrue(sr.involvesSequence(cds2)); + } }