Merge branch 'develop' into features/JAL-3010ontologyFeatureSettings
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 19 Sep 2018 14:26:17 +0000 (15:26 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 19 Sep 2018 14:26:17 +0000 (15:26 +0100)
Conflicts:
src/jalview/gui/FeatureSettings.java
src/jalview/gui/FeatureTypeSettings.java

118 files changed:
.ant-targets-build.xml
.classpath
.gitignore
.settings/org.eclipse.jdt.ui.prefs
AUTHORS
README
RELEASE
THIRDPARTYLIBS
build.xml
doc/patching-vaqua.txt [new file with mode: 0644]
examples/rna_ss_test.stk [new file with mode: 0644]
examples/testdata/example_annot_file.jva
help/help.jhm
help/helpTOC.xml
help/html/editing/index.html
help/html/features/clarguments.html
help/html/features/commandline.html
help/html/features/dasfeatures.html [deleted file]
help/html/features/dassettings.html [deleted file]
help/html/features/preferences.html
help/html/features/search.html
help/html/features/searchclearhist.png
help/html/features/seqfeatures.html
help/html/features/seqfetch.html
help/html/memory.html
help/html/menus/alignmentMenu.html
help/html/menus/alwview.html
help/html/menus/wsmenu.html
help/html/releases.html
help/html/webServices/dbreffetcher.html
help/html/webServices/index.html
help/html/whatsNew.html
lib/VAqua4.jar [deleted file]
lib/VAqua5-patch.jar [new file with mode: 0644]
lib/htsjdk-1.133.jar [deleted file]
lib/jdas-1.0.4.jar [deleted file]
nbbuild.xml
resources/authors.props
resources/uniprot_mapping.xml
src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java
src/jalview/analysis/Conservation.java
src/jalview/analysis/Rna.java
src/jalview/bin/Cache.java
src/jalview/bin/Jalview.java
src/jalview/datamodel/AlignmentAnnotation.java
src/jalview/datamodel/Annotation.java
src/jalview/datamodel/SequenceFeature.java
src/jalview/datamodel/features/SequenceFeatures.java
src/jalview/datamodel/features/SequenceFeaturesI.java
src/jalview/datamodel/xdb/uniprot/UniprotFeature.java
src/jalview/ext/ensembl/EnsemblCdna.java
src/jalview/ext/ensembl/EnsemblCds.java
src/jalview/ext/ensembl/EnsemblFeatures.java
src/jalview/ext/ensembl/EnsemblGene.java
src/jalview/ext/ensembl/EnsemblGenome.java
src/jalview/ext/ensembl/EnsemblInfo.java
src/jalview/ext/ensembl/EnsemblLookup.java
src/jalview/ext/ensembl/EnsemblMap.java
src/jalview/ext/ensembl/EnsemblProtein.java
src/jalview/ext/ensembl/EnsemblRestClient.java
src/jalview/ext/ensembl/EnsemblSeqProxy.java
src/jalview/ext/ensembl/EnsemblXref.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/AnnotationPanel.java
src/jalview/gui/AppVarna.java
src/jalview/gui/AquaInternalFrameManager.java
src/jalview/gui/DasSourceBrowser.java [deleted file]
src/jalview/gui/Desktop.java
src/jalview/gui/FeatureSettings.java
src/jalview/gui/FeatureTypeSettings.java
src/jalview/gui/FontChooser.java
src/jalview/gui/IdCanvas.java
src/jalview/gui/JDatabaseTree.java
src/jalview/gui/Preferences.java
src/jalview/gui/SeqCanvas.java
src/jalview/gui/SequenceFetcher.java
src/jalview/gui/TreeCanvas.java
src/jalview/io/FileFormat.java
src/jalview/io/JalviewFileChooser.java
src/jalview/io/JalviewFileFilter.java
src/jalview/io/JalviewFileView.java
src/jalview/io/StockholmFile.java
src/jalview/io/cache/JvCacheableInputBox.java
src/jalview/jbgui/GPreferences.java
src/jalview/util/MapList.java
src/jalview/ws/DBRefFetcher.java
src/jalview/ws/DasSequenceFeatureFetcher.java [deleted file]
src/jalview/ws/SequenceFetcher.java
src/jalview/ws/dbsources/Uniprot.java
src/jalview/ws/dbsources/das/api/DasSourceRegistryI.java [deleted file]
src/jalview/ws/dbsources/das/api/jalviewSourceI.java [deleted file]
src/jalview/ws/dbsources/das/datamodel/DasSequenceSource.java [deleted file]
src/jalview/ws/dbsources/das/datamodel/DasSourceRegistry.java [deleted file]
src/jalview/ws/dbsources/das/datamodel/JalviewSource.java [deleted file]
test/jalview/analysis/AlignmentUtilsTests.java
test/jalview/analysis/CrossRefTest.java
test/jalview/bin/CommandLineOperations.java
test/jalview/datamodel/features/FeatureAttributesTest.java
test/jalview/datamodel/features/SequenceFeaturesTest.java
test/jalview/ext/ensembl/EnsemblCdnaTest.java
test/jalview/ext/ensembl/EnsemblCdsTest.java
test/jalview/ext/ensembl/EnsemblGeneTest.java
test/jalview/ext/ensembl/EnsemblGenomeTest.java
test/jalview/ext/ensembl/EnsemblRestClientTest.java
test/jalview/ext/ensembl/EnsemblSeqProxyAdapter.java
test/jalview/ext/ensembl/EnsemblSeqProxyTest.java
test/jalview/gui/SeqCanvasTest.java
test/jalview/io/StockholmFileTest.java
test/jalview/util/MapListTest.java
test/jalview/ws/PDBSequenceFetcherTest.java
test/jalview/ws/SequenceFetcherTest.java
test/jalview/ws/dbsources/RemoteFormatTest.java
test/jalview/ws/dbsources/UniprotTest.java
test/jalview/ws/seqfetcher/DasSequenceFetcher.java [deleted file]
utils/InstallAnywhere/Jalview.iap_xml
utils/InstallAnywhere/README_IA
utils/classgraph-4.1.6.jar [new file with mode: 0644]

index 7ef21f1..15432a1 100644 (file)
@@ -1,2 +1,31 @@
+build
+buildPropertiesFile
+buildTests
+buildextclients
+buildindices
+castorbinding
+clean
+compileApplet
+distclean
 help
+init
+linkcheck
+makeApplet
+makedist
+makefulldist
+obfuscate
+packageApplet
+prepare
+prepareTests
+preparejnlp
+prepubapplet_1
+pubapplet
+runenv
+signApplet
+sourcedist
+sourcedoc
+sourcescrub
+testclean
+testng
 usage
+writejnlpf
index 0cdc4b9..0da91bb 100644 (file)
@@ -36,7 +36,6 @@
        <classpathentry kind="lib" path="lib/miglayout-4.0-swing.jar"/>
        <classpathentry kind="lib" path="lib/jswingreader-0.3.jar" sourcepath="/jswingreader"/>
        <classpathentry kind="lib" path="lib/commons-codec-1.3.jar"/>
-       <classpathentry kind="lib" path="lib/jdas-1.0.4.jar"/>
        <classpathentry kind="lib" path="lib/spring-core-3.0.5.RELEASE.jar"/>
        <classpathentry kind="lib" path="lib/spring-web-3.0.5.RELEASE.jar"/>
        <classpathentry kind="lib" path="lib/jabaws-min-client-2.2.0.jar" sourcepath="/clustengine"/>
@@ -48,7 +47,8 @@
        <classpathentry kind="lib" path="lib/VARNAv3-93.jar"/>
        <classpathentry kind="lib" path="lib/jfreesvg-2.1.jar"/>
        <classpathentry kind="lib" path="lib/quaqua-filechooser-only-8.0.jar"/>
-       <classpathentry kind="lib" path="lib/VAqua4.jar"/>
+       <classpathentry kind="lib" path="lib/VAqua5-patch.jar"/>
+       <classpathentry kind="lib" path="utils/classgraph-4.1.6.jar"/>
        <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/plugin"/>
        <classpathentry kind="lib" path="lib/xml-apis.jar"/>
        <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
index 2a55560..86637df 100644 (file)
@@ -1,5 +1,6 @@
 .project
 /dist
+/clover
 /classes
 /tests
 /test-reports
@@ -12,4 +13,4 @@
 TESTNG
 /jalviewApplet.jar
 /benchmarking/lib
-*.class
\ No newline at end of file
+*.class
index 30e76be..958613b 100644 (file)
@@ -40,6 +40,7 @@ sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=
 sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
 sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
 sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
 sp_cleanup.remove_redundant_type_arguments=true
 sp_cleanup.remove_trailing_whitespaces=false
 sp_cleanup.remove_trailing_whitespaces_all=true
diff --git a/AUTHORS b/AUTHORS
index 1bfc734..2fe3fce 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -7,15 +7,17 @@ or might otherwise be considered author of Jalview.
 The people listed below are 'The Jalview Authors', who collectively
 own the copyright to the Jalview source code and permit it to be released under GPL.
 
-This is the authoritative list. It was correct on 23rd November 2016.
+This is the authoritative list: it was correct on 5th September 2018 (or the last commit date!)
+
 If you are releasing a version of Jalview, please make sure any
 statement of authorship in the GUI reflects the list shown here.
 In particular, check the resources/authors.props file ! 
 
 Jim Procter
 Mungo Carstairs
-Tochukwu 'Charles' Ofoegbu
+Ben Soares
 Kira Mourao
+Tochukwu 'Charles' Ofoegbu
 Andrew Waterhouse
 Jan Engelhardt
 Lauren Lui
diff --git a/README b/README
index eaf226b..8172066 100755 (executable)
--- a/README
+++ b/README
@@ -21,13 +21,18 @@ For more help, read the file doc/building.html
 
 ##################
 
-To run application:
+To run application...
+[ NOTE: when using the -classpath option with the '*' wildcard, the argument must be quoted to avoid shell expansion of the wildcard,
+  ALSO, the wildcard MUST be as DIR/* and not DIR/*.jar etc or it will not be interpreted correctly ]
 
-java -Djava.ext.dirs=JALVIEW_HOME/lib -cp JALVIEW_HOME/jalview.jar jalview.bin.Jalview
+on Windows use:
+  java -classpath "JALVIEW_HOME/lib/*;JALVIEW_HOME/jalview.jar" jalview.bin.Jalview
+and on MacOS or Linux:
+  java -classpath "JALVIEW_HOME/lib/*:JALVIEW_HOME/jalview.jar" jalview.bin.Jalview
 
 Replace JALVIEW_HOME with the full path to Jalview Installation Directory. If building from source:
 
-java -Djava.ext.dirs=JALVIEW_BUILD/dist -cp JALVIEW_BUILD/dist/jalview.jar jalview.bin.Jalview
+  java -classpath "JALVIEW_BUILD/dist/*" jalview.bin.Jalview
 
 
 ##################
diff --git a/RELEASE b/RELEASE
index c61d86c..1960368 100644 (file)
--- a/RELEASE
+++ b/RELEASE
@@ -1,2 +1,2 @@
-jalview.release=releases/Release_2_10_4_Branch
-jalview.version=2.10.4b1
+jalview.release=releases/Release_2_11_Branch
+jalview.version=2.11.0
index d0d9125..afa99d2 100644 (file)
@@ -30,7 +30,6 @@ httpclient-4.0.3.jar
 httpcore-4.0.1.jar
 httpmime-4.0.3.jar
 jaxrpc.jar
-jdas-1.0.4.jar : Apache License - built from http://code.google.com/p/jdas/ (29th Feb 2012)
 jhall.jar
 jswingreader-0.3.jar : Apache license - built from http://jswingreader.sourceforge.net/ svn/trunk v12
 log4j-1.2.8.jar
@@ -39,8 +38,8 @@ miglayout-4.0-swing.jar       BSD http://www.migcalendar.com/miglayout/versions/4.0/li
 min-jaba-client.jar
 regex.jar
 saaj.jar
-spring-core-3.0.5.RELEASE.jar : Apache License: jdas runtime dependencies retrieved via maven
-spring-web-3.0.5.RELEASE.jar : Apache License: jdas runtime dependencies retrieved via maven
+spring-core-3.0.5.RELEASE.jar : Apache License: jdas runtime dependencies retrieved via maven - TODO: JAL-3035 remove if no longer needed ?
+spring-web-3.0.5.RELEASE.jar : Apache License: jdas runtime dependencies retrieved via maven - TODO: JAL-3035 remove if no longer needed ?
 vamsas-client.jar
 wsdl4j.jar
 xercesImpl.jar
@@ -50,15 +49,21 @@ jfreesvg-2.1.jar : GPL v3 licensed library from the JFree suite: http://www.jfre
 
 quaqua: v.8.0 (latest stable) by Randel S Hofer. LGPL and BSD Modified license: downloaded from http://www.randelshofer.ch/quaqua/ 
 
-vaqua: v4 (latest stable) by Alan Snyder et al. GPLv2 with Classpathe xception, also includes contributions from Quaqua: ownloaded from http://violetlib.org/vaqua/overview.html
+vaqua5-patch: This is a patched version of VAqua v5 (latest stable) by Alan Snyder et al. GPLv3 with Classpath exception, also includes contributions from Quaqua: http://violetlib.org/vaqua/overview.html - see doc/patching-vaqua.txt for patch details, and http://issues.jalview.org/browse/JAL-2988 for details of the bug that the patch addresses.
 
-lib/htsjdk-1.120-SNAPSHOT.jar: (currently not required for 2.10) built from maven master at https://github.com/samtools/htsjdk MIT License to Broad Institute
+lib/htsjdk-2.12.jar: built from maven master at https://github.com/samtools/htsjdk MIT License to Broad Institute
 
 lib/biojava-core-4.1.0.jar LGPLv2.1 - latest license at https://github.com/biojava/biojava/blob/master/LICENSE
 
 lib/biojava-ontology-4.1.0.jar LGPLv2.1 - latest license at https://github.com/biojava/biojava/blob/master/LICENSE
 
 
+Libraries for Test Suite
+
+utils/classgraph-4.1.6.jar: BSD License - allows recovery of classpath for programmatic construction of a Java command line to launch Jalview
+                      version 4.1.6 downloaded from https://mvnrepository.com/artifact/io.github.classgraph/classgraph/4.1.6
+
+
 Additional dependencies
 
 examples/javascript/deployJava.js : http://java.com/js/deployJava.js
index d826d83..5ca105a 100755 (executable)
--- a/build.xml
+++ b/build.xml
@@ -20,6 +20,9 @@
 <project name="jalviewX" default="usage" basedir="."
  xmlns:if="ant:if"
     xmlns:unless="ant:unless">
+  <taskdef classpath="${clover.jar}" resource="cloverlib.xml" if:set="clover.jar"/>
+  <clover-env if:set="clover.jar"/>
+
   <target name="help" depends="usage" />
   <target name="usage" depends="init">
     <echo message="~~~Jalview Ant build.xml Usage~~~~" />
@@ -40,6 +43,7 @@
     <echo message="See docs/building.html and the comments in build file for other targets." />
     <echo message="note: compile and makeApplet optionally compile/obfuscate applet against a different Java version by specifying -Djava118.home=PathtoJDK/lib which is the lib directory in the JDK install that contains rt.jar " />
     <echo message="Useful -D flags: -Ddonotobfuscate will prevent applet obfuscation" />
+    <echo message="Useful -D flags: -Dclover.jar to specify path to openclover for testng coverage report" />
   </target>
 
 
     <property name="docDir" value="doc" />
     <property name="sourceDir" value="src" />
     <property name="schemaDir" value="schemas" />
-    <property name="outputDir" value="classes" />
+    <property name="outputDir" value="classes" unless:set="clover.jar"/>
+    <property name="outputDir" value="cloverclasses" if:set="clover.jar"/>
     <property name="packageDir" value="dist" />
     <property name="outputJar" value="jalview.jar" />
     <!-- Jalview Applet JMol Jar Dependency -->
       verbose="2">
       <classpath>
         <pathelement location="${testOutputDir}" />
+        <pathelement location="${clover.jar}" if:set="clover.jar"/>
         <path refid="test.classpath" />
       </classpath>
       <jvmarg value="--add-modules=java.se.ee" if:set="java9"/>
     </jar>
 
     <antcall target="writejnlpf">
-      <param name="jnlpFile" value="${packageDir}/jalview.jnlp" />
+      <param name="jnlpFile" value="${packageDir}/jalview_256M.jnlp" />
       <param name="inih" value="10M" />
       <param name="maxh" value="256M" />
     </antcall>
+    <antcall target="writejnlpf">
+      <param name="jnlpFile" value="${packageDir}/jalview.jnlp" />
+      <param name="inih" value="800M" />
+      <param name="maxh" value="1024M" />
+    </antcall>
 
     <antcall target="writejnlpf">
       <param name="jnlpFile" value="${packageDir}/jalview_1G.jnlp" />
 
     <antcall target="writejnlpf">
       <param name="jnlpFile" value="${packageDir}/jalview_2G.jnlp" />
-      <param name="inih" value="256M" />
+      <param name="inih" value="800M" />
       <param name="maxh" value="1024M" />
     </antcall>
 
         <association mime-type="application-x/ext-file" extensions="jar"/>-->
   </target>
 
-  <target name="-jarsignwithtsa" depends="makedist,preparejnlp" if="timestamp">
+  <target name="-jarsignwithtsa" depends="makedist,preparejnlp" if="timestamp" unless="nosign">
     <signjar storepass="${jalview.keystore.pass}" keypass="${jalview.key.pass}" keystore="${jalview.keystore}" alias="${jalview.key}" lazy="false" verbose="false" sigalg="${jalview.keyalg}" digestalg="${jalview.keydig}"
       tsaproxyhost="${proxyHost}" tsaproxyport="${proxyPort}" tsaurl="${jalview.tsaurl}">
       <fileset dir="${packageDir}">
       </fileset>
     </signjar>
   </target>
-  <target name="-jarsignnotsa" depends="makedist,preparejnlp" unless="timestamp">
+  <target name="-jarsignnotsa" depends="makedist,preparejnlp" if:blank="timestamp" unless="nosign">
     <signjar storepass="${jalview.keystore.pass}" keypass="${jalview.key.pass}" keystore="${jalview.keystore}" alias="${jalview.key}" lazy="false" verbose="false" sigalg="${jalview.keyalg}" digestalg="${jalview.keydig}">
       <fileset dir="${packageDir}">
         <include name="*.jar" />
 </target>
 
 <target name="makedist" depends="build, buildPropertiesFile, linkcheck, buildindices">
+  <fail if="clover.jar">
+    Ignoring request to build jalview distribution with clover-instrumented classes
+  </fail>
   <!-- make the package jar if not already existing -->
   <mkdir dir="${packageDir}" />
   <!-- clean dir if it already existed -->
     <include name="ap_${jsonSimple}" />
   </fileset>
 </target>
-<target name="-signappletnotsa" unless="timestamp" depends="-signapplet">
+<target name="-signappletnotsa" if:blank="timestamp" depends="-signapplet" unless="nosign">
   <signjar storepass="${jalview.keystore.pass}" keypass="${jalview.key.pass}" keystore="${jalview.keystore}" alias="${jalview.key}" lazy="false" verbose="false">
     <fileset refid="signappletjarset" />
   </signjar>
 </target>
 
-<target name="-signapplettsa" if="timestamp" depends="-signapplet">
+<target name="-signapplettsa" if="timestamp" depends="-signapplet" unless="nosign">
   <signjar storepass="${jalview.keystore.pass}" keypass="${jalview.key.pass}" keystore="${jalview.keystore}" alias="${jalview.key}" lazy="false" verbose="false" tsaproxyhost="${proxyHost}" tsaproxyport="${proxyPort}" tsaurl="${jalview.tsaurl}">
     <fileset refid="signappletjarset" />
   </signjar>
diff --git a/doc/patching-vaqua.txt b/doc/patching-vaqua.txt
new file mode 100644 (file)
index 0000000..65c9974
--- /dev/null
@@ -0,0 +1,27 @@
+VAqua5-patched.jar - how the patch was created
+
+1. Download VAqua5 source from https://violetlib.org/release/vaqua/5/VAqua5Source.zip
+2. Unzip to a directory and apply this patch
+
+diff --git a/src/org/violetlib/aqua/fc/AquaFileChooserUI.java b/src/org/violetlib/aqua/fc/AquaFileChooserUI.java
+index 833366d..61f66e5 100644
+--- a/src/org/violetlib/aqua/fc/AquaFileChooserUI.java
++++ b/src/org/violetlib/aqua/fc/AquaFileChooserUI.java
+@@ -1171,7 +1171,8 @@ public class AquaFileChooserUI extends BasicFileChooserUI {
+         goToFolderCancelButtonText = getString("FileChooser.goToFolderCancelButtonText", l, "Cancel");
+         goToFolderAcceptButtonText = getString("FileChooser.goToFolderAcceptButtonText", l, "Accept");
+         goToFolderErrorText = getString("FileChooser.goToFolderErrorText", l, "The folder can\u2019t be found.");
+-        defaultInitialSaveFileName = getString("FileChooser.defaultSaveFileName", l, "Untitled");
++        // Don't set an initial filename for saving (or loading) !  
++       // defaultInitialSaveFileName = getString("FileChooser.defaultSaveFileName", l, "Untitled");
+     }
+     /**
+
+3. Ensure XCode is installed, along with command line tools and the OSX developer packs
+ - you should have /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
+
+4. Download the VAqua rendering library from violetlib.org and save to the VAqua source's lib folder as lib/VAquaRendering.jar
+
+5. change to the release directory and execute 'ant' - a few warnings are generated but providing a final jar is created, all is good!
+
diff --git a/examples/rna_ss_test.stk b/examples/rna_ss_test.stk
new file mode 100644 (file)
index 0000000..429612e
--- /dev/null
@@ -0,0 +1,6 @@
+# STOCKHOLM 1.0
+#=GF ID RNA.SS.TEST
+#=GF TP RNA;
+Test.sequence         GUACAAAAAAAAAA
+#=GC SS_cons          <(EHBheb(E)e)>
+//
index 1779247..6b9faa4 100644 (file)
@@ -18,5 +18,5 @@ SEQUENCE_GROUP        Group_A 30      50      *
 SEQUENCE_GROUP Group_B 1       351     2-5
 SEQUENCE_GROUP Group_C 12      14      -1      seq1    seq2    seq3
 PROPERTIES     Group_A description=This is the description     colour=Helix Propensity pidThreshold=0  outlineColour=red       displayBoxes=true       displayText=false       colourText=false        textCol1=black  textCol2=black  textColThreshold=0
-PROPERTIES     Group_B outlineColour=red       colour=None
+PROPERTIES     Group_B outlineColour=green     colour=None
 PROPERTIES     Group_C colour=Clustal
index e4bf12c..78f86b6 100755 (executable)
@@ -70,8 +70,6 @@
    <mapID target="annotations.fileformat" url="html/features/annotationsFormat.html"/>
    <mapID target="features.fileformat" url="html/features/featuresFormat.html"/>
    <mapID target="features.featureschemes" url="html/features/featureschemes.html"/>
-   <mapID target="das.settings" url="html/features/dassettings.html"/>
-   <mapID target="das.viewing" url="html/features/dasfeatures.html"/>
    <mapID target="edit" url="html/editing/index.html"/>
    <mapID target="jalarchive" url="html/features/jalarchive.html"/>
    <mapID target="multipleviews" url="html/features/multipleViews.html"/>
index b218b88..77ddd88 100755 (executable)
@@ -60,8 +60,6 @@
                        <tocitem text="Feature Colourschemes" target="features.featureschemes" />
                        <tocitem text="User Defined Sequence Features" target="seqfeatcreat" />
                        <tocitem text="Editing Sequence Features" target="seqfeatedit" />
-                       <tocitem text="DAS Feature Retrieval" target="das.viewing" />
-                       <tocitem text="DAS Feature Settings" target="das.settings" />
                        <tocitem text="HTML annotation report" target="io.seqreport" />
                </tocitem>
                
@@ -78,8 +76,7 @@
                        <tocitem text="Alignment Conservation Analysis" target="aacon" />
                        <tocitem text="Multi-Harmony Alignment Analysis" target="shmrws" />
                        <tocitem text="Sequence Retrieval" target="seqfetch" />
-                       <tocitem text="Database Reference Retrieval" target="dbreffetcher" />
-                       <tocitem text="DAS Feature Retrieval" target="das.viewing" />
+                       <tocitem text="Database Reference Retrieval" target="dbreffetcher" />                   
                </tocitem>
                
                <tocitem text="Colour Schemes" target="colours" expand="false">
index fd8c5a3..b3600c9 100755 (executable)
@@ -61,7 +61,7 @@
     <em>Undo / redo</em> - editing of sequences (insertion/removal of
     gaps, removal of sequences, trimming sequences etc) may be undone or
     redone at any time using the appropriate menu items from the edit
-    menu. The undo history list only allows a maximum of 10 actions.
+    menu.
   <p>
     <em>Trimming alignment</em> - First select a column by clicking the
     scale indicator (above the sequences) The alignment may then be
index e065494..fa273a5 100644 (file)
     </tr>
     <tr>
       <td>
-        <div align="center">-dasserver nickname=URL</div>
-      <td>
-        <div align="left">
-          Add and enable a <a href="dassettings.html">DAS server</a>
-          with given nickname (alphanumeric or underscores only) for
-          retrieval of features for all alignments<br> Sources that
-          also support the sequence command may be specified by
-          prepending the URL with 'sequence:'<br> <em>e.g.</em>
-          sequence:http://localdas.somewhere.org/das/source
-        </div>
-      </td>
-    </tr>
-    <tr>
-      <td>
-        <div align="center">-fetchfrom nickname</div>
-      <td>
-        <div align="left">
-          Query a <a href="dassettings.html">DAS source</a> called
-          nickname for features for the alignments and display them
-        </div>
-      </td>
-    </tr>
-    <tr>
-      <td>
         <div align="center">-groovy FILE/URL</div>
       <td>
         <div align="left">Execute groovy script in FILE (where
index 9cffc51..92d9323 100644 (file)
     provided by InstallAnywhere any output from the application will be
     sent to output.txt, not standard out.<br> The Jalview
     application also requires a number of additional libraries on the
-    class path. The command line below adds the Jalview installation's
-    'lib' directory to the list of directories that are searched for
-    jars to be added to the classpath:
+    class path. The command line below adds all the jar files in the
+    Jalview installation's 'lib' directory to the classpath, as well as
+    the Jalview application jar file:
   </p>
-  <pre>java -Djava.ext.dirs=$INSTALL_DIR$/lib -cp $INSTALL_DIR$/jalview.jar jalview.bin.Jalview -open [FILE] </pre>
+  <pre>java -classpath "$INSTALL_DIR$/lib/*:$INSTALL_DIR$/jalview.jar" jalview.bin.Jalview -open [FILE] </pre>
   <p>
     Use '-help' to get more information on the <a
       href="clarguments.html">command line arguments</a> that
diff --git a/help/html/features/dasfeatures.html b/help/html/features/dasfeatures.html
deleted file mode 100644 (file)
index 1965e70..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-<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>DAS Features</title>
-</head>
-
-<body>
-  <p>
-    <strong>DAS Sequence Feature Retrieval</strong>
-  </p>
-  <p>Jalview includes a client for retrieving sequences and their
-    features via the Distributed Annotation System.</p>
-  <ol>
-    <li>Open the Feature Settings panel by selecting &quot;View
-      -&gt; Feature Settings...&quot;</li>
-    <li>Click on the &quot;<a href="dassettings.html">DAS
-        Settings</a>&quot; tabbed pane.
-    </li>
-    <li>Select the sources to use for DAS feature retrieval, then
-      click the &quot;Fetch DAS Features&quot; button.
-      <ul>
-        <li>Cancelling Feature Retrieval<br> Press the <strong>Cancel
-            Fetch</strong> button to immediately stop feature retrieval. This
-          will not remove any features already added to the alignment,
-          but will halt any outstanding DAS requests.<em>The cancel
-            fetch button is of particular use when one or more DAS
-            annotation servers are not responding!</em>
-      </ul>
-    </li>
-  </ol>
-  <p>
-    If your DAS source selection contains sources which use UniProt
-    accession ids, you will be asked whether Jalview should find UniProt
-    Accession ids for the given sequence names. It is important to
-    realise that many DAS sources only use UniProt accession ids, rather
-    than Swissprot/UniProt sequence names.<br> The <a
-      href="../webServices/dbreffetcher.html">database
-      reference fetcher</a> documentation describes how Jalview discovers
-    what database references are appropriate for the sequences in the
-    alignment.
-  <ul>
-    <li><em>Note</em><br> Please remember to save your
-      alignment if either the start/end numbering, or the sequence IDs
-      were updated during the ID retrieval process.</li>
-  </ul>
-  <p>&nbsp;
-  <p>
-    <em>DAS support was introduced in Jalview Version 2.1.</em>
-  </p>
-  <br />
-  <p>
-    <em>The DAS registry at http://www.dasregistry.org was
-      decommissioned early in 2015. An unmaintained mirror is currently
-      hosted at http://www.ebi.ac.uk/das-srv/registry/.</em>
-  </p>
-  <p>&nbsp;
-</body>
-</html>
diff --git a/help/html/features/dassettings.html b/help/html/features/dassettings.html
deleted file mode 100644 (file)
index 9600070..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-<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>DAS Settings</title>
-</head>
-
-<body>
-  <p>
-    <strong>DAS Settings</strong>
-  </p>
-  <p>
-    Jalview can retrieve sequences and features from many <a
-      href="http://biodas.org/">DAS</a> sources. The DAS sources
-    that it uses are discovered and selected <em>via</em> the DAS
-    settings panel, opened either from the <a
-      href="featuresettings.html">View&#8594;Feature Settings</a> dialog
-    box from the alignment window's menu bar, or the <a
-      href="featuresettings.html">Tools&#8594;Preferences</a>
-    dialog box opened from the Desktop menu bar.
-  </p>
-  <p>
-    <img src="das.gif">
-  <p>The available sources are listed in the table using each
-    source's Nickname as its identifier. Clicking on a source's entry in
-    the table reveals more information about that service in the panel
-    to the right. Select the tickbox in the &quot;Use Source&quot;
-    column for a source to add it to the set Jalview queries for
-    alignment and sequence features.</p>
-  <p>You can filter the visible DAS sources by authority, type and
-    &quot;label&quot;. You should read the DAS documentation to
-    understand more about these values.
-  <p>
-    <strong>Updating the list of sources</strong>
-  </p>
-  <p>
-    When the DAS Settings panel is first opened, and when the <strong>'Refresh
-      source'</strong> buton is pressed, a list of DAS sources is retrieved from
-    the DAS registry URL. Note that the registry hosted at
-    http://www.dasregistry.org/das/ was retired at the start of 2015. An
-    alternative service is currently hosted at
-    http://www.ebi.ac.uk/das-srv/registry/das/. To connect to this
-    service, ensure your .jalview_properties file includes the following
-    line:<br> <b>DAS_REGISTRY_URL=http\://www.ebi.ac.uk/das-srv/registry/das/</b>
-  </p>
-  <p>
-    <strong>Adding your own DAS Sources</strong>
-  </p>
-  <p>You can add your own DAS source to the list by clicking the
-    &quot;Add Local Source&quot; button. Enter the URL and nickname of
-    your additional service. It should be noted that Jalview 2.1 will
-    not query additional sources for more information, but this will be
-    implemented in future editions.
-  <p>&nbsp;
-</body>
-</html>
index 50f864b..52e88db 100755 (executable)
         Preferences</a> tab contains settings affecting the export of
       sequence alignments and EPS files.
     </li>
-    <li>The <a href="dassettings.html"><strong>&quot;DAS
-          Settings&quot;</strong> Preferences</a> tab allows you to select which DAS
-      sources to use when fetching DAS Features.
-    </li>
     <li>The <a href="../webServices/webServicesPrefs.html"><strong>&quot;Web
           Service&quot;</strong> Preferences</a> tab allows you to configure the <a
       href="http://www.compbio.dundee.ac.uk/jabaws">JABAWS</a>
index 72e5bdf..eec68ee 100755 (executable)
@@ -159,7 +159,7 @@ td {
   <p>The search history keeps up to 99 queries by default. To clear
     the history, or modify the size of the history, right-click the text
     box.</p>
-  <img src="searchclearhist.png" width="402" height="121" align="left" />
+  <img src="searchclearhist.png" width="402" height="127" align="left" />
   <p>
     <strong>Other dialogs that provide a query history</strong>
   </p>
index 200c4d3..29cc34f 100644 (file)
Binary files a/help/html/features/searchclearhist.png and b/help/html/features/searchclearhist.png differ
index 3c9d2b8..eeb63f6 100755 (executable)
       href="featuresettings.html">Sequence Feature Settings</a>
     dialog box. Feature colour schemes and display parameters are unique
     to a particular alignment, so it is possible to colour the same
-    sequence features differently in different alignment views.<br>
-    Since Jalview 2.1, it is possible to add <a href="dassettings.html">DAS
-      features</a> to an alignment via the DAS tabbed pane of the feature
-    settings window.
+    sequence features differently in different alignment views.
   </p>
   <p>
     <strong>View&#8594;Sequence ID Tooltip&#8594;Show
index 44aa1c2..e726c49 100755 (executable)
   <p>
     <strong>Sequence Fetcher</strong>
   </p>
-  <p>
-    Jalview can retrieve sequences from certain databases using either
-    the DBFetch service provided by the EMBL European Bioinformatics
-    Institute, or, since Jalview 2.4, DAS servers capable of the <em>sequence</em>
-    command (configured in <a href="dassettings.html">DAS settings</a>).
-  </p>
-  <p>The Sequence Fetcher can be opened via the &quot;File&quot;
+       <p>Jalview can retrieve sequences from a range of sequence, 3D
+               structure, genomic and domain family databases provided by EMBL-EBI.</p>
+       <p>The Sequence Fetcher can be opened via the &quot;File&quot;
     menu on the main desktop in order to retrieve sequences as a new
     alignment, or opened via the &quot;File&quot; menu of an existing
     alignment to import additional sequences. There may be a short delay
-    when the sequence fetcher is first opened, whilst Jalview compiles
-    the list of available sequence datasources from the currently
-    defined DAS server registry.</p>
+    when the sequence fetcher is first opened, whilst Jalview contacts each database's web API.</p>
   <p>
     Every time a new fetcher is opened, you will need to <strong>select
       the database you want to retrieve sequences</strong> from the database
     tooltips are shown if you mouse over some sources, explaining what
     the database will retrieve. You can select one by using the up/down
     arrow keys and hitting return, or by double clicking with the mouse.
-    <br />
-    <em>If you have DAS sources enabled, then you may have several
-      sources for the same type of sequence identifier, and these will
-      be grouped together in a sub-branch branch labeled with the
-      identifier.</em>
   </p>
   <p>Once you have selected a sequence database, its fetcher dialog
     will open. Jalview provides two types of dialog:</p>
       currently selected database into the retrieval box. Finally, press
       &quot;OK&quot; to initiate the retrieval.</li>
   </ol>
-  <p>
-    <strong>Only retrieving part of a sequence</strong>
-  </p>
-  <p>
-    When using DAS sources (indicated by a &quot;<em>(DAS)</em>&quot;),
-    you can append a range in addition to a sequence ID. For example, to
-    retrieve 50 residues starting at position 35 in UNIPROT sequence
-    P73137 using the UNIPROT DAS server, you would enter
-    &quot;'P73137:35,84'.<br /> <em>Full support for DAS range
-      queries was introduced in Jalview 2.8</em>
-  </p>
 
   <p>If you use the WSDBFetch sequence fetcher services (EMBL,
     UniProt, PFAM, and RFAM) in work for publication, please cite:</p>
index 2142f98..9437a60 100755 (executable)
@@ -115,7 +115,7 @@ lax.nl.java.option.java.heap.size.initial=500m
 ! &lt;string&gt;-Xms2M&lt;/string&gt;
 ! &lt;string&gt;-Xmx64M&lt;/string&gt;
 &lt;/array&gt;
-</pre> Exchange the above two string tags for : <pre>
+</pre>Exchange the above two string tags for : <pre>
 &lt;string&gt;-Xms500M&lt;/string&gt;
 &lt;string&gt;-Xmx1000M&lt;/string&gt;
 </pre>
@@ -125,6 +125,11 @@ lax.nl.java.option.java.heap.size.initial=500m
       the file and try to start Jalview in the normal way. If it doesn't
       start, see below...</li>
   </ul>
+  <p>
+    <em>Please Note:</em> We do modify the default memory settings in
+    Jalview from time to time, so you may find different numbers to
+    those shown in the examples above.
+  </p>
   <font size="3"><em>Jalview doesn't start... What do the
       memory settings mean ?<a name="memsetting"></a>
   </em></font>
@@ -140,6 +145,12 @@ lax.nl.java.option.java.heap.size.initial=500m
     enlighten us if you know better!). Our experiments found 1000m to be
     the biggest setting that could be used on a 1GB machine. Just try
     reducing the sizes until Jalview starts up properly!</p>
+  <p>
+    We increased the default memory in Jalview 2.10.5 to 1G. To launch
+    Jalview with the pre 2.10.5 default memory allocation, use the <a
+      href="http://www.jalview.org/webstart/jalview_256MB.jnlp">Jalview
+      256MB JNLP</a>.
+  </p>
   <p>&nbsp;</p>
 </body>
 </html>
index 00a2ec4..f3ab75d 100755 (executable)
             href="../features/featuresettings.html">Sequence
               Feature Settings...</a> </strong><br> <em>Opens the
               Sequence Feature Settings dialog box to control the colour
-              and display of sequence features on the alignment, and
-              configure and retrieve features from DAS annotation
-              servers.</em></li>
+              and display of sequence features on the alignment.</em></li>
         <li><strong>Sequence ID Tooltip</strong><em>
             (application only) <br>This submenu's options allow the
             inclusion or exclusion of non-positional sequence features
       is dynamic, and may contain user-defined web service entries in
       addition to any of the following ones:</em>
     <ul>
-      <li><strong>Fetch DB References</strong><br> <em>This
-          submenu contains options for accessing any of the database
-          services that Jalview is aware of (e.g. DAS sequence servers
-          and the WSDBFetch service provided by the EBI) to verify
-          sequence start/end positions and retrieve all database cross
-          references and PDB ids associated with all or just the
-          selected sequences in the alignment.
-          <ul>
-            <li>'Trim Retrieved Sequences' - when checked, Jalview
-              will discard any additional sequence data for accessions
-              associated with sequences in the alignment. <br> <strong>Note:
-                Disabling this could cause out of memory errors when
-                working with genomic sequence records !</strong><br> <strong>Added
-                in Jalview 2.8.1</strong>
-            </li>
-            <li>'Standard Databases' will check sequences against
-              the EBI databases plus any active DAS sequence sources</li>
-          </ul> Other sub-menus allow you to pick a specific source to query
-          - sources are listed alphabetically according to their
-          nickname.
-      </em><br></li>
-    </ul>
+                               <li><strong>Fetch DB References</strong><br> <em>This
+                                               submenu contains options for accessing any of the database
+                                               services that Jalview is aware of (e.g. those provided by
+                                               EMBL-EBI) to verify sequence start/end positions and retrieve all
+                                               database cross references and PDB ids associated with all or just
+                                               the selected sequences in the alignment.
+                                               <ul>
+                                                       <li>'Trim Retrieved Sequences' - when checked, Jalview will
+                                                               discard any additional sequence data for accessions associated
+                                                               with sequences in the alignment. <br> <strong>Note:
+                                                                       Disabling this could cause out of memory errors when working
+                                                                       with genomic sequence records !</strong><br> <strong>Added
+                                                                       in Jalview 2.8.1</strong>
+                                                       </li>
+                                                       <li>'Standard Databases' will check sequences against the
+                                                               EBI databases.</li>
+                                               </ul> Other sub-menus allow you to pick a specific source to query -
+                                               sources are listed alphabetically according to their nickname.
+                               </em><br></li>
+                       </ul>
     <p>Selecting items from the following submenus will start a
       remote service on compute facilities at the University of Dundee,
       or elsewhere. You need a continuous network connection in order to
index 2028304..33ec77f 100755 (executable)
@@ -53,8 +53,7 @@
     <li><strong><a href="../features/featuresettings.html">Sequence
           Feature Settings...</a></strong><em><br> Opens the Sequence
         Feature Settings dialog box to control the colour and display of
-        sequence features on the alignment, and configure and retrieve
-        features from DAS annotation servers.</em></li>
+        sequence features on the alignment.</em></li>
     <li><strong>Sequence ID Tooltip</strong><em> (application
         only) <br>This submenu's options allow the inclusion or
         exclusion of non-positional sequence features or database cross
index b71bc1a..b8b357e 100755 (executable)
       dynamic, and may contain user-defined web service entries in
       addition to any of the following ones:</em>
   <ul>
-    <li><strong>Fetch DB References</strong><br> <em>This
-        submenu contains options for accessing any of the database
-        services that Jalview is aware of (e.g. DAS sequence servers and
-        the WSDBFetch service provided by the EBI) to verify sequence
-        start/end positions and retrieve all database cross references
-        and PDB ids associated with all or just the selected sequences
-        in the alignment.
-        <ul>
+    <li><strong>Fetch DB References</strong><br> <em>This submenu
+                               contains options for accessing any of the database services that
+                               Jalview is aware of (e.g services provided by the EBI) to verify
+                               sequence start/end positions and retrieve all database cross
+                               references and PDB ids associated with all or just the selected
+                               sequences in the alignment.
+                               <ul>
           <li>'Retrieve full Sequence' - when checked, Jalview will
             retrieve the full sequence for any accessions associated
             with sequences in the alignment. <br> <strong>Note:
@@ -45,7 +44,7 @@
               in Jalview 2.8.1</strong>
           </li>
           <li>'Standard Databases' will check sequences against the
-            EBI databases plus any active DAS sequence sources<</li>
+            EBI databases</li>
         </ul> Other submenus allow you to pick a specific source to query -
         sources are listed alphabetically according to their nickname.
     </em></li>
index 3c1d73c..af417a7 100755 (executable)
@@ -67,17 +67,160 @@ li:before {
         </div>
       </td>
     </tr>
+    
+      <td width="60" nowrap>
+        <div align="center">
+          <strong><a name="Jalview.2.11.0">2.11.0</a><br />
+            <em>8/09/2018</em></strong>
+        </div>
+      </td>
+      <td><div align="left">
+          <em></em>
+          <ul>
+            <li>
+              <!-- JAL-2865 -->Jalview doesn't hang when closing windows or the overview updates with large alignments.
+            </li>
+          </ul>
+        </div></td>
+      <td><div align="left">
+          <em></em>
+          <ul>
+            <li>
+              <!-- JAL-3035 -->DAS sequence retrieval and annotation capabilities removed from the Jalview Desktop
+            </li>
+          </ul>
+        </div></td>
+    </tr>
+    <tr>
+    <td width="60" nowrap>
+      <div align="center">
+        <strong><a name="Jalview.2.10.5">2.10.5</a><br /> <em>10/09/2018</em></strong>
+      </div>
+    </td>
+    <td><div align="left">
+        <em></em>
+        <ul>
+            <li>
+              <!-- JAL-3101 -->Default memory for Jalview webstart and
+              InstallAnywhere increased to 1G.
+            </li>
+            <li>
+              <!-- JAL-247 -->Hidden sequence markers and representative
+              sequence bolding included when exporting alignment as EPS,
+              SVG, PNG or HTML. <em>Display is configured via the
+                Format menu, or for command-line use via a jalview
+                properties file.</em>
+            </li>
+            <li>
+              <!-- JAL-3076 -->Ensembl client updated to Version 7 REST
+              API and sequence data now imported as JSON.
+            </li>
+            <li>
+              <!-- JAL-3065 -->Change in recommended way of starting
+              Jalview via a Java command line: add jars in lib directory
+              to CLASSPATH, rather than via the deprecated java.ext.dirs
+              property.
+            </li>
+          </ul>
+          <em>Development</em>
+          <ul>
+            <li>
+              <!-- JAL-3047 -->Support added to execute test suite
+              instrumented with <a href="http://openclover.org/">Open
+                Clover</a>
+            </li>
+          </ul>
+        </div></td>
+    <td><div align="left">
+        <em></em>
+        <ul>
+            <li>
+              <!-- JAL-3104 -->Poorly scaled bar in quality annotation
+              row shown in Feredoxin Structure alignment view of example
+              alignment.
+            </li>
+            <li>
+              <!-- JAL-2854 -->Annotation obscures sequences if lots of
+              annotation displayed.
+            </li>
+            <li>
+              <!-- JAL-3107 -->Group conservation/consensus not shown
+              for newly created group when 'Apply to all groups'
+              selected
+            </li>
+            <li>
+              <!-- JAL-3087 -->Corrupted display when switching to
+              wrapped mode when sequence panel's vertical scrollbar is
+              visible.
+            </li>
+            <li>
+              <!-- JAL-3003 -->Alignment is black in exported EPS file
+              when sequences are selected in exported view.</em>
+            </li>
+            <li>
+              <!-- JAL-3059 -->Groups with different coloured borders
+              aren't rendered with correct colour.
+            </li>
+            <li>
+              <!-- JAL-3092 -->Jalview could hang when importing certain
+              types of knotted RNA secondary structure.
+            </li>
+            <li>
+              <!-- JAL-3095 -->Sequence highlight and selection in
+              trimmed VARNA 2D structure is incorrect for sequences that
+              do not start at 1.
+            </li>
+            <li>
+              <!-- JAL-3061 -->'.' inserted into RNA secondary structure
+              annotation when columns are inserted into an alignment,
+              and when exporting as Stockholm flatfile.
+            </li>
+            <li>
+              <!-- JAL-3053 -->Jalview annotation rows containing upper
+              and lower-case 'E' and 'H' do not automatically get
+              treated as RNA secondary structure.
+            </li>
+            <li>
+              <!-- JAL-3106 -->.jvp should be used as default extension
+              (not .jar) when saving a jalview project file.
+            </li>
+            <li>
+              <!-- JAL-3105 -->Mac Users: closing a window correctly
+              transfers focus to previous window on OSX
+            </li>
+          </ul>
+          <em>Java 10 Issues Resolved</em>
+          <ul>
+            <li>
+              <!-- JAL-2988 -->OSX - Can't save new files via the File
+              or export menus by typing in a name into the Save dialog
+              box.
+            </li>
+            <li>
+              <!-- JAL-2988 JAL-2968 -->Jalview now uses patched version
+              of the <a href="https://violetlib.org/vaqua/overview.html">VAqua5</a>
+              'look and feel' which has improved compatibility with the
+              latest version of OSX.
+            </li>
+          </ul>
+        </div>
+    </td>
+    </tr>
     <tr>
       <td width="60" nowrap>
         <div align="center">
           <strong><a name="Jalview.2.10.4b1">2.10.4b1</a><br />
-            <em>27/05/2018</em></strong>
+            <em>7/06/2018</em></strong>
         </div>
       </td>
       <td><div align="left">
           <em></em>
           <ul>
             <li>
+              <!-- JAL-2920 -->Use HGVS nomenclature for variant
+              annotation retrieved from Uniprot
+            </li>
+            <li>
               <!-- JAL-1460 -->Windows File Shortcuts can be dragged
               onto the Jalview Desktop
             </li>
@@ -87,28 +230,37 @@ li:before {
           <em></em>
           <ul>
             <li>
+              <!-- JAL-3017 -->Cannot import features with multiple
+              variant elements (blocks import of some Uniprot records)
+            </li>
+            <li>
               <!-- JAL-2997 -->Clustal files with sequence positions in
               right-hand column parsed correctly
             </li>
             <li>
+              <!-- JAL-2991 -->Wrap view - export to SVG - IDs shown but
+              not alignment area in exported graphic
+            </li>
+            <li>
               <!-- JAL-2993 -->F2/Keyboard mode edits work when Overview
               window has input focus
             </li>
             <li>
-              <!-- JAL-2991 -->Wrap view - export to SVG - IDs shown but
-              not alignment area in exported graphic
+              <!-- JAL-2992 -->Annotation panel set too high when
+              annotation added to view (Windows)
+            </li>
+            <li>
+              <!-- JAL-3009 -->Jalview Desktop is slow to start up when
+              network connectivity is poor
             </li>
             <li>
               <!-- JAL-1460 -->Drag URL from chrome, firefox, IE to
-              Jalview desktop on Windows doesn't open file<br />
-            <em>Dragging the currently open URL and links from a page viewed in Firefox or Chrome on
-                Windows is now fully supported. If you are using Edge, only
-                links in the page can be dragged, and with Internet Explorer, only
-                the currently open URL in the browser can be dropped onto
-                Jalview.</em>
-                </li>
-            <li>
-              <!-- JAL-2992 -->
+              Jalview desktop on Windows doesn't open file<br /> <em>Dragging
+                the currently open URL and links from a page viewed in
+                Firefox or Chrome on Windows is now fully supported. If
+                you are using Edge, only links in the page can be
+                dragged, and with Internet Explorer, only the currently
+                open URL in the browser can be dropped onto Jalview.</em>
             </li>
           </ul>
         </div></td>
index 83c80ba..1f61dea 100644 (file)
@@ -30,8 +30,7 @@
   ID, and can be viewed in full via the
   <a href="../io/exportseqreport.html">Sequence Details</a> window. .
   Jalview also uses references for the retrieval of
-  <a href="../features/viewingpdbs.html">PDB structures</a> and <a
-    href="../features/dasfeatures.html">DAS features</a>, and for
+  <a href="../features/viewingpdbs.html">PDB structures</a>, and for
   retrieving sequence cross-references such as the protein products of a
   DNA sequence.
 </p>
   application provides three ways to access the retrieval function.
   Either:
 <ul>
-  <li>select the <strong>Discover PDB IDs</strong> option from the
-    structure submenu of the sequence's popup menu
-  </li>
-  <li>Choose one of the options from the 'Fetch DB Refs' submenu in
+       <li>select the <strong>Structure Chooser...</strong> option from
+               the Sequence ID popup menu.
+       </li>
+       <li>Choose one of the options from the 'Fetch DB Refs' submenu in
     the alignment window's <strong>Web Services</strong> menu:
     <ul>
-      <li><em>Standard Databases</em> will fetch references from
-        the EBI databases plus currently selected DAS sources</li>
-      <li>The other entries submenus leading to lists of individual
+                       <li><em>Standard Databases</em> will fetch references from EBI
+                               databases appropriate for the sequence type (Nucleotide or Protein)</li>
+                       <li>The other entries submenus leading to lists of individual
         database sources that Jalview can access.</li>
     </ul>
   </li>
-  <li>Answer 'Yes' when asked if you wish to retrieve database
-    references for your sequences after initiating a DAS Sequence
-    Feature fetch.</li>
 </ul>
 <p>Jalview discovers references for a sequence by generating a set
   of ID queries from the ID string of each sequence in the alignment. It
index d0b497c..8f36013 100755 (executable)
       Institute (EBI) and Distributed Annotation System servers that are
       capable of serving sequences.
     </li>
-    <li>The <a href="../features/dasfeatures.html">DAS Feature
-        Fetcher</a> enables the retrieval and visualization of features from
-      DAS annotation sources
-    </li>
-    <li>The <a href="dbreffetcher.html">Database Reference
-        Fetcher</a> transfers database references from records available
-      from DAS or the public sequence databases.
-    </li>
-    <li>The <strong>Web Services</strong> menu in each alignment
+               <li>The <a href="dbreffetcher.html">Database Reference
+                               Fetcher</a> transfers database references and annotation from the public
+                       sequence databases.
+               </li>
+               <li>The <strong>Web Services</strong> menu in each alignment
       window also provides access to the following:
       <ul>
         <li>Programs for <a href="msaclient.html">multiple
index 0abd2a7..13fe656 100755 (executable)
 </head>
 <body>
   <p>
-    <strong>What's new in Jalview 2.10.4 ?</strong>
-  </p>
-  <p>
-    This is the May 2018 release of Jalview, and the last in the 2.10.x series. Jalview 2.10.4 includes:
+    <strong>What's new in Jalview 2.10.5 ?</strong>
   </p>
+  <p>Jalview 2.10.5 is a minor release that includes critical
+    patches for users working with Ensembl, RNA secondary structure
+    annotation, and those running Jalview on OSX with Java 10.</p>
   <ul>
-    <li>Numerous efficiency improvements in the renderer and overview when working with large alignments with lots of hidden columns</li>
-    <li>Use of HTTPS when connecting to Uniprot, Ensembl and other EBI web services</li>
-    <li>Critical patches for running Jalview on OSX with Java 10</li>
-    <li>Easier adjustment of the Alignment ID panel and Annotation panel</li>
-    <li>Improved support for mapping between 3D Structures and Uniprot Protein Sequences</li>
-    <li>Improved support for discovering CDS and transcripts for Proteins and Ensembl gene IDs</li>
-    <li>New buttons on the Structure Chooser for adding structures
-      to an existing view, and disabling automatic superposition
-      according to linked alignments</li>
-    <li>Annotation transfer between Chimera and Jalview <em>(formerly only
-        available in 'Experimental' mode)</em></li>
+    <li>Jalview's default memory limit increased to 1G. <br/>If you have
+      problems starting Jalview 2.10.5 and you have 1G or less
+      physical memory on your machine, you will need to <a
+      href="memory.html#memsetting">reduce the memory</a> allocated to
+      Jalview.
+    </li>
+    <li>EPS, PNG and SVG export now includes hidden sequence
+      markers, and representative sequences are marked in bold.</li>
+    <li>Ensembl Client updated for Ensembl Rest API v7.<br />The
+      latest Ensembl API is not backwards compatible with earlier
+      versions of Jalview, so if you require Ensembl functionality you
+      will need to install this release.
+    </li>
+    <li>Improved support for VIENNA extended dot-bracket notation
+      for RNA secondary structure.</li>
+    <li>Positional and selected region highlighting in VARNA
+      'trimmed sequence' view made more reliable.</li>
   </ul>
   <p>
-    The full list of bugs fixed in this release can be found in the <a href="releases.html#Jalview.2.10.4">2.10.4
-      Release Notes</a>. 
+    The full list of bugs fixed in this release can be found in the <a
+      href="releases.html#Jalview.2.10.5">2.10.5 Release Notes</a>. The
+    majority of bug fixes and improvements in 2.10.5 are due to Jalview users
+    contacting us via the jalview-discuss email list. Thanks to everyone
+    who took the time to help make Jalview better !
+  </p>
+  <p>
+    <strong>Jalview and Java 10</strong>
   </p>
+  <p>This release addresses a critical bug for OSX users who are
+    running Jalview with Java 10 which can prevent files being saved
+    correctly through the 'Save As' dialog box.</p>
+    <em>Known Issues</em>
+  <ul>
+    <li>OSX: The 'Open File' dialog for Jalview's Groovy Console
+      appears with the title 'Save As', and attempting to select a file to load yields a FileNotFound exception.</br>The workaround is to first clear the 'Untitled' filename before selecting the file you wish to load.
+      </li>
+    <li>OSX: Links don't open when clicked on or via the Sequence or Alignment window popup menu.</li>
+    <li>OSX (Webstart): Jalview only displays old news feed items</li>
+  </ul>
 </body>
 </html>
diff --git a/lib/VAqua4.jar b/lib/VAqua4.jar
deleted file mode 100644 (file)
index c1e7cfc..0000000
Binary files a/lib/VAqua4.jar and /dev/null differ
diff --git a/lib/VAqua5-patch.jar b/lib/VAqua5-patch.jar
new file mode 100644 (file)
index 0000000..7b5c27b
Binary files /dev/null and b/lib/VAqua5-patch.jar differ
diff --git a/lib/htsjdk-1.133.jar b/lib/htsjdk-1.133.jar
deleted file mode 100644 (file)
index f084258..0000000
Binary files a/lib/htsjdk-1.133.jar and /dev/null differ
diff --git a/lib/jdas-1.0.4.jar b/lib/jdas-1.0.4.jar
deleted file mode 100644 (file)
index fb5d128..0000000
Binary files a/lib/jdas-1.0.4.jar and /dev/null differ
index d6e4cf3..ca8a275 100644 (file)
@@ -17,7 +17,7 @@
  * 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.
 -->
-<!--
+
 <!-- You may freely edit this file. See commented blocks below for -->
 <!-- some examples of how to customize the build. -->
 <!-- (If you delete it and reopen the project it will be recreated.) -->
index 3488ac6..3c06708 100644 (file)
@@ -1,4 +1,4 @@
-YEAR=2016
-AUTHORS=J Procter, M Carstairs, TC Ofoegbu, K Mourao, AM Waterhouse, J Engelhardt, LM Lui, A Menard, D Barton, N Sherstnev, D Roldan-Martinez, M Clamp, S Searle, G Barton
-AUTHORFNAMES=Jim Procter, Mungo Carstairs, Tochukwu 'Charles' Ofoegbu, Kira Mourao, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Anne Menard, Daniel Barton, Natasha Sherstnev, David Roldan-Martinez, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton
+YEAR=2018
+AUTHORS=J Procter, M Carstairs, B Soares, K Mourao, TC Ofoegbu, AM Waterhouse, J Engelhardt, LM Lui, A Menard, D Barton, N Sherstnev, D Roldan-Martinez, M Clamp, S Searle, G Barton
+AUTHORFNAMES=Jim Procter, Mungo Carstairs, Ben Soares, Kira Mourao, Tochukwu 'Charles' Ofoegbu, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Anne Menard, Daniel Barton, Natasha Sherstnev, David Roldan-Martinez, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton
  
\ No newline at end of file
index 832d3e5..68868c4 100755 (executable)
@@ -18,6 +18,7 @@
  * The Jalview Authors are detailed in the 'AUTHORS' file.
 -->
 <mapping>
+  <!-- see https://www.uniprot.org/docs/uniprot.xsd for latest Uniprot XML schema -->
        <class name="jalview.datamodel.xdb.uniprot.UniprotFile">
                  <map-to xml="uniprot"/>               
                  <field name="UniprotEntries" type="jalview.datamodel.xdb.uniprot.UniprotEntry" collection="vector">
@@ -69,7 +70,7 @@
     <field name="end">
       <bind-xml name="position" node="attribute" location="location/end"/>
     </field>
-    <field name="variation">
+    <field name="variation" collection="vector" type="string">
      <bind-xml name="variation"/>
     </field>
     <field name="original">
index 85ae718..a910a5a 100644 (file)
@@ -40,6 +40,7 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -83,7 +84,7 @@ public class ChimeraManager
     this.structureManager = structureManager;
     chimera = null;
     chimeraListenerThread = null;
-    currentModelsMap = new HashMap<Integer, ChimeraModel>();
+    currentModelsMap = new HashMap<>();
 
   }
 
@@ -98,7 +99,7 @@ public class ChimeraManager
   public List<ChimeraModel> getChimeraModels(String modelName,
           ModelType modelType)
   {
-    List<ChimeraModel> models = new ArrayList<ChimeraModel>();
+    List<ChimeraModel> models = new ArrayList<>();
     for (ChimeraModel model : currentModelsMap.values())
     {
       if (modelName.equals(model.getModelName())
@@ -112,7 +113,7 @@ public class ChimeraManager
 
   public Map<String, List<ChimeraModel>> getChimeraModelsMap()
   {
-    Map<String, List<ChimeraModel>> models = new HashMap<String, List<ChimeraModel>>();
+    Map<String, List<ChimeraModel>> models = new HashMap<>();
     for (ChimeraModel model : currentModelsMap.values())
     {
       String modelName = model.getModelName();
@@ -393,7 +394,7 @@ public class ChimeraManager
 
   public Map<Integer, ChimeraModel> getSelectedModels()
   {
-    Map<Integer, ChimeraModel> selectedModelsMap = new HashMap<Integer, ChimeraModel>();
+    Map<Integer, ChimeraModel> selectedModelsMap = new HashMap<>();
     List<String> chimeraReply = sendChimeraCommand(
             "list selection level molecule", true);
     if (chimeraReply != null)
@@ -418,7 +419,7 @@ public class ChimeraManager
    */
   public List<String> getSelectedResidueSpecs()
   {
-    List<String> selectedResidues = new ArrayList<String>();
+    List<String> selectedResidues = new ArrayList<>();
     List<String> chimeraReply = sendChimeraCommand(
             "list selection level residue", true);
     if (chimeraReply != null)
@@ -471,7 +472,7 @@ public class ChimeraManager
   // TODO: [Optional] Handle smiles names in a better way in Chimera?
   public List<ChimeraModel> getModelList()
   {
-    List<ChimeraModel> modelList = new ArrayList<ChimeraModel>();
+    List<ChimeraModel> modelList = new ArrayList<>();
     List<String> list = sendChimeraCommand("list models type molecule",
             true);
     if (list != null)
@@ -494,7 +495,7 @@ public class ChimeraManager
    */
   public List<String> getPresets()
   {
-    ArrayList<String> presetList = new ArrayList<String>();
+    ArrayList<String> presetList = new ArrayList<>();
     List<String> output = sendChimeraCommand("preset list", true);
     if (output != null)
     {
@@ -550,17 +551,19 @@ public class ChimeraManager
     // iterate over possible paths for starting Chimera
     for (String chimeraPath : chimeraPaths)
     {
-      File path = new File(chimeraPath);
-      // uncomment the next line to simulate Chimera not installed
-      // path = new File(chimeraPath + "x");
-      if (!path.canExecute())
-      {
-        error += "File '" + path + "' does not exist.\n";
-        continue;
-      }
       try
       {
-        List<String> args = new ArrayList<String>();
+        // ensure symbolic links are resolved
+        chimeraPath = Paths.get(chimeraPath).toRealPath().toString();
+        File path = new File(chimeraPath);
+        // uncomment the next line to simulate Chimera not installed
+        // path = new File(chimeraPath + "x");
+        if (!path.canExecute())
+        {
+          error += "File '" + path + "' does not exist.\n";
+          continue;
+        }
+        List<String> args = new ArrayList<>();
         args.add(chimeraPath);
         // shows Chimera output window but suppresses REST responses:
         // args.add("--debug");
@@ -573,7 +576,7 @@ public class ChimeraManager
         break;
       } catch (Exception e)
       {
-        // Chimera could not be started
+        // Chimera could not be started using this path
         error += e.getMessage();
       }
     }
@@ -699,7 +702,7 @@ public class ChimeraManager
 
   public List<String> getAttrList()
   {
-    List<String> attributes = new ArrayList<String>();
+    List<String> attributes = new ArrayList<>();
     final List<String> reply = sendChimeraCommand("list resattr", true);
     if (reply != null)
     {
@@ -718,7 +721,7 @@ public class ChimeraManager
   public Map<ChimeraResidue, Object> getAttrValues(String aCommand,
           ChimeraModel model)
   {
-    Map<ChimeraResidue, Object> values = new HashMap<ChimeraResidue, Object>();
+    Map<ChimeraResidue, Object> values = new HashMap<>();
     final List<String> reply = sendChimeraCommand("list residue spec "
             + model.toSpec() + " attribute " + aCommand, true);
     if (reply != null)
@@ -818,10 +821,10 @@ public class ChimeraManager
   protected List<String> sendRestCommand(String command)
   {
     String restUrl = "http://127.0.0.1:" + this.chimeraRestPort + "/run";
-    List<NameValuePair> commands = new ArrayList<NameValuePair>(1);
+    List<NameValuePair> commands = new ArrayList<>(1);
     commands.add(new BasicNameValuePair("command", command));
 
-    List<String> reply = new ArrayList<String>();
+    List<String> reply = new ArrayList<>();
     BufferedReader response = null;
     try
     {
index 131b39c..0af5d20 100755 (executable)
@@ -273,7 +273,7 @@ public class Conservation
        * or not conserved (-1)
        * Using TreeMap means properties are displayed in alphabetical order
        */
-      SortedMap<String, Integer> resultHash = new TreeMap<String, Integer>();
+      SortedMap<String, Integer> resultHash = new TreeMap<>();
       SymbolCounts symbolCounts = values.getSymbolCounts();
       char[] symbols = symbolCounts.symbols;
       int[] counts = symbolCounts.values;
@@ -567,7 +567,7 @@ public class Conservation
    */
   private void percentIdentity(ScoreMatrix sm)
   {
-    seqNums = new Vector<int[]>();
+    seqNums = new Vector<>();
     int i = 0, iSize = sequences.length;
     // Do we need to calculate this again?
     for (i = 0; i < iSize; i++)
@@ -622,7 +622,7 @@ public class Conservation
   protected void findQuality(int startCol, int endCol,
           ScoreMatrix scoreMatrix)
   {
-    quality = new Vector<Double>();
+    quality = new Vector<>();
 
     double max = -Double.MAX_VALUE;
     float[][] scores = scoreMatrix.getMatrix();
@@ -721,8 +721,8 @@ public class Conservation
 
   /**
    * Complete the given consensus and quuality annotation rows. Note: currently
-   * this method will enlarge the given annotation row if it is too small,
-   * otherwise will leave its length unchanged.
+   * this method will reallocate the given annotation row if it is different to
+   * the calculated width, otherwise will leave its length unchanged.
    * 
    * @param conservation
    *          conservation annotation row
@@ -754,7 +754,7 @@ public class Conservation
     float qmax = 0f;
 
     if (conservation != null && conservation.annotations != null
-            && conservation.annotations.length < alWidth)
+            && conservation.annotations.length != alWidth)
     {
       conservation.annotations = new Annotation[alWidth];
     }
@@ -763,7 +763,7 @@ public class Conservation
     {
       quality2.graphMax = (float) qualityMaximum;
       if (quality2.annotations != null
-              && quality2.annotations.length < alWidth)
+              && quality2.annotations.length != alWidth)
       {
         quality2.annotations = new Annotation[alWidth];
       }
index 0d39abf..e5cda93 100644 (file)
@@ -440,8 +440,8 @@ public class Rna
       /*
        * catch things like <<..<<..>>..<<..>>>> |
        */
-      int j = bps.size() - 1;
-      while (j >= 0)
+      int j = bps.size();
+      while (--j >= 0)
       {
         int popen = bps.get(j).getBP5();
 
@@ -460,7 +460,6 @@ public class Rna
             break;
           }
         }
-        j -= 1;
       }
 
       // Put positions and helix information into the hashtable
index dcd6546..83bc810 100755 (executable)
@@ -28,8 +28,6 @@ import jalview.schemes.UserColourScheme;
 import jalview.structure.StructureImportSettings;
 import jalview.urls.IdOrgSettings;
 import jalview.util.ColorUtils;
-import jalview.ws.dbsources.das.api.DasSourceRegistryI;
-import jalview.ws.dbsources.das.datamodel.DasSourceRegistry;
 import jalview.ws.sifts.SiftsSettings;
 
 import java.awt.Color;
@@ -982,22 +980,6 @@ public class Cache
     return null;
   }
 
-  private static DasSourceRegistryI sourceRegistry = null;
-
-  /**
-   * initialise and ..
-   * 
-   * @return instance of the das source registry
-   */
-  public static DasSourceRegistryI getDasSourceRegistry()
-  {
-    if (sourceRegistry == null)
-    {
-      sourceRegistry = new DasSourceRegistry();
-    }
-    return sourceRegistry;
-  }
-
   /**
    * Set the specified value, or remove it if null or empty. Does not save the
    * properties file.
index 2f5da61..c41f291 100755 (executable)
@@ -70,7 +70,14 @@ import groovy.util.GroovyScriptEngine;
 /**
  * Main class for Jalview Application <br>
  * <br>
- * start with java -Djava.ext.dirs=$PATH_TO_LIB$ jalview.bin.Jalview
+ * start with: java -classpath "$PATH_TO_LIB$/*:$PATH_TO_CLASSES$" \
+ * jalview.bin.Jalview
+ * 
+ * or on Windows: java -classpath "$PATH_TO_LIB$/*;$PATH_TO_CLASSES$" \
+ * jalview.bin.Jalview jalview.bin.Jalview
+ * 
+ * (ensure -classpath arg is quoted to avoid shell expansion of '*' and do not
+ * embellish '*' to e.g. '*.jar')
  * 
  * @author $author$
  * @version $Revision$
@@ -149,7 +156,6 @@ public class Jalview
           af.setProgressBar(MessageManager
                   .getString("status.das_features_being_retrived"), id);
           af.featureSettings_actionPerformed(null);
-          af.featureSettings.fetchDasFeatures(dasSources, true);
           af.setProgressBar(null, id);
           synchronized (us)
           {
@@ -265,7 +271,7 @@ public class Jalview
     {
       error.printStackTrace();
       System.out.println("\nEssential logging libraries not found."
-              + "\nUse: java -Djava.ext.dirs=$PATH_TO_LIB$ jalview.bin.Jalview");
+              + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview");
       System.exit(0);
     }
 
index 0098d76..ee9389c 100755 (executable)
@@ -25,6 +25,7 @@ import jalview.analysis.SecStrConsensus.SimpleBP;
 import jalview.analysis.WUSSParseException;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -164,6 +165,64 @@ public class AlignmentAnnotation
   }
 
   /**
+   * Get the RNA Secondary Structure SequenceFeature Array if present
+   */
+  public SequenceFeature[] getRnaSecondaryStructure()
+  {
+    return this._rnasecstr;
+  }
+
+  /**
+   * Check the RNA Secondary Structure is equivalent to one in given
+   * AlignmentAnnotation param
+   */
+  public boolean rnaSecondaryStructureEquivalent(AlignmentAnnotation that)
+  {
+    return rnaSecondaryStructureEquivalent(that, true);
+  }
+
+  public boolean rnaSecondaryStructureEquivalent(AlignmentAnnotation that, boolean compareType)
+  {
+    SequenceFeature[] thisSfArray = this.getRnaSecondaryStructure();
+    SequenceFeature[] thatSfArray = that.getRnaSecondaryStructure();
+    if (thisSfArray == null || thatSfArray == null)
+    {
+      return thisSfArray == null && thatSfArray == null;
+    }
+    if (thisSfArray.length != thatSfArray.length)
+    {
+      return false;
+    }
+    Arrays.sort(thisSfArray, new SFSortByEnd()); // probably already sorted
+                                                   // like this
+    Arrays.sort(thatSfArray, new SFSortByEnd()); // probably already sorted
+                                                   // like this
+    for (int i=0; i < thisSfArray.length; i++) {
+      SequenceFeature thisSf = thisSfArray[i];
+      SequenceFeature thatSf = thatSfArray[i];
+      if (compareType) {
+        if (thisSf.getType() == null || thatSf.getType() == null) {
+          if (thisSf.getType() == null && thatSf.getType() == null) {
+            continue;
+          } else {
+            return false;
+          }
+        }
+        if (! thisSf.getType().equals(thatSf.getType())) {
+          return false;
+        }
+      }
+      if (!(thisSf.getBegin() == thatSf.getBegin()
+              && thisSf.getEnd() == thatSf.getEnd()))
+      {
+        return false;
+      }
+    }
+    return true;
+
+  }
+
+  /**
    * map of positions in the associated annotation
    */
   private Map<Integer, Annotation> sequenceMapping;
@@ -294,6 +353,7 @@ public class AlignmentAnnotation
     char firstChar = 0;
     for (int i = 0; i < annotations.length; i++)
     {
+      // DEBUG System.out.println(i + ": " + annotations[i]);
       if (annotations[i] == null)
       {
         continue;
@@ -301,12 +361,15 @@ public class AlignmentAnnotation
       if (annotations[i].secondaryStructure == 'H'
               || annotations[i].secondaryStructure == 'E')
       {
+        // DEBUG System.out.println( "/H|E/ '" +
+        // annotations[i].secondaryStructure + "'");
         hasIcons |= true;
       }
       else
       // Check for RNA secondary structure
       {
-        // System.out.println(annotations[i].secondaryStructure);
+        // DEBUG System.out.println( "/else/ '" +
+        // annotations[i].secondaryStructure + "'");
         // TODO: 2.8.2 should this ss symbol validation check be a function in
         // RNA/ResidueProperties ?
         if (annotations[i].secondaryStructure == '('
@@ -317,10 +380,12 @@ public class AlignmentAnnotation
                 || annotations[i].secondaryStructure == 'B'
                 || annotations[i].secondaryStructure == 'C'
                 || annotations[i].secondaryStructure == 'D'
-                || annotations[i].secondaryStructure == 'E'
+                // || annotations[i].secondaryStructure == 'E' // ambiguous on
+                // its own -- already checked above
                 || annotations[i].secondaryStructure == 'F'
                 || annotations[i].secondaryStructure == 'G'
-                || annotations[i].secondaryStructure == 'H'
+                // || annotations[i].secondaryStructure == 'H' // ambiguous on
+                // its own -- already checked above
                 || annotations[i].secondaryStructure == 'I'
                 || annotations[i].secondaryStructure == 'J'
                 || annotations[i].secondaryStructure == 'K'
@@ -367,7 +432,7 @@ public class AlignmentAnnotation
         // &&
         // annotations[i].displayCharacter.charAt(0)==annotations[i].secondaryStructure
                 firstChar != ' ' && firstChar != '$' && firstChar != 0xCE
-                && firstChar != '(' && firstChar != '[' && firstChar != '>'
+                && firstChar != '(' && firstChar != '[' && firstChar != '<'
                 && firstChar != '{' && firstChar != 'A' && firstChar != 'B'
                 && firstChar != 'C' && firstChar != 'D' && firstChar != 'E'
                 && firstChar != 'F' && firstChar != 'G' && firstChar != 'H'
@@ -1648,4 +1713,5 @@ public class AlignmentAnnotation
     }
     return aa;
   }
+
 }
index ae29417..f6919cd 100755 (executable)
@@ -210,7 +210,10 @@ public class Annotation
     return ((value == 0f)
             && ((description == null) || (description.trim().length() == 0))
             && ((displayCharacter == null)
-                    || (displayCharacter.trim().length() == 0))
+                    || (displayCharacter.trim().length() == 0)
+                    || (displayCharacter.equals(" ."))) // RNA Stockholm blank
+                                                        // displayCharacter can
+                                                        // end up like this
             && (secondaryStructure == '\0' || (secondaryStructure == ' '))
             && colour == null);
   }
index 34565c6..7052f34 100755 (executable)
@@ -27,6 +27,7 @@ import jalview.datamodel.features.FeatureSourceI;
 import jalview.datamodel.features.FeatureSources;
 import jalview.util.StringUtils;
 
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -736,3 +737,21 @@ public class SequenceFeature implements FeatureLocationI
     source = theSource;
   }
 }
+
+class SFSortByEnd implements Comparator<SequenceFeature>
+{
+  @Override
+  public int compare(SequenceFeature a, SequenceFeature b)
+  {
+    return a.getEnd() - b.getEnd();
+  }
+}
+
+class SFSortByBegin implements Comparator<SequenceFeature>
+{
+  @Override
+  public int compare(SequenceFeature a, SequenceFeature b)
+  {
+    return a.getBegin() - b.getBegin();
+  }
+}
index fcf1b53..727d3ef 100644 (file)
@@ -87,7 +87,7 @@ public class SequenceFeatures implements SequenceFeaturesI
      */
     // featureStore = Collections
     // .synchronizedSortedMap(new TreeMap<String, FeatureStore>());
-    featureStore = new TreeMap<String, FeatureStore>();
+    featureStore = new TreeMap<>();
   }
 
   /**
@@ -382,9 +382,10 @@ public class SequenceFeatures implements SequenceFeaturesI
   }
 
   /**
-   * Answers true if the given type is one of the specified sequence ontology
-   * terms (or a sub-type of one), or if no terms are supplied. Answers false if
-   * filter terms are specified and the given term does not match any of them.
+   * Answers true if the given type matches one of the specified terms (or is a
+   * sub-type of one in the Sequence Ontology), or if no terms are supplied.
+   * Answers false if filter terms are specified and the given term does not
+   * match any of them.
    * 
    * @param type
    * @param soTerm
@@ -399,7 +400,7 @@ public class SequenceFeatures implements SequenceFeaturesI
     SequenceOntologyI so = SequenceOntologyFactory.getInstance();
     for (String term : soTerm)
     {
-      if (so.isA(type, term))
+      if (type.equals(term) || so.isA(type, term))
       {
         return true;
       }
index 80c4f9a..31712b9 100644 (file)
@@ -82,9 +82,9 @@ public interface SequenceFeaturesI
           String group, String... type);
 
   /**
-   * Answers a list of all features stored, whose type either matches one of the
-   * given ontology terms, or is a specialisation of a term in the Sequence
-   * Ontology. Results are returned in no particular guaranteed order.
+   * Answers a list of all features stored, whose type either matches, or is a
+   * specialisation (in the Sequence Ontology) of, one of the given terms.
+   * Results are returned in no particular order.
    * 
    * @param ontologyTerm
    * @return
index 4c2ae24..8bd5652 100644 (file)
@@ -20,6 +20,8 @@
  */
 package jalview.datamodel.xdb.uniprot;
 
+import java.util.Vector;
+
 /**
  * A data model class for binding from Uniprot XML via uniprot_mapping.xml
  */
@@ -31,7 +33,7 @@ public class UniprotFeature
 
   private String original = null;
 
-  private String variation = null;
+  private Vector<String> variation = null;
 
   private String status;
 
@@ -51,19 +53,7 @@ public class UniprotFeature
 
   public String getDescription()
   {
-    if (description == null && variation == null && original == null)
-    {
-      return null;
-    }
-    return (description == null ? "" : description)
-            + (variation != null
-                    ? (description != null ? " " : "") + "Variation: '"
-                            + variation + "'"
-                    : "")
-            + (original != null
-                    ? ((description != null || variation != null) ? " "
-                            : "") + "Original: '" + original + "'"
-                    : "");
+    return description;
   }
 
   public void setDescription(String d)
@@ -122,12 +112,12 @@ public class UniprotFeature
     this.original = original;
   }
 
-  public String getVariation()
+  public Vector<String> getVariation()
   {
     return variation;
   }
 
-  public void setVariation(String variant)
+  public void setVariation(Vector<String> variant)
   {
     this.variation = variant;
   }
index 952f01e..7384327 100644 (file)
 package jalview.ext.ensembl;
 
 import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
 import jalview.io.gff.SequenceOntologyFactory;
 import jalview.io.gff.SequenceOntologyI;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import com.stevesoft.pat.Regex;
 
 /**
@@ -109,23 +113,27 @@ public class EnsemblCdna extends EnsemblSeqProxy
   }
 
   /**
-   * Answers true if the sequence feature type is 'exon' (or a subtype of exon
-   * in the Sequence Ontology), and the Parent of the feature is the transcript
-   * we are retrieving
+   * Answers a list of sequence features (if any) whose type is 'exon' (or a
+   * subtype of exon in the Sequence Ontology), and whose Parent is the
+   * transcript we are retrieving
    */
   @Override
-  protected boolean identifiesSequence(SequenceFeature sf, String accId)
+  protected List<SequenceFeature> getIdentifyingFeatures(SequenceI seq,
+          String accId)
   {
-    if (SequenceOntologyFactory.getInstance().isA(sf.getType(),
-            SequenceOntologyI.EXON))
+    List<SequenceFeature> result = new ArrayList<>();
+    List<SequenceFeature> sfs = seq.getFeatures()
+            .getFeaturesByOntology(SequenceOntologyI.EXON);
+    for (SequenceFeature sf : sfs)
     {
       String parentFeature = (String) sf.getValue(PARENT);
       if (("transcript:" + accId).equals(parentFeature))
       {
-        return true;
+        result.add(sf);
       }
     }
-    return false;
+
+    return result;
   }
 
   /**
index 8b2550d..8a71b64 100644 (file)
@@ -102,23 +102,26 @@ public class EnsemblCds extends EnsemblSeqProxy
   }
 
   /**
-   * Answers true if the sequence feature type is 'CDS' (or a subtype of CDS in
-   * the Sequence Ontology), and the Parent of the feature is the transcript we
-   * are retrieving
+   * Answers a list of sequence features (if any) whose type is 'CDS' (or a
+   * subtype of CDS in the Sequence Ontology), and whose Parent is the
+   * transcript we are retrieving
    */
   @Override
-  protected boolean identifiesSequence(SequenceFeature sf, String accId)
+  protected List<SequenceFeature> getIdentifyingFeatures(SequenceI seq,
+          String accId)
   {
-    if (SequenceOntologyFactory.getInstance().isA(sf.getType(),
-            SequenceOntologyI.CDS))
+    List<SequenceFeature> result = new ArrayList<>();
+    List<SequenceFeature> sfs = seq.getFeatures()
+            .getFeaturesByOntology(SequenceOntologyI.CDS);
+    for (SequenceFeature sf : sfs)
     {
       String parentFeature = (String) sf.getValue(PARENT);
       if (("transcript:" + accId).equals(parentFeature))
       {
-        return true;
+        result.add(sf);
       }
     }
-    return false;
+    return result;
   }
 
   /**
@@ -130,7 +133,7 @@ public class EnsemblCds extends EnsemblSeqProxy
   protected List<int[]> getCdsRanges(SequenceI dnaSeq)
   {
     int len = dnaSeq.getLength();
-    List<int[]> ranges = new ArrayList<int[]>();
+    List<int[]> ranges = new ArrayList<>();
     ranges.add(new int[] { 1, len });
     return ranges;
   }
index cb6f548..582eac6 100644 (file)
@@ -22,9 +22,11 @@ package jalview.ext.ensembl;
 
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
+import jalview.io.DataSourceType;
 import jalview.io.FeaturesFile;
 import jalview.io.FileParse;
 
+import java.io.BufferedReader;
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -84,12 +86,13 @@ class EnsemblFeatures extends EnsemblRestClient
     // TODO: use a vararg String... for getSequenceRecords instead?
     List<String> queries = new ArrayList<>();
     queries.add(query);
-    FileParse fp = getSequenceReader(queries);
-    if (fp == null || !fp.isValid())
+    BufferedReader fp = getSequenceReader(queries);
+    if (fp == null)
     {
       return null;
     }
-    FeaturesFile fr = new FeaturesFile(fp);
+    FeaturesFile fr = new FeaturesFile(
+            new FileParse(fp, null, DataSourceType.URL));
     return new Alignment(fr.getSeqsAsArray());
   }
 
@@ -140,13 +143,13 @@ class EnsemblFeatures extends EnsemblRestClient
    * describes the required encoding of the response.
    */
   @Override
-  protected String getRequestMimeType(boolean multipleIds)
+  protected String getRequestMimeType()
   {
     return "text/x-gff3";
   }
 
   /**
-   * Returns the MIME type for GFF3.
+   * Returns the MIME type for GFF3
    */
   @Override
   protected String getResponseMimeType()
index 7e6f653..36b19e2 100644 (file)
@@ -548,23 +548,27 @@ public class EnsemblGene extends EnsemblSeqProxy
   }
 
   /**
-   * Answers true for a feature of type 'gene' (or a sub-type of gene in the
-   * Sequence Ontology), whose ID is the accession we are retrieving
+   * Answers a list of sequence features (if any) whose type is 'gene' (or a
+   * subtype of gene in the Sequence Ontology), and whose ID is the accession we
+   * are retrieving
    */
   @Override
-  protected boolean identifiesSequence(SequenceFeature sf, String accId)
+  protected List<SequenceFeature> getIdentifyingFeatures(SequenceI seq,
+          String accId)
   {
-    if (SequenceOntologyFactory.getInstance().isA(sf.getType(),
-            SequenceOntologyI.GENE))
+    List<SequenceFeature> result = new ArrayList<>();
+    List<SequenceFeature> sfs = seq.getFeatures()
+            .getFeaturesByOntology(SequenceOntologyI.GENE);
+    for (SequenceFeature sf : sfs)
     {
       // NB features as gff use 'ID'; rest services return as 'id'
       String id = (String) sf.getValue("ID");
       if ((GENE_PREFIX + accId).equalsIgnoreCase(id))
       {
-        return true;
+        result.add(sf);
       }
     }
-    return false;
+    return result;
   }
 
   /**
@@ -595,17 +599,6 @@ public class EnsemblGene extends EnsemblSeqProxy
   }
 
   /**
-   * Answers false. This allows an optimisation - a single 'gene' feature is all
-   * that is needed to identify the positions of the gene on the genomic
-   * sequence.
-   */
-  @Override
-  protected boolean isSpliceable()
-  {
-    return false;
-  }
-
-  /**
    * Override to do nothing as Ensembl doesn't return a protein sequence for a
    * gene identifier
    */
index bde3c0f..6684e20 100644 (file)
 package jalview.ext.ensembl;
 
 import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
+import jalview.io.gff.SequenceOntologyI;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * A client to fetch genomic sequence from Ensembl
@@ -94,22 +99,32 @@ public class EnsemblGenome extends EnsemblSeqProxy
   }
 
   /**
-   * Answers true if the sequence feature type is 'transcript' (or a subtype of
-   * transcript in the Sequence Ontology), and the ID of the feature is the
-   * transcript we are retrieving
+   * Answers a list of sequence features (if any) whose type is 'transcript' (or
+   * a subtype of transcript in the Sequence Ontology), and whose ID is the
+   * accession we are retrieving.
+   * <p>
+   * Note we also include features of type "NMD_transcript_variant", although
+   * not strictly 'transcript' in the SO, as they used in Ensembl as if they
+   * were.
    */
   @Override
-  protected boolean identifiesSequence(SequenceFeature sf, String accId)
+  protected List<SequenceFeature> getIdentifyingFeatures(SequenceI seq,
+          String accId)
   {
-    if (isTranscript(sf.getType()))
+    List<SequenceFeature> result = new ArrayList<>();
+    List<SequenceFeature> sfs = seq.getFeatures().getFeaturesByOntology(
+            SequenceOntologyI.TRANSCRIPT,
+            SequenceOntologyI.NMD_TRANSCRIPT_VARIANT);
+    for (SequenceFeature sf : sfs)
     {
+      // NB features as gff use 'ID'; rest services return as 'id'
       String id = (String) sf.getValue("ID");
       if (("transcript:" + accId).equals(id))
       {
-        return true;
+        result.add(sf);
       }
     }
-    return false;
+    return result;
   }
 
 }
index 37dff51..fa24f1e 100644 (file)
@@ -61,18 +61,6 @@ public class EnsemblInfo extends EnsemblRestClient
     return true;
   }
 
-  @Override
-  protected String getRequestMimeType(boolean multipleIds)
-  {
-    return "application/json";
-  }
-
-  @Override
-  protected String getResponseMimeType()
-  {
-    return "application/json";
-  }
-
   /**
    * Answers the domain (http://rest.ensembl.org or
    * http://rest.ensemblgenomes.org) for the given division, or null if not
index 5f353f8..c6b794a 100644 (file)
@@ -117,21 +117,9 @@ public class EnsemblLookup extends EnsemblRestClient
     return true;
   }
 
-  @Override
-  protected String getRequestMimeType(boolean multipleIds)
-  {
-    return "application/json";
-  }
-
-  @Override
-  protected String getResponseMimeType()
-  {
-    return "application/json";
-  }
-
   /**
    * Returns the gene id related to the given identifier (which may be for a
-   * gene, transcript or protein)
+   * gene, transcript or protein), or null if none is found
    * 
    * @param identifier
    * @return
@@ -143,7 +131,7 @@ public class EnsemblLookup extends EnsemblRestClient
 
   /**
    * Returns the gene id related to the given identifier (which may be for a
-   * gene, transcript or protein)
+   * gene, transcript or protein), or null if none is found
    * 
    * @param identifier
    * @param objectType
@@ -165,6 +153,10 @@ public class EnsemblLookup extends EnsemblRestClient
    */
   protected String parseGeneId(JSONObject val)
   {
+    if (val == null)
+    {
+      return null;
+    }
     String geneId = null;
     String type = val.get(OBJECT_TYPE).toString();
     if (OBJECT_TYPE_GENE.equalsIgnoreCase(type))
index 56657e0..f01bd4f 100644 (file)
@@ -98,18 +98,6 @@ public class EnsemblMap extends EnsemblRestClient
   }
 
   @Override
-  protected String getRequestMimeType(boolean multipleIds)
-  {
-    return "application/json";
-  }
-
-  @Override
-  protected String getResponseMimeType()
-  {
-    return "application/json";
-  }
-
-  @Override
   protected URL getUrl(List<String> ids) throws MalformedURLException
   {
     return null; // not used
@@ -257,7 +245,10 @@ public class EnsemblMap extends EnsemblRestClient
       {
         url = getIdMapUrl(domain, accession, start, end, cdsOrCdna);
         br = getHttpResponse(url, null);
-        return (parseIdMappingResponse(br, accession, domain));
+        if (br != null)
+        {
+          return (parseIdMappingResponse(br, accession, domain));
+        }
       }
       return null;
     } catch (Throwable t)
index 99006aa..0280f16 100644 (file)
@@ -22,6 +22,10 @@ package jalview.ext.ensembl;
 
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
+
+import java.util.ArrayList;
+import java.util.List;
 
 import com.stevesoft.pat.Regex;
 
@@ -106,10 +110,10 @@ public class EnsemblProtein extends EnsemblSeqProxy
   }
 
   @Override
-  protected boolean identifiesSequence(SequenceFeature sf, String accId)
+  protected List<SequenceFeature> getIdentifyingFeatures(SequenceI seq,
+          String accId)
   {
-    // not applicable - protein sequence is not a 'subset' of genomic sequence
-    return false;
+    return new ArrayList<>();
   }
 
   @Override
index 9dea886..9e01cc4 100644 (file)
@@ -20,8 +20,6 @@
  */
 package jalview.ext.ensembl;
 
-import jalview.io.DataSourceType;
-import jalview.io.FileParse;
 import jalview.util.StringUtils;
 
 import java.io.BufferedReader;
@@ -66,17 +64,14 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
    * @see https://github.com/Ensembl/ensembl-rest/wiki/Change-log
    * @see http://rest.ensembl.org/info/rest?content-type=application/json
    */
-  private static final String LATEST_ENSEMBLGENOMES_REST_VERSION = "6.0";
+  private static final String LATEST_ENSEMBLGENOMES_REST_VERSION = "7.0";
 
-  private static final String LATEST_ENSEMBL_REST_VERSION = "6.1";
+  private static final String LATEST_ENSEMBL_REST_VERSION = "7.0";
 
   private static final String REST_CHANGE_LOG = "https://github.com/Ensembl/ensembl-rest/wiki/Change-log";
 
   private static Map<String, EnsemblData> domainData;
 
-  // @see https://github.com/Ensembl/ensembl-rest/wiki/Output-formats
-  private static final String PING_URL = "http://rest.ensembl.org/info/ping.json";
-
   private final static long AVAILABILITY_RETEST_INTERVAL = 10000L; // 10 seconds
 
   private final static long VERSION_RETEST_INTERVAL = 1000L * 3600; // 1 hr
@@ -156,22 +151,28 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
   protected abstract boolean useGetRequest();
 
   /**
-   * Return the desired value for the Content-Type request header
-   * 
-   * @param multipleIds
+   * Returns the desired value for the Content-Type request header. Default is
+   * application/json, override if required to vary this.
    * 
    * @return
    * @see https://github.com/Ensembl/ensembl-rest/wiki/HTTP-Headers
    */
-  protected abstract String getRequestMimeType(boolean multipleIds);
+  protected String getRequestMimeType()
+  {
+    return "application/json";
+  }
 
   /**
-   * Return the desired value for the Accept request header
+   * Return the desired value for the Accept request header. Default is
+   * application/json, override if required to vary this.
    * 
    * @return
    * @see https://github.com/Ensembl/ensembl-rest/wiki/HTTP-Headers
    */
-  protected abstract String getResponseMimeType();
+  protected String getResponseMimeType()
+  {
+    return "application/json";
+  }
 
   /**
    * Checks Ensembl's REST 'ping' endpoint, and returns true if response
@@ -225,25 +226,20 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
   }
 
   /**
-   * returns a reader to a Fasta response from the Ensembl sequence endpoint
+   * Returns a reader to a (Json) response from the Ensembl sequence endpoint.
+   * If the request failed the return value may be null.
    * 
    * @param ids
    * @return
    * @throws IOException
    */
-  protected FileParse getSequenceReader(List<String> ids) throws IOException
+  protected BufferedReader getSequenceReader(List<String> ids)
+          throws IOException
   {
     URL url = getUrl(ids);
 
     BufferedReader reader = getHttpResponse(url, ids);
-    if (reader == null)
-    {
-      // request failed
-      return null;
-    }
-    FileParse fp = new FileParse(reader, url.toString(),
-            DataSourceType.URL);
-    return fp;
+    return reader;
   }
 
   /**
@@ -262,7 +258,8 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
   }
 
   /**
-   * Sends the HTTP request and gets the response as a reader
+   * Sends the HTTP request and gets the response as a reader. Returns null if
+   * the HTTP response code was not 200.
    * 
    * @param url
    * @param ids
@@ -271,7 +268,6 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
    *          in milliseconds
    * @return
    * @throws IOException
-   *           if response code was not 200, or other I/O error
    */
   protected BufferedReader getHttpResponse(URL url, List<String> ids,
           int readTimeout) throws IOException
@@ -335,8 +331,7 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
     boolean multipleIds = ids != null && ids.size() > 1;
     connection.setRequestMethod(
             multipleIds ? HttpMethod.POST : HttpMethod.GET);
-    connection.setRequestProperty("Content-Type",
-            getRequestMimeType(multipleIds));
+    connection.setRequestProperty("Content-Type", getRequestMimeType());
     connection.setRequestProperty("Accept", getResponseMimeType());
 
     connection.setUseCaches(false);
index 9229379..7b448fd 100644 (file)
@@ -28,12 +28,11 @@ import jalview.datamodel.AlignmentI;
 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.datamodel.features.SequenceFeatures;
 import jalview.exceptions.JalviewException;
-import jalview.io.FastaFile;
-import jalview.io.FileParse;
 import jalview.io.gff.Gff3Helper;
 import jalview.io.gff.SequenceOntologyFactory;
 import jalview.io.gff.SequenceOntologyI;
@@ -42,6 +41,7 @@ import jalview.util.DBRefUtils;
 import jalview.util.IntRangeComparator;
 import jalview.util.MapList;
 
+import java.io.BufferedReader;
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -50,6 +50,10 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+
 /**
  * Base class for Ensembl sequence fetchers
  * 
@@ -385,50 +389,44 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
       inProgress = false;
       throw new JalviewException("ENSEMBL Rest API not available.");
     }
-    FileParse fp = getSequenceReader(ids);
-    if (fp == null)
+    BufferedReader br = getSequenceReader(ids);
+    if (br == null)
     {
       return alignment;
     }
 
-    FastaFile fr = new FastaFile(fp);
-    if (fr.hasWarningMessage())
+    List<SequenceI> seqs = parseSequenceJson(br);
+
+    if (seqs.isEmpty())
     {
-      System.out.println(
-              String.format("Warning when retrieving %d ids %s\n%s",
-                      ids.size(), ids.toString(), fr.getWarningMessage()));
+      throw new IOException("No data returned for " + ids);
     }
-    else if (fr.getSeqs().size() != ids.size())
+
+    if (seqs.size() != ids.size())
     {
       System.out.println(String.format(
               "Only retrieved %d sequences for %d query strings",
-              fr.getSeqs().size(), ids.size()));
+              seqs.size(), ids.size()));
     }
 
-    if (fr.getSeqs().size() == 1 && fr.getSeqs().get(0).getLength() == 0)
+    if (!seqs.isEmpty())
     {
-      /*
-       * POST request has returned an empty FASTA file e.g. for invalid id
-       */
-      throw new IOException("No data returned for " + ids);
-    }
-
-    if (fr.getSeqs().size() > 0)
-    {
-      AlignmentI seqal = new Alignment(fr.getSeqsAsArray());
-      for (SequenceI sq : seqal.getSequences())
+      AlignmentI seqal = new Alignment(
+              seqs.toArray(new SequenceI[seqs.size()]));
+      for (SequenceI seq : seqs)
       {
-        if (sq.getDescription() == null)
+        if (seq.getDescription() == null)
         {
-          sq.setDescription(getDbName());
+          seq.setDescription(getDbName());
         }
-        String name = sq.getName();
+        String name = seq.getName();
         if (ids.contains(name)
                 || ids.contains(name.replace("ENSP", "ENST")))
         {
-          DBRefEntry dbref = DBRefUtils.parseToDbRef(sq, getDbSource(),
+          // TODO JAL-3077 use true accession version in dbref
+          DBRefEntry dbref = DBRefUtils.parseToDbRef(seq, getDbSource(),
                   getEnsemblDataVersion(), name);
-          sq.addDBRef(dbref);
+          seq.addDBRef(dbref);
         }
       }
       if (alignment == null)
@@ -444,6 +442,49 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
   }
 
   /**
+   * Parses a JSON response for a single sequence ID query
+   * 
+   * @param br
+   * @return a single jalview.datamodel.Sequence
+   * @see http://rest.ensembl.org/documentation/info/sequence_id
+   */
+  protected List<SequenceI> parseSequenceJson(BufferedReader br)
+  {
+    JSONParser jp = new JSONParser();
+    List<SequenceI> result = new ArrayList<>();
+    try
+    {
+      /*
+       * for now, assumes only one sequence returned; refactor if needed
+       * in future to handle a JSONArray with more than one
+       */
+      final JSONObject val = (JSONObject) jp.parse(br);
+      Object s = val.get("desc");
+      String desc = s == null ? null : s.toString();
+      s = val.get("id");
+      String id = s == null ? null : s.toString();
+      s = val.get("seq");
+      String seq = s == null ? null : s.toString();
+      Sequence sequence = new Sequence(id, seq);
+      if (desc != null)
+      {
+        sequence.setDescription(desc);
+      }
+      // todo JAL-3077 make a DBRefEntry with true accession version
+      // s = val.get("version");
+      // String version = s == null ? "0" : s.toString();
+      // DBRefEntry dbref = new DBRefEntry(getDbSource(), version, id);
+      // sequence.addDBRef(dbref);
+      result.add(sequence);
+    } catch (ParseException | IOException e)
+    {
+      System.err.println("Error processing JSON response: " + e.toString());
+      // ignore
+    }
+    return result;
+  }
+
+  /**
    * Returns the URL for the REST call
    * 
    * @return
@@ -464,7 +505,8 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
     }
     // @see https://github.com/Ensembl/ensembl-rest/wiki/Output-formats
     urlstring.append("?type=").append(getSourceEnsemblType().getType());
-    urlstring.append(("&Accept=text/x-fasta"));
+    urlstring.append(("&Accept=application/json"));
+    urlstring.append(("&Content-Type=application/json"));
 
     String objectType = getObjectType();
     if (objectType != null)
@@ -504,18 +546,6 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
     return false;
   }
 
-  @Override
-  protected String getRequestMimeType(boolean multipleIds)
-  {
-    return multipleIds ? "application/json" : "text/x-fasta";
-  }
-
-  @Override
-  protected String getResponseMimeType()
-  {
-    return "text/x-fasta";
-  }
-
   /**
    * 
    * @return the configured sequence return type for this source
@@ -551,8 +581,8 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
   protected MapList getGenomicRangesFromFeatures(SequenceI sourceSequence,
           String accId, int start)
   {
-    List<SequenceFeature> sfs = sourceSequence.getFeatures()
-            .getPositionalFeatures();
+    List<SequenceFeature> sfs = getIdentifyingFeatures(sourceSequence,
+            accId);
     if (sfs.isEmpty())
     {
       return null;
@@ -569,47 +599,31 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
 
     for (SequenceFeature sf : sfs)
     {
+      int strand = sf.getStrand();
+      strand = strand == 0 ? 1 : strand; // treat unknown as forward
+
+      if (directionSet && strand != direction)
+      {
+        // abort - mix of forward and backward
+        System.err
+                .println("Error: forward and backward strand for " + accId);
+        return null;
+      }
+      direction = strand;
+      directionSet = true;
+
       /*
-       * accept the target feature type or a specialisation of it
-       * (e.g. coding_exon for exon)
+       * add to CDS ranges, semi-sorted forwards/backwards
        */
-      if (identifiesSequence(sf, accId))
+      if (strand < 0)
       {
-        int strand = sf.getStrand();
-        strand = strand == 0 ? 1 : strand; // treat unknown as forward
-
-        if (directionSet && strand != direction)
-        {
-          // abort - mix of forward and backward
-          System.err.println(
-                  "Error: forward and backward strand for " + accId);
-          return null;
-        }
-        direction = strand;
-        directionSet = true;
-
-        /*
-         * add to CDS ranges, semi-sorted forwards/backwards
-         */
-        if (strand < 0)
-        {
-          regions.add(0, new int[] { sf.getEnd(), sf.getBegin() });
-        }
-        else
-        {
-          regions.add(new int[] { sf.getBegin(), sf.getEnd() });
-        }
-        mappedLength += Math.abs(sf.getEnd() - sf.getBegin() + 1);
-
-        if (!isSpliceable())
-        {
-          /*
-           * 'gene' sequence is contiguous so we can stop as soon as its
-           * identifying feature has been found
-           */
-          break;
-        }
+        regions.add(0, new int[] { sf.getEnd(), sf.getBegin() });
+      }
+      else
+      {
+        regions.add(new int[] { sf.getBegin(), sf.getEnd() });
       }
+      mappedLength += Math.abs(sf.getEnd() - sf.getBegin() + 1);
     }
 
     if (regions.isEmpty())
@@ -634,26 +648,18 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
   }
 
   /**
-   * Answers true if the sequence being retrieved may occupy discontiguous
-   * regions on the genomic sequence.
-   */
-  protected boolean isSpliceable()
-  {
-    return true;
-  }
-
-  /**
-   * Returns true if the sequence feature marks positions of the genomic
+   * Answers a list of sequence features that mark positions of the genomic
    * sequence feature which are within the sequence being retrieved. For
    * example, an 'exon' feature whose parent is the target transcript marks the
-   * cdna positions of the transcript.
+   * cdna positions of the transcript. For a gene sequence, this is trivially
+   * just the 'gene' feature with matching gene id.
    * 
-   * @param sf
+   * @param seq
    * @param accId
    * @return
    */
-  protected abstract boolean identifiesSequence(SequenceFeature sf,
-          String accId);
+  protected abstract List<SequenceFeature> getIdentifyingFeatures(
+          SequenceI seq, String accId);
 
   /**
    * Transfers the sequence feature to the target sequence, locating its start
index 27c448e..77768a6 100644 (file)
@@ -88,18 +88,6 @@ class EnsemblXref extends EnsemblRestClient
     return true;
   }
 
-  @Override
-  protected String getRequestMimeType(boolean multipleIds)
-  {
-    return "application/json";
-  }
-
-  @Override
-  protected String getResponseMimeType()
-  {
-    return "application/json";
-  }
-
   /**
    * Calls the Ensembl xrefs REST endpoint and retrieves any cross-references
    * ("primary_id") for the given identifier (Ensembl accession id) and database
@@ -113,8 +101,8 @@ class EnsemblXref extends EnsemblRestClient
    */
   public List<DBRefEntry> getCrossReferences(String identifier)
   {
-    List<DBRefEntry> result = new ArrayList<DBRefEntry>();
-    List<String> ids = new ArrayList<String>();
+    List<DBRefEntry> result = new ArrayList<>();
+    List<String> ids = new ArrayList<>();
     ids.add(identifier);
 
     BufferedReader br = null;
@@ -163,7 +151,7 @@ class EnsemblXref extends EnsemblRestClient
           throws IOException
   {
     JSONParser jp = new JSONParser();
-    List<DBRefEntry> result = new ArrayList<DBRefEntry>();
+    List<DBRefEntry> result = new ArrayList<>();
     try
     {
       JSONArray responses = (JSONArray) jp.parse(br);
index 82f9018..62f8891 100644 (file)
@@ -5305,6 +5305,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   {
     if (avc.createGroup())
     {
+      if (applyAutoAnnotationSettings.isSelected())
+      {
+        alignPanel.updateAnnotation(true, false);
+      }
       alignPanel.alignmentChanged();
     }
   }
index 2c5684a..60ef480 100644 (file)
@@ -37,7 +37,6 @@ import jalview.schemes.ResidueProperties;
 import jalview.structure.StructureSelectionManager;
 import jalview.util.Comparison;
 import jalview.util.MessageManager;
-import jalview.util.Platform;
 import jalview.viewmodel.ViewportListenerI;
 import jalview.viewmodel.ViewportRanges;
 
@@ -48,6 +47,7 @@ import java.awt.Dimension;
 import java.awt.Font;
 import java.awt.FontMetrics;
 import java.awt.Graphics;
+import java.awt.Graphics2D;
 import java.awt.event.AdjustmentEvent;
 import java.awt.event.AdjustmentListener;
 import java.awt.event.ComponentAdapter;
@@ -546,37 +546,10 @@ public class AlignmentPanel extends GAlignmentPanel implements
   protected void validateAnnotationDimensions(boolean adjustPanelHeight)
   {
     int annotationHeight = getAnnotationPanel().adjustPanelHeight();
+    annotationHeight = getAnnotationPanel()
+            .adjustForAlignFrame(adjustPanelHeight, annotationHeight);
 
-    if (adjustPanelHeight)
-    {
-      int rowHeight = av.getCharHeight();
-      int alignmentHeight = rowHeight * av.getAlignment().getHeight();
-
-      /*
-       * Estimate available height in the AlignFrame for alignment +
-       * annotations. Deduct an estimate for title bar, menu bar, scale panel,
-       * hscroll, status bar, insets. 
-       */
-      int stuff = Platform.isAMac() ? 120 : 140;
-      int availableHeight = alignFrame.getHeight() - stuff;
-
-      /*
-       * If not enough vertical space, maximize annotation height while keeping
-       * at least two rows of alignment visible
-       */
-      if (annotationHeight + alignmentHeight > availableHeight)
-      {
-        annotationHeight = Math.min(annotationHeight,
-                availableHeight - 2 * rowHeight);
-      }
-    }
-    else
-    {
-      // maintain same window layout whilst updating sliders
-      annotationHeight = annotationScroller.getSize().height;
-    }
     hscroll.addNotify();
-
     annotationScroller.setPreferredSize(
             new Dimension(annotationScroller.getWidth(), annotationHeight));
 
@@ -615,6 +588,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
     {
       annotationScroller.setVisible(true);
       annotationSpaceFillerHolder.setVisible(true);
+      validateAnnotationDimensions(false);
     }
 
     int canvasWidth = getSeqPanel().seqCanvas.getWidth();
@@ -942,30 +916,16 @@ public class AlignmentPanel extends GAlignmentPanel implements
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param pg
-   *          DOCUMENT ME!
-   * @param pwidth
-   *          DOCUMENT ME!
-   * @param pheight
-   *          DOCUMENT ME!
-   * @param pi
-   *          DOCUMENT ME!
-   * 
-   * @return DOCUMENT ME!
-   * 
-   * @throws PrinterException
-   *           DOCUMENT ME!
-   */
-  /**
    * Draws the alignment image, including sequence ids, sequences, and
    * annotation labels and annotations if shown, on either one or two Graphics
-   * context.
+   * contexts.
    * 
    * @param pageWidth
+   *          in pixels
    * @param pageHeight
-   * @param pi
+   *          in pixels
+   * @param pageIndex
+   *          (0, 1, ...)
    * @param idGraphics
    *          the graphics context for sequence ids and annotation labels
    * @param alignmentGraphics
@@ -974,7 +934,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
    * @return
    * @throws PrinterException
    */
-  public int printUnwrapped(int pageWidth, int pageHeight, int pi,
+  public int printUnwrapped(int pageWidth, int pageHeight, int pageIndex,
           Graphics idGraphics, Graphics alignmentGraphics)
           throws PrinterException
   {
@@ -988,8 +948,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
             : idWidth;
 
     FontMetrics fm = getFontMetrics(av.getFont());
-    int charHeight = av.getCharHeight();
-    int scaleHeight = charHeight + fm.getDescent();
+    final int charHeight = av.getCharHeight();
+    final int scaleHeight = charHeight + fm.getDescent();
 
     idGraphics.setColor(Color.white);
     idGraphics.fillRect(0, 0, pageWidth, pageHeight);
@@ -998,29 +958,20 @@ public class AlignmentPanel extends GAlignmentPanel implements
     /*
      * How many sequences and residues can we fit on a printable page?
      */
-    int totalRes = (pageWidth - idWidth) / av.getCharWidth();
+    final int totalRes = (pageWidth - idWidth) / av.getCharWidth();
 
-    int totalSeq = (pageHeight - scaleHeight) / charHeight - 1;
+    final int totalSeq = (pageHeight - scaleHeight) / charHeight - 1;
 
-    int alignmentWidth = av.getAlignment().getWidth();
-    int pagesWide = (alignmentWidth / totalRes) + 1;
+    final int alignmentWidth = av.getAlignment().getWidth();
+    final int pagesWide = (alignmentWidth / totalRes) + 1;
 
-    final int startRes = (pi % pagesWide) * totalRes;
-    int endRes = (startRes + totalRes) - 1;
+    final int startRes = (pageIndex % pagesWide) * totalRes;
+    final int endRes = Math.min(startRes + totalRes - 1,
+            alignmentWidth - 1);
 
-    if (endRes > (alignmentWidth - 1))
-    {
-      endRes = alignmentWidth - 1;
-    }
-
-    final int startSeq = (pi / pagesWide) * totalSeq;
-    int endSeq = startSeq + totalSeq;
-
-    int alignmentHeight = av.getAlignment().getHeight();
-    if (endSeq > alignmentHeight)
-    {
-      endSeq = alignmentHeight;
-    }
+    final int startSeq = (pageIndex / pagesWide) * totalSeq;
+    final int alignmentHeight = av.getAlignment().getHeight();
+    final int endSeq = Math.min(startSeq + totalSeq, alignmentHeight);
 
     int pagesHigh = ((alignmentHeight / totalSeq) + 1) * pageHeight;
 
@@ -1031,7 +982,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
 
     pagesHigh /= pageHeight;
 
-    if (pi >= (pagesWide * pagesHigh))
+    if (pageIndex >= (pagesWide * pagesHigh))
     {
       return Printable.NO_SUCH_PAGE;
     }
@@ -1050,47 +1001,12 @@ public class AlignmentPanel extends GAlignmentPanel implements
      * then reset to top left (0, 0)
      */
     idGraphics.translate(0, scaleHeight);
-    idGraphics.setFont(getIdPanel().getIdCanvas().getIdfont());
-    Color currentColor = null;
-    Color currentTextColor = null;
-
-    SequenceI seq;
-    for (int i = startSeq; i < endSeq; i++)
-    {
-      seq = av.getAlignment().getSequenceAt(i);
-      if ((av.getSelectionGroup() != null)
-              && av.getSelectionGroup().getSequences(null).contains(seq))
-      {
-        /*
-         * gray out ids of sequences in selection group (if any)
-         */
-        currentColor = Color.gray;
-        currentTextColor = Color.black;
-      }
-      else
-      {
-        currentColor = av.getSequenceColour(seq);
-        currentTextColor = Color.black;
-      }
-
-      idGraphics.setColor(currentColor);
-      idGraphics.fillRect(0, (i - startSeq) * charHeight, idWidth,
-              charHeight);
-
-      idGraphics.setColor(currentTextColor);
-
-      int xPos = 0;
-      String displayId = seq.getDisplayId(av.getShowJVSuffix());
-      if (av.isRightAlignIds())
-      {
-        fm = idGraphics.getFontMetrics();
-        xPos = idWidth - fm.stringWidth(displayId) - 4;
-      }
+    IdCanvas idCanvas = getIdPanel().getIdCanvas();
+    List<SequenceI> selection = av.getSelectionGroup() == null ? null
+            : av.getSelectionGroup().getSequences(null);
+    idCanvas.drawIds((Graphics2D) idGraphics, av, startSeq, endSeq - 1,
+            selection);
 
-      idGraphics.drawString(displayId, xPos,
-              (((i - startSeq) * charHeight) + charHeight)
-                      - (charHeight / 5));
-    }
     idGraphics.setFont(av.getFont());
     idGraphics.translate(0, -scaleHeight);
 
@@ -1100,7 +1016,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
      */
     alignmentGraphics.translate(alignmentGraphicsOffset, scaleHeight);
     getSeqPanel().seqCanvas.drawPanelForPrinting(alignmentGraphics, startRes,
-            endRes, startSeq, endSeq);
+            endRes, startSeq, endSeq - 1);
     alignmentGraphics.translate(-alignmentGraphicsOffset, 0);
 
     if (av.isShowAnnotation() && (endSeq == alignmentHeight))
@@ -1130,31 +1046,27 @@ public class AlignmentPanel extends GAlignmentPanel implements
   }
 
   /**
-   * DOCUMENT ME!
+   * Prints one page of an alignment in wrapped mode. Returns
+   * Printable.PAGE_EXISTS (0) if a page was drawn, or Printable.NO_SUCH_PAGE if
+   * no page could be drawn (page number out of range).
    * 
-   * @param pg
-   *          DOCUMENT ME!
-   * @param pwidth
-   *          DOCUMENT ME!
-   * @param pheight
-   *          DOCUMENT ME!
-   * @param pi
-   *          DOCUMENT ME!
+   * @param pageWidth
+   * @param pageHeight
+   * @param pageNumber
+   *          (0, 1, ...)
+   * @param g
    * 
-   * @return DOCUMENT ME!
+   * @return
    * 
    * @throws PrinterException
-   *           DOCUMENT ME!
    */
-  public int printWrappedAlignment(int pwidth, int pheight, int pi,
-          Graphics pg) throws PrinterException
+  public int printWrappedAlignment(int pageWidth, int pageHeight, int pageNumber,
+          Graphics g) throws PrinterException
   {
     int annotationHeight = 0;
-    AnnotationLabels labels = null;
     if (av.isShowAnnotation())
     {
       annotationHeight = getAnnotationPanel().adjustPanelHeight();
-      labels = new AnnotationLabels(av);
     }
 
     int hgap = av.getCharHeight();
@@ -1176,64 +1088,39 @@ public class AlignmentPanel extends GAlignmentPanel implements
     }
 
     int resWidth = getSeqPanel().seqCanvas
-            .getWrappedCanvasWidth(pwidth - idWidth);
+            .getWrappedCanvasWidth(pageWidth - idWidth);
 
     int totalHeight = cHeight * (maxwidth / resWidth + 1);
 
-    pg.setColor(Color.white);
-    pg.fillRect(0, 0, pwidth, pheight);
-    pg.setFont(av.getFont());
-
-    // //////////////
-    // Draw the ids
-    pg.setColor(Color.black);
+    g.setColor(Color.white);
+    g.fillRect(0, 0, pageWidth, pageHeight);
+    g.setFont(av.getFont());
+    g.setColor(Color.black);
 
-    pg.translate(0, -pi * pheight);
-
-    pg.setClip(0, pi * pheight, pwidth, pheight);
-
-    int ypos = hgap;
-
-    do
-    {
-      for (int i = 0; i < av.getAlignment().getHeight(); i++)
-      {
-        pg.setFont(getIdPanel().getIdCanvas().getIdfont());
-        SequenceI s = av.getAlignment().getSequenceAt(i);
-        String string = s.getDisplayId(av.getShowJVSuffix());
-        int xPos = 0;
-        if (av.isRightAlignIds())
-        {
-          FontMetrics fm = pg.getFontMetrics();
-          xPos = idWidth - fm.stringWidth(string) - 4;
-        }
-        pg.drawString(string, xPos,
-                ((i * av.getCharHeight()) + ypos + av.getCharHeight())
-                        - (av.getCharHeight() / 5));
-      }
-      if (labels != null)
-      {
-        pg.translate(-3, ypos
-                + (av.getAlignment().getHeight() * av.getCharHeight()));
+    /*
+     * method: print the whole wrapped alignment, but with a clip region that
+     * is restricted to the requested page; this supports selective print of 
+     * single  pages or ranges, (at the cost of some repeated processing in 
+     * the 'normal' case, when all pages are printed)
+     */
+    g.translate(0, -pageNumber * pageHeight);
 
-        pg.setFont(av.getFont());
-        labels.drawComponent(pg, idWidth);
-        pg.translate(+3, -ypos
-                - (av.getAlignment().getHeight() * av.getCharHeight()));
-      }
+    g.setClip(0, pageNumber * pageHeight, pageWidth, pageHeight);
 
-      ypos += cHeight;
-    } while (ypos < totalHeight);
+    /*
+     * draw sequence ids and annotation labels (if shown)
+     */
+    IdCanvas idCanvas = getIdPanel().getIdCanvas();
+    idCanvas.drawIdsWrapped((Graphics2D) g, av, 0, totalHeight);
 
-    pg.translate(idWidth, 0);
+    g.translate(idWidth, 0);
 
-    getSeqPanel().seqCanvas.drawWrappedPanelForPrinting(pg, pwidth - idWidth,
+    getSeqPanel().seqCanvas.drawWrappedPanelForPrinting(g, pageWidth - idWidth,
             totalHeight, 0);
 
-    if ((pi * pheight) < totalHeight)
+    if ((pageNumber * pageHeight) < totalHeight)
     {
       return Printable.PAGE_EXISTS;
-
     }
     else
     {
index dee56b0..50971c7 100755 (executable)
@@ -30,6 +30,7 @@ import jalview.renderer.AwtRenderPanelI;
 import jalview.schemes.ResidueProperties;
 import jalview.util.Comparison;
 import jalview.util.MessageManager;
+import jalview.util.Platform;
 import jalview.viewmodel.ViewportListenerI;
 import jalview.viewmodel.ViewportRanges;
 
@@ -206,7 +207,8 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
   @Override
   public Dimension getPreferredScrollableViewportSize()
   {
-    return getPreferredSize();
+    Dimension ps = getPreferredSize();
+    return new Dimension(ps.width, adjustForAlignFrame(false, ps.height));
   }
 
   @Override
@@ -1196,4 +1198,49 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
       repaint();
     }
   }
+
+  /**
+   * computes the visible height of the annotation panel
+   * 
+   * @param adjustPanelHeight
+   *          - when false, just adjust existing height according to other
+   *          windows
+   * @param annotationHeight
+   * @return height to use for the ScrollerPreferredVisibleSize
+   */
+  public int adjustForAlignFrame(boolean adjustPanelHeight,
+          int annotationHeight)
+  {
+    /*
+     * Estimate available height in the AlignFrame for alignment +
+     * annotations. Deduct an estimate for title bar, menu bar, scale panel,
+     * hscroll, status bar, insets. 
+     */
+    int stuff = (ap.getViewName() != null ? 30 : 0)
+            + (Platform.isAMac() ? 120 : 140);
+    int availableHeight = ap.alignFrame.getHeight() - stuff;
+    int rowHeight = av.getCharHeight();
+
+    if (adjustPanelHeight)
+    {
+      int alignmentHeight = rowHeight * av.getAlignment().getHeight();
+
+      /*
+       * If not enough vertical space, maximize annotation height while keeping
+       * at least two rows of alignment visible
+       */
+      if (annotationHeight + alignmentHeight > availableHeight)
+      {
+        annotationHeight = Math.min(annotationHeight,
+                availableHeight - 2 * rowHeight);
+      }
+    }
+    else
+    {
+      // maintain same window layout whilst updating sliders
+      annotationHeight = Math.min(ap.annotationScroller.getSize().height,
+              availableHeight - 2 * rowHeight);
+    }
+    return annotationHeight;
+  }
 }
index ea16f23..3a64716 100644 (file)
@@ -120,6 +120,15 @@ public class AppVarna extends JInternalFrame
       }
     }
 
+    /**
+     * highlight a region from start to end (inclusive) on rna
+     * 
+     * @param rna
+     * @param start
+     *          - first base pair index (from 0)
+     * @param end
+     *          - last base pair index (from 0)
+     */
     public void highlightRegion(RNA rna, int start, int end)
     {
       clearLastSelection();
@@ -397,7 +406,8 @@ public class AppVarna extends JInternalFrame
     RnaModel rnaModel = models.get(rna);
     if (rnaModel.seq == sequence)
     {
-      int highlightPos = rnaModel.gapped ? index : position - 1;
+      int highlightPos = rnaModel.gapped ? index
+              : position - sequence.getStart();
       mouseOverHighlighter.highlightRegion(rna, highlightPos, highlightPos);
       vab.updateSelectedRNA(rna);
     }
@@ -418,15 +428,28 @@ public class AppVarna extends JInternalFrame
     {
       return;
     }
-    if (seqsel != null && seqsel.getSize() > 0)
+
+    RnaModel rnaModel = models.get(rna);
+
+    if (seqsel != null && seqsel.getSize() > 0
+            && seqsel.contains(rnaModel.seq))
     {
       int start = seqsel.getStartRes(), end = seqsel.getEndRes();
-      ShiftList shift = offsets.get(rna);
-      if (shift != null)
+      if (rnaModel.gapped)
       {
-        start = shift.shift(start);
-        end = shift.shift(end);
+        ShiftList shift = offsets.get(rna);
+        if (shift != null)
+        {
+          start = shift.shift(start);
+          end = shift.shift(end);
+        }
       }
+      else
+      {
+        start = rnaModel.seq.findPosition(start) - rnaModel.seq.getStart();
+        end = rnaModel.seq.findPosition(end) - rnaModel.seq.getStart();
+      }
+
       selectionHighlighter.highlightRegion(rna, start, end);
       selectionHighlighter.getLastHighlight()
               .setOutlineColor(seqsel.getOutlineColour());
index 537ec17..8ef204c 100644 (file)
@@ -152,11 +152,12 @@ public class AquaInternalFrameManager extends DefaultDesktopManager
         super.activateFrame(f);
       }
 
-      // If this is the first activation, add to child list.
-      if (fChildFrames.indexOf(f) == -1)
+      // add or relocate to top of stack
+      if (fChildFrames.indexOf(f) != -1)
       {
-        fChildFrames.addElement(f);
+        fChildFrames.remove(f);
       }
+      fChildFrames.addElement(f);
 
       if (fCurrentFrame != null && f != fCurrentFrame)
       {
diff --git a/src/jalview/gui/DasSourceBrowser.java b/src/jalview/gui/DasSourceBrowser.java
deleted file mode 100644 (file)
index 8570ac3..0000000
+++ /dev/null
@@ -1,864 +0,0 @@
-/*
- * 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.jbgui.GDasSourceBrowser;
-import jalview.util.MessageManager;
-import jalview.util.TableSorter;
-import jalview.ws.dbsources.das.api.DasSourceRegistryI;
-import jalview.ws.dbsources.das.api.jalviewSourceI;
-
-import java.awt.BorderLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Properties;
-import java.util.StringTokenizer;
-import java.util.Vector;
-
-import javax.swing.JCheckBox;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
-import javax.swing.ListSelectionModel;
-import javax.swing.SwingUtilities;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.table.AbstractTableModel;
-
-import org.biodas.jdas.schema.sources.CAPABILITY;
-import org.biodas.jdas.schema.sources.COORDINATES;
-import org.biodas.jdas.schema.sources.PROP;
-import org.biodas.jdas.schema.sources.VERSION;
-
-public class DasSourceBrowser extends GDasSourceBrowser
-        implements Runnable, ListSelectionListener
-{
-  DasSourceRegistryI sourceRegistry = null;
-
-  Vector<String> selectedSources;
-
-  public DasSourceBrowser(FeatureSettings featureSettings)
-  {
-    fs = featureSettings;
-    // TODO DasSourceRegistryProvider API
-    sourceRegistry = jalview.bin.Cache.getDasSourceRegistry();
-    String registry = sourceRegistry.getDasRegistryURL();
-
-    registryURL.setText(registry);
-
-    setSelectedFromProperties();
-
-    displayFullDetails(null);
-    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-
-    filter1.addListSelectionListener(this);
-    filter2.addListSelectionListener(this);
-    filter3.addListSelectionListener(this);
-
-    // Ask to be notified of selection changes.
-    ListSelectionModel rowSM = table.getSelectionModel();
-    rowSM.addListSelectionListener(new ListSelectionListener()
-    {
-      @Override
-      public void valueChanged(ListSelectionEvent e)
-      {
-        ListSelectionModel lsm = (ListSelectionModel) e.getSource();
-        if (!lsm.isSelectionEmpty())
-        {
-          int selectedRow = lsm.getMinSelectionIndex();
-          displayFullDetails(table.getValueAt(selectedRow, 0).toString());
-        }
-      }
-    });
-
-    table.addMouseListener(new MouseAdapter()
-    {
-      @Override
-      public void mouseClicked(MouseEvent evt)
-      {
-        if (evt.getClickCount() == 2 || evt.isPopupTrigger())
-        {
-          editRemoveLocalSource(evt);
-        }
-      }
-    });
-
-    if (sourceRegistry.getSources() != null)
-    {
-      init();
-    }
-  }
-
-  FeatureSettings fs = null;
-
-  private boolean loadingDasSources;
-
-  public DasSourceBrowser()
-  {
-    this(null);
-  }
-
-  @Override
-  public void paintComponent(java.awt.Graphics g)
-  {
-    if (sourceRegistry == null)
-    {
-      Thread worker = new Thread(this);
-      worker.start();
-    }
-  }
-
-  void init()
-  {
-    List<jalviewSourceI> sources = sourceRegistry.getSources();
-    int dSize = sources.size();
-    Object[][] data = new Object[dSize][2];
-    for (int i = 0; i < dSize; i++)
-    {
-      data[i][0] = sources.get(i).getTitle(); // what's equivalent of nickname
-      data[i][1] = new Boolean(
-              selectedSources.contains(sources.get(i).getTitle()));
-    }
-
-    refreshTableData(data);
-    setCapabilities(sourceRegistry);
-
-    javax.swing.SwingUtilities.invokeLater(new Runnable()
-    {
-      @Override
-      public void run()
-      {
-        TableSorter sorter = (TableSorter) table.getModel();
-        sorter.setSortingStatus(1, TableSorter.DESCENDING);
-        sorter.setSortingStatus(1, TableSorter.NOT_SORTED);
-      }
-    });
-
-    progressBar.setIndeterminate(false);
-    progressBar.setVisible(false);
-    addLocal.setVisible(true);
-    refresh.setVisible(true);
-  }
-
-  public void refreshTableData(Object[][] data)
-  {
-    TableSorter sorter = new TableSorter(new DASTableModel(data));
-    sorter.setTableHeader(table.getTableHeader());
-    table.setModel(sorter);
-  }
-
-  void displayFullDetails(String nickName)
-  {
-
-    StringBuffer text = new StringBuffer(
-            "<HTML><font size=\"2\" face=\"Verdana, Arial, Helvetica, sans-serif\">");
-
-    if (nickName == null)
-    {
-      fullDetails.setText(text + MessageManager
-              .getString("label.select_das_service_from_table"));
-      return;
-    }
-
-    int dSize = sourceRegistry.getSources().size();
-    for (jalviewSourceI ds : sourceRegistry.getSources())
-    {
-      if (!ds.getTitle().equals(nickName))
-      {
-        continue;
-      }
-
-      VERSION latest = ds.getVersion();
-      text.append(
-              "<font color=\"#0000FF\">Id:</font> " + ds.getUri() + "<br>");
-      text.append("<font color=\"#0000FF\">Nickname:</font> "
-              + ds.getTitle() + "<br>");
-
-      text.append("<font color=\"#0000FF\">URL:</font> <a href=\""
-              + ds.getSourceURL() + "\">" + ds.getSourceURL() + "</a>"
-              + "<br>");
-      if (!ds.isLocal())
-      {
-        if (ds.getDocHref() != null && ds.getDocHref().length() > 0)
-        {
-          text.append("<font color=\"#0000FF\">Site:</font> <a href=\""
-                  + ds.getDocHref() + "\">" + ds.getDocHref() + "</a>"
-                  + "<br>");
-        }
-
-        text.append("<font color=\"#0000FF\">Description:</font> "
-                + ds.getDescription() + "<br>");
-
-        text.append(
-                "<font color=\"#0000FF\">Admin Email:</font> <a href=\"mailto:"
-                        + ds.getEmail() + "\">" + ds.getEmail() + "</a>"
-                        + "<br>");
-
-        text.append("<font color=\"#0000FF\">Registered at:</font> "
-                + latest.getCreated() + "<br>");
-
-        // TODO: Identify last successful test date
-        // text.append("<font color=\"#0000FF\">Last successful test:</font> "
-        // + latest.dasSources[i].getLeaseDate() + "<br>");
-      }
-      else
-      {
-        text.append("Source was added manually.<br/>");
-      }
-      text.append("<font color=\"#0000FF\">Labels:</font> ");
-      boolean b = false;
-      for (PROP labl : latest.getPROP())
-      {
-        if (labl.getName().equalsIgnoreCase("LABEL"))
-        {
-          if (b)
-          {
-            text.append(",");
-          }
-          text.append(" ");
-
-          text.append(labl.getValue());
-          b = true;
-        }
-        ;
-      }
-      text.append("<br>");
-
-      text.append("<font color=\"#0000FF\">Capabilities:</font> ");
-      CAPABILITY[] scap = latest.getCAPABILITY().toArray(new CAPABILITY[0]);
-      for (int j = 0; j < scap.length; j++)
-      {
-        text.append(scap[j].getType());
-        if (j < scap.length - 1)
-        {
-          text.append(", ");
-        }
-      }
-      text.append("<br>");
-
-      text.append("<font color=\"#0000FF\">Coordinates:</font>");
-      int i = 1;
-      for (COORDINATES dcs : latest.getCOORDINATES())
-      {
-        text.append("<br/>" + i++ + ". ");
-        text.append(dcs.getAuthority() + " : " + dcs.getSource());
-        if (dcs.getTaxid() != null && dcs.getTaxid().trim().length() > 0)
-        {
-          text.append(" [TaxId:" + dcs.getTaxid() + "]");
-        }
-        if (dcs.getVersion() != null
-                && dcs.getVersion().trim().length() > 0)
-        {
-          {
-            text.append(" {v. " + dcs.getVersion() + "}");
-          }
-        }
-        text.append(" (<a href=\"" + dcs.getUri() + "\">" + dcs.getUri()
-                + "</a>)");
-      }
-      text.append("</font></html>");
-
-      break;
-    }
-
-    fullDetails.setText(text.toString());
-    javax.swing.SwingUtilities.invokeLater(new Runnable()
-    {
-      @Override
-      public void run()
-      {
-        fullDetailsScrollpane.getVerticalScrollBar().setValue(0);
-      }
-    });
-  }
-
-  @Override
-  public void run()
-  {
-    loadingDasSources = true;
-
-    addLocal.setVisible(false);
-    refresh.setVisible(false);
-    progressBar.setVisible(true);
-    progressBar.setIndeterminate(true);
-    setParentGuiEnabled(false);
-    // Refresh the source list.
-    sourceRegistry.refreshSources();
-
-    init();
-
-    setParentGuiEnabled(true);
-    loadingDasSources = false;
-
-  }
-
-  private void setParentGuiEnabled(boolean b)
-  {
-    if (fs != null)
-    {
-      fs.fetchDAS.setEnabled(b);
-      fs.saveDAS.setEnabled(b);
-    }
-  }
-
-  public Vector<jalviewSourceI> getSelectedSources()
-  {
-    // wait around if we're still loading.
-    while (sourceRegistry == null)
-    {
-      if (!loadingDasSources)
-      {
-        new Thread(this).start();
-        try
-        {
-          Thread.sleep(5);
-        } catch (Exception e)
-        {
-        }
-        ;
-        while (loadingDasSources)
-        {
-          try
-          {
-            Thread.sleep(5);
-          } catch (Exception e)
-          {
-          }
-          ;
-        }
-        ;
-      }
-    }
-
-    Vector<jalviewSourceI> selected = new Vector<jalviewSourceI>();
-    for (String source : selectedSources)
-    {
-      jalviewSourceI srce = sourceRegistry.getSource(source);
-      if (srce != null)
-      {
-        selected.addElement(srce);
-      }
-    }
-    return selected;
-  }
-
-  @Override
-  public void refresh_actionPerformed(ActionEvent e)
-  {
-    saveProperties(jalview.bin.Cache.applicationProperties);
-
-    Thread worker = new Thread(this);
-    worker.start();
-  }
-
-  private void setCapabilities(DasSourceRegistryI sourceRegistry2)
-  {
-    Vector<String> authority = new Vector<String>();
-    Vector<String> type = new Vector<String>();
-    Vector<String> label = new Vector<String>();
-    Vector<String> taxIds = new Vector<String>();
-    authority.add("Any");
-    type.add("Any");
-    label.add("Any");
-
-    for (jalviewSourceI ds : sourceRegistry2.getSources())
-    {
-      VERSION latest = ds.getVersion();
-
-      for (COORDINATES cs : latest.getCOORDINATES())
-      {
-        if (!type.contains(cs.getSource()))
-        {
-          type.add(cs.getSource()); // source==category
-        }
-
-        if (!authority.contains(cs.getAuthority()))
-        {
-          authority.add(cs.getAuthority());
-        }
-      }
-
-      for (PROP slabel : latest.getPROP())
-      {
-        if (slabel.getName().equalsIgnoreCase("LABEL")
-                && !label.contains(slabel.getValue()))
-        {
-          label.add(slabel.getValue());
-        }
-      }
-
-    }
-
-    filter1.setListData(authority);
-    filter2.setListData(type);
-    filter3.setListData(label);
-    // filter4 taxIds
-
-    javax.swing.SwingUtilities.invokeLater(new Runnable()
-    {
-      @Override
-      public void run()
-      {
-        filter1.setSelectedIndex(0);
-        filter2.setSelectedIndex(0);
-        filter3.setSelectedIndex(0);
-      }
-    });
-  }
-
-  @Override
-  public void amendLocal(boolean newSource)
-  {
-    String url = "http://localhost:8080/", nickname = "";
-    boolean seqsrc = false;
-    if (!newSource)
-    {
-      int selectedRow = table.getSelectionModel().getMinSelectionIndex();
-      nickname = table.getValueAt(selectedRow, 0).toString();
-      jalviewSourceI source = sourceRegistry.getSource(nickname);
-      url = source.getUri();
-      seqsrc = source.isSequenceSource();
-    }
-
-    JTextField nametf = new JTextField(nickname, 40);
-    JTextField urltf = new JTextField(url, 40);
-    JCheckBox seqs = new JCheckBox(
-            MessageManager.getString("label.sequence_source"));
-    seqs.setSelected(seqsrc);
-    JPanel panel = new JPanel(new BorderLayout());
-    JPanel pane12 = new JPanel(new BorderLayout());
-    pane12.add(new JLabel(MessageManager.getString("label.name:")),
-            BorderLayout.CENTER);
-    pane12.add(nametf, BorderLayout.EAST);
-    panel.add(pane12, BorderLayout.NORTH);
-    pane12 = new JPanel(new BorderLayout());
-    pane12.add(new JLabel(MessageManager.getString("label.url:")),
-            BorderLayout.NORTH);
-    pane12.add(seqs, BorderLayout.SOUTH);
-    pane12.add(urltf, BorderLayout.EAST);
-    panel.add(pane12, BorderLayout.SOUTH);
-
-    int reply = JvOptionPane.showInternalConfirmDialog(Desktop.desktop,
-            panel, MessageManager.getString("label.enter_local_das_source"),
-            JvOptionPane.OK_CANCEL_OPTION);
-
-    if (reply != JvOptionPane.OK_OPTION)
-    {
-      return;
-    }
-
-    if (!urltf.getText().endsWith("/"))
-    {
-      urltf.setText(urltf.getText() + "/");
-    }
-
-    jalviewSourceI local = sourceRegistry.createLocalSource(urltf.getText(),
-            nametf.getText(), seqs.isSelected(), true);
-    List sources = sourceRegistry.getSources();
-    int osize = sources.size();
-    int size = osize + (newSource ? 1 : 0);
-
-    Object[][] data = new Object[size][2];
-    DASTableModel dtm = (table != null)
-            ? (DASTableModel) ((TableSorter) table.getModel())
-                    .getTableModel()
-            : null;
-    for (int i = 0; i < osize; i++)
-    {
-      String osrc = (dtm == null || i >= osize) ? null
-              : (String) dtm.getValueAt(i, 0);
-      if (!newSource && osrc != null
-              && dtm.getValueAt(i, 0).equals(nickname))
-      {
-        data[i][0] = local.getTitle();
-        data[i][1] = new Boolean(true);
-      }
-      else
-      {
-        data[i][0] = osrc;
-        data[i][1] = new Boolean(selectedSources.contains(osrc));
-      }
-    }
-    // Always add a new source at the end
-    if (newSource)
-    {
-      data[osize][0] = local.getTitle();
-      data[osize][1] = new Boolean(true);
-      selectedSources.add(local.getTitle());
-    }
-
-    refreshTableData(data);
-
-    SwingUtilities.invokeLater(new Runnable()
-    {
-      @Override
-      public void run()
-      {
-        scrollPane.getVerticalScrollBar()
-                .setValue(scrollPane.getVerticalScrollBar().getMaximum());
-      }
-    });
-
-    displayFullDetails(local.getTitle());
-  }
-
-  public void editRemoveLocalSource(MouseEvent evt)
-  {
-    int selectedRow = table.getSelectionModel().getMinSelectionIndex();
-    if (selectedRow == -1)
-    {
-      return;
-    }
-
-    String nickname = table.getValueAt(selectedRow, 0).toString();
-
-    if (!sourceRegistry.getSource(nickname).isLocal())
-    {
-      JvOptionPane.showInternalMessageDialog(Desktop.desktop,
-              MessageManager.getString(
-                      "label.you_can_only_edit_or_remove_local_das_sources"),
-              MessageManager.getString("label.public_das_source"),
-              JvOptionPane.WARNING_MESSAGE);
-      return;
-    }
-
-    Object[] options = { "Edit", "Remove", "Cancel" };
-    int choice = JvOptionPane.showInternalOptionDialog(Desktop.desktop,
-            "Do you want to edit or remove " + nickname + "?",
-            "Edit / Remove Local DAS Source",
-            JvOptionPane.YES_NO_CANCEL_OPTION,
-            JvOptionPane.QUESTION_MESSAGE, null, options, options[2]);
-
-    switch (choice)
-    {
-    case 0:
-      amendLocal(false);
-      break;
-    case 1:
-      sourceRegistry.removeLocalSource(sourceRegistry.getSource(nickname));
-      selectedSources.remove(nickname);
-      Object[][] data = new Object[sourceRegistry.getSources().size()][2];
-      int index = 0, l = table.getRowCount();
-
-      for (int i = 0; i < l; i++)
-      {
-        String nm;
-        if ((nm = (String) table.getValueAt(i, 0)).equals(nickname))
-        {
-          continue;
-        }
-        else
-        {
-          data[index][0] = nm;
-          data[index][1] = new Boolean(selectedSources.contains(nm));
-          index++;
-        }
-      }
-      refreshTableData(data);
-      SwingUtilities.invokeLater(new Runnable()
-      {
-        @Override
-        public void run()
-        {
-          scrollPane.getVerticalScrollBar()
-                  .setValue(scrollPane.getVerticalScrollBar().getMaximum());
-        }
-      });
-
-      break;
-    }
-  }
-
-  @Override
-  public void valueChanged(ListSelectionEvent evt)
-  {
-    // Called when the MainTable selection changes
-    if (evt.getValueIsAdjusting())
-    {
-      return;
-    }
-
-    displayFullDetails(null);
-
-    // Filter the displayed data sources
-
-    ArrayList names = new ArrayList();
-    ArrayList selected = new ArrayList();
-
-    // The features filter is not visible, but we must still
-    // filter the das source list here.
-    // July 2006 - only 6 sources fo not serve features
-    Object[] dummyFeatureList = new Object[] { "features" };
-    List<jalviewSourceI> srcs = sourceRegistry.getSources();
-    for (jalviewSourceI ds : srcs)
-    {
-
-      VERSION v = ds.getVersion();
-      List<COORDINATES> coords = v.getCOORDINATES();
-      if (ds.isLocal() || ((coords == null || coords.size() == 0)
-              && filter1.getSelectedIndex() == 0
-              && filter2.getSelectedIndex() == 0
-              && filter3.getSelectedIndex() == 0))
-      {
-        // THIS IS A FIX FOR LOCAL SOURCES WHICH DO NOT
-        // HAVE COORDINATE SYSTEMS, INFO WHICH AT PRESENT
-        // IS ADDED FROM THE REGISTRY
-        names.add(ds.getTitle());
-        selected.add(new Boolean(selectedSources.contains(ds.getTitle())));
-        continue;
-      }
-
-      if (!selectedInList(dummyFeatureList, ds.getCapabilityList(v))
-              || !selectedInList(filter3.getSelectedValues(),
-                      ds.getLabelsFor(v)))
-      {
-        continue;
-      }
-
-      for (int j = 0; j < coords.size(); j++)
-      {
-        if (selectedInList(filter1.getSelectedValues(),
-                new String[]
-                { coords.get(j).getAuthority() })
-                && selectedInList(filter2.getSelectedValues(), new String[]
-                { coords.get(j).getSource() }))
-        {
-          names.add(ds.getTitle());
-          selected.add(
-                  new Boolean(selectedSources.contains(ds.getTitle())));
-          break;
-        }
-      }
-    }
-
-    int dSize = names.size();
-    Object[][] data = new Object[dSize][2];
-    for (int d = 0; d < dSize; d++)
-    {
-      data[d][0] = names.get(d);
-      data[d][1] = selected.get(d);
-    }
-
-    refreshTableData(data);
-  }
-
-  private boolean selectedInList(Object[] selection, String[] items)
-  {
-    for (int i = 0; i < selection.length; i++)
-    {
-      if (selection[i].equals("Any"))
-      {
-        return true;
-      }
-      if (items == null || items.length == 0)
-      {
-        return false;
-      }
-      String sel = (items[0].startsWith("das1:") ? "das1:" : "")
-              + selection[i];
-      for (int j = 0; j < items.length; j++)
-      {
-        if (sel.equals(items[j]))
-        {
-          return true;
-        }
-      }
-    }
-
-    return false;
-  }
-
-  void setSelectedFromProperties()
-  {
-    String active = jalview.bin.Cache.getDefault("DAS_ACTIVE_SOURCE",
-            "uniprot");
-    StringTokenizer st = new StringTokenizer(active, "\t");
-    selectedSources = new Vector();
-    while (st.hasMoreTokens())
-    {
-      selectedSources.addElement(st.nextToken());
-    }
-  }
-
-  @Override
-  public void reset_actionPerformed(ActionEvent e)
-  {
-    registryURL.setText(sourceRegistry.getDasRegistryURL());
-  }
-
-  /**
-   * set the DAS source settings in the given jalview properties.
-   * 
-   * @param properties
-   */
-  public void saveProperties(Properties properties)
-  {
-    if (registryURL.getText() == null || registryURL.getText().length() < 1)
-    {
-      properties.remove(jalview.bin.Cache.DAS_REGISTRY_URL);
-    }
-    else
-    {
-      properties.setProperty(jalview.bin.Cache.DAS_REGISTRY_URL,
-              registryURL.getText());
-    }
-
-    StringBuffer sb = new StringBuffer();
-    for (int r = 0; r < table.getModel().getRowCount(); r++)
-    {
-      if (((Boolean) table.getValueAt(r, 1)).booleanValue())
-      {
-        sb.append(table.getValueAt(r, 0) + "\t");
-      }
-    }
-
-    properties.setProperty(jalview.bin.Cache.DAS_ACTIVE_SOURCE,
-            sb.toString());
-
-    String sourceprop = sourceRegistry.getLocalSourceString();
-    properties.setProperty(jalview.bin.Cache.DAS_LOCAL_SOURCE, sourceprop);
-  }
-
-  class DASTableModel extends AbstractTableModel
-  {
-
-    public DASTableModel(Object[][] data)
-    {
-      this.data = data;
-    }
-
-    private String[] columnNames = new String[] {
-        MessageManager.getString("label.nickname"),
-        MessageManager.getString("label.use_source") };
-
-    private Object[][] data;
-
-    @Override
-    public int getColumnCount()
-    {
-      return columnNames.length;
-    }
-
-    @Override
-    public int getRowCount()
-    {
-      return data.length;
-    }
-
-    @Override
-    public String getColumnName(int col)
-    {
-      return columnNames[col];
-    }
-
-    @Override
-    public Object getValueAt(int row, int col)
-    {
-      return data[row][col];
-    }
-
-    /*
-     * JTable uses this method to determine the default renderer/ editor for
-     * each cell. If we didn't implement this method, then the last column would
-     * contain text ("true"/"false"), rather than a check box.
-     */
-    @Override
-    public Class getColumnClass(int c)
-    {
-      return getValueAt(0, c).getClass();
-    }
-
-    /*
-     * Don't need to implement this method unless your table's editable.
-     */
-    @Override
-    public boolean isCellEditable(int row, int col)
-    {
-      // Note that the data/cell address is constant,
-      // no matter where the cell appears onscreen.
-      return col == 1;
-
-    }
-
-    /*
-     * Don't need to implement this method unless your table's data can change.
-     */
-    @Override
-    public void setValueAt(Object value, int row, int col)
-    {
-      data[row][col] = value;
-      fireTableCellUpdated(row, col);
-
-      String name = getValueAt(row, 0).toString();
-      boolean selected = ((Boolean) value).booleanValue();
-
-      if (selectedSources.contains(name) && !selected)
-      {
-        selectedSources.remove(name);
-      }
-
-      if (!selectedSources.contains(name) && selected)
-      {
-        selectedSources.add(name);
-      }
-    }
-  }
-
-  public void initDasSources()
-  {
-
-    Thread thr = new Thread(new Runnable()
-    {
-      @Override
-      public void run()
-      {
-        // this actually initialises the das source list
-        paintComponent(null); // yuk
-      }
-    });
-    thr.start();
-    while (loadingDasSources || sourceRegistry == null)
-    {
-      try
-      {
-        Thread.sleep(10);
-      } catch (Exception e)
-      {
-      }
-      ;
-    }
-  }
-
-  /**
-   * disable or enable the buttons on the source browser
-   * 
-   * @param b
-   */
-  public void setGuiEnabled(boolean b)
-  {
-    refresh.setEnabled(b);
-    addLocal.setEnabled(b);
-  }
-}
index 569257f..8d9e366 100644 (file)
@@ -519,7 +519,7 @@ public class Desktop extends jalview.jbgui.GDesktop
   {
     final Desktop me = this;
     // Thread off the news reader, in case there are connection problems.
-    addDialogThread(new Runnable()
+    new Thread(new Runnable()
     {
       @Override
       public void run()
@@ -530,13 +530,13 @@ public class Desktop extends jalview.jbgui.GDesktop
         showNews.setVisible(true);
         Cache.log.debug("Completed news thread.");
       }
-    });
+    }).start();
   }
 
   public void getIdentifiersOrgData()
   {
     // Thread off the identifiers fetcher
-    addDialogThread(new Runnable()
+    new Thread(new Runnable()
     {
       @Override
       public void run()
@@ -553,7 +553,8 @@ public class Desktop extends jalview.jbgui.GDesktop
                   + e.getMessage());
         }
       }
-    });
+    }).start();
+    ;
   }
 
   @Override
index 5f06439..a53d730 100644 (file)
@@ -38,10 +38,7 @@ import jalview.schemabinding.version2.MatcherSet;
 import jalview.schemes.FeatureColour;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
-import jalview.viewmodel.AlignmentViewport;
 import jalview.viewmodel.seqfeatures.FeatureRendererModel.FeatureSettingsBean;
-import jalview.ws.DasSequenceFeatureFetcher;
-import jalview.ws.dbsources.das.api.jalviewSourceI;
 
 import java.awt.BorderLayout;
 import java.awt.Color;
@@ -77,7 +74,6 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.Vector;
 
 import javax.help.HelpSetException;
 import javax.swing.AbstractCellEditor;
@@ -100,7 +96,6 @@ import javax.swing.JTable;
 import javax.swing.ListSelectionModel;
 import javax.swing.RowFilter;
 import javax.swing.SwingConstants;
-import javax.swing.SwingUtilities;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
 import javax.swing.table.AbstractTableModel;
@@ -134,12 +129,6 @@ public class FeatureSettings extends JPanel
 
   private static final int MIN_HEIGHT = 400;
 
-  DasSourceBrowser dassourceBrowser;
-
-  DasSequenceFeatureFetcher dasFeatureFetcher;
-
-  JPanel dasSettingsPane = new JPanel();
-
   final FeatureRenderer fr;
 
   public final AlignFrame af;
@@ -170,12 +159,6 @@ public class FeatureSettings extends JPanel
 
   int selectedRow = -1;
 
-  JButton fetchDAS = new JButton();
-
-  JButton saveDAS = new JButton();
-
-  JButton cancelDAS = new JButton();
-
   boolean resettingTable = false;
 
   /*
@@ -230,9 +213,6 @@ public class FeatureSettings extends JPanel
 
     scrollPane.setViewportView(table);
 
-    dassourceBrowser = new DasSourceBrowser(this);
-    dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
-
     if (af.getViewport().isShowSequenceFeatures() || !fr.hasRenderOrder())
     {
       fr.findAllFeatures(true); // display everything!
@@ -280,7 +260,6 @@ public class FeatureSettings extends JPanel
                       javax.swing.event.InternalFrameEvent evt)
               {
                 fr.removePropertyChangeListener(change);
-                dassourceBrowser.fs = null;
               };
             });
     frame.setLayer(JLayeredPane.PALETTE_LAYER);
@@ -1238,8 +1217,6 @@ public class FeatureSettings extends JPanel
     JPanel settingsPane = new JPanel();
     settingsPane.setLayout(new BorderLayout());
 
-    dasSettingsPane.setLayout(new BorderLayout());
-
     JPanel bigPanel = new JPanel();
     bigPanel.setLayout(new BorderLayout());
 
@@ -1408,38 +1385,6 @@ public class FeatureSettings extends JPanel
     transparency.setMaximum(70);
     transparency.setToolTipText(
             MessageManager.getString("label.transparency_tip"));
-    fetchDAS.setText(MessageManager.getString("label.fetch_das_features"));
-    fetchDAS.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        fetchDAS_actionPerformed(e);
-      }
-    });
-    saveDAS.setText(MessageManager.getString("action.save_as_default"));
-    saveDAS.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        saveDAS_actionPerformed(e);
-      }
-    });
-
-    JPanel dasButtonPanel = new JPanel();
-    dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
-    dasSettingsPane.setBorder(null);
-    cancelDAS.setEnabled(false);
-    cancelDAS.setText(MessageManager.getString("action.cancel_fetch"));
-    cancelDAS.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        cancelDAS_actionPerformed(e);
-      }
-    });
 
     JPanel lowerPanel = new JPanel(new GridLayout(1, 2));
     bigPanel.add(lowerPanel, BorderLayout.SOUTH);
@@ -1463,172 +1408,11 @@ public class FeatureSettings extends JPanel
     buttonPanel.add(loadColours);
     buttonPanel.add(saveColours);
     bigPanel.add(scrollPane, BorderLayout.CENTER);
-    dasSettingsPane.add(dasButtonPanel, BorderLayout.SOUTH);
-    dasButtonPanel.add(fetchDAS);
-    dasButtonPanel.add(cancelDAS);
-    dasButtonPanel.add(saveDAS);
     settingsPane.add(bigPanel, BorderLayout.CENTER);
     settingsPane.add(buttonPanel, BorderLayout.SOUTH);
     this.add(settingsPane);
   }
 
-  public void fetchDAS_actionPerformed(ActionEvent e)
-  {
-    fetchDAS.setEnabled(false);
-    cancelDAS.setEnabled(true);
-    dassourceBrowser.setGuiEnabled(false);
-    Vector<jalviewSourceI> selectedSources = dassourceBrowser
-            .getSelectedSources();
-    doDasFeatureFetch(selectedSources, true, true);
-  }
-
-  /**
-   * get the features from selectedSources for all or the current selection
-   * 
-   * @param selectedSources
-   * @param checkDbRefs
-   * @param promptFetchDbRefs
-   */
-  private void doDasFeatureFetch(List<jalviewSourceI> selectedSources,
-          boolean checkDbRefs, boolean promptFetchDbRefs)
-  {
-    SequenceI[] dataset, seqs;
-    int iSize;
-    AlignmentViewport vp = af.getViewport();
-    if (vp.getSelectionGroup() != null
-            && vp.getSelectionGroup().getSize() > 0)
-    {
-      iSize = vp.getSelectionGroup().getSize();
-      dataset = new SequenceI[iSize];
-      seqs = vp.getSelectionGroup().getSequencesInOrder(vp.getAlignment());
-    }
-    else
-    {
-      iSize = vp.getAlignment().getHeight();
-      seqs = vp.getAlignment().getSequencesArray();
-    }
-
-    dataset = new SequenceI[iSize];
-    for (int i = 0; i < iSize; i++)
-    {
-      dataset[i] = seqs[i].getDatasetSequence();
-    }
-
-    cancelDAS.setEnabled(true);
-    dasFeatureFetcher = new jalview.ws.DasSequenceFeatureFetcher(dataset,
-            this, selectedSources, checkDbRefs, promptFetchDbRefs);
-    af.getViewport().setShowSequenceFeatures(true);
-    af.showSeqFeatures.setSelected(true);
-  }
-
-  /**
-   * blocking call to initialise the das source browser
-   */
-  public void initDasSources()
-  {
-    dassourceBrowser.initDasSources();
-  }
-
-  /**
-   * examine the current list of das sources and return any matching the given
-   * nicknames in sources
-   * 
-   * @param sources
-   *          Vector of Strings to resolve to DAS source nicknames.
-   * @return sources that are present in source list.
-   */
-  public List<jalviewSourceI> resolveSourceNicknames(Vector<String> sources)
-  {
-    return dassourceBrowser.sourceRegistry.resolveSourceNicknames(sources);
-  }
-
-  /**
-   * get currently selected das sources. ensure you have called initDasSources
-   * before calling this.
-   * 
-   * @return vector of selected das source nicknames
-   */
-  public Vector<jalviewSourceI> getSelectedSources()
-  {
-    return dassourceBrowser.getSelectedSources();
-  }
-
-  /**
-   * properly initialise DAS fetcher and then initiate a new thread to fetch
-   * features from the named sources (rather than any turned on by default)
-   * 
-   * @param sources
-   * @param block
-   *          if true then runs in same thread, otherwise passes to the Swing
-   *          executor
-   */
-  public void fetchDasFeatures(Vector<String> sources, boolean block)
-  {
-    initDasSources();
-    List<jalviewSourceI> resolved = dassourceBrowser.sourceRegistry
-            .resolveSourceNicknames(sources);
-    if (resolved.size() == 0)
-    {
-      resolved = dassourceBrowser.getSelectedSources();
-    }
-    if (resolved.size() > 0)
-    {
-      final List<jalviewSourceI> dassources = resolved;
-      fetchDAS.setEnabled(false);
-      // cancelDAS.setEnabled(true); doDasFetch does this.
-      Runnable fetcher = new Runnable()
-      {
-
-        @Override
-        public void run()
-        {
-          doDasFeatureFetch(dassources, true, false);
-
-        }
-      };
-      if (block)
-      {
-        fetcher.run();
-      }
-      else
-      {
-        SwingUtilities.invokeLater(fetcher);
-      }
-    }
-  }
-
-  public void saveDAS_actionPerformed(ActionEvent e)
-  {
-    dassourceBrowser
-            .saveProperties(jalview.bin.Cache.applicationProperties);
-  }
-
-  public void complete()
-  {
-    fetchDAS.setEnabled(true);
-    cancelDAS.setEnabled(false);
-    dassourceBrowser.setGuiEnabled(true);
-
-  }
-
-  public void cancelDAS_actionPerformed(ActionEvent e)
-  {
-    if (dasFeatureFetcher != null)
-    {
-      dasFeatureFetcher.cancel();
-    }
-    complete();
-  }
-
-  public void noDasSourceActive()
-  {
-    complete();
-    JvOptionPane.showInternalConfirmDialog(Desktop.desktop,
-            MessageManager.getString("label.no_das_sources_selected_warn"),
-            MessageManager.getString("label.no_das_sources_selected_title"),
-            JvOptionPane.DEFAULT_OPTION, JvOptionPane.INFORMATION_MESSAGE);
-  }
-
   /**
    * Reorders features by 'dragging' selectedRow to 'newRow'
    * 
@@ -1800,7 +1584,6 @@ public class FeatureSettings extends JPanel
         }
       }
     }
-
   }
 
   class ColorRenderer extends JLabel implements TableCellRenderer
@@ -2067,10 +1850,9 @@ public class FeatureSettings extends JPanel
           chooser.setRequestFocusEnabled(true);
           chooser.requestFocus();
           chooser.addActionListener(this);
-          chooser.showTab(true);
+          // Make the renderer reappear.
+          fireEditingStopped();
         }
-        // Make the renderer reappear.
-        fireEditingStopped();
       }
       else
       {
@@ -2183,7 +1965,6 @@ public class FeatureSettings extends JPanel
                   chooser.getWidth(), chooser.getHeight());
           chooser.validate();
         }
-        chooser.showTab(false);
         fireEditingStopped();
       }
       else if (e.getSource() instanceof Component)
index c71d878..7aef644 100644 (file)
@@ -67,7 +67,6 @@ import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JRadioButton;
 import javax.swing.JSlider;
-import javax.swing.JTabbedPane;
 import javax.swing.JTextField;
 import javax.swing.SwingConstants;
 import javax.swing.border.LineBorder;
@@ -112,7 +111,8 @@ public class FeatureTypeSettings extends JalviewDialog
   /*
    * FeatureRenderer holds colour scheme and filters for feature types
    */
-  private final FeatureRenderer fr; // todo refactor to allow interface type here
+  private final FeatureRenderer fr; // todo refactor to allow interface type
+                                    // here
 
   /*
    * the view panel to update when settings change
@@ -161,7 +161,12 @@ public class FeatureTypeSettings extends JalviewDialog
 
   private JRadioButton graduatedColour = new JRadioButton();
 
-  private JPanel singleColour = new JPanel();
+  /**
+   * colours and filters are shown in tabbed view or single content pane
+   */
+  JPanel coloursPanel, filtersPanel;
+
+  JPanel singleColour = new JPanel();
 
   private JPanel minColour = new JPanel();
 
@@ -205,13 +210,8 @@ public class FeatureTypeSettings extends JalviewDialog
    */
   private List<FeatureMatcherI> filters;
 
-  // set white normally, black to debug layout
-  private Color debugBorderColour = Color.white;
-
   private JPanel chooseFiltersPanel;
 
-  private JTabbedPane tabbedPane;
-
   /*
    * feature types present in Feature Renderer which are
    * sub-types of the one this editor is acting on
@@ -296,7 +296,7 @@ public class FeatureTypeSettings extends JalviewDialog
     String title = MessageManager
             .formatMessage("label.display_settings_for", new String[]
             { theType });
-    initDialogFrame(this, true, blocking, title, 600, 360);
+    initDialogFrame(this, true, blocking, title, 500, 500);
 
     waitForInput();
   }
@@ -443,8 +443,6 @@ public class FeatureTypeSettings extends JalviewDialog
   private void initialise()
   {
     this.setLayout(new BorderLayout());
-    tabbedPane = new JTabbedPane();
-    this.add(tabbedPane, BorderLayout.CENTER);
 
     /*
      * an ActionListener that applies colour changes
@@ -459,18 +457,16 @@ public class FeatureTypeSettings extends JalviewDialog
     };
 
     /*
-     * first tab: colour options
+     * first panel/tab: colour options
      */
     JPanel coloursPanel = initialiseColoursPanel();
-    tabbedPane.addTab(MessageManager.getString("action.colour"),
-            coloursPanel);
+    this.add(coloursPanel, BorderLayout.NORTH);
 
     /*
-     * second tab: filter options
+     * second panel/tab: filter options
      */
     JPanel filtersPanel = initialiseFiltersPanel();
-    tabbedPane.addTab(MessageManager.getString("label.filters"),
-            filtersPanel);
+    this.add(filtersPanel, BorderLayout.CENTER);
 
     JPanel okCancelPanel = initialiseOkCancelPanel();
 
@@ -776,7 +772,10 @@ public class FeatureTypeSettings extends JalviewDialog
   private JPanel initialiseColoursPanel()
   {
     JPanel colourByPanel = new JPanel();
+    colourByPanel.setBackground(Color.white);
     colourByPanel.setLayout(new BoxLayout(colourByPanel, BoxLayout.Y_AXIS));
+    JvSwingUtils.createTitledBorder(colourByPanel,
+            MessageManager.getString("action.colour"), true);
 
     /*
      * option to apply colour to sub-types as well (if there are any)
@@ -792,8 +791,8 @@ public class FeatureTypeSettings extends JalviewDialog
      */
     JPanel simpleColourPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
     simpleColourPanel.setBackground(Color.white);
-    JvSwingUtils.createTitledBorder(simpleColourPanel,
-            MessageManager.getString("label.simple"), true);
+//    JvSwingUtils.createTitledBorder(simpleColourPanel,
+//            MessageManager.getString("label.simple"), true);
     colourByPanel.add(simpleColourPanel);
 
     simpleColour = new JRadioButton(
@@ -811,7 +810,7 @@ public class FeatureTypeSettings extends JalviewDialog
       }
 
     });
-    
+
     singleColour.setFont(JvSwingUtils.getLabelFont());
     singleColour.setBorder(BorderFactory.createLineBorder(Color.black));
     singleColour.setPreferredSize(new Dimension(40, 20));
@@ -938,9 +937,9 @@ public class FeatureTypeSettings extends JalviewDialog
   }
 
   /**
-   * Constructs and sets the selected colour options as the colour for the feature
-   * type, and repaints the alignment, and optionally the Overview and/or
-   * structure viewer if open
+   * Constructs and sets the selected colour options as the colour for the
+   * feature type, and repaints the alignment, and optionally the Overview
+   * and/or structure viewer if open
    * 
    * @param updateStructsAndOverview
    */
@@ -1185,8 +1184,8 @@ public class FeatureTypeSettings extends JalviewDialog
 
   /**
    * Converts the slider value to its absolute value by dividing by the
-   * scaleFactor. Rounding errors are squashed by forcing min/max of slider range
-   * to the actual min/max of feature score range
+   * scaleFactor. Rounding errors are squashed by forcing min/max of slider
+   * range to the actual min/max of feature score range
    * 
    * @return
    */
@@ -1209,11 +1208,11 @@ public class FeatureTypeSettings extends JalviewDialog
   }
 
   /**
-   * A helper method to build the drop-down choice of attributes for a feature. If
-   * 'withRange' is true, then Score, and any attributes with a min-max range, are
-   * added. If 'withText' is true, Label and any known attributes are added. This
-   * allows 'categorical numerical' attributes e.g. codon position to be coloured
-   * by text.
+   * A helper method to build the drop-down choice of attributes for a feature.
+   * If 'withRange' is true, then Score, and any attributes with a min-max
+   * range, are added. If 'withText' is true, Label and any known attributes are
+   * added. This allows 'categorical numerical' attributes e.g. codon position
+   * to be coloured by text.
    * <p>
    * Where metadata is available with a description for an attribute, that is
    * added as a tooltip.
@@ -1322,10 +1321,13 @@ public class FeatureTypeSettings extends JalviewDialog
   {
     JPanel andOrPanel = new JPanel(new BorderLayout());
     andOrPanel.setBackground(Color.white);
-    JPanel panel1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
-    andOrPanel.add(panel1, BorderLayout.WEST);
-    panel1.setBackground(Color.white);
-    panel1.setBorder(BorderFactory.createLineBorder(debugBorderColour));
+//<<<<<<< HEAD
+//    JPanel panel1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
+//    andOrPanel.add(panel1, BorderLayout.WEST);
+//    panel1.setBackground(Color.white);
+//    panel1.setBorder(BorderFactory.createLineBorder(debugBorderColour));
+//=======
+//>>>>>>> refs/heads/develop
     andFilters = new JRadioButton(MessageManager.getString("label.and"));
     orFilters = new JRadioButton(MessageManager.getString("label.or"));
     ActionListener actionListener = new ActionListener()
@@ -1342,10 +1344,10 @@ public class FeatureTypeSettings extends JalviewDialog
     andOr.add(andFilters);
     andOr.add(orFilters);
     andFilters.setSelected(true);
-    panel1.add(
+    andOrPanel.add(
             new JLabel(MessageManager.getString("label.join_conditions")));
-    panel1.add(andFilters);
-    panel1.add(orFilters);
+    andOrPanel.add(andFilters);
+    andOrPanel.add(orFilters);
 
     return andOrPanel;
   }
@@ -1427,7 +1429,6 @@ public class FeatureTypeSettings extends JalviewDialog
     for (FeatureMatcherI filter : filters)
     {
       JPanel row = addFilter(filter, attNames, filterIndex);
-      row.setBorder(BorderFactory.createLineBorder(debugBorderColour));
       chooseFiltersPanel.add(row);
       filterIndex++;
     }
@@ -1439,7 +1440,8 @@ public class FeatureTypeSettings extends JalviewDialog
   /**
    * A helper method that constructs a row (panel) with one filter condition:
    * <ul>
-   * <li>a drop-down list of Label, Score and attribute names to choose from</li>
+   * <li>a drop-down list of Label, Score and attribute names to choose
+   * from</li>
    * <li>a drop-down list of conditions to choose from</li>
    * <li>a text field for input of a match pattern</li>
    * <li>optionally, a 'remove' button</li>
@@ -1637,8 +1639,8 @@ public class FeatureTypeSettings extends JalviewDialog
    * @param selectedCondition
    * @param patternField
    */
-  private void setNumericHints(String attName,
-          Condition selectedCondition, JTextField patternField)
+  private void setNumericHints(String attName, Condition selectedCondition,
+          JTextField patternField)
   {
     patternField.setToolTipText("");
 
@@ -1672,11 +1674,11 @@ public class FeatureTypeSettings extends JalviewDialog
   }
 
   /**
-   * Populates the drop-down list of comparison conditions for the given attribute
-   * name. The conditions added depend on the datatype of the attribute values.
-   * The supplied condition is set as the selected item in the list, provided it
-   * is in the list. If the pattern is now invalid (non-numeric pattern for a
-   * numeric condition), it is cleared.
+   * Populates the drop-down list of comparison conditions for the given
+   * attribute name. The conditions added depend on the datatype of the
+   * attribute values. The supplied condition is set as the selected item in the
+   * list, provided it is in the list. If the pattern is now invalid
+   * (non-numeric pattern for a numeric condition), it is cleared.
    * 
    * @param attName
    * @param cond
@@ -1755,12 +1757,12 @@ public class FeatureTypeSettings extends JalviewDialog
   }
 
   /**
-   * Answers true unless a numeric condition has been selected with a non-numeric
-   * value. Sets the value field to RED with a tooltip if in error.
+   * Answers true unless a numeric condition has been selected with a
+   * non-numeric value. Sets the value field to RED with a tooltip if in error.
    * <p>
-   * If the pattern is expected but is empty, this method returns false, but does
-   * not mark the field as invalid. This supports selecting an attribute for a new
-   * condition before a match pattern has been entered.
+   * If the pattern is expected but is empty, this method returns false, but
+   * does not mark the field as invalid. This supports selecting an attribute
+   * for a new condition before a match pattern has been entered.
    * 
    * @param value
    * @param condCombo
@@ -1806,14 +1808,15 @@ public class FeatureTypeSettings extends JalviewDialog
 
   /**
    * Constructs a filter condition from the given input fields, and replaces the
-   * condition at filterIndex with the new one. Does nothing if the pattern field
-   * is blank (unless the match condition is one that doesn't require a pattern,
-   * e.g. 'Is present'). Answers true if the filter was updated, else false.
+   * condition at filterIndex with the new one. Does nothing if the pattern
+   * field is blank (unless the match condition is one that doesn't require a
+   * pattern, e.g. 'Is present'). Answers true if the filter was updated, else
+   * false.
    * <p>
    * This method may update the tooltip on the filter value field to show the
-   * value range, if a numeric condition is selected. This ensures the tooltip is
-   * updated when a numeric valued attribute is chosen on the last 'add a filter'
-   * row.
+   * value range, if a numeric condition is selected. This ensures the tooltip
+   * is updated when a numeric valued attribute is chosen on the last 'add a
+   * filter' row.
    * 
    * @param attCombo
    * @param condCombo
@@ -1861,17 +1864,6 @@ public class FeatureTypeSettings extends JalviewDialog
   }
 
   /**
-   * Makes the dialog visible, at the Feature Colour tab or at the Filters tab
-   * 
-   * @param coloursTab
-   */
-  public void showTab(boolean coloursTab)
-  {
-    setVisible(true);
-    tabbedPane.setSelectedIndex(coloursTab ? 0 : 1);
-  }
-
-  /**
    * Action on any change to feature filtering, namely
    * <ul>
    * <li>change of selected attribute</li>
@@ -1879,8 +1871,8 @@ public class FeatureTypeSettings extends JalviewDialog
    * <li>change of match pattern</li>
    * <li>removal of a condition</li>
    * </ul>
-   * The inputs are parsed into a combined filter and this is set for the feature
-   * type, and the alignment redrawn.
+   * The inputs are parsed into a combined filter and this is set for the
+   * feature type, and the alignment redrawn.
    */
   protected void filtersChanged()
   {
index f3c8e8f..c66f304 100755 (executable)
@@ -134,7 +134,7 @@ public class FontChooser extends GFontChooser
       fontAsCdna.setSelected(ap.av.isProteinFontAsCdna());
     }
 
-    if (tp != null)
+    if (isTreeFont())
     {
       Desktop.addInternalFrame(frame,
               MessageManager.getString("action.change_font_tree_panel"),
@@ -229,7 +229,11 @@ public class FontChooser extends GFontChooser
   @Override
   protected void cancel_actionPerformed()
   {
-    if (ap != null)
+    if (isTreeFont())
+    {
+      tp.setTreeFont(oldFont);
+    }
+    else if (ap != null)
     {
       ap.av.setFont(oldFont, true);
       ap.av.setScaleProteinAsCdna(oldProteinScale);
@@ -250,10 +254,6 @@ public class FontChooser extends GFontChooser
         splitFrame.repaint();
       }
     }
-    else if (tp != null)
-    {
-      tp.setTreeFont(oldFont);
-    }
 
     try
     {
@@ -263,6 +263,11 @@ public class FontChooser extends GFontChooser
     }
   }
 
+  private boolean isTreeFont()
+  {
+    return tp != null;
+  }
+
   /**
    * DOCUMENT ME!
    */
@@ -317,7 +322,7 @@ public class FontChooser extends GFontChooser
       }
       return;
     }
-    if (tp != null)
+    if (isTreeFont())
     {
       tp.setTreeFont(newFont);
     }
index cd7b0b7..cf88c90 100755 (executable)
@@ -63,10 +63,6 @@ public class IdCanvas extends JPanel implements ViewportListenerI
 
   List<SequenceI> searchResults;
 
-  FontMetrics fm;
-
-  AnnotationLabels labels = null;
-
   AnnotationPanel ap;
 
   private Font idfont;
@@ -88,7 +84,7 @@ public class IdCanvas extends JPanel implements ViewportListenerI
   /**
    * DOCUMENT ME!
    * 
-   * @param gg
+   * @param g
    *          DOCUMENT ME!
    * @param hiddenRows
    *          true - check and display hidden row marker if need be
@@ -101,7 +97,7 @@ public class IdCanvas extends JPanel implements ViewportListenerI
    * @param ypos
    *          DOCUMENT ME!
    */
-  public void drawIdString(Graphics2D gg, boolean hiddenRows, SequenceI s,
+  public void drawIdString(Graphics2D g, boolean hiddenRows, SequenceI s,
           int i, int starty, int ypos)
   {
     int xPos = 0;
@@ -110,39 +106,40 @@ public class IdCanvas extends JPanel implements ViewportListenerI
 
     if ((searchResults != null) && searchResults.contains(s))
     {
-      gg.setColor(Color.black);
-      gg.fillRect(0, ((i - starty) * charHeight) + ypos, getWidth(),
+      g.setColor(Color.black);
+      g.fillRect(0, ((i - starty) * charHeight) + ypos, getWidth(),
               charHeight);
-      gg.setColor(Color.white);
+      g.setColor(Color.white);
     }
     else if ((av.getSelectionGroup() != null)
             && av.getSelectionGroup().getSequences(null).contains(s))
     {
-      gg.setColor(Color.lightGray);
-      gg.fillRect(0, ((i - starty) * charHeight) + ypos, getWidth(),
+      g.setColor(Color.lightGray);
+      g.fillRect(0, ((i - starty) * charHeight) + ypos, getWidth(),
               charHeight);
-      gg.setColor(Color.white);
+      g.setColor(Color.white);
     }
     else
     {
-      gg.setColor(av.getSequenceColour(s));
-      gg.fillRect(0, ((i - starty) * charHeight) + ypos, getWidth(),
+      g.setColor(av.getSequenceColour(s));
+      g.fillRect(0, ((i - starty) * charHeight) + ypos, getWidth(),
               charHeight);
-      gg.setColor(Color.black);
+      g.setColor(Color.black);
     }
 
     if (av.isRightAlignIds())
     {
+      FontMetrics fm = g.getFontMetrics();
       xPos = panelWidth
               - fm.stringWidth(s.getDisplayId(av.getShowJVSuffix())) - 4;
     }
 
-    gg.drawString(s.getDisplayId(av.getShowJVSuffix()), xPos,
+    g.drawString(s.getDisplayId(av.getShowJVSuffix()), xPos,
             (((i - starty + 1) * charHeight) + ypos) - (charHeight / 5));
 
     if (hiddenRows)
     {
-      drawMarker(i, starty, ypos);
+      drawMarker(g, av, i, starty, ypos);
     }
 
   }
@@ -199,7 +196,7 @@ public class IdCanvas extends JPanel implements ViewportListenerI
 
     gg.translate(0, transY);
 
-    drawIds(ss, es);
+    drawIds(gg, av, ss, es, searchResults);
 
     gg.translate(0, -transY);
 
@@ -255,159 +252,167 @@ public class IdCanvas extends JPanel implements ViewportListenerI
     gg.setColor(Color.white);
     gg.fillRect(0, 0, getWidth(), imgHeight);
     
-    drawIds(av.getRanges().getStartSeq(), av.getRanges().getEndSeq());
+    drawIds(gg, av, av.getRanges().getStartSeq(), av.getRanges().getEndSeq(), searchResults);
     
     g.drawImage(image, 0, 0, this);
   }
 
   /**
-   * DOCUMENT ME!
+   * Draws sequence ids from sequence index startSeq to endSeq (inclusive), with
+   * the font and other display settings configured on the viewport. Ids of
+   * sequences included in the selection are coloured grey, otherwise the
+   * current id colour for the sequence id is used.
    * 
-   * @param starty
-   *          DOCUMENT ME!
-   * @param endy
-   *          DOCUMENT ME!
+   * @param g
+   * @param alignViewport
+   * @param startSeq
+   * @param endSeq
+   * @param selection
    */
-  void drawIds(int starty, int endy)
+  void drawIds(Graphics2D g, AlignViewport alignViewport, final int startSeq,
+          final int endSeq, List<SequenceI> selection)
   {
-    if (av.isSeqNameItalics())
+    Font font = alignViewport.getFont();
+    if (alignViewport.isSeqNameItalics())
     {
-      setIdfont(new Font(av.getFont().getName(), Font.ITALIC,
-              av.getFont().getSize()));
+      setIdfont(new Font(font.getName(), Font.ITALIC,
+              font.getSize()));
     }
     else
     {
-      setIdfont(av.getFont());
+      setIdfont(font);
     }
 
-    gg.setFont(getIdfont());
-    fm = gg.getFontMetrics();
+    g.setFont(getIdfont());
+    FontMetrics fm = g.getFontMetrics();
 
-    if (av.antiAlias)
+    if (alignViewport.antiAlias)
     {
-      gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+      g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
               RenderingHints.VALUE_ANTIALIAS_ON);
     }
 
     Color currentColor = Color.white;
     Color currentTextColor = Color.black;
 
-    boolean hasHiddenRows = av.hasHiddenRows();
+    boolean hasHiddenRows = alignViewport.hasHiddenRows();
 
-    if (av.getWrapAlignment())
+    if (alignViewport.getWrapAlignment())
     {
-      drawIdsWrapped(starty, hasHiddenRows);
+      drawIdsWrapped(g, alignViewport, startSeq, getHeight());
       return;
     }
 
-    // No need to hang on to labels if we're not wrapped
-    labels = null;
-
     // Now draw the id strings
     int panelWidth = getWidth();
     int xPos = 0;
 
-    SequenceI sequence;
     // Now draw the id strings
-    for (int i = starty; i <= endy; i++)
+    for (int i = startSeq; i <= endSeq; i++)
     {
-      sequence = av.getAlignment().getSequenceAt(i);
+      SequenceI sequence = alignViewport.getAlignment().getSequenceAt(i);
 
       if (sequence == null)
       {
         continue;
       }
 
-      if (hasHiddenRows || av.isDisplayReferenceSeq())
+      if (hasHiddenRows || alignViewport.isDisplayReferenceSeq())
       {
-        setHiddenFont(sequence);
+        g.setFont(getHiddenFont(sequence, alignViewport));
       }
 
       // Selected sequence colours
-      if ((searchResults != null) && searchResults.contains(sequence))
+      if (selection != null && selection.contains(sequence))
       {
         currentColor = Color.black;
         currentTextColor = Color.white;
       }
-      else if ((av.getSelectionGroup() != null) && av.getSelectionGroup()
-              .getSequences(null).contains(sequence))
+      else if ((alignViewport.getSelectionGroup() != null) && alignViewport
+              .getSelectionGroup().getSequences(null).contains(sequence))
       {
         currentColor = Color.lightGray;
         currentTextColor = Color.black;
       }
       else
       {
-        currentColor = av.getSequenceColour(sequence);
+        currentColor = alignViewport.getSequenceColour(sequence);
         currentTextColor = Color.black;
       }
 
-      gg.setColor(currentColor);
+      g.setColor(currentColor);
 
-      gg.fillRect(0, (i - starty) * av.getCharHeight(), getWidth(),
-              av.getCharHeight());
+      int charHeight = alignViewport.getCharHeight();
+      g.fillRect(0, (i - startSeq) * charHeight,
+              getWidth(), charHeight);
 
-      gg.setColor(currentTextColor);
+      g.setColor(currentTextColor);
 
-      String string = sequence.getDisplayId(av.getShowJVSuffix());
+      String string = sequence
+              .getDisplayId(alignViewport.getShowJVSuffix());
 
-      if (av.isRightAlignIds())
+      if (alignViewport.isRightAlignIds())
       {
         xPos = panelWidth - fm.stringWidth(string) - 4;
       }
 
-      gg.drawString(string, xPos,
-              (((i - starty) * av.getCharHeight()) + av.getCharHeight())
-                      - (av.getCharHeight() / 5));
+      g.drawString(string, xPos, (((i - startSeq) * charHeight) + charHeight)
+              - (charHeight / 5));
 
       if (hasHiddenRows)
       {
-        drawMarker(i, starty, 0);
+        drawMarker(g, alignViewport, i, startSeq, 0);
       }
     }
   }
 
   /**
-   * Draws sequence ids in wrapped mode
+   * Draws sequence ids, and annotation labels if annotations are shown, in
+   * wrapped mode
    * 
-   * @param starty
-   * @param hasHiddenRows
+   * @param g
+   * @param alignViewport
+   * @param startSeq
    */
-  protected void drawIdsWrapped(int starty, boolean hasHiddenRows)
+  void drawIdsWrapped(Graphics2D g, AlignViewport alignViewport,
+          int startSeq, int pageHeight)
   {
-    int maxwidth = av.getAlignment().getWidth();
-    int alheight = av.getAlignment().getHeight();
+    int alignmentWidth = alignViewport.getAlignment().getWidth();
+    final int alheight = alignViewport.getAlignment().getHeight();
 
-    if (av.hasHiddenColumns())
+    if (alignViewport.hasHiddenColumns())
     {
-      maxwidth = av.getAlignment().getHiddenColumns()
-              .absoluteToVisibleColumn(maxwidth) - 1;
+      alignmentWidth = alignViewport.getAlignment().getHiddenColumns()
+              .absoluteToVisibleColumn(alignmentWidth) - 1;
     }
 
     int annotationHeight = 0;
 
-    if (av.isShowAnnotation())
+    AnnotationLabels labels = null;
+    if (alignViewport.isShowAnnotation())
     {
       if (ap == null)
       {
-        ap = new AnnotationPanel(av);
+        ap = new AnnotationPanel(alignViewport);
       }
-
       annotationHeight = ap.adjustPanelHeight();
-      if (labels == null)
-      {
-        labels = new AnnotationLabels(av);
-      }
+      labels = new AnnotationLabels(alignViewport);
     }
 
-    int hgap = av.getCharHeight();
-    if (av.getScaleAboveWrapped())
+    final int charHeight = alignViewport.getCharHeight();
+    int hgap = charHeight;
+    if (alignViewport.getScaleAboveWrapped())
     {
-      hgap += av.getCharHeight();
+      hgap += charHeight;
     }
 
-    int cHeight = alheight * av.getCharHeight() + hgap + annotationHeight;
+    /*
+     * height of alignment + gap + annotations (if shown)
+     */
+    int cHeight = alheight * charHeight + hgap
+            + annotationHeight;
 
-    ViewportRanges ranges = av.getRanges();
+    ViewportRanges ranges = alignViewport.getRanges();
 
     int rowSize = ranges.getViewportWidth();
 
@@ -415,49 +420,58 @@ public class IdCanvas extends JPanel implements ViewportListenerI
      * draw repeating sequence ids until out of sequence data or
      * out of visible space, whichever comes first
      */
+    boolean hasHiddenRows = alignViewport.hasHiddenRows();
     int ypos = hgap;
-    int row = ranges.getStartRes();
-    while ((ypos <= getHeight()) && (row < maxwidth))
+    int rowStartRes = ranges.getStartRes();
+    while ((ypos <= pageHeight) && (rowStartRes < alignmentWidth))
     {
-      for (int i = starty; i < alheight; i++)
+      for (int i = startSeq; i < alheight; i++)
       {
-        SequenceI s = av.getAlignment().getSequenceAt(i);
-        if (hasHiddenRows || av.isDisplayReferenceSeq())
+        SequenceI s = alignViewport.getAlignment().getSequenceAt(i);
+        if (hasHiddenRows || alignViewport.isDisplayReferenceSeq())
         {
-          setHiddenFont(s);
+          g.setFont(getHiddenFont(s, alignViewport));
         }
         else
         {
-          gg.setFont(getIdfont());
+          g.setFont(getIdfont());
         }
-
-        drawIdString(gg, hasHiddenRows, s, i, 0, ypos);
+        drawIdString(g, hasHiddenRows, s, i, 0, ypos);
       }
 
-      if (labels != null && av.isShowAnnotation())
+      if (labels != null && alignViewport.isShowAnnotation())
       {
-        gg.translate(0, ypos + (alheight * av.getCharHeight()));
-        labels.drawComponent(gg, getWidth());
-        gg.translate(0, -ypos - (alheight * av.getCharHeight()));
+        g.translate(0, ypos + (alheight * charHeight));
+        labels.drawComponent(g, getWidth());
+        g.translate(0, -ypos - (alheight * charHeight));
       }
 
       ypos += cHeight;
-      row += rowSize;
+      rowStartRes += rowSize;
     }
   }
 
-  void drawMarker(int i, int starty, int yoffset)
+  /**
+   * Draws a marker (a blue right-pointing triangle) between sequences to
+   * indicate hidden sequences.
+   * 
+   * @param g
+   * @param alignViewport
+   * @param seqIndex
+   * @param starty
+   * @param yoffset
+   */
+  void drawMarker(Graphics2D g, AlignViewport alignViewport, int seqIndex, int starty, int yoffset)
   {
-
-    SequenceI[] hseqs = av.getAlignment()
+    SequenceI[] hseqs = alignViewport.getAlignment()
             .getHiddenSequences().hiddenSequences;
     // Use this method here instead of calling hiddenSeq adjust
     // 3 times.
     int hSize = hseqs.length;
 
-    int hiddenIndex = i;
-    int lastIndex = i - 1;
-    int nextIndex = i + 1;
+    int hiddenIndex = seqIndex;
+    int lastIndex = seqIndex - 1;
+    int nextIndex = seqIndex + 1;
 
     for (int j = 0; j < hSize; j++)
     {
@@ -478,52 +492,56 @@ public class IdCanvas extends JPanel implements ViewportListenerI
       }
     }
 
+    /*
+     * are we below or above the hidden sequences?
+     */
     boolean below = (hiddenIndex > lastIndex + 1);
     boolean above = (nextIndex > hiddenIndex + 1);
 
-    gg.setColor(Color.blue);
+    g.setColor(Color.blue);
+    int charHeight = av.getCharHeight();
+
+    /*
+     * vertices of the triangle, below or above hidden seqs
+     */
+    int[] xPoints = new int[]
+    { getWidth() - charHeight,
+        getWidth() - charHeight, getWidth() };
+    int yShift = seqIndex - starty;
+
     if (below)
     {
-      gg.fillPolygon(
-              new int[]
-              { getWidth() - av.getCharHeight(),
-                  getWidth() - av.getCharHeight(), getWidth() },
-              new int[]
-              { (i - starty) * av.getCharHeight() + yoffset,
-                  (i - starty) * av.getCharHeight() + yoffset
-                          + av.getCharHeight() / 4,
-                  (i - starty) * av.getCharHeight() + yoffset },
-              3);
+      int[] yPoints = new int[] { yShift * charHeight + yoffset,
+          yShift * charHeight + yoffset + charHeight / 4,
+          yShift * charHeight + yoffset };
+      g.fillPolygon(xPoints, yPoints, 3);
     }
     if (above)
     {
-      gg.fillPolygon(
-              new int[]
-              { getWidth() - av.getCharHeight(),
-                  getWidth() - av.getCharHeight(), getWidth() },
-              new int[]
-              { (i - starty + 1) * av.getCharHeight() + yoffset,
-                  (i - starty + 1) * av.getCharHeight() + yoffset
-                          - av.getCharHeight() / 4,
-                  (i - starty + 1) * av.getCharHeight() + yoffset },
-              3);
-
+      yShift++;
+      int[] yPoints = new int[] { yShift * charHeight + yoffset,
+          yShift * charHeight + yoffset - charHeight / 4,
+          yShift * charHeight + yoffset };
+      g.fillPolygon(xPoints, yPoints, 3);
     }
   }
 
-  void setHiddenFont(SequenceI seq)
+  /**
+   * Answers the standard sequence id font, or a bold font if the sequence is
+   * set as reference or a hidden group representative
+   * 
+   * @param seq
+   * @param alignViewport
+   * @return
+   */
+  private Font getHiddenFont(SequenceI seq, AlignViewport alignViewport)
   {
-    Font bold = new Font(av.getFont().getName(), Font.BOLD,
-            av.getFont().getSize());
-
     if (av.isReferenceSeq(seq) || av.isHiddenRepSequence(seq))
     {
-      gg.setFont(bold);
-    }
-    else
-    {
-      gg.setFont(getIdfont());
+      return new Font(av.getFont().getName(), Font.BOLD,
+              av.getFont().getSize());
     }
+    return getIdfont();
   }
 
   /**
index 1018d6e..8d62433 100644 (file)
@@ -20,7 +20,6 @@
  */
 package jalview.gui;
 
-import jalview.bin.Cache;
 import jalview.util.MessageManager;
 import jalview.ws.seqfetcher.DbSourceProxy;
 
@@ -42,7 +41,6 @@ import java.util.List;
 import java.util.Vector;
 
 import javax.swing.JButton;
-import javax.swing.JFrame;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
@@ -518,54 +516,6 @@ public class JDatabaseTree extends JalviewDialog implements KeyListener
     lstners.remove(actionListener);
   }
 
-  public static void main(String args[])
-  {
-    Cache.getDasSourceRegistry();
-    JDatabaseTree jdt = new JDatabaseTree(new jalview.ws.SequenceFetcher());
-    JFrame foo = new JFrame();
-    foo.setLayout(new BorderLayout());
-    foo.add(jdt.getDatabaseSelectorButton(), BorderLayout.CENTER);
-    foo.pack();
-    foo.setVisible(true);
-    int nultimes = 5;
-    final Thread us = Thread.currentThread();
-    jdt.addActionListener(new ActionListener()
-    {
-
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        us.interrupt();
-      }
-    });
-    do
-    {
-      try
-      {
-        Thread.sleep(50);
-      } catch (InterruptedException x)
-      {
-        nultimes--;
-        if (!jdt.hasSelection())
-        {
-          System.out.println("No Selection");
-        }
-        else
-        {
-          System.out.println("Selection: " + jdt.getSelectedItem());
-          int s = 1;
-          for (DbSourceProxy pr : jdt.getSelectedSources())
-          {
-            System.out.println("Source " + s++ + ": " + pr.getDbName()
-                    + " (" + pr.getDbSource() + ") Version "
-                    + pr.getDbVersion() + ". Test:\t" + pr.getTestQuery());
-          }
-          System.out.println("Test queries: " + jdt.getExampleQueries());
-        }
-      }
-    } while (nultimes > 0 && foo.isVisible());
-    foo.setVisible(false);
-  }
 
   @Override
   public void keyPressed(KeyEvent arg0)
index 5aab26d..7d02fac 100755 (executable)
@@ -168,8 +168,6 @@ public class Preferences extends GPreferences
 
   JInternalFrame frame;
 
-  DasSourceBrowser dasSource;
-
   private WsPreferences wsPrefs;
 
   private OptionsParam promptEachTimeOpt = new OptionsParam(
@@ -190,8 +188,6 @@ public class Preferences extends GPreferences
     super();
     frame = new JInternalFrame();
     frame.setContentPane(this);
-    dasSource = new DasSourceBrowser();
-    dasTab.add(dasSource, BorderLayout.CENTER);
     wsPrefs = new WsPreferences();
     wsTab.add(wsPrefs, BorderLayout.CENTER);
     int width = 500, height = 450;
@@ -797,7 +793,6 @@ public class Preferences extends GPreferences
     Cache.applicationProperties.setProperty("PAD_GAPS",
             Boolean.toString(padGaps.isSelected()));
 
-    dasSource.saveProperties(Cache.applicationProperties);
     wsPrefs.updateAndRefreshWsMenuConfig(false);
     Cache.saveProperties();
     Desktop.instance.doConfigureStructurePrefs();
index 8f315bd..5c404f0 100755 (executable)
@@ -32,7 +32,6 @@ import jalview.util.Comparison;
 import jalview.viewmodel.ViewportListenerI;
 import jalview.viewmodel.ViewportRanges;
 
-import java.awt.AlphaComposite;
 import java.awt.BasicStroke;
 import java.awt.BorderLayout;
 import java.awt.Color;
@@ -365,31 +364,27 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
     width -= (width % charWidth);
     height -= (height % charHeight);
     
-    // selectImage is the selection group outline image
-    BufferedImage selectImage = drawSelectionGroup(
-            ranges.getStartRes(), ranges.getEndRes(),
-            ranges.getStartSeq(), ranges.getEndSeq());
-    
     if ((img != null) && (fastPaint
             || (getVisibleRect().width != g.getClipBounds().width)
             || (getVisibleRect().height != g.getClipBounds().height)))
     {
-      BufferedImage lcimg = buildLocalImage(selectImage);
-      g.drawImage(lcimg, 0, 0, this);
+      g.drawImage(img, 0, 0, this);
+
+      drawSelectionGroup((Graphics2D) g, ranges.getStartRes(),
+              ranges.getEndRes(), ranges.getStartSeq(), ranges.getEndSeq());
+
       fastPaint = false;
     }
-    else if ((width > 0) && (height > 0))
+    else if (width > 0 && height > 0)
     {
-      // img is a cached version of the last view we drew, if any
-      // if we have no img or the size has changed, make a new one
+      /*
+       * img is a cached version of the last view we drew, if any
+       * if we have no img or the size has changed, make a new one
+       */
       if (img == null || width != img.getWidth()
               || height != img.getHeight())
       {
-        img = setupImage();
-        if (img == null)
-        {
-          return;
-        }
+        img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
         gg = (Graphics2D) img.getGraphics();
         gg.setFont(av.getFont());
       }
@@ -412,11 +407,11 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
         drawPanel(gg, ranges.getStartRes(), ranges.getEndRes(),
                 ranges.getStartSeq(), ranges.getEndSeq(), 0);
       }
-    
-      // lcimg is a local *copy* of img which we'll draw selectImage on top of
-      BufferedImage lcimg = buildLocalImage(selectImage);
-      g.drawImage(lcimg, 0, 0, this);
 
+      drawSelectionGroup(gg, ranges.getStartRes(),
+              ranges.getEndRes(), ranges.getStartSeq(), ranges.getEndSeq());
+
+      g.drawImage(img, 0, 0, this);
     }
 
     if (av.cursorMode)
@@ -445,14 +440,8 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
   {
     drawPanel(g1, startRes, endRes, startSeq, endSeq, 0);
 
-    BufferedImage selectImage = drawSelectionGroup(startRes, endRes,
+    drawSelectionGroup((Graphics2D) g1, startRes, endRes,
             startSeq, endSeq);
-    if (selectImage != null)
-    {
-      ((Graphics2D) g1).setComposite(AlphaComposite
-              .getInstance(AlphaComposite.SRC_OVER));
-      g1.drawImage(selectImage, 0, 0, this);
-    }
   }
 
   /**
@@ -470,104 +459,16 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
   public void drawWrappedPanelForPrinting(Graphics g, int canvasWidth,
           int canvasHeight, int startRes)
   {
-    SequenceGroup group = av.getSelectionGroup();
-
     drawWrappedPanel(g, canvasWidth, canvasHeight, startRes);
 
+    SequenceGroup group = av.getSelectionGroup();
     if (group != null)
     {
-      BufferedImage selectImage = null;
-      try
-      {
-        selectImage = new BufferedImage(canvasWidth, canvasHeight,
-                BufferedImage.TYPE_INT_ARGB); // ARGB so alpha compositing works
-      } catch (OutOfMemoryError er)
-      {
-        System.gc();
-        System.err.println("Print image OutOfMemory Error.\n" + er);
-        new OOMWarning("Creating wrapped alignment image for printing", er);
-      }
-      if (selectImage != null)
-      {
-        Graphics2D g2 = selectImage.createGraphics();
-        setupSelectionGroup(g2, selectImage);
-        drawWrappedSelection(g2, group, canvasWidth, canvasHeight,
+      drawWrappedSelection((Graphics2D) g, group, canvasWidth, canvasHeight,
                 startRes);
-
-        g2.setComposite(
-                AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
-        g.drawImage(selectImage, 0, 0, this);
-        g2.dispose();
-      }
     }
   }
 
-  /*
-   * Make a local image by combining the cached image img
-   * with any selection
-   */
-  private BufferedImage buildLocalImage(BufferedImage selectImage)
-  {
-    // clone the cached image
-         BufferedImage lcimg = new BufferedImage(img.getWidth(), img.getHeight(),
-                   img.getType());
-
-    // BufferedImage lcimg = new BufferedImage(img.getWidth(), img.getHeight(),
-    // img.getType());
-    Graphics2D g2d = lcimg.createGraphics();
-    g2d.drawImage(img, 0, 0, null);
-
-    // overlay selection group on lcimg
-    if (selectImage != null)
-    {
-      g2d.setComposite(
-              AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
-      g2d.drawImage(selectImage, 0, 0, this);
-    }
-
-    g2d.dispose();
-
-    return lcimg;
-  }
-
-  /*
-   * Set up a buffered image of the correct height and size for the sequence canvas
-   */
-  private BufferedImage setupImage()
-  {
-    BufferedImage lcimg = null;
-
-    int charWidth = av.getCharWidth();
-    int charHeight = av.getCharHeight();
-    
-    int width = getWidth();
-    int height = getHeight();
-
-    width -= (width % charWidth);
-    height -= (height % charHeight);
-
-    if ((width < 1) || (height < 1))
-    {
-      return null;
-    }
-
-    try
-    {
-       lcimg = new BufferedImage(width, height,
-                BufferedImage.TYPE_INT_ARGB); // ARGB so alpha compositing works
-    } catch (OutOfMemoryError er)
-    {
-      System.gc();
-      System.err.println(
-              "Group image OutOfMemory Redraw Error.\n" + er);
-      new OOMWarning("Creating alignment image for display", er);
-
-      return null;
-    }
-
-    return lcimg;
-  }
-
   /**
    * Returns the visible width of the canvas in residues, after allowing for
    * East or West scales (if shown)
@@ -658,7 +559,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
     calculateWrappedGeometry(canvasWidth, canvasHeight);
 
     /*
-     * draw one width at a time (including any scales or annotation shown),
+     * draw one width at a time (excluding any scales or annotation shown),
      * until we have run out of either alignment or vertical space available
      */
     int ypos = wrappedSpaceAboveAlignment;
@@ -709,7 +610,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
      */
     wrappedRepeatHeightPx = wrappedSpaceAboveAlignment;
     // add sequences
-    wrappedRepeatHeightPx += av.getRanges().getViewportHeight()
+    wrappedRepeatHeightPx += av.getAlignment().getHeight()
             * charHeight;
     // add annotations panel height if shown
     wrappedRepeatHeightPx += getAnnotationHeight();
@@ -964,6 +865,10 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
 
     // chop the wrapped alignment extent up into panel-sized blocks and treat
     // each block as if it were a block from an unwrapped alignment
+    g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT,
+            BasicStroke.JOIN_ROUND, 3f, new float[]
+            { 5f, 3f }, 0f));
+    g.setColor(Color.RED);
     while ((ypos <= canvasHeight) && (startx < maxwidth))
     {
       // set end value to be start + width, or maxwidth, whichever is smaller
@@ -988,6 +893,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
       // update horizontal offset
       startx += cWidth;
     }
+    g.setStroke(new BasicStroke());
   }
 
   int getAnnotationHeight()
@@ -1154,14 +1060,21 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
 
   }
 
+  /**
+   * Draws the outlines of any groups defined on the alignment (excluding the
+   * current selection group, if any)
+   * 
+   * @param g1
+   * @param startRes
+   * @param endRes
+   * @param startSeq
+   * @param endSeq
+   * @param offset
+   */
   void drawGroupsBoundaries(Graphics g1, int startRes, int endRes,
           int startSeq, int endSeq, int offset)
   {
     Graphics2D g = (Graphics2D) g1;
-    //
-    // ///////////////////////////////////
-    // Now outline any areas if necessary
-    // ///////////////////////////////////
 
     SequenceGroup group = null;
     int groupIndex = -1;
@@ -1174,18 +1087,15 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
 
     if (group != null)
     {
-      g.setStroke(new BasicStroke());
-      g.setColor(group.getOutlineColour());
-      
       do
       {
+        g.setColor(group.getOutlineColour());
+
         drawPartialGroupOutline(g, group, startRes, endRes, startSeq,
                 endSeq, offset);
 
         groupIndex++;
 
-        g.setStroke(new BasicStroke());
-
         if (groupIndex >= av.getAlignment().getGroups().size())
         {
           break;
@@ -1199,33 +1109,28 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
 
   }
 
-
-  /*
-   * Draw the selection group as a separate image and overlay
+  /**
+   * Draws the outline of the current selection group (if any)
+   * 
+   * @param g
+   * @param startRes
+   * @param endRes
+   * @param startSeq
+   * @param endSeq
    */
-  private BufferedImage drawSelectionGroup(int startRes, int endRes,
+  private void drawSelectionGroup(Graphics2D g, int startRes, int endRes,
           int startSeq, int endSeq)
   {
-    // get a new image of the correct size
-    BufferedImage selectionImage = setupImage();
-
-    if (selectionImage == null)
-    {
-      return null;
-    }
-
     SequenceGroup group = av.getSelectionGroup();
     if (group == null)
     {
-      // nothing to draw
-      return null;
+      return;
     }
 
-    // set up drawing colour
-    Graphics2D g = (Graphics2D) selectionImage.getGraphics();
-
-    setupSelectionGroup(g, selectionImage);
-
+    g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT,
+            BasicStroke.JOIN_ROUND, 3f, new float[]
+            { 5f, 3f }, 0f));
+    g.setColor(Color.RED);
     if (!av.getWrapAlignment())
     {
       drawUnwrappedSelection(g, group, startRes, endRes, startSeq, endSeq,
@@ -1236,9 +1141,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
       drawWrappedSelection(g, group, getWidth(), getHeight(),
               av.getRanges().getStartRes());
     }
-
-    g.dispose();
-    return selectionImage;
+    g.setStroke(new BasicStroke());
   }
 
   /**
@@ -1329,33 +1232,23 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
   }
 
 
-  /*
-   * Set up graphics for selection group
-   */
-  private void setupSelectionGroup(Graphics2D g,
-          BufferedImage selectionImage)
-  {
-    // set background to transparent
-    g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
-    g.fillRect(0, 0, selectionImage.getWidth(), selectionImage.getHeight());
-
-    // set up foreground to draw red dashed line
-    g.setComposite(AlphaComposite.Src);
-    g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT,
-            BasicStroke.JOIN_ROUND, 3f, new float[]
-    { 5f, 3f }, 0f));
-    g.setColor(Color.RED);
-  }
-
-  /*
+  /**
    * Draw a selection group over an unwrapped alignment
-   * @param g graphics object to draw with
-   * @param group selection group
-   * @param startRes start residue of area to draw
-   * @param endRes end residue of area to draw
-   * @param startSeq start sequence of area to draw
-   * @param endSeq end sequence of area to draw
-   * @param offset vertical offset (used when called from wrapped alignment code)
+   * 
+   * @param g
+   *          graphics object to draw with
+   * @param group
+   *          selection group
+   * @param startRes
+   *          start residue of area to draw
+   * @param endRes
+   *          end residue of area to draw
+   * @param startSeq
+   *          start sequence of area to draw
+   * @param endSeq
+   *          end sequence of area to draw
+   * @param offset
+   *          vertical offset (used when called from wrapped alignment code)
    */
   private void drawUnwrappedSelection(Graphics2D g, SequenceGroup group,
           int startRes, int endRes, int startSeq, int endSeq, int offset)
@@ -1393,8 +1286,16 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
     }
   }
 
-  /*
-   * Draw the selection group as a separate image and overlay
+  /**
+   * Draws part of a selection group outline
+   * 
+   * @param g
+   * @param group
+   * @param startRes
+   * @param endRes
+   * @param startSeq
+   * @param endSeq
+   * @param verticalOffset
    */
   private void drawPartialGroupOutline(Graphics2D g, SequenceGroup group,
           int startRes, int endRes, int startSeq, int endSeq,
index 53ce80c..0982dcc 100755 (executable)
@@ -34,7 +34,6 @@ import jalview.io.gff.SequenceOntologyI;
 import jalview.util.DBRefUtils;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
-import jalview.ws.dbsources.das.api.DasSourceRegistryI;
 import jalview.ws.seqfetcher.DbSourceProxy;
 
 import java.awt.BorderLayout;
@@ -111,10 +110,6 @@ public class SequenceFetcher extends JPanel implements Runnable
 
   private static jalview.ws.SequenceFetcher sfetch = null;
 
-  private static long lastDasSourceRegistry = -3;
-
-  private static DasSourceRegistryI dasRegistry = null;
-
   private static boolean _initingFetcher = false;
 
   private static Thread initingThread = null;
@@ -165,11 +160,7 @@ public class SequenceFetcher extends JPanel implements Runnable
                 Thread.currentThread().hashCode());
       }
     }
-    if (sfetch == null || dasRegistry != Cache.getDasSourceRegistry()
-            || lastDasSourceRegistry != (Cache.getDasSourceRegistry()
-                    .getDasRegistryURL()
-                    + Cache.getDasSourceRegistry().getLocalSourceString())
-                            .hashCode())
+    if (sfetch == null)
     {
       _initingFetcher = true;
       initingThread = Thread.currentThread();
@@ -183,16 +174,12 @@ public class SequenceFetcher extends JPanel implements Runnable
                         "status.init_sequence_database_fetchers"),
                 Thread.currentThread().hashCode());
       }
-      dasRegistry = Cache.getDasSourceRegistry();
-      dasRegistry.refreshSources();
 
       jalview.ws.SequenceFetcher sf = new jalview.ws.SequenceFetcher();
       if (guiWindow != null)
       {
         guiWindow.setProgressBar(null, Thread.currentThread().hashCode());
       }
-      lastDasSourceRegistry = (dasRegistry.getDasRegistryURL()
-              + dasRegistry.getLocalSourceString()).hashCode();
       sfetch = sf;
       _initingFetcher = false;
       initingThread = null;
@@ -564,15 +551,10 @@ public class SequenceFetcher extends JPanel implements Runnable
       dbeg.setText(MessageManager.formatMessage("label.example_query_param",
               new String[]
               { eq }));
+      // TODO this should be a property of the SequenceFetcher whether commas are and
+      // colons are allowed in the IDs...
+
       boolean enablePunct = !(eq != null && eq.indexOf(",") > -1);
-      for (DbSourceProxy dbs : database.getSelectedSources())
-      {
-        if (dbs instanceof jalview.ws.dbsources.das.datamodel.DasSequenceSource)
-        {
-          enablePunct = false;
-          break;
-        }
-      }
       replacePunctuation.setEnabled(enablePunct);
 
     } catch (Exception ex)
index 7dc1a99..fa30e13 100755 (executable)
@@ -962,6 +962,15 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
           }
         }
         colourGroups(groups);
+
+        /*
+         * clear partition (don't show vertical line) if
+         * it is to the right of all nodes
+         */
+        if (groups.isEmpty())
+        {
+          threshold = 0f;
+        }
       }
 
       PaintRefresher.Refresh(tp, ap.av.getSequenceSetId());
@@ -981,7 +990,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
 
       Vector<SequenceNode> l = tree.findLeaves(groups.get(i));
 
-      Vector<SequenceI> sequences = new Vector<SequenceI>();
+      Vector<SequenceI> sequences = new Vector<>();
 
       for (int j = 0; j < l.size(); j++)
       {
index 4b33dbf..e94e1ce 100644 (file)
@@ -347,7 +347,7 @@ public enum FileFormat implements FileFormatI
       return true;
     }
   },
-  Jalview("Jalview", "jar,jvp", true, true)
+  Jalview("Jalview", "jvp, jar", true, true)
   {
     @Override
     public AlignmentFileReaderI getReader(FileParse source)
index c49e34f..7a21c16 100755 (executable)
@@ -68,8 +68,8 @@ public class JalviewFileChooser extends JFileChooser
   public static JalviewFileChooser forRead(String directory,
           String selected)
   {
-    List<String> extensions = new ArrayList<String>();
-    List<String> descs = new ArrayList<String>();
+    List<String> extensions = new ArrayList<>();
+    List<String> descs = new ArrayList<>();
     for (FileFormatI format : FileFormats.getInstance().getFormats())
     {
       if (format.isReadable())
@@ -96,8 +96,8 @@ public class JalviewFileChooser extends JFileChooser
   {
     // TODO in Java 8, forRead and forWrite can be a single method
     // with a lambda expression parameter for isReadable/isWritable
-    List<String> extensions = new ArrayList<String>();
-    List<String> descs = new ArrayList<String>();
+    List<String> extensions = new ArrayList<>();
+    List<String> descs = new ArrayList<>();
     for (FileFormatI format : FileFormats.getInstance().getFormats())
     {
       if (format.isWritable())
@@ -142,7 +142,7 @@ public class JalviewFileChooser extends JFileChooser
     super(safePath(dir));
     if (extensions.length == descs.length)
     {
-      List<String[]> formats = new ArrayList<String[]>();
+      List<String[]> formats = new ArrayList<>();
       for (int i = 0; i < extensions.length; i++)
       {
         formats.add(new String[] { extensions[i], descs[i] });
@@ -278,6 +278,19 @@ public class JalviewFileChooser extends JFileChooser
     return null;
   }
 
+  File ourselectedFile = null;
+
+  @Override
+  public File getSelectedFile()
+  {
+    File selfile = super.getSelectedFile();
+    if (selfile == null && ourselectedFile != null)
+    {
+      return ourselectedFile;
+    }
+    return selfile;
+  }
+
   @Override
   public int showSaveDialog(Component parent) throws HeadlessException
   {
@@ -285,23 +298,48 @@ public class JalviewFileChooser extends JFileChooser
 
     setDialogType(SAVE_DIALOG);
 
+    this.setSelectedFile(null);
     int ret = showDialog(parent, MessageManager.getString("action.save"));
+    ourselectedFile = getSelectedFile();
 
+    if (getSelectedFile() == null)
+    {
+      // Workaround for Java 9,10 on OSX - no selected file, but there is a
+      // filename typed in
+      try
+      {
+        String filename = ((BasicFileChooserUI) getUI()).getFileName();
+        if (filename != null && filename.length() > 0)
+        {
+          ourselectedFile = new File(getCurrentDirectory(), filename);
+        }
+      } catch (Throwable x)
+      {
+        System.err.println(
+                "Unexpected exception when trying to get filename.");
+        x.printStackTrace();
+      }
+    }
+    if (ourselectedFile == null)
+    {
+      return JalviewFileChooser.CANCEL_OPTION;
+    }
     if (getFileFilter() instanceof JalviewFileFilter)
     {
       JalviewFileFilter jvf = (JalviewFileFilter) getFileFilter();
 
-      if (!jvf.accept(getSelectedFile()))
+      if (!jvf.accept(ourselectedFile))
       {
-        String withExtension = getSelectedFile() + "."
+        String withExtension = getSelectedFile().getName() + "."
                 + jvf.getAcceptableExtension();
-        setSelectedFile(new File(withExtension));
+        ourselectedFile = (new File(getCurrentDirectory(), withExtension));
+        setSelectedFile(ourselectedFile);
       }
     }
     // TODO: ENSURE THAT FILES SAVED WITH A ':' IN THE NAME ARE REFUSED AND THE
     // USER PROMPTED FOR A NEW FILENAME
     if ((ret == JalviewFileChooser.APPROVE_OPTION)
-            && getSelectedFile().exists())
+            && ourselectedFile.exists())
     {
       int confirm = JvOptionPane.showConfirmDialog(parent,
               MessageManager.getString("label.overwrite_existing_file"),
index d59e88a..21f5b0f 100755 (executable)
 package jalview.io;
 
 import java.io.File;
-import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.StringTokenizer;
 
 import javax.swing.filechooser.FileFilter;
@@ -31,7 +33,7 @@ public class JalviewFileFilter extends FileFilter
 {
   public static Hashtable suffixHash = new Hashtable();
 
-  private Hashtable filters = null;
+  private Map<String, JalviewFileFilter> filters = null;
 
   private String description = "no description";
 
@@ -72,10 +74,11 @@ public class JalviewFileFilter extends FileFilter
 
   public String getAcceptableExtension()
   {
-    return filters.keys().nextElement().toString();
+    return filters.keySet().iterator().next().toString();
   }
 
   // takes account of the fact that database is a directory
+  @Override
   public boolean accept(File f)
   {
     if (f != null)
@@ -87,7 +90,7 @@ public class JalviewFileFilter extends FileFilter
         return true;
       }
 
-      if ((extension != null) && (filters.get(getExtension(f)) != null))
+      if ((extension != null) && (filters.get(extension) != null))
       {
         return true;
       }
@@ -118,13 +121,14 @@ public class JalviewFileFilter extends FileFilter
   {
     if (filters == null)
     {
-      filters = new Hashtable(5);
+      filters = new LinkedHashMap<>(5);
     }
 
     filters.put(extension.toLowerCase(), this);
     fullDescription = null;
   }
 
+  @Override
   public String getDescription()
   {
     if (fullDescription == null)
@@ -135,15 +139,15 @@ public class JalviewFileFilter extends FileFilter
                 : (description + " (");
 
         // build the description from the extension list
-        Enumeration extensions = filters.keys();
+        Iterator<String> extensions = filters.keySet().iterator();
 
         if (extensions != null)
         {
-          fullDescription += ("." + (String) extensions.nextElement());
+          fullDescription += ("." + extensions.next());
 
-          while (extensions.hasMoreElements())
+          while (extensions.hasNext())
           {
-            fullDescription += (", " + (String) extensions.nextElement());
+            fullDescription += (", " + extensions.next());
           }
         }
 
index b2fe587..18114f3 100755 (executable)
@@ -37,14 +37,15 @@ public class JalviewFileView extends FileView
 
   private void loadExtensions()
   {
-    extensions = new HashMap<String, String>();
+    extensions = new HashMap<>();
     for (FileFormatI ff : FileFormats.getInstance().getFormats())
     {
       String desc = ff.getName() + " file";
       String exts = ff.getExtensions();
       for (String ext : exts.split(","))
       {
-        extensions.put(ext.trim().toLowerCase(),
+        ext = ext.trim().toLowerCase();
+        extensions.put(ext,
                 desc + ("jar".equals(ext) ? " (old)" : ""));
       }
     }
@@ -124,7 +125,7 @@ public class JalviewFileView extends FileView
     {
       if (icons == null)
       {
-        icons = new HashMap<String, ImageIcon>();
+        icons = new HashMap<>();
       }
       if (!icons.containsKey(filePath))
       {
index f5b5177..0e73af1 100644 (file)
@@ -83,6 +83,14 @@ public class StockholmFile extends AlignFile
   public static final Regex DETECT_BRACKETS = new Regex(
           "(<|>|\\[|\\]|\\(|\\)|\\{|\\})");
 
+  // WUSS extended symbols. Avoid ambiguity with protein SS annotations by using NOT_RNASS first.
+  public static final String RNASS_BRACKETS = "<>[](){}AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+
+  // use the following regex to decide an annotations (whole) line is NOT an RNA
+  // SS (it contains only E,H,e,h and other non-brace/non-alpha chars)
+  private static final Regex NOT_RNASS = new Regex(
+          "^[^<>[\\](){}A-DF-Za-df-z]*$");
+
   StringBuffer out; // output buffer
 
   AlignmentI al;
@@ -197,7 +205,7 @@ public class StockholmFile extends AlignFile
     String version;
     // String id;
     Hashtable seqAnn = new Hashtable(); // Sequence related annotations
-    LinkedHashMap<String, String> seqs = new LinkedHashMap<String, String>();
+    LinkedHashMap<String, String> seqs = new LinkedHashMap<>();
     Regex p, r, rend, s, x;
     // Temporary line for processing RNA annotation
     // String RNAannot = "";
@@ -658,7 +666,7 @@ public class StockholmFile extends AlignFile
               strucAnn = new Hashtable();
             }
 
-            Vector<AlignmentAnnotation> newStruc = new Vector<AlignmentAnnotation>();
+            Vector<AlignmentAnnotation> newStruc = new Vector<>();
             parseAnnotationRow(newStruc, type, ns);
             for (AlignmentAnnotation alan : newStruc)
             {
@@ -710,7 +718,7 @@ public class StockholmFile extends AlignFile
   private void guessDatabaseFor(Sequence seqO, String dbr, String dbsource)
   {
     DBRefEntry dbrf = null;
-    List<DBRefEntry> dbrs = new ArrayList<DBRefEntry>();
+    List<DBRefEntry> dbrs = new ArrayList<>();
     String seqdb = "Unknown", sdbac = "" + dbr;
     int st = -1, en = -1, p;
     if ((st = sdbac.indexOf("/")) > -1)
@@ -824,9 +832,14 @@ public class StockholmFile extends AlignFile
     }
     boolean ss = false, posterior = false;
     type = id2type(type);
+
+    boolean isrnass = false;
     if (type.equalsIgnoreCase("secondary structure"))
     {
       ss = true;
+      isrnass = !NOT_RNASS.search(annots); // sorry about the double negative
+                                           // here (it's easier for dealing with
+                                           // other non-alpha-non-brace chars)
     }
     if (type.equalsIgnoreCase("posterior probability"))
     {
@@ -844,7 +857,7 @@ public class StockholmFile extends AlignFile
       {
         // if (" .-_".indexOf(pos) == -1)
         {
-          if (DETECT_BRACKETS.search(pos))
+          if (isrnass && RNASS_BRACKETS.indexOf(pos) >= 0)
           {
             ann.secondaryStructure = Rna.getRNASecStrucState(pos).charAt(0);
             ann.displayCharacter = "" + pos.charAt(0);
@@ -1114,22 +1127,36 @@ public class StockholmFile extends AlignFile
     String ch = (annot == null)
             ? ((sequenceI == null) ? "-"
                     : Character.toString(sequenceI.getCharAt(k)))
-            : annot.displayCharacter;
+            : (annot.displayCharacter == null
+                    ? String.valueOf(annot.secondaryStructure)
+                    : annot.displayCharacter);
+    if (ch == null)
+    {
+      ch = " ";
+    }
     if (key != null && key.equals("SS"))
     {
+      char ssannotchar = ' ';
+      boolean charset = false;
       if (annot == null)
       {
         // sensible gap character
-        return ' ';
+        ssannotchar = ' ';
+        charset = true;
       }
       else
       {
         // valid secondary structure AND no alternative label (e.g. ' B')
         if (annot.secondaryStructure > ' ' && ch.length() < 2)
         {
-          return annot.secondaryStructure;
+          ssannotchar = annot.secondaryStructure;
+          charset = true;
         }
       }
+      if (charset)
+      {
+        return (ssannotchar == ' ' && isrna) ? '.' : ssannotchar;
+      }
     }
 
     if (ch.length() == 0)
@@ -1144,7 +1171,9 @@ public class StockholmFile extends AlignFile
     {
       seq = ch.charAt(1);
     }
-    return seq;
+
+    return (seq == ' ' && key != null && key.equals("SS") && isrna) ? '.'
+            : seq;
   }
 
   public String print()
index a837512..beef3e7 100644 (file)
@@ -23,8 +23,6 @@ package jalview.io.cache;
 import jalview.bin.Cache;
 import jalview.util.MessageManager;
 
-import java.awt.Color;
-import java.awt.Dimension;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.KeyEvent;
@@ -36,37 +34,22 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 
-import javax.swing.BorderFactory;
 import javax.swing.JComboBox;
-import javax.swing.JLabel;
 import javax.swing.JMenuItem;
-import javax.swing.JPanel;
 import javax.swing.JPopupMenu;
-import javax.swing.JTextField;
 import javax.swing.SwingUtilities;
-import javax.swing.text.AttributeSet;
-import javax.swing.text.BadLocationException;
-import javax.swing.text.PlainDocument;
 
 public class JvCacheableInputBox<E> extends JComboBox<String>
 {
 
   private static final long serialVersionUID = 5774610435079326695L;
 
-  private static final int INPUT_LIMIT = 2;
-
   private static final int LEFT_BOARDER_WIDTH = 16;
 
   private String cacheKey;
 
   private AppCache appCache;
 
-  private JPanel pnlDefaultCache = new JPanel();
-
-  private JLabel lblDefaultCacheSize = new JLabel();
-
-  private JTextField txtDefaultCacheSize = new JTextField();
-
   private JPopupMenu popup = new JPopupMenu();
 
   private JMenuItem menuItemClearCache = new JMenuItem();
@@ -123,8 +106,8 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
   }
 
   /**
-   * Method for initialising cache items for a given cache key and populating
-   * the in-memory cache with persisted cache items
+   * Method for initialising cache items for a given cache key and populating the
+   * in-memory cache with persisted cache items
    * 
    * @param cacheKey
    */
@@ -144,7 +127,7 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
             .getAllCachedItemsFor(cacheKey);
     if (foundCacheItems == null)
     {
-      foundCacheItems = new LinkedHashSet<String>();
+      foundCacheItems = new LinkedHashSet<>();
     }
     // populate memory cache
     for (String cacheItem : persistedCacheItems)
@@ -159,48 +142,7 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
    */
   private void initCachePopupMenu()
   {
-    pnlDefaultCache.setBackground(Color.WHITE);
-    // pad panel so as to align with other menu items
-    pnlDefaultCache.setBorder(
-            BorderFactory.createEmptyBorder(0, LEFT_BOARDER_WIDTH, 0, 0));
-    txtDefaultCacheSize.setPreferredSize(new Dimension(45, 20));
-    txtDefaultCacheSize.setFont(new java.awt.Font("Verdana", 0, 12));
-    lblDefaultCacheSize
-            .setText(MessageManager.getString("label.default_cache_size"));
-    lblDefaultCacheSize.setFont(new java.awt.Font("Verdana", 0, 12));
-    // Force input to accept only Integer entries up to length - INPUT_LIMIT
-    txtDefaultCacheSize.setDocument(new PlainDocument()
-    {
-      private static final long serialVersionUID = 1L;
-
-      @Override
-      public void insertString(int offs, String str, AttributeSet a)
-              throws BadLocationException
-      {
-        if (getLength() + str.length() <= INPUT_LIMIT && isInteger(str))
-        {
-          super.insertString(offs, str, a);
-        }
-      }
-    });
-    txtDefaultCacheSize.addKeyListener(new java.awt.event.KeyAdapter()
-    {
-      @Override
-      public void keyPressed(KeyEvent e)
-      {
-        if (e.getKeyCode() == KeyEvent.VK_ENTER)
-        {
-          e.consume();
-          updateCache();
-          closePopup();
-        }
-      }
-    });
-
-    txtDefaultCacheSize.setText(appCache.getCacheLimit(cacheKey));
-    pnlDefaultCache.add(lblDefaultCacheSize);
     menuItemClearCache.setFont(new java.awt.Font("Verdana", 0, 12));
-    pnlDefaultCache.add(txtDefaultCacheSize);
     menuItemClearCache
             .setText(MessageManager.getString("action.clear_cached_items"));
     menuItemClearCache.addActionListener(new ActionListener()
@@ -215,18 +157,11 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
       }
     });
 
-    popup.insert(pnlDefaultCache, 0);
     popup.add(menuItemClearCache);
     setComponentPopupMenu(popup);
     add(popup);
   }
 
-  private void closePopup()
-  {
-    popup.setVisible(false);
-    popup.transferFocus();
-  }
-
   /**
    * Answers true if input text is an integer
    * 
@@ -255,10 +190,7 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
       @Override
       public void run()
       {
-        int userLimit = txtDefaultCacheSize.getText().trim().isEmpty()
-                ? Integer.valueOf(AppCache.DEFAULT_LIMIT)
-                : Integer.valueOf(txtDefaultCacheSize.getText());
-        int cacheLimit = appCache.updateCacheLimit(cacheKey, userLimit);
+        int cacheLimit = Integer.parseInt(appCache.getCacheLimit(cacheKey));
         String userInput = getUserInput();
         if (userInput != null && !userInput.isEmpty())
         {
@@ -277,7 +209,7 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
           removeAllItems();
         }
         Set<String> cacheItems = appCache.getAllCachedItemsFor(cacheKey);
-        List<String> reversedCacheItems = new ArrayList<String>();
+        List<String> reversedCacheItems = new ArrayList<>();
         reversedCacheItems.addAll(cacheItems);
         cacheItems = null;
         Collections.reverse(reversedCacheItems);
@@ -326,10 +258,6 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
   public void persistCache()
   {
     appCache.persistCache(cacheKey);
-    int userLimit = txtDefaultCacheSize.getText().trim().isEmpty()
-            ? Integer.valueOf(AppCache.DEFAULT_LIMIT)
-            : Integer.valueOf(txtDefaultCacheSize.getText());
-    appCache.updateCacheLimit(cacheKey, userLimit);
   }
 
   /**
index 26e0919..6807382 100755 (executable)
@@ -264,10 +264,6 @@ public class GPreferences extends JPanel
 
   protected JCheckBox sortByTree = new JCheckBox();
 
-  /*
-   * DAS Settings tab
-   */
-  protected JPanel dasTab = new JPanel();
 
   /*
    * Web Services tab
@@ -326,12 +322,6 @@ public class GPreferences extends JPanel
             MessageManager.getString("label.editing"));
 
     /*
-     * See DasSourceBrowser for the real work of configuring this tab.
-     */
-    dasTab.setLayout(new BorderLayout());
-    tabbedPane.add(dasTab, MessageManager.getString("label.das_settings"));
-
-    /*
      * See WsPreferences for the real work of configuring this tab.
      */
     wsTab.setLayout(new BorderLayout());
index 7f1abc4..9f28ee1 100644 (file)
@@ -327,6 +327,13 @@ public class MapList
     fromHighest = Integer.MIN_VALUE;
     for (int[] range : fromRange)
     {
+      if (range.length != 2)
+      {
+        // throw new IllegalArgumentException(range);
+        System.err.println(
+                "Invalid format for fromRange " + Arrays.toString(range)
+                + " may cause errors");
+      }
       fromLowest = Math.min(fromLowest, Math.min(range[0], range[1]));
       fromHighest = Math.max(fromHighest, Math.max(range[0], range[1]));
     }
@@ -335,6 +342,13 @@ public class MapList
     toHighest = Integer.MIN_VALUE;
     for (int[] range : toRange)
     {
+      if (range.length != 2)
+      {
+        // throw new IllegalArgumentException(range);
+        System.err.println("Invalid format for toRange "
+                + Arrays.toString(range)
+                + " may cause errors");
+      }
       toLowest = Math.min(toLowest, Math.min(range[0], range[1]));
       toHighest = Math.max(toHighest, Math.max(range[0], range[1]));
     }
@@ -1203,11 +1217,20 @@ public class MapList
     for (int[] range : getToRanges())
     {
       int[] transferred = map.locateInTo(range[0], range[1]);
-      if (transferred == null)
+      if (transferred == null || transferred.length % 2 != 0)
       {
         return null;
       }
-      toRanges.add(transferred);
+
+      /*
+       *  convert [start1, end1, start2, end2, ...] 
+       *  to [[start1, end1], [start2, end2], ...]
+       */
+      for (int i = 0; i < transferred.length;)
+      {
+        toRanges.add(new int[] { transferred[i], transferred[i + 1] });
+        i += 2;
+      }
     }
 
     return new MapList(getFromRanges(), toRanges, outFromRatio, outToRatio);
index 1677eca..061e70c 100644 (file)
@@ -28,15 +28,12 @@ import jalview.datamodel.DBRefSource;
 import jalview.datamodel.Mapping;
 import jalview.datamodel.SequenceI;
 import jalview.gui.CutAndPasteTransfer;
-import jalview.gui.DasSourceBrowser;
 import jalview.gui.Desktop;
 import jalview.gui.FeatureSettings;
 import jalview.gui.IProgressIndicator;
 import jalview.gui.OOMWarning;
 import jalview.util.DBRefUtils;
 import jalview.util.MessageManager;
-import jalview.ws.dbsources.das.api.jalviewSourceI;
-import jalview.ws.dbsources.das.datamodel.DasSequenceSource;
 import jalview.ws.seqfetcher.DbSourceProxy;
 
 import java.util.ArrayList;
@@ -119,7 +116,7 @@ public class DBRefFetcher implements Runnable
           DbSourceProxy[] sources, FeatureSettings featureSettings,
           boolean isNucleotide)
   {
-    listeners = new ArrayList<FetchFinishedListenerI>();
+    listeners = new ArrayList<>();
     this.progressWindow = progressIndicatorFrame;
     alseqs = new SequenceI[seqs.length];
     SequenceI[] ds = new SequenceI[seqs.length];
@@ -165,23 +162,7 @@ public class DBRefFetcher implements Runnable
   {
     // af.featureSettings_actionPerformed(null);
     String[] defdb = null;
-    List<DbSourceProxy> selsources = new ArrayList<DbSourceProxy>();
-    Vector<jalviewSourceI> dasselsrc = (featureSettings != null)
-            ? featureSettings.getSelectedSources()
-            : new DasSourceBrowser().getSelectedSources();
-
-    for (jalviewSourceI src : dasselsrc)
-    {
-      List<DbSourceProxy> sp = src.getSequenceSourceProxies();
-      if (sp != null)
-      {
-        selsources.addAll(sp);
-        if (sp.size() > 1)
-        {
-          Cache.log.debug("Added many Db Sources for :" + src.getTitle());
-        }
-      }
-    }
+    List<DbSourceProxy> selsources = new ArrayList<>();
     // select appropriate databases based on alignFrame context.
     if (forNucleotide)
     {
@@ -191,7 +172,7 @@ public class DBRefFetcher implements Runnable
     {
       defdb = DBRefSource.PROTEINDBS;
     }
-    List<DbSourceProxy> srces = new ArrayList<DbSourceProxy>();
+    List<DbSourceProxy> srces = new ArrayList<>();
     for (String ddb : defdb)
     {
       List<DbSourceProxy> srcesfordb = sfetcher.getSourceProxy(ddb);
@@ -235,30 +216,6 @@ public class DBRefFetcher implements Runnable
   }
 
   /**
-   * retrieve all the das sequence sources and add them to the list of db
-   * sources to retrieve from
-   */
-  public void appendAllDasSources()
-  {
-    if (dbSources == null)
-    {
-      dbSources = new DbSourceProxy[0];
-    }
-    // append additional sources
-    DbSourceProxy[] otherdb = sfetcher
-            .getDbSourceProxyInstances(DasSequenceSource.class);
-    if (otherdb != null && otherdb.length > 0)
-    {
-      DbSourceProxy[] newsrc = new DbSourceProxy[dbSources.length
-              + otherdb.length];
-      System.arraycopy(dbSources, 0, newsrc, 0, dbSources.length);
-      System.arraycopy(otherdb, 0, newsrc, dbSources.length,
-              otherdb.length);
-      dbSources = newsrc;
-    }
-  }
-
-  /**
    * start the fetcher thread
    * 
    * @param waitTillFinished
@@ -311,14 +268,14 @@ public class DBRefFetcher implements Runnable
       }
       else if (seqs == null)
       {
-        seqs = new Vector<SequenceI>();
+        seqs = new Vector<>();
         seqs.addElement(seq);
       }
 
     }
     else
     {
-      seqs = new Vector<SequenceI>();
+      seqs = new Vector<>();
       seqs.addElement(seq);
     }
 
@@ -357,9 +314,9 @@ public class DBRefFetcher implements Runnable
       e.printStackTrace();
     }
 
-    Vector<SequenceI> sdataset = new Vector<SequenceI>(
+    Vector<SequenceI> sdataset = new Vector<>(
             Arrays.asList(dataset));
-    List<String> warningMessages = new ArrayList<String>();
+    List<String> warningMessages = new ArrayList<>();
 
     int db = 0;
     while (sdataset.size() > 0 && db < dbSources.length)
@@ -371,8 +328,8 @@ public class DBRefFetcher implements Runnable
       SequenceI[] currSeqs = new SequenceI[sdataset.size()];
       sdataset.copyInto(currSeqs);// seqs that are to be validated against
       // dbSources[db]
-      Vector<String> queries = new Vector<String>(); // generated queries curSeq
-      seqRefs = new Hashtable<String, Vector<SequenceI>>();
+      Vector<String> queries = new Vector<>(); // generated queries curSeq
+      seqRefs = new Hashtable<>();
 
       int seqIndex = 0;
 
@@ -574,7 +531,7 @@ public class DBRefFetcher implements Runnable
     {
       // Work out which sequences this sequence matches,
       // taking into account all accessionIds and names in the file
-      Vector<SequenceI> sequenceMatches = new Vector<SequenceI>();
+      Vector<SequenceI> sequenceMatches = new Vector<>();
       // look for corresponding accession ids
       DBRefEntry[] entryRefs = DBRefUtils
               .selectRefs(retrievedSeq.getDBRefs(), new String[]
@@ -826,7 +783,7 @@ public class DBRefFetcher implements Runnable
    */
   private SequenceI[] recoverDbSequences(SequenceI[] sequencesArray)
   {
-    Vector<SequenceI> nseq = new Vector<SequenceI>();
+    Vector<SequenceI> nseq = new Vector<>();
     for (int i = 0; sequencesArray != null
             && i < sequencesArray.length; i++)
     {
diff --git a/src/jalview/ws/DasSequenceFeatureFetcher.java b/src/jalview/ws/DasSequenceFeatureFetcher.java
deleted file mode 100644 (file)
index c661e2c..0000000
+++ /dev/null
@@ -1,925 +0,0 @@
-/*
- * 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.ws;
-
-import jalview.bin.Cache;
-import jalview.datamodel.DBRefEntry;
-import jalview.datamodel.DBRefSource;
-import jalview.datamodel.SequenceFeature;
-import jalview.datamodel.SequenceI;
-import jalview.gui.AlignFrame;
-import jalview.gui.Desktop;
-import jalview.gui.FeatureSettings;
-import jalview.gui.JvOptionPane;
-import jalview.util.DBRefUtils;
-import jalview.util.MessageManager;
-import jalview.util.UrlLink;
-import jalview.ws.dbsources.das.api.DasSourceRegistryI;
-import jalview.ws.dbsources.das.api.jalviewSourceI;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.Vector;
-
-import org.biodas.jdas.client.FeaturesClient;
-import org.biodas.jdas.client.adapters.features.DasGFFAdapter;
-import org.biodas.jdas.client.adapters.features.DasGFFAdapter.GFFAdapter;
-import org.biodas.jdas.client.threads.FeaturesClientMultipleSources;
-import org.biodas.jdas.schema.features.ERRORSEGMENT;
-import org.biodas.jdas.schema.features.FEATURE;
-import org.biodas.jdas.schema.features.LINK;
-import org.biodas.jdas.schema.features.SEGMENT;
-import org.biodas.jdas.schema.features.TYPE;
-import org.biodas.jdas.schema.features.UNKNOWNFEATURE;
-import org.biodas.jdas.schema.features.UNKNOWNSEGMENT;
-import org.biodas.jdas.schema.sources.COORDINATES;
-
-/**
- * DOCUMENT ME!
- * 
- * @author $author$
- * @version $Revision$
- */
-public class DasSequenceFeatureFetcher
-{
-  SequenceI[] sequences;
-
-  AlignFrame af;
-
-  FeatureSettings fsettings;
-
-  StringBuffer sbuffer = new StringBuffer();
-
-  List<jalviewSourceI> selectedSources;
-
-  boolean cancelled = false;
-
-  private void debug(String mesg)
-  {
-    debug(mesg, null);
-  }
-
-  private void debug(String mesg, Exception e)
-  {
-    if (Cache.log != null)
-    {
-      Cache.log.debug(mesg, e);
-    }
-    else
-    {
-      System.err.println(mesg);
-      if (e != null)
-      {
-        e.printStackTrace();
-      }
-    }
-  }
-
-  long startTime;
-
-  private DasSourceRegistryI sourceRegistry;
-
-  private boolean useJDASMultiThread = true;
-
-  /**
-   * Creates a new SequenceFeatureFetcher object. Uses default
-   * 
-   * @param align
-   *          DOCUMENT ME!
-   * @param ap
-   *          DOCUMENT ME!
-   */
-  public DasSequenceFeatureFetcher(SequenceI[] sequences,
-          FeatureSettings fsettings, Vector selectedSources)
-  {
-    this(sequences, fsettings, selectedSources, true, true, true);
-  }
-
-  public DasSequenceFeatureFetcher(SequenceI[] oursequences,
-          FeatureSettings fsettings, List<jalviewSourceI> selectedSources2,
-          boolean checkDbrefs, boolean promptFetchDbrefs)
-  {
-    this(oursequences, fsettings, selectedSources2, checkDbrefs,
-            promptFetchDbrefs, true);
-  }
-
-  public DasSequenceFeatureFetcher(SequenceI[] oursequences,
-          FeatureSettings fsettings, List<jalviewSourceI> selectedSources2,
-          boolean checkDbrefs, boolean promptFetchDbrefs,
-          boolean useJDasMultiThread)
-  {
-    this.useJDASMultiThread = useJDasMultiThread;
-    this.selectedSources = new ArrayList<>();
-    // filter both sequences and sources to eliminate duplicates
-    for (jalviewSourceI src : selectedSources2)
-    {
-      if (!selectedSources.contains(src))
-      {
-        selectedSources.add(src);
-      }
-      ;
-    }
-    Vector sqs = new Vector();
-    for (int i = 0; i < oursequences.length; i++)
-    {
-      if (!sqs.contains(oursequences[i]))
-      {
-        sqs.addElement(oursequences[i]);
-      }
-    }
-    sequences = new SequenceI[sqs.size()];
-    for (int i = 0; i < sequences.length; i++)
-    {
-      sequences[i] = (SequenceI) sqs.elementAt(i);
-    }
-    if (fsettings != null)
-    {
-      this.fsettings = fsettings;
-      this.af = fsettings.af;
-      af.setShowSeqFeatures(true);
-    }
-    int uniprotCount = 0;
-    for (jalviewSourceI source : selectedSources)
-    {
-      for (COORDINATES coords : source.getVersion().getCOORDINATES())
-      {
-        // TODO: match UniProt coord system canonically (?) - does
-        // UniProt==uniprot==UNIPROT ?
-        if (coords.getAuthority().toLowerCase().equals("uniprot"))
-        {
-          uniprotCount++;
-          break;
-        }
-      }
-    }
-
-    int refCount = 0;
-    for (int i = 0; i < sequences.length; i++)
-    {
-      DBRefEntry[] dbref = sequences[i].getDBRefs();
-      if (dbref != null)
-      {
-        for (int j = 0; j < dbref.length; j++)
-        {
-          if (dbref[j].getSource().equals(DBRefSource.UNIPROT))
-          {
-            refCount++;
-            break;
-          }
-        }
-      }
-    }
-
-    if (checkDbrefs && refCount < sequences.length && uniprotCount > 0)
-    {
-
-      int reply = JvOptionPane.YES_OPTION;
-      if (promptFetchDbrefs)
-      {
-        reply = JvOptionPane.showInternalConfirmDialog(Desktop.desktop,
-                MessageManager.getString(
-                        "info.you_want_jalview_to_find_uniprot_accessions"),
-                MessageManager
-                        .getString("label.find_uniprot_accession_ids"),
-                JvOptionPane.YES_NO_OPTION, JvOptionPane.QUESTION_MESSAGE);
-      }
-
-      if (reply == JvOptionPane.YES_OPTION)
-      {
-        Thread thread = new Thread(new FetchDBRefs());
-        thread.start();
-      }
-      else
-      {
-        _startFetching();
-      }
-    }
-    else
-    {
-      _startFetching();
-    }
-
-  }
-
-  private void _startFetching()
-  {
-    running = true;
-    new Thread(new FetchSeqFeatures()).start();
-  }
-
-  class FetchSeqFeatures implements Runnable
-  {
-    @Override
-    public void run()
-    {
-      startFetching();
-      setGuiFetchComplete();
-    }
-  }
-
-  class FetchDBRefs implements Runnable
-  {
-    @Override
-    public void run()
-    {
-      running = true;
-      boolean isNucleotide = af.getViewport().getAlignment().isNucleotide();
-      new DBRefFetcher(sequences, af, null, af.featureSettings,
-              isNucleotide).fetchDBRefs(true);
-
-      startFetching();
-      setGuiFetchComplete();
-    }
-  }
-
-  /**
-   * Spawns Fetcher threads to add features to sequences in the dataset
-   */
-  void startFetching()
-  {
-    running = true;
-    cancelled = false;
-    startTime = System.currentTimeMillis();
-    if (af != null)
-    {
-      af.setProgressBar(MessageManager.getString(
-              "status.fetching_das_sequence_features"), startTime);
-    }
-    if (sourceRegistry == null)
-    {
-      sourceRegistry = Cache.getDasSourceRegistry();
-    }
-    if (selectedSources == null || selectedSources.size() == 0)
-    {
-      try
-      {
-        jalviewSourceI[] sources = sourceRegistry.getSources()
-                .toArray(new jalviewSourceI[0]);
-        String active = Cache.getDefault("DAS_ACTIVE_SOURCE", "uniprot");
-        StringTokenizer st = new StringTokenizer(active, "\t");
-        selectedSources = new Vector();
-        String token;
-        while (st.hasMoreTokens())
-        {
-          token = st.nextToken();
-          for (int i = 0; i < sources.length; i++)
-          {
-            if (sources[i].getTitle().equals(token))
-            {
-              selectedSources.add(sources[i]);
-              break;
-            }
-          }
-        }
-      } catch (Exception ex)
-      {
-        debug("Exception whilst setting default feature sources from registry and local preferences.",
-                ex);
-      }
-    }
-
-    if (selectedSources == null || selectedSources.size() == 0)
-    {
-      System.out.println("No DAS Sources active");
-      cancelled = true;
-      setGuiNoDassourceActive();
-      return;
-    }
-
-    sourcesRemaining = selectedSources.size();
-    FeaturesClientMultipleSources fc = new FeaturesClientMultipleSources();
-    fc.setConnProps(sourceRegistry.getSessionHandler());
-    // Now sending requests one at a time to each server
-    ArrayList<jalviewSourceI> srcobj = new ArrayList<>();
-    ArrayList<String> src = new ArrayList<>();
-    List<List<String>> ids = new ArrayList<>();
-    List<List<DBRefEntry>> idobj = new ArrayList<>();
-    List<Map<String, SequenceI>> sqset = new ArrayList<>();
-    for (jalviewSourceI _sr : selectedSources)
-    {
-
-      Map<String, SequenceI> slist = new HashMap<>();
-      List<DBRefEntry> idob = new ArrayList<>();
-      List<String> qset = new ArrayList<>();
-
-      for (SequenceI seq : sequences)
-      {
-        Object[] idset = nextSequence(_sr, seq);
-        if (idset != null)
-        {
-          List<DBRefEntry> _idob = (List<DBRefEntry>) idset[0];
-          List<String> _qset = (List<String>) idset[1];
-          if (_idob.size() > 0)
-          {
-            // add sequence's ref for each id derived from it
-            // (space inefficient, but most unambiguous)
-            // could replace with hash with _qset values as keys.
-            Iterator<DBRefEntry> dbobj = _idob.iterator();
-            for (String q : _qset)
-            {
-              SequenceI osq = slist.get(q);
-              DBRefEntry dr = dbobj.next();
-              if (osq != null && osq != seq)
-              {
-                // skip - non-canonical query
-              }
-              else
-              {
-                idob.add(dr);
-                qset.add(q);
-                slist.put(q, seq);
-              }
-            }
-          }
-        }
-      }
-      if (idob.size() > 0)
-      {
-        srcobj.add(_sr);
-        src.add(_sr.getSourceURL());
-        ids.add(qset);
-        idobj.add(idob);
-        sqset.add(slist);
-      }
-    }
-    Map<String, Map<List<String>, Exception>> errors = new HashMap<>();
-    Map<String, Map<List<String>, DasGFFAdapter>> results = new HashMap<>();
-    if (!useJDASMultiThread)
-    {
-      Iterator<String> sources = src.iterator();
-      // iterate over each query for each source and do each one individually
-      for (List<String> idl : ids)
-      {
-        String source = sources.next();
-        FeaturesClient featuresc = new FeaturesClient(
-                sourceRegistry.getSessionHandler()
-                        .getConnectionPropertyProviderFor(source));
-        for (String id : idl)
-        {
-          List<String> qid = Arrays.asList(new String[] { id });
-          try
-          {
-            DasGFFAdapter dga = featuresc.fetchData(source, qid);
-            Map<List<String>, DasGFFAdapter> ers = results.get(source);
-            if (ers == null)
-            {
-              results.put(source,
-                      ers = new HashMap<>());
-            }
-            ers.put(qid, dga);
-          } catch (Exception ex)
-          {
-            Map<List<String>, Exception> ers = errors.get(source);
-            if (ers == null)
-            {
-              errors.put(source,
-                      ers = new HashMap<>());
-            }
-            ers.put(qid, ex);
-          }
-        }
-      }
-    }
-    else
-    {
-      // pass them all at once
-      fc.fetchData(src, ids, false, results, errors);
-      fc.shutDown();
-      while (!fc.isTerminated())
-      {
-        try
-        {
-          Thread.sleep(200);
-        } catch (InterruptedException x)
-        {
-
-        }
-      }
-    }
-    Iterator<List<String>> idset = ids.iterator();
-    Iterator<List<DBRefEntry>> idobjset = idobj.iterator();
-    Iterator<Map<String, SequenceI>> seqset = sqset.iterator();
-    for (jalviewSourceI source : srcobj)
-    {
-      processResponse(seqset.next(), source, idset.next(), idobjset.next(),
-              results.get(source.getSourceURL()),
-              errors.get(source.getSourceURL()));
-    }
-  }
-
-  private void processResponse(Map<String, SequenceI> sequencemap,
-          jalviewSourceI jvsource, List<String> ids, List<DBRefEntry> idobj,
-          Map<List<String>, DasGFFAdapter> results,
-          Map<List<String>, Exception> errors)
-  {
-    Set<SequenceI> sequences = new HashSet<>();
-    String source = jvsource.getSourceURL();
-    // process features
-    DasGFFAdapter result = (results == null) ? null : results.get(ids);
-    Exception error = (errors == null) ? null : errors.get(ids);
-    if (result == null)
-    {
-      debug("das source " + source + " could not be contacted. "
-              + (error == null ? "" : error.toString()));
-    }
-    else
-    {
-
-      GFFAdapter gff = result.getGFF();
-      List<SEGMENT> segments = gff.getSegments();
-      List<ERRORSEGMENT> errorsegs = gff.getErrorSegments();
-      List<UNKNOWNFEATURE> unkfeats = gff.getUnknownFeatures();
-      List<UNKNOWNSEGMENT> unksegs = gff.getUnknownSegments();
-      debug("das source " + source + " returned " + gff.getTotal()
-              + " responses. " + (errorsegs != null ? errorsegs.size() : 0)
-              + " were incorrect segment queries, "
-              + (unkfeats != null ? unkfeats.size() : 0)
-              + " were unknown features "
-              + (unksegs != null ? unksegs.size() : 0)
-              + " were unknown segments and "
-              + (segments != null ? segments.size() : 0)
-              + " were segment responses.");
-      Iterator<DBRefEntry> dbr = idobj.iterator();
-      if (segments != null)
-      {
-        for (SEGMENT seg : segments)
-        {
-          String id = seg.getId();
-          if (ids.indexOf(id) == -1)
-          {
-            id = id.toUpperCase();
-          }
-          DBRefEntry dbref = idobj.get(ids.indexOf(id));
-          SequenceI sequence = sequencemap.get(id);
-          boolean added = false;
-          sequences.add(sequence);
-
-          for (FEATURE feat : seg.getFEATURE())
-          {
-            // standard DAS feature-> jalview sequence feature transformation
-            SequenceFeature f = newSequenceFeature(feat,
-                    jvsource.getTitle());
-            if (!parseSeqFeature(sequence, f, feat, jvsource))
-            {
-              if (dbref.getMap() != null && f.getBegin() > 0
-                      && f.getEnd() > 0)
-              {
-                debug("mapping from " + f.getBegin() + " - " + f.getEnd());
-                SequenceFeature vf[] = null;
-
-                try
-                {
-                  vf = dbref.getMap().locateFeature(f);
-                } catch (Exception ex)
-                {
-                  Cache.log.warn(
-                          "Error in 'experimental' mapping of features. Please try to reproduce and then report info to jalview-discuss@jalview.org.");
-                  Cache.log.warn("Mapping feature from " + f.getBegin()
-                          + " to " + f.getEnd() + " in dbref "
-                          + dbref.getAccessionId() + " in "
-                          + dbref.getSource());
-                  Cache.log.warn("using das Source " + source);
-                  Cache.log.warn("Exception", ex);
-                }
-
-                if (vf != null)
-                {
-                  for (int v = 0; v < vf.length; v++)
-                  {
-                    debug("mapping to " + v + ": " + vf[v].getBegin()
-                            + " - " + vf[v].getEnd());
-                    sequence.addSequenceFeature(vf[v]);
-                  }
-                }
-              }
-              else
-              {
-                sequence.addSequenceFeature(f);
-              }
-            }
-          }
-        }
-        featuresAdded(sequences);
-      }
-      else
-      {
-        // System.out.println("No features found for " + seq.getName()
-        // + " from: " + e.getDasSource().getNickname());
-      }
-    }
-  }
-
-  private void setGuiNoDassourceActive()
-  {
-
-    if (af != null)
-    {
-      af.setProgressBar(
-              MessageManager.getString("status.no_das_sources_active"),
-              startTime);
-    }
-    if (getFeatSettings() != null)
-    {
-      fsettings.noDasSourceActive();
-    }
-  }
-
-  /**
-   * Update our fsettings dialog reference if we didn't have one when we were
-   * first initialised.
-   * 
-   * @return fsettings
-   */
-  private FeatureSettings getFeatSettings()
-  {
-    if (fsettings == null)
-    {
-      if (af != null)
-      {
-        fsettings = af.featureSettings;
-      }
-    }
-    return fsettings;
-  }
-
-  public void cancel()
-  {
-    if (af != null)
-    {
-      af.setProgressBar(MessageManager.getString(
-              "status.das_feature_fetching_cancelled"), startTime);
-    }
-    cancelled = true;
-  }
-
-  int sourcesRemaining = 0;
-
-  private boolean running = false;
-
-  private void setGuiFetchComplete()
-  {
-    running = false;
-    if (!cancelled && af != null)
-    {
-      // only update the progress bar if we've completed the fetch normally
-      af.setProgressBar(MessageManager.getString(
-              "status.das_feature_fetching_complete"), startTime);
-    }
-
-    if (af != null && af.featureSettings != null)
-    {
-      af.featureSettings.discoverAllFeatureData();
-    }
-
-    if (getFeatSettings() != null)
-    {
-      fsettings.complete();
-    }
-  }
-
-  void featuresAdded(Set<SequenceI> seqs)
-  {
-    if (af == null)
-    {
-      // no gui to update with features.
-      return;
-    }
-    af.getFeatureRenderer().featuresAdded();
-
-    int start = af.getViewport().getRanges().getStartSeq();
-    int end = af.getViewport().getRanges().getEndSeq();
-    int index;
-    for (index = start; index < end; index++)
-    {
-      for (SequenceI seq : seqs)
-      {
-        if (seq == af.getViewport().getAlignment().getSequenceAt(index)
-                .getDatasetSequence())
-        {
-          af.alignPanel.paintAlignment(true, true);
-          index = end;
-          break;
-        }
-      }
-    }
-  }
-
-  Object[] nextSequence(jalviewSourceI dasSource, SequenceI seq)
-  {
-    if (cancelled)
-    {
-      return null;
-    }
-    DBRefEntry[] uprefs = DBRefUtils.selectRefs(seq.getDBRefs(),
-            new String[]
-            {
-                // jalview.datamodel.DBRefSource.PDB,
-                DBRefSource.UNIPROT,
-            // jalview.datamodel.DBRefSource.EMBL - not tested on any EMBL coord
-            // sys sources
-            });
-    // TODO: minimal list of DAS queries to make by querying with untyped ID if
-    // distinct from any typed IDs
-
-    List<DBRefEntry> ids = new ArrayList<>();
-    List<String> qstring = new ArrayList<>();
-    boolean dasCoordSysFound = false;
-
-    if (uprefs != null)
-    {
-      // do any of these ids match the source's coordinate system ?
-      for (int j = 0; !dasCoordSysFound && j < uprefs.length; j++)
-      {
-
-        for (COORDINATES csys : dasSource.getVersion().getCOORDINATES())
-        {
-          if (DBRefUtils.isDasCoordinateSystem(csys.getAuthority(),
-                  uprefs[j]))
-          {
-            debug("Launched fetcher for coordinate system "
-                    + csys.getAuthority());
-            // Will have to pass any mapping information to the fetcher
-            // - the start/end for the DBRefEntry may not be the same as the
-            // sequence's start/end
-
-            System.out.println(
-                    seq.getName() + " " + (seq.getDatasetSequence() == null)
-                            + " " + csys.getUri());
-
-            dasCoordSysFound = true; // break's out of the loop
-            ids.add(uprefs[j]);
-            qstring.add(uprefs[j].getAccessionId());
-          }
-          else
-          {
-            System.out.println("IGNORE " + csys.getAuthority());
-          }
-        }
-      }
-    }
-
-    if (!dasCoordSysFound)
-    {
-      String id = null;
-      // try and use the name as the sequence id
-      if (seq.getName().indexOf("|") > -1)
-      {
-        id = seq.getName().substring(seq.getName().lastIndexOf("|") + 1);
-        if (id.trim().length() < 4)
-        {
-          // hack - we regard a significant ID as being at least 4
-          // non-whitespace characters
-          id = seq.getName().substring(0, seq.getName().lastIndexOf("|"));
-          if (id.indexOf("|") > -1)
-          {
-            id = id.substring(id.lastIndexOf("|") + 1);
-          }
-        }
-      }
-      else
-      {
-        id = seq.getName();
-      }
-      if (id != null)
-      {
-        DBRefEntry dbre = new DBRefEntry();
-        dbre.setAccessionId(id);
-        // Should try to call a general feature fetcher that
-        // queries many sources with name to discover applicable ID references
-        ids.add(dbre);
-        qstring.add(dbre.getAccessionId());
-      }
-    }
-
-    return new Object[] { ids, qstring };
-  }
-
-  /**
-   * examine the given sequence feature to determine if it should actually be
-   * turned into sequence annotation or database cross references rather than a
-   * simple sequence feature.
-   * 
-   * @param seq
-   *          the sequence to annotate
-   * @param f
-   *          the jalview sequence feature generated from the DAS feature
-   * @param map
-   *          the sequence feature attributes
-   * @param source
-   *          the source that emitted the feature
-   * @return true if feature was consumed as another kind of annotation.
-   */
-  protected boolean parseSeqFeature(SequenceI seq, SequenceFeature f,
-          FEATURE feature, jalviewSourceI source)
-  {
-    SequenceI mseq = seq;
-    while (seq.getDatasetSequence() != null)
-    {
-      seq = seq.getDatasetSequence();
-    }
-    if (f.getType() != null)
-    {
-      String type = f.getType();
-      if (type.equalsIgnoreCase("protein_name"))
-      {
-        // parse name onto the alignment sequence or the dataset sequence.
-        if (seq.getDescription() == null
-                || seq.getDescription().trim().length() == 0)
-        {
-          // could look at the note series to pick out the first long name, for
-          // the moment just use the whole description string
-          seq.setDescription(f.getDescription());
-        }
-        if (mseq.getDescription() == null
-                || mseq.getDescription().trim().length() == 0)
-        {
-          // could look at the note series to pick out the first long name, for
-          // the moment just use the whole description string
-          mseq.setDescription(f.getDescription());
-        }
-        return true;
-      }
-      // check if source has biosapiens or other sequence ontology label
-      if (type.equalsIgnoreCase("DBXREF") || type.equalsIgnoreCase("DBREF"))
-      {
-        // try to parse the accession out
-
-        DBRefEntry dbr = new DBRefEntry();
-        dbr.setVersion(source.getTitle());
-        StringTokenizer st = new StringTokenizer(f.getDescription(), ":");
-        if (st.hasMoreTokens())
-        {
-          dbr.setSource(st.nextToken());
-        }
-        if (st.hasMoreTokens())
-        {
-          dbr.setAccessionId(st.nextToken());
-        }
-        seq.addDBRef(dbr);
-
-        if (f.links != null && f.links.size() > 0)
-        {
-          // feature is also appended to enable links to be seen.
-          // TODO: consider extending dbrefs to have their own links ?
-          // TODO: new feature: extract dbref links from DAS servers and add the
-          // URL pattern to the list of DB name associated links in the user's
-          // preferences ?
-          // for the moment - just fix up the existing feature so it displays
-          // correctly.
-          // f.setType(dbr.getSource());
-          // f.setDescription();
-          f.setValue("linkonly", Boolean.TRUE);
-          // f.setDescription("");
-          Vector newlinks = new Vector();
-          Enumeration it = f.links.elements();
-          while (it.hasMoreElements())
-          {
-            String elm;
-            UrlLink urllink = new UrlLink(elm = (String) it.nextElement());
-            if (urllink.isValid())
-            {
-              urllink.setLabel(f.getDescription());
-              newlinks.addElement(urllink.toString());
-            }
-            else
-            {
-              // couldn't parse the link properly. Keep it anyway - just in
-              // case.
-              debug("couldn't parse link string - " + elm);
-              newlinks.addElement(elm);
-            }
-          }
-          f.links = newlinks;
-          seq.addSequenceFeature(f);
-        }
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /**
-   * creates a jalview sequence feature from a das feature document
-   * 
-   * @param feat
-   * @return sequence feature object created using dasfeature information
-   */
-  SequenceFeature newSequenceFeature(FEATURE feat, String nickname)
-  {
-    if (feat == null)
-    {
-      return null;
-    }
-    try
-    {
-      /**
-       * Different qNames for a DAS Feature - are string keys to the HashMaps in
-       * features "METHOD") || qName.equals("TYPE") || qName.equals("START") ||
-       * qName.equals("END") || qName.equals("NOTE") || qName.equals("LINK") ||
-       * qName.equals("SCORE")
-       */
-      String desc = new String();
-      if (feat.getNOTE() != null)
-      {
-        for (String note : feat.getNOTE())
-        {
-          desc += note;
-        }
-      }
-
-      int start = 0, end = 0;
-      float score = 0f;
-
-      try
-      {
-        start = Integer.parseInt(feat.getSTART().toString());
-      } catch (Exception ex)
-      {
-      }
-      try
-      {
-        end = Integer.parseInt(feat.getEND().toString());
-      } catch (Exception ex)
-      {
-      }
-      try
-      {
-        Object scr = feat.getSCORE();
-        if (scr != null)
-        {
-          score = (float) Double.parseDouble(scr.toString());
-
-        }
-      } catch (Exception ex)
-      {
-      }
-
-      SequenceFeature f = new SequenceFeature(getTypeString(feat.getTYPE()),
-              desc, start, end, score, nickname);
-
-      if (feat.getLINK() != null)
-      {
-        for (LINK link : feat.getLINK())
-        {
-          // Do not put feature extent in link text for non-positional features
-          if (f.begin == 0 && f.end == 0)
-          {
-            f.addLink(f.getType() + " " + link.getContent() + "|"
-                    + link.getHref());
-          }
-          else
-          {
-            f.addLink(f.getType() + " " + f.begin + "_" + f.end + " "
-                    + link.getContent() + "|" + link.getHref());
-          }
-        }
-      }
-
-      return f;
-    } catch (Exception e)
-    {
-      System.out.println("ERRR " + e);
-      e.printStackTrace();
-      System.out.println("############");
-      debug("Failed to parse " + feat.toString(), e);
-      return null;
-    }
-  }
-
-  private String getTypeString(TYPE type)
-  {
-    return type.getContent();
-  }
-
-  public boolean isRunning()
-  {
-    return running;
-  }
-
-}
index a0b77de..29d4ec7 100644 (file)
@@ -29,12 +29,10 @@ import jalview.ws.dbsources.PfamFull;
 import jalview.ws.dbsources.PfamSeed;
 import jalview.ws.dbsources.RfamSeed;
 import jalview.ws.dbsources.Uniprot;
-import jalview.ws.dbsources.das.api.jalviewSourceI;
 import jalview.ws.seqfetcher.ASequenceFetcher;
 import jalview.ws.seqfetcher.DbSourceProxy;
 
 import java.util.ArrayList;
-import java.util.List;
 
 /**
  * This implements the run-time discovery of sequence database clients.
@@ -50,11 +48,6 @@ public class SequenceFetcher extends ASequenceFetcher
    */
   public SequenceFetcher()
   {
-    this(true);
-  }
-
-  public SequenceFetcher(boolean addDas)
-  {
     addDBRefSourceImpl(EnsemblGene.class);
     addDBRefSourceImpl(EnsemblGenomes.class);
     addDBRefSourceImpl(EmblSource.class);
@@ -64,26 +57,19 @@ public class SequenceFetcher extends ASequenceFetcher
     addDBRefSourceImpl(PfamFull.class);
     addDBRefSourceImpl(PfamSeed.class);
     addDBRefSourceImpl(RfamSeed.class);
-
-    if (addDas)
-    {
-      registerDasSequenceSources();
-    }
   }
 
   /**
-   * return an ordered list of database sources where non-das database classes
-   * appear before das database classes
+   * return an ordered list of database sources excluding alignment only databases
    */
   public String[] getOrderedSupportedSources()
   {
     String[] srcs = this.getSupportedDb();
-    ArrayList<String> dassrc = new ArrayList<String>(),
-            nondas = new ArrayList<String>();
+    ArrayList<String> src = new ArrayList<>();
+
     for (int i = 0; i < srcs.length; i++)
     {
-      boolean das = false, skip = false;
-      String nm;
+      boolean skip = false;
       for (DbSourceProxy dbs : getSourceProxy(srcs[i]))
       {
         // Skip the alignment databases for the moment - they're not useful for
@@ -92,86 +78,28 @@ public class SequenceFetcher extends ASequenceFetcher
         {
           skip = true;
         }
-        else
-        {
-          nm = dbs.getDbName();
-          if (getSourceProxy(
-                  srcs[i]) instanceof jalview.ws.dbsources.das.datamodel.DasSequenceSource)
-          {
-            if (nm.startsWith("das:"))
-            {
-              nm = nm.substring(4);
-              das = true;
-            }
-            break;
-          }
-        }
       }
       if (skip)
       {
         continue;
       }
-      if (das)
       {
-        dassrc.add(srcs[i]);
-      }
-      else
-      {
-        nondas.add(srcs[i]);
+        src.add(srcs[i]);
       }
     }
-    String[] tosort = nondas.toArray(new String[0]),
-            sorted = nondas.toArray(new String[0]);
+    String[] tosort = src.toArray(new String[0]),
+            sorted = src.toArray(new String[0]);
     for (int j = 0, jSize = sorted.length; j < jSize; j++)
     {
       tosort[j] = tosort[j].toLowerCase();
     }
     jalview.util.QuickSort.sort(tosort, sorted);
     // construct array with all sources listed
-
-    srcs = new String[sorted.length + dassrc.size()];
     int i = 0;
     for (int j = sorted.length - 1; j >= 0; j--, i++)
     {
       srcs[i] = sorted[j];
-      sorted[j] = null;
-    }
-
-    sorted = dassrc.toArray(new String[0]);
-    tosort = dassrc.toArray(new String[0]);
-    for (int j = 0, jSize = sorted.length; j < jSize; j++)
-    {
-      tosort[j] = tosort[j].toLowerCase();
-    }
-    jalview.util.QuickSort.sort(tosort, sorted);
-    for (int j = sorted.length - 1; j >= 0; j--, i++)
-    {
-      srcs[i] = sorted[j];
     }
     return srcs;
   }
-
-  /**
-   * query the currently defined DAS source registry for sequence sources and
-   * add a DasSequenceSource instance for each source to the SequenceFetcher
-   * source list.
-   */
-  public void registerDasSequenceSources()
-  {
-    // TODO: define a context as a registry provider (either desktop,
-    // jalview.bin.cache, or something else).
-    for (jalviewSourceI source : jalview.bin.Cache.getDasSourceRegistry()
-            .getSources())
-    {
-      if (source.isSequenceSource())
-      {
-        List<DbSourceProxy> dassources = source.getSequenceSourceProxies();
-        for (DbSourceProxy seqsrc : dassources)
-        {
-          addDbRefSourceImpl(seqsrc);
-        }
-      }
-    }
-  }
-
 }
index 6b09eb6..167cd97 100644 (file)
@@ -32,6 +32,8 @@ import jalview.datamodel.SequenceI;
 import jalview.datamodel.xdb.uniprot.UniprotEntry;
 import jalview.datamodel.xdb.uniprot.UniprotFeature;
 import jalview.datamodel.xdb.uniprot.UniprotFile;
+import jalview.schemes.ResidueProperties;
+import jalview.util.StringUtils;
 import jalview.ws.seqfetcher.DbSourceProxyImpl;
 
 import java.io.InputStream;
@@ -40,6 +42,7 @@ import java.io.Reader;
 import java.net.URL;
 import java.net.URLConnection;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Vector;
 
 import org.exolab.castor.mapping.Mapping;
@@ -278,7 +281,7 @@ public class Uniprot extends DbSourceProxyImpl
       for (UniprotFeature uf : entry.getFeature())
       {
         SequenceFeature copy = new SequenceFeature(uf.getType(),
-                uf.getDescription(), uf.getBegin(), uf.getEnd(), "Uniprot");
+                getDescription(uf), uf.getBegin(), uf.getEnd(), "Uniprot");
         copy.setStatus(uf.getStatus());
         sequence.addSequenceFeature(copy);
       }
@@ -291,6 +294,94 @@ public class Uniprot extends DbSourceProxyImpl
   }
 
   /**
+   * Constructs a feature description from the description and (optionally)
+   * original and variant fields of the Uniprot XML feature
+   * 
+   * @param uf
+   * @return
+   */
+  protected static String getDescription(UniprotFeature uf)
+  {
+    String orig = uf.getOriginal();
+    List<String> variants = uf.getVariation();
+    StringBuilder sb = new StringBuilder();
+
+    /*
+     * append variant in standard format if present
+     * e.g. p.Arg59Lys
+     * multiple variants are split over lines using <br>
+     */
+    boolean asHtml = false;
+    if (orig != null && !orig.isEmpty() && variants != null
+            && !variants.isEmpty())
+    {
+      int p = 0;
+      for (String var : variants)
+      {
+        // TODO proper HGVS nomenclature for delins structural variations
+        // http://varnomen.hgvs.org/recommendations/protein/variant/delins/
+        // for now we are pragmatic - any orig/variant sequence longer than
+        // three characters is shown with single-character notation rather than
+        // three-letter notation
+        sb.append("p.");
+        if (orig.length() < 4)
+        {
+          for (int c = 0, clen = orig.length(); c < clen; c++)
+          {
+            char origchar = orig.charAt(c);
+            String orig3 = ResidueProperties.aa2Triplet.get("" + origchar);
+            sb.append(orig3 == null ? origchar
+                    : StringUtils.toSentenceCase(orig3));
+          }
+        }
+        else
+        {
+          sb.append(orig);
+        }
+
+        sb.append(Integer.toString(uf.getPosition()));
+
+        if (var.length() < 4)
+        {
+          for (int c = 0, clen = var.length(); c < clen; c++)
+          {
+            char varchar = var.charAt(c);
+            String var3 = ResidueProperties.aa2Triplet.get("" + varchar);
+
+            sb.append(var3 != null ? StringUtils.toSentenceCase(var3)
+                    : "" + varchar);
+          }
+        }
+        else
+        {
+          sb.append(var);
+        }
+        if (++p != variants.size())
+        {
+          sb.append("<br/>&nbsp;&nbsp;");
+          asHtml = true;
+        }
+        else
+        {
+          sb.append(" ");
+        }
+      }
+    }
+    String description = uf.getDescription();
+    if (description != null)
+    {
+      sb.append(description);
+    }
+    if (asHtml)
+    {
+      sb.insert(0, "<html>");
+      sb.append("</html>");
+    }
+
+    return sb.toString();
+  }
+
+  /**
    * 
    * @param entry
    *          UniportEntry
diff --git a/src/jalview/ws/dbsources/das/api/DasSourceRegistryI.java b/src/jalview/ws/dbsources/das/api/DasSourceRegistryI.java
deleted file mode 100644 (file)
index 55c50b2..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.ws.dbsources.das.api;
-
-import java.util.List;
-
-import org.biodas.jdas.client.threads.MultipleConnectionPropertyProviderI;
-
-/**
- * API for a registry that provides datasources that jalview can access
- * 
- * @author jprocter
- * 
- */
-public interface DasSourceRegistryI
-{
-
-  List<jalviewSourceI> getSources();
-
-  String getDasRegistryURL();
-
-  jalviewSourceI getSource(String nickname);
-
-  // TODO: re JAL-424 - introduce form where local source is queried for
-  // metadata, rather than have it all provided by caller.
-  jalviewSourceI createLocalSource(String uri, String name,
-          boolean sequence, boolean features);
-
-  boolean removeLocalSource(jalviewSourceI source);
-
-  void refreshSources();
-
-  String getLocalSourceString();
-
-  List<jalviewSourceI> resolveSourceNicknames(List<String> sources);
-
-  // TODO: refactor to jDAS specific interface
-  MultipleConnectionPropertyProviderI getSessionHandler();
-}
diff --git a/src/jalview/ws/dbsources/das/api/jalviewSourceI.java b/src/jalview/ws/dbsources/das/api/jalviewSourceI.java
deleted file mode 100644 (file)
index bc3c8ea..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.ws.dbsources.das.api;
-
-import jalview.ws.seqfetcher.DbSourceProxy;
-
-import java.util.List;
-
-import org.biodas.jdas.schema.sources.MAINTAINER;
-import org.biodas.jdas.schema.sources.VERSION;
-
-public interface jalviewSourceI
-{
-
-  String getTitle();
-
-  VERSION getVersion();
-
-  String getDocHref();
-
-  String getDescription();
-
-  String getUri();
-
-  MAINTAINER getMAINTAINER();
-
-  String getEmail();
-
-  boolean isLocal();
-
-  boolean isSequenceSource();
-
-  String[] getCapabilityList(VERSION v);
-
-  String[] getLabelsFor(VERSION v);
-
-  /**
-   * 
-   * @return null if not a sequence source, otherwise a series of database
-   *         sources that can be used to retrieve sequence data for particular
-   *         database coordinate systems
-   */
-  List<DbSourceProxy> getSequenceSourceProxies();
-
-  boolean isFeatureSource();
-
-  /**
-   * returns the base URL for the latest version of a source's DAS endpoint set
-   * 
-   * @return
-   */
-  String getSourceURL();
-
-  /**
-   * test to see if this source's latest version is older than the given source
-   * 
-   * @param jalviewSourceI
-   * @return true if newer than given source
-   */
-  boolean isNewerThan(jalviewSourceI jalviewSourceI);
-
-  /**
-   * test if the source is a reference source for the authority
-   * 
-   * @return
-   */
-  boolean isReferenceSource();
-
-}
diff --git a/src/jalview/ws/dbsources/das/datamodel/DasSequenceSource.java b/src/jalview/ws/dbsources/das/datamodel/DasSequenceSource.java
deleted file mode 100644 (file)
index 84f6d4d..0000000
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * 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.ws.dbsources.das.datamodel;
-
-import jalview.bin.Cache;
-import jalview.datamodel.Alignment;
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.DBRefEntry;
-import jalview.datamodel.Sequence;
-import jalview.datamodel.SequenceI;
-import jalview.util.MessageManager;
-import jalview.ws.dbsources.das.api.jalviewSourceI;
-import jalview.ws.seqfetcher.DbSourceProxy;
-import jalview.ws.seqfetcher.DbSourceProxyImpl;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.StringTokenizer;
-import java.util.Vector;
-
-import org.biodas.jdas.client.SequenceClient;
-import org.biodas.jdas.client.adapters.sequence.DasSequenceAdapter;
-import org.biodas.jdas.client.threads.MultipleConnectionPropertyProviderI;
-import org.biodas.jdas.client.threads.SequenceClientMultipleSources;
-import org.biodas.jdas.schema.sequence.SEQUENCE;
-import org.biodas.jdas.schema.sources.COORDINATES;
-import org.biodas.jdas.schema.sources.SOURCE;
-import org.biodas.jdas.schema.sources.VERSION;
-
-import com.stevesoft.pat.Regex;
-
-/**
- * an instance of this class is created for each unique DAS Sequence source (ie
- * one capable of handling the 'sequence' for a particular MapMaster)
- * 
- * @author JimP
- * 
- */
-public class DasSequenceSource extends DbSourceProxyImpl
-        implements DbSourceProxy
-{
-  private jalviewSourceI jsrc;
-
-  protected SOURCE source = null;
-
-  protected VERSION version = null;
-
-  protected COORDINATES coordsys = null;
-
-  protected String dbname = "DASCS";
-
-  protected String dbrefname = "das:source";
-
-  protected MultipleConnectionPropertyProviderI connprops = null;
-
-  /**
-   * DAS sources are tier 1 - if we have a direct DB connection then we should
-   * prefer it
-   */
-  private int tier = 1;
-
-  /**
-   * create a new DbSource proxy for a DAS 1 source
-   * 
-   * @param dbnbame
-   *          Human Readable Name to use when fetching from this source
-   * @param dbrefname
-   *          DbRefName for DbRefs attached to sequences retrieved from this
-   *          source
-   * @param source
-   *          Das1Source
-   * @param coordsys
-   *          specific coordinate system to use for this source
-   * @throws Exception
-   *           if source is not capable of the 'sequence' command
-   */
-  public DasSequenceSource(String dbname, String dbrefname, SOURCE source,
-          VERSION version, COORDINATES coordsys,
-          MultipleConnectionPropertyProviderI connprops) throws Exception
-  {
-    if (!(jsrc = new JalviewSource(source, connprops, false))
-            .isSequenceSource())
-    {
-      throw new Exception(MessageManager.formatMessage(
-              "exception.das_source_doesnt_support_sequence_command",
-              new String[]
-              { source.getTitle() }));
-    }
-    this.tier = 1 + ((jsrc.isLocal() || jsrc.isReferenceSource()) ? 0 : 1);
-    this.source = source;
-    this.dbname = dbname;
-    this.dbrefname = dbrefname.toUpperCase();
-    if (coordsys != null)
-    {
-      this.coordsys = coordsys;
-    }
-    this.connprops = connprops;
-  }
-
-  public String getAccessionSeparator()
-  {
-    return "\t";
-  }
-
-  public Regex getAccessionValidator()
-  {
-    /** ? * */
-    return Regex.perlCode("m/([^:]+)(:\\d+,\\d+)?/");
-  }
-
-  public String getDbName()
-  {
-    // TODO: map to
-    return dbname + " (DAS)";
-  }
-
-  public String getDbSource()
-  {
-    return dbrefname;
-  }
-
-  public String getDbVersion()
-  {
-    return coordsys != null ? coordsys.getVersion() : "";
-  }
-
-  public AlignmentI getSequenceRecords(String queries) throws Exception
-  {
-    StringTokenizer st = new StringTokenizer(queries, "\t");
-    List<String> toks = new ArrayList<String>(),
-            src = new ArrayList<String>(), acIds = new ArrayList<String>();
-    while (st.hasMoreTokens())
-    {
-      String t;
-      toks.add(t = st.nextToken());
-      acIds.add(t.replaceAll(":[0-9,]+", ""));
-    }
-    src.add(jsrc.getSourceURL());
-    Map<String, Map<List<String>, DasSequenceAdapter>> resultset = new HashMap<String, Map<List<String>, DasSequenceAdapter>>();
-    Map<String, Map<List<String>, Exception>> errors = new HashMap<String, Map<List<String>, Exception>>();
-
-    // First try multiple sources
-    boolean multiple = true, retry = false;
-    do
-    {
-      if (!multiple)
-      {
-        retry = false;
-        // slow, fetch one at a time.
-        for (String sr : src)
-        {
-          System.err.println(
-                  "Retrieving IDs individually from das source: " + sr);
-          org.biodas.jdas.client.SequenceClient sq = new SequenceClient(
-                  connprops.getConnectionPropertyProviderFor(sr));
-          for (String q : toks)
-          {
-            List<String> qset = Arrays.asList(new String[] { q });
-            try
-            {
-              DasSequenceAdapter s = sq.fetchData(sr, qset);
-              Map<List<String>, DasSequenceAdapter> dss = resultset.get(sr);
-              if (dss == null)
-              {
-                resultset.put(sr,
-                        dss = new HashMap<List<String>, DasSequenceAdapter>());
-              }
-              dss.put(qset, s);
-            } catch (Exception x)
-            {
-              Map<List<String>, Exception> ers = errors.get(sr);
-              if (ers == null)
-              {
-                errors.put(sr,
-                        ers = new HashMap<List<String>, Exception>());
-              }
-              ers.put(qset, x);
-            }
-          }
-        }
-      }
-      else
-      {
-        SequenceClientMultipleSources sclient;
-        sclient = new SequenceClientMultipleSources();
-        sclient.fetchData(src, toks, resultset, errors);
-        sclient.shutDown();
-        while (!sclient.isTerminated())
-        {
-          try
-          {
-            Thread.sleep(200);
-
-          } catch (InterruptedException x)
-          {
-          }
-        }
-        if (resultset.isEmpty() && !errors.isEmpty())
-        {
-          retry = true;
-          multiple = false;
-        }
-      }
-    } while (retry);
-
-    if (resultset.isEmpty())
-    {
-      System.err.println("Sequence Query to " + jsrc.getTitle() + " with '"
-              + queries + "' returned no sequences.");
-      return null;
-    }
-    else
-    {
-      Vector<SequenceI> seqs = null;
-      for (Map.Entry<String, Map<List<String>, DasSequenceAdapter>> resset : resultset
-              .entrySet())
-      {
-        for (Map.Entry<List<String>, DasSequenceAdapter> result : resset
-                .getValue().entrySet())
-        {
-          DasSequenceAdapter dasseqresp = result.getValue();
-          List<String> accessions = result.getKey();
-          for (SEQUENCE e : dasseqresp.getSequence())
-          {
-            String lbl = e.getId();
-
-            if (acIds.indexOf(lbl) == -1)
-            {
-              System.err.println(
-                      "Warning - received sequence event for strange accession code ("
-                              + lbl + ")");
-            }
-            else
-            {
-              if (seqs == null)
-              {
-                if (e.getContent().length() == 0)
-                {
-                  System.err.println(
-                          "Empty sequence returned for accession code ("
-                                  + lbl + ") from " + resset.getKey()
-                                  + " (source is " + getDbName());
-                  continue;
-                }
-              }
-              seqs = new java.util.Vector<SequenceI>();
-              // JDAS returns a sequence complete with any newlines and spaces
-              // in the XML
-              Sequence sq = new Sequence(lbl,
-                      e.getContent().replaceAll("\\s+", ""));
-              sq.setStart(e.getStart().intValue());
-              sq.addDBRef(new DBRefEntry(getDbSource(),
-                      getDbVersion() + ":" + e.getVersion(), lbl));
-              seqs.addElement(sq);
-            }
-          }
-        }
-      }
-
-      if (seqs == null || seqs.size() == 0)
-        return null;
-      SequenceI[] sqs = new SequenceI[seqs.size()];
-      for (int i = 0, iSize = seqs.size(); i < iSize; i++)
-      {
-        sqs[i] = (SequenceI) seqs.elementAt(i);
-      }
-      Alignment al = new Alignment(sqs);
-      if (jsrc.isFeatureSource())
-      {
-        java.util.Vector<jalviewSourceI> srcs = new java.util.Vector<jalviewSourceI>();
-        srcs.addElement(jsrc);
-        try
-        {
-          jalview.ws.DasSequenceFeatureFetcher dssf = new jalview.ws.DasSequenceFeatureFetcher(
-                  sqs, null, srcs, false, false, multiple);
-          while (dssf.isRunning())
-          {
-            try
-            {
-              Thread.sleep(200);
-            } catch (InterruptedException x)
-            {
-
-            }
-          }
-
-        } catch (Exception x)
-        {
-          Cache.log.error(
-                  "Couldn't retrieve features for sequence from its source.",
-                  x);
-        }
-      }
-
-      return al;
-    }
-  }
-
-  public String getTestQuery()
-  {
-    return coordsys == null ? "" : coordsys.getTestRange();
-  }
-
-  public boolean isValidReference(String accession)
-  {
-    // TODO try to validate an accession against source
-    // We don't really know how to do this without querying source
-
-    return true;
-  }
-
-  /**
-   * @return the source
-   */
-  public SOURCE getSource()
-  {
-    return source;
-  }
-
-  /**
-   * @return the coordsys
-   */
-  public COORDINATES getCoordsys()
-  {
-    return coordsys;
-  }
-
-  @Override
-  public int getTier()
-  {
-    return tier;
-  }
-}
diff --git a/src/jalview/ws/dbsources/das/datamodel/DasSourceRegistry.java b/src/jalview/ws/dbsources/das/datamodel/DasSourceRegistry.java
deleted file mode 100644 (file)
index de7f380..0000000
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * 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.ws.dbsources.das.datamodel;
-
-import jalview.bin.Cache;
-import jalview.ws.dbsources.das.api.DasSourceRegistryI;
-import jalview.ws.dbsources.das.api.jalviewSourceI;
-
-import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.StringTokenizer;
-
-import org.biodas.jdas.client.ConnectionPropertyProviderI;
-import org.biodas.jdas.client.SourcesClient;
-import org.biodas.jdas.client.threads.MultipleConnectionPropertyProviderI;
-import org.biodas.jdas.dassources.Capabilities;
-import org.biodas.jdas.schema.sources.CAPABILITY;
-import org.biodas.jdas.schema.sources.SOURCE;
-import org.biodas.jdas.schema.sources.SOURCES;
-import org.biodas.jdas.schema.sources.VERSION;
-
-/**
- *
- */
-public class DasSourceRegistry
-        implements DasSourceRegistryI, MultipleConnectionPropertyProviderI
-{
-  // private org.biodas.jdas.schema.sources.SOURCE[] dasSources = null;
-  private List<jalviewSourceI> dasSources = null;
-
-  private Hashtable<String, jalviewSourceI> sourceNames = null;
-
-  private Hashtable<String, jalviewSourceI> localSources = null;
-
-  // public static String DEFAULT_REGISTRY = "http://www.dasregistry.org/das/";
-  public static String DEFAULT_REGISTRY = "http://www.ebi.ac.uk/das-srv/registry/das/";
-
-  /**
-   * true if thread is running and we are talking to DAS registry service
-   */
-  private boolean loadingDasSources = false;
-
-  public boolean isLoadingDasSources()
-  {
-    return loadingDasSources;
-  }
-
-  @Override
-  public String getDasRegistryURL()
-  {
-    String registry = jalview.bin.Cache.getDefault("DAS_REGISTRY_URL",
-            DEFAULT_REGISTRY);
-
-    if (registry.indexOf("/registry/das1/sources/") > -1)
-    {
-      jalview.bin.Cache.setProperty(jalview.bin.Cache.DAS_REGISTRY_URL,
-              DEFAULT_REGISTRY);
-      registry = DEFAULT_REGISTRY;
-    }
-    if (registry.lastIndexOf("sources.xml") == registry.length() - 11)
-    {
-      // no trailing sources.xml document for registry in JDAS
-      jalview.bin.Cache.setProperty(jalview.bin.Cache.DAS_REGISTRY_URL,
-              registry = registry.substring(0,
-                      registry.lastIndexOf("sources.xml")));
-    }
-    return registry;
-  }
-
-  /**
-   * query the default DAS Source Registry for sources. Uses value of jalview
-   * property DAS_REGISTRY_URL and the DasSourceBrowser.DEFAULT_REGISTRY if that
-   * doesn't exist.
-   * 
-   * @return list of sources
-   */
-  private List<jalviewSourceI> getDASSources()
-  {
-
-    return getDASSources(getDasRegistryURL(), this);
-  }
-
-  /**
-   * query the given URL for DasSources.
-   * 
-   * @param registryURL
-   *          return sources from registryURL
-   */
-  private static List<jalviewSourceI> getDASSources(String registryURL,
-          MultipleConnectionPropertyProviderI registry)
-  {
-    try
-    {
-      URL url = new URL(registryURL);
-      org.biodas.jdas.client.SourcesClientInterface client = new SourcesClient();
-
-      SOURCES sources = client.fetchDataRegistry(registryURL, null, null,
-              null, null, null, null);
-
-      List<SOURCE> dassources = sources.getSOURCE();
-      ArrayList<jalviewSourceI> dsrc = new ArrayList<jalviewSourceI>();
-      HashMap<String, Integer> latests = new HashMap<String, Integer>();
-      Integer latest;
-      for (SOURCE src : dassources)
-      {
-        JalviewSource jsrc = new JalviewSource(src, registry, false);
-        latest = latests.get(jsrc.getSourceURL());
-        if (latest != null)
-        {
-          if (jsrc.isNewerThan(dsrc.get(latest.intValue())))
-          {
-            dsrc.set(latest.intValue(), jsrc);
-          }
-          else
-          {
-            System.out.println(
-                    "Debug: Ignored older source " + jsrc.getTitle());
-          }
-        }
-        else
-        {
-          latests.put(jsrc.getSourceURL(), Integer.valueOf(dsrc.size()));
-          dsrc.add(jsrc);
-        }
-      }
-      return dsrc;
-    } catch (Exception ex)
-    {
-      System.out.println(
-              "DAS1 registry at " + registryURL + " no longer exists");
-      return new ArrayList<jalviewSourceI>();
-    }
-  }
-
-  public void run()
-  {
-    getSources();
-  }
-
-  @Override
-  public List<jalviewSourceI> getSources()
-  {
-    if (dasSources == null)
-    {
-      dasSources = getDASSources();
-    }
-    return appendLocalSources();
-  }
-
-  /**
-   * generate Sources from the local das source list
-   * 
-   */
-  private void addLocalDasSources()
-  {
-    if (localSources == null)
-    {
-      // get local sources from properties and initialise the local source list
-      String local = jalview.bin.Cache.getProperty("DAS_LOCAL_SOURCE");
-
-      if (local != null)
-      {
-        int n = 1;
-        StringTokenizer st = new StringTokenizer(local, "\t");
-        while (st.hasMoreTokens())
-        {
-          String token = st.nextToken();
-          int bar = token.indexOf("|");
-          if (bar == -1)
-          {
-            System.err.println(
-                    "Warning: DAS user local source appears to have no nickname (expected a '|' followed by nickname)\nOffending definition: '"
-                            + token + "'");
-          }
-          String url = token.substring(bar + 1);
-          boolean features = true, sequence = false;
-          if (url.startsWith("sequence:"))
-          {
-            url = url.substring(9);
-            // this source also serves sequences as well as features
-            sequence = true;
-          }
-          try
-          {
-            if (bar > -1)
-            {
-              createLocalSource(url, token.substring(0, bar), sequence,
-                      features);
-            }
-            else
-            {
-              createLocalSource(url, "User Source" + n, sequence, features);
-            }
-          } catch (Exception q)
-          {
-            System.err.println(
-                    "Unexpected exception when creating local source from '"
-                            + token + "'");
-            q.printStackTrace();
-          }
-          n++;
-        }
-      }
-    }
-  }
-
-  private List<jalviewSourceI> appendLocalSources()
-  {
-    List<jalviewSourceI> srclist = new ArrayList<jalviewSourceI>();
-    addLocalDasSources();
-    sourceNames = new Hashtable<String, jalviewSourceI>();
-    if (dasSources != null)
-    {
-      for (jalviewSourceI src : dasSources)
-      {
-        sourceNames.put(src.getTitle(), src);
-        srclist.add(src);
-      }
-    }
-
-    if (localSources == null)
-    {
-      return srclist;
-    }
-    Enumeration en = localSources.keys();
-    while (en.hasMoreElements())
-    {
-      String key = en.nextElement().toString();
-      jalviewSourceI jvsrc = localSources.get(key);
-      sourceNames.put(key, jvsrc);
-      srclist.add(jvsrc);
-    }
-    return srclist;
-  }
-
-  /*
-  * 
-  */
-
-  @Override
-  public jalviewSourceI createLocalSource(String url, String name,
-          boolean sequence, boolean features)
-  {
-    SOURCE local = _createLocalSource(url, name, sequence, features);
-
-    if (localSources == null)
-    {
-      localSources = new Hashtable<String, jalviewSourceI>();
-    }
-    jalviewSourceI src = new JalviewSource(local, this, true);
-    localSources.put(local.getTitle(), src);
-    return src;
-  }
-
-  private SOURCE _createLocalSource(String url, String name,
-          boolean sequence, boolean features)
-  {
-    SOURCE local = new SOURCE();
-
-    local.setUri(url);
-    local.setTitle(name);
-    local.setVERSION(new ArrayList<VERSION>());
-    VERSION v = new VERSION();
-    List<CAPABILITY> cp = new ArrayList<CAPABILITY>();
-    if (sequence)
-    {
-      /*
-       * Could try and synthesize a coordinate system for the source if needbe
-       * COORDINATES coord = new COORDINATES(); coord.setAuthority("NCBI");
-       * coord.setSource("Chromosome"); coord.setTaxid("9606");
-       * coord.setVersion("35"); version.getCOORDINATES().add(coord);
-       */
-      CAPABILITY cap = new CAPABILITY();
-      cap.setType("das1:" + Capabilities.SEQUENCE.getName());
-      cap.setQueryUri(url + "/sequence");
-      cp.add(cap);
-    }
-    if (features)
-    {
-      CAPABILITY cap = new CAPABILITY();
-      cap.setType("das1:" + Capabilities.FEATURES.getName());
-      cap.setQueryUri(url + "/features");
-      cp.add(cap);
-    }
-
-    v.getCAPABILITY().addAll(cp);
-    local.getVERSION().add(v);
-
-    return local;
-  }
-
-  @Override
-  public jalviewSourceI getSource(String nickname)
-  {
-    return sourceNames.get(nickname);
-  }
-
-  @Override
-  public boolean removeLocalSource(jalviewSourceI source)
-  {
-    if (localSources.containsValue(source))
-    {
-      localSources.remove(source.getTitle());
-      sourceNames.remove(source.getTitle());
-      dasSources.remove(source);
-      jalview.bin.Cache.setProperty("DAS_LOCAL_SOURCE",
-              getLocalSourceString());
-
-      return true;
-    }
-    return false;
-  }
-
-  @Override
-  public void refreshSources()
-  {
-    dasSources = null;
-    sourceNames = null;
-    run();
-  }
-
-  @Override
-  public List<jalviewSourceI> resolveSourceNicknames(List<String> sources)
-  {
-    ArrayList<jalviewSourceI> resolved = new ArrayList<jalviewSourceI>();
-    if (sourceNames != null)
-    {
-      for (String src : sources)
-      {
-        jalviewSourceI dsrc = sourceNames.get(src);
-        if (dsrc != null)
-        {
-          resolved.add(dsrc);
-        }
-      }
-    }
-    return resolved;
-  }
-
-  @Override
-  public String getLocalSourceString()
-  {
-    if (localSources != null)
-    {
-      StringBuffer sb = new StringBuffer();
-      Enumeration en = localSources.keys();
-      while (en.hasMoreElements())
-      {
-        String token = en.nextElement().toString();
-        jalviewSourceI srco = localSources.get(token);
-        sb.append(token + "|" + (srco.isSequenceSource() ? "sequence:" : "")
-                + srco.getUri() + "\t");
-      }
-      return sb.toString();
-    }
-    return "";
-  }
-
-  private static final Hashtable<URL, String> authStash;
-  static
-  {
-    authStash = new Hashtable<URL, String>();
-
-    try
-    {
-      // TODO: allow same credentials for https and http
-      authStash.put(
-              new URL("http://www.compbio.dundee.ac.uk/geneweb/das/myseq/"),
-              "Basic SmltOm1pSg==");
-    } catch (MalformedURLException e)
-    {
-      // TODO Auto-generated catch block
-      e.printStackTrace();
-    }
-  }
-
-  @Override
-  public MultipleConnectionPropertyProviderI getSessionHandler()
-  {
-    return this;
-  }
-
-  @Override
-  public ConnectionPropertyProviderI getConnectionPropertyProviderFor(
-          String arg0)
-  {
-
-    final ConnectionPropertyProviderI conprov = new ConnectionPropertyProviderI()
-    {
-      boolean authed = false;
-
-      @Override
-      public void setConnectionProperties(HttpURLConnection connection)
-      {
-        String auth = authStash.get(connection.getURL());
-        if (auth != null && auth.length() > 0)
-        {
-          connection.setRequestProperty("Authorisation", auth);
-          authed = true;
-        }
-        else
-        {
-          authed = false;
-        }
-      }
-
-      @Override
-      public boolean getResponseProperties(HttpURLConnection connection)
-      {
-        String auth = authStash.get(connection.getURL());
-        if (auth != null && auth.length() == 0)
-        {
-          // don't attempt to check if we authed or not - user entered empty
-          // password
-          return false;
-        }
-        if (!authed)
-        {
-          if (auth != null)
-          {
-            // try and pass credentials.
-            return true;
-          }
-          // see if we should try and create a new auth record.
-          String ameth = connection.getHeaderField("X-DAS-AuthMethods");
-          Cache.log.debug("Could authenticate to " + connection.getURL()
-                  + " with : " + ameth);
-          // TODO: search auth string and raise login box - return if auth was
-          // provided
-          return false;
-        }
-        else
-        {
-          // check to see if auth was successful
-          String asuc = connection
-                  .getHeaderField("X-DAS_AuthenticatedUser");
-          if (asuc != null && asuc.trim().length() > 0)
-          {
-            // authentication was successful
-            Cache.log.debug("Authenticated successfully to "
-                    + connection.getURL().toString());
-            return false;
-          }
-          // it wasn't - so we should tell the user it failed and ask if they
-          // want to attempt authentication again.
-          authStash.remove(connection.getURL());
-          // open a new login/password dialog with cancel button
-          // set new authStash content with password and return true
-          return true; //
-          // User cancelled auth - so put empty string in stash to indicate we
-          // don't want to auth with this server.
-          // authStash.put(connection.getURL(), "");
-          // return false;
-        }
-      }
-    };
-    return conprov;
-  }
-
-}
diff --git a/src/jalview/ws/dbsources/das/datamodel/JalviewSource.java b/src/jalview/ws/dbsources/das/datamodel/JalviewSource.java
deleted file mode 100644 (file)
index 07ba027..0000000
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * 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.ws.dbsources.das.datamodel;
-
-import jalview.util.MessageManager;
-import jalview.ws.dbsources.das.api.jalviewSourceI;
-import jalview.ws.seqfetcher.DbSourceProxy;
-
-import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-
-import org.biodas.jdas.client.threads.MultipleConnectionPropertyProviderI;
-import org.biodas.jdas.dassources.Capabilities;
-import org.biodas.jdas.dassources.utils.DasTimeFormat;
-import org.biodas.jdas.schema.sources.CAPABILITY;
-import org.biodas.jdas.schema.sources.COORDINATES;
-import org.biodas.jdas.schema.sources.MAINTAINER;
-import org.biodas.jdas.schema.sources.PROP;
-import org.biodas.jdas.schema.sources.SOURCE;
-import org.biodas.jdas.schema.sources.VERSION;
-
-public class JalviewSource implements jalviewSourceI
-{
-  SOURCE source;
-
-  MultipleConnectionPropertyProviderI connprov;
-
-  public JalviewSource(SOURCE local2,
-          MultipleConnectionPropertyProviderI connprov, boolean local)
-  {
-    this.connprov = connprov;
-    this.local = local;
-    source = local2;
-  }
-
-  @Override
-  public String getTitle()
-  {
-    return source.getTitle();
-  }
-
-  @Override
-  public VERSION getVersion()
-  {
-
-    return getVersionFor(source);
-  }
-
-  @Override
-  public String getDocHref()
-  {
-    return source.getDocHref();
-  }
-
-  @Override
-  public String getDescription()
-  {
-    return source.getDescription();
-  }
-
-  @Override
-  public String getUri()
-  {
-    return source.getUri();
-  }
-
-  @Override
-  public MAINTAINER getMAINTAINER()
-  {
-    return source.getMAINTAINER();
-  }
-
-  @Override
-  public String getEmail()
-  {
-    return (local) ? null : source.getMAINTAINER().getEmail();
-  }
-
-  boolean local = false;
-
-  @Override
-  public boolean isLocal()
-  {
-    return local;
-  }
-
-  @Override
-  public boolean isSequenceSource()
-  {
-    String seqcap = "das1:" + Capabilities.SEQUENCE.getName();
-    for (String cp : getCapabilityList(getVersionFor(source)))
-    {
-      if (cp.equals(seqcap))
-      {
-        return true;
-
-      }
-    }
-    return false;
-  }
-
-  @Override
-  public boolean isFeatureSource()
-  {
-    String seqcap = "das1:" + Capabilities.FEATURES.getName();
-    for (String cp : getCapabilityList(getVersionFor(source)))
-    {
-      if (cp.equals(seqcap))
-      {
-        return true;
-
-      }
-    }
-    return false;
-  }
-
-  private VERSION getVersionFor(SOURCE ds)
-  {
-    VERSION latest = null;
-    for (VERSION v : ds.getVERSION())
-    {
-      if (latest == null
-              || isLaterThan(latest.getCreated(), v.getCreated()))
-      {
-        // TODO: das 1.6 - should just get the first version - ignore other
-        // versions since not specified how to construct URL from version's URI
-        // + source URI
-        latest = v;
-      }
-    }
-    return latest;
-  }
-
-  /**
-   * compare date strings. null or unparseable dates are assumed to be oldest
-   * 
-   * @param ref
-   * @param newer
-   * @return true iff ref comes before newer
-   */
-  private boolean isLaterThan(String ref, String newer)
-  {
-    Date refdate = null, newdate = null;
-    if (ref != null && ref.trim().length() > 0)
-    {
-      try
-      {
-        refdate = DasTimeFormat.fromDASString(ref.trim());
-
-      } catch (ParseException x)
-      {
-      }
-    }
-    if (newer != null && newer.trim().length() > 0)
-    {
-      try
-      {
-        newdate = DasTimeFormat.fromDASString(newer);
-      } catch (ParseException e)
-      {
-      }
-    }
-    if (refdate != null)
-    {
-      if (newdate != null)
-      {
-        return refdate.before(newdate);
-      }
-      return false;
-    }
-    if (newdate != null)
-    {
-      return true;
-    }
-    // assume first instance of source is newest in list. - TODO: check if
-    // natural ordering of source versions is newest first or oldest first
-    return false;
-  }
-
-  public String[] getLabelsFor(VERSION v)
-  {
-    ArrayList<String> labels = new ArrayList<String>();
-    for (PROP p : v.getPROP())
-    {
-      if (p.getName().equalsIgnoreCase("LABEL"))
-      {
-        labels.add(p.getValue());
-      }
-    }
-    return labels.toArray(new String[0]);
-  }
-
-  private CAPABILITY getCapability(Capabilities capability)
-  {
-    for (CAPABILITY p : getVersion().getCAPABILITY())
-    {
-      if (p.getType().equalsIgnoreCase(capability.getName()) || p.getType()
-              .equalsIgnoreCase("das1:" + capability.getName()))
-      {
-        return p;
-      }
-    }
-    return null;
-  }
-
-  public String[] getCapabilityList(VERSION v)
-  {
-
-    ArrayList<String> labels = new ArrayList<String>();
-    for (CAPABILITY p : v.getCAPABILITY())
-    {
-      // TODO: work out what to do with namespace prefix
-      // does SEQUENCE == das1:SEQUENCE and das2:SEQUENCE ?
-      // for moment, just show all capabilities...
-      if (p.getType().startsWith("das1:"))
-      {
-        labels.add(p.getType());
-      }
-    }
-    return labels.toArray(new String[0]);
-  }
-
-  @Override
-  public List<DbSourceProxy> getSequenceSourceProxies()
-  {
-    if (!isSequenceSource())
-    {
-      return null;
-    }
-    ArrayList<DbSourceProxy> seqsources = new ArrayList<DbSourceProxy>();
-    if (!local)
-    {
-      VERSION v = getVersion();
-      Map<String, COORDINATES> latestc = new Hashtable<String, COORDINATES>();
-      for (COORDINATES cs : v.getCOORDINATES())
-      {
-        COORDINATES ltst = latestc.get(cs.getUri());
-        if (ltst == null || ltst.getVersion() == null
-                || (ltst.getVersion() != null && cs.getVersion() != null
-                        && isLaterThan(ltst.getVersion(), cs.getVersion())))
-        {
-          latestc.put(cs.getUri(), cs);
-        }
-      }
-      for (COORDINATES cs : latestc.values())
-      {
-        DasSequenceSource ds;
-        /*
-         * if (css == null || css.length == 0) { // TODO: query das source
-         * directly to identify coordinate system... or // have to make up a
-         * coordinate system css = new DasCoordinateSystem[] { new
-         * DasCoordinateSystem() }; css[0].setName(d1s.getNickname());
-         * css[0].setUniqueId(d1s.getNickname()); } for (int c = 0; c <
-         * css.length; c++) {
-         */
-        try
-        {
-          seqsources.add(ds = new DasSequenceSource(
-                  getTitle() + " (" + cs.getAuthority() + " "
-                          + cs.getSource()
-                          + (cs.getVersion() != null ? " " + cs.getVersion()
-                                  : "")
-                          + ")",
-                  cs.getAuthority(), source, v, cs, connprov));
-          if (seqsources.size() > 1)
-          {
-            System.err.println("Added another sequence DB source for "
-                    + getTitle() + " (" + ds.getDbName() + ")");
-          }
-        } catch (Exception e)
-        {
-          System.err.println("Ignoring sequence coord system " + cs + " ("
-                  + cs.getContent() + ") for source " + getTitle()
-                  + "- threw exception when constructing fetcher.\n");
-          e.printStackTrace();
-        }
-      }
-    }
-    else
-    {
-      try
-      {
-        seqsources.add(new DasSequenceSource(getTitle(), getTitle(), source,
-                getVersion(), null, connprov));
-      } catch (Exception e)
-      {
-        // TODO Auto-generated catch block
-        e.printStackTrace();
-      }
-
-    }
-    if (seqsources.size() > 1)
-    {
-      // sort by name
-      DbSourceProxy[] tsort = seqsources.toArray(new DasSequenceSource[0]);
-      String[] nm = new String[tsort.length];
-      for (int i = 0; i < nm.length; i++)
-      {
-        nm[i] = tsort[i].getDbName().toLowerCase();
-      }
-      jalview.util.QuickSort.sort(nm, tsort);
-      seqsources.clear();
-      for (DbSourceProxy ssrc : tsort)
-      {
-        seqsources.add(ssrc);
-      }
-    }
-    return seqsources;
-  }
-
-  @Override
-  public String getSourceURL()
-  {
-    try
-    {
-      // kind of dumb, since
-      // org.biodas.jdas.dassources.utils.VersionAdapter.getSourceUriFromQueryUri()
-      // does this,
-      // but this way, we can access non DAS 1.6 compliant sources (which have
-      // to have a URL like <sourcename>/das/ and cause a validation exception)
-
-      for (CAPABILITY cap : getVersion().getCAPABILITY())
-      {
-        String capname = cap.getType()
-                .substring(cap.getType().indexOf(":") + 1);
-        int p = cap.getQueryUri().lastIndexOf(capname);
-        if (p < -1)
-        {
-          throw new Exception(MessageManager.formatMessage(
-                  "exception.invalid_das_source", new String[]
-                  { source.getUri() }));
-        }
-        if (cap.getQueryUri().charAt(p) == '/')
-        {
-          p--;
-        }
-        return cap.getQueryUri().substring(0, p);
-      }
-    } catch (Exception x)
-    {
-      System.err.println("Serious: Couldn't get the URL for source "
-              + source.getTitle());
-      x.printStackTrace();
-    }
-    return null;
-  }
-
-  @Override
-  public boolean isNewerThan(jalviewSourceI other)
-  {
-    return isLaterThan(getVersion().getCreated(),
-            other.getVersion().getCreated());
-  }
-
-  @Override
-  public boolean isReferenceSource()
-  {
-    // TODO check source object for indication that we are the primary for a DAS
-    // coordinate system
-    return false;
-  }
-}
index 92bf0ce..a7a7d34 100644 (file)
@@ -2685,14 +2685,14 @@ public class AlignmentUtilsTests
     assertEquals(2, toMap.getFromRanges().get(0).length);
     assertEquals(1, toMap.getFromRanges().get(0)[0]);
     assertEquals(12, toMap.getFromRanges().get(0)[1]);
-    assertEquals(1, toMap.getToRanges().size());
-    assertEquals(4, toMap.getToRanges().get(0).length);
+    assertEquals(2, toMap.getToRanges().size());
+    assertEquals(2, toMap.getToRanges().get(0).length);
     assertEquals(158, toMap.getToRanges().get(0)[0]);
     assertEquals(164, toMap.getToRanges().get(0)[1]);
-    assertEquals(210, toMap.getToRanges().get(0)[2]);
-    assertEquals(214, toMap.getToRanges().get(0)[3]);
+    assertEquals(210, toMap.getToRanges().get(1)[0]);
+    assertEquals(214, toMap.getToRanges().get(1)[1]);
     // or summarised as (but toString might change in future):
-    assertEquals("[ [1, 12] ] 1:1 to [ [158, 164, 210, 214] ]",
+    assertEquals("[ [1, 12] ] 1:1 to [ [158, 164] [210, 214] ]",
             toMap.toString());
 
     /*
@@ -2704,7 +2704,7 @@ public class AlignmentUtilsTests
     assertEquals("GRCh38", toLoci.getAssemblyId());
     assertEquals("7", toLoci.getChromosomeId());
     toMap = toLoci.getMap();
-    assertEquals("[ [1, 12] ] 1:1 to [ [158, 164, 210, 214] ]",
+    assertEquals("[ [1, 12] ] 1:1 to [ [158, 164] [210, 214] ]",
             toMap.toString());
   }
 
index 0265af3..b3c78be 100644 (file)
@@ -427,7 +427,7 @@ public class CrossRefTest
      * argument false suppresses adding DAS sources
      * todo: define an interface type SequenceFetcherI and mock that
      */
-    SequenceFetcher mockFetcher = new SequenceFetcher(false)
+    SequenceFetcher mockFetcher = new SequenceFetcher()
     {
       @Override
       public boolean isFetchable(String source)
@@ -505,7 +505,7 @@ public class CrossRefTest
      * argument false suppresses adding DAS sources
      * todo: define an interface type SequenceFetcherI and mock that
      */
-    SequenceFetcher mockFetcher = new SequenceFetcher(false)
+    SequenceFetcher mockFetcher = new SequenceFetcher()
     {
       @Override
       public boolean isFetchable(String source)
@@ -651,7 +651,7 @@ public class CrossRefTest
      * passed in calls to getSequences() - important to verify that
      * duplicate sequence fetches are not requested
      */
-    SequenceFetcher mockFetcher = new SequenceFetcher(false)
+    SequenceFetcher mockFetcher = new SequenceFetcher()
     {
       int call = 0;
 
index 69a3ef7..3ac8656 100644 (file)
@@ -35,6 +35,9 @@ import org.testng.annotations.BeforeTest;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
+import io.github.classgraph.ClassGraph;
+import io.github.classgraph.ScanResult;
+
 public class CommandLineOperations
 {
 
@@ -45,7 +48,7 @@ public class CommandLineOperations
     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
   }
 
-  private static final int TEST_TIMEOUT = 4500; // Note longer timeout needed on
+  private static final int TEST_TIMEOUT = 9000; // Note longer timeout needed on
                                                 // full test run than on
                                                 // individual tests
 
@@ -55,7 +58,7 @@ public class CommandLineOperations
 
   private static final int MINFILESIZE_BIG = 4096;
 
-  private ArrayList<String> successfulCMDs = new ArrayList<String>();
+  private ArrayList<String> successfulCMDs = new ArrayList<>();
 
   /***
    * from
@@ -113,13 +116,39 @@ public class CommandLineOperations
     }
   }
 
+  private static ClassGraph scanner = null;
+
+  private static String classpath = null;
+
+  public synchronized static String getClassPath()
+  {
+    if (scanner == null)
+    {
+      scanner = new ClassGraph();
+      ScanResult scan = scanner.scan();
+      classpath = scan.getClasspath();
+    }
+    while (classpath == null)
+    {
+      try
+      {
+        Thread.sleep(10);
+      } catch (InterruptedException x)
+      {
+
+      }
+    }
+    return classpath;
+  }
   private Worker jalviewDesktopRunner(boolean withAwt, String cmd,
           int timeout)
   {
+    // Note: JAL-3065 - don't include quotes for lib/* because the arguments are
+    // not expanded by the shell
+    String classpath = getClassPath();
     String _cmd = "java "
             + (withAwt ? "-Djava.awt.headless=true" : "")
-            + " -Djava.ext.dirs=./lib -classpath ./classes jalview.bin.Jalview ";
-    System.out.println("CMD [" + cmd + "]");
+            + " -classpath " + classpath + " jalview.bin.Jalview ";
     Process ls2_proc = null;
     Worker worker = null;
     try
index 686cd2f..0846ec2 100644 (file)
@@ -76,12 +76,14 @@ public class FeatureAttributesTest
     assertNull(fa.getMinMax("Pfam", "kd"));
     sf.setValue("domain", "xyz");
     assertNull(fa.getMinMax("Pfam", "kd"));
-    sf.setValue("kd", "some text");
-    assertNull(fa.getMinMax("Pfam", "kd"));
     sf.setValue("kd", "1.3");
     assertEquals(fa.getMinMax("Pfam", "kd"), new float[] { 1.3f, 1.3f });
     sf.setValue("kd", "-2.6");
     assertEquals(fa.getMinMax("Pfam", "kd"), new float[] { -2.6f, 1.3f });
+    // setting 'mixed' character and numeric values wipes the min/max value
+    sf.setValue("kd", "some text");
+    assertNull(fa.getMinMax("Pfam", "kd"));
+
     Map<String, String> csq = new HashMap<>();
     csq.put("AF", "-3");
     sf.setValue("CSQ", csq);
index 39d6dce..32987b0 100644 (file)
@@ -13,10 +13,10 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import junit.extensions.PA;
-
 import org.testng.annotations.Test;
 
+import junit.extensions.PA;
+
 public class SequenceFeaturesTest
 {
   @Test(groups = "Functional")
@@ -1005,33 +1005,44 @@ public class SequenceFeaturesTest
     assertTrue(store.getFeaturesByOntology(new String[] {}).isEmpty());
     assertTrue(store.getFeaturesByOntology((String[]) null).isEmpty());
   
-    SequenceFeature sf1 = new SequenceFeature("transcript", "desc", 10, 20,
+    SequenceFeature transcriptFeature = new SequenceFeature("transcript", "desc", 10, 20,
             Float.NaN, null);
-    store.add(sf1);
+    store.add(transcriptFeature);
 
-    // mRNA isA transcript; added here 'as if' non-positional
-    // just to show that non-positional features are included in results
-    SequenceFeature sf2 = new SequenceFeature("mRNA", "desc", 0, 0,
+    /*
+     * mRNA is a sub-type of transcript; added here 'as if' non-positional
+     * just to show that non-positional features are included in results
+     */
+    SequenceFeature mrnaFeature = new SequenceFeature("mRNA", "desc", 0, 0,
             Float.NaN, null);
-    store.add(sf2);
+    store.add(mrnaFeature);
 
-    SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 30, 40,
+    SequenceFeature pfamFeature = new SequenceFeature("Pfam", "desc", 30, 40,
             Float.NaN, null);
-    store.add(sf3);
+    store.add(pfamFeature);
 
+    /*
+     * "transcript" matches both itself and the sub-term "mRNA"
+     */
     features = store.getFeaturesByOntology("transcript");
     assertEquals(features.size(), 2);
-    assertTrue(features.contains(sf1));
-    assertTrue(features.contains(sf2));
+    assertTrue(features.contains(transcriptFeature));
+    assertTrue(features.contains(mrnaFeature));
 
+    /*
+     * "mRNA" matches itself but not parent term "transcript"
+     */
     features = store.getFeaturesByOntology("mRNA");
     assertEquals(features.size(), 1);
-    assertTrue(features.contains(sf2));
+    assertTrue(features.contains(mrnaFeature));
 
+    /*
+     * "pfam" is not an SO term but is included as an exact match
+     */
     features = store.getFeaturesByOntology("mRNA", "Pfam");
     assertEquals(features.size(), 2);
-    assertTrue(features.contains(sf2));
-    assertTrue(features.contains(sf3));
+    assertTrue(features.contains(mrnaFeature));
+    assertTrue(features.contains(pfamFeature));
 
     features = store.getFeaturesByOntology("sequence_variant");
     assertTrue(features.isEmpty());
@@ -1040,7 +1051,7 @@ public class SequenceFeaturesTest
   @Test(groups = "Functional")
   public void testSortFeatures()
   {
-    List<SequenceFeature> sfs = new ArrayList<SequenceFeature>();
+    List<SequenceFeature> sfs = new ArrayList<>();
     SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 30, 80,
             Float.NaN, null);
     sfs.add(sf1);
index 779962c..c9d8deb 100644 (file)
@@ -25,6 +25,7 @@ import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertNull;
 import static org.testng.AssertJUnit.assertTrue;
 
+import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceDummy;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
@@ -241,37 +242,51 @@ public class EnsemblCdnaTest
    * accession id as parent
    */
   @Test(groups = "Functional")
-  public void testIdentifiesSequence()
+  public void testGetIdentifyingFeatures()
   {
     String accId = "ABC123";
-    EnsemblCdna testee = new EnsemblCdna();
+    SequenceI seq = new Sequence(accId, "MKLNFRQIE");
 
-    // exon with no parent not valid
-    SequenceFeature sf = new SequenceFeature("exon", "", 1, 2, 0f, null);
-    assertFalse(testee.identifiesSequence(sf, accId));
+    // exon with no parent: not valid
+    SequenceFeature sf1 = new SequenceFeature("exon", "", 1, 2, 0f, null);
+    seq.addSequenceFeature(sf1);
 
-    // exon with wrong parent not valid
-    sf.setValue("Parent", "transcript:XYZ");
-    assertFalse(testee.identifiesSequence(sf, accId));
+    // exon with wrong parent: not valid
+    SequenceFeature sf2 = new SequenceFeature("exon", "", 1, 2, 0f, null);
+    sf2.setValue("Parent", "transcript:XYZ");
+    seq.addSequenceFeature(sf2);
 
     // exon with right parent is valid
-    sf.setValue("Parent", "transcript:" + accId);
-    assertTrue(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf3 = new SequenceFeature("exon", "", 1, 2, 0f, null);
+    sf3.setValue("Parent", "transcript:" + accId);
+    seq.addSequenceFeature(sf3);
 
     // exon sub-type with right parent is valid
-    sf = new SequenceFeature("coding_exon", "", 1, 2, 0f, null);
-    sf.setValue("Parent", "transcript:" + accId);
-    assertTrue(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf4 = new SequenceFeature("coding_exon", "", 1, 2, 0f,
+            null);
+    sf4.setValue("Parent", "transcript:" + accId);
+    seq.addSequenceFeature(sf4);
 
     // transcript not valid:
-    sf = new SequenceFeature("transcript", "", 1, 2, 0f, null);
-    sf.setValue("Parent", "transcript:" + accId);
-    assertFalse(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf5 = new SequenceFeature("transcript", "", 1, 2, 0f,
+            null);
+    sf5.setValue("Parent", "transcript:" + accId);
+    seq.addSequenceFeature(sf5);
 
     // CDS not valid:
-    sf = new SequenceFeature("CDS", "", 1, 2, 0f, null);
-    sf.setValue("Parent", "transcript:" + accId);
-    assertFalse(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf6 = new SequenceFeature("transcript", "", 1, 2, 0f,
+            null);
+    sf6.setValue("Parent", "transcript:" + accId);
+    seq.addSequenceFeature(sf6);
+
+    List<SequenceFeature> sfs = new EnsemblCdna()
+            .getIdentifyingFeatures(seq, accId);
+    assertFalse(sfs.contains(sf1));
+    assertFalse(sfs.contains(sf2));
+    assertTrue(sfs.contains(sf3));
+    assertTrue(sfs.contains(sf4));
+    assertFalse(sfs.contains(sf5));
+    assertFalse(sfs.contains(sf6));
   }
 
   @Test(groups = "Functional")
index 8482c90..a44ab7f 100644 (file)
@@ -24,6 +24,7 @@ import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertTrue;
 
+import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceDummy;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
@@ -152,37 +153,50 @@ public class EnsemblCdsTest
    * accession id as parent
    */
   @Test(groups = "Functional")
-  public void testIdentifiesSequence()
+  public void testGetIdentifyingFeatures()
   {
     String accId = "ABC123";
-    EnsemblCds testee = new EnsemblCds();
+    SequenceI seq = new Sequence(accId, "MKDONS");
 
     // cds with no parent not valid
-    SequenceFeature sf = new SequenceFeature("CDS", "", 1, 2, 0f, null);
-    assertFalse(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf1 = new SequenceFeature("CDS", "", 1, 2, 0f, null);
+    seq.addSequenceFeature(sf1);
 
     // cds with wrong parent not valid
-    sf.setValue("Parent", "transcript:XYZ");
-    assertFalse(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf2 = new SequenceFeature("CDS", "", 1, 2, 0f, null);
+    sf2.setValue("Parent", "transcript:XYZ");
+    seq.addSequenceFeature(sf2);
 
     // cds with right parent is valid
-    sf.setValue("Parent", "transcript:" + accId);
-    assertTrue(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf3 = new SequenceFeature("CDS", "", 1, 2, 0f, null);
+    sf3.setValue("Parent", "transcript:" + accId);
+    seq.addSequenceFeature(sf3);
 
     // cds sub-type with right parent is valid
-    sf = new SequenceFeature("CDS_predicted", "", 1, 2, 0f, null);
-    sf.setValue("Parent", "transcript:" + accId);
-    assertTrue(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf4 = new SequenceFeature("CDS_predicted", "", 1, 2, 0f,
+            null);
+    sf4.setValue("Parent", "transcript:" + accId);
+    seq.addSequenceFeature(sf4);
 
     // transcript not valid:
-    sf = new SequenceFeature("transcript", "", 1, 2, 0f, null);
-    sf.setValue("Parent", "transcript:" + accId);
-    assertFalse(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf5 = new SequenceFeature("transcript", "", 1, 2, 0f,
+            null);
+    sf5.setValue("Parent", "transcript:" + accId);
+    seq.addSequenceFeature(sf5);
 
     // exon not valid:
-    sf = new SequenceFeature("exon", "", 1, 2, 0f, null);
-    sf.setValue("Parent", "transcript:" + accId);
-    assertFalse(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf6 = new SequenceFeature("exon", "", 1, 2, 0f, null);
+    sf6.setValue("Parent", "transcript:" + accId);
+    seq.addSequenceFeature(sf6);
+
+    List<SequenceFeature> sfs = new EnsemblCds().getIdentifyingFeatures(seq,
+            accId);
+    assertFalse(sfs.contains(sf1));
+    assertFalse(sfs.contains(sf2));
+    assertTrue(sfs.contains(sf3));
+    assertTrue(sfs.contains(sf4));
+    assertFalse(sfs.contains(sf5));
+    assertFalse(sfs.contains(sf6));
   }
 
   @Test(groups = "Functional")
index 217742d..446b4f7 100644 (file)
@@ -26,6 +26,7 @@ import static org.testng.AssertJUnit.assertTrue;
 
 import jalview.api.FeatureSettingsModelI;
 import jalview.bin.Cache;
+import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceDummy;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
@@ -77,17 +78,9 @@ public class EnsemblGeneTest
     genomic.setEnd(50000);
     String geneId = "ABC123";
 
-    // gene at (start+20000) length 501
-    // should be ignored - the first 'gene' found defines the whole range
-    // (note features are found in position order, not addition order)
-    SequenceFeature sf = new SequenceFeature("gene", "", 20000, 20500, 0f,
-            null);
-    sf.setValue("ID", "gene:" + geneId);
-    sf.setStrand("+");
-    genomic.addSequenceFeature(sf);
-
     // gene at (start + 10500) length 101
-    sf = new SequenceFeature("gene", "", 10500, 10600, 0f, null);
+    SequenceFeature sf = new SequenceFeature("gene", "", 10500, 10600, 0f,
+            null);
     sf.setValue("ID", "gene:" + geneId);
     sf.setStrand("+");
     genomic.addSequenceFeature(sf);
@@ -117,17 +110,9 @@ public class EnsemblGeneTest
     genomic.setEnd(50000);
     String geneId = "ABC123";
 
-    // gene at (start+20000) length 501
-    // should be ignored - the first 'gene' found defines the whole range
-    // (real data would only have one such feature)
-    SequenceFeature sf = new SequenceFeature("ncRNA_gene", "", 20000,
-            20500, 0f, null);
-    sf.setValue("ID", "gene:" + geneId);
-    sf.setStrand("-");
-    genomic.addSequenceFeature(sf);
-
     // gene at (start + 10500) length 101
-    sf = new SequenceFeature("gene", "", 10500, 10600, 0f, null);
+    SequenceFeature sf = new SequenceFeature("gene", "", 10500, 10600, 0f,
+            null);
     sf.setValue("ID", "gene:" + geneId);
     sf.setStrand("+");
     genomic.addSequenceFeature(sf);
@@ -240,40 +225,48 @@ public class EnsemblGeneTest
    * accession id as ID
    */
   @Test(groups = "Functional")
-  public void testIdentifiesSequence()
+  public void testGetIdentifyingFeatures()
   {
     String accId = "ABC123";
-    EnsemblGene testee = new EnsemblGene();
+    SequenceI seq = new Sequence(accId, "HIBEES");
 
     // gene with no ID not valid
-    SequenceFeature sf = new SequenceFeature("gene", "", 1, 2, 0f, null);
-    assertFalse(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf1 = new SequenceFeature("gene", "", 1, 2, 0f, null);
+    seq.addSequenceFeature(sf1);
 
     // gene with wrong ID not valid
-    sf.setValue("ID", "gene:XYZ");
-    assertFalse(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf2 = new SequenceFeature("gene", "", 1, 2, 0f, null);
+    sf2.setValue("ID", "gene:XYZ");
+    seq.addSequenceFeature(sf2);
 
     // gene with right ID is valid
-    sf.setValue("ID", "gene:" + accId);
-    assertTrue(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf3 = new SequenceFeature("gene", "", 1, 2, 0f, null);
+    sf3.setValue("ID", "gene:" + accId);
+    seq.addSequenceFeature(sf3);
 
     // gene sub-type with right ID is valid
-    sf = new SequenceFeature("snRNA_gene", "", 1, 2, 0f, null);
-    sf.setValue("ID", "gene:" + accId);
-    assertTrue(testee.identifiesSequence(sf, accId));
-
-    // test is not case-sensitive
-    assertTrue(testee.identifiesSequence(sf, accId.toLowerCase()));
+    SequenceFeature sf4 = new SequenceFeature("snRNA_gene", "", 1, 2, 0f, null);
+    sf4.setValue("ID", "gene:" + accId);
+    seq.addSequenceFeature(sf4);
 
     // transcript not valid:
-    sf = new SequenceFeature("transcript", "", 1, 2, 0f, null);
-    sf.setValue("ID", "gene:" + accId);
-    assertFalse(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf5 = new SequenceFeature("transcript", "", 1, 2, 0f, null);
+    sf5.setValue("ID", "gene:" + accId);
+    seq.addSequenceFeature(sf5);
 
     // exon not valid:
-    sf = new SequenceFeature("exon", "", 1, 2, 0f, null);
-    sf.setValue("ID", "gene:" + accId);
-    assertFalse(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf6 = new SequenceFeature("exon", "", 1, 2, 0f, null);
+    sf6.setValue("ID", "gene:" + accId);
+    seq.addSequenceFeature(sf6);
+    
+    List<SequenceFeature> sfs = new EnsemblGene()
+            .getIdentifyingFeatures(seq, accId);
+    assertFalse(sfs.contains(sf1));
+    assertFalse(sfs.contains(sf2));
+    assertTrue(sfs.contains(sf3));
+    assertTrue(sfs.contains(sf4));
+    assertFalse(sfs.contains(sf5));
+    assertFalse(sfs.contains(sf6));
   }
 
   /**
index 8687da9..72ee492 100644 (file)
@@ -24,6 +24,7 @@ import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertTrue;
 
+import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceDummy;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
@@ -162,43 +163,58 @@ public class EnsemblGenomeTest
    * accession id as ID
    */
   @Test(groups = "Functional")
-  public void testIdentifiesSequence()
+  public void testGetIdentifyingFeatures()
   {
     String accId = "ABC123";
-    EnsemblGenome testee = new EnsemblGenome();
+    SequenceI seq = new Sequence(accId, "HEARTS");
 
     // transcript with no ID not valid
-    SequenceFeature sf = new SequenceFeature("transcript", "", 1, 2, 0f,
+    SequenceFeature sf1 = new SequenceFeature("transcript", "", 1, 2, 0f,
             null);
-    assertFalse(testee.identifiesSequence(sf, accId));
+    seq.addSequenceFeature(sf1);
 
     // transcript with wrong ID not valid
-    sf.setValue("ID", "transcript");
-    assertFalse(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf2 = new SequenceFeature("transcript", "", 1, 2, 0f,
+            null);
+    sf2.setValue("ID", "transcript");
+    seq.addSequenceFeature(sf2);
 
     // transcript with right ID is valid
-    sf.setValue("ID", "transcript:" + accId);
-    assertTrue(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf3 = new SequenceFeature("transcript", "", 1, 2, 0f,
+            null);
+    sf3.setValue("ID", "transcript:" + accId);
+    seq.addSequenceFeature(sf3);
 
     // transcript sub-type with right ID is valid
-    sf = new SequenceFeature("ncRNA", "", 1, 2, 0f, null);
-    sf.setValue("ID", "transcript:" + accId);
-    assertTrue(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf4 = new SequenceFeature("ncRNA", "", 1, 2, 0f, null);
+    sf4.setValue("ID", "transcript:" + accId);
+    seq.addSequenceFeature(sf4);
 
     // Ensembl treats NMD_transcript_variant as if a transcript
-    sf = new SequenceFeature("NMD_transcript_variant", "", 1, 2, 0f, null);
-    sf.setValue("ID", "transcript:" + accId);
-    assertTrue(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf5 = new SequenceFeature("NMD_transcript_variant", "",
+            1, 2, 0f, null);
+    sf5.setValue("ID", "transcript:" + accId);
+    seq.addSequenceFeature(sf5);
 
     // gene not valid:
-    sf = new SequenceFeature("gene", "", 1, 2, 0f, null);
-    sf.setValue("ID", "transcript:" + accId);
-    assertFalse(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf6 = new SequenceFeature("gene", "", 1, 2, 0f, null);
+    sf6.setValue("ID", "transcript:" + accId);
+    seq.addSequenceFeature(sf6);
 
     // exon not valid:
-    sf = new SequenceFeature("exon", "", 1, 2, 0f, null);
-    sf.setValue("ID", "transcript:" + accId);
-    assertFalse(testee.identifiesSequence(sf, accId));
+    SequenceFeature sf7 = new SequenceFeature("exon", "", 1, 2, 0f, null);
+    sf7.setValue("ID", "transcript:" + accId);
+    seq.addSequenceFeature(sf7);
+
+    List<SequenceFeature> sfs = new EnsemblGenome()
+            .getIdentifyingFeatures(seq, accId);
+    assertFalse(sfs.contains(sf1));
+    assertFalse(sfs.contains(sf2));
+    assertTrue(sfs.contains(sf3));
+    assertTrue(sfs.contains(sf4));
+    assertTrue(sfs.contains(sf5));
+    assertFalse(sfs.contains(sf6));
+    assertFalse(sfs.contains(sf7));
   }
 
 }
index cc3a3db..460d16c 100644 (file)
@@ -79,19 +79,6 @@ public class EnsemblRestClientTest
       {
         return false;
       }
-
-      @Override
-      protected String getRequestMimeType(boolean b)
-      {
-        return null;
-      }
-
-      @Override
-      protected String getResponseMimeType()
-      {
-        return null;
-      }
-
     };
   }
 
index 9fad30e..be7bdf2 100644 (file)
 package jalview.ext.ensembl;
 
 import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * A convenience class to simplify writing unit tests (pending Mockito or
@@ -65,9 +69,10 @@ public class EnsemblSeqProxyAdapter extends EnsemblSeqProxy
   }
 
   @Override
-  protected boolean identifiesSequence(SequenceFeature sf, String accId)
+  protected List<SequenceFeature> getIdentifyingFeatures(SequenceI seq,
+          String accId)
   {
-    return false;
+    return new ArrayList<>();
   }
 
 }
index 42afa82..69b2ad4 100644 (file)
@@ -23,14 +23,13 @@ package jalview.ext.ensembl;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertSame;
 
-import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.datamodel.features.SequenceFeatures;
 import jalview.gui.JvOptionPane;
 import jalview.io.DataSourceType;
 import jalview.io.FastaFile;
-import jalview.io.FileParse;
 import jalview.io.gff.SequenceOntologyFactory;
 import jalview.io.gff.SequenceOntologyLite;
 
@@ -125,7 +124,11 @@ public class EnsemblSeqProxyTest
                   + "LKKALMMRGLIPECCAVYRIQDGEKKPIGWDTDISWLTGEELHVEVLENVPLTTHNFVRK\n"
                   + "TFFTLAFCDFCRKLLFQGFRCQTCGYKFHQRCSTEVPLMCVNYDQLDLLFVSKFFEHHPI\n"
                   + "PQEEASLAETALTSGSSPSAPASDSIGPQILTSPSPSKSIPIPQPFRPADEDHRNQFGQR\n"
-                  + "DRSSSAPNVHINTIEPVNIDDLIRDQGFRGDGGSTTGLSATPPASLPGSLTNVKALQKSP\n"
+                  + "DRSSSAPNVHINTIEPVNIDDLIRDQGFRGDG\n"
+                  // ? insertion added in ENSP00000288602.11, not in P15056
+                  + "APLNQLMRCLRKYQSRTPSPLLHSVPSEIVFDFEPGPVFR\n"
+                  // end insertion
+                  + "GSTTGLSATPPASLPGSLTNVKALQKSP\n"
                   + "GPQRERKSSSSSEDRNRMKTLGRRDSSDDWEIPDGQITVGQRIGSGSFGTVYKGKWHGDV\n"
                   + "AVKMLNVTAPTPQQLQAFKNEVGVLRKTRHVNILLFMGYSTKPQLAIVTQWCEGSSLYHH\n"
                   + "LHIIETKFEMIKLIDIARQTAQGMDYLHAKSIIHRDLKSNNIFLHEDLTVKIGDFGLATV\n"
@@ -153,22 +156,21 @@ public class EnsemblSeqProxyTest
   }
 
   @Test(dataProvider = "ens_seqs", suiteName = "live")
-  public void testGetOneSeqs(EnsemblRestClient proxy, String sq,
+  public void testGetSequenceRecords(EnsemblSeqProxy proxy, String sq,
           String fastasq) throws Exception
   {
-    FileParse fp = proxy.getSequenceReader(Arrays
-            .asList(new String[] { sq }));
-    SequenceI[] sqs = new FastaFile(fp).getSeqsAsArray();
     FastaFile trueRes = new FastaFile(fastasq, DataSourceType.PASTE);
-    SequenceI[] trueSqs = trueRes.getSeqsAsArray();
-    Assert.assertEquals(sqs.length, trueSqs.length,
+    SequenceI[] expected = trueRes.getSeqsAsArray();
+    AlignmentI retrieved = proxy.getSequenceRecords(sq);
+
+    Assert.assertEquals(retrieved.getHeight(), expected.length,
             "Different number of sequences retrieved for query " + sq);
-    Alignment ral = new Alignment(sqs);
-    for (SequenceI tr : trueSqs)
+
+    for (SequenceI tr : expected)
     {
       SequenceI[] rseq;
       Assert.assertNotNull(
-              rseq = ral.findSequenceMatch(tr.getName()),
+              rseq = retrieved.findSequenceMatch(tr.getName()),
               "Couldn't find sequences matching expected sequence "
                       + tr.getName());
       Assert.assertEquals(rseq.length, 1,
@@ -179,7 +181,6 @@ public class EnsemblSeqProxyTest
               "Sequences differ for " + tr.getName() + "\n" + "Exp:"
                       + tr.getSequenceAsString() + "\n" + "Got:"
                       + rseq[0].getSequenceAsString());
-
     }
   }
 
index 68ee98c..5298680 100644 (file)
@@ -48,17 +48,17 @@ public class SeqCanvasTest
     AlignmentI al = av.getAlignment();
     assertEquals(al.getWidth(), 157);
     assertEquals(al.getHeight(), 15);
+    av.getRanges().setStartEndSeq(0, 14);
+
+    SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
 
     av.setWrapAlignment(true);
-    av.getRanges().setStartEndSeq(0, 14);
     av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
     int charHeight = av.getCharHeight();
     int charWidth = av.getCharWidth();
     assertEquals(charHeight, 17);
     assertEquals(charWidth, 12);
 
-    SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
-
     /*
      * first with scales above, left, right
      */
@@ -298,4 +298,42 @@ public class SeqCanvasTest
     testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
     assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
   }
+
+  /**
+   * Test simulates loading an unwrapped alignment, shrinking it vertically so
+   * not all sequences are visible, then changing to wrapped mode. The ranges
+   * endSeq should be unchanged, but the vertical repeat height should include
+   * all sequences.
+   */
+  @Test(groups = "Functional")
+  public void testCalculateWrappedGeometry_fromScrolled()
+  {
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/uniref50.fa", DataSourceType.FILE);
+    AlignViewport av = af.getViewport();
+    AlignmentI al = av.getAlignment();
+    assertEquals(al.getWidth(), 157);
+    assertEquals(al.getHeight(), 15);
+    av.getRanges().setStartEndSeq(0, 3);
+    av.setShowAnnotation(false);
+    av.setScaleAboveWrapped(true);
+
+    SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
+
+    av.setWrapAlignment(true);
+    av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
+    int charHeight = av.getCharHeight();
+    int charWidth = av.getCharWidth();
+    assertEquals(charHeight, 17);
+    assertEquals(charWidth, 12);
+
+    int canvasWidth = 400;
+    int canvasHeight = 300;
+    testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+
+    assertEquals(av.getRanges().getEndSeq(), 3); // unchanged
+    int repeatingHeight = (int) PA.getValue(testee,
+            "wrappedRepeatHeightPx");
+    assertEquals(repeatingHeight, charHeight * (2 + al.getHeight()));
+  }
 }
index 4273e6c..e86c8ad 100644 (file)
@@ -38,6 +38,8 @@ import java.util.BitSet;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
@@ -54,7 +56,8 @@ public class StockholmFileTest
   }
 
   static String PfamFile = "examples/PF00111_seed.stk",
-          RfamFile = "examples/RF00031_folded.stk";
+          RfamFile = "examples/RF00031_folded.stk",
+          RnaSSTestFile = "examples/rna_ss_test.stk";
 
   @Test(groups = { "Functional" })
   public void pfamFileIO() throws Exception
@@ -230,8 +233,8 @@ public class StockholmFileTest
     // we might want to revise this in future
     int aa_new_size = (aa_new == null ? 0 : aa_new.length);
     int aa_original_size = (aa_original == null ? 0 : aa_original.length);
-    Map<Integer, BitSet> orig_groups = new HashMap<Integer, BitSet>();
-    Map<Integer, BitSet> new_groups = new HashMap<Integer, BitSet>();
+    Map<Integer, BitSet> orig_groups = new HashMap<>();
+    Map<Integer, BitSet> new_groups = new HashMap<>();
 
     if (aa_new != null && aa_original != null)
     {
@@ -623,13 +626,13 @@ public class StockholmFileTest
   {
     for (char ch : new char[] { '{', '}', '[', ']', '(', ')', '<', '>' })
     {
-      Assert.assertTrue(StockholmFile.DETECT_BRACKETS.matchAt("" + ch, 0),
-              "Didn't recognise " + ch + " as a WUSS bracket");
+      Assert.assertTrue(StockholmFile.RNASS_BRACKETS.indexOf(ch) >= 0,
+              "Didn't recognise '" + ch + "' as a WUSS bracket");
     }
-    for (char ch : new char[] { '@', '!', 'V', 'Q', '*', ' ', '-', '.' })
+    for (char ch : new char[] { '@', '!', '*', ' ', '-', '.' })
     {
-      Assert.assertFalse(StockholmFile.DETECT_BRACKETS.matchAt("" + ch, 0),
-              "Shouldn't recognise " + ch + " as a WUSS bracket");
+      Assert.assertFalse(StockholmFile.RNASS_BRACKETS.indexOf(ch) >= 0,
+              "Shouldn't recognise '" + ch + "' as a WUSS bracket");
     }
   }
   private static void roundTripSSForRNA(String aliFile, String annFile)
@@ -654,4 +657,191 @@ public class StockholmFileTest
     testAlignmentEquivalence(al, newAl, true, true, true);
 
   }
+
+  // this is the single sequence alignment and the SS annotations equivalent to
+  // the ones in file RnaSSTestFile
+  String aliFileRnaSS = ">Test.sequence/1-14\n"
+          + "GUACAAAAAAAAAA";
+  String annFileRnaSSAlphaChars = "JALVIEW_ANNOTATION\n"
+          + "# Created: Thu Aug 02 14:54:57 BST 2018\n" + "\n"
+          + "NO_GRAPH\tSecondary Structure\tSecondary Structure\t<,<|(,(|E,E|H,H|B,B|h,h|e,e|b,b|(,(|E,E|),)|e,e|),)|>,>|\t2.0\n"
+          + "\n"
+          + "ROWPROPERTIES\tSecondary Structure\tscaletofit=true\tshowalllabs=true\tcentrelabs=false\n"
+          + "\n" + "\n" + "ALIGNMENT\tID=RNA.SS.TEST\tTP=RNA;";
+  String wrongAnnFileRnaSSAlphaChars = "JALVIEW_ANNOTATION\n"
+          + "# Created: Thu Aug 02 14:54:57 BST 2018\n" + "\n"
+          + "NO_GRAPH\tSecondary Structure\tSecondary Structure\t<,<|(,(|H,H|E,E|B,B|h,h|e,e|b,b|(,(|E,E|),)|e,e|),)|>,>|\t2.0\n"
+          + "\n"
+          + "ROWPROPERTIES\tSecondary Structure\tscaletofit=true\tshowalllabs=true\tcentrelabs=false\n"
+          + "\n" + "\n" + "ALIGNMENT\tID=RNA.SS.TEST\tTP=RNA;";
+  @Test(groups = { "Functional" })
+  public void stockholmFileRnaSSAlphaChars() throws Exception
+  {
+    AppletFormatAdapter af = new AppletFormatAdapter();
+    AlignmentI al = af.readFile(RnaSSTestFile, DataSourceType.FILE,
+            jalview.io.FileFormat.Stockholm);
+    Iterable<AlignmentAnnotation> aai = al.findAnnotations(null, null,
+            "Secondary Structure");
+    AlignmentAnnotation aa = aai.iterator().next();
+    Assert.assertTrue(aa.isRNA(),
+            "'" + RnaSSTestFile + "' not recognised as RNA SS");
+    Assert.assertTrue(aa.isValidStruc(),
+            "'" + RnaSSTestFile + "' not recognised as valid structure");
+    Annotation[] as = aa.annotations;
+    char[] As = new char[as.length];
+    for (int i = 0; i < as.length; i++)
+    {
+      As[i] = as[i].secondaryStructure;
+    }
+    char[] shouldBe = { '<', '(', 'E', 'H', 'B', 'h', 'e', 'b', '(', 'E',
+        ')', 'e', ')', '>' };
+    Assert.assertTrue(
+            Arrays.equals(As, shouldBe),
+            "Annotation is " + new String(As) + " but should be "
+                    + new String(shouldBe));
+
+    // this should result in the same RNA SS Annotations
+    AlignmentI newAl = new AppletFormatAdapter().readFile(
+            aliFileRnaSS,
+            DataSourceType.PASTE, jalview.io.FileFormat.Fasta);
+    AnnotationFile aaf = new AnnotationFile();
+    aaf.readAnnotationFile(newAl, annFileRnaSSAlphaChars,
+            DataSourceType.PASTE);
+
+    Assert.assertTrue(
+            testRnaSSAnnotationsEquivalent(al.getAlignmentAnnotation()[0],
+                    newAl.getAlignmentAnnotation()[0]),
+            "RNA SS Annotations SHOULD be pair-wise equivalent (but apparently aren't): \n"
+                    + "RNA SS A 1:" + al.getAlignmentAnnotation()[0] + "\n"
+                    + "RNA SS A 2:" + newAl.getAlignmentAnnotation()[0]);
+
+    // this should NOT result in the same RNA SS Annotations
+    newAl = new AppletFormatAdapter().readFile(
+            aliFileRnaSS, DataSourceType.PASTE,
+            jalview.io.FileFormat.Fasta);
+    aaf = new AnnotationFile();
+    aaf.readAnnotationFile(newAl, wrongAnnFileRnaSSAlphaChars,
+            DataSourceType.PASTE);
+
+    boolean mismatch = testRnaSSAnnotationsEquivalent(al.getAlignmentAnnotation()[0],
+            newAl.getAlignmentAnnotation()[0]);
+    Assert.assertFalse(mismatch,
+            "RNA SS Annotations SHOULD NOT be pair-wise equivalent (but apparently are): \n"
+                    + "RNA SS A 1:" + al.getAlignmentAnnotation()[0] + "\n"
+                    + "RNA SS A 2:" + newAl.getAlignmentAnnotation()[0]);
+  }
+
+  private static boolean testRnaSSAnnotationsEquivalent(
+          AlignmentAnnotation a1,
+          AlignmentAnnotation a2)
+  {
+    return a1.rnaSecondaryStructureEquivalent(a2);
+  }
+
+  String annFileRnaSSWithSpaceChars = "JALVIEW_ANNOTATION\n"
+          + "# Created: Thu Aug 02 14:54:57 BST 2018\n" + "\n"
+          + "NO_GRAPH\tSecondary Structure\tSecondary Structure\t<,<|.,.|H,H| , |B,B|h,h| , |b,b|(,(|E,E|.,.|e,e|),)|>,>|\t2.0\n"
+          + "\n"
+          + "ROWPROPERTIES\tSecondary Structure\tscaletofit=true\tshowalllabs=true\tcentrelabs=false\n"
+          + "\n" + "\n" + "ALIGNMENT\tID=RNA.SS.TEST\tTP=RNA;";
+  String annFileRnaSSWithoutSpaceChars = "JALVIEW_ANNOTATION\n"
+          + "# Created: Thu Aug 02 14:54:57 BST 2018\n" + "\n"
+          + "NO_GRAPH\tSecondary Structure\tSecondary Structure\t<,<|.,.|H,H|.,.|B,B|h,h|.,.|b,b|(,(|E,E|.,.|e,e|),)|>,>|\t2.0\n"
+          + "\n"
+          + "ROWPROPERTIES\tSecondary Structure\tscaletofit=true\tshowalllabs=true\tcentrelabs=false\n"
+          + "\n" + "\n" + "ALIGNMENT\tID=RNA.SS.TEST\tTP=RNA;";
+
+  String wrongAnnFileRnaSSWithoutSpaceChars = "JALVIEW_ANNOTATION\n"
+          + "# Created: Thu Aug 02 14:54:57 BST 2018\n" + "\n"
+          + "NO_GRAPH\tSecondary Structure\tSecondary Structure\t<,<|.,.|H,H|Z,Z|B,B|h,h|z,z|b,b|(,(|E,E|.,.|e,e|),)|>,>|\t2.0\n"
+          + "\n"
+          + "ROWPROPERTIES\tSecondary Structure\tscaletofit=true\tshowalllabs=true\tcentrelabs=false\n"
+          + "\n" + "\n" + "ALIGNMENT\tID=RNA.SS.TEST\tTP=RNA;";
+
+  @Test(groups = { "Functional" })
+  public void stockholmFileRnaSSSpaceChars() throws Exception
+  {
+    AlignmentI alWithSpaces = new AppletFormatAdapter().readFile(
+            aliFileRnaSS, DataSourceType.PASTE,
+            jalview.io.FileFormat.Fasta);
+    AnnotationFile afWithSpaces = new AnnotationFile();
+    afWithSpaces.readAnnotationFile(alWithSpaces,
+            annFileRnaSSWithSpaceChars, DataSourceType.PASTE);
+
+    Iterable<AlignmentAnnotation> aaiWithSpaces = alWithSpaces
+            .findAnnotations(null, null, "Secondary Structure");
+    AlignmentAnnotation aaWithSpaces = aaiWithSpaces.iterator().next();
+    Assert.assertTrue(aaWithSpaces.isRNA(),
+            "'" + aaWithSpaces + "' not recognised as RNA SS");
+    Assert.assertTrue(aaWithSpaces.isValidStruc(),
+            "'" + aaWithSpaces + "' not recognised as valid structure");
+    Annotation[] annWithSpaces = aaWithSpaces.annotations;
+    char[] As = new char[annWithSpaces.length];
+    for (int i = 0; i < annWithSpaces.length; i++)
+    {
+      As[i] = annWithSpaces[i].secondaryStructure;
+    }
+    // check all spaces and dots are spaces in the internal representation
+    char[] shouldBe = { '<', ' ', 'H', ' ', 'B', 'h', ' ', 'b', '(', 'E',
+        ' ', 'e', ')', '>' };
+    Assert.assertTrue(Arrays.equals(As, shouldBe), "Annotation is "
+            + new String(As) + " but should be " + new String(shouldBe));
+
+    // this should result in the same RNA SS Annotations
+    AlignmentI alWithoutSpaces = new AppletFormatAdapter().readFile(
+            aliFileRnaSS, DataSourceType.PASTE,
+            jalview.io.FileFormat.Fasta);
+    AnnotationFile afWithoutSpaces = new AnnotationFile();
+    afWithoutSpaces.readAnnotationFile(alWithoutSpaces,
+            annFileRnaSSWithoutSpaceChars,
+            DataSourceType.PASTE);
+
+    Assert.assertTrue(
+            testRnaSSAnnotationsEquivalent(
+                    alWithSpaces.getAlignmentAnnotation()[0],
+                    alWithoutSpaces.getAlignmentAnnotation()[0]),
+            "RNA SS Annotations SHOULD be pair-wise equivalent (but apparently aren't): \n"
+                    + "RNA SS A 1:"
+                    + alWithSpaces.getAlignmentAnnotation()[0]
+                            .getRnaSecondaryStructure()
+                    + "\n" + "RNA SS A 2:"
+                    + alWithoutSpaces.getAlignmentAnnotation()[0]
+                            .getRnaSecondaryStructure());
+
+    // this should NOT result in the same RNA SS Annotations
+    AlignmentI wrongAlWithoutSpaces = new AppletFormatAdapter().readFile(
+            aliFileRnaSS, DataSourceType.PASTE,
+            jalview.io.FileFormat.Fasta);
+    AnnotationFile wrongAfWithoutSpaces = new AnnotationFile();
+    wrongAfWithoutSpaces.readAnnotationFile(wrongAlWithoutSpaces,
+            wrongAnnFileRnaSSWithoutSpaceChars,
+            DataSourceType.PASTE);
+
+    Assert.assertFalse(
+            testRnaSSAnnotationsEquivalent(
+                    alWithSpaces.getAlignmentAnnotation()[0],
+                    wrongAlWithoutSpaces.getAlignmentAnnotation()[0]),
+            "RNA SS Annotations SHOULD NOT be pair-wise equivalent (but apparently are): \n"
+                    + "RNA SS A 1:"
+                    + alWithSpaces.getAlignmentAnnotation()[0]
+                            .getRnaSecondaryStructure()
+                    + "\n" + "RNA SS A 2:"
+                    + wrongAlWithoutSpaces.getAlignmentAnnotation()[0]
+                            .getRnaSecondaryStructure());
+
+    // check no spaces in the output
+    // TODO: create a better 'save as <format>' pattern
+    alWithSpaces.getAlignmentAnnotation()[0].visible = true;
+    StockholmFile sf = new StockholmFile(alWithSpaces);
+
+    String stockholmFile = sf.print(alWithSpaces.getSequencesArray(), true);
+    Pattern noSpacesInRnaSSAnnotation = Pattern
+            .compile("\\n#=GC SS_cons\\s+\\S{14}\\n");
+    Matcher m = noSpacesInRnaSSAnnotation.matcher(stockholmFile);
+    boolean matches = m.find();
+    Assert.assertTrue(matches,
+            "StockholmFile output does not contain expected output (may contain spaces):\n"
+                    + stockholmFile);
+
+  }
 }
index 1acc9e1..86dcc39 100644 (file)
@@ -828,22 +828,31 @@ public class MapListTest
      */
     MapList ml1 = new MapList(new int[] { 3, 4, 8, 12 }, new int[] { 5, 8,
         11, 13 }, 1, 1);
+    assertEquals("{[3, 4], [8, 12]}", prettyPrint(ml1.getFromRanges()));
+    assertEquals("{[5, 8], [11, 13]}", prettyPrint(ml1.getToRanges()));
+
     MapList ml2 = new MapList(new int[] { 1, 50 }, new int[] { 40, 45, 70,
         75, 90, 127 }, 1, 1);
+    assertEquals("{[1, 50]}", prettyPrint(ml2.getFromRanges()));
+    assertEquals("{[40, 45], [70, 75], [90, 127]}",
+            prettyPrint(ml2.getToRanges()));
+
     MapList compound = ml1.traverse(ml2);
 
-    assertEquals(compound.getFromRatio(), 1);
-    assertEquals(compound.getToRatio(), 1);
+    assertEquals(1, compound.getFromRatio());
+    assertEquals(1, compound.getToRatio());
     List<int[]> fromRanges = compound.getFromRanges();
-    assertEquals(fromRanges.size(), 2);
+    assertEquals(2, fromRanges.size());
     assertArrayEquals(new int[] { 3, 4 }, fromRanges.get(0));
     assertArrayEquals(new int[] { 8, 12 }, fromRanges.get(1));
     List<int[]> toRanges = compound.getToRanges();
-    assertEquals(toRanges.size(), 2);
+    assertEquals(4, toRanges.size());
     // 5-8 maps to 44-45,70-71
     // 11-13 maps to 74-75,90
-    assertArrayEquals(new int[] { 44, 45, 70, 71 }, toRanges.get(0));
-    assertArrayEquals(new int[] { 74, 75, 90, 90 }, toRanges.get(1));
+    assertArrayEquals(new int[] { 44, 45 }, toRanges.get(0));
+    assertArrayEquals(new int[] { 70, 71 }, toRanges.get(1));
+    assertArrayEquals(new int[] { 74, 75 }, toRanges.get(2));
+    assertArrayEquals(new int[] { 90, 90 }, toRanges.get(3));
 
     /*
      * 1:1 over 1:1 backwards ('reverse strand')
@@ -853,14 +862,15 @@ public class MapListTest
             new int[] { 1000, 901, 600, 201 }, 1, 1);
     compound = ml1.traverse(ml2);
 
-    assertEquals(compound.getFromRatio(), 1);
-    assertEquals(compound.getToRatio(), 1);
+    assertEquals(1, compound.getFromRatio());
+    assertEquals(1, compound.getToRatio());
     fromRanges = compound.getFromRanges();
-    assertEquals(fromRanges.size(), 1);
+    assertEquals(1, fromRanges.size());
     assertArrayEquals(new int[] { 1, 50 }, fromRanges.get(0));
     toRanges = compound.getToRanges();
-    assertEquals(toRanges.size(), 1);
-    assertArrayEquals(new int[] { 931, 901, 600, 582 }, toRanges.get(0));
+    assertEquals(2, toRanges.size());
+    assertArrayEquals(new int[] { 931, 901 }, toRanges.get(0));
+    assertArrayEquals(new int[] { 600, 582 }, toRanges.get(1));
 
     /*
      * 1:1 plus 1:3 should result in 1:3
@@ -870,15 +880,16 @@ public class MapListTest
             1, 3);
     compound = ml1.traverse(ml2);
 
-    assertEquals(compound.getFromRatio(), 1);
-    assertEquals(compound.getToRatio(), 3);
+    assertEquals(1, compound.getFromRatio());
+    assertEquals(3, compound.getToRatio());
     fromRanges = compound.getFromRanges();
-    assertEquals(fromRanges.size(), 1);
+    assertEquals(1, fromRanges.size());
     assertArrayEquals(new int[] { 1, 30 }, fromRanges.get(0));
     // 11-40 maps to 31-50,91-160
     toRanges = compound.getToRanges();
-    assertEquals(toRanges.size(), 1);
-    assertArrayEquals(new int[] { 31, 50, 91, 160 }, toRanges.get(0));
+    assertEquals(2, toRanges.size());
+    assertArrayEquals(new int[] { 31, 50 }, toRanges.get(0));
+    assertArrayEquals(new int[] { 91, 160 }, toRanges.get(1));
 
     /*
      * 3:1 plus 1:1 should result in 3:1
@@ -888,15 +899,16 @@ public class MapListTest
             1, 1);
     compound = ml1.traverse(ml2);
 
-    assertEquals(compound.getFromRatio(), 3);
-    assertEquals(compound.getToRatio(), 1);
+    assertEquals(3, compound.getFromRatio());
+    assertEquals(1, compound.getToRatio());
     fromRanges = compound.getFromRanges();
-    assertEquals(fromRanges.size(), 1);
+    assertEquals(1, fromRanges.size());
     assertArrayEquals(new int[] { 1, 30 }, fromRanges.get(0));
     // 11-20 maps to 11-15, 91-95
     toRanges = compound.getToRanges();
-    assertEquals(toRanges.size(), 1);
-    assertArrayEquals(new int[] { 11, 15, 91, 95 }, toRanges.get(0));
+    assertEquals(2, toRanges.size());
+    assertArrayEquals(new int[] { 11, 15 }, toRanges.get(0));
+    assertArrayEquals(new int[] { 91, 95 }, toRanges.get(1));
 
     /*
      * 1:3 plus 3:1 should result in 1:1
@@ -906,15 +918,16 @@ public class MapListTest
             3, 1);
     compound = ml1.traverse(ml2);
 
-    assertEquals(compound.getFromRatio(), 1);
-    assertEquals(compound.getToRatio(), 1);
+    assertEquals(1, compound.getFromRatio());
+    assertEquals(1, compound.getToRatio());
     fromRanges = compound.getFromRanges();
-    assertEquals(fromRanges.size(), 1);
+    assertEquals(1, fromRanges.size());
     assertArrayEquals(new int[] { 21, 40 }, fromRanges.get(0));
     // 13-72 maps 3:1 to 55-70, 121-124
     toRanges = compound.getToRanges();
-    assertEquals(toRanges.size(), 1);
-    assertArrayEquals(new int[] { 55, 70, 121, 124 }, toRanges.get(0));
+    assertEquals(2, toRanges.size());
+    assertArrayEquals(new int[] { 55, 70 }, toRanges.get(0));
+    assertArrayEquals(new int[] { 121, 124 }, toRanges.get(1));
 
     /*
      * 3:1 plus 1:3 should result in 1:1
@@ -924,15 +937,16 @@ public class MapListTest
             1, 3);
     compound = ml1.traverse(ml2);
 
-    assertEquals(compound.getFromRatio(), 1);
-    assertEquals(compound.getToRatio(), 1);
+    assertEquals(1, compound.getFromRatio());
+    assertEquals(1, compound.getToRatio());
     fromRanges = compound.getFromRanges();
-    assertEquals(fromRanges.size(), 1);
+    assertEquals(1, fromRanges.size());
     assertArrayEquals(new int[] { 31, 90 }, fromRanges.get(0));
     // 13-32 maps to 47-50,71-126
     toRanges = compound.getToRanges();
-    assertEquals(toRanges.size(), 1);
-    assertArrayEquals(new int[] { 47, 50, 71, 126 }, toRanges.get(0));
+    assertEquals(2, toRanges.size());
+    assertArrayEquals(new int[] { 47, 50 }, toRanges.get(0));
+    assertArrayEquals(new int[] { 71, 126 }, toRanges.get(1));
 
     /*
      * method returns null if not all regions are mapped through
index cc3dca8..d1e32b9 100644 (file)
@@ -62,7 +62,7 @@ public class PDBSequenceFetcherTest
     Cache.applicationProperties.setProperty("ADD_SS_ANN",
             Boolean.TRUE.toString());
 
-    sf = new SequenceFetcher(false);
+    sf = new SequenceFetcher();
   }
 
   /**
index 32afd5f..0b501ee 100644 (file)
@@ -52,26 +52,24 @@ public class SequenceFetcherTest
    */
   public static void main(String[] argv)
   {
-    // TODO: extracted from SequenceFetcher - convert to proper unit test with
+    // TODO: extracted from SequenceFetcher - convert to network dependent
+    // functional integration test with
     // assertions
 
     String usage = "SequenceFetcher.main [-nodas] [<DBNAME> [<ACCNO>]]\n"
             + "With no arguments, all DbSources will be queried with their test Accession number.\n"
             + "With one argument, the argument will be resolved to one or more db sources and each will be queried with their test accession only.\n"
-            + "If given two arguments, SequenceFetcher will try to find the DbFetcher corresponding to <DBNAME> and retrieve <ACCNO> from it.\n"
-            + "The -nodas option will exclude DAS sources from the database fetchers Jalview will try to use.";
-    boolean withDas = true;
-    if (argv != null && argv.length > 0
-            && argv[0].toLowerCase().startsWith("-nodas"))
+            + "If given two arguments, SequenceFetcher will try to find the DbFetcher corresponding to <DBNAME> and retrieve <ACCNO> from it.";
+
+    if (argv != null && argv.length > 0)
     {
-      withDas = false;
       String targs[] = new String[argv.length - 1];
       System.arraycopy(argv, 1, targs, 0, targs.length);
       argv = targs;
     }
     if (argv != null && argv.length > 0)
     {
-      List<DbSourceProxy> sps = new SequenceFetcher(withDas)
+      List<DbSourceProxy> sps = new SequenceFetcher()
               .getSourceProxy(argv[0]);
 
       if (sps != null)
@@ -102,7 +100,7 @@ public class SequenceFetcherTest
       System.out.println(usage);
       return;
     }
-    ASequenceFetcher sfetcher = new SequenceFetcher(withDas);
+    ASequenceFetcher sfetcher = new SequenceFetcher();
     String[] dbSources = sfetcher.getSupportedDb();
     for (int dbsource = 0; dbsource < dbSources.length; dbsource++)
     {
@@ -124,7 +122,7 @@ public class SequenceFetcherTest
           String testQuery)
   {
     AlignmentI ds = null;
-    Vector<Object[]> noProds = new Vector<Object[]>();
+    Vector<Object[]> noProds = new Vector<>();
     System.out.println("Source: " + sp.getDbName() + " (" + db
             + "): retrieving test:" + sp.getTestQuery());
     {
index 90d4472..e04d195 100644 (file)
@@ -51,7 +51,7 @@ public class RemoteFormatTest
     Cache.applicationProperties.setProperty("ADD_SS_ANN",
             Boolean.TRUE.toString());
 
-    sf = new SequenceFetcher(false);
+    sf = new SequenceFetcher();
   }
 
   @DataProvider(name = "AccessionData")
@@ -92,7 +92,7 @@ public class RemoteFormatTest
   @Test(groups = { "Network" })
   public void testUniprotFreeTextSearch() throws Exception
   {
-    List<FTSDataColumnI> wantedFields = new ArrayList<FTSDataColumnI>();
+    List<FTSDataColumnI> wantedFields = new ArrayList<>();
     FTSRestClientI client = UniProtFTSRestClient.getInstance();
     wantedFields.add(client.getDataColumnByNameOrCode("id"));
     wantedFields.add(client.getDataColumnByNameOrCode("entry name"));
index c603a11..060c303 100644 (file)
@@ -35,6 +35,7 @@ import java.io.Reader;
 import java.io.StringReader;
 import java.util.Vector;
 
+import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
@@ -66,6 +67,9 @@ public class UniprotTest
           + "<feature type=\"sequence variant\"><original>M</original><variation>L</variation><location><position position=\"41\"/></location></feature>"
           + "<feature type=\"sequence variant\" description=\"Pathogenic\"><original>M</original><variation>L</variation><location><position position=\"41\"/></location></feature>"
           + "<feature type=\"sequence variant\" description=\"Pathogenic\"><original>M</original><location><position position=\"41\"/></location></feature>"
+          + "<feature type=\"sequence variant\" description=\"Foo\"><variation>L</variation><variation>LMV</variation><original>M</original><location><position position=\"42\"/></location></feature>"
+          + "<feature type=\"sequence variant\" description=\"Foo\"><variation>LL</variation><variation>LMV</variation><original>ML</original><location><begin position=\"42\"/><end position=\"43\"/></location></feature>"
+          + "<feature type=\"sequence variant\" description=\"Foo Too\"><variation>LL</variation><variation>LMVK</variation><original>MLML</original><location><begin position=\"42\"/><end position=\"45\"/></location></feature>"
           + "<sequence length=\"10\" mass=\"27410\" checksum=\"8CB760AACF88FE6C\" modified=\"2008-01-15\" version=\"1\">MHAPL VSKDL</sequence></entry>"
           + "</uniprot>";
 
@@ -101,7 +105,7 @@ public class UniprotTest
      * Check sequence features
      */
     Vector<UniprotFeature> features = entry.getFeature();
-    assertEquals(6, features.size());
+    assertEquals(9, features.size());
     UniprotFeature sf = features.get(0);
     assertEquals("signal peptide", sf.getType());
     assertNull(sf.getDescription());
@@ -123,25 +127,50 @@ public class UniprotTest
 
     sf = features.get(3);
     assertEquals("sequence variant", sf.getType());
-    assertEquals("Variation: 'L' Original: 'M'", sf.getDescription());
+    assertNull(sf.getDescription());
     assertEquals(41, sf.getPosition());
     assertEquals(41, sf.getBegin());
     assertEquals(41, sf.getEnd());
 
     sf = features.get(4);
     assertEquals("sequence variant", sf.getType());
-    assertEquals("Pathogenic Variation: 'L' Original: 'M'",
-            sf.getDescription());
+    assertEquals("Pathogenic", sf.getDescription());
     assertEquals(41, sf.getPosition());
     assertEquals(41, sf.getBegin());
     assertEquals(41, sf.getEnd());
 
     sf = features.get(5);
     assertEquals("sequence variant", sf.getType());
-    assertEquals("Pathogenic Original: 'M'", sf.getDescription());
+    assertEquals("Pathogenic", sf.getDescription());
     assertEquals(41, sf.getPosition());
     assertEquals(41, sf.getBegin());
     assertEquals(41, sf.getEnd());
+
+    sf = features.get(6);
+    assertEquals("sequence variant", sf.getType());
+    assertEquals("Foo",
+            sf.getDescription());
+    assertEquals(42, sf.getPosition());
+    assertEquals(42, sf.getBegin());
+    assertEquals(42, sf.getEnd());
+    Assert.assertEquals(Uniprot.getDescription(sf),
+            "<html>p.Met42Leu" + "<br/>&nbsp;&nbsp;"
+                    + "p.Met42LeuMetVal Foo</html>");
+
+    sf = features.get(7);
+    assertEquals(42, sf.getBegin());
+    assertEquals(43, sf.getEnd());
+    Assert.assertEquals(Uniprot.getDescription(sf),
+            "<html>p.MetLeu42LeuLeu" + "<br/>&nbsp;&nbsp;"
+                    + "p.MetLeu42LeuMetVal Foo</html>");
+
+    sf = features.get(8);
+    assertEquals(42, sf.getBegin());
+    assertEquals(45, sf.getEnd());
+    Assert.assertEquals(Uniprot.getDescription(sf),
+            "<html>p.MLML42LeuLeu" + "<br/>&nbsp;&nbsp;"
+                    + "p.MLML42LMVK Foo Too</html>");
+
     /*
      * Check cross-references
      */
@@ -210,4 +239,53 @@ public class UniprotTest
     assertEquals(expectedDescription,
             Uniprot.getUniprotEntryDescription(entry));
   }
+
+  @Test(groups = { "Functional" })
+  public void testGetDescription()
+  {
+    UniprotFeature uf = new UniprotFeature();
+    assertEquals("", Uniprot.getDescription(uf));
+
+    uf.setDescription("Hello");
+    assertEquals("Hello", Uniprot.getDescription(uf));
+
+    uf.setPosition(23);
+    uf.setOriginal("K");
+    Vector<String> vars = new Vector<>();
+    vars.add("y");
+    uf.setVariation(vars);
+    assertEquals("p.Lys23Tyr Hello", Uniprot.getDescription(uf));
+
+    // multiple variants generate an html description over more than one line
+    vars.add("W");
+    assertEquals("<html>p.Lys23Tyr<br/>&nbsp;&nbsp;p.Lys23Trp Hello</html>",
+            Uniprot.getDescription(uf));
+
+    /*
+     * indel cases
+     * up to 3 bases (original or variant) are shown using 3 letter code
+     */
+    vars.clear();
+    vars.add("KWE");
+    uf.setOriginal("KLS");
+    assertEquals("p.LysLeuSer23LysTrpGlu Hello",
+            Uniprot.getDescription(uf));
+
+    // adding a fourth original base switches to single letter code
+    uf.setOriginal("KLST");
+    assertEquals("p.KLST23LysTrpGlu Hello", Uniprot.getDescription(uf));
+
+    // adding a fourth variant switches to single letter code
+    vars.clear();
+    vars.add("KWES");
+    assertEquals("p.KLST23KWES Hello", Uniprot.getDescription(uf));
+
+    vars.clear();
+    vars.add("z"); // unknown variant - fails gracefully
+    uf.setOriginal("K");
+    assertEquals("p.Lys23z Hello", Uniprot.getDescription(uf));
+
+    uf.setVariation(null); // variant missing - is ignored
+    assertEquals("Hello", Uniprot.getDescription(uf));
+  }
 }
diff --git a/test/jalview/ws/seqfetcher/DasSequenceFetcher.java b/test/jalview/ws/seqfetcher/DasSequenceFetcher.java
deleted file mode 100644 (file)
index f1dafcb..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.ws.seqfetcher;
-
-import static org.testng.Assert.assertTrue;
-
-import jalview.bin.Cache;
-import jalview.gui.JvOptionPane;
-
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-public class DasSequenceFetcher
-{
-
-  @BeforeClass(alwaysRun = true)
-  public void setUpJvOptionPane()
-  {
-    JvOptionPane.setInteractiveMode(false);
-    JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
-  }
-
-  @Test(groups = { "Network" })
-  public void testDasRegistryContact()
-  {
-    Cache.getDasSourceRegistry().refreshSources();
-    assertTrue(Cache.getDasSourceRegistry().getSources().isEmpty(),
-            "Expected to find no DAS sources at the registry. Check config.");
-  }
-
-}
index ced9ac0..c69d554 100755 (executable)
@@ -200,7 +200,7 @@ Can be separated by colons (Mac OS/Unix) or semicolons (Windows)]]></string>
                                                        <method name="addElement">
                                                                <object class="com.zerog.ia.installer.util.LAXPropertyData" objectID="97fa91cfa6f7">
                                                                        <property name="propertyValue">
-                                                                               <string><![CDATA[268400000]]></string>
+                                                                               <string><![CDATA[1060000000]]></string>
                                                                        </property>
                                                                        <property name="propertyName">
                                                                                <string><![CDATA[lax.nl.java.option.java.heap.size.max]]></string>
@@ -254,7 +254,7 @@ it will search for ones in this list]]></string>
                                                        <method name="addElement">
                                                                <object class="com.zerog.ia.installer.util.LAXPropertyData" objectID="97f991ffa6f7">
                                                                        <property name="propertyValue">
-                                                                               <string><![CDATA[33554432]]></string>
+                                                                               <string><![CDATA[1000000000]]></string>
                                                                        </property>
                                                                        <property name="propertyName">
                                                                                <string><![CDATA[lax.nl.java.option.java.heap.size.initial]]></string>
@@ -2337,7 +2337,7 @@ and any path to a file to save to the file]]></string>
                 <string><![CDATA[664]]></string>
               </property>
               <property name="sourceName">
-                <string><![CDATA[VAqua4.jar]]></string>
+                <string><![CDATA[VAqua5-patch.jar]]></string>
               </property>
               <property name="overrideUnixPermissions">
                 <boolean>false</boolean>
@@ -2355,10 +2355,10 @@ and any path to a file to save to the file]]></string>
                 <boolean>true</boolean>
               </property>
               <property name="destinationName">
-                <string><![CDATA[VAqua4.jar]]></string>
+                <string><![CDATA[VAqua5-patch.jar]]></string>
               </property>
               <property name="fileSize">
-                <long>1355141</long>
+                <long>1370564</long>
               </property>
               <property name="macBinary">
                 <boolean>false</boolean>
index e9e5176..82062f9 100755 (executable)
@@ -6,18 +6,26 @@ Jalview Readme
 
 To run application:
 
-java -Djava.ext.dirs=JALVIEW_HOME/lib -jar JALVIEW_HOME/jalview.jar [-help ... ]
+java -classpath "JALVIEW_HOME/lib/*" -jar JALVIEW_HOME/jalview.jar [-help ... ]
 
 Replace JALVIEW_HOME with the full path to Jalview Installation Directory.
 Use -help to see the available command line arguments.
 
 For best results use a Sun java run time environment (not the gcj gnu java, sorry!). 
 
-If you want to the java runtime bundled with Jalview, then launch jalview like this:
+If you want to use the java runtime bundled with Jalview, then launch jalview like this:
 
-JAVA_HOME=JALVIEW_HOME/jre JALVIEW_HOME/jre/bin/java -Djava.ext.dirs=JALVIEW_HOME/lib -jar JALVIEW_HOME/jalview.jar 
+in Windows:
+JAVA_HOME=JALVIEW_HOME/jre JALVIEW_HOME/jre/bin/java -classpath "JALVIEW_HOME/lib/*;JALVIEW_HOME/jalview.jar" jalview.bin.Jalview
+
+in Linux:
+JAVA_HOME=JALVIEW_HOME/jre JALVIEW_HOME/jre/bin/java -classpath "JALVIEW_HOME/lib/*:JALVIEW_HOME/jalview.jar" jalview.bin.Jalview
+
+in macOS:
+JAVA_HOME=JALVIEW_HOME/jre/Contents/Home JALVIEW_HOME/jre/Contents/Home/bin/java -classpath "JALVIEW_HOME/lib/*:JALVIEW_HOME/jalview.jar" jalview.bin.Jalview
+
+Note: ensure the -classpath argument is quoted and only use a terminating wildcard (e.g. 'DIR/*') to refer to all jar files in a directory, don't use e.g. 'DIR/*.jar'
 
-Please Note: the -jar jalview.jar option launches the jalview.bin.Jalview class in the jalview.jar
 ##################
 
 
diff --git a/utils/classgraph-4.1.6.jar b/utils/classgraph-4.1.6.jar
new file mode 100644 (file)
index 0000000..a0788bc
Binary files /dev/null and b/utils/classgraph-4.1.6.jar differ