JAL-1830 dropped reference counts for mappings, instead remove mapping
[jalview.git] / src / jalview / structure / StructureSelectionManager.java
index ac14b52..9dd730c 100644 (file)
  */
 package jalview.structure;
 
+import jalview.analysis.AlignSeq;
+import jalview.api.AlignmentViewPanel;
+import jalview.api.StructureSelectionManagerProvider;
+import jalview.commands.CommandI;
+import jalview.commands.EditCommand;
+import jalview.commands.OrderCommand;
+import jalview.datamodel.AlignedCodonFrame;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.PDBEntry;
+import jalview.datamodel.SearchResults;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.gui.Desktop;
+import jalview.io.AppletFormatAdapter;
+import jalview.util.MappingUtils;
+import jalview.util.MessageManager;
+
 import java.io.PrintStream;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -37,22 +56,6 @@ import MCview.Atom;
 import MCview.PDBChain;
 import MCview.PDBfile;
 
-import jalview.analysis.AlignSeq;
-import jalview.api.StructureSelectionManagerProvider;
-import jalview.commands.CommandI;
-import jalview.commands.EditCommand;
-import jalview.commands.OrderCommand;
-import jalview.datamodel.AlignedCodonFrame;
-import jalview.datamodel.AlignmentAnnotation;
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.Annotation;
-import jalview.datamodel.PDBEntry;
-import jalview.datamodel.SearchResults;
-import jalview.datamodel.SequenceI;
-import jalview.io.AppletFormatAdapter;
-import jalview.util.MappingUtils;
-import jalview.util.MessageManager;
-
 public class StructureSelectionManager
 {
   public final static String NEWLINE = System.lineSeparator();
@@ -72,12 +75,6 @@ public class StructureSelectionManager
    */
   Set<AlignedCodonFrame> seqmappings = new LinkedHashSet<AlignedCodonFrame>();
 
-  /*
-   * Reference counters for the above mappings. Remove mappings when ref count
-   * goes to zero.
-   */
-  Map<AlignedCodonFrame, Integer> seqMappingRefCounts = new HashMap<AlignedCodonFrame, Integer>();
-
   private List<CommandListener> commandListeners = new ArrayList<CommandListener>();
 
   private List<SelectionListener> sel_listeners = new ArrayList<SelectionListener>();
@@ -518,8 +515,12 @@ public class StructureSelectionManager
         if (resNum != tmp.resNumber && tmp.alignmentMapping != -1)
         {
           resNum = tmp.resNumber;
-          mapping[tmp.alignmentMapping + 1][0] = tmp.resNumber;
-          mapping[tmp.alignmentMapping + 1][1] = tmp.atomIndex;
+          if (tmp.alignmentMapping >= -1)
+          {
+            // TODO (JAL-1836) address root cause: negative residue no in PDB file
+            mapping[tmp.alignmentMapping + 1][0] = tmp.resNumber;
+            mapping[tmp.alignmentMapping + 1][1] = tmp.atomIndex;
+          }
         }
 
         index++;
@@ -721,13 +722,16 @@ public class StructureSelectionManager
               {
                 results = MappingUtils.buildSearchResults(seq, index,
                         seqmappings);
-              }
+               }
               if (handlingVamsasMo)
               {
                 results.addResult(seq, index, index);
 
               }
-              seqListener.highlightSequence(results);
+              if (!results.isEmpty())
+              {
+                seqListener.highlightSequence(results);
+              }
             }
           }
         }
@@ -908,83 +912,137 @@ public class StructureSelectionManager
   }
 
   /**
-   * Decrement the reference counter for each of the given mappings, and remove
-   * it entirely if its reference counter reduces to zero.
+   * Deregister each mapping in the set, unless there is still an alignment that
+   * holds a reference to it. Note we do not update the set itself, as it may be
+   * shared with an alignment view which is still open.
    * 
    * @param set
    */
