temp push
[jalview.git] / src / jalview / structure / StructureSelectionManager.java
index 9513220..d6eec47 100644 (file)
@@ -22,6 +22,8 @@ package jalview.structure;
 
 import jalview.analysis.AlignSeq;
 import jalview.api.StructureSelectionManagerProvider;
+import jalview.bin.ApplicationSingletonProvider;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 import jalview.commands.CommandI;
 import jalview.commands.EditCommand;
 import jalview.commands.OrderCommand;
@@ -41,6 +43,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 +59,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 +84,77 @@ 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);
+  }
+
+  /**
+   * 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;
+  }
+
+  /**
+   * Removes the instance associated with this provider
+   * 
+   * @param provider
+   */
+
+  public static void release(StructureSelectionManagerProvider provider)
+  {
+    getInstance().selectionManagers.remove(provider);
+  }
+
+  /**
+   * 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
@@ -197,49 +269,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 +298,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 +336,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 +362,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 +410,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)
@@ -650,7 +684,6 @@ public class StructureSelectionManager
         {
           ds = ds.getDatasetSequence();
         }
-        ;
         if (ds.getAnnotation() != null)
         {
           for (AlignmentAnnotation ala : ds.getAnnotation())
@@ -858,13 +891,14 @@ public class StructureSelectionManager
    * @param pdbResNum
    * @param chain
    * @param pdbfile
+   * @return
    */
-  public void mouseOverStructure(int pdbResNum, String chain,
+  public String mouseOverStructure(int pdbResNum, String chain,
           String pdbfile)
   {
     AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
     List<AtomSpec> atoms = Collections.singletonList(atomSpec);
-    mouseOverStructure(atoms);
+    return mouseOverStructure(atoms);
   }
 
   /**
@@ -872,12 +906,12 @@ public class StructureSelectionManager
    * 
    * @param atoms
    */
-  public void mouseOverStructure(List<AtomSpec> atoms)
+  public String mouseOverStructure(List<AtomSpec> atoms)
   {
     if (listeners == null)
     {
       // old or prematurely sent event
-      return;
+      return null;
     }
     boolean hasSequenceListener = false;
     for (int i = 0; i < listeners.size(); i++)
@@ -889,18 +923,24 @@ public class StructureSelectionManager
     }
     if (!hasSequenceListener)
     {
-      return;
+      return null;
     }
 
     SearchResultsI results = findAlignmentPositionsForStructurePositions(
             atoms);
+    String result = null;
     for (Object li : listeners)
     {
       if (li instanceof SequenceListener)
       {
-        ((SequenceListener) li).highlightSequence(results);
+        String s = ((SequenceListener) li).highlightSequence(results);
+        if (s != null)
+        {
+          result = s;
+        }
       }
     }
+    return result;
   }
 
   /**
@@ -1170,7 +1210,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);
@@ -1319,41 +1360,10 @@ public class StructureSelectionManager
         {
           slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
         }
-        ;
-      }
-    }
-  }
-
-  /**
-   * release all references associated with this manager provider
-   * 
-   * @param jalviewLite
-   */
-  public static void release(StructureSelectionManagerProvider jalviewLite)
-  {
-    // 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)
-        {
-        }
       }
     }
   }
-
+  
   public void registerPDBEntry(PDBEntry pdbentry)
   {
     if (pdbentry.getFile() != null