JAL-3446 from JAL-3253 ApplicationSingletonProvider missing for
[jalview.git] / src / jalview / structure / StructureSelectionManager.java
index 65df679..bb1bb94 100644 (file)
@@ -22,6 +22,9 @@ package jalview.structure;
 
 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;
 import jalview.commands.OrderCommand;
@@ -41,6 +44,7 @@ import jalview.io.DataSourceType;
 import jalview.io.StructureFile;
 import jalview.util.MappingUtils;
 import jalview.util.MessageManager;
+import jalview.util.Platform;
 import jalview.ws.sifts.SiftsClient;
 import jalview.ws.sifts.SiftsException;
 import jalview.ws.sifts.SiftsSettings;
@@ -56,16 +60,14 @@ import java.util.List;
 import java.util.Map;
 import java.util.Vector;
 
-import MCview.Atom;
-import MCview.PDBChain;
-import MCview.PDBfile;
+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<>();
 
   private boolean processSecondaryStructure = false;
@@ -83,6 +85,67 @@ public class StructureSelectionManager
 
   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;
+  }
+
+
   /**
    * @return true if will try to use external services for processing secondary
    *         structure
@@ -197,49 +260,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
@@ -269,7 +289,7 @@ public class StructureSelectionManager
     return relaySeqMappings;
   }
 
-  Vector listeners = new Vector();
+  Vector<Object> listeners = new Vector<>();
 
   /**
    * register a listener for alignment sequence mouseover events
@@ -307,6 +327,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
@@ -331,8 +353,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
@@ -376,7 +401,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)
@@ -429,7 +454,8 @@ public class StructureSelectionManager
     } catch (SiftsException e)
     {
       isMapUsingSIFTs = false;
-      e.printStackTrace();
+      Cache.log.error("SIFTS mapping failed", e);
+      Cache.log.error("Falling back on Needleman & Wunsch alignment");
       siftsClient = null;
     }
 
@@ -650,7 +676,6 @@ public class StructureSelectionManager
         {
           ds = ds.getDatasetSequence();
         }
-        ;
         if (ds.getAnnotation() != null)
         {
           for (AlignmentAnnotation ala : ds.getAnnotation())
@@ -904,9 +929,9 @@ public class StructureSelectionManager
         if (s != null)
         {
           result = s;
-        }
       }
     }
+  }
     return result;
   }
 
@@ -1177,7 +1202,8 @@ public class StructureSelectionManager
     StringBuilder sb = new StringBuilder(64);
     for (StructureMapping sm : mappings)
     {
-      if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
+      if (Platform.pathEquals(sm.pdbfile, pdbfile)
+              && seqs.contains(sm.sequence))
       {
         sb.append(sm.mappingDetails);
         sb.append(NEWLINE);
@@ -1239,42 +1265,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();
     }
   }
 
@@ -1326,38 +1355,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
-        {
-          mnger.finalize();
-        } catch (Throwable x)
-        {
-        }
-      }
-    }
+    getInstance().selectionManagers.remove(provider);
   }
-
+  
   public void registerPDBEntry(PDBEntry pdbentry)
   {
     if (pdbentry.getFile() != null