refactored to propery separate addToDocument,addFromDocument, updateToDocument, updat...
[jalview.git] / src / jalview / io / vamsas / Sequencefeature.java
1 /**\r
2  * \r
3  */\r
4 package jalview.io.vamsas;\r
5 \r
6 import java.util.Enumeration;\r
7 import java.util.Vector;\r
8 \r
9 import uk.ac.vamsas.objects.core.DataSet;\r
10 import uk.ac.vamsas.objects.core.DataSetAnnotations;\r
11 import uk.ac.vamsas.objects.core.Link;\r
12 import uk.ac.vamsas.objects.core.Property;\r
13 import uk.ac.vamsas.objects.core.Provenance;\r
14 import uk.ac.vamsas.objects.core.RangeAnnotation;\r
15 import uk.ac.vamsas.objects.core.Score;\r
16 import uk.ac.vamsas.objects.core.Seg;\r
17 import uk.ac.vamsas.objects.core.Sequence;\r
18 import uk.ac.vamsas.objects.utils.Properties;\r
19 import jalview.bin.Cache;\r
20 import jalview.datamodel.SequenceFeature;\r
21 import jalview.datamodel.SequenceI;\r
22 import jalview.io.VamsasAppDatastore;\r
23 import jalview.util.UrlLink;\r
24 \r
25 /**\r
26  * @author JimP\r
27  * \r
28  */\r
29 public class Sequencefeature extends Rangetype\r
30 {\r
31 \r
32   uk.ac.vamsas.objects.core.DataSet dataset;\r
33 \r
34   uk.ac.vamsas.objects.core.Sequence sequence;\r
35 \r
36   private SequenceI dsSeq;\r
37 \r
38   public Sequencefeature(VamsasAppDatastore vamsasAppDatastore,\r
39           SequenceFeature sequenceFeature,\r
40           uk.ac.vamsas.objects.core.DataSet dataset,\r
41           uk.ac.vamsas.objects.core.Sequence sequence)\r
42   {\r
43     super(vamsasAppDatastore, sequenceFeature, DataSetAnnotations.class);\r
44     this.dataset = dataset;\r
45     this.sequence = sequence;\r
46     doSync();\r
47   }\r
48 \r
49   public Sequencefeature(VamsasAppDatastore vamsasAppDatastore,\r
50           DataSetAnnotations dseta, SequenceI dsSeq)\r
51   {\r
52     super(vamsasAppDatastore, dseta, jalview.datamodel.SequenceFeature.class);\r
53     this.dsSeq = dsSeq;\r
54     doJvUpdate();\r
55   }\r
56 \r
57   public void addToDocument()\r
58   {\r
59     DataSetAnnotations dsa = (DataSetAnnotations) vobj;\r
60     jalview.datamodel.SequenceFeature feature = (jalview.datamodel.SequenceFeature) jvobj;\r
61     dsa = (DataSetAnnotations) getDSAnnotationFromJalview(\r
62             new DataSetAnnotations(), feature);\r
63     if (dsa.getProvenance() == null)\r
64     {\r
65       dsa.setProvenance(new Provenance());\r
66     }\r
67     addProvenance(dsa.getProvenance(), "created"); // JBPNote - need\r
68     // to update\r
69     dsa.addSeqRef(sequence); // we have just created this annotation\r
70     // - so safe to use this\r
71     bindjvvobj(feature, dsa);\r
72     dataset.addDataSetAnnotations(dsa);\r
73   }\r
74 \r
75   public void addFromDocument()\r
76   {\r
77     DataSetAnnotations dsa = (DataSetAnnotations) vobj;\r
78     if (dsa.getSeqRefCount()!=1)\r
79     {\r
80       Cache.log.warn("Not binding "+dsa.getVorbaId()+" to Sequence Feature - has multiple dataset sequence references.");\r
81       return;\r
82     }\r
83     jalview.datamodel.SequenceFeature sf = (jalview.datamodel.SequenceFeature) jvobj;\r
84     dsSeq.addSequenceFeature(sf = getJalviewSeqFeature(dsa));\r
85     jvobj = sf;\r
86     bindjvvobj(sf, dsa);\r
87   }\r
88 \r
89   public void conflict()\r
90   {\r
91     log.warn("Untested sequencefeature conflict code");\r
92     DataSetAnnotations dsa = (DataSetAnnotations) vobj;\r
93     jalview.datamodel.SequenceFeature feature = (jalview.datamodel.SequenceFeature) jvobj;\r
94     jalview.datamodel.SequenceFeature sf = getJalviewSeqFeature(dsa);\r
95     replaceJvObjMapping(feature, sf); // switch binding of dsa from old feature to newly created feature\r
96     dsSeq.addSequenceFeature(sf); // add new imported feature\r
97     addToDocument(); // and create a new feature in the document        \r
98   }\r
99 \r
100   public void updateToDoc()\r
101   {\r
102     DataSetAnnotations dsa = (DataSetAnnotations) vobj;\r
103     jalview.datamodel.SequenceFeature feature = (jalview.datamodel.SequenceFeature) jvobj;\r
104     if (dsa.getSeqRefCount() != 1)\r
105     {\r
106       replaceJvObjMapping(feature, null);\r
107       Cache.log\r
108               .warn("Binding of annotation to jalview feature has changed. Removing binding and recreating.");\r
109       doSync(); // re-verify bindings.\r
110     }\r
111     else\r
112     {\r
113       // Sync the features from Jalview\r
114       long oldref = dsa.get__last_hash();\r
115       getDSAnnotationFromJalview(dsa, feature);\r
116       if (oldref != dsa.hashCode())\r
117       {\r
118         Cache.log\r
119                 .debug("Updated dataset sequence annotation from feature.");\r
120         addProvenance(dsa.getProvenance(), "modified");\r
121       }\r
122     }\r
123 \r
124   }\r
125   public void updateFromDoc()\r
126   {\r
127     DataSetAnnotations dsa = (DataSetAnnotations) vobj;\r
128     jalview.datamodel.SequenceFeature feature = (jalview.datamodel.SequenceFeature) jvobj;\r
129     if (dsa.getSeqRefCount() != 1)\r
130     {\r
131       // conflicting update from document - we cannot map this feature anymore.\r
132       replaceJvObjMapping(feature, null);\r
133       Cache.log\r
134               .warn("annotation ("+dsa.getVorbaId()+" bound to jalview feature cannot be mapped. Removing binding, deleting feature, and deleting feature.");\r
135        // - consider deleting the feature ?\r
136       dsSeq.deleteFeature(feature);\r
137       // doSync();\r
138     }\r
139     else\r
140     {\r
141       // Sync the features to Jalview - easiest to delete and add the feature again\r
142       jalview.datamodel.SequenceFeature newsf = getJalviewSeqFeature(dsa);\r
143       dsSeq.deleteFeature(feature);\r
144       replaceJvObjMapping(feature, newsf);\r
145       dsSeq.addSequenceFeature(newsf);\r
146       feature.otherDetails.clear();\r
147     }\r
148   }\r
149 \r
150   /**\r
151    * correctly create/update a RangeAnnotation from a jalview sequence feature\r
152    * TODO: refactor to a method in jalview.io.vamsas.RangeAnnotation class\r
153    * \r
154    * @param dsa\r
155    *                (typically DataSetAnnotations or\r
156    *                AlignmentSequenceAnnotation)\r
157    * @param feature\r
158    *                (the feature to be mapped from)\r
159    * @return\r
160    */\r
161   private RangeAnnotation getDSAnnotationFromJalview(RangeAnnotation dsa,\r
162           jalview.datamodel.SequenceFeature feature)\r
163   {\r
164     dsa.setType(feature.getType());\r
165     Seg vSeg = new Seg();\r
166     vSeg.setStart(feature.getBegin());\r
167     vSeg.setEnd(feature.getEnd());\r
168     vSeg.setInclusive(true);\r
169     if (dsa.getSegCount() > 1)\r
170     {\r
171       Cache.log\r
172               .debug("About to destroy complex annotation in vamsas document mapped to sequence feature ("\r
173                       + dsa.getVorbaId() + ")");\r
174     }\r
175     dsa.setSeg(new Seg[]\r
176     { vSeg });\r
177     dsa.setDescription(feature.getDescription());\r
178     dsa.setStatus(feature.getStatus());\r
179     if (feature.links != null && feature.links.size() > 0)\r
180     {\r
181       for (int i = 0, iSize = feature.links.size(); i < iSize; i++)\r
182       {\r
183         String link = (String) feature.links.elementAt(i);\r
184         UrlLink ulink = new UrlLink(link);\r
185         /*\r
186          * int sep = link.indexOf('|'); if (sep > -1) { Link vLink = new Link();\r
187          * if (sep > 0) { vLink.setContent(link.substring(0, sep - 1)); } else {\r
188          * vLink.setContent(""); } vLink.setHref(link.substring(sep + 1)); //\r
189          * TODO: validate href. dsa.addLink(vLink); }\r
190          */\r
191         Link vLink = new Link();\r
192         vLink.setContent(ulink.getLabel());\r
193         vLink.setHref(ulink.getUrl_prefix());\r
194       }\r
195     }\r
196     dsa.setGroup(feature.getFeatureGroup());\r
197     if (feature.getScore() != Float.NaN)\r
198     {\r
199       Score fscore = new Score();\r
200       dsa.setScore(new Score[]\r
201       { fscore });\r
202       fscore.setContent(feature.getScore());\r
203       fscore.setName(feature.getType());\r
204     }\r
205     if (feature.otherDetails != null)\r
206     {\r
207       Enumeration iter = feature.otherDetails.keys();\r
208       Vector props = dsa.getPropertyAsReference();\r
209       while (iter.hasMoreElements())\r
210       {\r
211         String key = (String) iter.nextElement();\r
212         if (!key.equalsIgnoreCase("score")\r
213                 && !key.equalsIgnoreCase("status"))\r
214         {\r
215           Property nprop = new Property();\r
216           nprop.setName(key);\r
217           Object vlu = feature.getValue(key);\r
218           nprop.setContent(feature.getValue(key).toString());\r
219           boolean valid = false;\r
220           if (vlu instanceof String)\r
221           {\r
222             nprop.setType(uk.ac.vamsas.objects.utils.Properties.STRINGTYPE);\r
223             valid = true;\r
224           }\r
225           else if (vlu instanceof Integer)\r
226           {\r
227             valid = true;\r
228             nprop\r
229                     .setType(uk.ac.vamsas.objects.utils.Properties.INTEGERTYPE);\r
230           }\r
231           else if (vlu instanceof Float)\r
232           {\r
233             nprop.setType(uk.ac.vamsas.objects.utils.Properties.FLOATTYPE);\r
234             valid = true;\r
235           }\r
236           if (valid)\r
237           {\r
238             if (props != null)\r
239             {\r
240               uk.ac.vamsas.objects.utils.Properties.addOrReplace(props,\r
241                       nprop);\r
242             }\r
243             else\r
244             {\r
245               dsa.addProperty(nprop);\r
246             }\r
247           }\r
248         }\r
249       }\r
250     }\r
251     return dsa;\r
252   }\r
253   private SequenceFeature getJalviewSeqFeature(RangeAnnotation dseta)\r
254   {\r
255     int[] se = getBounds(dseta);\r
256     SequenceFeature sf = new jalview.datamodel.SequenceFeature(dseta\r
257             .getType(), dseta.getDescription(), dseta.getStatus(), se[0],\r
258             se[1], dseta.getGroup());\r
259     if (dseta.getLinkCount() > 0)\r
260     {\r
261       Link[] links = dseta.getLink();\r
262       for (int i = 0; i < links.length; i++)\r
263       {\r
264         sf.addLink(links[i].getContent() + "|" + links[i].getHref());\r
265       }\r
266     }\r
267     if (dseta.getScoreCount()>0)\r
268     {\r
269       Enumeration scr = dseta.enumerateScore();\r
270       while (scr.hasMoreElements())\r
271       {\r
272         Score score = (Score) scr.nextElement();\r
273         if (score.getName().equals(sf.getType()))\r
274         {\r
275           sf.setScore(score.getContent());\r
276         } else {\r
277           sf.setValue(score.getName(), ""+score.getContent());\r
278         }\r
279       }\r
280     }\r
281     // other details\r
282     Enumeration props = dseta.enumerateProperty();\r
283     while (props.hasMoreElements())\r
284     {\r
285       Property p = (Property) props.nextElement();\r
286       Object val = null;\r
287       if (Properties.isValid(p)) \r
288       {\r
289         if (Properties.isString(p))\r
290         {\r
291         val = p.getContent();\r
292         }\r
293         if (Properties.isBoolean(p))\r
294         {\r
295           try {\r
296             val = new Boolean(p.getContent());\r
297           } catch (Exception e) {}\r
298         }\r
299         if (Properties.isFloat(p))\r
300         {\r
301           try {\r
302               val = new Float(p.getContent());\r
303               \r
304             } catch (Exception e)\r
305             {\r
306             }\r
307           }\r
308         if(Properties.isInteger(p))\r
309         {\r
310           try {\r
311                 val = new Integer(p.getContent());\r
312           } catch (Exception e)\r
313           {\r
314               } \r
315         }\r
316         if (val!=null)\r
317         {\r
318           sf.setValue(p.getName(), val);\r
319         }\r
320       }\r
321     }\r
322 \r
323     return sf;\r
324   }\r
325 \r
326 }\r