JAL-2029 many-to-many EnsemblCDS-to-Uniprot mappings
[jalview.git] / src / jalview / datamodel / xdb / embl / EmblFeatureLocations.java
index eb0bee7..9774004 100644 (file)
  */
 package jalview.datamodel.xdb.embl;
 
+import jalview.bin.Cache;
+import jalview.util.ArrayUtils;
+
+import java.util.Arrays;
 import java.util.Vector;
 
 /**
- * Data model for a <loctaion> child element of a <feature> read
+ * Data model for a <location> child element of a <feature> read
  * from an EMBL query reply
  * 
  * @see embl_mapping.xml
+ * @see http://www.insdc.org/files/feature_table.html#3.4.2
  */
 public class EmblFeatureLocations
 {
@@ -101,21 +106,21 @@ public class EmblFeatureLocations
   }
 
   /**
-   * Return all location elements concerning given accession as start-end pairs
-   * TODO: pass back complement and 'less than or more than' range information
-   * TODO: deal with multiple accessions
+   * Return all location elements concerning given accession as start-end pairs.
+   * If the CDS feature is on the forward strand, then start <= end, if on the
+   * reverse strand then start > end.
    * 
    * @param accession
    *          the accession string for which locations are requested, or null
    *          for all locations
-   * @return null or int[] { start1, end1, ... }
+   * @return int[] { start1, end1, ... }
    */
-
-  public int[] getElementRanges(String accession)
+  int[] getElementRanges(String accession)
   {
     int sepos = 0;
     int[] se = new int[locElements.size() * 2];
-    if (locationType.equalsIgnoreCase("single")) // TODO: or "simple" ?
+    if ("single".equalsIgnoreCase(locationType)
+            || "join".equalsIgnoreCase(locationType))
     {
       for (EmblFeatureLocElement loce : locElements)
       {
@@ -125,50 +130,61 @@ public class EmblFeatureLocations
           BasePosition bp[] = loce.getBasePositions();
           if (bp.length == 2)
           {
-            se[sepos++] = Integer.parseInt(bp[0].getPos());
-            se[sepos++] = Integer.parseInt(bp[1].getPos());
+            try
+            {
+              int start = Integer.parseInt(bp[0].getPos());
+              int end = Integer.parseInt(bp[1].getPos());
+              se[sepos++] = start;
+              se[sepos++] = end;
+            } catch (NumberFormatException e)
+            {
+              System.err
+                      .println("format error in EMBL CDS location basePosition: "
+                              + e.getMessage());
+            }
           }
-        }
-      }
-    }
-    else if (locationType.equalsIgnoreCase("join"))
-    {
-      for (EmblFeatureLocElement loce : locElements)
-      {
-        if (accession == null || loce.accession != null
-                && accession.equals(loce.accession))
-        {
-          BasePosition bp[] = loce.getBasePositions();
-          if (bp.length == 2)
+          else
           {
-            se[sepos++] = Integer.parseInt(bp[0].getPos());
-            se[sepos++] = Integer.parseInt(bp[1].getPos());
+            System.err
+                    .println("format error in EMBL CDS location, basePosition count = "
+                            + bp.length);
           }
         }
       }
-      return se;
     }
     else if (locationType != null)
     {
-      if (jalview.bin.Cache.log != null)
+      if (Cache.log != null)
       {
-        jalview.bin.Cache.log
-                .error("EmbleFeatureLocations.getElementRanges cannot deal with locationType=='"
+        Cache.log
+                .error("EmblFeatureLocations.getElementRanges cannot deal with locationType=='"
                         + locationType + "'");
       }
       else
       {
         System.err
-                .println("EmbleFeatureLocations.getElementRanges cannot deal with locationType=='"
+                .println("EmblFeatureLocations.getElementRanges cannot deal with locationType=='"
                         + locationType + "'");
       }
     }
-    // trim range if necessary.
-    if (se != null && sepos != se.length)
+
+    if (sepos != se.length)
+    {
+      /*
+       * we failed to parse something - trim off null values
+       */
+      se = Arrays.copyOf(se, sepos);
+    }
+
+    /*
+     * If on the complement, reverse the ranges to [end, start, ...end1, start1].
+     * For an example of a joined complement, see (tRNA feature) CAGL0B00165r on
+     * http://www.ebi.ac.uk/ena/data/view/CR380948&display=xml
+     * http://www.ebi.ac.uk/Tools/dbfetch/dbfetch/embl/CR380948/emblxml
+     */
+    if (locationComplement)
     {
-      int[] trimmed = new int[sepos];
-      System.arraycopy(se, 0, trimmed, 0, sepos);
-      se = trimmed;
+      ArrayUtils.reverseIntArray(se);
     }
     return se;
   }