JAL-3253 ApplicationSingletonProvider replaces Instance
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 15 May 2019 16:01:43 +0000 (17:01 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 15 May 2019 16:01:43 +0000 (17:01 +0100)
54 files changed:
resources/lang/Messages.properties
resources/lang/Messages_es.properties
src/jalview/analysis/AlignmentSorter.java
src/jalview/analysis/scoremodels/ScoreModels.java
src/jalview/bin/ApplicationSingletonProvider.java [new file with mode: 0644]
src/jalview/bin/Cache.java
src/jalview/bin/Instance.java [deleted file]
src/jalview/bin/Jalview.java
src/jalview/datamodel/features/FeatureAttributes.java
src/jalview/datamodel/features/FeatureSources.java
src/jalview/ext/ensembl/EnsemblInfo.java
src/jalview/fts/service/pdb/PDBFTSRestClient.java
src/jalview/fts/service/uniprot/UniProtFTSRestClient.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/AssociatePdbFileWithSeq.java
src/jalview/gui/CrossRefAction.java
src/jalview/gui/Desktop.java
src/jalview/gui/SplitFrame.java
src/jalview/gui/VamsasApplication.java
src/jalview/httpserver/HttpServer.java
src/jalview/io/FileFormats.java
src/jalview/io/FileLoader.java
src/jalview/io/VamsasAppDatastore.java
src/jalview/io/cache/AppCache.java
src/jalview/io/gff/SequenceOntologyFactory.java
src/jalview/io/vamsas/Sequencemapping.java
src/jalview/project/Jalview2XML.java
src/jalview/rest/RestHandler.java
src/jalview/schemes/ColourSchemes.java
src/jalview/structure/StructureImportSettings.java
src/jalview/structure/StructureSelectionManager.java
src/jalview/urls/IdOrgSettings.java
src/jalview/ws/SequenceFetcher.java
src/jalview/ws/jws1/Discoverer.java
src/jalview/ws/jws2/Jws2Discoverer.java
src/jalview/ws/jws2/jabaws2/Jws2InstanceFactory.java
src/jalview/ws/rest/RestClient.java
src/jalview/ws/sifts/SiftsSettings.java
test/jalview/analysis/FinderTest.java
test/jalview/analysis/scoremodels/ScoreModelsTest.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/EnsemblSeqProxyTest.java
test/jalview/ext/jmol/JmolCommandsTest.java
test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java
test/jalview/gui/AlignViewportTest.java
test/jalview/io/FeaturesFileTest.java
test/jalview/io/Jalview2xmlBase.java
test/jalview/renderer/seqfeatures/FeatureColourFinderTest.java
test/jalview/structure/Mapping.java
test/jalview/structure/StructureSelectionManagerTest.java
test/jalview/structures/models/AAStructureBindingModelTest.java

index 6c11705..36ade0b 100644 (file)
@@ -954,8 +954,6 @@ error.implementation_error_maplist_is_null = Implementation error. MapList is nu
 error.implementation_error_cannot_have_null_alignment = Implementation error: Cannot have null alignment property key
 error.implementation_error_null_fileparse = Implementation error. Null FileParse in copy constructor
 error.implementation_error_cannot_map_alignment_sequences = IMPLEMENTATION ERROR: Cannot map an alignment of sequences from different datasets into a single alignment in the vamsas document.
-error.implementation_error_structure_selection_manager_null = Implementation error. Structure selection manager's context is 'null'
-exception.ssm_context_is_null = SSM context is null
 error.idstring_seqstrings_only_one_per_sequence = idstrings and seqstrings contain one string each per sequence
 error.cannot_have_mixed_length_replacement_vectors = Cannot have mixed length replacement vectors. Replacement vector for {0} is {1} strings long, and have already seen a {2} length vector.
 error.cannot_have_zero_length_vector_replacement_strings = Cannot have zero length vector of replacement strings - either 1 value or n values.
index 8f91dc7..8bd22a0 100644 (file)
@@ -879,8 +879,6 @@ error.implementation_error_maplist_is_null = Error de implementaci
 error.implementation_error_cannot_have_null_alignment = Error de implementación: no es posible tener una clave nula en el alineamiento
 error.implementation_error_null_fileparse = Error de implementación. FileParse nulo en el construictor de copia
 error.implementation_error_cannot_map_alignment_sequences = Error de implementación: no es posible maper un alineamiento de secuencias desde distintos conjuntos de datos en un único alineamiento en el documento VAMSAS.
-error.implementation_error_structure_selection_manager_null = Error de implementación. El contexto structure selection manager's es nulo
-exception.ssm_context_is_null = El contexto SSM es nulo
 error.idstring_seqstrings_only_one_per_sequence = idstrings y seqstrings contienen una cadena por cada secuencia
 error.cannot_have_mixed_length_replacement_vectors = No es posible tener vectores de reemplazo de distinta longitud. El vector de reemplazo para {0} es de {1} cadenas de largo, pero se ha considerado ya como un vector de longitud {2}.
 error.cannot_have_zero_length_vector_replacement_strings = No es posible tener un vector de cadenas de reemplazo de longitud cero - debe ser uno o n.
index e9eee16..8634db6 100755 (executable)
@@ -22,7 +22,8 @@ package jalview.analysis;
 
 import jalview.analysis.scoremodels.PIDModel;
 import jalview.analysis.scoremodels.SimilarityParams;
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AlignmentOrder;
@@ -52,7 +53,7 @@ import java.util.List;
  * from the first tobesorted position in the alignment. e.g. (a,tb2,b,tb1,c,tb3
  * becomes a,tb1,tb2,tb3,b,c)
  */
-public class AlignmentSorter
+public class AlignmentSorter implements ApplicationSingletonI
 {
 
   private AlignmentSorter()
@@ -62,10 +63,8 @@ public class AlignmentSorter
 
   private static AlignmentSorter getInstance()
   {
-    Instance j = Instance.getInstance();
-    return (j.alignmentSorter == null
-            ? j.alignmentSorter = new AlignmentSorter()
-            : j.alignmentSorter);
+    return (AlignmentSorter) ApplicationSingletonProvider
+            .getInstance(AlignmentSorter.class);
   }
 
   /**
index 7431b86..8700ec0 100644 (file)
@@ -22,7 +22,8 @@ package jalview.analysis.scoremodels;
 
 import jalview.api.AlignmentViewPanel;
 import jalview.api.analysis.ScoreModelI;
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.io.DataSourceType;
 import jalview.io.FileParse;
 import jalview.io.ScoreMatrixFile;
@@ -34,7 +35,7 @@ import java.util.Map;
 /**
  * A class that can register and serve instances of ScoreModelI
  */
-public class ScoreModels
+public class ScoreModels implements ApplicationSingletonI
 {
   /**
    * Answers the singleton instance of this class, with lazy initialisation
@@ -44,9 +45,7 @@ public class ScoreModels
    */
   public static ScoreModels getInstance()
   {
-    Instance j = Instance.getInstance();
-    return (j.scoreModels == null ? j.scoreModels = new ScoreModels()
-            : j.scoreModels);
+    return (ScoreModels) ApplicationSingletonProvider.getInstance(ScoreModels.class);
   }
 
   /**
@@ -150,7 +149,7 @@ public class ScoreModels
    */
   public void reset()
   {
-    Instance.getInstance().scoreModels = new ScoreModels();
+    ApplicationSingletonProvider.removeInstance(this.getClass());
   }
 
   /**
diff --git a/src/jalview/bin/ApplicationSingletonProvider.java b/src/jalview/bin/ApplicationSingletonProvider.java
new file mode 100644 (file)
index 0000000..eb82104
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.bin;
+
+import jalview.util.Platform;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A class to hold singleton objects, whose scope (context) is
+ * <ul>
+ * <li>the Java runtime (JVM) when running as Java</li>
+ * <li>one 'applet', when running as JalviewJS</li>
+ * </ul>
+ * This allows separation of multiple JS applets running on the same browser
+ * page, each with their own 'singleton' instances.
+ * <p>
+ * Instance objects are held in a separate Map (keyed by Class) for each
+ * context. For Java, this is just a single static Map. For SwingJS, the map is
+ * stored as a field {@code _swingjsSingletons} of
+ * {@code Thread.currentThread.getThreadGroup()}, as a proxy for the applet.
+ * <p>
+ * Note that when an applet is stopped, its ThreadGroup is removed, allowing any
+ * singleton references to be garbage collected.
+ * 
+ * @author hansonr
+ */
+public class ApplicationSingletonProvider
+{
+  /**
+   * A tagging interface to mark classes whose singleton instances may be served
+   * by {@code ApplicationSingletonProvider}, giving a distinct instance per JS
+   * 'applet'.
+   * <p>
+   * A class whose singleton should have global scope (be shared across all
+   * applets on a page) should <em>not</em> use this mechanism, but just provide
+   * a single instance (class static member) in the normal way.
+   */
+  public interface ApplicationSingletonI
+  {
+  }
+  
+  /*
+   * Map used to hold singletons in JVM context
+   */
+  private static Map<Class<? extends ApplicationSingletonI>, ApplicationSingletonI> singletons = new HashMap<>();
+
+  /**
+   * private constructor for non-instantiable class
+   */
+  private ApplicationSingletonProvider()
+  {
+  }
+
+  /**
+   * Returns the singletons map for the current context (JVM for Java,
+   * ThreadGroup for JS), creating the map on the first request for each JS
+   * ThreadGroup
+   * 
+   * @return
+   */
+  private static Map<Class<? extends ApplicationSingletonI>, ApplicationSingletonI> getContextMap()
+  {
+    @SuppressWarnings("unused")
+    ThreadGroup g = (Platform.isJS()
+            ? Thread.currentThread().getThreadGroup()
+            : null);
+    Map<Class<? extends ApplicationSingletonI>, ApplicationSingletonI> map = singletons;
+    /** @j2sNative map = g._swingjsSingletons; */
+    if (map == null)
+    {
+      map = new HashMap<>();
+      /** @j2sNative g._swingjsSingletons = map; */
+    }
+
+    return map;
+  }
+
+  /**
+   * Answers the singleton instance of the given class for the current context
+   * (JVM or SwingJS 'applet'). If no instance yet exists, one is created, by
+   * calling the class's no-argument constructor. Answers null if any error
+   * occurs (or occurred previously for the same class).
+   * 
+   * @param c
+   * @return
+   */
+  public static ApplicationSingletonI getInstance(Class<? extends ApplicationSingletonI> c)
+  {
+    Map<Class<? extends ApplicationSingletonI>, ApplicationSingletonI> map = getContextMap();
+    if (map.containsKey(c))
+    {
+      /*
+       * singleton already created _or_ creation failed (null value stored)
+       */
+      return map.get(c);
+    }
+
+    /*
+     * create and save the singleton
+     */
+    ApplicationSingletonI o = map.get(c);
+    try
+    {
+      Constructor<? extends ApplicationSingletonI> con = c
+              .getDeclaredConstructor();
+      con.setAccessible(true);
+      o = con.newInstance();
+    } catch (IllegalAccessException | InstantiationException
+            | IllegalArgumentException | InvocationTargetException
+            | NoSuchMethodException | SecurityException e)
+    {
+      Cache.log.error("Failed to create singleton for " + c.toString()
+              + ", error was: " + e.toString());
+      e.printStackTrace();
+    }
+
+    /*
+     * store the new singleton; note that a
+     * null value is saved if construction failed
+     */
+    getContextMap().put(c, o);
+
+    return o;
+  }
+
+  /**
+   * Removes the current singleton instance of the given class from the current
+   * application context. This has the effect of ensuring that a new instance is
+   * created the next time one is requested.
+   * 
+   * @param c
+   */
+  public static void removeInstance(
+          Class<? extends ApplicationSingletonI> c)
+  {
+    Map<Class<? extends ApplicationSingletonI>, ApplicationSingletonI> map = getContextMap();
+    if (map != null)
+    {
+      map.remove(c);
+    }
+  }
+}
index 086419b..c95b507 100755 (executable)
@@ -20,6 +20,7 @@
  */
 package jalview.bin;
 
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.datamodel.PDBEntry;
 import jalview.gui.UserDefinedColours;
 import jalview.schemes.ColourSchemeLoader;
@@ -207,7 +208,7 @@ import org.apache.log4j.SimpleLayout;
  * @author $author$
  * @version $Revision$
  */
-public class Cache
+public class Cache implements ApplicationSingletonI
 {
 
   private Cache()
@@ -224,8 +225,7 @@ public class Cache
    */
   private static Cache getInstance()
   {
-    Instance i = Instance.getInstance();
-    return (i.cache == null ? i.cache = new Cache() : i.cache);
+    return (Cache) ApplicationSingletonProvider.getInstance(Cache.class);
   }
 
   /**
diff --git a/src/jalview/bin/Instance.java b/src/jalview/bin/Instance.java
deleted file mode 100644 (file)
index a8db18f..0000000
+++ /dev/null
@@ -1,180 +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.bin;
-
-import jalview.analysis.AlignmentSorter;
-import jalview.analysis.scoremodels.ScoreModels;
-import jalview.api.StructureSelectionManagerProvider;
-import jalview.datamodel.features.FeatureAttributes;
-import jalview.datamodel.features.FeatureSources;
-import jalview.ext.ensembl.EnsemblInfo;
-import jalview.fts.service.pdb.PDBFTSRestClient;
-import jalview.fts.service.uniprot.UniProtFTSRestClient;
-import jalview.gui.Desktop;
-import jalview.httpserver.HttpServer;
-import jalview.io.FileFormats;
-import jalview.io.cache.AppCache;
-import jalview.io.gff.SequenceOntologyFactory;
-import jalview.rest.RestHandler;
-import jalview.schemes.ColourSchemes;
-import jalview.structure.StructureImportSettings;
-import jalview.structure.StructureSelectionManager;
-import jalview.urls.IdOrgSettings;
-import jalview.util.Platform;
-import jalview.ws.jws1.Discoverer;
-import jalview.ws.jws2.Jws2Discoverer;
-import jalview.ws.jws2.jabaws2.Jws2InstanceFactory;
-import jalview.ws.rest.RestClient;
-import jalview.ws.sifts.SiftsSettings;
-
-import java.util.IdentityHashMap;
-
-/**
- * A class to hold singleton instances so that they are not shared among
- * multiple JavaScript apps on a page. Fields are all formerly static class or
- * object references are preserved in this singleton as "pseudo" static
- * references that will be unique for each JavaScript applet or Java
- * application.
- * 
- * There are three kinds of references:
- * 
- * Class references for classes with public getInstance() calls and a private
- * constructor.
- * 
- * Class references for classes with private getInstance() calls and a private
- * constructor.
- * 
- * Object references held here for a class as "pseudo" static field and
- * referenced by Instance.getInstance().fieldName. These classes
- * 
- * @author hansonr
- *
- */
-public class Instance
-{
-
-  private Instance()
-  {
-    // singleton -- use getInstance();
-  }
-
-  private static Instance instance;
-
-  /**
-   * 
-   * Creates a static reference to this class, either as a static field (Java)
-   * or as an element in the applet's ThreadGroup object.
-   * 
-   * @return new Instance()
-   */
-  public static Instance getInstance()
-  {
-
-    // assign g only if JavaScript and instance only if Java
-
-    @SuppressWarnings("unused")
-    ThreadGroup g = (Platform.isJS()
-            ? Thread.currentThread().getThreadGroup()
-            : null);
-    Instance i = /** @j2sNative g._jalviewInstance || */
-            instance;
-    if (i == null)
-    {
-      i = /**
-           * @j2sNative g._jalviewInstance =
-           */
-              new Instance();
-      instance = /** @j2sNative null && */
-              i;
-    }
-    return i;
-  }
-
-  public Jalview jalview;
-
-  public Desktop desktop;
-
-
-
-  // The following are PUBLIC singletons; their class has a private constructor
-  // that is assigned by the class as part of a public static getInstance()
-  // call.
-
-  public AppCache appCache;
-
-  public ColourSchemes colourSchemes;
-
-  public Discoverer discoverer;
-
-  public FileFormats fileFormats;
-
-  public HttpServer httpServer;
-
-  public RestClient restClient;
-
-  public RestHandler restHandler;
-
-  public ScoreModels scoreModels;
-
-  public jalview.ws.SequenceFetcher sequenceFetcher;
-
-  public SiftsSettings siftsSettings;
-
-
-  // The following are PRIVATE singletons; their class has only static public
-  // methods and a private constructor that is assigned by the class as part of
-  // a private static getInstance() call.
-
-  public AlignmentSorter alignmentSorter;
-
-  public Cache cache;
-
-  public EnsemblInfo ensemblInfo;
-
-  public FeatureAttributes featureAttributes;
-
-  public FeatureSources featureSources;
-
-  public IdOrgSettings idOrgSettings;
-
-  public Jws2Discoverer j2s2discoverer;
-
-  public Jws2InstanceFactory jws2InstanceFactory;
-
-  public PDBFTSRestClient pdbFTSRestClient;
-
-  public SequenceOntologyFactory sequenceOntologyFactory;
-
-  public StructureImportSettings structureImportSettings;
-
-  public UniProtFTSRestClient uniprotFTSRestClient;
-
-  // The following formerly static Object references are
-  // preserved in this singleton as "pseudo" static references
-  // that will be unique for each JavaScript applet or Java application.
-
-  /**
-   * StructureSelectionManager "static"
-   */
-  public IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> structureSelections;
-
-
-}
index cb2b469..402f9bf 100755 (executable)
@@ -22,6 +22,7 @@ package jalview.bin;
 
 import jalview.api.AlignViewportI;
 import jalview.api.JalviewApp;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
 import jalview.ext.so.SequenceOntology;
@@ -90,18 +91,17 @@ import groovy.util.GroovyScriptEngine;
  * @author $author$
  * @version $Revision$
  */
-public class Jalview
+public class Jalview implements ApplicationSingletonI
 {
 
   public static Jalview getInstance()
   {
-    Instance i = Instance.getInstance();
-    return (i.jalview == null ? i.jalview = new Jalview() : i.jalview);
+    return (Jalview) ApplicationSingletonProvider
+            .getInstance(Jalview.class);
   }
 
-  public Jalview()
+  private Jalview()
   {
-    Instance.getInstance().jalview = this;
   }
 
   static
@@ -230,7 +230,7 @@ public class Jalview
   public static void main(String[] args)
   {
     // setLogging(); // BH - for event debugging in JavaScript
-    new Jalview().doMain(args);
+    getInstance().doMain(args);
   }
 
   private static void logClass(String name)
@@ -437,12 +437,12 @@ public class Jalview
      */
     if (Cache.getDefault("USE_FULL_SO", false))
     {
-      SequenceOntologyFactory.setInstance(new SequenceOntology());
+      SequenceOntologyFactory.setSequenceOntology(new SequenceOntology());
     }
 
     if (!headless)
     {
-      desktop = new Desktop();
+      desktop = Desktop.getInstance();
       desktop.setInBatchMode(true); // indicate we are starting up
       desktop.setVisible(true);
 
index 81c670b..f51fe48 100644 (file)
@@ -1,6 +1,7 @@
 package jalview.datamodel.features;
 
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -14,7 +15,7 @@ import java.util.TreeMap;
 /**
  * A singleton class to hold the set of attributes known for each feature type
  */
-public class FeatureAttributes
+public class FeatureAttributes implements ApplicationSingletonI
 {
   public enum Datatype
   {
@@ -23,10 +24,8 @@ public class FeatureAttributes
 
   public static FeatureAttributes getInstance()
   {
-    Instance i = Instance.getInstance();
-    return (i.featureAttributes == null
-            ? i.featureAttributes = new FeatureAttributes()
-            : i.featureAttributes);
+    return (FeatureAttributes) ApplicationSingletonProvider
+            .getInstance(FeatureAttributes.class);
   }
 
   private FeatureAttributes()
index a281eea..ec04bad 100644 (file)
@@ -1,19 +1,18 @@
 package jalview.datamodel.features;
 
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 
 import java.util.HashMap;
 import java.util.Map;
 
-public class FeatureSources
+public class FeatureSources implements ApplicationSingletonI
 {
 
   public static FeatureSources getInstance()
   {
-    Instance i = Instance.getInstance();
-    return (i.featureSources == null
-            ? i.featureSources = new FeatureSources()
-            : i.featureSources);
+    return (FeatureSources) ApplicationSingletonProvider
+            .getInstance(FeatureSources.class);
   }
 
   private Map<String, FeatureSourceI> sources;
index a91985c..a59a64d 100644 (file)
@@ -1,6 +1,7 @@
 package jalview.ext.ensembl;
 
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.DBRefSource;
 
@@ -15,19 +16,17 @@ import java.util.Set;
 
 import org.json.simple.parser.ParseException;
 
-public class EnsemblInfo extends EnsemblRestClient
+public class EnsemblInfo extends EnsemblRestClient implements ApplicationSingletonI
 {
 
   /**
    * On first request only, populate the lookup map by fetching the list of
-   * divisions known to EnsemblGenomes.
+   * divisions known to EnsemblGenomes
    * 
    */
   private static EnsemblInfo getInstance()
   {
-    Instance j = Instance.getInstance();
-    return (j.ensemblInfo == null ? j.ensemblInfo = new EnsemblInfo()
-            : j.ensemblInfo);
+    return (EnsemblInfo) ApplicationSingletonProvider.getInstance(EnsemblInfo.class);
   }
 
   private EnsemblInfo()
index 340830e..87d640b 100644 (file)
@@ -20,7 +20,8 @@
  */
 package jalview.fts.service.pdb;
 
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.datamodel.SequenceI;
 import jalview.fts.api.FTSData;
 import jalview.fts.api.FTSDataColumnI;
@@ -54,19 +55,16 @@ import com.sun.jersey.api.client.config.DefaultClientConfig;
  * 
  * @author tcnofoegbu
  */
-public class PDBFTSRestClient extends FTSRestClient
+public class PDBFTSRestClient extends FTSRestClient implements ApplicationSingletonI
 {
+  public static final String PDB_SEARCH_ENDPOINT = "https://www.ebi.ac.uk/pdbe/search/pdb/select?";
 
   public static FTSRestClientI getInstance()
   {
-    Instance j = Instance.getInstance();
-    return (j.pdbFTSRestClient == null
-            ? j.pdbFTSRestClient = new PDBFTSRestClient()
-            : j.pdbFTSRestClient);
+    return (FTSRestClientI) ApplicationSingletonProvider
+            .getInstance(PDBFTSRestClient.class);
   }
 
-  public static final String PDB_SEARCH_ENDPOINT = "https://www.ebi.ac.uk/pdbe/search/pdb/select?";
-
   private PDBFTSRestClient()
   {
     // singleton -- use getInstance()
index 871ba19..9570dd3 100644 (file)
@@ -21,8 +21,9 @@
 
 package jalview.fts.service.uniprot;
 
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.bin.Cache;
-import jalview.bin.Instance;
 import jalview.fts.api.FTSData;
 import jalview.fts.api.FTSDataColumnI;
 import jalview.fts.api.FTSRestClientI;
@@ -45,13 +46,13 @@ import com.sun.jersey.api.client.WebResource;
 import com.sun.jersey.api.client.config.DefaultClientConfig;
 
 public class UniProtFTSRestClient extends FTSRestClient
+        implements ApplicationSingletonI
 {
 
   public static FTSRestClientI getInstance()
   {
-    Instance j = Instance.getInstance();
-    return (j.uniprotFTSRestClient == null ? j.uniprotFTSRestClient = new UniProtFTSRestClient()
-            : j.uniprotFTSRestClient);
+    return (FTSRestClientI) ApplicationSingletonProvider
+            .getInstance(UniProtFTSRestClient.class);
   }
 
   private UniProtFTSRestClient()
index ec940b6..1ebf584 100644 (file)
@@ -383,7 +383,7 @@ public class AlignViewport extends AlignmentViewport
      */
     if (align != null)
     {
-      Desktop.getStructureSelectionManager()
+      Desktop.getInstance().getStructureSelectionManager()
               .registerMappings(align.getCodonFrames());
     }
 
@@ -404,7 +404,7 @@ public class AlignViewport extends AlignmentViewport
       List<AlignedCodonFrame> mappings = al.getCodonFrames();
       if (mappings != null)
       {
-        StructureSelectionManager ssm = Desktop
+        StructureSelectionManager ssm = Desktop.getInstance()
                 .getStructureSelectionManager();
         for (AlignedCodonFrame acf : mappings)
         {
@@ -530,7 +530,7 @@ public class AlignViewport extends AlignmentViewport
   @Override
   public void sendSelection()
   {
-    Desktop.getStructureSelectionManager().sendSelection(
+    Desktop.getInstance().getStructureSelectionManager().sendSelection(
             new SequenceGroup(getSelectionGroup()),
             new ColumnSelection(getColumnSelection()),
             new HiddenColumns(getAlignment().getHiddenColumns()), this);
@@ -574,7 +574,7 @@ public class AlignViewport extends AlignmentViewport
   @Override
   public StructureSelectionManager getStructureSelectionManager()
   {
-    return Desktop.getStructureSelectionManager();
+    return Desktop.getInstance().getStructureSelectionManager();
   }
 
   @Override
index 08a6802..b81c344 100644 (file)
@@ -61,8 +61,8 @@ public class AssociatePdbFileWithSeq
   {
     PDBEntry entry = new PDBEntry();
     StructureFile pdbfile = null;
-    pdbfile = Desktop.getStructureSelectionManager().setMapping(false,
-            new SequenceI[]
+    pdbfile = Desktop.getInstance().getStructureSelectionManager()
+            .setMapping(false, new SequenceI[]
             { sequence }, null, fileName, type);
     if (pdbfile == null)
     {
@@ -84,7 +84,8 @@ public class AssociatePdbFileWithSeq
     entry.setType(PDBEntry.Type.FILE);
     entry.setFile(fileName);
     sequence.getDatasetSequence().addPDBId(entry);
-    Desktop.getStructureSelectionManager().registerPDBEntry(entry);
+    Desktop.getInstance().getStructureSelectionManager()
+            .registerPDBEntry(entry);
     return entry;
   }
 }
index 3f3c298..2d20ad9 100644 (file)
@@ -440,7 +440,7 @@ public class CrossRefAction implements Runnable
      * register any new mappings for sequence mouseover etc
      * (will not duplicate any previously registered mappings)
      */
-    Desktop.getStructureSelectionManager()
+    Desktop.getInstance().getStructureSelectionManager()
             .registerMappings(dataset.getCodonFrames());
 
     if (copyAlignment.getHeight() <= 0)
index 826a869..c3640a9 100644 (file)
@@ -22,8 +22,10 @@ package jalview.gui;
 
 import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
+import jalview.api.StructureSelectionManagerProvider;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.bin.Cache;
-import jalview.bin.Instance;
 import jalview.bin.Jalview;
 import jalview.gui.ImageExporter.ImageWriterI;
 import jalview.io.BackupFiles;
@@ -37,6 +39,7 @@ import jalview.io.FormatAdapter;
 import jalview.io.IdentifyFile;
 import jalview.io.JalviewFileChooser;
 import jalview.io.JalviewFileView;
+import jalview.jbgui.GDesktop;
 import jalview.jbgui.GSplitFrame;
 import jalview.jbgui.GStructureViewer;
 import jalview.project.Jalview2XML;
@@ -135,9 +138,9 @@ import org.stackoverflowusers.file.WindowsShortcut;
  * @version $Revision: 1.155 $
  */
 @SuppressWarnings("serial")
-public class Desktop extends jalview.jbgui.GDesktop
+public class Desktop extends GDesktop
         implements DropTargetListener, ClipboardOwner, IProgressIndicator,
-        jalview.api.StructureSelectionManagerProvider
+        StructureSelectionManagerProvider, ApplicationSingletonI
 {
 
   private final static int DEFAULT_MIN_WIDTH = 300;
@@ -199,10 +202,10 @@ public class Desktop extends jalview.jbgui.GDesktop
     return Desktop.getInstance().desktopPane;
   }
 
-  public static StructureSelectionManager getStructureSelectionManager()
+  public StructureSelectionManager getStructureSelectionManager()
   {
     return StructureSelectionManager
-            .getStructureSelectionManager(Desktop.getInstance());
+            .getStructureSelectionManager(this);
   }
 
   static int openFrameCount = 0;
@@ -351,11 +354,17 @@ public class Desktop extends jalview.jbgui.GDesktop
 
   public MyDesktopPane desktopPane;
 
+  /**
+   * Answers an 'application scope' singleton instance of this class. Separate
+   * SwingJS 'applets' running in the same browser page will each have a
+   * distinct instance of Desktop.
+   * 
+   * @return
+   */
   public static Desktop getInstance()
   {
-    Instance i = Instance.getInstance();
-    return (i.desktop == null ? (i.desktop = new Desktop(true))
-            : i.desktop);
+    return (Desktop) ApplicationSingletonProvider
+            .getInstance(Desktop.class);
   }
 
   /**
@@ -367,23 +376,24 @@ public class Desktop extends jalview.jbgui.GDesktop
   {
     instanceOnly = true;
   }
+  
   /**
-   * Creates a new Desktop object.
+   * Private constructor enforces singleton pattern. It is called by reflection
+   * from ApplicationSingletonProvider.getInstance().
    */
-  public Desktop()
+  @SuppressWarnings("unused")
+  private Desktop()
   {
     /**
      * A note to implementors. It is ESSENTIAL that any activities that might
      * block are spawned off as threads rather than waited for during this
      * constructor.
      */
-    Instance.getInstance().desktop = this;
-
     if (!Platform.isJS())
     {
       doVamsasClientCheck();
     }
-
+    
     doConfigureStructurePrefs();
     setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
@@ -392,7 +402,7 @@ public class Desktop extends jalview.jbgui.GDesktop
     boolean showjconsole = jalview.bin.Cache.getDefault("SHOW_JAVA_CONSOLE",
             false);
     desktopPane = new MyDesktopPane(selmemusage);
-
+    
     showMemusage.setSelected(selmemusage);
     desktopPane.setBackground(Color.white);
     getContentPane().setLayout(new BorderLayout());
@@ -400,16 +410,16 @@ public class Desktop extends jalview.jbgui.GDesktop
     // JScrollPane sp = new JScrollPane();
     // sp.getViewport().setView(desktop);
     // getContentPane().add(sp, BorderLayout.CENTER);
-
+    
     // BH 2018 - just an experiment to try unclipped JInternalFrames.
     if (Platform.isJS())
     {
       getRootPane().putClientProperty("swingjs.overflow.hidden", "false");
     }
-
+    
     getContentPane().add(desktopPane, BorderLayout.CENTER);
     desktopPane.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
-
+    
     // This line prevents Windows Look&Feel resizing all new windows to maximum
     // if previous window was maximised
     desktopPane.setDesktopManager(new MyDesktopManager(
@@ -418,7 +428,7 @@ public class Desktop extends jalview.jbgui.GDesktop
                             ? new AquaInternalFrameManager(
                                     desktopPane.getDesktopManager())
                             : desktopPane.getDesktopManager())));
-
+    
     Rectangle dims = getLastKnownDimensions("");
     if (dims != null)
     {
@@ -431,7 +441,7 @@ public class Desktop extends jalview.jbgui.GDesktop
       int yPos = Math.max(5, (screenSize.height - 650) / 2);
       setBounds(xPos, yPos, 900, 650);
     }
-
+    
     if (!Platform.isJS())
     /**
      * Java only
@@ -439,7 +449,7 @@ public class Desktop extends jalview.jbgui.GDesktop
      * @j2sIgnore
      */
     {
-
+    
       jconsole = new Console(this, showjconsole);
       // add essential build information
       jconsole.setHeader("Jalview Version: "
@@ -452,19 +462,19 @@ public class Desktop extends jalview.jbgui.GDesktop
               + System.getProperty("os.arch") + " "
               + System.getProperty("os.name") + " "
               + System.getProperty("os.version"));
-
+    
       showConsole(showjconsole);
-
+    
       showNews.setVisible(false);
-
+    
       experimentalFeatures.setSelected(showExperimental());
-
+    
       getIdentifiersOrgData();
-
+    
       checkURLLinks();
-
+    
       // Spawn a thread that shows the splashscreen
-
+    
       SwingUtilities.invokeLater(new Runnable()
       {
         @Override
@@ -473,7 +483,7 @@ public class Desktop extends jalview.jbgui.GDesktop
           new SplashScreen();
         }
       });
-
+    
       // Thread off a new instance of the file chooser - this reduces the time
       // it
       // takes to open it later on.
@@ -493,7 +503,7 @@ public class Desktop extends jalview.jbgui.GDesktop
       changeSupport.addJalviewPropertyChangeListener("services",
               new PropertyChangeListener()
               {
-
+    
                 @Override
                 public void propertyChange(PropertyChangeEvent evt)
                 {
@@ -501,13 +511,13 @@ public class Desktop extends jalview.jbgui.GDesktop
                           + evt.getNewValue());
                   JalviewServicesChanged(evt);
                 }
-
+    
               });
-
+    
     }
-
+    
     this.setDropTarget(new java.awt.dnd.DropTarget(desktopPane, this));
-
+    
     this.addWindowListener(new WindowAdapter()
     {
       @Override
@@ -516,7 +526,7 @@ public class Desktop extends jalview.jbgui.GDesktop
         quit();
       }
     });
-
+    
     MouseAdapter ma;
     this.addMouseListener(ma = new MouseAdapter()
     {
@@ -528,7 +538,7 @@ public class Desktop extends jalview.jbgui.GDesktop
           showPasteMenu(evt.getX(), evt.getY());
         }
       }
-
+    
       @Override
       public void mouseReleased(MouseEvent evt)
       {
@@ -539,7 +549,6 @@ public class Desktop extends jalview.jbgui.GDesktop
       }
     });
     desktopPane.addMouseListener(ma);
-
   }
 
   /**
@@ -614,7 +623,7 @@ public class Desktop extends jalview.jbgui.GDesktop
         }
       }
     }).start();
-    ;
+    
   }
 
   @Override
@@ -964,7 +973,7 @@ public class Desktop extends jalview.jbgui.GDesktop
           menuItem.removeActionListener(menuItem.getActionListeners()[0]);
         }
         Desktop.getInstance().windowMenu.remove(menuItem);
-      };
+      }
     });
 
     menuItem.addActionListener(new ActionListener()
@@ -2366,7 +2375,7 @@ public class Desktop extends jalview.jbgui.GDesktop
                 });
                 rthr.start();
               }
-            };
+            }
           });
           VamsasStMenu.add(sessit);
         }
@@ -3266,7 +3275,6 @@ public class Desktop extends jalview.jbgui.GDesktop
           } catch (InterruptedException x)
           {
           }
-          ;
         }
         if (instanceOnly)
         {
@@ -3555,7 +3563,6 @@ public class Desktop extends jalview.jbgui.GDesktop
             System.err.println(
                     "Please ignore plist error - occurs due to problem with java 8 on OSX");
           }
-          ;
         }
       } catch (Throwable ex)
       {
index b801352..8bfa428 100644 (file)
@@ -149,7 +149,7 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI
   {
     // TODO if CommandListener is only ever 1:1 for complementary views,
     // may change broadcast pattern to direct messaging (more efficient)
-    final StructureSelectionManager ssm = Desktop
+    final StructureSelectionManager ssm = Desktop.getInstance()
             .getStructureSelectionManager();
     ssm.addCommandListener(((AlignFrame) getTopFrame()).getViewport());
     ssm.addCommandListener(((AlignFrame) getBottomFrame()).getViewport());
@@ -282,7 +282,7 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI
       public void internalFrameClosed(InternalFrameEvent evt)
       {
         close();
-      };
+      }
     });
   }
 
@@ -555,7 +555,7 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI
      */
     adjustLayout();
 
-    final StructureSelectionManager ssm = Desktop
+    final StructureSelectionManager ssm = Desktop.getInstance()
             .getStructureSelectionManager();
     ssm.addCommandListener(newTopPanel.av);
     ssm.addCommandListener(newBottomPanel.av);
index 3731102..4404a8d 100644 (file)
@@ -762,7 +762,7 @@ public class VamsasApplication implements SelectionSource, VamsasSource
       try
       {
         IPickManager pm = vclient.getPickManager();
-        StructureSelectionManager ssm = Desktop
+        StructureSelectionManager ssm = Desktop.getInstance()
                 .getStructureSelectionManager();
         VamsasApplication me = this;
         pm.registerMessageHandler(new IMessageHandler()
@@ -830,7 +830,6 @@ public class VamsasApplication implements SelectionSource, VamsasSource
                 {
                   type = jvobjs[o].getClass();
                 }
-                ;
                 if (type != jvobjs[o].getClass())
                 {
                   send = false;
@@ -954,7 +953,6 @@ public class VamsasApplication implements SelectionSource, VamsasSource
               {
                 jvobjs[c] = null;
               }
-              ;
               jvobjs = null;
               return;
             }
index 8797f33..8cb1846 100644 (file)
@@ -20,7 +20,8 @@
  */
 package jalview.httpserver;
 
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.rest.RestHandler;
 
 import java.net.BindException;
@@ -50,7 +51,7 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool;
  * @author gmcarstairs
  * @see http://eclipse.org/jetty/documentation/current/embedding-jetty.html
  */
-public class HttpServer
+public class HttpServer implements ApplicationSingletonI
 {
 
   /**
@@ -63,9 +64,7 @@ public class HttpServer
   {
     synchronized (HttpServer.class)
     {
-      Instance j = Instance.getInstance();
-      return (j.httpServer == null ? j.httpServer = new HttpServer()
-              : j.httpServer);
+      return (HttpServer) ApplicationSingletonProvider.getInstance(HttpServer.class);
     }
   }
 
index d65fe95..e83b87c 100644 (file)
@@ -20,7 +20,8 @@
  */
 package jalview.io;
 
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -38,13 +39,11 @@ import java.util.Set;
  * @author gmcarstairs
  *
  */
-public class FileFormats
+public class FileFormats implements ApplicationSingletonI
 {
   public static FileFormats getInstance()
   {
-    Instance i = Instance.getInstance();
-    return (i.fileFormats == null ? i.fileFormats = new FileFormats()
-            : i.fileFormats);
+    return (FileFormats) ApplicationSingletonProvider.getInstance(FileFormats.class);
   }
 
   /**
index f5c3c54..f8283c3 100755 (executable)
@@ -409,7 +409,7 @@ public class FileLoader implements Runnable
               {
                 // register PDB entries with desktop's structure selection
                 // manager
-                Desktop.getStructureSelectionManager()
+                Desktop.getInstance().getStructureSelectionManager()
                         .registerPDBEntry(pdbe);
               }
             }
index 98b5b49..1f2f0fb 100644 (file)
@@ -389,7 +389,6 @@ public class VamsasAppDatastore
         {
           dssmods.addElement(sequence);
         }
-        ;
       }
       if (dssmods.size() > 0)
       {
@@ -585,7 +584,6 @@ public class VamsasAppDatastore
                           (AlignmentSequence) alsref, aa[i]);
                   break;
                 }
-                ;
               }
             }
           }
@@ -1478,7 +1476,7 @@ public class VamsasAppDatastore
           // active
           if (mappings != null)
           {
-            Desktop.getStructureSelectionManager()
+            Desktop.getInstance().getStructureSelectionManager()
                     .registerMappings(mappings);
           }
         }
index 8b09cd3..2a254cc 100644 (file)
@@ -21,7 +21,8 @@
 package jalview.io.cache;
 
 import jalview.bin.Cache;
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 
 import java.util.Hashtable;
 import java.util.LinkedHashSet;
@@ -33,13 +34,12 @@ import java.util.LinkedHashSet;
  * @author tcnofoegbu
  *
  */
-public class AppCache
+public class AppCache implements ApplicationSingletonI
 {
 
   public static AppCache getInstance()
   {
-    Instance j = Instance.getInstance();
-    return (j.appCache == null ? j.appCache = new AppCache() : j.appCache);
+    return (AppCache) ApplicationSingletonProvider.getInstance(AppCache.class);
   }
 
   private AppCache()
index 258b16a..2ba41da 100644 (file)
  */
 package jalview.io.gff;
 
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 
 /**
  * A factory class that returns a model of the Sequence Ontology. By default a
- * hard-coded subset is used (for the applet, or testing), or setInstance() can
- * be used to set full Ontology data.
+ * hard-coded subset is used (for the applet, or testing), or
+ * setSequenceOntology() can be used to set full Ontology data.
  * 
  * @author gmcarstairs
  *
  */
-public class SequenceOntologyFactory
+public class SequenceOntologyFactory implements ApplicationSingletonI
 {
+  /**
+   * Answers an instance of this class for the current application context. Note
+   * that this supports running two JS 'applets' on the same page, one with the
+   * full Sequence Ontology (USE_FULL_SO = true) and one with a hard-coded
+   * subset (USE_FULL_SO = false). If this is overkill, could change this method
+   * to just return a common static instance.
+   * 
+   * @return
+   */
+  private static synchronized SequenceOntologyFactory getInstance()
+  {
+    return (SequenceOntologyFactory) ApplicationSingletonProvider
+            .getInstance(SequenceOntologyFactory.class);
+  }
 
+  /**
+   * Answers the configured model of the Sequence Ontology.
+   * 
+   * @return
+   */
   public static synchronized SequenceOntologyI getSequenceOntology()
   {
-    SequenceOntologyFactory j = getInstance();
-    return (j.sequenceOntology == null
-            ? j.sequenceOntology = new SequenceOntologyLite()
-            : j.sequenceOntology);
+    SequenceOntologyFactory f = getInstance();
+    return (f.sequenceOntology == null
+            ? f.sequenceOntology = new SequenceOntologyLite()
+            : f.sequenceOntology);
   }
 
   /**
@@ -46,7 +66,7 @@ public class SequenceOntologyFactory
    * 
    * @param so
    */
-  public static void setInstance(SequenceOntologyI so)
+  public static void setSequenceOntology(SequenceOntologyI so)
   {
     getInstance().sequenceOntology = so;
   }
@@ -58,12 +78,4 @@ public class SequenceOntologyFactory
     // private singleton
   }
 
-  private static synchronized SequenceOntologyFactory getInstance()
-  {
-    Instance j = Instance.getInstance();
-    return (j.sequenceOntologyFactory == null
-            ? j.sequenceOntologyFactory = new SequenceOntologyFactory()
-            : j.sequenceOntologyFactory);
-  }
-
 }
index bacf8dc..47cceb7 100644 (file)
@@ -369,7 +369,8 @@ public class Sequencemapping extends Rangetype
       acf.addMap(from, to, mapping);
     }
     bindjvvobj(mapping, sequenceMapping);
-    Desktop.getStructureSelectionManager().registerMapping(acf);
+    Desktop.getInstance().getStructureSelectionManager()
+            .registerMapping(acf);
     // Try to link up any conjugate database references in the two sequences
     // matchConjugateDBRefs(from, to, mapping);
     // Try to propagate any dbrefs across this mapping.
index e293831..9d9faa1 100644 (file)
@@ -2952,7 +2952,7 @@ public class Jalview2XML
     {
       if (ds.getCodonFrames() != null)
       {
-        Desktop.getStructureSelectionManager()
+        Desktop.getInstance().getStructureSelectionManager()
                 .registerMappings(ds.getCodonFrames());
       }
     }
@@ -3573,7 +3573,8 @@ public class Jalview2XML
             {
               entry.setProperty(prop.getName(), prop.getValue());
             }
-            Desktop.getStructureSelectionManager().registerPDBEntry(entry);
+            Desktop.getInstance().getStructureSelectionManager()
+                    .registerPDBEntry(entry);
             // adds PDBEntry to datasequence's set (since Jalview 2.10)
             if (al.getSequenceAt(i).getDatasetSequence() != null)
             {
index 61d75ee..fefdc57 100644 (file)
@@ -20,7 +20,8 @@
  */
 package jalview.rest;
 
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.httpserver.AbstractRequestHandler;
 
 import java.io.IOException;
@@ -35,6 +36,7 @@ import javax.servlet.http.HttpServletResponse;
  * Accessed only by HttpServer.
  */
 public class RestHandler extends AbstractRequestHandler
+        implements ApplicationSingletonI
 {
   private static final String MY_PATH = "rest";
 
@@ -50,9 +52,7 @@ public class RestHandler extends AbstractRequestHandler
   {
     synchronized (RestHandler.class)
     {
-      Instance j = Instance.getInstance();
-      return (j.restHandler == null ? j.restHandler = new RestHandler()
-              : j.restHandler);
+      return (RestHandler) ApplicationSingletonProvider.getInstance(RestHandler.class);
     }
   }
 
index b3f94b6..e11540c 100644 (file)
@@ -21,7 +21,8 @@
 package jalview.schemes;
 
 import jalview.api.AlignViewportI;
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.datamodel.AnnotatedCollectionI;
 import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceI;
@@ -31,7 +32,7 @@ import java.awt.Color;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
-public class ColourSchemes
+public class ColourSchemes implements ApplicationSingletonI
 {
 
   /**
@@ -41,9 +42,8 @@ public class ColourSchemes
    */
   public static ColourSchemes getInstance()
   {
-    Instance j = Instance.getInstance();
-    return (j.colourSchemes == null ? j.colourSchemes = new ColourSchemes()
-            : j.colourSchemes);
+    return (ColourSchemes) ApplicationSingletonProvider
+            .getInstance(ColourSchemes.class);
   }
 
   private ColourSchemes()
index c28f9df..b5672ab 100644 (file)
@@ -20,7 +20,8 @@
  */
 package jalview.structure;
 
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.PDBEntry.Type;
 
@@ -31,7 +32,7 @@ import jalview.datamodel.PDBEntry.Type;
  * @author tcofoegbu
  *
  */
-public class StructureImportSettings
+public class StructureImportSettings implements ApplicationSingletonI
 {
 
   private StructureImportSettings()
@@ -41,10 +42,8 @@ public class StructureImportSettings
 
   private static StructureImportSettings getInstance()
   {
-    Instance j = Instance.getInstance();
-    return (j.structureImportSettings == null
-            ? j.structureImportSettings = new StructureImportSettings()
-            : j.structureImportSettings);
+    return (StructureImportSettings) ApplicationSingletonProvider
+            .getInstance(StructureImportSettings.class);
   }
 
   /**
index e890dce..e7835f3 100644 (file)
@@ -22,7 +22,8 @@ package jalview.structure;
 
 import jalview.analysis.AlignSeq;
 import jalview.api.StructureSelectionManagerProvider;
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.commands.CommandI;
 import jalview.commands.EditCommand;
 import jalview.commands.OrderCommand;
@@ -61,79 +62,97 @@ import mc_view.Atom;
 import mc_view.PDBChain;
 import mc_view.PDBfile;
 
-public class StructureSelectionManager
+public class StructureSelectionManager implements ApplicationSingletonI
 {
+  public final static String NEWLINE = System.lineSeparator();
+
+  private List<StructureMapping> mappings = new ArrayList<>();
+
+  private boolean processSecondaryStructure = false;
+
+  private boolean secStructServices = false;
+
+  private boolean addTempFacAnnot = false;
+
+  /*
+   * Set of any registered mappings between (dataset) sequences.
+   */
+  private List<AlignedCodonFrame> seqmappings = new ArrayList<>();
+
+  private List<CommandListener> commandListeners = new ArrayList<>();
+
+  private List<SelectionListener> sel_listeners = new ArrayList<>();
 
+  /*
+   * instances of this class scoped by some context class
+   */
+  private IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> structureSelections;
+
+  /**
+   * Answers an instance of this class for the current application (Java or JS
+   * 'applet') scope
+   * 
+   * @return
+   */
+  private static StructureSelectionManager getInstance()
+  {
+    return (StructureSelectionManager) ApplicationSingletonProvider
+            .getInstance(StructureSelectionManager.class);
+  }
+
+  /**
+   * Answers an instance of this class for the current application (Java or JS
+   * 'applet') scope, and scoped to the specified context
+   * 
+   * @param context
+   * @return
+   */
   public static StructureSelectionManager getStructureSelectionManager(
           StructureSelectionManagerProvider context)
   {
-    IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> map = Instance
-            .getInstance().structureSelections;
+    return getInstance().getInstanceForContext(context);
+  }
 
-    if (map == null)
-    {
-      map = Instance
-              .getInstance().structureSelections = new IdentityHashMap<>();
-    }
-    StructureSelectionManager instance = map.get(context);
+  /**
+   * Answers an instance of this class scoped to the given context. The instance
+   * is created on the first request for the context, thereafter the same
+   * instance is returned.
+   * 
+   * @param context
+   * @return
+   */
+  StructureSelectionManager getInstanceForContext(
+          StructureSelectionManagerProvider context)
+  {
+    StructureSelectionManager instance = structureSelections.get(context);
     if (instance == null)
     {
-      // BH: actually, not possible except for coding error; this is an attempt
-      // to discover that.
-      if (context == null && !map.isEmpty())
-      {
-        throw new Error(MessageManager.getString(
-                "error.implementation_error_structure_selection_manager_null"),
-                new NullPointerException(MessageManager
-                        .getString("exception.ssm_context_is_null")));
-      }
-      map.put(context, instance = new StructureSelectionManager());
+      instance = new StructureSelectionManager();
+      structureSelections.put(context, instance);
     }
     return instance;
   }
 
   /**
-   * release all references associated with this manager provider
+   * Removes the instance associated with this provider
    * 
    * @param provider
    */
 
   public static void release(StructureSelectionManagerProvider provider)
   {
-    IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> map = Instance
-            .getInstance().structureSelections;
-    if (map != null)
-    {
-      map.remove(provider);
-    }
+    getInstance().structureSelections.remove(provider);
   }
 
-  public StructureSelectionManager()
+  /**
+   * Private constructor as all 'singleton' instances are managed here or by
+   * ApplicationSingletonProvider
+   */
+  private StructureSelectionManager()
   {
+    structureSelections = new IdentityHashMap<>();
   }
 
-  public final static String NEWLINE = System.lineSeparator();
-
-  // BH unnecessary; IdentityHashMap can handle this
-  // private static StructureSelectionManager nullProvider;
-
-  private List<StructureMapping> mappings = new ArrayList<>();
-
-  private boolean processSecondaryStructure = false;
-
-  private boolean secStructServices = false;
-
-  private boolean addTempFacAnnot = false;
-
-  /*
-   * Set of any registered mappings between (dataset) sequences.
-   */
-  private List<AlignedCodonFrame> seqmappings = new ArrayList<>();
-
-  private List<CommandListener> commandListeners = new ArrayList<>();
-
-  private List<SelectionListener> sel_listeners = new ArrayList<>();
-
   /**
    * @return true if will try to use external services for processing secondary
    *         structure
@@ -663,7 +682,6 @@ public class StructureSelectionManager
         {
           ds = ds.getDatasetSequence();
         }
-        ;
         if (ds.getAnnotation() != null)
         {
           for (AlignmentAnnotation ala : ds.getAnnotation())
@@ -1311,7 +1329,6 @@ public class StructureSelectionManager
         {
           slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
         }
-        ;
       }
     }
   }
index d99d16d..10c3478 100644 (file)
 
 package jalview.urls;
 
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 
 /**
  * Holds settings for identifiers.org e.g. url, download location
- * 
- * @author $author$
- * @version $Revision$
  */
-public class IdOrgSettings
+public class IdOrgSettings implements ApplicationSingletonI
 {
 
   private IdOrgSettings()
@@ -39,9 +37,8 @@ public class IdOrgSettings
 
   private static IdOrgSettings getInstance()
   {
-    Instance j = Instance.getInstance();
-    return (j.idOrgSettings == null ? j.idOrgSettings = new IdOrgSettings()
-            : j.idOrgSettings);
+    return (IdOrgSettings) ApplicationSingletonProvider
+            .getInstance(IdOrgSettings.class);
   }
 
   private String url;
index 7ac1179..10a2b28 100644 (file)
@@ -20,7 +20,8 @@
  */
 package jalview.ws;
 
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.datamodel.DBRefSource;
 import jalview.ext.ensembl.EnsemblGene;
 import jalview.ws.dbsources.Uniprot;
@@ -39,8 +40,12 @@ import java.util.List;
  * instantiated by reflection and queried for their DbRefSource and version
  * association.
  */
-public class SequenceFetcher extends ASequenceFetcher
+public class SequenceFetcher extends ASequenceFetcher implements ApplicationSingletonI
 {
+  /*
+   * set a mock fetcher here for testing only - reset to null afterwards
+   */
+  private static SequenceFetcher mockFetcher;
 
   /**
    * Returns a new SequenceFetcher singleton, or a mock object if one has been
@@ -50,10 +55,9 @@ public class SequenceFetcher extends ASequenceFetcher
    */
   public static SequenceFetcher getInstance()
   {
-    Instance j = Instance.getInstance();
-    return (j.sequenceFetcher == null
-            ? j.sequenceFetcher = new SequenceFetcher()
-            : j.sequenceFetcher);
+    return mockFetcher != null ? mockFetcher
+            : (SequenceFetcher) ApplicationSingletonProvider
+                    .getInstance(SequenceFetcher.class);
   }
 
   /**
@@ -66,7 +70,7 @@ public class SequenceFetcher extends ASequenceFetcher
    */
   public static void setSequenceFetcher(SequenceFetcher sf)
   {
-    Instance.getInstance().sequenceFetcher = sf;
+    mockFetcher = sf;
   }
 
   /**
index ea836f9..74263b1 100644 (file)
@@ -20,7 +20,8 @@
  */
 package jalview.ws.jws1;
 
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.gui.JvOptionPane;
 import jalview.util.MessageManager;
 
@@ -35,14 +36,12 @@ import ext.vamsas.RegistryServiceSoapBindingStub;
 import ext.vamsas.ServiceHandle;
 import ext.vamsas.ServiceHandles;
 
-public class Discoverer implements Runnable
+public class Discoverer implements Runnable, ApplicationSingletonI
 {
 
   public static Discoverer getInstance()
   {
-    Instance j = Instance.getInstance();
-    return (j.discoverer == null ? j.discoverer = new Discoverer()
-            : j.discoverer);
+    return (Discoverer) ApplicationSingletonProvider.getInstance(Discoverer.class);
   }
 
   private Discoverer()
index 6eaaee1..bd4d352 100644 (file)
@@ -21,7 +21,8 @@
 package jalview.ws.jws2;
 
 import jalview.bin.Cache;
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.gui.AlignFrame;
 import jalview.gui.Desktop;
 import jalview.gui.JvSwingUtils;
@@ -61,7 +62,8 @@ import compbio.ws.client.Services;
  * @author JimP
  * 
  */
-public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
+public class Jws2Discoverer
+        implements Runnable, WSMenuEntryProviderI, ApplicationSingletonI
 {
 
   /**
@@ -71,10 +73,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
    */
   public static Jws2Discoverer getInstance()
   {
-    Instance j = Instance.getInstance();
-    return (j.j2s2discoverer == null
-            ? j.j2s2discoverer = new Jws2Discoverer()
-            : j.j2s2discoverer);
+    return (Jws2Discoverer) ApplicationSingletonProvider
+            .getInstance(Jws2Discoverer.class);
   }
 
   /**
index 159edda..1983ff5 100644 (file)
@@ -20,7 +20,8 @@
  */
 package jalview.ws.jws2.jabaws2;
 
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.ws.jws2.AAConClient;
 import jalview.ws.jws2.RNAalifoldClient;
 import jalview.ws.uimodel.AlignAnalysisUIText;
@@ -30,7 +31,7 @@ import java.util.HashSet;
 
 import compbio.data.msa.JABAService;
 
-public class Jws2InstanceFactory
+public class Jws2InstanceFactory implements ApplicationSingletonI
 {
 
   private Jws2InstanceFactory()
@@ -40,10 +41,8 @@ public class Jws2InstanceFactory
 
   private static Jws2InstanceFactory getInstance()
   {
-    Instance j = Instance.getInstance();
-    return (j.jws2InstanceFactory == null
-            ? j.jws2InstanceFactory = new Jws2InstanceFactory()
-            : j.jws2InstanceFactory);
+    return (Jws2InstanceFactory) ApplicationSingletonProvider
+            .getInstance(Jws2InstanceFactory.class);
   }
 
   private HashMap<String, AlignAnalysisUIText> aaConGUI;
index d83ae6f..a5b68d7 100644 (file)
@@ -21,7 +21,8 @@
 package jalview.ws.rest;
 
 import jalview.bin.Cache;
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.datamodel.AlignmentView;
 import jalview.gui.AlignFrame;
 import jalview.gui.AlignViewport;
@@ -50,7 +51,7 @@ import javax.swing.event.MenuListener;
  * 
  */
 public class RestClient extends WSClient
-        implements WSClientI, WSMenuEntryProviderI
+        implements WSClientI, WSMenuEntryProviderI, ApplicationSingletonI
 {
   public static final String RSBS_SERVICES = "RSBS_SERVICES";
 
@@ -70,6 +71,114 @@ public class RestClient extends WSClient
 
   protected Vector<String> services = null;
 
+  private static RestClient getInstance()
+  {
+    return (RestClient) ApplicationSingletonProvider.getInstance(RestClient.class);
+  }
+
+  public static RestClient makeShmmrRestClient()
+  {
+    String action = "Analysis",
+            description = "Sequence Harmony and Multi-Relief (Brandt et al. 2010)",
+            name = MessageManager.getString("label.multiharmony");
+    Hashtable<String, InputType> iparams = new Hashtable<>();
+    // jalview.ws.rest.params.JobConstant toolp;
+    // toolp = new jalview.ws.rest.JobConstant("tool","jalview");
+    // iparams.put(toolp.token, toolp);
+    // toolp = new jalview.ws.rest.params.JobConstant("mbjob[method]","shmr");
+    // iparams.put(toolp.token, toolp);
+    // toolp = new
+    // jalview.ws.rest.params.JobConstant("mbjob[description]","step 1");
+    // iparams.put(toolp.token, toolp);
+    // toolp = new jalview.ws.rest.params.JobConstant("start_search","1");
+    // iparams.put(toolp.token, toolp);
+    // toolp = new jalview.ws.rest.params.JobConstant("blast","0");
+    // iparams.put(toolp.token, toolp);
+
+    jalview.ws.rest.params.Alignment aliinput = new jalview.ws.rest.params.Alignment();
+    // SHMR server has a 65K limit for content pasted into the 'ali' parameter,
+    // so we always upload our files.
+    aliinput.token = "ali_file";
+    aliinput.writeAsFile = true;
+    iparams.put(aliinput.token, aliinput);
+    jalview.ws.rest.params.SeqGroupIndexVector sgroups = new jalview.ws.rest.params.SeqGroupIndexVector();
+    sgroups.setMinsize(2);
+    sgroups.min = 2;// need at least two group defined to make a partition
+    iparams.put("groups", sgroups);
+    sgroups.token = "groups";
+    sgroups.sep = " ";
+    RestServiceDescription shmrService = new RestServiceDescription(action,
+            description, name,
+            "http://zeus.few.vu.nl/programs/shmrwww/index.php?tool=jalview", // ?tool=jalview&mbjob[method]=shmr&mbjob[description]=step1",
+            "?tool=jalview", iparams, true, false, '-');
+    // a priori knowledge of the data returned from the service
+    shmrService.addResultDatatype(JvDataType.ANNOTATION);
+    return new RestClient(shmrService);
+  }
+
+  public static RestClient[] getRestClients()
+  {
+    RestClient c = getInstance();
+
+    if (c.services == null)
+    {
+      c.services = new Vector<>();
+      try
+      {
+        for (RestServiceDescription descr : RestServiceDescription
+                .parseDescriptions(
+                        jalview.bin.Cache.getDefault(RSBS_SERVICES,
+                                makeShmmrRestClient().service.toString())))
+        {
+          c.services.add(descr.toString());
+        }
+      } catch (Exception ex)
+      {
+        System.err.println(
+                "Serious - RSBS descriptions in user preferences are corrupt!");
+        ex.printStackTrace();
+      }
+
+    }
+    RestClient[] lst = new RestClient[c.services.size()];
+    int i = 0;
+    for (String svc : c.services)
+    {
+      lst[i++] = new RestClient(new RestServiceDescription(svc));
+    }
+    return lst;
+  }
+
+  public static Vector<String> getRsbsDescriptions()
+  {
+    Vector<String> rsbsDescrs = new Vector<>();
+    for (RestClient rsbs : getRestClients())
+    {
+      rsbsDescrs.add(rsbs.getRestDescription().toString());
+    }
+    return rsbsDescrs;
+  }
+
+  public static void setRsbsServices(Vector<String> rsbsUrls)
+  {
+    if (rsbsUrls != null)
+    {
+      // TODO: consider validating services ?
+      RestClient c = getInstance();
+      c.services = new Vector<>(rsbsUrls);
+      StringBuffer sprop = new StringBuffer();
+      for (String s : c.services)
+      {
+        sprop.append(s);
+      }
+      Cache.setProperty(RSBS_SERVICES, sprop.toString());
+    }
+    else
+    {
+      Cache.removeProperty(RSBS_SERVICES);
+    }
+  }
+
   /**
    * get the alignFrame for the associated input data if it exists.
    * 
@@ -80,13 +189,6 @@ public class RestClient extends WSClient
     return jalview.gui.Desktop.getAlignFrameFor(av);
   }
 
-  private static RestClient getInstance()
-  {
-    Instance j = Instance.getInstance();
-    return (j.restClient == null ? j.restClient = new RestClient()
-            : j.restClient);
-  }
-
   private RestClient()
   {
 
@@ -356,46 +458,6 @@ public class RestClient extends WSClient
     }
   }
 
-  public static RestClient makeShmmrRestClient()
-  {
-    String action = "Analysis",
-            description = "Sequence Harmony and Multi-Relief (Brandt et al. 2010)",
-            name = MessageManager.getString("label.multiharmony");
-    Hashtable<String, InputType> iparams = new Hashtable<>();
-    // jalview.ws.rest.params.JobConstant toolp;
-    // toolp = new jalview.ws.rest.JobConstant("tool","jalview");
-    // iparams.put(toolp.token, toolp);
-    // toolp = new jalview.ws.rest.params.JobConstant("mbjob[method]","shmr");
-    // iparams.put(toolp.token, toolp);
-    // toolp = new
-    // jalview.ws.rest.params.JobConstant("mbjob[description]","step 1");
-    // iparams.put(toolp.token, toolp);
-    // toolp = new jalview.ws.rest.params.JobConstant("start_search","1");
-    // iparams.put(toolp.token, toolp);
-    // toolp = new jalview.ws.rest.params.JobConstant("blast","0");
-    // iparams.put(toolp.token, toolp);
-
-    jalview.ws.rest.params.Alignment aliinput = new jalview.ws.rest.params.Alignment();
-    // SHMR server has a 65K limit for content pasted into the 'ali' parameter,
-    // so we always upload our files.
-    aliinput.token = "ali_file";
-    aliinput.writeAsFile = true;
-    iparams.put(aliinput.token, aliinput);
-    jalview.ws.rest.params.SeqGroupIndexVector sgroups = new jalview.ws.rest.params.SeqGroupIndexVector();
-    sgroups.setMinsize(2);
-    sgroups.min = 2;// need at least two group defined to make a partition
-    iparams.put("groups", sgroups);
-    sgroups.token = "groups";
-    sgroups.sep = " ";
-    RestServiceDescription shmrService = new RestServiceDescription(action,
-            description, name,
-            "http://zeus.few.vu.nl/programs/shmrwww/index.php?tool=jalview", // ?tool=jalview&mbjob[method]=shmr&mbjob[description]=step1",
-            "?tool=jalview", iparams, true, false, '-');
-    // a priori knowledge of the data returned from the service
-    shmrService.addResultDatatype(JvDataType.ANNOTATION);
-    return new RestClient(shmrService);
-  }
-
   public AlignmentPanel recoverAlignPanelForView()
   {
     AlignmentPanel[] aps = Desktop
@@ -416,39 +478,6 @@ public class RestClient extends WSClient
     return true;
   }
 
-  public static RestClient[] getRestClients()
-  {
-    RestClient c = getInstance();
-
-    if (c.services == null)
-    {
-      c.services = new Vector<>();
-      try
-      {
-        for (RestServiceDescription descr : RestServiceDescription
-                .parseDescriptions(
-                        jalview.bin.Cache.getDefault(RSBS_SERVICES,
-                                makeShmmrRestClient().service.toString())))
-        {
-          c.services.add(descr.toString());
-        }
-      } catch (Exception ex)
-      {
-        System.err.println(
-                "Serious - RSBS descriptions in user preferences are corrupt!");
-        ex.printStackTrace();
-      }
-
-    }
-    RestClient[] lst = new RestClient[c.services.size()];
-    int i = 0;
-    for (String svc : c.services)
-    {
-      lst[i++] = new RestClient(new RestServiceDescription(svc));
-    }
-    return lst;
-  }
-
   public String getAction()
   {
     return service.details.Action;
@@ -459,34 +488,4 @@ public class RestClient extends WSClient
     return service;
   }
 
-  public static Vector<String> getRsbsDescriptions()
-  {
-    Vector<String> rsbsDescrs = new Vector<>();
-    for (RestClient rsbs : getRestClients())
-    {
-      rsbsDescrs.add(rsbs.getRestDescription().toString());
-    }
-    return rsbsDescrs;
-  }
-
-  public static void setRsbsServices(Vector<String> rsbsUrls)
-  {
-    if (rsbsUrls != null)
-    {
-      // TODO: consider validating services ?
-      RestClient c = getInstance();
-      c.services = new Vector<>(rsbsUrls);
-      StringBuffer sprop = new StringBuffer();
-      for (String s : c.services)
-      {
-        sprop.append(s);
-      }
-      Cache.setProperty(RSBS_SERVICES, sprop.toString());
-    }
-    else
-    {
-      Cache.removeProperty(RSBS_SERVICES);
-    }
-  }
-
 }
index 8fd5300..88aaed4 100644 (file)
  */
 package jalview.ws.sifts;
 
-import jalview.bin.Instance;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 
 import java.util.Objects;
 
-public class SiftsSettings
+public class SiftsSettings implements ApplicationSingletonI
 {
 
   /**
@@ -34,13 +35,8 @@ public class SiftsSettings
    */
   public static SiftsSettings getInstance()
   {
-    {
-      Instance j = Instance.getInstance();
-      return (j.siftsSettings == null
-              ? j.siftsSettings = new SiftsSettings()
-              : j.siftsSettings);
-    }
-
+    return (SiftsSettings) ApplicationSingletonProvider
+            .getInstance(SiftsSettings.class);
   }
 
   private SiftsSettings()
index bd18abd..d360db4 100644 (file)
@@ -67,6 +67,7 @@ public class FinderTest
   @BeforeClass(groups = "Functional")
   public void setUp()
   {
+    Cache.initLogger();
     Cache.loadProperties("test/jalview/io/testProps.jvprops");
     Cache.setPropertyNoSave("PAD_GAPS",
             Boolean.FALSE.toString());
index 5e44d3d..9684cf2 100644 (file)
@@ -7,6 +7,8 @@ import static org.testng.Assert.assertTrue;
 import jalview.api.analysis.PairwiseScoreModelI;
 import jalview.api.analysis.ScoreModelI;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.util.Iterator;
 
 import org.testng.annotations.Test;
@@ -102,4 +104,17 @@ public class ScoreModelsTest
       }
     }
   }
+
+  @Test(groups = "Functional")
+  public void testInstantiate()
+          throws InstantiationException, IllegalAccessException,
+          NoSuchMethodException, SecurityException,
+          IllegalArgumentException, InvocationTargetException
+  {
+    Class<? extends Object> c = ScoreModels.class;
+    Constructor<? extends Object> con = c.getDeclaredConstructor();
+    con.setAccessible(true);
+    Object o = con.newInstance();
+    System.out.println(o);
+  }
 }
index 9e9d9a4..92fef42 100644 (file)
@@ -54,13 +54,13 @@ public class EnsemblCdnaTest
   @BeforeClass(alwaysRun = true)
   public void setUp()
   {
-    SequenceOntologyFactory.setInstance(new SequenceOntologyLite());
+    SequenceOntologyFactory.setSequenceOntology(new SequenceOntologyLite());
   }
 
   @AfterClass(alwaysRun = true)
   public void tearDown()
   {
-    SequenceOntologyFactory.setInstance(null);
+    SequenceOntologyFactory.setSequenceOntology(null);
   }
 
   /**
index e7574eb..4521d9b 100644 (file)
@@ -53,13 +53,13 @@ public class EnsemblCdsTest
   @BeforeClass(alwaysRun = true)
   public void setUp()
   {
-    SequenceOntologyFactory.setInstance(new SequenceOntologyLite());
+    SequenceOntologyFactory.setSequenceOntology(new SequenceOntologyLite());
   }
 
   @AfterClass(alwaysRun = true)
   public void tearDown()
   {
-    SequenceOntologyFactory.setInstance(null);
+    SequenceOntologyFactory.setSequenceOntology(null);
   }
 
   /**
index 8b1e840..da129ba 100644 (file)
@@ -56,13 +56,13 @@ public class EnsemblGeneTest
   public void setUp()
   {
     Cache.loadProperties("test/jalview/io/testProps.jvprops");
-    SequenceOntologyFactory.setInstance(new SequenceOntologyLite());
+    SequenceOntologyFactory.setSequenceOntology(new SequenceOntologyLite());
   }
 
   @AfterClass(alwaysRun = true)
   public void tearDown()
   {
-    SequenceOntologyFactory.setInstance(null);
+    SequenceOntologyFactory.setSequenceOntology(null);
   }
 
   /**
index 11140f9..0a9cc64 100644 (file)
@@ -52,13 +52,13 @@ public class EnsemblGenomeTest
   @BeforeClass(alwaysRun = true)
   public void setUp()
   {
-    SequenceOntologyFactory.setInstance(new SequenceOntologyLite());
+    SequenceOntologyFactory.setSequenceOntology(new SequenceOntologyLite());
   }
 
   @AfterClass(alwaysRun = true)
   public void tearDown()
   {
-    SequenceOntologyFactory.setInstance(null);
+    SequenceOntologyFactory.setSequenceOntology(null);
   }
 
   /**
index 17e92c8..27008f5 100644 (file)
@@ -139,13 +139,13 @@ public class EnsemblSeqProxyTest
   @BeforeClass(alwaysRun = true)
   public void setUp()
   {
-    SequenceOntologyFactory.setInstance(new SequenceOntologyLite());
+    SequenceOntologyFactory.setSequenceOntology(new SequenceOntologyLite());
   }
 
   @AfterClass(alwaysRun = true)
   public void tearDown()
   {
-    SequenceOntologyFactory.setInstance(null);
+    SequenceOntologyFactory.setSequenceOntology(null);
   }
 
   @DataProvider(name = "ens_seqs")
index e42b54f..353d5ea 100644 (file)
@@ -61,7 +61,8 @@ public class JmolCommandsTest
     SequenceRenderer sr = new SequenceRenderer(af.getViewport());
     SequenceI[][] seqs = new SequenceI[][] { { seq1 }, { seq2 } };
     String[] files = new String[] { "seq1.pdb", "seq2.pdb" };
-    StructureSelectionManager ssm = new StructureSelectionManager();
+    StructureSelectionManager ssm = StructureSelectionManager
+            .getStructureSelectionManager(null);
 
     // need some mappings!
 
@@ -90,12 +91,13 @@ public class JmolCommandsTest
     SequenceRenderer sr = new SequenceRenderer(af.getViewport());
     SequenceI[][] seqs = new SequenceI[][] { { seq1 }, { seq2 } };
     String[] files = new String[] { "seq1.pdb", "seq2.pdb" };
-    StructureSelectionManager ssm = new StructureSelectionManager();
+    StructureSelectionManager ssm = StructureSelectionManager
+            .getStructureSelectionManager(null);
   
     /*
      * map residues 1-10 to residues 21-30 (atoms 105-150) in structures
      */
-    HashMap<Integer, int[]> map = new HashMap<Integer, int[]>();
+    HashMap<Integer, int[]> map = new HashMap<>();
     for (int pos = 1; pos <= seq1.getLength(); pos++)
     {
       map.put(pos, new int[] { 20 + pos, 5 * (20 + pos) });
index 2c973ca..bf4889a 100644 (file)
@@ -59,7 +59,7 @@ public class ChimeraCommandsTest
   public void testBuildColourCommands()
   {
 
-    Map<Object, AtomSpecModel> map = new LinkedHashMap<Object, AtomSpecModel>();
+    Map<Object, AtomSpecModel> map = new LinkedHashMap<>();
     ChimeraCommands.addColourRange(map, Color.blue, 0, 2, 5, "A");
     ChimeraCommands.addColourRange(map, Color.blue, 0, 7, 7, "B");
     ChimeraCommands.addColourRange(map, Color.blue, 0, 9, 23, "A");
@@ -84,8 +84,8 @@ public class ChimeraCommandsTest
     /*
      * make a map of { featureType, {featureValue, {residue range specification } } }
      */
-    Map<String, Map<Object, AtomSpecModel>> featuresMap = new LinkedHashMap<String, Map<Object, AtomSpecModel>>();
-    Map<Object, AtomSpecModel> featureValues = new HashMap<Object, AtomSpecModel>();
+    Map<String, Map<Object, AtomSpecModel>> featuresMap = new LinkedHashMap<>();
+    Map<Object, AtomSpecModel> featureValues = new HashMap<>();
     
     /*
      * start with just one feature/value...
@@ -184,12 +184,13 @@ public class ChimeraCommandsTest
     SequenceRenderer sr = new SequenceRenderer(af.getViewport());
     SequenceI[][] seqs = new SequenceI[][] { { seq1 }, { seq2 } };
     String[] files = new String[] { "seq1.pdb", "seq2.pdb" };
-    StructureSelectionManager ssm = new StructureSelectionManager();
+    StructureSelectionManager ssm = StructureSelectionManager
+            .getStructureSelectionManager(null);
 
     /*
      * map residues 1-10 to residues 21-30 (atoms 105-150) in structures
      */
-    HashMap<Integer, int[]> map = new HashMap<Integer, int[]>();
+    HashMap<Integer, int[]> map = new HashMap<>();
     for (int pos = 1; pos <= seq1.getLength(); pos++)
     {
       map.put(pos, new int[] { 20 + pos, 5 * (20 + pos) });
index 71378fe..ff8b19c 100644 (file)
@@ -79,7 +79,7 @@ public class AlignViewportTest
     /*
      * remove any sequence mappings left lying around by other tests
      */
-    Desktop.getStructureSelectionManager().resetAll();
+    Desktop.getInstance().getStructureSelectionManager().resetAll();
   }
 
   @BeforeMethod(alwaysRun = true)
@@ -125,7 +125,7 @@ public class AlignViewportTest
      * Verify that creating the alignment for the new View has registered the
      * mappings
      */
-    List<AlignedCodonFrame> sequenceMappings = Desktop
+    List<AlignedCodonFrame> sequenceMappings = Desktop.getInstance()
             .getStructureSelectionManager().getSequenceMappings();
     assertEquals(2, sequenceMappings.size());
     assertTrue(sequenceMappings.contains(acf1));
@@ -149,7 +149,8 @@ public class AlignViewportTest
   {
     Desktop d = Desktop.getInstance();
     assertNotNull(d);
-    StructureSelectionManager ssm = Desktop.getStructureSelectionManager();
+    StructureSelectionManager ssm = Desktop.getInstance()
+            .getStructureSelectionManager();
     ssm.resetAll();
 
     AlignFrame af1 = new FileLoader().LoadFileWaitTillLoaded(
@@ -211,7 +212,8 @@ public class AlignViewportTest
   {
     Desktop d = Desktop.getInstance();
     assertNotNull(d);
-    StructureSelectionManager ssm = Desktop.getStructureSelectionManager();
+    StructureSelectionManager ssm = Desktop.getInstance()
+            .getStructureSelectionManager();
     ssm.resetAll();
 
     AlignFrame af1 = new FileLoader().LoadFileWaitTillLoaded(
@@ -443,7 +445,6 @@ public class AlignViewportTest
     {
       c++;
     }
-    ;
     Assert.assertEquals(c, 1, "Expected to find one occupancy row.");
   }
 
index 59ef8ad..59d024c 100644 (file)
@@ -69,7 +69,7 @@ public class FeaturesFileTest
     /*
      * remove any sequence mappings created so they don't pollute other tests
      */
-    Desktop.getStructureSelectionManager().resetAll();
+    Desktop.getInstance().getStructureSelectionManager().resetAll();
   }
 
   @BeforeClass(alwaysRun = true)
index 3a0560c..2af9559 100644 (file)
@@ -31,7 +31,7 @@ import java.util.Date;
 
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
-import org.testng.annotations.BeforeTest;
+import org.testng.annotations.BeforeMethod;
 
 public class Jalview2xmlBase
 {
@@ -54,6 +54,8 @@ public class Jalview2xmlBase
      */
     Cache.loadProperties("test/jalview/io/testProps.jvprops");
 
+    Cache.initLogger();
+
     /*
      * set news feed last read to a future time to ensure no
      * 'unread' news item is displayed
@@ -73,7 +75,7 @@ public class Jalview2xmlBase
     jalview.gui.Desktop.getInstance().closeAll_actionPerformed(null);
   }
 
-  @BeforeTest(alwaysRun = true)
+  @BeforeMethod(alwaysRun = true)
   public static void clearDesktop()
   {
     if (Desktop.getInstance() != null && Desktop.getFrames() != null
index af7c2ed..82027f0 100644 (file)
@@ -7,6 +7,7 @@ import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 
 import jalview.api.FeatureColourI;
+import jalview.bin.Cache;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
@@ -56,6 +57,7 @@ public class FeatureColourFinderTest
   @BeforeTest(alwaysRun = true)
   public void setUp()
   {
+    Cache.initLogger();
     // aligned column 8 is sequence position 6
     String s = ">s1\nABCDE---FGHIJKLMNOPQRSTUVWXYZ\n";
     af = new FileLoader().LoadFileWaitTillLoaded(s,
index 4bee3f5..1970ff2 100644 (file)
@@ -23,6 +23,7 @@ package jalview.structure;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertTrue;
 
+import jalview.bin.Cache;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.Sequence;
@@ -41,6 +42,11 @@ import org.testng.annotations.Test;
 
 public class Mapping
 {
+  @BeforeClass(alwaysRun = true)
+  public void setUp()
+  {
+    Cache.initLogger();
+  }
 
   @BeforeClass(alwaysRun = true)
   public void setUpJvOptionPane()
@@ -75,7 +81,8 @@ public class Mapping
       int coils[] = { 266, 275, 278, 287, 289, 298, 302, 316 }, helices[] = new int[]
       { 303, 315 }, sheets[] = new int[] { 267, 268, 269, 270 };
 
-      StructureSelectionManager ssm = new jalview.structure.StructureSelectionManager();
+      StructureSelectionManager ssm = StructureSelectionManager
+              .getStructureSelectionManager(null);
       StructureFile pmap = ssm.setMapping(true, new SequenceI[] { uprot },
               new String[] { "A" }, "test/jalview/ext/jmol/1QCF.pdb",
               DataSourceType.FILE);
@@ -144,7 +151,8 @@ public class Mapping
             "EIVKGVCSNFLCDLQPGDNVQITGPVGKEMLMPKDPNATIIMLATGTGIAPFRSFLWKMFFEKHDDYKFNGLGWLFLGVPTSSSLLYKEEFGKM");
     Sequence sq1 = new Sequence(sq);
     String inFile;
-    StructureSelectionManager ssm = new jalview.structure.StructureSelectionManager();
+    StructureSelectionManager ssm = StructureSelectionManager
+            .getStructureSelectionManager(null);
     // Associate the 1GAQ pdb file with the subsequence 'imported' from another
     // source
     StructureFile pde = ssm.setMapping(true, new SequenceI[] { sq },
@@ -243,7 +251,8 @@ public class Mapping
                     ">FER1_MAIZE/1-150 Ferredoxin-1, chloroplast precursor\nMATVLGSPRAPAFFFSSSSLRAAPAPTAVALPAAKVGIMGRSASSRRRLRAQATYNVKLITPEGEVELQVPD\nDVYILDQAEEDGIDLPYSCRAGSCSSCAGKVVSGSVDQSDQSYLDDGQIADGWVLTCHAYPTSDVVIETHKE\nEELTGA",
                     DataSourceType.PASTE, FileFormat.Fasta);
     SequenceI newseq = seqf.getViewport().getAlignment().getSequenceAt(0);
-    StructureSelectionManager ssm = new jalview.structure.StructureSelectionManager();
+    StructureSelectionManager ssm = StructureSelectionManager
+            .getStructureSelectionManager(null);
     StructureFile pmap = ssm.setMapping(true, new SequenceI[] { newseq },
             new String[] { null }, "examples/3W5V.pdb",
             DataSourceType.FILE);
@@ -272,7 +281,8 @@ public class Mapping
     // make it harder by shifting the copy vs the reference
     newseq.setStart(refseq.getStart() + 25);
     newseq.setEnd(refseq.getLength() + 25 + refseq.getStart());
-    StructureSelectionManager ssm = new jalview.structure.StructureSelectionManager();
+    StructureSelectionManager ssm = StructureSelectionManager
+            .getStructureSelectionManager(null);
     ssm.setProcessSecondaryStructure(true);
     ssm.setAddTempFacAnnot(true);
     StructureFile pmap = ssm.setMapping(true, new SequenceI[] { newseq },
index dab692f..d8f7314 100644 (file)
@@ -80,7 +80,8 @@ public class StructureSelectionManagerTest extends Jalview2xmlBase
   public void setUp()
   {
     StructureImportSettings.setShowSeqFeatures(true);
-    ssm = new StructureSelectionManager();
+    StructureSelectionManager.release(null);
+    ssm = StructureSelectionManager.getStructureSelectionManager(null);
   }
 
   @Test(groups = { "Functional" })
@@ -124,10 +125,10 @@ public class StructureSelectionManagerTest extends Jalview2xmlBase
     acf3.addMap(new Sequence("s3", "ttt"), new Sequence("p3", "p"),
             new MapList(new int[] { 1, 3 }, new int[] { 1, 1 }, 1, 1));
 
-    List<AlignedCodonFrame> set1 = new ArrayList<AlignedCodonFrame>();
+    List<AlignedCodonFrame> set1 = new ArrayList<>();
     set1.add(acf1);
     set1.add(acf2);
-    List<AlignedCodonFrame> set2 = new ArrayList<AlignedCodonFrame>();
+    List<AlignedCodonFrame> set2 = new ArrayList<>();
     set2.add(acf2);
     set2.add(acf3);
 
@@ -155,7 +156,8 @@ public class StructureSelectionManagerTest extends Jalview2xmlBase
     SequenceI seq = new Sequence(
             "1GAQ|B",
             "ATYNVKLITPEGEVELQVPDDVYILDQAEEDGIDLPYSCRAGSCSSCAGKVVSGSVDQSDQSYLDDGQIADGWVLTCHAYPTSDVVIETHKEEELTGA");
-    StructureSelectionManager sm = new StructureSelectionManager();
+    StructureSelectionManager sm = StructureSelectionManager
+            .getStructureSelectionManager(null);
     sm.setProcessSecondaryStructure(true);
     sm.setAddTempFacAnnot(true);
     StructureFile pmap = sm.setMapping(true, new SequenceI[] { seq },
@@ -202,11 +204,12 @@ public class StructureSelectionManagerTest extends Jalview2xmlBase
     Desktop.getInstance().closeAll_actionPerformed(null);
     try { 
       Thread.sleep(200);
-    } catch (Exception foo) {}; 
+    } catch (Exception foo) {} 
     SequenceI seq = new Sequence("4IM2|A",
             "LDFCIRNIEKTVMGEISDIHTKLLRLSSSQGTIE");
     String P4IM2_MISSING = "examples/testdata/4IM2_missing.pdb";
-    StructureSelectionManager sm = new StructureSelectionManager();
+    StructureSelectionManager sm = StructureSelectionManager
+            .getStructureSelectionManager(null);
     sm.setProcessSecondaryStructure(true);
     sm.setAddTempFacAnnot(true);
     StructureFile pmap = sm.setMapping(true, new SequenceI[] { seq },
@@ -406,7 +409,7 @@ public class StructureSelectionManagerTest extends Jalview2xmlBase
             ">TBK1_HUMAN/470-502 Serine/threonine-protein kinase TBK1\nFCIRNIEKTVKVYEKLMKINLEAAELGEISDIH",
             DataSourceType.PASTE);
     Desktop.addInternalFrame(alf, "Foo", 800, 600);
-    ;
+    
     AlignmentI al = alf.getViewport().getAlignment();
     SequenceI seq = al.getSequenceAt(0);
     assertEquals(470, seq.getStart());
@@ -459,14 +462,12 @@ public class StructureSelectionManagerTest extends Jalview2xmlBase
         Assert.assertNull(subseq,
                 "Expected no annotation transferred at position " + p);
       }
-      ;
       if (orig != null)
       {
         Assert.assertNotNull(subseq,
                 "Expected annotation transfer at position " + p);
         assertEquals(orig.value, subseq.value);
       }
-      ;
 
     }
   }
@@ -487,7 +488,6 @@ public class StructureSelectionManagerTest extends Jalview2xmlBase
     } catch (InterruptedException q)
     {
     }
-    ;
     Assert.assertTrue(schoose.selectStructure(pDBID),
             "Couldn't select structure via structure chooser: " + pDBID);
     schoose.showStructures(true);
index af02d5e..e7483ff 100644 (file)
@@ -130,7 +130,8 @@ public class AAStructureBindingModelTest
     PDBEntry importedPDB = new PDBEntry("3A6S", "", Type.PDB,
             "Paste");
     AAStructureBindingModel binder = new AAStructureBindingModel(
-            new StructureSelectionManager(), new PDBEntry[]
+            StructureSelectionManager.getStructureSelectionManager(null),
+            new PDBEntry[]
             { importedPDB },
             new SequenceI[][]
             { importedAl.getSequencesArray() }, null)
@@ -272,7 +273,8 @@ public class AAStructureBindingModelTest
     seqs[0] = new SequenceI[] { seq1a, seq1b };
     seqs[1] = new SequenceI[] { seq2 };
     seqs[2] = new SequenceI[] { seq3 };
-    StructureSelectionManager ssm = new StructureSelectionManager();
+    StructureSelectionManager ssm = StructureSelectionManager
+            .getStructureSelectionManager(null);
 
     ssm.setMapping(new SequenceI[] { seq1a, seq1b }, null, PDB_1,
             DataSourceType.PASTE, null);