fix class-cast exception and added beginnings of DBRef inference mechanism
[jalview.git] / src / jalview / io / vamsas / Sequencemapping.java
1 package jalview.io.vamsas;\r
2 \r
3 import java.util.Vector;\r
4 \r
5 import jalview.datamodel.AlignedCodonFrame;\r
6 import jalview.datamodel.Mapping;\r
7 import jalview.datamodel.SequenceI;\r
8 import jalview.io.VamsasAppDatastore;\r
9 import uk.ac.vamsas.client.Vobject;\r
10 import uk.ac.vamsas.objects.core.AlignmentSequence;\r
11 import uk.ac.vamsas.objects.core.DataSet;\r
12 import uk.ac.vamsas.objects.core.Local;\r
13 import uk.ac.vamsas.objects.core.RangeType;\r
14 import uk.ac.vamsas.objects.core.Seg;\r
15 import uk.ac.vamsas.objects.core.Sequence;\r
16 import uk.ac.vamsas.objects.core.SequenceMapping;\r
17 import uk.ac.vamsas.objects.core.SequenceType;\r
18 \r
19 public class Sequencemapping extends Rangetype\r
20 {\r
21   public Sequencemapping(VamsasAppDatastore datastore, SequenceMapping sequenceMapping)\r
22   {\r
23     super(datastore);\r
24     Object mjvmapping = getvObj2jv(sequenceMapping);\r
25     if (mjvmapping==null)\r
26     {\r
27       add(sequenceMapping);\r
28     } else {\r
29       if (sequenceMapping.isUpdated())\r
30       {\r
31         update((jalview.util.MapList) mjvmapping, sequenceMapping);\r
32       }\r
33     }\r
34   }\r
35   /**\r
36    * create or update a vamsas sequence mapping corresponding to a jalview\r
37    * Mapping between two dataset sequences\r
38    * \r
39    * @param datastore\r
40    * @param mjvmapping\r
41    * @param from\r
42    * @param ds\r
43    */\r
44   public Sequencemapping(VamsasAppDatastore datastore, jalview.datamodel.Mapping mjvmapping, uk.ac.vamsas.objects.core.SequenceType from, uk.ac.vamsas.objects.core.DataSet ds)\r
45   {\r
46     super(datastore);\r
47     SequenceMapping sequenceMapping = (SequenceMapping) getjv2vObj(mjvmapping);\r
48     if (sequenceMapping==null)\r
49     {\r
50       add(mjvmapping, from, ds);\r
51     } else {\r
52       if (from!=null && sequenceMapping.getLoc()!=from)\r
53       {\r
54         jalview.bin.Cache.log.warn("Probable IMPLEMENTATION ERROR: "+from+" doesn't match the local mapping sequence.");\r
55       }\r
56       if (ds!=null && sequenceMapping.is__stored_in_document() && sequenceMapping.getV_parent()!=ds)\r
57       {\r
58         jalview.bin.Cache.log.warn("Probable IMPLEMENTATION ERROR: "+ds+" doesn't match the parent of the bound sequence mapping object.");\r
59       }\r
60       if (sequenceMapping.isUpdated())\r
61       { \r
62         conflict(mjvmapping, sequenceMapping);\r
63       } else {\r
64         update(mjvmapping, sequenceMapping);\r
65       }\r
66     }\r
67   }\r
68   private void conflict(Mapping mjvmapping, SequenceMapping sequenceMapping)\r
69   {\r
70     // TODO Auto-generated method stub\r
71 \r
72   }\r
73   private void add(Mapping mjvmapping, uk.ac.vamsas.objects.core.SequenceType from, DataSet ds)\r
74   {\r
75     SequenceI jvto = mjvmapping.getTo();\r
76     while (jvto.getDatasetSequence()!=null)\r
77     {\r
78       jvto = jvto.getDatasetSequence();\r
79     }\r
80     SequenceType to = (SequenceType) getjv2vObj(jvto);\r
81     if (to==null)\r
82     {\r
83       jalview.bin.Cache.log.warn("NONFATAL - do a second update: Ignoring Forward Reference to seuqence not yet bound to vamsas seuqence object");\r
84       return;\r
85     } \r
86     SequenceMapping sequenceMapping = new SequenceMapping();\r
87     sequenceMapping.setLoc(from);\r
88     sequenceMapping.setMap(to);\r
89     boolean dnaToProt=false,sense=false;\r
90     // ensure that we create a mapping with the correct sense\r
91     if (((Sequence) sequenceMapping.getLoc())\r
92             .getDictionary()\r
93             .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA))\r
94     {\r
95       if (((Sequence) sequenceMapping.getMap())\r
96               .getDictionary()\r
97               .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_AA))\r
98       {\r
99         dnaToProt=true;\r
100         sense=true;\r
101       } \r
102     } else {\r
103       if (((Sequence) sequenceMapping.getMap())\r
104               .getDictionary()\r
105               .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA))\r
106       {\r
107         dnaToProt=true;\r
108         sense=false;\r
109       } \r
110     }\r
111 \r
112     if (!dnaToProt)\r
113     {\r
114       jalview.bin.Cache.log.warn("Ignoring Mapping - don't support protein to protein mapping in vamsas document yet.");\r
115       return;\r
116     }\r
117     if (ds==null)\r
118     {\r
119       // locate dataset for storage of SequenceMapping\r
120       if (sense)\r
121       {\r
122         ds = (DataSet) ((uk.ac.vamsas.client.Vobject) sequenceMapping.getLoc()).getV_parent();\r
123       } else {\r
124         ds = (DataSet) ((uk.ac.vamsas.client.Vobject) sequenceMapping.getMap()).getV_parent();\r
125       } \r
126     }\r
127     if (sense)\r
128     {\r
129       this.initMapType(sequenceMapping, mjvmapping.getMap(), true);\r
130     } else {\r
131       this.initMapType(sequenceMapping, mjvmapping.getMap().getInverse(), true);\r
132     }\r
133     ds.addSequenceMapping(sequenceMapping);\r
134     sequenceMapping.setProvenance(this.dummyProvenance("user defined coding region translation")); // TODO:\r
135     // correctly\r
136     // construct\r
137     // provenance\r
138     // based\r
139     // on\r
140     // source\r
141     // of\r
142     // mapping\r
143     bindjvvobj(mjvmapping, sequenceMapping);\r
144 \r
145     jalview.bin.Cache.log.debug("Successfully created mapping "+sequenceMapping.getVorbaId());\r
146   }\r
147   private void update(jalview.util.MapList mjvmapping, SequenceMapping sequenceMapping)\r
148   {\r
149     jalview.bin.Cache.log.error("Not implemented: Jalview Update Alcodon Mapping:TODO!"); \r
150   }\r
151   private void update(jalview.datamodel.Mapping mjvmapping, SequenceMapping sequenceMapping)\r
152   {\r
153     jalview.bin.Cache.log.error("Not implemented: Jalview Update Sequence DBRef Mapping"); \r
154   }\r
155   /**\r
156    * limitations: Currently, jalview only deals with mappings between dataset\r
157    * sequences, and even then, only between those that map from DNA to Protein.\r
158    * \r
159    * @param sequenceMapping\r
160    */\r
161   private void add(SequenceMapping sequenceMapping)\r
162   {\r
163     Object mobj;\r
164     SequenceI from=null,to=null;\r
165     boolean dnaToProt=false,sense=false;\r
166     Sequence sdloc=null, sdmap=null;\r
167     if (sequenceMapping.getLoc() instanceof AlignmentSequence)\r
168     {\r
169       sdloc = (Sequence) ((AlignmentSequence) sequenceMapping.getLoc()).getRefid();\r
170     } else {\r
171       sdloc = ((Sequence) sequenceMapping.getLoc());\r
172     }\r
173     if (sequenceMapping.getMap() instanceof AlignmentSequence)\r
174     {\r
175       sdmap = (Sequence) ((AlignmentSequence) sequenceMapping.getMap()).getRefid();\r
176     } else {\r
177       sdmap = ((Sequence) sequenceMapping.getMap());\r
178     }\r
179     if (sdloc==null || sdmap == null)\r
180     {\r
181       jalview.bin.Cache.log.info("Ignoring non sequence-sequence mapping");\r
182       return;\r
183     }\r
184     mobj = this.getvObj2jv((Vobject) sdloc);\r
185     if (mobj instanceof SequenceI)\r
186     {\r
187       from = (SequenceI) mobj;\r
188     }\r
189     mobj = this.getvObj2jv((Vobject) sdmap);\r
190     if (mobj instanceof SequenceI)\r
191     {\r
192       to = (SequenceI) mobj;\r
193     }\r
194     if (from == null || to == null)\r
195     {\r
196 \r
197       jalview.bin.Cache.log.error("Probable Vamsas implementation error : unbound dataset sequences involved in a mapping are being parsed!");\r
198       return;\r
199     } \r
200 \r
201     if (sdloc.getDictionary()\r
202             .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA))\r
203     {\r
204       if (sdmap.getDictionary()\r
205               .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_AA))\r
206       {\r
207         dnaToProt=true;\r
208         sense=true;\r
209       } \r
210       // else {\r
211 \r
212       // }\r
213     } else {\r
214       if (sdmap.getDictionary()\r
215               .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA))\r
216       {\r
217         dnaToProt=true;\r
218         sense=false;\r
219       } \r
220     }\r
221     // create mapping storage object and make each dataset alignment reference\r
222     // it.\r
223     jalview.datamodel.AlignmentI dsLoc = (jalview.datamodel.AlignmentI) getvObj2jv(sdloc.getV_parent());\r
224     jalview.datamodel.AlignmentI dsMap = (jalview.datamodel.AlignmentI) getvObj2jv(sdmap.getV_parent());\r
225     AlignedCodonFrame afc = new AlignedCodonFrame(0);\r
226 \r
227     if (dsLoc!=null && dsLoc!=dsMap)\r
228     {\r
229       dsLoc.addCodonFrame(afc);\r
230     }\r
231     if (dsMap!=null)\r
232     {\r
233       dsMap.addCodonFrame(afc);\r
234     }\r
235     // create and add the new mapping to (each) dataset's codonFrame\r
236 \r
237     jalview.util.MapList mapping = null; \r
238     if (!sense)\r
239     {\r
240       mapping = this.parsemapType(sequenceMapping, 1, 3); // invert sense\r
241       mapping = new jalview.util.MapList(mapping.getToRanges(), mapping.getFromRanges(), mapping.getToRatio(), mapping.getFromRatio());\r
242       afc.addMap(to, from, mapping);\r
243     } else {\r
244       mapping = this.parsemapType(sequenceMapping, 3, 1); // correct sense\r
245       afc.addMap(from, to, mapping);\r
246     }\r
247     bindjvvobj(mapping, sequenceMapping);\r
248     jalview.structure.StructureSelectionManager.getStructureSelectionManager().addMappings(new AlignedCodonFrame[] { afc });\r
249     // Try to link up any conjugate database references in the two sequences\r
250     // matchConjugateDBRefs(from, to,  mapping);\r
251     // Try to propagate any dbrefs across this mapping.\r
252 \r
253   }\r
254   /**\r
255    * Complete any 'to' references in jalview.datamodel.Mapping objects associated with conjugate DBRefEntry under given mapping  \r
256    * @param from sequence corresponding to from reference for sequence mapping\r
257    * @param to sequence correspondeing to to reference for sequence mapping\r
258    * @param smap maplist parsed in same sense as from and to\r
259    */\r
260   private void matchConjugateDBRefs(SequenceI from, SequenceI to,\r
261           jalview.util.MapList smap)\r
262   {\r
263     if (from.getDBRef()==null && to.getDBRef()==null)\r
264     {\r
265       if (jalview.bin.Cache.log.isDebugEnabled())\r
266       {\r
267         jalview.bin.Cache.log.debug("Not matching conjugate refs for "+from.getName()+" and "+to.getName());\r
268       }\r
269       return; \r
270     }\r
271     if (jalview.bin.Cache.log.isDebugEnabled())\r
272     {\r
273       jalview.bin.Cache.log.debug("Matching conjugate refs for "+from.getName()+" and "+to.getName());\r
274     }\r
275     jalview.datamodel.DBRefEntry[] fdb = from.getDBRef();\r
276     jalview.datamodel.DBRefEntry[] tdb = new jalview.datamodel.DBRefEntry[to.getDBRef().length];\r
277     int tdblen = to.getDBRef().length;\r
278     System.arraycopy(to.getDBRef(), 0, tdb, 0, tdblen);\r
279     Vector matched = new Vector();\r
280     jalview.util.MapList smapI = smap.getInverse();\r
281     for (int f=0;f<fdb.length; f++)\r
282     {\r
283       jalview.datamodel.DBRefEntry fe = fdb[f];\r
284       jalview.datamodel.Mapping fmp = fe.getMap();\r
285       boolean fmpnnl = fmp!=null;\r
286       // if (fmpnnl && fmp.getTo()!=null)\r
287       //{\r
288       //  jalview.bin.Cache.log.debug("Not overwriting existing To reference in "+fe);\r
289       //  continue;\r
290       //}\r
291       // smap from maps from fe.local to fe.map\r
292       boolean smapfromlocal2fe = (fmpnnl) ? smap.equals(fmp.getMap()) : false;\r
293       // smap from maps from fe.map to fe.local.\r
294       boolean smapfromfemap2local = (fmpnnl) ? smapI.equals(fmp.getMap()) : false;\r
295       for (int t=0; t<tdblen; t++)\r
296       {\r
297         jalview.datamodel.DBRefEntry te = tdb[t];\r
298         if (te!=null)\r
299         {\r
300           if (fe.getSource().equals(te.getSource())\r
301               && fe.getAccessionId().equals(te.getAccessionId()))\r
302           {\r
303             jalview.datamodel.Mapping tmp = te.getMap();\r
304             boolean tmpnnl = tmp!=null;\r
305             if (tmpnnl && tmp.getTo()!=null)\r
306             {\r
307               \r
308             }\r
309             // smap to maps from te.local to te.map\r
310             boolean smaptolocal2tm = (tmpnnl) ? smap.equals(tmp.getMap()) : false;\r
311             // smap to maps from te.map to te.local\r
312             boolean smaptotemap2local = (tmpnnl) ? smapI.equals(fmp.getMap()) : false;\r
313             if (smapfromlocal2fe && smaptotemap2local)\r
314             {\r
315               // smap implies mapping from to to from\r
316               fmp.setTo(to);\r
317               tmp.setTo(from);\r
318             } else \r
319               if (smapfromfemap2local && smaptolocal2tm) {\r
320                 fmp.setTo(to);\r
321               }\r
322             }\r
323             \r
324         }\r
325       }\r
326     }\r
327     }\r
328 }