From 3efc513242af226b2829a887afdb65fb4c6a1bb7 Mon Sep 17 00:00:00 2001 From: BobHanson Date: Tue, 2 Jun 2020 19:58:05 -0500 Subject: [PATCH] JAL-3446 from JAL-3253 ApplicationSingletonProvider StructureSelectionManager and others --- src/jalview/bin/Jalview.java | 2 +- .../datamodel/features/SequenceFeatures.java | 2 +- src/jalview/ext/ensembl/EnsemblCds.java | 2 +- src/jalview/ext/ensembl/EnsemblGene.java | 4 +- src/jalview/ext/ensembl/EnsemblSeqProxy.java | 4 +- src/jalview/httpserver/HttpServer.java | 39 ++-- src/jalview/io/FileFormats.java | 20 +- src/jalview/io/cache/AppCache.java | 26 +-- src/jalview/io/gff/Gff3Helper.java | 4 +- src/jalview/io/gff/InterProScanHelper.java | 2 +- src/jalview/io/gff/SequenceOntologyFactory.java | 54 +++++- src/jalview/rest/RestHandler.java | 16 +- src/jalview/schemes/ColourSchemes.java | 63 ++++-- src/jalview/structure/StructureImportSettings.java | 63 +++--- .../structure/StructureSelectionManager.java | 203 ++++++++++---------- test/jalview/ext/ensembl/EnsemblCdnaTest.java | 4 +- test/jalview/ext/ensembl/EnsemblCdsTest.java | 4 +- test/jalview/ext/ensembl/EnsemblGeneTest.java | 4 +- test/jalview/ext/ensembl/EnsemblGenomeTest.java | 4 +- test/jalview/ext/ensembl/EnsemblSeqProxyTest.java | 4 +- test/jalview/ext/jmol/JmolCommandsTest.java | 4 +- .../ext/rbvi/chimera/ChimeraCommandsTest.java | 2 +- test/jalview/structure/Mapping.java | 12 +- .../structure/StructureSelectionManagerTest.java | 6 +- .../models/AAStructureBindingModelTest.java | 4 +- 25 files changed, 317 insertions(+), 235 deletions(-) diff --git a/src/jalview/bin/Jalview.java b/src/jalview/bin/Jalview.java index 963963d..ad7bad6 100755 --- a/src/jalview/bin/Jalview.java +++ b/src/jalview/bin/Jalview.java @@ -483,7 +483,7 @@ public class Jalview implements ApplicationSingletonI, JalviewJSApi boolean soDefault = !Platform.isJS(); if (Cache.getDefault("USE_FULL_SO", soDefault)) { - SequenceOntologyFactory.setInstance(new SequenceOntology()); + SequenceOntologyFactory.setSequenceOntology(new SequenceOntology()); } if (!headless) diff --git a/src/jalview/datamodel/features/SequenceFeatures.java b/src/jalview/datamodel/features/SequenceFeatures.java index 8ac4991..82772bc 100644 --- a/src/jalview/datamodel/features/SequenceFeatures.java +++ b/src/jalview/datamodel/features/SequenceFeatures.java @@ -372,7 +372,7 @@ public class SequenceFeatures implements SequenceFeaturesI { return true; } - SequenceOntologyI so = SequenceOntologyFactory.getInstance(); + SequenceOntologyI so = SequenceOntologyFactory.getSequenceOntology(); for (String term : soTerm) { if (type.equals(term) || so.isA(type, term)) diff --git a/src/jalview/ext/ensembl/EnsemblCds.java b/src/jalview/ext/ensembl/EnsemblCds.java index 8f13d99..bf37265 100644 --- a/src/jalview/ext/ensembl/EnsemblCds.java +++ b/src/jalview/ext/ensembl/EnsemblCds.java @@ -93,7 +93,7 @@ public class EnsemblCds extends EnsemblSeqProxy @Override protected boolean retainFeature(SequenceFeature sf, String accessionId) { - if (SequenceOntologyFactory.getInstance().isA(sf.getType(), + if (SequenceOntologyFactory.getSequenceOntology().isA(sf.getType(), SequenceOntologyI.CDS)) { return false; diff --git a/src/jalview/ext/ensembl/EnsemblGene.java b/src/jalview/ext/ensembl/EnsemblGene.java index 157b8b9..3d957f0 100644 --- a/src/jalview/ext/ensembl/EnsemblGene.java +++ b/src/jalview/ext/ensembl/EnsemblGene.java @@ -578,7 +578,7 @@ public class EnsemblGene extends EnsemblSeqProxy @Override protected boolean retainFeature(SequenceFeature sf, String accessionId) { - SequenceOntologyI so = SequenceOntologyFactory.getInstance(); + SequenceOntologyI so = SequenceOntologyFactory.getSequenceOntology(); String type = sf.getType(); if (so.isA(type, SequenceOntologyI.GENE)) { @@ -625,7 +625,7 @@ public class EnsemblGene extends EnsemblSeqProxy { return new FeatureSettingsAdapter() { - SequenceOntologyI so = SequenceOntologyFactory.getInstance(); + SequenceOntologyI so = SequenceOntologyFactory.getSequenceOntology(); @Override public boolean isFeatureDisplayed(String type) diff --git a/src/jalview/ext/ensembl/EnsemblSeqProxy.java b/src/jalview/ext/ensembl/EnsemblSeqProxy.java index fd8800f..11f8b7b 100644 --- a/src/jalview/ext/ensembl/EnsemblSeqProxy.java +++ b/src/jalview/ext/ensembl/EnsemblSeqProxy.java @@ -732,7 +732,7 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient * for sequence_variant on reverse strand, have to convert the allele * values to their complements */ - if (!forwardStrand && SequenceOntologyFactory.getInstance() + if (!forwardStrand && SequenceOntologyFactory.getSequenceOntology() .isA(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT)) { reverseComplementAlleles(copy); @@ -966,7 +966,7 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient public static boolean isTranscript(String featureType) { return SequenceOntologyI.NMD_TRANSCRIPT_VARIANT.equals(featureType) - || SequenceOntologyFactory.getInstance().isA(featureType, + || SequenceOntologyFactory.getSequenceOntology().isA(featureType, SequenceOntologyI.TRANSCRIPT); } } diff --git a/src/jalview/httpserver/HttpServer.java b/src/jalview/httpserver/HttpServer.java index a18d38d..9a59bda 100644 --- a/src/jalview/httpserver/HttpServer.java +++ b/src/jalview/httpserver/HttpServer.java @@ -20,6 +20,8 @@ */ package jalview.httpserver; +import jalview.bin.ApplicationSingletonProvider; +import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI; import jalview.rest.RestHandler; import java.net.BindException; @@ -49,8 +51,21 @@ 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 { + /** + * Returns the singleton instance of this class. + * + * @return + * @throws BindException + */ + public static HttpServer getInstance() throws BindException + { + synchronized (HttpServer.class) + { + return (HttpServer) ApplicationSingletonProvider.getInstance(HttpServer.class); + } + } /* * 'context root' - actually just prefixed to the path for each handler for * now - see registerHandler @@ -58,11 +73,6 @@ public class HttpServer private static final String JALVIEW_PATH = "jalview"; /* - * Singleton instance of this server - */ - private static HttpServer instance; - - /* * The Http server */ private Server server; @@ -82,23 +92,6 @@ public class HttpServer */ private URI contextRoot; - /** - * Returns the singleton instance of this class. - * - * @return - * @throws BindException - */ - public static HttpServer getInstance() throws BindException - { - synchronized (HttpServer.class) - { - if (instance == null) - { - instance = new HttpServer(); - } - return instance; - } - } /** * Private constructor to enforce use of singleton diff --git a/src/jalview/io/FileFormats.java b/src/jalview/io/FileFormats.java index aadcdb9..7743e17 100644 --- a/src/jalview/io/FileFormats.java +++ b/src/jalview/io/FileFormats.java @@ -27,6 +27,9 @@ import java.util.List; import java.util.Map; import java.util.Set; +import jalview.bin.ApplicationSingletonProvider; +import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI; + /** * A singleton registry of alignment file formats known to Jalview. On startup, * the 'built-in' formats are added (from the FileFormat enum). Additional @@ -36,24 +39,23 @@ import java.util.Set; * @author gmcarstairs * */ -public class FileFormats +public class FileFormats implements ApplicationSingletonI { - private static FileFormats instance = new FileFormats(); + public static FileFormats getInstance() + { + return (FileFormats) ApplicationSingletonProvider.getInstance(FileFormats.class); + } + /* * A lookup map of file formats by upper-cased name */ - private static Map formats; + private Map formats; /* * Formats in this set are capable of being identified by IdentifyFile */ - private static Set identifiable; - - public static FileFormats getInstance() - { - return instance; - } + private Set identifiable; /** * Private constructor registers Jalview's built-in file formats diff --git a/src/jalview/io/cache/AppCache.java b/src/jalview/io/cache/AppCache.java index eaf6ecd..76827f9 100644 --- a/src/jalview/io/cache/AppCache.java +++ b/src/jalview/io/cache/AppCache.java @@ -20,6 +20,8 @@ */ package jalview.io.cache; +import jalview.bin.ApplicationSingletonProvider; +import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI; import jalview.bin.Cache; import java.util.Hashtable; @@ -31,14 +33,18 @@ import java.util.LinkedHashSet; * @author tcnofoegbu * */ -public class AppCache +public class AppCache implements ApplicationSingletonI { + + public static AppCache getInstance() + { + return (AppCache) ApplicationSingletonProvider.getInstance(AppCache.class); + } + public static final String DEFAULT_LIMIT = "99"; public static final String CACHE_DELIMITER = ";"; - private static AppCache instance = null; - private static final String DEFAULT_LIMIT_KEY = ".DEFAULT_LIMIT"; private Hashtable> cacheItems; @@ -66,20 +72,6 @@ public class AppCache } /** - * Returns a singleton instance of AppCache - * - * @return - */ - public static AppCache getInstance() - { - if (instance == null) - { - instance = new AppCache(); - } - return instance; - } - - /** * Method for persisting cache items for a given cache key * * @param cacheKey diff --git a/src/jalview/io/gff/Gff3Helper.java b/src/jalview/io/gff/Gff3Helper.java index 1ef8848..e422ed4 100644 --- a/src/jalview/io/gff/Gff3Helper.java +++ b/src/jalview/io/gff/Gff3Helper.java @@ -91,7 +91,7 @@ public class Gff3Helper extends GffHelperBase String atts = gff[ATTRIBUTES_COL]; Map> attributes = parseNameValuePairs(atts); - SequenceOntologyI so = SequenceOntologyFactory.getInstance(); + SequenceOntologyI so = SequenceOntologyFactory.getSequenceOntology(); if (so.isA(soTerm, SequenceOntologyI.PROTEIN_MATCH)) { sf = processProteinMatch(attributes, seq, gff, align, newseqs, @@ -385,7 +385,7 @@ public class Gff3Helper extends GffHelperBase desc = target.split(" ")[0]; } - SequenceOntologyI so = SequenceOntologyFactory.getInstance(); + SequenceOntologyI so = SequenceOntologyFactory.getSequenceOntology(); String type = sf.getType(); if (so.isA(type, SequenceOntologyI.SEQUENCE_VARIANT)) { diff --git a/src/jalview/io/gff/InterProScanHelper.java b/src/jalview/io/gff/InterProScanHelper.java index 948cdd2..141b677 100644 --- a/src/jalview/io/gff/InterProScanHelper.java +++ b/src/jalview/io/gff/InterProScanHelper.java @@ -108,7 +108,7 @@ public class InterProScanHelper extends Gff3Helper */ public static boolean recognises(String[] columns) { - SequenceOntologyI so = SequenceOntologyFactory.getInstance(); + SequenceOntologyI so = SequenceOntologyFactory.getSequenceOntology(); String type = columns[TYPE_COL]; if (so.isA(type, SequenceOntologyI.PROTEIN_MATCH) || (".".equals(columns[SOURCE_COL]) diff --git a/src/jalview/io/gff/SequenceOntologyFactory.java b/src/jalview/io/gff/SequenceOntologyFactory.java index 90cae7a..ee362b4 100644 --- a/src/jalview/io/gff/SequenceOntologyFactory.java +++ b/src/jalview/io/gff/SequenceOntologyFactory.java @@ -20,6 +20,9 @@ */ package jalview.io.gff; +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 @@ -28,21 +31,52 @@ package jalview.io.gff; * @author gmcarstairs * */ -public class SequenceOntologyFactory +public class SequenceOntologyFactory implements ApplicationSingletonI { - private static SequenceOntologyI instance; + /** + * 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); + } - public static synchronized SequenceOntologyI getInstance() + /** + * Answers the configured model of the Sequence Ontology. + * + * @return + */ + public static synchronized SequenceOntologyI getSequenceOntology() { - if (instance == null) - { - instance = new SequenceOntologyLite(); - } - return instance; + SequenceOntologyFactory f = getInstance(); + return (f.sequenceOntology == null + ? f.sequenceOntology = new SequenceOntologyLite() + : f.sequenceOntology); } - public static void setInstance(SequenceOntologyI so) + /** + * For testng only + * + * @param so + */ + public static void setSequenceOntology(SequenceOntologyI so) { - instance = so; + getInstance().sequenceOntology = so; } + + + private SequenceOntologyI sequenceOntology; + + private SequenceOntologyFactory() + { + // private singleton + } + } diff --git a/src/jalview/rest/RestHandler.java b/src/jalview/rest/RestHandler.java index a37882f..7c8c9a6 100644 --- a/src/jalview/rest/RestHandler.java +++ b/src/jalview/rest/RestHandler.java @@ -20,6 +20,8 @@ */ package jalview.rest; +import jalview.bin.ApplicationSingletonProvider; +import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI; import jalview.httpserver.AbstractRequestHandler; import java.io.IOException; @@ -30,20 +32,16 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** - * A simple handler to process (or delegate) HTTP requests on /jalview/rest + * A simple handler to process (or delegate) HTTP requests on /jalview/rest. */ public class RestHandler extends AbstractRequestHandler + implements ApplicationSingletonI { private static final String MY_PATH = "rest"; private static final String MY_NAME = "Rest"; /** - * Singleton instance of this class - */ - private static RestHandler instance = null; - - /** * Returns the singleton instance of this class * * @return @@ -53,12 +51,8 @@ public class RestHandler extends AbstractRequestHandler { synchronized (RestHandler.class) { - if (instance == null) - { - instance = new RestHandler(); - } + return (RestHandler) ApplicationSingletonProvider.getInstance(RestHandler.class); } - return instance; } /** diff --git a/src/jalview/schemes/ColourSchemes.java b/src/jalview/schemes/ColourSchemes.java index d31fbba..0ff7c6e 100644 --- a/src/jalview/schemes/ColourSchemes.java +++ b/src/jalview/schemes/ColourSchemes.java @@ -21,24 +21,19 @@ package jalview.schemes; import jalview.api.AlignViewportI; +import jalview.bin.ApplicationSingletonProvider; +import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI; import jalview.datamodel.AnnotatedCollectionI; import jalview.datamodel.SequenceCollectionI; import jalview.datamodel.SequenceI; +import jalview.util.ColorUtils; +import java.awt.Color; import java.util.LinkedHashMap; import java.util.Map; -public class ColourSchemes +public class ColourSchemes implements ApplicationSingletonI { - /* - * singleton instance of this class - */ - private static ColourSchemes instance = new ColourSchemes(); - - /* - * a map from scheme name (lower-cased) to an instance of it - */ - private Map schemes; /** * Returns the singleton instance of this class @@ -47,7 +42,8 @@ public class ColourSchemes */ public static ColourSchemes getInstance() { - return instance; + return (ColourSchemes) ApplicationSingletonProvider + .getInstance(ColourSchemes.class); } private ColourSchemes() @@ -56,6 +52,51 @@ public class ColourSchemes } /** + * ColourSchemeProperty "static" + */ + public Color[] rnaHelices = null; + + /** + * delete the existing cached RNA helices colours + */ + public static void resetRnaHelicesShading() + { + getInstance().rnaHelices = null; + } + + public static void initRnaHelicesShading(int n) + { + int i = 0; + ColourSchemes j = getInstance(); + + if (j.rnaHelices == null) + { + j.rnaHelices = new Color[n + 1]; + } + else if (j.rnaHelices != null && j.rnaHelices.length <= n) + { + Color[] t = new Color[n + 1]; + System.arraycopy(j.rnaHelices, 0, t, 0, j.rnaHelices.length); + i = j.rnaHelices.length; + j.rnaHelices = t; + } + else + { + return; + } + // Generate random colors and store + for (; i <= n; i++) + { + j.rnaHelices[i] = ColorUtils.generateRandomColor(Color.white); + } + } + + /** + * a map from scheme name (lower-cased) to an instance of it + */ + private Map schemes; + + /** * Loads an instance of each standard or user-defined colour scheme * * @return diff --git a/src/jalview/structure/StructureImportSettings.java b/src/jalview/structure/StructureImportSettings.java index 9662fee..b5672ab 100644 --- a/src/jalview/structure/StructureImportSettings.java +++ b/src/jalview/structure/StructureImportSettings.java @@ -20,6 +20,8 @@ */ package jalview.structure; +import jalview.bin.ApplicationSingletonProvider; +import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI; import jalview.datamodel.PDBEntry; import jalview.datamodel.PDBEntry.Type; @@ -30,27 +32,39 @@ import jalview.datamodel.PDBEntry.Type; * @author tcofoegbu * */ -public class StructureImportSettings +public class StructureImportSettings implements ApplicationSingletonI { + + private StructureImportSettings() + { + // private singleton + } + + private static StructureImportSettings getInstance() + { + return (StructureImportSettings) ApplicationSingletonProvider + .getInstance(StructureImportSettings.class); + } + /** * set to true to add derived sequence annotations (temp factor read from * file, or computed secondary structure) to the alignment */ - private static boolean visibleChainAnnotation = false; + private boolean visibleChainAnnotation = false; /** * Set true to predict secondary structure (using JMol for protein, Annotate3D * for RNA) */ - private static boolean processSecStr = false; + private boolean processSecStr = false; /** * Set true (with predictSecondaryStructure=true) to predict secondary * structure using an external service (currently Annotate3D for RNA only) */ - private static boolean externalSecondaryStructure = false; + private boolean externalSecondaryStructure = false; - private static boolean showSeqFeatures = true; + private boolean showSeqFeatures = true; public enum StructureParser { @@ -61,92 +75,93 @@ public class StructureImportSettings * Determines the default file format for structure files to be downloaded * from the PDB sequence fetcher. Possible options include: PDB|mmCIF */ - private static PDBEntry.Type defaultStructureFileFormat = Type.PDB; + private PDBEntry.Type defaultStructureFileFormat = Type.PDB; /** * Determines the parser used for parsing PDB format file. Possible options * are : JMolParser|JalveiwParser */ - private static StructureParser defaultPDBFileParser = StructureParser.JMOL_PARSER; + private StructureParser defaultPDBFileParser = StructureParser.JMOL_PARSER; public static void addSettings(boolean addAlignmentAnnotations, boolean processSecStr, boolean externalSecStr) { - StructureImportSettings.visibleChainAnnotation = addAlignmentAnnotations; - StructureImportSettings.processSecStr = processSecStr; - StructureImportSettings.externalSecondaryStructure = externalSecStr; - StructureImportSettings.showSeqFeatures = true; + StructureImportSettings s = getInstance(); + s.visibleChainAnnotation = addAlignmentAnnotations; + s.processSecStr = processSecStr; + s.externalSecondaryStructure = externalSecStr; + s.showSeqFeatures = true; } public static boolean isVisibleChainAnnotation() { - return visibleChainAnnotation; + return getInstance().visibleChainAnnotation; } public static void setVisibleChainAnnotation( boolean visibleChainAnnotation) { - StructureImportSettings.visibleChainAnnotation = visibleChainAnnotation; + getInstance().visibleChainAnnotation = visibleChainAnnotation; } public static boolean isProcessSecondaryStructure() { - return processSecStr; + return getInstance().processSecStr; } public static void setProcessSecondaryStructure( boolean processSecondaryStructure) { - StructureImportSettings.processSecStr = processSecondaryStructure; + getInstance().processSecStr = processSecondaryStructure; } public static boolean isExternalSecondaryStructure() { - return externalSecondaryStructure; + return getInstance().externalSecondaryStructure; } public static void setExternalSecondaryStructure( boolean externalSecondaryStructure) { - StructureImportSettings.externalSecondaryStructure = externalSecondaryStructure; + getInstance().externalSecondaryStructure = externalSecondaryStructure; } public static boolean isShowSeqFeatures() { - return showSeqFeatures; + return getInstance().showSeqFeatures; } public static void setShowSeqFeatures(boolean showSeqFeatures) { - StructureImportSettings.showSeqFeatures = showSeqFeatures; + getInstance().showSeqFeatures = showSeqFeatures; } public static PDBEntry.Type getDefaultStructureFileFormat() { - return defaultStructureFileFormat; + return getInstance().defaultStructureFileFormat; } public static void setDefaultStructureFileFormat( String defaultStructureFileFormat) { - StructureImportSettings.defaultStructureFileFormat = PDBEntry.Type + getInstance().defaultStructureFileFormat = PDBEntry.Type .valueOf(defaultStructureFileFormat.toUpperCase()); } public static String getDefaultPDBFileParser() { - return defaultPDBFileParser.toString(); + return getInstance().defaultPDBFileParser.toString(); } public static void setDefaultPDBFileParser( StructureParser defaultPDBFileParser) { - StructureImportSettings.defaultPDBFileParser = defaultPDBFileParser; + getInstance().defaultPDBFileParser = defaultPDBFileParser; } public static void setDefaultPDBFileParser(String defaultPDBFileParser) { - StructureImportSettings.defaultPDBFileParser = StructureParser + getInstance().defaultPDBFileParser = StructureParser .valueOf(defaultPDBFileParser.toUpperCase()); } diff --git a/src/jalview/structure/StructureSelectionManager.java b/src/jalview/structure/StructureSelectionManager.java index 8c3816e..5b432f5 100644 --- a/src/jalview/structure/StructureSelectionManager.java +++ b/src/jalview/structure/StructureSelectionManager.java @@ -20,19 +20,10 @@ */ package jalview.structure; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Vector; - import jalview.analysis.AlignSeq; import jalview.api.StructureSelectionManagerProvider; +import jalview.bin.ApplicationSingletonProvider; +import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI; import jalview.bin.Cache; import jalview.commands.CommandI; import jalview.commands.EditCommand; @@ -57,16 +48,26 @@ import jalview.util.Platform; import jalview.ws.sifts.SiftsClient; import jalview.ws.sifts.SiftsException; import jalview.ws.sifts.SiftsSettings; + +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Vector; + 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(); - static IdentityHashMap instances; - private List mappings = new ArrayList<>(); private boolean processSecondaryStructure = false; @@ -84,6 +85,66 @@ public class StructureSelectionManager private List sel_listeners = new ArrayList<>(); + /* + * instances of this class scoped by some context class + */ + private IdentityHashMap selectionManagers; + + /** + * 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) + { + return getInstance().getInstanceForContext(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. Note that the context may be null (this is the case + * when running headless without a Desktop). + * + * @param context + * @return + */ + StructureSelectionManager getInstanceForContext( + StructureSelectionManagerProvider context) + { + StructureSelectionManager instance = selectionManagers.get(context); + if (instance == null) + { + instance = new StructureSelectionManager(); + selectionManagers.put(context, instance); + } + return instance; + } + + /** + * Private constructor as all 'singleton' instances are managed here or by + * ApplicationSingletonProvider + */ + private StructureSelectionManager() + { + selectionManagers = new IdentityHashMap<>(); + } + /** * @return true if will try to use external services for processing secondary * structure @@ -198,49 +259,6 @@ public class StructureSelectionManager || pdbIdFileName.containsKey(idOrFile); } - private static StructureSelectionManager nullProvider = null; - - public static StructureSelectionManager getStructureSelectionManager( - StructureSelectionManagerProvider context) - { - if (context == null) - { - if (nullProvider == null) - { - if (instances != null) - { - throw new Error(MessageManager.getString( - "error.implementation_error_structure_selection_manager_null"), - new NullPointerException(MessageManager - .getString("exception.ssm_context_is_null"))); - } - else - { - nullProvider = new StructureSelectionManager(); - } - return nullProvider; - } - } - if (instances == null) - { - instances = new java.util.IdentityHashMap<>(); - } - StructureSelectionManager instance = instances.get(context); - if (instance == null) - { - if (nullProvider != null) - { - instance = nullProvider; - } - else - { - instance = new StructureSelectionManager(); - } - instances.put(context, instance); - } - return instance; - } - /** * flag controlling whether SeqMappings are relayed from received sequence * mouse over events to other sequences @@ -270,7 +288,7 @@ public class StructureSelectionManager return relaySeqMappings; } - Vector listeners = new Vector(); + Vector listeners = new Vector<>(); /** * register a listener for alignment sequence mouseover events @@ -308,6 +326,8 @@ public class StructureSelectionManager * Import structure data and register a structure mapping for broadcasting * colouring, mouseovers and selection events (convenience wrapper). * + * This is the standard entry point. + * * @param sequence * - one or more sequences to be mapped to pdbFile * @param targetChains @@ -332,8 +352,11 @@ public class StructureSelectionManager * broadcasting colouring, mouseovers and selection events (convenience * wrapper). * + * + * * @param forStructureView - * when true, record the mapping for use in mouseOvers + * when true (testng only), record the mapping for use in mouseOvers + * (testng only) * @param sequence * - one or more sequences to be mapped to pdbFile * @param targetChains @@ -377,7 +400,7 @@ public class StructureSelectionManager * mapping operation * @return null or the structure data parsed as a pdb file */ - synchronized public StructureFile computeMapping( + synchronized private StructureFile computeMapping( boolean forStructureView, SequenceI[] sequenceArray, String[] targetChainIds, String pdbFile, DataSourceType sourceType, IProgressIndicator progress) @@ -652,7 +675,6 @@ public class StructureSelectionManager { ds = ds.getDatasetSequence(); } - ; if (ds.getAnnotation() != null) { for (AlignmentAnnotation ala : ds.getAnnotation()) @@ -906,9 +928,9 @@ public class StructureSelectionManager if (s != null) { result = s; - } } } + } return result; } @@ -1242,42 +1264,45 @@ public class StructureSelectionManager } /** - * Resets this object to its initial state by removing all registered - * listeners, codon mappings, PDB file mappings + * Reset this object to its initial state by removing all registered + * listeners, codon mappings, PDB file mappings. + * + * Called only by Desktop and testng. + * */ public void resetAll() { if (mappings != null) { - mappings.clear(); + mappings.clear(); } if (seqmappings != null) { - seqmappings.clear(); + seqmappings.clear(); } if (sel_listeners != null) { - sel_listeners.clear(); + sel_listeners.clear(); } if (listeners != null) { - listeners.clear(); + listeners.clear(); } if (commandListeners != null) { - commandListeners.clear(); + commandListeners.clear(); } if (view_listeners != null) { - view_listeners.clear(); + view_listeners.clear(); } if (pdbFileNameId != null) { - pdbFileNameId.clear(); + pdbFileNameId.clear(); } if (pdbIdFileName != null) { - pdbIdFileName.clear(); + pdbIdFileName.clear(); } } @@ -1329,41 +1354,23 @@ public class StructureSelectionManager { slis.viewPosition(startRes, endRes, startSeq, endSeq, source); } - ; + } } } + /** - * release all references associated with this manager provider + * Removes the instance associated with this provider * - * @param jalviewLite + * @param provider */ - public static void release(StructureSelectionManagerProvider jalviewLite) + + public static void release(StructureSelectionManagerProvider provider) { - // synchronized (instances) - { - if (instances == null) - { - return; - } - StructureSelectionManager mnger = (instances.get(jalviewLite)); - if (mnger != null) - { - instances.remove(jalviewLite); - try - { - /* bsoares 2019-03-20 finalize deprecated, no apparent external - * resources to close - */ - // mnger.finalize(); - } catch (Throwable x) - { - } - } - } + getInstance().selectionManagers.remove(provider); } - + public void registerPDBEntry(PDBEntry pdbentry) { if (pdbentry.getFile() != null diff --git a/test/jalview/ext/ensembl/EnsemblCdnaTest.java b/test/jalview/ext/ensembl/EnsemblCdnaTest.java index 9e9d9a4..92fef42 100644 --- a/test/jalview/ext/ensembl/EnsemblCdnaTest.java +++ b/test/jalview/ext/ensembl/EnsemblCdnaTest.java @@ -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); } /** diff --git a/test/jalview/ext/ensembl/EnsemblCdsTest.java b/test/jalview/ext/ensembl/EnsemblCdsTest.java index e7574eb..4521d9b 100644 --- a/test/jalview/ext/ensembl/EnsemblCdsTest.java +++ b/test/jalview/ext/ensembl/EnsemblCdsTest.java @@ -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); } /** diff --git a/test/jalview/ext/ensembl/EnsemblGeneTest.java b/test/jalview/ext/ensembl/EnsemblGeneTest.java index 8b1e840..da129ba 100644 --- a/test/jalview/ext/ensembl/EnsemblGeneTest.java +++ b/test/jalview/ext/ensembl/EnsemblGeneTest.java @@ -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); } /** diff --git a/test/jalview/ext/ensembl/EnsemblGenomeTest.java b/test/jalview/ext/ensembl/EnsemblGenomeTest.java index 11140f9..0a9cc64 100644 --- a/test/jalview/ext/ensembl/EnsemblGenomeTest.java +++ b/test/jalview/ext/ensembl/EnsemblGenomeTest.java @@ -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); } /** diff --git a/test/jalview/ext/ensembl/EnsemblSeqProxyTest.java b/test/jalview/ext/ensembl/EnsemblSeqProxyTest.java index e17b4a6..a4d6d92 100644 --- a/test/jalview/ext/ensembl/EnsemblSeqProxyTest.java +++ b/test/jalview/ext/ensembl/EnsemblSeqProxyTest.java @@ -135,13 +135,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") diff --git a/test/jalview/ext/jmol/JmolCommandsTest.java b/test/jalview/ext/jmol/JmolCommandsTest.java index e42b54f..8752f93 100644 --- a/test/jalview/ext/jmol/JmolCommandsTest.java +++ b/test/jalview/ext/jmol/JmolCommandsTest.java @@ -61,7 +61,7 @@ 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,7 +90,7 @@ 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 diff --git a/test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java b/test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java index 06a09df..a18a8a3 100644 --- a/test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java +++ b/test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java @@ -184,7 +184,7 @@ 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 diff --git a/test/jalview/structure/Mapping.java b/test/jalview/structure/Mapping.java index 4bee3f5..40715c8 100644 --- a/test/jalview/structure/Mapping.java +++ b/test/jalview/structure/Mapping.java @@ -75,7 +75,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 +145,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 +245,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 +275,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 }, diff --git a/test/jalview/structure/StructureSelectionManagerTest.java b/test/jalview/structure/StructureSelectionManagerTest.java index dab692f..8108cd8 100644 --- a/test/jalview/structure/StructureSelectionManagerTest.java +++ b/test/jalview/structure/StructureSelectionManagerTest.java @@ -80,7 +80,7 @@ public class StructureSelectionManagerTest extends Jalview2xmlBase public void setUp() { StructureImportSettings.setShowSeqFeatures(true); - ssm = new StructureSelectionManager(); + ssm = StructureSelectionManager.getStructureSelectionManager(null); } @Test(groups = { "Functional" }) @@ -155,7 +155,7 @@ 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 }, @@ -206,7 +206,7 @@ public class StructureSelectionManagerTest extends Jalview2xmlBase 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 }, diff --git a/test/jalview/structures/models/AAStructureBindingModelTest.java b/test/jalview/structures/models/AAStructureBindingModelTest.java index af02d5e..ac7e736 100644 --- a/test/jalview/structures/models/AAStructureBindingModelTest.java +++ b/test/jalview/structures/models/AAStructureBindingModelTest.java @@ -130,7 +130,7 @@ 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 +272,7 @@ 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); -- 1.7.10.2