JAL-2106 DBRefEntry.isPrimary() minimal test & implementation
authorJim Procter <jprocter@issues.jalview.org>
Wed, 24 Aug 2016 14:43:43 +0000 (15:43 +0100)
committerJim Procter <jprocter@issues.jalview.org>
Wed, 24 Aug 2016 14:45:59 +0000 (15:45 +0100)
src/jalview/api/DBRefEntryI.java
src/jalview/datamodel/DBRefEntry.java
test/jalview/datamodel/DBRefEntryTest.java

index 32245b3..701acb6 100644 (file)
@@ -70,4 +70,28 @@ public interface DBRefEntryI
    * @return
    */
   public boolean updateFrom(DBRefEntryI otherEntry);
+
+  /**
+   * Method to distinguish between direct and indirect database references
+   * 
+   * primary references indicate the local sequence data directly corresponds
+   * with the database record. All other references are secondary. direct
+   * references indicate that part or all of the local sequence data can be
+   * mapped with another sequence, enabling annotation transfer.
+   * cross-references indicate the local sequence data can be corresponded to
+   * some other linear coordinate system via a transformation.
+   * 
+   * This method is also sufficient to distinguish direct DBRefEntry mappings
+   * from other relationships - e.g. coding relationships (imply a 1:3/3:1
+   * mapping), but not transcript relationships, which imply a (possibly
+   * non-contiguous) 1:1 mapping
+   * 
+   * The only way a dbref's mappings can be fully verified is via the local
+   * sequence frame, so rather than use isPrimary directly, please use
+   * SequenceI.getPrimaryDbRefs()
+   *
+   * @return true if this reference provides a primary accession for the
+   *         associated sequence object
+   */
+  public boolean isPrimary();
 }
index a641b1b..6a48da7 100755 (executable)
@@ -22,6 +22,8 @@ package jalview.datamodel;
 
 import jalview.api.DBRefEntryI;
 
+import java.util.Arrays;
+
 public class DBRefEntry implements DBRefEntryI
 {
   String source = "", version = "", accessionId = "";
@@ -279,5 +281,45 @@ public class DBRefEntry implements DBRefEntryI
   public String toString()
   {
     return getSrcAccString();
+
+  @Override
+  public boolean isPrimary()
+  {
+    /*
+     * if a map is present, unless it is 1:1 and has no SequenceI mate, it cannot be a primary reference.  
+     */
+    if (map != null)
+    {
+      if (map.getTo() != null)
+      {
+        return false;
+      }
+      if (map.getMap().getFromRatio() != map.getMap().getToRatio()
+              || map.getMap().getFromRatio() != 1)
+      {
+        return false;
+      }
+    }
+    if (version == null)
+    {
+      // no version string implies the reference has not been verified at all.
+      return false;
+    }
+    // tricky - this test really needs to search the sequence's set of dbrefs to
+    // see if there is a primary reference that derived this reference.
+    String ucv = version.toUpperCase();
+    for (String primsrc : Arrays.asList(DBRefSource.allSources()))
+    {
+      if (ucv.startsWith(primsrc.toUpperCase()))
+      {
+        // by convention, many secondary references inherit the primary
+        // reference's
+        // source string as a prefix for any version information from the
+        // secondary reference.
+        return false;
+      }
+    }
+    return true;
+  }
   }
 }
index ae6dcda..8cc31e0 100644 (file)
@@ -138,4 +138,41 @@ public class DBRefEntryTest
     assertFalse(ref1.updateFrom(ref2));
     assertEquals("10", ref1.getVersion());
   }
+
+  @Test(groups = { "Functional" })
+  public void testIsPrimary()
+  {
+    DBRefEntry dbr = new DBRefEntry(DBRefSource.UNIPROT, "", "Q12345");
+    assertTrue(dbr.isPrimary());
+    /*
+     *  1:1 mapping with shift
+     */
+    dbr.setMap(new Mapping(null, new int[] { 1, 3 }, new int[] { 5, 9 }, 1,
+            1));
+    assertTrue(dbr.isPrimary());
+
+    /*
+     *  1:1 mapping with shift and sequenceRef
+     */
+    dbr.setMap(new Mapping(new Sequence("foo", "ASDF"), new int[] { 1, 3 },
+            new int[] { 5, 9 }, 1, 1));
+    assertFalse(dbr.isPrimary());
+
+    /*
+     * 1:3 mapping with shift (fail)
+     */
+    dbr.setMap(new Mapping(null, new int[] { 1, 3 }, new int[] { 5, 9 }, 1,
+            3));
+    assertFalse(dbr.isPrimary());
+    /*
+     * 2:2 mapping with shift (expected fail, but maybe not realistic)
+     */
+    dbr.setMap(new Mapping(null, new int[] { 1, 3 }, new int[] { 5, 9 }, 2,
+            2));
+    assertFalse(dbr.isPrimary());
+
+    dbr.setVersion(DBRefSource.EMBL + ":0");
+    assertFalse(dbr.isPrimary());
+
+  }
 }