-  public void removeMappings(Set<AlignedCodonFrame> set)
+  public void deregisterMappings(Set<AlignedCodonFrame> set)
   {
     if (set != null)
     {
       for (AlignedCodonFrame acf : set)
       {
-        removeMapping(acf);
+        deregisterMapping(acf);
       }
     }
   }
 
   /**
-   * Decrement the reference counter for the given mapping, and remove it
-   * entirely if its reference counter reduces to zero.
+   * Remove the given mapping provided no alignment holds a reference to it
    * 
    * @param acf
    */
-  public void removeMapping(AlignedCodonFrame acf)
+  public void deregisterMapping(AlignedCodonFrame acf)
   {
-    if (acf != null && seqmappings.contains(acf))
+    if (noReferencesTo(acf))
     {
-      int count = seqMappingRefCounts.get(acf);
-      count--;
-      if (count > 0)
-      {
-        seqMappingRefCounts.put(acf, count);
+      boolean removed = seqmappings.remove(acf);
+      if (removed && seqmappings.isEmpty())
+      { // debug
+        System.out.println("All mappings removed");
       }
-      else
+    }
+  }
+
+  /**
+   * Answers true if no alignment holds a reference to the given mapping
+   * 
+   * @param acf
+   * @return
+   */
+  protected boolean noReferencesTo(AlignedCodonFrame acf)
+  {
+    AlignFrame[] frames = Desktop.getAlignFrames();
+    if (frames == null)
+    {
+      return true;
+    }
+    for (AlignFrame af : frames)
+    {
+      for (AlignmentViewPanel ap : af.getAlignPanels())
       {
-        seqmappings.remove(acf);
-        seqMappingRefCounts.remove(acf);
+        AlignmentI al = ap.getAlignment();
+        if (al != null && al.getCodonFrames().contains(acf))
+        {
+          return false;
+        }
       }
     }
+    return true;
   }
 
   /**
-   * Add each of the given codonFrames to the stored set. If not aready present,
-   * increments its reference count instead.
+   * Add each of the given codonFrames to the stored set, if not aready present.
    * 
    * @param set
    */
-  public void addMappings(Set<AlignedCodonFrame> set)
+  public void registerMappings(Set<AlignedCodonFrame> set)
   {
     if (set != null)
     {
       for (AlignedCodonFrame acf : set)
       {
-        addMapping(acf);
+        registerMapping(acf);
       }
     }
   }
 
   /**
-   * Add the given mapping to the stored set, or if already stored, increment
-   * its reference counter.
+   * Add the given mapping to the stored set, unless already stored.
    */
-  public void addMapping(AlignedCodonFrame acf)
+  public void registerMapping(AlignedCodonFrame acf)
   {
     if (acf != null)
     {
-      if (seqmappings.contains(acf))
-      {
-        seqMappingRefCounts.put(acf, seqMappingRefCounts.get(acf) + 1);
-      }
-      else
+      if (!seqmappings.contains(acf))
       {
         seqmappings.add(acf);
-        seqMappingRefCounts.put(acf, 1);
       }
     }
   }
 
+  /**
+   * Resets this object to its initial state by removing all registered
+   * listeners, codon mappings, PDB file mappings
+   */
+  public void resetAll()
+  {
+    if (mappings != null)
+    {
+      mappings.clear();
+    }
+    if (seqmappings != null)
+    {
+      seqmappings.clear();
+    }
+    if (sel_listeners != null)
+    {
+      sel_listeners.clear();
+    }
+    if (listeners != null)
+    {
+      listeners.clear();
+    }
+    if (commandListeners != null)
+    {
+      commandListeners.clear();
+    }
+    if (view_listeners != null)
+    {
+      view_listeners.clear();
+    }
+    if (pdbFileNameId != null)
+    {
+      pdbFileNameId.clear();
+    }
+    if (pdbIdFileName != null)
+    {
+      pdbIdFileName.clear();
+    }
+  }
+
   public void addSelectionListener(SelectionListener selecter)
   {
     if (!sel_listeners.contains(selecter))