JAL-2154 systematic pattern for defining/resolving forward references to sequences
authorJim Procter <jprocter@issues.jalview.org>
Sun, 24 Jul 2016 12:58:45 +0000 (13:58 +0100)
committerJim Procter <jprocter@issues.jalview.org>
Sun, 24 Jul 2016 12:58:45 +0000 (13:58 +0100)
src/jalview/gui/Jalview2XML.java

index 1a82a68..c0e1ebe 100644 (file)
@@ -165,7 +165,7 @@ public class Jalview2XML
    */
   Map<String, SequenceI> seqRefIds = null;
 
-  Vector<Object[]> frefedSequence = null;
+  List<SeqFref> frefedSequence = null;
 
   boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
 
@@ -242,6 +242,10 @@ public class Jalview2XML
     {
       seqRefIds = new HashMap<String, SequenceI>();
     }
+    if (frefedSequence == null)
+    {
+      frefedSequence = new ArrayList<SeqFref>();
+    }
   }
 
   public Jalview2XML()
@@ -253,78 +257,141 @@ public class Jalview2XML
     this.raiseGUI = raiseGUI;
   }
 
-  public void resolveFrefedSequences()
+  /**
+   * base class for resolving forward references to sequences by their ID
+   * 
+   * @author jprocter
+   *
+   */
+  abstract class SeqFref
   {
-    if (frefedSequence.size() > 0)
+    String sref;
+
+    public SeqFref(String _sref)
+    {
+      sref = _sref;
+    }
+
+    public String getSref()
+    {
+      return sref;
+    }
+
+    public SequenceI getSrefSeq()
+    {
+      return seqRefIds.get(sref);
+    }
+
+    public boolean isResolvable()
+    {
+      return seqRefIds.get(sref) != null;
+    }
+
+    public SequenceI getSrefDatasetSeq()
     {
-      int r = 0, rSize = frefedSequence.size();
-      while (r < rSize)
+      SequenceI sq = seqRefIds.get(sref);
+      if (sq != null)
       {
-        Object[] ref = frefedSequence.elementAt(r);
-        if (ref != null)
+        while (sq.getDatasetSequence() != null)
         {
-          String sref = (String) ref[0];
-          if (seqRefIds.containsKey(sref))
-          {
-            if (ref[1] instanceof jalview.datamodel.Mapping)
-            {
-              SequenceI seq = seqRefIds.get(sref);
-              while (seq.getDatasetSequence() != null)
-              {
-                seq = seq.getDatasetSequence();
-              }
-              ((jalview.datamodel.Mapping) ref[1]).setTo(seq);
-            }
-            else
-            {
-              if (ref[1] instanceof jalview.datamodel.AlignedCodonFrame)
-              {
-                SequenceI seq = seqRefIds.get(sref);
-                while (seq.getDatasetSequence() != null)
-                {
-                  seq = seq.getDatasetSequence();
-                }
-                if (ref[2] != null
-                        && ref[2] instanceof jalview.datamodel.Mapping)
-                {
-                  jalview.datamodel.Mapping mp = (jalview.datamodel.Mapping) ref[2];
-                  ((jalview.datamodel.AlignedCodonFrame) ref[1]).addMap(
-                          seq, mp.getTo(), mp.getMap());
-                }
-                else
-                {
-                  System.err
-                          .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for AlcodonFrames involving "
-                                  + ref[2].getClass() + " type objects.");
-                }
-              }
-              else
-              {
-                System.err
-                        .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for "
-                                + ref[1].getClass() + " type objects.");
-              }
-            }
-            frefedSequence.remove(r);
-            rSize--;
-          }
-          else
-          {
-            System.err
-                    .println("IMPLEMENTATION WARNING: Unresolved forward reference for hash string "
-                            + ref[0]
-                            + " with objecttype "
-                            + ref[1].getClass());
-            r++;
-          }
+          sq = sq.getDatasetSequence();
         }
-        else
+      }
+      return sq;
+    }
+    /**
+     * @return true if the forward reference was fully resolved
+     */
+    abstract boolean resolve();
+  }
+
+  /**
+   * create forward reference for a mapping
+   * 
+   * @param sref
+   * @param _jmap
+   * @return
+   */
+  public SeqFref newMappingRef(final String sref,
+          final jalview.datamodel.Mapping _jmap)
+  {
+    SeqFref fref = new SeqFref(sref)
+    {
+      public jalview.datamodel.Mapping jmap = _jmap;
+
+      @Override
+      boolean resolve()
+      {
+        SequenceI seq = getSrefDatasetSeq();
+        if (seq == null)
         {
-          // empty reference
-          frefedSequence.remove(r);
-          rSize--;
+          return false;
         }
+        jmap.setTo(seq);
+        return true;
       }
+    };
+    return fref;
+  }
+
+  public SeqFref newAlcodMapRef(final String sref,
+          final AlignedCodonFrame _cf, final jalview.datamodel.Mapping _jmap)
+  {
+
+    SeqFref fref = new SeqFref(sref)
+    {
+      AlignedCodonFrame cf = _cf;
+
+      public jalview.datamodel.Mapping mp = _jmap;
+
+      @Override
+      boolean resolve()
+      {
+        SequenceI seq = getSrefDatasetSeq();
+        if (seq == null)
+        {
+          return false;
+        }
+        cf.addMap(seq, mp.getTo(), mp.getMap());
+        return true;
+      }
+    };
+    return fref;
+  }
+
+  public void resolveFrefedSequences()
+  {
+    Iterator<SeqFref> nextFref=frefedSequence.iterator();
+    int toresolve=frefedSequence.size();
+    int unresolved=0,failedtoresolve=0;
+    while (nextFref.hasNext()) {
+      SeqFref ref = nextFref.next();
+      if (ref.isResolvable())
+      {
+        try {
+          if (ref.resolve())
+          {
+            nextFref.remove();
+          } else {
+            failedtoresolve++;
+          }
+        } catch (Exception x) {
+          System.err.println("IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "+ref.getSref());
+          x.printStackTrace();
+          failedtoresolve++;
+        } 
+      } else {
+        unresolved++;
+      }
+    }
+    if (unresolved>0)
+    {
+      System.err.println("There were "+unresolved+" forward references left unresolved on the stack.");
+    }
+    if (failedtoresolve>0)
+    {
+      System.err.println("SERIOUS! " + failedtoresolve
+              + " resolvable forward references failed to resolve.");
     }
   }
 
@@ -2241,13 +2308,8 @@ public class Jalview2XML
     }
     if (seqRefIds == null)
     {
-      seqRefIds = new HashMap<String, SequenceI>();
-    }
-    if (frefedSequence == null)
-    {
-      frefedSequence = new Vector<Object[]>();
+      initSeqRefs();
     }
-
     AlignFrame af = null, _af = null;
     Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
     final String file = jprovider.getFilename();
@@ -2859,8 +2921,8 @@ public class Jalview2XML
             else
             {
               // defer to later
-              frefedSequence.add(new Object[] { maps[m].getDnasq(), cf,
-                  mapping });
+              frefedSequence.add(newAlcodMapRef(maps[m].getDnasq(), cf,
+                      mapping));
             }
           }
           al.addCodonFrame(cf);
@@ -5003,7 +5065,7 @@ public class Jalview2XML
         }
         else
         {
-          frefedSequence.add(new Object[] { dsfor, jmap });
+          frefedSequence.add(newMappingRef(dsfor, jmap));
         }
       }
       else