Merge branch 'Jalview-JS/develop' into develop
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 18 May 2020 09:59:52 +0000 (10:59 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 18 May 2020 09:59:52 +0000 (10:59 +0100)
Conflicts:
build.gradle
src/jalview/gui/PopupMenu.java
src/jalview/io/SequenceAnnotationReport.java
src/jalview/io/StockholmFile.java
src/jalview/util/DBRefUtils.java
src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java

79 files changed:
doc/building.md
examples/groovy/ComputePeptideVariants.groovy [new file with mode: 0644]
help/help/help.jhm
help/help/helpTOC.xml
help/help/html/features/importvcf.html
help/help/html/features/seqfeaturereport.html [new file with mode: 0644]
help/help/html/features/seqfeaturesrep.png [new file with mode: 0644]
help/help/html/features/splitView.html
help/help/html/menus/popupMenu.html
help/help/html/releases.html
help/help/html/whatsNew.html
src/jalview/analysis/GeneticCodeI.java
src/jalview/analysis/GeneticCodes.java
src/jalview/api/FinderI.java
src/jalview/appletgui/APopupMenu.java
src/jalview/bin/GetMemory.java
src/jalview/bin/JalviewTaskbar.java
src/jalview/bin/Launcher.java
src/jalview/bin/MemorySetting.java
src/jalview/datamodel/GeneLociI.java
src/jalview/datamodel/GeneLocus.java
src/jalview/datamodel/MappedFeatures.java
src/jalview/datamodel/Point.java
src/jalview/datamodel/SearchResults.java
src/jalview/datamodel/SequenceFeature.java
src/jalview/datamodel/features/FeatureAttributeType.java
src/jalview/datamodel/features/FeatureAttributes.java
src/jalview/datamodel/features/FeatureMatcher.java
src/jalview/datamodel/features/FeatureMatcherI.java
src/jalview/datamodel/features/FeatureMatcherSet.java
src/jalview/datamodel/features/FeatureMatcherSetI.java
src/jalview/datamodel/features/FeatureSource.java
src/jalview/datamodel/features/FeatureSourceI.java
src/jalview/datamodel/features/FeatureSources.java
src/jalview/ext/android/ContainerHelpers.java
src/jalview/ext/android/SparseDoubleArray.java
src/jalview/ext/android/SparseIntArray.java
src/jalview/ext/android/SparseShortArray.java
src/jalview/ext/ensembl/EnsemblInfo.java
src/jalview/ext/ensembl/EnsemblMap.java
src/jalview/ext/htsjdk/VCFReader.java
src/jalview/gui/APQHandlers.java
src/jalview/gui/IdPanel.java
src/jalview/gui/JalviewBooleanRadioButtons.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/SeqPanel.java
src/jalview/io/BackupFilenameFilter.java
src/jalview/io/BackupFilenameParts.java
src/jalview/io/BackupFiles.java
src/jalview/io/BackupFilesPresetEntry.java
src/jalview/io/FeaturesFile.java
src/jalview/io/IntKeyStringValueEntry.java
src/jalview/io/SequenceAnnotationReport.java
src/jalview/io/StockholmFile.java
src/jalview/io/vcf/VCFLoader.java
src/jalview/renderer/seqfeatures/FeatureRenderer.java
src/jalview/util/DBRefUtils.java
src/jalview/util/JSONUtils.java
src/jalview/util/MathUtils.java
src/jalview/util/ShortcutKeyMaskExWrapper.java
src/jalview/util/ShortcutKeyMaskExWrapper11.java
src/jalview/util/ShortcutKeyMaskExWrapper8.java
src/jalview/util/ShortcutKeyMaskExWrapperI.java
src/jalview/util/matcher/Condition.java
src/jalview/util/matcher/Matcher.java
src/jalview/util/matcher/MatcherI.java
src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java
test/jalview/datamodel/SearchResultsTest.java
test/jalview/datamodel/SequenceFeatureTest.java
test/jalview/datamodel/features/FeatureMatcherTest.java
test/jalview/gui/FeatureSettingsTest.java
test/jalview/gui/FreeUpMemoryTest.java
test/jalview/io/FeaturesFileTest.java
test/jalview/io/SequenceAnnotationReportTest.java
test/jalview/io/StockholmFileTest.java
test/jalview/project/Jalview2xmlTests.java
test/jalview/util/DBRefUtilsTest.java
test/jalview/util/matcher/MatcherTest.java
utils/install4j/install4j8_template.install4j

index 398181a..ad19979 100644 (file)
@@ -165,6 +165,7 @@ Within the `jalview` folder you will find (of possible interest):
  `utils/install4j/`  | files used by the packaging tool, install4j
  `build.gradle`      | the build file used by gradle
  `gradle.properties` | configurable properties for the build process
+ `RELEASE`          | propertyfile configuring JALVIEW_VERSION (from jalview.version) and the release branch (from jalview.release). An alternative file can be specified via JALVIEW_RELEASE_FILE property
 
 Note that you need a Java 11 JDK to compile Jalview whether your target build is Java 1.8 or Java 11.
 
@@ -422,7 +423,7 @@ There are several values of `CHANNEL` that can be chosen, with a default of `LOC
       Note that bamboo_planKey should be set by the build plan with `-Pbamboo_planKey=${bamboo.planKey}`
     - application subdir as `alt`
     - Getdown launcher cannot use a `file://` scheme appbase. 
-* `DEVELOP`: This is for creating a `develop` appbase channel on the main web server.  This won't become live until the actual getdown artefact is synced to the web server.
+* `DEVELOP`: This is for creating a `develop` appbase channel on the main web server. This won't become live until the actual getdown artefact is synced to the web server.
   It will set
     - `appbase` as `http://www.jalview.org/getdown/develop/JAVA_VERSION`
     - application subdir as `alt`
@@ -465,6 +466,13 @@ e.g.
 gradle getdown -PCHANNEL=SCRATCH-my_test_version
 ```
 
+#### JALVIEW_VERSION and the RELEASE file
+Any Jalview build will include the value of JALVIEW_VERSION in various places, including the 'About' and Jalview Desktop window title, and in filenames for the stand-alone executable jar. You can specify a custom version for a build via the JALVIEW_VERSION property, but for most situations, JALVIEW_VERSION will be automatically configured according to the value of the CHANNEL property, using the `jalview.version` property specified in the RELEASE file:
+  - `CHANNEL=RELEASE` will set version to jalview.version
+  - `CHANNEL=TEST or DEVELOP` will append '-test' or '-develop' to jalview.version
+  
+It is also possible to specify a custom location for the RELEASE file via an optional JALVIEW_RELEASE_FILE property.
+
 #### `install4jMediaTypes`
 If you are building *install4j* installers (requires *install4j* to be installed) then this property specifies a comma-separated 
 list of media types (i.e. platform specific installers) *install4j* should actually build.
diff --git a/examples/groovy/ComputePeptideVariants.groovy b/examples/groovy/ComputePeptideVariants.groovy
new file mode 100644 (file)
index 0000000..6caa69c
--- /dev/null
@@ -0,0 +1,32 @@
+import jalview.datamodel.SequenceFeature
+import jalview.gui.Desktop
+def af = jalview.bin.Jalview.currentAlignFrame
+def av = af.viewport
+def fr = Desktop.getAlignFrameFor(av.codingComplement).getFeatureRenderer()
+def counts = 0
+def countm = 0
+for (seq in av.alignment.sequences) 
+{
+   ds = seq.datasetSequence
+   for (res = ds.start ; res <= ds.end; res++) 
+   {
+     mf = fr.findComplementFeaturesAtResidue(seq, res)
+     if (mf != null)
+     {
+         for (feature in mf.features)
+         {
+           variant = mf.findProteinVariants(feature)
+           if (!"".equals(variant))
+           {
+               type = variant.contains("=") ? "synonymous_variant" : "missense_variant"
+               if (type.equals("synonymous_variant")) counts++ else countm++;
+               sf = new SequenceFeature(type, variant, res, res, null)
+               seq.addSequenceFeature(sf)
+           }
+         }
+     }
+   }
+}
+af.getFeatureRenderer().featuresAdded()
+af.alignPanel.paintAlignment(true, true)
+println "Added " + countm + " missense and " + counts + " synonymous variants"
\ No newline at end of file
index aecd1a4..99d010d 100755 (executable)
@@ -47,6 +47,7 @@
    <mapID target="seqfeatures" url="html/features/seqfeatures.html"/>
    <mapID target="seqfeatedit" url="html/features/editingFeatures.html"/>
    <mapID target="seqfeatcreat" url="html/features/creatinFeatures.html"/>
+   <mapID target="seqfeatures.report" url="html/features/seqfeaturereport.html"/>
    <mapID target="seqfeatures.settings" url="html/features/featuresettings.html"/>
    <mapID target="seqfeatures.settings.selcols" url="html/features/featuresettings.html#selectbyfeature"/>
    <mapID target="viewingpdbs" url="html/features/viewingpdbs.html"/>
index 5802ddb..a0c7fe6 100755 (executable)
@@ -63,6 +63,7 @@
                        <tocitem text="Feature Colourschemes" target="features.featureschemes" />
                        <tocitem text="User Defined Sequence Features" target="seqfeatcreat" />
                        <tocitem text="Editing Sequence Features" target="seqfeatedit" />
+                       <tocitem text="HTML Feature Attributes report" target="seqfeatures.report" />
                        <tocitem text="HTML annotation report" target="io.seqreport" />
                </tocitem>
                
index 511ff2e..7b699eb 100755 (executable)
     for more information.
   </p>
   <p>
+    <strong>Working with variants without CSQ fields</strong>
+  </p>
+  <p>
+    <a name="computepepvariants">Jalview 2.11.1's new virtual
+      features</a> mean that peptide sequences are no longer annotated
+    directly with protein missense variants. This makes it harder to
+    filter variants when they do not already include the CSQ field. You
+    can rescue the pre-2.11.1 functionality by:
+  </p>
+  <ol>
+    <li>Download the script at
+      https://www.jalview.org/examples/groovy/ComputePeptideVariants.groovy</li>
+    <li>Executing the script via the <a href="groovy.html">Groovy
+        Console</a> on a linked CDS/Protein view to create missense and
+      synonymous peptide variant features.
+    </li>
+  </ol>
+  <p>
     <strong>Working with variants from organisms other than
       H.sapiens.</strong>
   </p>
diff --git a/help/help/html/features/seqfeaturereport.html b/help/help/html/features/seqfeaturereport.html
new file mode 100644 (file)
index 0000000..340df5c
--- /dev/null
@@ -0,0 +1,54 @@
+<html>
+<!--
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ -->
+<head>
+<title>Sequence Feature Reports</title>
+</head>
+<body>
+  <p>
+    <strong>Sequence Feature Reports</strong> <br /> Sequence features
+    can carry a number of attributes. To view all the attributes for a
+    particular sequence feature, mouse over the feature and <em>right-click</em>
+    to open the <a href="../menus/popupMenu.html#featuredetails">Popup Menu</a> and
+    select the feature's entry from the <em>Feature Details</em>
+    submenu.
+  </p>
+  <img src="seqfeaturesrep.png" width="460"
+    alt="Full details for a particular Sequence Feature can be displayed as HTML in a report window" />
+  <p>
+    <em>Virtual Feature Reports</em><br /> When a sequence feature
+    report is shown for features mapped between CDS and Protein
+    sequences, the report will include both the original and mapped
+    feature's location.
+  </p>
+  <p>
+    <strong>Copying and pasting annotation to other programs</strong><br>
+    The <strong>File&rarr;Save</strong> option in the sequence
+    annotation report window allows the report to be saved as HTML,
+    which will preserve links and any other metadata. It is also
+    possible to copy and paste the text to other programs, but in some
+    cases, the HTML will not be preserved. In that case, you can toggle
+    the display of HTML source code with the <strong>Edit&rarr;Show
+      HTML Source</strong> drop down menu entry.
+  </p>
+  <em>Feature Reports were added in Jalview 2.11.</em>
+</body>
+</html>
diff --git a/help/help/html/features/seqfeaturesrep.png b/help/help/html/features/seqfeaturesrep.png
new file mode 100644 (file)
index 0000000..f5995a1
Binary files /dev/null and b/help/help/html/features/seqfeaturesrep.png differ
index 03b9ced..bb379ed 100644 (file)
       settings tabs and corresponding views showing 'Virtual Features'
       from each view overlaid on the other (created with Jalview 2.11.1.0).</em>
   </p>
-  <p>When virtual features are enabled, they are also shown on any
-    linked 3D structure views when 'Colour by Sequence' is enabled, and
+  <p>
+    When virtual features are enabled, they are also shown on any linked
+    3D structure views when 'Colour by Sequence' is enabled, and
     exported as GFF and Jalview Features files (mapped to their
-    associated virtual coordinates).</p>
+    associated virtual coordinates). Both the original and the mapped
+    locations are also included in <a href="seqfeaturereport.html">Sequence
+      Feature Reports</a>.
+  </p>
   <p>
     <strong>Operations supported in Split Frame Mode</strong>
   </p>
index 7625606..9c65e1a 100755 (executable)
   <p>
     <strong>Popup Menu</strong><br> <em>This menu is visible
       when right clicking either within a selected region on the
-      alignment or on a selected sequence name. It may not be accessible
+      alignment, on a sequence name, and also when right-clicking a sequence feature. It may not be accessible
       when in 'Cursor Mode' (toggled with the F2 key).</em><br /> <em><strong>Mac
         Users:</strong> pressing CTRL whilst clicking the mouse/track pad is the
       same as a right-click. See your system's settings to configure
       your track-pad's corners to generate right-clicks.</em>
   </p>
   <ul>
-    <li><strong>Selection</strong>
+    <li><strong>Selection<br/></strong>
+    <em>This menu is only visible when right-clicking a selected sequence or region of the alignment. </em>
       <ul>
         <li><a name="sqreport"><strong>Sequence
               Details...<br>
         according to gaps in just the current sequence)</em></li>
     <li><strong>Hide Sequences</strong><br> <em>Hides the
         currently selected sequences in this alignment view.</em><strong><br>
-    </strong></li>
+    </strong><br/>&nbsp;<br/></li>
+    
+    <li><strong><a name="featuredetails"> Feature Details</a><br /></strong>
+    <em>Each entry opens a <a
+      href="../features/seqfeaturereport.html">Sequence Feature
+        Report</a> for visible features under the mouse.<br />Only visible
+      when right-clicking a region where <a
+      href="../features/seqfeatures.html">Sequence Features</a> are
+      shown.
+    </em>
+  </li>
   </ul>
+  
 </body>
 </html>
index 0097655..5b6180d 100755 (executable)
@@ -58,13 +58,15 @@ li:before {
     <tr>
       <td width="60" align="center" nowrap><strong><a
           id="Jalview.2.11.1">2.11.1</a><a id="Jalview.2.11.1.0">.0</a><br />
-          <em>9/04/2020</em></strong></td>
+          <em>22/04/2020</em></strong></td>
       <td align="left" valign="top">
         <ul>
           <li>
-            <!-- JAL-3187,JAL-3305,JAL-3304,JAL-3302 -->Map 'virtual'
-            codon features shown on protein (or vice versa) for display
-            in alignments, on structure views and for export.
+            <!-- JAL-3187,JAL-3305,JAL-3304,JAL-3302,JAL-3567 -->Map
+            'virtual' codon features shown on protein (or vice versa)
+            for display in alignments, on structure views (including
+            transfer to UCSF chimera), in feature reports and for
+            export.
           </li>
           <li>
             <!-- JAL-3121 -->Feature attributes from VCF files can be
@@ -98,6 +100,9 @@ li:before {
             <!-- JAL-3549 -->Warn if Sort by Score or Density attempted
             with no feature types visible
           </li>
+          <li>
+          <!-- JAL-3574 -->Improved support for filtering feature attributes with large integer values
+          </li>
         </ul><em>Jalview Installer</em>
            <ul>
           <li>
@@ -139,6 +144,11 @@ li:before {
             to stdout containing the consensus sequence for each
             alignment in a Jalview session
           </li>
+          <li>
+            <!-- JAL-3578 -->ComputePeptideVariants.groovy to translate
+            genomic sequence_variant annotation from CDS as
+            missense_variant or synonymous_variant on protein products.
+          </li>
         </ul>
       </td>
       <td align="left" valign="top">
@@ -148,6 +158,11 @@ li:before {
             'Show hidden markers' option is not ticked
           </li>
           <li>
+            <!-- JAL-247 -->Hidden sequence markers not shown in EPS and
+            PNG output when 'Automatically set ID width' is set in
+            jalview preferences or properties file
+          </li>
+          <li>
             <!-- JAL-3571 -->Feature Editor dialog can be opened when
             'Show Sequence Features' option is not ticked
           </li>
@@ -201,6 +216,11 @@ li:before {
             <!-- JAL-3406 -->Credits missing some authors in Jalview
             help documentation for 2.11.0 release
           </li>
+          <li>
+            <!-- JAL-3529 -->Export of Pfam alignment as Stockholm
+            includes Pfam ID as sequence's accession rather than its
+            Uniprot Accession
+          </li>
         </ul> <em>Java 11 Compatibility issues</em>
         <ul>
           <li>
index 00f9466..0f0c7f1 100755 (executable)
       <a href="features/splitView.html#virtualfeats">Sequence
         Features dialog</a>. This allows more analyses of nucleotide and
       peptide sequence features on alignments in a more flexible and
-      memory efficient way than in earlier versions.</li>
+      memory efficient way than in earlier versions.<br />
+    <em>Note: Virtual features work best when variants are
+        annotated with CSQ fields. Please <a
+        href="features/importvcf.html#computepepvariants">see this
+          Groovy script workaround</a> if you are working with VCF files
+        without CSQ fields.
+    </em></li>
     <li><strong>Improved VCF data import</strong><br /> <a
       href="features/importvcf.html#attribs">Standard attributes for
         filtering variants</a> (e.g. position, QUAL field etc) are now
index daed0ac..228ea30 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.analysis;
 
 public interface GeneticCodeI
index 137b7f8..df1dd82 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.analysis;
 
 import jalview.bin.Cache;
index 19f6136..71b35ef 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.api;
 
 import jalview.datamodel.SearchResultsI;
index 3aed7ec..e1bfbde 100644 (file)
  */
 package jalview.appletgui;
 
+import java.awt.CheckboxMenuItem;
+import java.awt.Frame;
+import java.awt.Menu;
+import java.awt.MenuItem;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.Vector;
+
 import jalview.analysis.AAFrequency;
 import jalview.analysis.AlignmentAnnotationUtils;
 import jalview.analysis.AlignmentUtils;
@@ -57,25 +76,6 @@ import jalview.schemes.ZappoColourScheme;
 import jalview.util.MessageManager;
 import jalview.util.UrlLink;
 
-import java.awt.CheckboxMenuItem;
-import java.awt.Frame;
-import java.awt.Menu;
-import java.awt.MenuItem;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.Vector;
-
 public class APopupMenu extends java.awt.PopupMenu
         implements ActionListener, ItemListener
 {
@@ -900,7 +900,7 @@ public class APopupMenu extends java.awt.PopupMenu
       contents.append(MessageManager
               .formatMessage("label.annotation_for_displayid", new Object[]
               { seq.getDisplayId(true) }));
-      new SequenceAnnotationReport(null).createSequenceAnnotationReport(
+      new SequenceAnnotationReport(false).createSequenceAnnotationReport(
               contents, seq, true, true, ap.seqPanel.seqCanvas.fr);
       contents.append("</p>");
     }
index e89bffb..b01dfb8 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.bin;
 
 import java.lang.management.ManagementFactory;
index 7dd0382..da83a09 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.bin;
 
 import java.awt.Image;
index 1541615..fb1c5cd 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.bin;
 
 import java.io.File;
index 7849ba2..159374a 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.bin;
 
 /**
index 09db9d7..732fd1e 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel;
 
 import jalview.util.MapList;
index f81348f..5a98c63 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel;
 
 import jalview.util.MapList;
index 0fa03cf..d652a97 100644 (file)
@@ -1,14 +1,35 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel;
 
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
 import jalview.io.gff.Gff3Helper;
 import jalview.schemes.ResidueProperties;
+import jalview.util.MapList;
 import jalview.util.MappingUtils;
 import jalview.util.StringUtils;
 
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
 /**
  * A data bean to hold a list of mapped sequence features (e.g. CDS features
  * mapped from protein), and the mapping between the sequences. It also provides
@@ -18,22 +39,26 @@ import java.util.Set;
  */
 public class MappedFeatures
 {
+  /*
+   * VEP CSQ:HGVSp (if present) is a short-cut to the protein variant consequence
+   */
   private static final String HGV_SP = "HGVSp";
 
   private static final String CSQ = "CSQ";
 
   /*
-   * the mapping from one sequence to another
+   * the sequence the mapped features are on
    */
-  public final Mapping mapping;
+  private final SequenceI featureSequence;
 
-  /**
-   * the sequence mapped from
+  /*
+   * the mapping between sequences;
+   * NB this could be in either sense (from or to featureSequence)
    */
-  public final SequenceI fromSeq;
+  private final Mapping mapping;
 
   /*
-   * features on the sequence mapped to that overlap the mapped positions
+   * features on featureSequence that overlap the mapped positions
    */
   public final List<SequenceFeature> features;
 
@@ -60,21 +85,23 @@ public class MappedFeatures
    * Constructor
    * 
    * @param theMapping
-   * @param from
-   *                      the sequence mapped from (e.g. CDS)
+   *          sequence mapping (which may be either to, or from, the sequence
+   *          holding the linked features)
+   * @param featureSeq
+   *          the sequence hosting the virtual features
    * @param pos
-   *                      the residue position in the sequence mapped to
+   *          the residue position in the sequence mapped to
    * @param res
-   *                      the residue character at position pos
+   *          the residue character at position pos
    * @param theFeatures
-   *                      list of mapped features found in the 'from' sequence at
-   *                      the mapped position(s)
+   *          list of mapped features found in the 'featureSeq' sequence at the
+   *          mapped position(s)
    */
-  public MappedFeatures(Mapping theMapping, SequenceI from, int pos,
+  public MappedFeatures(Mapping theMapping, SequenceI featureSeq, int pos,
           char res, List<SequenceFeature> theFeatures)
   {
     mapping = theMapping;
-    fromSeq = from;
+    featureSequence = featureSeq;
     toPosition = pos;
     toResidue = res;
     features = theFeatures;
@@ -90,13 +117,13 @@ public class MappedFeatures
     {
       codonPos = codonPositions;
       baseCodon = new char[3];
-      int cdsStart = fromSeq.getStart();
+      int cdsStart = featureSequence.getStart();
       baseCodon[0] = Character
-              .toUpperCase(fromSeq.getCharAt(codonPos[0] - cdsStart));
+              .toUpperCase(featureSequence.getCharAt(codonPos[0] - cdsStart));
       baseCodon[1] = Character
-              .toUpperCase(fromSeq.getCharAt(codonPos[1] - cdsStart));
+              .toUpperCase(featureSequence.getCharAt(codonPos[1] - cdsStart));
       baseCodon[2] = Character
-              .toUpperCase(fromSeq.getCharAt(codonPos[2] - cdsStart));
+              .toUpperCase(featureSequence.getCharAt(codonPos[2] - cdsStart));
     }
     else
     {
@@ -108,11 +135,14 @@ public class MappedFeatures
   /**
    * Computes and returns comma-delimited HGVS notation peptide variants derived
    * from codon allele variants. If no variants are found, answers an empty
-   * string.
+   * string. The peptide variant is either simply read from the "CSQ:HGVSp"
+   * attribute if present, else computed based on the "alleles" attribute if
+   * present. If neither attribute is found, no variant (empty string) is
+   * returned.
    * 
    * @param sf
-   *             a sequence feature (which must be one of those held in this
-   *             object)
+   *          a sequence feature (which must be one of those held in this
+   *          object)
    * @return
    */
   public String findProteinVariants(SequenceFeature sf)
@@ -233,4 +263,53 @@ public class MappedFeatures
 
     return vars.toString();
   }
+
+  /**
+   * Answers the name of the linked sequence holding any mapped features
+   * 
+   * @return
+   */
+  public String getLinkedSequenceName()
+  {
+    return featureSequence == null ? null : featureSequence.getName();
+  }
+
+  /**
+   * Answers the mapped ranges (as one or more [start, end] positions) which
+   * correspond to the given [begin, end] range of the linked sequence.
+   * 
+   * <pre>
+   * Example: MappedFeatures with CDS features mapped to peptide 
+   * CDS/200-220 gtc aac TGa acGt att AAC tta
+   * mapped to PEP/6-7 WN by mapping [206, 207, 210, 210, 215, 217] to [6, 7]
+   * getMappedPositions(206, 206) should return [6, 6]
+   * getMappedPositions(200, 214) should return [6, 6]
+   * getMappedPositions(210, 215) should return [6, 7]
+   * </pre>
+   * 
+   * @param begin
+   * @param end
+   * @return
+   */
+  public int[] getMappedPositions(int begin, int end)
+  {
+    MapList map = mapping.getMap();
+    return mapping.to == featureSequence ? map.locateInFrom(begin, end)
+            : map.locateInTo(begin, end);
+  }
+
+  /**
+   * Answers true if the linked features are on coding sequence, false if on
+   * peptide
+   * 
+   * @return
+   */
+  public boolean isFromCds()
+  {
+    if (mapping.getMap().getFromRatio() == 3)
+    {
+      return mapping.to != featureSequence;
+    }
+    return mapping.to == featureSequence;
+  }
 }
index e7c77c0..3e57e4c 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel;
 
 /**
index 31736e5..0074d2a 100755 (executable)
@@ -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;
       }
index 2dd9cf0..6eeba2f 100755 (executable)
  */
 package jalview.datamodel;
 
-import jalview.datamodel.features.FeatureAttributeType;
-import jalview.datamodel.features.FeatureAttributes;
-import jalview.datamodel.features.FeatureLocationI;
-import jalview.datamodel.features.FeatureSourceI;
-import jalview.datamodel.features.FeatureSources;
-import jalview.util.StringUtils;
-
 import java.util.Comparator;
 import java.util.LinkedHashMap;
 import java.util.Map;
@@ -35,6 +28,13 @@ import java.util.SortedMap;
 import java.util.TreeMap;
 import java.util.Vector;
 
+import jalview.datamodel.features.FeatureAttributeType;
+import jalview.datamodel.features.FeatureAttributes;
+import jalview.datamodel.features.FeatureLocationI;
+import jalview.datamodel.features.FeatureSourceI;
+import jalview.datamodel.features.FeatureSources;
+import jalview.util.StringUtils;
+
 /**
  * A class that models a single contiguous feature on a sequence. If flag
  * 'contactFeature' is true, the start and end positions are interpreted instead
@@ -586,13 +586,17 @@ public class SequenceFeature implements FeatureLocationI
   }
 
   /**
-   * Answers an html-formatted report of feature details
+   * Answers an html-formatted report of feature details. If parameter
+   * {@code mf} is not null, the feature is a virtual linked feature, and
+   * details included both the original location and the mapped location
+   * (CDS/peptide).
    * 
    * @param seqName
+   * @param mf
    * 
    * @return
    */
-  public String getDetailsReport(String seqName)
+  public String getDetailsReport(String seqName, MappedFeatures mf)
   {
     FeatureSourceI metadata = FeatureSources.getInstance()
             .getSource(source);
@@ -600,9 +604,26 @@ public class SequenceFeature implements FeatureLocationI
     StringBuilder sb = new StringBuilder(128);
     sb.append("<br>");
     sb.append("<table>");
-    sb.append(String.format(ROW_DATA, "Location", seqName,
+    String name = mf == null ? seqName : mf.getLinkedSequenceName();
+    sb.append(String.format(ROW_DATA, "Location", name,
             begin == end ? begin
                     : begin + (isContactFeature() ? ":" : "-") + end));
+
+    String consequence = "";
+    if (mf != null)
+    {
+      int[] beginRange = mf.getMappedPositions(begin, begin);
+      int[] endRange = mf.getMappedPositions(end, end);
+      int from = beginRange[0];
+      int to = endRange[endRange.length - 1];
+      String s = mf.isFromCds() ? "Peptide Location" : "Coding location";
+      sb.append(String.format(ROW_DATA, s, seqName, from == to ? from
+              : from + (isContactFeature() ? ":" : "-") + to));
+      if (mf.isFromCds())
+      {
+        consequence = mf.findProteinVariants(this);
+      }
+    }
     sb.append(String.format(ROW_DATA, "Type", type, ""));
     String desc = StringUtils.stripHtmlTags(description);
     sb.append(String.format(ROW_DATA, "Description", desc, ""));
@@ -615,6 +636,12 @@ public class SequenceFeature implements FeatureLocationI
       sb.append(String.format(ROW_DATA, "Group", featureGroup, ""));
     }
 
+    if (!consequence.isEmpty())
+    {
+      sb.append(String.format(ROW_DATA, "Consequence",
+              "<i>Translated by Jalview</i>", consequence));
+    }
+
     if (otherDetails != null)
     {
       TreeMap<String, Object> ordered = new TreeMap<>(
index fd3069d..a05a2fb 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel.features;
 
 /**
index e9a5ece..bcf404b 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel.features;
 
 import java.util.ArrayList;
index f844141..e9fb9b2 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel.features;
 
 import jalview.datamodel.SequenceFeature;
index f1f8585..9a18808 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel.features;
 
 import jalview.datamodel.SequenceFeature;
index b51f2f0..3743278 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel.features;
 
 import jalview.datamodel.SequenceFeature;
index 90c2986..989424c 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel.features;
 
 import jalview.datamodel.SequenceFeature;
index a1be1dc..176ab02 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel.features;
 
 import java.util.HashMap;
index c873593..6c5fc99 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel.features;
 
 public interface FeatureSourceI
index 1be1b82..b316821 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel.features;
 
 import java.util.HashMap;
index 26bd142..d383409 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.ext.android;
 
 /*
index eaf059c..ea6265f 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.ext.android;
 
 /*
index fcd4f1f..d67121b 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.ext.android;
 
 /*
index f961f55..6cd8019 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.ext.android;
 
 /*
index 97a8e74..97ad242 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.ext.ensembl;
 
 import jalview.datamodel.AlignmentI;
index e9cc9e1..cfc679c 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.ext.ensembl;
 
 import jalview.datamodel.AlignmentI;
index 2859e0f..16ff41b 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.ext.htsjdk;
 
 import jalview.bin.Cache;
index c5a1b66..fb9b707 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.gui;
 
 import jalview.util.MessageManager;
index f53d8b3..4b5e9d4 100755 (executable)
  */
 package jalview.gui;
 
-import jalview.datamodel.AlignmentAnnotation;
-import jalview.datamodel.Sequence;
-import jalview.datamodel.SequenceGroup;
-import jalview.datamodel.SequenceI;
-import jalview.gui.SeqPanel.MousePos;
-import jalview.io.SequenceAnnotationReport;
-import jalview.util.MessageManager;
-import jalview.util.Platform;
-import jalview.viewmodel.AlignmentViewport;
-import jalview.viewmodel.ViewportRanges;
-
 import java.awt.BorderLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -47,6 +36,17 @@ import javax.swing.SwingUtilities;
 import javax.swing.Timer;
 import javax.swing.ToolTipManager;
 
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.gui.SeqPanel.MousePos;
+import jalview.io.SequenceAnnotationReport;
+import jalview.util.MessageManager;
+import jalview.util.Platform;
+import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.ViewportRanges;
+
 /**
  * This panel hosts alignment sequence ids and responds to mouse clicks on them,
  * as well as highlighting ids matched by a search from the Find menu.
@@ -65,8 +65,6 @@ public class IdPanel extends JPanel
 
   ScrollThread scrollThread = null;
 
-  String linkImageURL;
-
   int offy;
 
   // int width;
@@ -87,8 +85,7 @@ public class IdPanel extends JPanel
     this.av = av;
     alignPanel = parent;
     setIdCanvas(new IdCanvas(av));
-    linkImageURL = getClass().getResource("/images/link.gif").toString();
-    seqAnnotReport = new SequenceAnnotationReport(linkImageURL);
+    seqAnnotReport = new SequenceAnnotationReport(true);
     setLayout(new BorderLayout());
     add(getIdCanvas(), BorderLayout.CENTER);
     addMouseListener(this);
index 1f0c35a..aa09849 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.gui;
 
 import java.awt.Font;
index 8be93a1..2a7fb9f 100644 (file)
  */
 package jalview.gui;
 
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.Vector;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JInternalFrame;
+import javax.swing.JLabel;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JRadioButtonMenuItem;
+import javax.swing.JScrollPane;
+
 import jalview.analysis.AAFrequency;
 import jalview.analysis.AlignmentAnnotationUtils;
 import jalview.analysis.AlignmentUtils;
@@ -58,35 +87,6 @@ import jalview.util.StringUtils;
 import jalview.util.UrlLink;
 import jalview.viewmodel.seqfeatures.FeatureRendererModel;
 
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.BitSet;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Hashtable;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.Vector;
-
-import javax.swing.ButtonGroup;
-import javax.swing.JCheckBoxMenuItem;
-import javax.swing.JInternalFrame;
-import javax.swing.JLabel;
-import javax.swing.JMenu;
-import javax.swing.JMenuItem;
-import javax.swing.JPanel;
-import javax.swing.JPopupMenu;
-import javax.swing.JRadioButtonMenuItem;
-import javax.swing.JScrollPane;
-
 /**
  * The popup menu that is displayed on right-click on a sequence id, or in the
  * sequence alignment.
@@ -761,14 +761,16 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
   }
 
   /**
-   * Add a link to show feature details for each sequence feature
+   * Add a menu item to show feature details for each sequence feature. Any
+   * linked 'virtual' features (CDS/protein) are also optionally found and
+   * included.
    * 
    * @param features
-   * @param column
    * @param seq
+   * @param column
    */
   protected void addFeatureDetails(List<SequenceFeature> features,
-          SequenceI seq, int column)
+          final SequenceI seq, final int column)
   {
     /*
      * add features in CDS/protein complement at the corresponding
@@ -803,39 +805,49 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
     String name = seq.getName();
     for (final SequenceFeature sf : features)
     {
-      addFeatureDetailsMenuItem(details, name, sf);
+      addFeatureDetailsMenuItem(details, name, sf, null);
     }
 
     if (mf != null)
     {
-      name = mf.fromSeq == seq ? mf.mapping.getTo().getName()
-              : mf.fromSeq.getName();
       for (final SequenceFeature sf : mf.features)
       {
-        addFeatureDetailsMenuItem(details, name, sf);
+        addFeatureDetailsMenuItem(details, name, sf, mf);
       }
     }
   }
 
   /**
-   * A helper method to add one menu item whose action is to show details for one
-   * feature. The menu text includes feature description, but this may be
+   * A helper method to add one menu item whose action is to show details for
+   * one feature. The menu text includes feature description, but this may be
    * truncated.
    * 
    * @param details
    * @param seqName
    * @param sf
+   * @param mf
    */
   void addFeatureDetailsMenuItem(JMenu details, final String seqName,
-          final SequenceFeature sf)
+          final SequenceFeature sf, MappedFeatures mf)
   {
     int start = sf.getBegin();
     int end = sf.getEnd();
+    if (mf != null)
+    {
+      /*
+       * show local rather than linked feature coordinates
+       */
+      int[] beginRange = mf.getMappedPositions(start, start);
+      start = beginRange[0];
+      int[] endRange = mf.getMappedPositions(end, end);
+      end = endRange[endRange.length - 1];
+    }
     StringBuilder desc = new StringBuilder();
     desc.append(sf.getType()).append(" ").append(String.valueOf(start));
     if (start != end)
     {
-      desc.append("-").append(String.valueOf(end));
+      desc.append(sf.isContactFeature() ? ":" : "-");
+      desc.append(String.valueOf(end));
     }
     String description = sf.getDescription();
     if (description != null)
@@ -866,20 +878,21 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        showFeatureDetails(seqName, sf);
+        showFeatureDetails(sf, seqName, mf);
       }
     });
     details.add(item);
   }
 
   /**
-   * Opens a panel showing a text report of feature dteails
-   * 
-   * @param seqName
+   * Opens a panel showing a text report of feature details
    * 
    * @param sf
+   * @param seqName
+   * @param mf
    */
-  protected void showFeatureDetails(String seqName, SequenceFeature sf)
+  protected void showFeatureDetails(SequenceFeature sf, String seqName,
+          MappedFeatures mf)
   {
     JInternalFrame details;
     if (Platform.isJS())
@@ -891,7 +904,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
       // TODO JAL-3026 set style of table correctly for feature details
       JLabel reprt = new JLabel(MessageManager
               .formatMessage("label.html_content", new Object[]
-              { sf.getDetailsReport(seqName) }));
+              { sf.getDetailsReport(seqName, mf) }));
       reprt.setBackground(Color.WHITE);
       reprt.setOpaque(true);
       panel.add(reprt, BorderLayout.CENTER);
@@ -906,10 +919,10 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
      */
     {
       CutAndPasteHtmlTransfer cap = new CutAndPasteHtmlTransfer();
-      // it appears Java's CSS does not support border-collaps :-(
+      // it appears Java's CSS does not support border-collapse :-(
       cap.addStylesheetRule("table { border-collapse: collapse;}");
       cap.addStylesheetRule("table, td, th {border: 1px solid black;}");
-      cap.setText(sf.getDetailsReport(seqName));
+      cap.setText(sf.getDetailsReport(seqName, mf));
       details = cap;
     }
     Desktop.addInternalFrame(details,
@@ -1795,7 +1808,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
               "label.create_sequence_details_report_annotation_for",
               new Object[]
               { seq.getDisplayId(true) }) + "</h2></p><p>");
-      new SequenceAnnotationReport(null).createSequenceAnnotationReport(
+      new SequenceAnnotationReport(false).createSequenceAnnotationReport(
               contents, seq, true, true, ap.getSeqPanel().seqCanvas.fr);
       contents.append("</p>");
     }
index 2ad5bea..d22ddd4 100644 (file)
@@ -212,8 +212,6 @@ public class SeqPanel extends JPanel
 
   StringBuffer keyboardNo2;
 
-  java.net.URL linkImageURL;
-
   private final SequenceAnnotationReport seqARep;
 
   /*
@@ -244,8 +242,7 @@ public class SeqPanel extends JPanel
    */
   public SeqPanel(AlignViewport viewport, AlignmentPanel alignPanel)
   {
-    linkImageURL = getClass().getResource("/images/link.gif");
-    seqARep = new SequenceAnnotationReport(linkImageURL.toString());
+    seqARep = new SequenceAnnotationReport(true);
     ToolTipManager.sharedInstance().registerComponent(this);
     ToolTipManager.sharedInstance().setInitialDelay(0);
     ToolTipManager.sharedInstance().setDismissDelay(10000);
@@ -1067,9 +1064,9 @@ public class SeqPanel extends JPanel
     {
       List<SequenceFeature> features = ap.getFeatureRenderer()
               .findFeaturesAtColumn(sequence, column + 1);
-      unshownFeatures = seqARep.appendFeaturesLengthLimit(tooltipText, pos,
-              features,
-              this.ap.getSeqPanel().seqCanvas.fr, MAX_TOOLTIP_LENGTH);
+      unshownFeatures = seqARep.appendFeatures(tooltipText, pos,
+              features, this.ap.getSeqPanel().seqCanvas.fr,
+              MAX_TOOLTIP_LENGTH);
 
       /*
        * add features in CDS/protein complement at the corresponding
@@ -1087,9 +1084,8 @@ public class SeqPanel extends JPanel
                   pos);
           if (mf != null)
           {
-            unshownFeatures = seqARep.appendFeaturesLengthLimit(
-                    tooltipText, pos, mf, fr2,
-                    MAX_TOOLTIP_LENGTH);
+            unshownFeatures = seqARep.appendFeatures(tooltipText,
+                    pos, mf, fr2, MAX_TOOLTIP_LENGTH);
           }
         }
       }
@@ -1245,7 +1241,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;
   }
@@ -1261,7 +1257,7 @@ public class SeqPanel extends JPanel
    * Sequence 6 ID: O.niloticus.3 Nucleotide: Uracil (2)
    * </pre>
    * 
-   * @param sequence
+   * @param seqName
    * @param seqIndex
    *          sequence position in the alignment (1..)
    * @param sequenceChar
@@ -1269,7 +1265,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);
@@ -1279,7 +1275,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;
 
@@ -1324,7 +1320,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();
@@ -1336,8 +1333,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;
       }
     }
index 573040f..b8a721e 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io;
 
 import java.io.File;
index 1504404..339cefa 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io;
 
 import java.io.File;
index 06c2fc9..0d5f92b 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io;
 
 import jalview.bin.Cache;
index 4face29..69130d0 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io;
 
 import jalview.bin.Cache;
index d2a9b0a..c08c84e 100755 (executable)
  */
 package jalview.io;
 
+import java.awt.Color;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
 import jalview.analysis.AlignmentUtils;
 import jalview.analysis.SequenceIdMatcher;
 import jalview.api.AlignViewportI;
@@ -44,18 +56,6 @@ import jalview.util.MapList;
 import jalview.util.ParseHtmlBodyAndLinks;
 import jalview.util.StringUtils;
 
-import java.awt.Color;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.TreeMap;
-
 /**
  * Parses and writes features files, which may be in Jalview, GFF2 or GFF3
  * format. These are tab-delimited formats but with differences in the use of
@@ -736,7 +736,6 @@ public class FeaturesFile extends AlignFile implements FeaturesSourceI
 
       if (mf != null)
       {
-        MapList mapping = mf.mapping.getMap();
         for (SequenceFeature sf : mf.features)
         {
           /*
@@ -752,9 +751,7 @@ public class FeaturesFile extends AlignFile implements FeaturesSourceI
             found.add(sf);
             int begin = sf.getBegin();
             int end = sf.getEnd();
-            int[] range = mf.mapping.getTo() == seq.getDatasetSequence()
-                    ? mapping.locateInTo(begin, end)
-                    : mapping.locateInFrom(begin, end);
+            int[] range = mf.getMappedPositions(begin, end);
             SequenceFeature sf2 = new SequenceFeature(sf, range[0],
                     range[1], group, sf.getScore());
             complementary.add(sf2);
index 084dbc5..77a9a47 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io;
 
 public class IntKeyStringValueEntry
index 9d7fcfc..8e4e783 100644 (file)
@@ -55,9 +55,9 @@ public class SequenceAnnotationReport
 
   private static final int MAX_SOURCES = 40;
 
- // public static final String[][] PRIMARY_SOURCES  moved to DBRefSource.java
+  private static String linkImageURL;
 
-  final String linkImageURL;
+ // public static final String[][] PRIMARY_SOURCES  moved to DBRefSource.java
 
   /*
    * Comparator to order DBRefEntry by Source + accession id (case-insensitive),
@@ -117,14 +117,30 @@ public class SequenceAnnotationReport
 //    }
   };
 
-  public SequenceAnnotationReport(String linkURL)
+  private boolean forTooltip;
+
+  /**
+   * Constructor given a flag which affects behaviour
+   * <ul>
+   * <li>if true, generates feature details suitable to show in a tooltip</li>
+   * <li>if false, generates feature details in a form suitable for the sequence
+   * details report</li>
+   * </ul>
+   * 
+   * @param isForTooltip
+   */
+  public SequenceAnnotationReport(boolean isForTooltip)
   {
-    this.linkImageURL = linkURL;
+    this.forTooltip = isForTooltip;
+    if (linkImageURL == null)
+    {
+      linkImageURL = getClass().getResource("/images/link.gif").toString();
+    }
   }
 
   /**
-   * Append text for the list of features to the tooltip Returns number of
-   * features left if maxlength limit is (or would have been) reached
+   * Append text for the list of features to the tooltip. Returns the number of
+   * features not added if maxlength limit is (or would have been) reached.
    * 
    * @param sb
    * @param residuePos
@@ -132,7 +148,7 @@ public class SequenceAnnotationReport
    * @param minmax
    * @param maxlength
    */
-  public int appendFeaturesLengthLimit(final StringBuilder sb,
+  public int appendFeatures(final StringBuilder sb,
           int residuePos, List<SequenceFeature> features,
           FeatureRendererModel fr, int maxlength)
   {
@@ -147,16 +163,10 @@ public class SequenceAnnotationReport
     return 0;
   }
 
-  public void appendFeatures(final StringBuilder sb, int residuePos,
-          List<SequenceFeature> features, FeatureRendererModel fr)
-  {
-    appendFeaturesLengthLimit(sb, residuePos, features, fr, 0);
-  }
-
   /**
-   * Appends text for mapped features (e.g. CDS feature for peptide or vice versa)
-   * Returns number of features left if maxlength limit is (or would have been)
-   * reached
+   * Appends text for mapped features (e.g. CDS feature for peptide or vice
+   * versa) Returns number of features left if maxlength limit is (or would have
+   * been) reached.
    * 
    * @param sb
    * @param residuePos
@@ -164,7 +174,7 @@ public class SequenceAnnotationReport
    * @param fr
    * @param maxlength
    */
-  public int appendFeaturesLengthLimit(StringBuilder sb, int residuePos,
+  public int appendFeatures(StringBuilder sb, int residuePos,
           MappedFeatures mf, FeatureRendererModel fr, int maxlength)
   {
     for (int i = 0; i < mf.features.size(); i++)
@@ -178,12 +188,6 @@ public class SequenceAnnotationReport
     return 0;
   }
 
-  public void appendFeatures(StringBuilder sb, int residuePos,
-          MappedFeatures mf, FeatureRendererModel fr)
-  {
-    appendFeaturesLengthLimit(sb, residuePos, mf, fr, 0);
-  }
-
   /**
    * Appends the feature at rpos to the given buffer
    * 
@@ -196,19 +200,49 @@ public class SequenceAnnotationReport
           FeatureRendererModel fr, SequenceFeature feature,
           MappedFeatures mf, int maxlength)
   {
+    int begin = feature.getBegin();
+    int end = feature.getEnd();
+
+    /*
+     * if this is a virtual features, convert begin/end to the
+     * coordinates of the sequence it is mapped to
+     */
+    int[] beginRange = null;
+    int[] endRange = null;
+    if (mf != null)
+    {
+      beginRange = mf.getMappedPositions(begin, begin);
+      endRange = mf.getMappedPositions(end, end);
+      if (beginRange == null || endRange == null)
+      {
+        // something went wrong
+        return false;
+      }
+      begin = beginRange[0];
+      end = endRange[endRange.length - 1];
+    }
+
     StringBuilder sb = new StringBuilder();
     if (feature.isContactFeature())
     {
-      if (feature.getBegin() == rpos || feature.getEnd() == rpos)
+      /*
+       * include if rpos is at start or end position of [mapped] feature
+       */
+      boolean showContact = (mf == null) && (rpos == begin || rpos == end);
+      boolean showMappedContact = (mf != null) && ((rpos >= beginRange[0]
+              && rpos <= beginRange[beginRange.length - 1])
+              || (rpos >= endRange[0]
+                      && rpos <= endRange[endRange.length - 1]));
+      if (showContact || showMappedContact)
       {
         if (sb0.length() > 6)
         {
           sb.append("<br/>");
         }
-        sb.append(feature.getType()).append(" ").append(feature.getBegin())
-                .append(":").append(feature.getEnd());
+        sb.append(feature.getType()).append(" ").append(begin).append(":")
+                .append(end);
       }
-      return appendTextMaxLengthReached(sb0, sb, maxlength);
+      return appendText(sb0, sb, maxlength);
     }
 
     if (sb0.length() > 6)
@@ -223,11 +257,11 @@ public class SequenceAnnotationReport
       if (rpos != 0)
       {
         // we are marking a positional feature
-        sb.append(feature.begin);
-      }
-      if (feature.begin != feature.end)
-      {
-        sb.append(" ").append(feature.end);
+        sb.append(begin);
+        if (begin != end)
+        {
+          sb.append(" ").append(end);
+        }
       }
 
       String description = feature.getDescription();
@@ -288,29 +322,21 @@ public class SequenceAnnotationReport
         }
       }
     }
-    return appendTextMaxLengthReached(sb0, sb, maxlength);
-  }
-
-  void appendFeature(final StringBuilder sb, int rpos,
-          FeatureRendererModel fr, SequenceFeature feature,
-          MappedFeatures mf)
-  {
-    appendFeature(sb, rpos, fr, feature, mf, 0);
+    return appendText(sb0, sb, maxlength);
   }
 
   /**
-   * Appends {@code sb} to {@code sb0}, and returns false, unless
-   * {@code maxlength} is not zero and appending would make the total length
-   * greater than {@code maxlength}, in which case the text is not appended, and
-   * the method returns true.
+   * Appends sb to sb0, and returns false, unless maxlength is not zero and
+   * appending would make the result longer than or equal to maxlength, in which
+   * case the append is not done and returns true
    * 
    * @param sb0
    * @param sb
    * @param maxlength
    * @return
    */
-  private static boolean appendTextMaxLengthReached(StringBuilder sb0,
-          StringBuilder sb, int maxlength)
+  private static boolean appendText(StringBuilder sb0, StringBuilder sb,
+          int maxlength)
   {
     if (maxlength == 0 || sb0.length() + sb.length() < maxlength)
     {
@@ -472,7 +498,7 @@ public class SequenceAnnotationReport
               .getNonPositionalFeatures())
       {
         int sz = -sb.length();
-        appendFeature(sb, 0, fr, sf, null);
+        appendFeature(sb, 0, fr, sf, null, 0);
         sz += sb.length();
         maxWidth = Math.max(maxWidth, sz);
       }
index 84e629e..8b26757 100644 (file)
  */
 package jalview.io;
 
-import jalview.analysis.Rna;
-import jalview.datamodel.AlignmentAnnotation;
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.Annotation;
-import jalview.datamodel.DBRefEntry;
-import jalview.datamodel.Mapping;
-import jalview.datamodel.Sequence;
-import jalview.datamodel.SequenceFeature;
-import jalview.datamodel.SequenceI;
-import jalview.schemes.ResidueProperties;
-import jalview.util.Comparison;
-import jalview.util.Format;
-import jalview.util.MessageManager;
-
 import java.io.BufferedReader;
 import java.io.FileReader;
 import java.io.IOException;
@@ -53,6 +39,21 @@ import com.stevesoft.pat.Regex;
 import fr.orsay.lri.varna.exceptions.ExceptionUnmatchedClosingParentheses;
 import fr.orsay.lri.varna.factories.RNAFactory;
 import fr.orsay.lri.varna.models.rna.RNA;
+import jalview.analysis.Rna;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.DBRefSource;
+import jalview.datamodel.Mapping;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
+import jalview.schemes.ResidueProperties;
+import jalview.util.Comparison;
+import jalview.util.DBRefUtils;
+import jalview.util.Format;
+import jalview.util.MessageManager;
 
 // import org.apache.log4j.*;
 
@@ -332,17 +333,14 @@ public class StockholmFile extends AlignFile
 
           if (accAnnotations != null && accAnnotations.containsKey("AC"))
           {
-            if (dbsource != null)
+            String dbr = (String) accAnnotations.get("AC");
+            if (dbr != null)
             {
-              String dbr = (String) accAnnotations.get("AC");
-              if (dbr != null)
-              {
-                // we could get very clever here - but for now - just try to
-                // guess accession type from source of alignment plus structure
-                // of accession
-                guessDatabaseFor(seqO, dbr, dbsource);
-
-              }
+              // we could get very clever here - but for now - just try to
+              // guess accession type from type of sequence, source of alignment plus
+              // structure
+              // of accession
+              guessDatabaseFor(seqO, dbr, dbsource);
             }
             // else - do what ? add the data anyway and prompt the user to
             // specify what references these are ?
@@ -527,6 +525,9 @@ public class StockholmFile extends AlignFile
               treeName = an.stringMatched(2);
               treeString = new StringBuffer();
             }
+            // TODO: JAL-3532 - this is where GF comments and database references are lost
+            // suggest overriding this method for Stockholm files to catch and properly
+            // process CC, DR etc into multivalued properties
             setAlignmentProperty(an.stringMatched(1), an.stringMatched(2));
           }
         }
@@ -755,6 +756,12 @@ public class StockholmFile extends AlignFile
         st = -1;
       }
     }
+    if (dbsource == null)
+    {
+      // make up an origin based on whether the sequence looks like it is nucleotide
+      // or protein
+      dbsource = (seqO.isProtein()) ? "PFAM" : "RFAM";
+    }
     if (dbsource.equals("PFAM"))
     {
       seqdb = "UNIPROT";
@@ -930,6 +937,11 @@ public class StockholmFile extends AlignFile
     return annot;
   }
 
+  private String dbref_to_ac_record(DBRefEntry ref)
+  {
+    return ref.getSource().toString() + " ; "
+            + ref.getAccessionId().toString();
+  }
   @Override
   public String print(SequenceI[] s, boolean jvSuffix)
   {
@@ -944,6 +956,7 @@ public class StockholmFile extends AlignFile
     int slen = s.length;
     SequenceI seq;
     Hashtable<String, String> dataRef = null;
+    boolean isAA = s[in].isProtein();
     while ((in < slen) && ((seq = s[in]) != null))
     {
       String tmp = printId(seq, jvSuffix);
@@ -961,14 +974,29 @@ public class StockholmFile extends AlignFile
         {
           dataRef = new Hashtable<>();
         }
-        for (int idb = 0; idb < ndb; idb++)
+        List<DBRefEntry> primrefs = seq.getPrimaryDBRefs();
+        if (primrefs.size() >= 1)
         {
-
-          DBRefEntry ref = seqrefs.get(idb);
-          String datAs1 = ref.getSource().toString()
-                  + " ; "
-                  + ref.getAccessionId().toString();
-          dataRef.put(tmp, datAs1);
+          dataRef.put(tmp, dbref_to_ac_record(primrefs.get(0)));
+        }
+        else
+        {
+          for (int idb = 0; idb < seq.getDBRefs().size(); idb++)
+          {
+            DBRefEntry dbref = seq.getDBRefs().get(idb);
+            dataRef.put(tmp, dbref_to_ac_record(dbref));
+            // if we put in a uniprot or EMBL record then we're done:
+            if (isAA && DBRefSource.UNIPROT
+                    .equals(DBRefUtils.getCanonicalName(dbref.getSource())))
+            {
+              break;
+            }
+            if (!isAA && DBRefSource.EMBL
+                    .equals(DBRefUtils.getCanonicalName(dbref.getSource())))
+            {
+              break;
+            }
+          }
         }
       }
       in++;
@@ -998,10 +1026,11 @@ public class StockholmFile extends AlignFile
       while (en.hasMoreElements())
       {
         Object idd = en.nextElement();
-        String type = (String) dataRef.remove(idd);
+        String type = dataRef.remove(idd);
         out.append(new Format("%-" + (maxid - 2) + "s")
                 .form("#=GS " + idd.toString() + " "));
-        if (type.contains("PFAM") || type.contains("RFAM"))
+        if (isAA && type.contains("UNIPROT")
+                || (!isAA && type.contains("EMBL")))
         {
 
           out.append(" AC " + type.substring(type.indexOf(";") + 1));
index 168f1c6..1eeb922 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.io.vcf;
 
 import jalview.analysis.Dna;
index 1fccfa2..aa3328b 100644 (file)
@@ -112,6 +112,10 @@ public class FeatureRenderer extends FeatureRendererModel
         continue;
       }
 
+      /*
+       * JAL-3045 text is always drawn over features, even if
+       * 'Show Text' is unchecked in the format menu
+       */
       g.setColor(Color.white);
       int charOffset = (charWidth - fm.charWidth(s)) / 2;
       g.drawString(String.valueOf(s),
index fb54bba..ae0243e 100755 (executable)
  */
 package jalview.util;
 
-import jalview.datamodel.DBRefEntry;
-import jalview.datamodel.DBRefSource;
-import jalview.datamodel.Mapping;
-import jalview.datamodel.PDBEntry;
-import jalview.datamodel.SequenceI;
-
 import java.util.ArrayList;
 import java.util.BitSet;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 import com.stevesoft.pat.Regex;
 
+import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.DBRefSource;
+import jalview.datamodel.Mapping;
+import jalview.datamodel.PDBEntry;
+import jalview.datamodel.SequenceI;
+
 /**
  * Utilities for handling DBRef objects and their collections.
  */
@@ -308,6 +307,75 @@ public class DBRefUtils
 
        };
 
+  /**
+   * Parses a DBRefEntry and adds it to the sequence, also a PDBEntry if the
+   * database is PDB.
+   * <p>
+   * Used by file parsers to generate DBRefs from annotation within file (eg
+   * Stockholm)
+   * 
+   * @param dbname
+   * @param version
+   * @param acn
+   * @param seq
+   *          where to annotate with reference
+   * @return parsed version of entry that was added to seq (if any)
+   */
+  public static DBRefEntry parseToDbRef(SequenceI seq, String dbname,
+          String version, String acn)
+  {
+    DBRefEntry ref = null;
+    if (dbname != null)
+    {
+      String locsrc = DBRefUtils.getCanonicalName(dbname);
+      if (locsrc.equals(DBRefSource.PDB))
+      {
+        /*
+         * Check for PFAM style stockhom PDB accession id citation e.g.
+         * "1WRI A; 7-80;"
+         */
+        Regex r = new com.stevesoft.pat.Regex(
+                "([0-9][0-9A-Za-z]{3})\\s*(.?)\\s*;\\s*([0-9]+)-([0-9]+)");
+        if (r.search(acn.trim()))
+        {
+          String pdbid = r.stringMatched(1);
+          String chaincode = r.stringMatched(2);
+          if (chaincode == null)
+          {
+            chaincode = " ";
+          }
+          // String mapstart = r.stringMatched(3);
+          // String mapend = r.stringMatched(4);
+          if (chaincode.equals(" "))
+          {
+            chaincode = "_";
+          }
+          // construct pdb ref.
+          ref = new DBRefEntry(locsrc, version, pdbid + chaincode);
+          PDBEntry pdbr = new PDBEntry();
+          pdbr.setId(pdbid);
+          pdbr.setType(PDBEntry.Type.PDB);
+          pdbr.setChainCode(chaincode);
+          seq.addPDBId(pdbr);
+        }
+        else
+        {
+          System.err.println("Malformed PDB DR line:" + acn);
+        }
+      }
+      else
+      {
+        // default:
+        ref = new DBRefEntry(locsrc, version, acn.trim());
+      }
+    }
+    if (ref != null)
+    {
+      seq.addDBRef(ref);
+    }
+    return ref;
+  }
+
        /**
         * accession ID and DB must be identical. Version is ignored. Map is either not
         * defined or is a match (or is compatible?)
@@ -451,60 +519,6 @@ public class DBRefUtils
   }
 
        /**
-        * Parses a DBRefEntry and adds it to the sequence, also a PDBEntry if the
-        * database is PDB.
-        * <p>
-        * Used by file parsers to generate DBRefs from annotation within file (eg
-        * Stockholm)
-        * 
-        * @param dbname
-        * @param version
-        * @param acn
-        * @param seq     where to annotate with reference
-        * @return parsed version of entry that was added to seq (if any)
-        */
-       public static DBRefEntry parseToDbRef(SequenceI seq, String dbname, String version, String acn) {
-               DBRefEntry ref = null;
-               if (dbname != null) {
-                       String locsrc = DBRefUtils.getCanonicalName(dbname);
-                       if (locsrc.equals(DBRefSource.PDB)) {
-                               /*
-                                * Check for PFAM style stockhom PDB accession id citation e.g. "1WRI A; 7-80;"
-                                */
-                               Regex r = new com.stevesoft.pat.Regex("([0-9][0-9A-Za-z]{3})\\s*(.?)\\s*;\\s*([0-9]+)-([0-9]+)");
-                               if (r.search(acn.trim())) {
-                                       String pdbid = r.stringMatched(1);
-                                       String chaincode = r.stringMatched(2);
-                                       if (chaincode == null) {
-                                               chaincode = " ";
-                                       }
-                                       // String mapstart = r.stringMatched(3);
-                                       // String mapend = r.stringMatched(4);
-                                       if (chaincode.equals(" ")) {
-                                               chaincode = "_";
-                                       }
-                                       // construct pdb ref.
-                                       ref = new DBRefEntry(locsrc, version, pdbid + chaincode);
-                                       PDBEntry pdbr = new PDBEntry();
-                                       pdbr.setId(pdbid);
-                                       pdbr.setType(PDBEntry.Type.PDB);
-                                       pdbr.setChainCode(chaincode);
-                                       seq.addPDBId(pdbr);
-                               } else {
-                                       System.err.println("Malformed PDB DR line:" + acn);
-                               }
-                       } else {
-                               // default:
-                               ref = new DBRefEntry(locsrc, version, acn);
-                       }
-               }
-               if (ref != null) {
-                       seq.addDBRef(ref);
-               }
-               return ref;
-       }
-
-       /**
         * Returns true if either object is null, or they are equal
         * 
         * @param o1
index dde1662..7a5fb15 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.util;
 
 import java.io.IOException;
index 72d46a2..ecbb6e1 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.util;
 
 public class MathUtils
index c83da4e..83330b9 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.util;
 
 import java.awt.event.MouseEvent;
index 7a3c8ca..9877b5d 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.util;
 
 import java.awt.GraphicsEnvironment;
index a7817bd..f1014af 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.util;
 
 import java.awt.GraphicsEnvironment;
index bf17259..74c565d 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.util;
 
 import java.awt.event.MouseEvent;
index 8816a7f..f47b367 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.util.matcher;
 
 import jalview.util.MessageManager;
index 0792509..51e1828 100644 (file)
@@ -1,39 +1,69 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.util.matcher;
 
 import java.util.Objects;
-import java.util.regex.Pattern;
 
 /**
  * A bean to describe one attribute-based filter
  */
 public class Matcher implements MatcherI
 {
+  public enum PatternType
+  {
+    String, Integer, Float
+  }
+
   /*
    * the comparison condition
    */
-  Condition condition;
+  private final Condition condition;
 
   /*
-   * the string pattern as entered, or the regex, to compare to
-   * also holds the string form of float value if a numeric condition
+   * the string pattern as entered, to compare to
    */
-  String pattern;
+  private String pattern;
 
   /*
    * the pattern in upper case, for non-case-sensitive matching
    */
-  String uppercasePattern;
+  private final String uppercasePattern;
 
   /*
    * the compiled regex if using a pattern match condition
-   * (reserved for possible future enhancement)
+   * (possible future enhancement)
+   */
+  // private Pattern regexPattern;
+
+  /*
+   * the value to compare to for a numerical condition with a float pattern
    */
-  Pattern regexPattern;
+  private float floatValue = 0F;
 
   /*
-   * the value to compare to for a numerical condition
+   * the value to compare to for a numerical condition with an integer pattern
    */
-  float value;
+  private long longValue = 0L;
+
+  private PatternType patternType;
 
   /**
    * Constructor
@@ -51,30 +81,38 @@ public class Matcher implements MatcherI
   {
     Objects.requireNonNull(cond);
     condition = cond;
+
     if (cond.isNumeric())
     {
-      value = Float.valueOf(compareTo);
-      pattern = String.valueOf(value);
-      uppercasePattern = pattern;
+      try
+      {
+        longValue = Long.valueOf(compareTo);
+        pattern = String.valueOf(longValue);
+        patternType = PatternType.Integer;
+      } catch (NumberFormatException e)
+      {
+        floatValue = Float.valueOf(compareTo);
+        pattern = String.valueOf(floatValue);
+        patternType = PatternType.Float;
+      }
     }
     else
     {
       pattern = compareTo;
-      if (pattern != null)
-      {
-        uppercasePattern = pattern.toUpperCase();
-      }
+      patternType = PatternType.String;
     }
 
+    uppercasePattern = pattern == null ? null : pattern.toUpperCase();
+
     // if we add regex conditions (e.g. matchesPattern), then
     // pattern should hold the raw regex, and
     // regexPattern = Pattern.compile(compareTo);
   }
 
   /**
-   * Constructor for a numerical match condition. Note that if a string
-   * comparison condition is specified, this will be converted to a comparison
-   * with the float value as string
+   * Constructor for a float-valued numerical match condition. Note that if a
+   * string comparison condition is specified, this will be converted to a
+   * comparison with the float value as string
    * 
    * @param cond
    * @param compareTo
@@ -85,39 +123,56 @@ public class Matcher implements MatcherI
   }
 
   /**
+   * Constructor for an integer-valued numerical match condition. Note that if a
+   * string comparison condition is specified, this will be converted to a
+   * comparison with the integer value as string
+   * 
+   * @param cond
+   * @param compareTo
+   */
+  public Matcher(Condition cond, long compareTo)
+  {
+    this(cond, String.valueOf(compareTo));
+  }
+
+  /**
    * {@inheritDoc}
    */
-  @SuppressWarnings("incomplete-switch")
   @Override
-  public boolean matches(String val)
+  public boolean matches(String compareTo)
   {
-    if (condition.isNumeric())
+    if (compareTo == null)
     {
-      try
-      {
-        /*
-         * treat a null value (no such attribute) as
-         * failing any numerical filter condition
-         */
-        return val == null ? false : matches(Float.valueOf(val));
-      } catch (NumberFormatException e)
-      {
-        return false;
-      }
+      return matchesNull();
     }
-    
-    /*
-     * a null value matches a negative condition, fails a positive test
-     */
-    if (val == null)
+
+    boolean matched = false;
+    switch (patternType)
     {
-      return condition == Condition.NotContains
-              || condition == Condition.NotMatches 
-              || condition == Condition.NotPresent;
+    case Float:
+      matched = matchesFloat(compareTo, floatValue);
+      break;
+    case Integer:
+      matched = matchesLong(compareTo);
+      break;
+    default:
+      matched = matchesString(compareTo);
+      break;
     }
-    
-    String upper = val.toUpperCase().trim();
+    return matched;
+  }
+
+  /**
+   * Executes a non-case-sensitive string comparison to the given value, after
+   * trimming it. Returns true if the test passes, false if it fails.
+   * 
+   * @param compareTo
+   * @return
+   */
+  boolean matchesString(String compareTo)
+  {
     boolean matched = false;
+    String upper = compareTo.toUpperCase().trim();
     switch(condition) {
     case Matches:
       matched = upper.equals(uppercasePattern);
@@ -141,38 +196,48 @@ public class Matcher implements MatcherI
   }
 
   /**
-   * Applies a numerical comparison match condition
+   * Performs a numerical comparison match condition test against a float value
    * 
-   * @param f
+   * @param testee
+   * @param compareTo
    * @return
    */
-  @SuppressWarnings("incomplete-switch")
-  boolean matches(float f)
+  boolean matchesFloat(String testee, float compareTo)
   {
     if (!condition.isNumeric())
     {
-      return matches(String.valueOf(f));
+      // failsafe, shouldn't happen
+      return matches(testee);
+    }
+
+    float f = 0f;
+    try
+    {
+      f = Float.valueOf(testee);
+    } catch (NumberFormatException e)
+    {
+      return false;
     }
     
     boolean matched = false;
     switch (condition) {
     case LT:
-      matched = f < value;
+      matched = f < compareTo;
       break;
     case LE:
-      matched = f <= value;
+      matched = f <= compareTo;
       break;
     case EQ:
-      matched = f == value;
+      matched = f == compareTo;
       break;
     case NE:
-      matched = f != value;
+      matched = f != compareTo;
       break;
     case GT:
-      matched = f > value;
+      matched = f > compareTo;
       break;
     case GE:
-      matched = f >= value;
+      matched = f >= compareTo;
       break;
     default:
       break;
@@ -188,7 +253,7 @@ public class Matcher implements MatcherI
   @Override
   public int hashCode()
   {
-    return pattern.hashCode() + condition.hashCode() + (int) value;
+    return pattern.hashCode() + condition.hashCode() + (int) floatValue;
   }
 
   /**
@@ -203,7 +268,8 @@ public class Matcher implements MatcherI
       return false;
     }
     Matcher m = (Matcher) obj;
-    if (condition != m.condition || value != m.value)
+    if (condition != m.condition || floatValue != m.floatValue
+            || longValue != m.longValue)
     {
       return false;
     }
@@ -227,12 +293,6 @@ public class Matcher implements MatcherI
   }
 
   @Override
-  public float getFloatValue()
-  {
-    return value;
-  }
-
-  @Override
   public String toString()
   {
     StringBuilder sb = new StringBuilder();
@@ -248,4 +308,81 @@ public class Matcher implements MatcherI
 
     return sb.toString();
   }
+
+  /**
+   * Performs a numerical comparison match condition test against an integer
+   * value
+   * 
+   * @param compareTo
+   * @return
+   */
+  boolean matchesLong(String compareTo)
+  {
+    if (!condition.isNumeric())
+    {
+      // failsafe, shouldn't happen
+      return matches(String.valueOf(compareTo));
+    }
+
+    long val = 0L;
+    try
+    {
+      val = Long.valueOf(compareTo);
+    } catch (NumberFormatException e)
+    {
+      /*
+       * try the presented value as a float instead
+       */
+      return matchesFloat(compareTo, longValue);
+    }
+    
+    boolean matched = false;
+    switch (condition) {
+    case LT:
+      matched = val < longValue;
+      break;
+    case LE:
+      matched = val <= longValue;
+      break;
+    case EQ:
+      matched = val == longValue;
+      break;
+    case NE:
+      matched = val != longValue;
+      break;
+    case GT:
+      matched = val > longValue;
+      break;
+    case GE:
+      matched = val >= longValue;
+      break;
+    default:
+      break;
+    }
+  
+    return matched;
+  }
+
+  /**
+   * Tests whether a null value matches the condition. The rule is that any
+   * numeric condition is failed, and only 'negative' string conditions are
+   * matched. So for example <br>
+   * {@code null contains "damaging"}<br>
+   * fails, but <br>
+   * {@code null does not contain "damaging"}</br>
+   * passes.
+   */
+  boolean matchesNull()
+  {
+    if (condition.isNumeric())
+    {
+      return false;
+    }
+    else
+    {
+      return condition == Condition.NotContains
+              || condition == Condition.NotMatches
+              || condition == Condition.NotPresent;
+    }
+  }
 }
index ca6d44c..a951fae 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview 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.
+ *  
+ * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.util.matcher;
 
 public interface MatcherI
@@ -13,6 +33,4 @@ public interface MatcherI
   Condition getCondition();
 
   String getPattern();
-
-  float getFloatValue();
 }
index 68345b9..3608626 100644 (file)
@@ -1199,8 +1199,8 @@ public abstract class FeatureRendererModel
   }
 
   @Override
-  public MappedFeatures findComplementFeaturesAtResidue(SequenceI sequence,
-          int pos)
+  public MappedFeatures findComplementFeaturesAtResidue(
+          final SequenceI sequence, final int pos)
   {
     SequenceI ds = sequence.getDatasetSequence();
     if (ds == null)
@@ -1269,9 +1269,12 @@ public abstract class FeatureRendererModel
     }
 
     /*
-     * sort by renderorder, inefficiently
+     * sort by renderorder (inefficiently but ok for small scale);
+     * NB this sorts 'on top' feature to end, for rendering
      */
     List<SequenceFeature> result = new ArrayList<>();
+    final int toAdd = found.size();
+    int added = 0;
     for (String type : renderOrder)
     {
       for (SequenceFeature sf : found)
@@ -1279,11 +1282,11 @@ public abstract class FeatureRendererModel
         if (type.equals(sf.getType()))
         {
           result.add(sf);
-          if (result.size() == found.size())
-          {
-            return new MappedFeatures(mapping, mapFrom, pos, residue,
-                    result);
-          }
+          added++;
+        }
+        if (added == toAdd)
+        {
+          break;
         }
       }
     }
index 349b5d1..a302d6e 100644 (file)
@@ -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));
+  }
 }
index cd8f9eb..f8479a3 100644 (file)
@@ -26,11 +26,15 @@ import static org.testng.AssertJUnit.assertNull;
 import static org.testng.AssertJUnit.assertSame;
 import static org.testng.AssertJUnit.assertTrue;
 
-import jalview.gui.JvOptionPane;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
+import jalview.gui.JvOptionPane;
+import jalview.util.MapList;
+
 public class SequenceFeatureTest
 {
 
@@ -285,7 +289,7 @@ public class SequenceFeatureTest
     String expected = "<br><table><tr><td>Location</td><td>TestSeq</td><td>22</td></tr>"
             + "<tr><td>Type</td><td>variant</td><td></td></tr>"
             + "<tr><td>Description</td><td>G,C</td><td></td></tr></table>";
-    assertEquals(expected, sf.getDetailsReport(seqName));
+    assertEquals(expected, sf.getDetailsReport(seqName, null));
 
     // contact feature
     sf = new SequenceFeature("Disulphide Bond", "a description", 28, 31,
@@ -293,7 +297,7 @@ public class SequenceFeatureTest
     expected = "<br><table><tr><td>Location</td><td>TestSeq</td><td>28:31</td></tr>"
             + "<tr><td>Type</td><td>Disulphide Bond</td><td></td></tr>"
             + "<tr><td>Description</td><td>a description</td><td></td></tr></table>";
-    assertEquals(expected, sf.getDetailsReport(seqName));
+    assertEquals(expected, sf.getDetailsReport(seqName, null));
 
     sf = new SequenceFeature("variant", "G,C", 22, 33,
             12.5f, "group");
@@ -306,7 +310,7 @@ public class SequenceFeatureTest
             + "<tr><td>Group</td><td>group</td><td></td></tr>"
             + "<tr><td>Child</td><td></td><td>ENSP002</td></tr>"
             + "<tr><td>Parent</td><td></td><td>ENSG001</td></tr></table>";
-    assertEquals(expected, sf.getDetailsReport(seqName));
+    assertEquals(expected, sf.getDetailsReport(seqName, null));
 
     /*
      * feature with embedded html link in description
@@ -317,6 +321,39 @@ public class SequenceFeatureTest
             + "<tr><td>Type</td><td>Pfam</td><td></td></tr>"
             + "<tr><td>Description</td><td>Fer2 Status: True Positive <a href=\"http://pfam.xfam.org/family/PF00111\">Pfam 8_8</a></td><td></td></tr>"
             + "<tr><td>Group</td><td>Uniprot</td><td></td></tr></table>";
-    assertEquals(expected, sf.getDetailsReport(seqName));
+    assertEquals(expected, sf.getDetailsReport(seqName, null));
+  }
+
+  /**
+   * Feature details report for a virtual feature should include original and
+   * mapped locations, and also derived peptide consequence if it can be
+   * determined
+   */
+  @Test(groups = { "Functional" })
+  public void testGetDetailsReport_virtualFeature()
+  {
+    SequenceI cds = new Sequence("Cds/101-121", "CCTttgAGAtttCAAatgGAT");
+    SequenceI seq = new Sequence("TestSeq/8-14", "PLRFQMD");
+    MapList map = new MapList(new int[] { 101, 118 }, new int[] { 8, 13 },
+            3, 1);
+    Mapping mapping = new Mapping(seq, map);
+    List<SequenceFeature> features = new ArrayList<>();
+    // vary ttg (Leu) to ttc (Phe)
+    SequenceFeature sf = new SequenceFeature("variant", "G,C", 106, 106,
+            null);
+    sf.setValue("alleles", "G,C"); // needed to compute peptide consequence!
+    features.add(sf);
+
+    MappedFeatures mf = new MappedFeatures(mapping, cds, 9, 'L', features);
+
+    String expected = "<br><table><tr><td>Location</td><td>Cds</td><td>106</td></tr>"
+            + "<tr><td>Peptide Location</td><td>TestSeq</td><td>9</td></tr>"
+            + "<tr><td>Type</td><td>variant</td><td></td></tr>"
+            + "<tr><td>Description</td><td>G,C</td><td></td></tr>"
+            + "<tr><td>Consequence</td><td><i>Translated by Jalview</i></td><td>p.Leu9Phe</td></tr>"
+            + "<tr><td>alleles</td><td></td><td>G,C</td></tr>"
+            + "</table>";
+
+    assertEquals(expected, sf.getDetailsReport(seq.getName(), mf));
   }
 }
index 4bd34cb..f403a57 100644 (file)
@@ -6,14 +6,17 @@ import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertSame;
 import static org.testng.Assert.assertTrue;
 
-import jalview.datamodel.SequenceFeature;
-import jalview.util.MessageManager;
-import jalview.util.matcher.Condition;
-
 import java.util.Locale;
 
 import org.testng.annotations.Test;
 
+import jalview.datamodel.SequenceFeature;
+import jalview.util.MessageManager;
+import jalview.util.matcher.Condition;
+import jalview.util.matcher.Matcher;
+import jalview.util.matcher.MatcherI;
+import junit.extensions.PA;
+
 public class FeatureMatcherTest
 {
   @Test(groups = "Functional")
@@ -222,7 +225,7 @@ public class FeatureMatcherTest
     FeatureMatcherI fm = FeatureMatcher.byAttribute(Condition.GE, "-2f",
             "AF");
     assertEquals(fm.getMatcher().getCondition(), Condition.GE);
-    assertEquals(fm.getMatcher().getFloatValue(), -2F);
+    assertEquals(PA.getValue(fm.getMatcher(), "floatValue"), -2F);
     assertEquals(fm.getMatcher().getPattern(), "-2.0");
   }
 
@@ -233,71 +236,88 @@ public class FeatureMatcherTest
     assertFalse(fm.isByLabel());
     assertFalse(fm.isByScore());
     assertEquals(fm.getAttribute(), new String[] { "AF" });
-    assertSame(Condition.LT, fm.getMatcher().getCondition());
-    assertEquals(fm.getMatcher().getFloatValue(), 1.2f);
-    assertEquals(fm.getMatcher().getPattern(), "1.2");
+    MatcherI matcher = fm.getMatcher();
+    assertSame(Condition.LT, matcher.getCondition());
+    assertEquals(PA.getValue(matcher, "floatValue"), 1.2f);
+    assertSame(PA.getValue(matcher, "patternType"),
+            Matcher.PatternType.Float);
+    assertEquals(matcher.getPattern(), "1.2");
 
     // quotes are optional, condition is not case sensitive
     fm = FeatureMatcher.fromString("AF lt '1.2'");
+    matcher = fm.getMatcher();
     assertFalse(fm.isByLabel());
     assertFalse(fm.isByScore());
     assertEquals(fm.getAttribute(), new String[] { "AF" });
-    assertSame(Condition.LT, fm.getMatcher().getCondition());
-    assertEquals(fm.getMatcher().getFloatValue(), 1.2f);
-    assertEquals(fm.getMatcher().getPattern(), "1.2");
+    assertSame(Condition.LT, matcher.getCondition());
+    assertEquals(PA.getValue(matcher, "floatValue"), 1.2F);
+    assertEquals(matcher.getPattern(), "1.2");
 
     fm = FeatureMatcher.fromString("'AF' Present");
+    matcher = fm.getMatcher();
     assertFalse(fm.isByLabel());
     assertFalse(fm.isByScore());
     assertEquals(fm.getAttribute(), new String[] { "AF" });
-    assertSame(Condition.Present, fm.getMatcher().getCondition());
+    assertSame(Condition.Present, matcher.getCondition());
+    assertSame(PA.getValue(matcher, "patternType"),
+            Matcher.PatternType.String);
 
     fm = FeatureMatcher.fromString("CSQ:Consequence contains damaging");
+    matcher = fm.getMatcher();
     assertFalse(fm.isByLabel());
     assertFalse(fm.isByScore());
     assertEquals(fm.getAttribute(), new String[] { "CSQ", "Consequence" });
-    assertSame(Condition.Contains, fm.getMatcher().getCondition());
-    assertEquals(fm.getMatcher().getPattern(), "damaging");
+    assertSame(Condition.Contains, matcher.getCondition());
+    assertEquals(matcher.getPattern(), "damaging");
 
     // keyword Label is not case sensitive
     fm = FeatureMatcher.fromString("LABEL Matches 'foobar'");
+    matcher = fm.getMatcher();
     assertTrue(fm.isByLabel());
     assertFalse(fm.isByScore());
     assertNull(fm.getAttribute());
-    assertSame(Condition.Matches, fm.getMatcher().getCondition());
-    assertEquals(fm.getMatcher().getPattern(), "foobar");
+    assertSame(Condition.Matches, matcher.getCondition());
+    assertEquals(matcher.getPattern(), "foobar");
 
     fm = FeatureMatcher.fromString("'Label' matches 'foo bar'");
+    matcher = fm.getMatcher();
     assertTrue(fm.isByLabel());
     assertFalse(fm.isByScore());
     assertNull(fm.getAttribute());
-    assertSame(Condition.Matches, fm.getMatcher().getCondition());
-    assertEquals(fm.getMatcher().getPattern(), "foo bar");
+    assertSame(Condition.Matches, matcher.getCondition());
+    assertEquals(matcher.getPattern(), "foo bar");
 
     // quotes optional on pattern
     fm = FeatureMatcher.fromString("'Label' matches foo bar");
+    matcher = fm.getMatcher();
     assertTrue(fm.isByLabel());
     assertFalse(fm.isByScore());
     assertNull(fm.getAttribute());
-    assertSame(Condition.Matches, fm.getMatcher().getCondition());
-    assertEquals(fm.getMatcher().getPattern(), "foo bar");
+    assertSame(Condition.Matches, matcher.getCondition());
+    assertEquals(matcher.getPattern(), "foo bar");
 
-    fm = FeatureMatcher.fromString("Score GE 12.2");
+    // integer condition
+    fm = FeatureMatcher.fromString("Score GE 12");
+    matcher = fm.getMatcher();
     assertFalse(fm.isByLabel());
     assertTrue(fm.isByScore());
     assertNull(fm.getAttribute());
-    assertSame(Condition.GE, fm.getMatcher().getCondition());
-    assertEquals(fm.getMatcher().getPattern(), "12.2");
-    assertEquals(fm.getMatcher().getFloatValue(), 12.2f);
+    assertSame(Condition.GE, matcher.getCondition());
+    assertEquals(matcher.getPattern(), "12");
+    assertEquals(PA.getValue(matcher, "floatValue"), 0f);
+    assertEquals(PA.getValue(matcher, "longValue"), 12L);
+    assertSame(PA.getValue(matcher, "patternType"),
+            Matcher.PatternType.Integer);
 
     // keyword Score is not case sensitive
     fm = FeatureMatcher.fromString("'SCORE' ge '12.2'");
+    matcher = fm.getMatcher();
     assertFalse(fm.isByLabel());
     assertTrue(fm.isByScore());
     assertNull(fm.getAttribute());
-    assertSame(Condition.GE, fm.getMatcher().getCondition());
-    assertEquals(fm.getMatcher().getPattern(), "12.2");
-    assertEquals(fm.getMatcher().getFloatValue(), 12.2f);
+    assertSame(Condition.GE, matcher.getCondition());
+    assertEquals(matcher.getPattern(), "12.2");
+    assertEquals(PA.getValue(matcher, "floatValue"), 12.2F);
 
     // invalid numeric pattern
     assertNull(FeatureMatcher.fromString("Score eq twelve"));
index fd4bd4b..f09c7c7 100644 (file)
@@ -4,6 +4,13 @@ import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 
+import java.awt.Color;
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+
+import org.testng.annotations.Test;
+
 import jalview.api.FeatureColourI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
@@ -17,13 +24,6 @@ import jalview.schemes.FeatureColourTest;
 import jalview.util.matcher.Condition;
 import jalview.viewmodel.seqfeatures.FeatureRendererModel;
 
-import java.awt.Color;
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-
-import org.testng.annotations.Test;
-
 public class FeatureSettingsTest
 {
   /**
@@ -160,7 +160,7 @@ public class FeatureSettingsTest
     assertEquals(fr.getFeatureFilter("type2").toStableString(),
             "(Score LE 2.4) AND (Score GT 1.1)");
     assertEquals(fr.getFeatureFilter("type3").toStableString(),
-            "(AF Contains X) OR (CSQ:PolyPhen NE 0.0)");
+            "(AF Contains X) OR (CSQ:PolyPhen NE 0)");
   }
 
   /**
index 9b21274..24697c0 100644 (file)
@@ -68,13 +68,27 @@ public class FreeUpMemoryTest
     File f = generateAlignment();
     f.deleteOnExit();
 
+    long expectedMin = 35L;
+    long usedMemoryAtStart=getUsedMemory();
+    if (usedMemoryAtStart>expectedMin)
+    {
+      System.err.println("used memory before test is "+usedMemoryAtStart+" > "+expectedMin+"MB .. adjusting minimum.");
+      expectedMin = usedMemoryAtStart;
+    }
     doStuffInJalview(f);
 
     Desktop.instance.closeAll_actionPerformed(null);
 
-    checkUsedMemory(35L);
+    checkUsedMemory(expectedMin);
   }
 
+  private static long getUsedMemory()
+  {
+    long availableMemory = Runtime.getRuntime().totalMemory() / ONE_MB;
+    long freeMemory = Runtime.getRuntime().freeMemory() / ONE_MB;
+    long usedMemory = availableMemory - freeMemory;
+    return usedMemory;
+  }
   /**
    * Requests garbage collection and then checks whether remaining memory in use
    * is less than the expected value (in Megabytes)
@@ -101,10 +115,7 @@ public class FreeUpMemoryTest
     /*
      * check used memory is 'reasonably low'
      */
-    long availableMemory = Runtime.getRuntime().totalMemory() / ONE_MB;
-    long freeMemory = Runtime.getRuntime().freeMemory() / ONE_MB;
-    long usedMemory = availableMemory - freeMemory;
-
+    long usedMemory = getUsedMemory();
     /*
      * sanity check - fails if any frame was added after
      * closeAll_actionPerformed
index 298ae6b..b753e94 100644 (file)
@@ -27,6 +27,18 @@ import static org.testng.AssertJUnit.assertSame;
 import static org.testng.AssertJUnit.assertTrue;
 import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
 
+import java.awt.Color;
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
 import jalview.api.FeatureColourI;
 import jalview.api.FeatureRenderer;
 import jalview.datamodel.Alignment;
@@ -47,18 +59,7 @@ import jalview.structure.StructureSelectionManager;
 import jalview.util.matcher.Condition;
 import jalview.viewmodel.seqfeatures.FeatureRendererModel;
 import jalview.viewmodel.seqfeatures.FeatureRendererModel.FeatureSettingsBean;
-
-import java.awt.Color;
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
+import junit.extensions.PA;
 
 public class FeaturesFileTest
 {
@@ -725,7 +726,7 @@ public class FeaturesFileTest
     assertTrue(matcher.isByScore());
     assertSame(matcher.getMatcher().getCondition(), Condition.LT);
     assertEquals(matcher.getMatcher().getPattern(), "1.3");
-    assertEquals(matcher.getMatcher().getFloatValue(), 1.3f);
+    assertEquals(PA.getValue(matcher.getMatcher(), "floatValue"), 1.3f);
 
     assertFalse(matchers.hasNext());
   }
index 42183ca..772ed2b 100644 (file)
@@ -23,8 +23,18 @@ package jalview.io;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertTrue;
 
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
 import jalview.api.FeatureColourI;
 import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.MappedFeatures;
+import jalview.datamodel.Mapping;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
@@ -32,16 +42,8 @@ import jalview.gui.JvOptionPane;
 import jalview.io.gff.GffConstants;
 import jalview.renderer.seqfeatures.FeatureRenderer;
 import jalview.schemes.FeatureColour;
+import jalview.util.MapList;
 import jalview.viewmodel.seqfeatures.FeatureRendererModel;
-
-import java.awt.Color;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
 import junit.extensions.PA;
 
 public class SequenceAnnotationReportTest
@@ -57,24 +59,24 @@ public class SequenceAnnotationReportTest
   @Test(groups = "Functional")
   public void testAppendFeature_disulfideBond()
   {
-    SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+    SequenceAnnotationReport sar = new SequenceAnnotationReport(false);
     StringBuilder sb = new StringBuilder();
     sb.append("123456");
     SequenceFeature sf = new SequenceFeature("disulfide bond", "desc", 1,
             3, 1.2f, "group");
 
     // residuePos == 2 does not match start or end of feature, nothing done:
-    sar.appendFeature(sb, 2, null, sf, null);
+    sar.appendFeature(sb, 2, null, sf, null, 0);
     assertEquals("123456", sb.toString());
 
     // residuePos == 1 matches start of feature, text appended (but no <br/>)
     // feature score is not included
-    sar.appendFeature(sb, 1, null, sf, null);
+    sar.appendFeature(sb, 1, null, sf, null, 0);
     assertEquals("123456disulfide bond 1:3", sb.toString());
 
     // residuePos == 3 matches end of feature, text appended
     // <br/> is prefixed once sb.length() > 6
-    sar.appendFeature(sb, 3, null, sf, null);
+    sar.appendFeature(sb, 3, null, sf, null, 0);
     assertEquals("123456disulfide bond 1:3<br/>disulfide bond 1:3",
             sb.toString());
   }
@@ -82,13 +84,13 @@ public class SequenceAnnotationReportTest
   @Test(groups = "Functional")
   public void testAppendFeatures_longText()
   {
-    SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+    SequenceAnnotationReport sar = new SequenceAnnotationReport(false);
     StringBuilder sb = new StringBuilder();
     String longString = "Abcd".repeat(50);
     SequenceFeature sf = new SequenceFeature("sequence", longString, 1, 3,
             "group");
 
-    sar.appendFeature(sb, 1, null, sf, null);
+    sar.appendFeature(sb, 1, null, sf, null, 0);
     assertTrue(sb.length() < 100);
 
     List<SequenceFeature> sfl = new ArrayList<>();
@@ -103,7 +105,7 @@ public class SequenceAnnotationReportTest
     sfl.add(sf);
     sfl.add(sf);
     sfl.add(sf);
-    int n = sar.appendFeaturesLengthLimit(sb, 1, sfl,
+    int n = sar.appendFeatures(sb, 1, sfl,
             new FeatureRenderer(null), 200); // text should terminate before 200 characters
     String s = sb.toString();
     assertTrue(s.length() < 200);
@@ -114,27 +116,27 @@ public class SequenceAnnotationReportTest
   @Test(groups = "Functional")
   public void testAppendFeature_status()
   {
-    SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+    SequenceAnnotationReport sar = new SequenceAnnotationReport(false);
     StringBuilder sb = new StringBuilder();
     SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3,
             Float.NaN, "group");
     sf.setStatus("Confirmed");
 
-    sar.appendFeature(sb, 1, null, sf, null);
+    sar.appendFeature(sb, 1, null, sf, null, 0);
     assertEquals("METAL 1 3; Fe2-S; (Confirmed)", sb.toString());
   }
 
   @Test(groups = "Functional")
   public void testAppendFeature_withScore()
   {
-    SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+    SequenceAnnotationReport sar = new SequenceAnnotationReport(false);
     StringBuilder sb = new StringBuilder();
     SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3, 1.3f,
             "group");
 
     FeatureRendererModel fr = new FeatureRenderer(null);
     Map<String, float[][]> minmax = fr.getMinMax();
-    sar.appendFeature(sb, 1, fr, sf, null);
+    sar.appendFeature(sb, 1, fr, sf, null, 0);
     /*
      * map has no entry for this feature type - score is not shown:
      */
@@ -144,7 +146,7 @@ public class SequenceAnnotationReportTest
      * map has entry for this feature type - score is shown:
      */
     minmax.put("METAL", new float[][] { { 0f, 1f }, null });
-    sar.appendFeature(sb, 1, fr, sf, null);
+    sar.appendFeature(sb, 1, fr, sf, null, 0);
     // <br/> is appended to a buffer > 6 in length
     assertEquals("METAL 1 3; Fe2-S<br/>METAL 1 3; Fe2-S Score=1.3",
             sb.toString());
@@ -154,19 +156,19 @@ public class SequenceAnnotationReportTest
      */
     minmax.put("METAL", new float[][] { { 2f, 2f }, null });
     sb.setLength(0);
-    sar.appendFeature(sb, 1, fr, sf, null);
+    sar.appendFeature(sb, 1, fr, sf, null, 0);
     assertEquals("METAL 1 3; Fe2-S", sb.toString());
   }
 
   @Test(groups = "Functional")
   public void testAppendFeature_noScore()
   {
-    SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+    SequenceAnnotationReport sar = new SequenceAnnotationReport(false);
     StringBuilder sb = new StringBuilder();
     SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3,
             Float.NaN, "group");
 
-    sar.appendFeature(sb, 1, null, sf, null);
+    sar.appendFeature(sb, 1, null, sf, null, 0);
     assertEquals("METAL 1 3; Fe2-S", sb.toString());
   }
 
@@ -176,7 +178,7 @@ public class SequenceAnnotationReportTest
   @Test(groups = "Functional")
   public void testAppendFeature_colouredByAttribute()
   {
-    SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+    SequenceAnnotationReport sar = new SequenceAnnotationReport(false);
     StringBuilder sb = new StringBuilder();
     SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3,
             Float.NaN, "group");
@@ -186,7 +188,7 @@ public class SequenceAnnotationReportTest
      * first with no colour by attribute
      */
     FeatureRendererModel fr = new FeatureRenderer(null);
-    sar.appendFeature(sb, 1, fr, sf, null);
+    sar.appendFeature(sb, 1, fr, sf, null, 0);
     assertEquals("METAL 1 3; Fe2-S", sb.toString());
 
     /*
@@ -197,7 +199,7 @@ public class SequenceAnnotationReportTest
     fc.setAttributeName("Pfam");
     fr.setColour("METAL", fc);
     sb.setLength(0);
-    sar.appendFeature(sb, 1, fr, sf, null);
+    sar.appendFeature(sb, 1, fr, sf, null, 0);
     assertEquals("METAL 1 3; Fe2-S", sb.toString()); // no change
 
     /*
@@ -205,7 +207,7 @@ public class SequenceAnnotationReportTest
      */
     fc.setAttributeName("clinical_significance");
     sb.setLength(0);
-    sar.appendFeature(sb, 1, fr, sf, null);
+    sar.appendFeature(sb, 1, fr, sf, null, 0);
     assertEquals("METAL 1 3; Fe2-S; clinical_significance=Benign",
             sb.toString());
   }
@@ -213,7 +215,7 @@ public class SequenceAnnotationReportTest
   @Test(groups = "Functional")
   public void testAppendFeature_withScoreStatusAttribute()
   {
-    SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+    SequenceAnnotationReport sar = new SequenceAnnotationReport(false);
     StringBuilder sb = new StringBuilder();
     SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3, 1.3f,
             "group");
@@ -227,7 +229,7 @@ public class SequenceAnnotationReportTest
     fc.setAttributeName("clinical_significance");
     fr.setColour("METAL", fc);
     minmax.put("METAL", new float[][] { { 0f, 1f }, null });
-    sar.appendFeature(sb, 1, fr, sf, null);
+    sar.appendFeature(sb, 1, fr, sf, null, 0);
 
     assertEquals(
             "METAL 1 3; Fe2-S Score=1.3; (Confirmed); clinical_significance=Benign",
@@ -237,38 +239,38 @@ public class SequenceAnnotationReportTest
   @Test(groups = "Functional")
   public void testAppendFeature_DescEqualsType()
   {
-    SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+    SequenceAnnotationReport sar = new SequenceAnnotationReport(false);
     StringBuilder sb = new StringBuilder();
     SequenceFeature sf = new SequenceFeature("METAL", "METAL", 1, 3,
             Float.NaN, "group");
 
     // description is not included if it duplicates type:
-    sar.appendFeature(sb, 1, null, sf, null);
+    sar.appendFeature(sb, 1, null, sf, null, 0);
     assertEquals("METAL 1 3", sb.toString());
 
     sb.setLength(0);
     sf.setDescription("Metal");
     // test is case-sensitive:
-    sar.appendFeature(sb, 1, null, sf, null);
+    sar.appendFeature(sb, 1, null, sf, null, 0);
     assertEquals("METAL 1 3; Metal", sb.toString());
   }
 
   @Test(groups = "Functional")
   public void testAppendFeature_stripHtml()
   {
-    SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+    SequenceAnnotationReport sar = new SequenceAnnotationReport(false);
     StringBuilder sb = new StringBuilder();
     SequenceFeature sf = new SequenceFeature("METAL",
             "<html><body>hello<em>world</em></body></html>", 1, 3,
             Float.NaN, "group");
 
-    sar.appendFeature(sb, 1, null, sf, null);
+    sar.appendFeature(sb, 1, null, sf, null, 0);
     // !! strips off </body> but not <body> ??
     assertEquals("METAL 1 3; <body>hello<em>world</em>", sb.toString());
 
     sb.setLength(0);
     sf.setDescription("<br>&kHD>6");
-    sar.appendFeature(sb, 1, null, sf, null);
+    sar.appendFeature(sb, 1, null, sf, null, 0);
     // if no <html> tag, html-encodes > and < (only):
     assertEquals("METAL 1 3; &lt;br&gt;&kHD&gt;6", sb.toString());
   }
@@ -276,7 +278,7 @@ public class SequenceAnnotationReportTest
   @Test(groups = "Functional")
   public void testCreateSequenceAnnotationReport()
   {
-    SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+    SequenceAnnotationReport sar = new SequenceAnnotationReport(false);
     StringBuilder sb = new StringBuilder();
 
     SequenceI seq = new Sequence("s1", "MAKLKRFQSSTLL");
@@ -398,7 +400,7 @@ public class SequenceAnnotationReportTest
   @Test(groups = "Functional")
   public void testCreateSequenceAnnotationReport_withEllipsis()
   {
-    SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+    SequenceAnnotationReport sar = new SequenceAnnotationReport(false);
     StringBuilder sb = new StringBuilder();
   
     SequenceI seq = new Sequence("s1", "ABC");
@@ -424,4 +426,63 @@ public class SequenceAnnotationReportTest
             .endsWith(
                     "<br/>PDB7 3iu1<br/>PDB8,...<br/>(Output Sequence Details to list all database references)</i>"));
   }
+
+  /**
+   * Test adding a linked feature to the tooltip
+   */
+  @Test(groups = "Functional")
+  public void testAppendFeature_virtualFeature()
+  {
+    /*
+     * map CDS to peptide sequence
+     */
+    SequenceI cds = new Sequence("Cds/101-121", "CCTttgAGAtttCAAatgGAT");
+    SequenceI peptide = new Sequence("Peptide/8-14", "PLRFQMD");
+    MapList map = new MapList(new int[] { 101, 118 }, new int[] { 8, 13 },
+            3, 1);
+    Mapping mapping = new Mapping(peptide, map);
+
+    /*
+     * assume variant feature found at CDS position 106 G>C
+     */
+    List<SequenceFeature> features = new ArrayList<>();
+    // vary ttg (Leu) to ttc (Phe)
+    SequenceFeature sf = new SequenceFeature("variant", "G,C", 106, 106,
+            Float.NaN, null);
+    features.add(sf);
+    MappedFeatures mf = new MappedFeatures(mapping, cds, 9, 'L', features);
+
+    StringBuilder sb = new StringBuilder();
+    SequenceAnnotationReport sar = new SequenceAnnotationReport(false);
+    sar.appendFeature(sb, 1, null, sf, mf, 0);
+
+    /*
+     * linked feature shown in tooltip in protein coordinates
+     */
+    assertEquals("variant 9; G,C", sb.toString());
+
+    /*
+     * adding "alleles" attribute to variant allows peptide consequence
+     * to be calculated and added to the tooltip
+     */
+    sf.setValue("alleles", "G,C");
+    sb = new StringBuilder();
+    sar.appendFeature(sb, 1, null, sf, mf, 0);
+    assertEquals("variant 9; G,C p.Leu9Phe", sb.toString());
+
+    /*
+     * now a virtual peptide feature on CDS
+     * feature at 11-12 on peptide maps to 110-115 on CDS
+     * here we test for tooltip at 113 (t)
+     */
+    SequenceFeature sf2 = new SequenceFeature("metal", "Fe", 11, 12,
+            2.3f, "Uniprot");
+    features.clear();
+    features.add(sf2);
+    mapping = new Mapping(peptide, map);
+    mf = new MappedFeatures(mapping, peptide, 113, 't', features);
+    sb = new StringBuilder();
+    sar.appendFeature(sb, 1, null, sf2, mf, 0);
+    assertEquals("metal 110 115; Fe Score=2.3", sb.toString());
+  }
 }
index ba4312a..9fdd7b9 100644 (file)
  */
 package jalview.io;
 
+import static org.testng.Assert.assertTrue;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertNotNull;
 import static org.testng.AssertJUnit.assertTrue;
 import static org.testng.AssertJUnit.fail;
 
+import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
+import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.gui.JvOptionPane;
+import jalview.util.DBRefUtils;
 
 import java.io.File;
 import java.util.Arrays;
@@ -93,14 +98,55 @@ public class StockholmFileTest
   }
 
   /**
+   * JAL-3529 - verify uniprot refs for sequences are output for sequences
+   * retrieved via Pfam
+   */
+  @Test(groups = { "Functional" })
+  public void dbrefOutput() throws Exception
+  {
+    // sequences retrieved in a Pfam domain alignment also have a PFAM database
+    // reference
+    SequenceI sq = new Sequence("FER2_SPIOL", "AASSDDDFFF");
+    sq.addDBRef(new DBRefEntry("UNIPROT", "1", "P00224"));
+    sq.addDBRef(new DBRefEntry("PFAM", "1", "P00224.1"));
+    sq.addDBRef(new DBRefEntry("PFAM", "1", "PF00111"));
+    AppletFormatAdapter af = new AppletFormatAdapter();
+    String toStockholm = af.formatSequences(FileFormat.Stockholm,
+            new Alignment(new SequenceI[]
+            { sq }), false);
+    System.out.println(toStockholm);
+    // bleh - java.util.Regex sucks
+    assertTrue(
+            Pattern.compile(
+                    "^#=GS\\s+FER2_SPIOL(/\\d+-\\d+)?\\s+AC\\s+P00224$",
+                    Pattern.MULTILINE).matcher(toStockholm)
+                    .find(),
+            "Couldn't locate UNIPROT Accession in generated Stockholm file.");
+    AlignmentI fromStockholm = af.readFile(toStockholm,
+            DataSourceType.PASTE, FileFormat.Stockholm);
+    SequenceI importedSeq = fromStockholm.getSequenceAt(0);
+    assertTrue(importedSeq.getDBRefs().length == 1,
+            "Expected just one database reference to be added to sequence.");
+    assertTrue(
+            importedSeq.getDBRefs()[0].getAccessionId().indexOf(" ") == -1,
+            "Spaces were found in accession ID.");
+    List<DBRefEntry> dbrefs = DBRefUtils.searchRefs(importedSeq.getDBRefs(),
+            "P00224");
+    assertTrue(dbrefs.size() == 1,
+            "Couldn't find Uniprot DBRef on re-imported sequence.");
+
+  }
+
+  /**
    * test alignment data in given file can be imported, exported and reimported
    * with no dataloss
    * 
    * @param f
-   *          - source datafile (IdentifyFile.identify() should work with it)
+   *                               - source datafile (IdentifyFile.identify()
+   *                               should work with it)
    * @param ioformat
-   *          - label for IO class used to write and read back in the data from
-   *          f
+   *                               - label for IO class used to write and read
+   *                               back in the data from f
    * @param ignoreFeatures
    * @param ignoreRowVisibility
    * @param allowNullAnnotations
index 80ed4c1..eb66416 100644 (file)
@@ -1035,7 +1035,7 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     assertEquals(fr.getFeatureFilter("type2").toStableString(),
             "(Score LE 2.4) AND (Score GT 1.1)");
     assertEquals(fr.getFeatureFilter("type3").toStableString(),
-            "(AF Contains X) OR (CSQ:PolyPhen NE 0.0)");
+            "(AF Contains X) OR (CSQ:PolyPhen NE 0)");
   }
 
   private void addFeature(SequenceI seq, String featureType, int score)
index d3e6221..f92e454 100644 (file)
@@ -136,6 +136,11 @@ public class DBRefUtilsTest
     assertEquals("1.2", ref.getVersion());
     assertEquals("a7890", ref.getAccessionId());
     assertTrue(seq.getAllPDBEntries().isEmpty());
+    SequenceI seq2 = new Sequence("Seq2", "ABCD");
+    // Check that whitespace doesn't confuse parseToDbRef
+    DBRefEntry ref2 = DBRefUtils.parseToDbRef(seq2, "EMBL", "1.2",
+            " a7890");
+    assertEquals(ref, ref2);
   }
 
   /**
index a47fb60..c964195 100644 (file)
@@ -3,6 +3,7 @@ package jalview.util.matcher;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertSame;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
@@ -10,6 +11,7 @@ import java.util.Locale;
 
 import org.testng.annotations.Test;
 
+import jalview.util.matcher.Matcher.PatternType;
 import junit.extensions.PA;
 
 public class MatcherTest
@@ -21,22 +23,44 @@ public class MatcherTest
     assertEquals(m.getCondition(), Condition.Contains);
     assertEquals(m.getPattern(), "foo");
     assertEquals(PA.getValue(m, "uppercasePattern"), "FOO");
-    assertEquals(m.getFloatValue(), 0f);
+    assertEquals(PA.getValue(m, "floatValue"), 0f);
+    assertEquals(PA.getValue(m, "longValue"), 0L);
+    assertSame(PA.getValue(m, "patternType"), PatternType.String);
 
     m = new Matcher(Condition.GT, -2.1f);
     assertEquals(m.getCondition(), Condition.GT);
     assertEquals(m.getPattern(), "-2.1");
-    assertEquals(m.getFloatValue(), -2.1f);
+    assertEquals(PA.getValue(m, "floatValue"), -2.1f);
+    assertEquals(PA.getValue(m, "longValue"), 0L);
+    assertSame(PA.getValue(m, "patternType"), PatternType.Float);
 
     m = new Matcher(Condition.NotContains, "-1.2f");
     assertEquals(m.getCondition(), Condition.NotContains);
     assertEquals(m.getPattern(), "-1.2f");
-    assertEquals(m.getFloatValue(), 0f);
+    assertEquals(PA.getValue(m, "floatValue"), 0f);
+    assertEquals(PA.getValue(m, "longValue"), 0L);
+    assertSame(PA.getValue(m, "patternType"), PatternType.String);
 
     m = new Matcher(Condition.GE, "-1.2f");
     assertEquals(m.getCondition(), Condition.GE);
     assertEquals(m.getPattern(), "-1.2");
-    assertEquals(m.getFloatValue(), -1.2f);
+    assertEquals(PA.getValue(m, "floatValue"), -1.2f);
+    assertEquals(PA.getValue(m, "longValue"), 0L);
+    assertSame(PA.getValue(m, "patternType"), PatternType.Float);
+
+    m = new Matcher(Condition.GE, "113890813");
+    assertEquals(m.getCondition(), Condition.GE);
+    assertEquals(m.getPattern(), "113890813");
+    assertEquals(PA.getValue(m, "floatValue"), 0f);
+    assertEquals(PA.getValue(m, "longValue"), 113890813L);
+    assertSame(PA.getValue(m, "patternType"), PatternType.Integer);
+
+    m = new Matcher(Condition.GE, "-987f");
+    assertEquals(m.getCondition(), Condition.GE);
+    assertEquals(m.getPattern(), "-987.0");
+    assertEquals(PA.getValue(m, "floatValue"), -987f);
+    assertEquals(PA.getValue(m, "longValue"), 0L);
+    assertSame(PA.getValue(m, "patternType"), PatternType.Float);
 
     try
     {
@@ -53,7 +77,25 @@ public class MatcherTest
       fail("Expected exception");
     } catch (NumberFormatException e)
     {
-      // expected
+      // expected - see Long.valueOf()
+    }
+
+    try
+    {
+      new Matcher(Condition.LT, "123_456");
+      fail("Expected exception");
+    } catch (NumberFormatException e)
+    {
+      // expected - see Long.valueOf()
+    }
+
+    try
+    {
+      new Matcher(Condition.LT, "123456L");
+      fail("Expected exception");
+    } catch (NumberFormatException e)
+    {
+      // expected - see Long.valueOf()
     }
   }
 
@@ -82,7 +124,7 @@ public class MatcherTest
     /*
      * >= test
      */
-    m = new Matcher(Condition.GE, 2f);
+    m = new Matcher(Condition.GE, "2f");
     assertTrue(m.matches("2"));
     assertTrue(m.matches("2.1"));
     assertFalse(m.matches("1.9"));
@@ -98,7 +140,7 @@ public class MatcherTest
     /*
      * <= test
      */
-    m = new Matcher(Condition.LE, 2f);
+    m = new Matcher(Condition.LE, "2.0f");
     assertTrue(m.matches("2"));
     assertFalse(m.matches("2.1"));
     assertTrue(m.matches("1.9"));
@@ -112,17 +154,25 @@ public class MatcherTest
     assertTrue(m.matches("1.9"));
   }
 
+  /**
+   * Verifies that all numeric match conditions fail when applied to non-numeric
+   * or null values
+   */
   @Test(groups = "Functional")
-  public void testMatches_floatNullOrInvalid()
+  public void testNumericMatch_nullOrInvalidValue()
   {
     for (Condition cond : Condition.values())
     {
       if (cond.isNumeric())
       {
-        MatcherI m = new Matcher(cond, 2f);
-        assertFalse(m.matches(null));
-        assertFalse(m.matches(""));
-        assertFalse(m.matches("two"));
+        MatcherI m1 = new Matcher(cond, 2.1f);
+        MatcherI m2 = new Matcher(cond, 2345L);
+        assertFalse(m1.matches(null));
+        assertFalse(m1.matches(""));
+        assertFalse(m1.matches("two"));
+        assertFalse(m2.matches(null));
+        assertFalse(m2.matches(""));
+        assertFalse(m2.matches("two"));
       }
     }
   }
@@ -166,7 +216,7 @@ public class MatcherTest
      */
     m = new Matcher(Condition.NotMatches, "benign");
     assertFalse(m.matches("benign"));
-    assertFalse(m.matches(" Benign ")); // trim before testing
+    assertFalse(m.matches(" Benign ")); // trimmed before testing
     assertTrue(m.matches("MOSTLY BENIGN"));
     assertTrue(m.matches("pathogenic"));
     assertTrue(m.matches(null));
@@ -188,11 +238,18 @@ public class MatcherTest
     assertTrue(m.matches(null));
 
     /*
-     * a float with a string match condition will be treated as string
+     * a number with a string match condition will be treated as string
+     * (these cases shouldn't arise as the match() method is coded)
      */
     Matcher m1 = new Matcher(Condition.Contains, "32");
-    assertFalse(m1.matches(-203f));
-    assertTrue(m1.matches(-4321.0f));
+    assertFalse(m1.matchesFloat("-203f", 0f));
+    assertTrue(m1.matchesFloat("-4321.0f", 0f));
+    assertFalse(m1.matchesFloat("-203", 0f));
+    assertTrue(m1.matchesFloat("-4321", 0f));
+    assertFalse(m1.matchesLong("-203"));
+    assertTrue(m1.matchesLong("-4321"));
+    assertFalse(m1.matchesLong("-203f"));
+    assertTrue(m1.matchesLong("-4321.0f"));
   }
 
   /**
@@ -202,9 +259,15 @@ public class MatcherTest
   public void testMatches_floatWithStringCondition()
   {
     MatcherI m = new Matcher(Condition.Contains, 1.2e-6f);
+    assertEquals(m.getPattern(), "1.2E-6");
+    assertEquals(PA.getValue(m, "uppercasePattern"), "1.2E-6");
+    assertEquals(PA.getValue(m, "floatValue"), 0f);
+    assertEquals(PA.getValue(m, "longValue"), 0L);
+    assertSame(PA.getValue(m, "patternType"), PatternType.String);
     assertTrue(m.matches("1.2e-6"));
 
     m = new Matcher(Condition.Contains, 0.0000001f);
+    assertEquals(m.getPattern(), "1.0E-7");
     assertTrue(m.matches("1.0e-7"));
     assertTrue(m.matches("1.0E-7"));
     assertFalse(m.matches("0.0000001f"));
@@ -218,6 +281,9 @@ public class MatcherTest
     MatcherI m = new Matcher(Condition.LT, 1.2e-6f);
     assertEquals(m.toString(), "< 1.2E-6");
 
+    m = new Matcher(Condition.GE, "20200413");
+    assertEquals(m.toString(), ">= 20200413");
+
     m = new Matcher(Condition.NotMatches, "ABC");
     assertEquals(m.toString(), "Does not match 'ABC'");
 
@@ -242,7 +308,7 @@ public class MatcherTest
     assertFalse(m.equals(new Matcher(Condition.NotMatches, "def")));
 
     /*
-     * numeric conditions
+     * numeric conditions - float values
      */
     m = new Matcher(Condition.LT, -1f);
     assertFalse(m.equals(null));
@@ -256,6 +322,19 @@ public class MatcherTest
     assertFalse(m.equals(new Matcher(Condition.NE, -1f)));
     assertFalse(m.equals(new Matcher(Condition.LT, 1f)));
     assertFalse(m.equals(new Matcher(Condition.LT, -1.1f)));
+
+    /*
+     * numeric conditions - integer values
+     */
+    m = new Matcher(Condition.LT, -123456);
+    assertFalse(m.equals(null));
+    assertFalse(m.equals("foo"));
+    assertTrue(m.equals(m));
+    assertTrue(m.equals(new Matcher(Condition.LT, -123456)));
+    assertFalse(m.equals(new Matcher(Condition.LT, +123456)));
+    assertTrue(m.equals(new Matcher(Condition.LT, "-123456")));
+    assertFalse(m.equals(new Matcher(Condition.LT, -123456f)));
+    assertFalse(m.equals(new Matcher(Condition.LT, "-123456f")));
   }
 
   @Test(groups = "Functional")
@@ -270,4 +349,76 @@ public class MatcherTest
     assertNotEquals(m1.hashCode(), m4.hashCode());
     assertNotEquals(m3.hashCode(), m4.hashCode());
   }
+
+  /**
+   * Tests for integer comparison conditions
+   */
+  @Test(groups = "Functional")
+  public void testMatches_long()
+  {
+    /*
+     * EQUALS test
+     */
+    MatcherI m = new Matcher(Condition.EQ, 2);
+    assertTrue(m.matches("2"));
+    assertTrue(m.matches("+2"));
+    assertFalse(m.matches("3"));
+    // a float value may be passed to an integer matcher
+    assertTrue(m.matches("2.0"));
+    assertTrue(m.matches("2.000000f"));
+    assertFalse(m.matches("2.01"));
+  
+    /*
+     * NOT EQUALS test
+     */
+    m = new Matcher(Condition.NE, 123);
+    assertFalse(m.matches("123"));
+    assertFalse(m.matches("123.0"));
+    assertTrue(m.matches("-123"));
+  
+    /*
+     * >= test
+     */
+    m = new Matcher(Condition.GE, "113890813");
+    assertTrue(m.matches("113890813"));
+    assertTrue(m.matches("113890814"));
+    assertFalse(m.matches("-113890813"));
+  
+    /*
+     * > test
+     */
+    m = new Matcher(Condition.GT, 113890813);
+    assertFalse(m.matches("113890813"));
+    assertTrue(m.matches("113890814"));
+  
+    /*
+     * <= test
+     */
+    m = new Matcher(Condition.LE, "113890813");
+    assertTrue(m.matches("113890813"));
+    assertFalse(m.matches("113890814"));
+    assertTrue(m.matches("113890812"));
+  
+    /*
+     * < test
+     */
+    m = new Matcher(Condition.LT, 113890813);
+    assertFalse(m.matches("113890813"));
+    assertFalse(m.matches("113890814"));
+    assertTrue(m.matches("113890812"));
+  }
+
+  /**
+   * Tests comparing a float value with an integer condition
+   */
+  @Test(groups = "Functional")
+  public void testMatches_floatValueIntegerCondition()
+  {
+    MatcherI m = new Matcher(Condition.GT, 1234);
+    assertEquals(PA.getValue(m, "longValue"), 1234L);
+    assertSame(PA.getValue(m, "patternType"), PatternType.Integer);
+    assertTrue(m.matches("1235"));
+    assertTrue(m.matches("9867.345"));
+    assertTrue(m.matches("9867.345f"));
+  }
 }
index eb585d9..a02cd6d 100644 (file)
@@ -684,7 +684,7 @@ return console.askYesNo(message, true);
               </action>
               <action id="1525" beanClass="com.install4j.runtime.beans.actions.files.DeleteFileAction" actionElevationType="elevated" rollbackBarrierExitCode="0">
                 <serializedBean>
-                  <property name="files" type="array" class="java.io.File" length="32">
+                  <property name="files" type="array" class="java.io.File" length="36">
                     <element index="0">
                       <object class="java.io.File">
                         <string>jre</string>
@@ -702,117 +702,117 @@ return console.askYesNo(message, true);
                     </element>
                     <element index="3">
                       <object class="java.io.File">
-                        <string>${compiler:GETDOWN_DIST_DIR}</string>
+                        <string>getdown-launcher.jar</string>
                       </object>
                     </element>
                     <element index="4">
                       <object class="java.io.File">
-                        <string>${compiler:GETDOWN_ALT_DIR}</string>
+                        <string>getdown-launcher-old.jar</string>
                       </object>
                     </element>
                     <element index="5">
                       <object class="java.io.File">
-                        <string>${compiler:GETDOWN_RESOURCE_DIR}</string>
+                        <string>getdown-launcher-new.jar</string>
                       </object>
                     </element>
                     <element index="6">
                       <object class="java.io.File">
-                        <string>getdown-launcher.jar</string>
+                        <string>gettingdown.lock</string>
                       </object>
                     </element>
                     <element index="7">
                       <object class="java.io.File">
-                        <string>getdown-launcher-old.jar</string>
+                        <string>jre.zip</string>
                       </object>
                     </element>
                     <element index="8">
                       <object class="java.io.File">
-                        <string>getdown-launcher-new.jar</string>
+                        <string>digest.txt</string>
                       </object>
                     </element>
                     <element index="9">
                       <object class="java.io.File">
-                        <string>*.jarv</string>
+                        <string>digest2.txt</string>
                       </object>
                     </element>
                     <element index="10">
                       <object class="java.io.File">
-                        <string>gettingdown.lock</string>
+                        <string>getdown-launcher.jarv</string>
                       </object>
                     </element>
                     <element index="11">
                       <object class="java.io.File">
-                        <string>*.log</string>
+                        <string>getdown-launcher-new.jarv</string>
                       </object>
                     </element>
                     <element index="12">
                       <object class="java.io.File">
-                        <string>*.txt</string>
+                        <string>launcher.log</string>
                       </object>
                     </element>
                     <element index="13">
                       <object class="java.io.File">
-                        <string>*_new</string>
+                        <string>proxy.txt</string>
                       </object>
                     </element>
                     <element index="14">
                       <object class="java.io.File">
-                        <string>digest.txt</string>
+                        <string>build_properties</string>
                       </object>
                     </element>
                     <element index="15">
                       <object class="java.io.File">
-                        <string>digest2.txt</string>
+                        <string>channel_launch*.jvl</string>
                       </object>
                     </element>
                     <element index="16">
                       <object class="java.io.File">
-                        <string>getdown-launcher.jarv</string>
+                        <string>jalview*.jvl</string>
                       </object>
                     </element>
                     <element index="17">
                       <object class="java.io.File">
-                        <string>getdown-launcher-new.jarv</string>
+                        <string>*.jarv</string>
                       </object>
                     </element>
                     <element index="18">
                       <object class="java.io.File">
-                        <string>channel_launch*.jvl</string>
+                        <string>*.log</string>
                       </object>
                     </element>
                     <element index="19">
                       <object class="java.io.File">
-                        <string>launcher.log</string>
+                        <string>*.txt</string>
                       </object>
                     </element>
                     <element index="20">
                       <object class="java.io.File">
-                        <string>proxy.txt</string>
+                        <string>*_new</string>
                       </object>
                     </element>
                     <element index="21">
                       <object class="java.io.File">
-                        <string>META-INF</string>
+                        <string>hs_err_*.*</string>
                       </object>
                     </element>
                     <element index="22">
                       <object class="java.io.File">
-                        <string>install/getdown-launcher.jar</string>
+                        <string>${compiler:GETDOWN_DIST_DIR}</string>
                       </object>
                     </element>
                     <element index="23">
                       <object class="java.io.File">
-                        <string>install/getdown.txt</string>
+                        <string>${compiler:GETDOWN_ALT_DIR}</string>
                       </object>
                     </element>
                     <element index="24">
                       <object class="java.io.File">
-                        <string>install/build_properties</string>
+                        <string>${compiler:GETDOWN_RESOURCE_DIR}</string>
                       </object>
                     </element>
                     <element index="25">
                       <object class="java.io.File">
-                        <string>build_properties</string>
+                        <string>META-INF</string>
                       </object>
                     </element>
                     <element index="26">
@@ -822,27 +822,47 @@ return console.askYesNo(message, true);
                     </element>
                     <element index="27">
                       <object class="java.io.File">
-                        <string>dist</string>
+                        <string>resource</string>
                       </object>
                     </element>
                     <element index="28">
                       <object class="java.io.File">
-                        <string>release</string>
+                        <string>dist</string>
                       </object>
                     </element>
                     <element index="29">
                       <object class="java.io.File">
-                        <string>alt</string>
+                        <string>release</string>
                       </object>
                     </element>
                     <element index="30">
                       <object class="java.io.File">
-                        <string>resource</string>
+                        <string>alt</string>
                       </object>
                     </element>
                     <element index="31">
                       <object class="java.io.File">
-                        <string>hs_err_*.*</string>
+                        <string>dev</string>
+                      </object>
+                    </element>
+                    <element index="32">
+                      <object class="java.io.File">
+                        <string>build</string>
+                      </object>
+                    </element>
+                    <element index="33">
+                      <object class="java.io.File">
+                        <string>alt_*</string>
+                      </object>
+                    </element>
+                    <element index="34">
+                      <object class="java.io.File">
+                        <string>dev_*</string>
+                      </object>
+                    </element>
+                    <element index="35">
+                      <object class="java.io.File">
+                        <string>build_*</string>
                       </object>
                     </element>
                   </property>