JAL-2029 many-to-many EnsemblCDS-to-Uniprot mappings
[jalview.git] / src / jalview / datamodel / xdb / embl / EmblFeatureLocations.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.datamodel.xdb.embl;
22
23 import jalview.bin.Cache;
24 import jalview.util.ArrayUtils;
25
26 import java.util.Arrays;
27 import java.util.Vector;
28
29 /**
30  * Data model for a &lt;location&gt; child element of a &lt;feature&gt; read
31  * from an EMBL query reply
32  * 
33  * @see embl_mapping.xml
34  * @see http://www.insdc.org/files/feature_table.html#3.4.2
35  */
36 public class EmblFeatureLocations
37 {
38   Vector<EmblFeatureLocElement> locElements;
39
40   String locationType;
41
42   boolean locationComplement;
43
44   /**
45    * @return the locationComplement
46    */
47   public boolean isLocationComplement()
48   {
49     return locationComplement;
50   }
51
52   /**
53    * @param locationComplement
54    *          the locationComplement to set
55    */
56   public void setLocationComplement(boolean locationComplement)
57   {
58     this.locationComplement = locationComplement;
59   }
60
61   /**
62    * @return the locationType
63    */
64   public String getLocationType()
65   {
66     return locationType;
67   }
68
69   /**
70    * @param locationType
71    *          the locationType to set
72    */
73   public void setLocationType(String locationType)
74   {
75     this.locationType = locationType;
76   }
77
78   /**
79    * @return the locElements
80    */
81   public Vector<EmblFeatureLocElement> getLocElements()
82   {
83     return locElements;
84   }
85
86   /**
87    * @param locElements
88    *          the locElements to set
89    */
90   public void setLocElements(Vector<EmblFeatureLocElement> locElements)
91   {
92     this.locElements = locElements;
93   }
94
95   /**
96    * Return all location elements as start-end pairs (without accessions) TODO:
97    * pass back complement and 'less than or more than' range information Note:
98    * do not use this since it throws away any accessionIds associated with each
99    * location!
100    * 
101    * @return int[] { start1, end1, ... }
102    */
103   public int[] getElementRanges()
104   {
105     return getElementRanges(null);
106   }
107
108   /**
109    * Return all location elements concerning given accession as start-end pairs.
110    * If the CDS feature is on the forward strand, then start <= end, if on the
111    * reverse strand then start > end.
112    * 
113    * @param accession
114    *          the accession string for which locations are requested, or null
115    *          for all locations
116    * @return int[] { start1, end1, ... }
117    */
118   int[] getElementRanges(String accession)
119   {
120     int sepos = 0;
121     int[] se = new int[locElements.size() * 2];
122     if ("single".equalsIgnoreCase(locationType)
123             || "join".equalsIgnoreCase(locationType))
124     {
125       for (EmblFeatureLocElement loce : locElements)
126       {
127         if (accession == null || loce.accession != null
128                 && accession.equals(loce.accession))
129         {
130           BasePosition bp[] = loce.getBasePositions();
131           if (bp.length == 2)
132           {
133             try
134             {
135               int start = Integer.parseInt(bp[0].getPos());
136               int end = Integer.parseInt(bp[1].getPos());
137               se[sepos++] = start;
138               se[sepos++] = end;
139             } catch (NumberFormatException e)
140             {
141               System.err
142                       .println("format error in EMBL CDS location basePosition: "
143                               + e.getMessage());
144             }
145           }
146           else
147           {
148             System.err
149                     .println("format error in EMBL CDS location, basePosition count = "
150                             + bp.length);
151           }
152         }
153       }
154     }
155     else if (locationType != null)
156     {
157       if (Cache.log != null)
158       {
159         Cache.log
160                 .error("EmblFeatureLocations.getElementRanges cannot deal with locationType=='"
161                         + locationType + "'");
162       }
163       else
164       {
165         System.err
166                 .println("EmblFeatureLocations.getElementRanges cannot deal with locationType=='"
167                         + locationType + "'");
168       }
169     }
170
171     if (sepos != se.length)
172     {
173       /*
174        * we failed to parse something - trim off null values
175        */
176       se = Arrays.copyOf(se, sepos);
177     }
178
179     /*
180      * If on the complement, reverse the ranges to [end, start, ...end1, start1].
181      * For an example of a joined complement, see (tRNA feature) CAGL0B00165r on
182      * http://www.ebi.ac.uk/ena/data/view/CR380948&display=xml
183      * http://www.ebi.ac.uk/Tools/dbfetch/dbfetch/embl/CR380948/emblxml
184      */
185     if (locationComplement)
186     {
187       ArrayUtils.reverseIntArray(se);
188     }
189     return se;
190   }
191 }