JAL-653 encapsulate Strand, Attributes, Status of SequenceFeature
[jalview.git] / src / jalview / datamodel / SequenceFeature.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;
22
23 import java.util.HashMap;
24 import java.util.Map;
25 import java.util.Vector;
26
27 /**
28  * DOCUMENT ME!
29  * 
30  * @author $author$
31  * @version $Revision$
32  */
33 public class SequenceFeature
34 {
35   private static final String STATUS = "status";
36
37   private static final String STRAND = "STRAND";
38
39   private static final String ATTRIBUTES = "ATTRIBUTES";
40
41   public int begin;
42
43   public int end;
44
45   public float score;
46
47   public String type;
48
49   public String description;
50
51   public Map<String, Object> otherDetails;
52
53   public Vector<String> links;
54
55   // Feature group can be set from a features file
56   // as a group of features between STARTGROUP and ENDGROUP markers
57   public String featureGroup;
58
59   public SequenceFeature()
60   {
61   }
62
63   /**
64    * Constructs a duplicate feature. Note: Uses makes a shallow copy of the
65    * otherDetails map, so the new and original SequenceFeature may reference the
66    * same objects in the map.
67    * 
68    * @param cpy
69    */
70   public SequenceFeature(SequenceFeature cpy)
71   {
72     if (cpy != null)
73     {
74       begin = cpy.begin;
75       end = cpy.end;
76       score = cpy.score;
77       if (cpy.type != null)
78       {
79         type = new String(cpy.type);
80       }
81       if (cpy.description != null)
82       {
83         description = new String(cpy.description);
84       }
85       if (cpy.featureGroup != null)
86       {
87         featureGroup = new String(cpy.featureGroup);
88       }
89       if (cpy.otherDetails != null)
90       {
91         try
92         {
93           otherDetails = (Map<String, Object>) ((HashMap<String, Object>) cpy.otherDetails)
94                   .clone();
95         } catch (Exception e)
96         {
97           // ignore
98         }
99       }
100       if (cpy.links != null && cpy.links.size() > 0)
101       {
102         links = new Vector<String>();
103         for (int i = 0, iSize = cpy.links.size(); i < iSize; i++)
104         {
105           links.addElement(cpy.links.elementAt(i));
106         }
107       }
108     }
109   }
110
111   public SequenceFeature(String type, String desc, String status,
112           int begin, int end, String featureGroup)
113   {
114     this.type = type;
115     this.description = desc;
116     setValue(STATUS, status);
117     this.begin = begin;
118     this.end = end;
119     this.featureGroup = featureGroup;
120   }
121
122   public SequenceFeature(String type, String desc, int begin, int end,
123           float score, String featureGroup)
124   {
125     this.type = type;
126     this.description = desc;
127     this.begin = begin;
128     this.end = end;
129     this.score = score;
130     this.featureGroup = featureGroup;
131   }
132
133   public boolean equals(SequenceFeature sf)
134   {
135     if (begin != sf.begin || end != sf.end || score != sf.score)
136     {
137       return false;
138     }
139
140     if (!(type + description + featureGroup).equals(sf.type
141             + sf.description + sf.featureGroup))
142     {
143       return false;
144     }
145
146     return true;
147   }
148
149   /**
150    * DOCUMENT ME!
151    * 
152    * @return DOCUMENT ME!
153    */
154   public int getBegin()
155   {
156     return begin;
157   }
158
159   public void setBegin(int start)
160   {
161     this.begin = start;
162   }
163
164   /**
165    * DOCUMENT ME!
166    * 
167    * @return DOCUMENT ME!
168    */
169   public int getEnd()
170   {
171     return end;
172   }
173
174   public void setEnd(int end)
175   {
176     this.end = end;
177   }
178
179   /**
180    * DOCUMENT ME!
181    * 
182    * @return DOCUMENT ME!
183    */
184   public String getType()
185   {
186     return type;
187   }
188
189   public void setType(String type)
190   {
191     this.type = type;
192   }
193
194   /**
195    * DOCUMENT ME!
196    * 
197    * @return DOCUMENT ME!
198    */
199   public String getDescription()
200   {
201     return description;
202   }
203
204   public void setDescription(String desc)
205   {
206     description = desc;
207   }
208
209   public String getFeatureGroup()
210   {
211     return featureGroup;
212   }
213
214   public void setFeatureGroup(String featureGroup)
215   {
216     this.featureGroup = featureGroup;
217   }
218
219   public void addLink(String labelLink)
220   {
221     if (links == null)
222     {
223       links = new Vector<String>();
224     }
225
226     links.insertElementAt(labelLink, 0);
227   }
228
229   public float getScore()
230   {
231     return score;
232   }
233
234   public void setScore(float value)
235   {
236     score = value;
237   }
238
239   /**
240    * Used for getting values which are not in the basic set. eg STRAND, FRAME
241    * for GFF file
242    * 
243    * @param key
244    *          String
245    */
246   public Object getValue(String key)
247   {
248     if (otherDetails == null)
249     {
250       return null;
251     }
252     else
253     {
254       return otherDetails.get(key);
255     }
256   }
257
258   /**
259    * Returns a property value for the given key if known, else the specified
260    * default value
261    * 
262    * @param key
263    * @param defaultValue
264    * @return
265    */
266   public Object getValue(String key, Object defaultValue)
267   {
268     Object value = getValue(key);
269     return value == null ? defaultValue : value;
270   }
271
272   /**
273    * Used for setting values which are not in the basic set. eg STRAND, FRAME
274    * for GFF file
275    * 
276    * @param key
277    *          eg STRAND
278    * @param value
279    *          eg +
280    */
281   public void setValue(String key, Object value)
282   {
283     if (value != null)
284     {
285       if (otherDetails == null)
286       {
287         otherDetails = new HashMap<String, Object>();
288       }
289
290       otherDetails.put(key, value);
291     }
292   }
293
294   /*
295    * The following methods are added to maintain the castor Uniprot mapping file
296    * for the moment.
297    */
298   public void setStatus(String status)
299   {
300     setValue(STATUS, status);
301   }
302
303   public String getStatus()
304   {
305     return (String) getValue(STATUS);
306   }
307
308   public void setAttributes(String attr)
309   {
310     setValue(ATTRIBUTES, attr);
311   }
312
313   public String getAttributes()
314   {
315     return (String) getValue(ATTRIBUTES);
316   }
317
318   public void setPosition(int pos)
319   {
320     begin = pos;
321     end = pos;
322   }
323
324   public int getPosition()
325   {
326     return begin;
327   }
328
329   /**
330    * Return 1 for forward strand ('+' in GFF), -1 for reverse strand ('-' in
331    * GFF), and 0 for unknown or not (validly) specified
332    * 
333    * @return
334    */
335   public int getStrand()
336   {
337     int strand = 0;
338     if (otherDetails != null)
339     {
340       Object str = otherDetails.get(STRAND);
341       if ("-".equals(str))
342       {
343         strand = -1;
344       }
345       else if ("+".equals(str))
346       {
347         strand = 1;
348       }
349     }
350     return strand;
351   }
352
353   public void setStrand(String strand)
354   {
355     setValue(STRAND, strand);
356   }
357
358 }