Merge branch 'develop' into update_212_Dec_merge_with_21125_chamges
[jalview.git] / src / jalview / structure / StructureSelectionManager.java
index c8a846c..ae5431b 100644 (file)
  */
 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.Locale;
-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.Console;
 import jalview.commands.CommandI;
 import jalview.commands.EditCommand;
@@ -58,15 +49,27 @@ 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.Locale;
+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<StructureSelectionManagerProvider, StructureSelectionManager> instances;
 
   private List<StructureMapping> mappings = new ArrayList<>();
 
@@ -84,6 +87,111 @@ public class StructureSelectionManager
   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> 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);
+  }
+
+  /**
+   * Private constructor as all 'singleton' instances are managed here or by
+   * ApplicationSingletonProvider
+   */
+  private StructureSelectionManager()
+  {
+    selectionManagers = new IdentityHashMap<>();
+  }
+
+  /**
+   * 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;
+  }
+/** Null provider in 2.11.2
+
+
+  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;
+  }
+*/
 
   /**
    * @return true if will try to use external services for processing secondary
@@ -199,49 +307,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
@@ -271,7 +336,7 @@ public class StructureSelectionManager
     return relaySeqMappings;
   }
 
-  Vector listeners = new Vector();
+  Vector<Object> listeners = new Vector<>();
 
   /**
    * register a listener for alignment sequence mouseover events
@@ -309,6 +374,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
@@ -321,7 +388,7 @@ public class StructureSelectionManager
    * @return null or the structure data parsed as a pdb file
    */
   synchronized public StructureFile setMapping(SequenceI[] sequence,
-          String[] targetChains, String pdbFile, DataSourceType protocol,
+          String[] targetChains, String pdbFile, DataSourceType protocol, 
           IProgressIndicator progress)
   {
     return computeMapping(true, sequence, targetChains, pdbFile, protocol,
@@ -333,8 +400,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
@@ -378,9 +448,9 @@ public class StructureSelectionManager
    *          mapping operation
    * @return null or the structure data parsed as a pdb file
    */
-  synchronized public StructureFile computeMapping(boolean forStructureView,
-          SequenceI[] sequenceArray, String[] targetChainIds,
-          String pdbFile, DataSourceType sourceType,
+  synchronized private StructureFile computeMapping(
+          boolean forStructureView, SequenceI[] sequenceArray,
+          String[] targetChainIds, String pdbFile, DataSourceType sourceType,
           IProgressIndicator progress)
   {
     long progressSessionId = System.currentTimeMillis() * 3;
@@ -411,20 +481,17 @@ public class StructureSelectionManager
         registerPDBFile(pdb.getId().trim(), pdbFile);
       }
       // if PDBId is unavailable then skip SIFTS mapping execution path
-      // TODO: JAL-3868 need to know if structure is actually from
-      // PDB (has valid PDB ID and has provenance suggesting it
+      // TODO: JAL-3868 need to know if structure is actually from 
+      // PDB (has valid PDB ID and has provenance suggesting it 
       // actually came from PDB)
       boolean isProtein = false;
-      for (SequenceI s : sequenceArray)
-      {
-        if (s.isProtein())
-        {
+      for (SequenceI s:sequenceArray) {
+        if (s.isProtein()) {
           isProtein = true;
           break;
         }
       }
-      isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable()
-              && !pdb.getId().startsWith("AF-") && isProtein;
+      isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable() && !pdb.getId().startsWith("AF-") && isProtein;
 
     } catch (Exception ex)
     {
@@ -536,11 +603,9 @@ public class StructureSelectionManager
       List<StructureMapping> seqToStrucMapping = new ArrayList<>();
       if (isMapUsingSIFTs && seq.isProtein())
       {
-        if (progress != null)
-        {
-          progress.setProgressBar(
-                  MessageManager
-                          .getString("status.obtaining_mapping_with_sifts"),
+        if (progress!=null) {
+          progress.setProgressBar(MessageManager
+                .getString("status.obtaining_mapping_with_sifts"),
                   progressSessionId);
         }
         jalview.datamodel.Mapping sqmpping = maxAlignseq
@@ -583,8 +648,9 @@ public class StructureSelectionManager
             StructureMapping siftsMapping = null;
             try
             {
-              siftsMapping = getStructureMapping(seq, pdbFile, chain.id,
-                      pdb, chain, sqmpping, maxAlignseq, siftsClient);
+              siftsMapping = getStructureMapping(seq,
+                      pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq,
+                      siftsClient);
               foundSiftsMappings.add(siftsMapping);
               chain.makeExactMapping(siftsMapping, seq);
               chain.transferRESNUMFeatures(seq, "IEA: SIFTS",
@@ -594,10 +660,12 @@ public class StructureSelectionManager
             } catch (SiftsException e)
             {
               System.err.println(e.getMessage());
-            } catch (Exception e)
+            }
+            catch (Exception e)
             {
-              System.err.println(
-                      "Unexpected exception during SIFTS mapping - falling back to NW for this sequence/structure pair");
+              System.err
+                      .println(
+                              "Unexpected exception during SIFTS mapping - falling back to NW for this sequence/structure pair");
               System.err.println(e.getMessage());
             }
           }
@@ -623,9 +691,8 @@ public class StructureSelectionManager
       {
         if (progress != null)
         {
-          progress.setProgressBar(
-                  MessageManager.getString(
-                          "status.obtaining_mapping_with_nw_alignment"),
+          progress.setProgressBar(MessageManager
+                                 .getString("status.obtaining_mapping_with_nw_alignment"),
                   progressSessionId);
         }
         StructureMapping nwMapping = getNWMappings(seq, pdbFile, maxChainId,
@@ -715,8 +782,7 @@ public class StructureSelectionManager
   private StructureMapping getStructureMapping(SequenceI seq,
           String pdbFile, String targetChainId, StructureFile pdb,
           PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
-          AlignSeq maxAlignseq, SiftsClient siftsClient)
-          throws SiftsException
+          AlignSeq maxAlignseq, SiftsClient siftsClient) throws SiftsException
   {
     StructureMapping curChainMapping = siftsClient
             .getSiftsStructureMapping(seq, pdbFile, targetChainId);
@@ -1261,8 +1327,11 @@ 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()
   {
@@ -1300,7 +1369,11 @@ public class StructureSelectionManager
     }
   }
 
-  public void addSelectionListener(SelectionListener selecter)
+  public List<SelectionListener> getListeners() {
+    return sel_listeners;
+  }
+  
+   public void addSelectionListener(SelectionListener selecter)
   {
     if (!sel_listeners.contains(selecter))
     {
@@ -1353,34 +1426,15 @@ public class StructureSelectionManager
     }
   }
 
+  
   /**
-   * 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)