JAL-1641 refinement of the JSON data model and abstraction of several methods that...
[jalview.git] / src / jalview / io / JSONFile.java
1 package jalview.io;
2
3 import jalview.api.FeaturesDisplayedI;
4 import jalview.datamodel.AlignmentAnnotation;
5 import jalview.datamodel.Annotation;
6 import jalview.datamodel.Sequence;
7 import jalview.datamodel.SequenceFeature;
8 import jalview.datamodel.SequenceGroup;
9 import jalview.datamodel.SequenceI;
10 import jalview.gui.AlignFrame;
11 import jalview.gui.Desktop;
12 import jalview.json.binding.v1.AlignmentAnnotationPojo;
13 import jalview.json.binding.v1.AlignmentPojo;
14 import jalview.json.binding.v1.AnnotationPojo;
15 import jalview.json.binding.v1.JalviewSettingsPojo;
16 import jalview.json.binding.v1.JalviewSettingsPojo.JalviewBioJsColorSchemeMapper;
17 import jalview.json.binding.v1.SequenceFeaturesPojo;
18 import jalview.json.binding.v1.SequenceGrpPojo;
19 import jalview.json.binding.v1.SequencePojo;
20 import jalview.schemes.ColourSchemeI;
21 import jalview.schemes.ColourSchemeProperty;
22 import jalview.viewmodel.AlignmentViewport;
23
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.Hashtable;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Vector;
30
31 import org.json.simple.JSONArray;
32 import org.json.simple.JSONObject;
33 import org.json.simple.parser.JSONParser;
34
35 public class JSONFile extends AlignFile
36 {
37   private ColourSchemeI cs;
38
39   private String jalviewVersion;
40
41   private String webStartLaunchServletUrl = "http://www.jalview.org/services/launchApp";
42
43   public static final String FILE_EXT = "json";
44
45   public static final String FILE_DESC = "JSON";
46
47   private String globalColorScheme;
48
49   private boolean showSeqFeatures;
50
51   private Hashtable<String, Sequence> seqMap;
52
53   private FeaturesDisplayedI displayedFeatures;
54
55   private AlignmentViewport av;
56
57   private jalview.api.FeatureRenderer fr;
58
59   public JSONFile()
60   {
61     super();
62   }
63
64   public JSONFile(FileParse source) throws IOException
65   {
66     super(source);
67   }
68
69   public JSONFile(String inFile, String type) throws IOException
70   {
71     super(inFile, type);
72   }
73
74   @Override
75   public void parse() throws IOException
76   {
77     StringBuilder jsonStringBuilder = new StringBuilder();
78     String currentLine;
79     while ((currentLine = nextLine()) != null)
80     {
81       jsonStringBuilder.append(currentLine);
82     }
83     parse(jsonStringBuilder.toString());
84
85   }
86
87   @Override
88   public String print()
89   {
90     try
91     {
92       JSONExportSettings exportSettings = new JSONExportSettings();
93       exportSettings.setExportAnnotations(true);
94       exportSettings.setExportGroups(true);
95       exportSettings.setExportJalviewSettings(true);
96       exportSettings.setExportSequenceFeatures(true);
97
98       AlignmentPojo jsonAlignmentPojo = new AlignmentPojo();
99       if (Desktop.getCurrentAlignFrame() != null)
100       {
101         globalColorScheme = ColourSchemeProperty.getColourName(Desktop
102                 .getCurrentAlignFrame().getViewport()
103                 .getGlobalColourScheme());
104         this.av = Desktop.getCurrentAlignFrame().getCurrentView();
105         this.fr = Desktop.getCurrentAlignFrame().alignPanel
106                 .cloneFeatureRenderer();
107         displayedFeatures = av.getFeaturesDisplayed();
108         showSeqFeatures = Desktop.getCurrentAlignFrame().showSeqFeatures
109                 .isSelected();
110       }
111
112       int count = 0;
113       for (SequenceI seq : seqs)
114       {
115         StringBuilder name = new StringBuilder();
116         name.append(seq.getName()).append("/").append(seq.getStart())
117                 .append("-").append(seq.getEnd());
118         SequencePojo jsonSeqPojo = new SequencePojo();
119         jsonSeqPojo.setId(seq.getName() + "_" + seq.hashCode());
120         jsonSeqPojo.setOrder(++count);
121         jsonSeqPojo.setEnd(seq.getEnd());
122         jsonSeqPojo.setStart(seq.getStart());
123         jsonSeqPojo.setName(name.toString());
124         jsonSeqPojo.setSeq(seq.getSequenceAsString());
125         jsonAlignmentPojo.getSeqs().add(jsonSeqPojo);
126       }
127
128       if (exportSettings.isExportJalviewSettings())
129       {
130         JalviewSettingsPojo jvSettings = new JalviewSettingsPojo();
131         jvSettings.setGlobalColorScheme(globalColorScheme);
132         jvSettings.setJalviewVersion(jalviewVersion);
133         jvSettings.setWebStartUrl(webStartLaunchServletUrl);
134         jvSettings.setShowSeqFeatures(showSeqFeatures);
135         jsonAlignmentPojo.setJalviewSettings(jvSettings);
136       }
137
138       if (exportSettings.isExportAnnotations())
139       {
140         jsonAlignmentPojo
141                 .setAlignAnnotation(annotationToJsonPojo(annotations));
142       }
143
144       if (exportSettings.isExportSequenceFeatures())
145       {
146         jsonAlignmentPojo.setSeqFeatures(sequenceFeatureToJsonPojo(seqs,
147                 displayedFeatures));
148       }
149
150       if (exportSettings.isExportGroups() && seqGroups.size() > 0)
151       {
152         ArrayList<SequenceGrpPojo> sequenceGroupsPojo = new ArrayList<SequenceGrpPojo>();
153         for (SequenceGroup seqGrp : seqGroups)
154         {
155           SequenceGrpPojo seqGrpPojo = new SequenceGrpPojo();
156           seqGrpPojo.setGroupName(seqGrp.getName());
157           seqGrpPojo.setColourScheme(ColourSchemeProperty
158                   .getColourName(seqGrp.cs));
159           seqGrpPojo.setColourText(seqGrp.getColourText());
160           seqGrpPojo.setDescription(seqGrp.getDescription());
161           seqGrpPojo.setDisplayBoxes(seqGrp.getDisplayBoxes());
162           seqGrpPojo.setDisplayText(seqGrp.getDisplayText());
163           seqGrpPojo.setEndRes(seqGrp.getEndRes());
164           seqGrpPojo.setStartRes(seqGrp.getStartRes());
165           seqGrpPojo.setShowNonconserved(seqGrp.getShowNonconserved());
166           for (SequenceI seq : seqGrp.getSequences())
167           {
168             seqGrpPojo.getSeqsHash().add(
169                     seq.getName() + "_" + seq.hashCode());
170           }
171           jsonAlignmentPojo.getSeqGroups().add(seqGrpPojo);
172         }
173       }
174       com.json.JSONObject generatedJSon = new com.json.JSONObject(
175               jsonAlignmentPojo);
176       String jsonOutput = generatedJSon.toString();
177       return jsonOutput.replaceAll("xstart", "xStart").replaceAll("xend",
178               "xEnd");
179     } catch (Exception e)
180     {
181       e.printStackTrace();
182       throw e;
183     }
184   }
185
186   public static List<SequenceFeaturesPojo> sequenceFeatureToJsonPojo(
187           List<SequenceI> seqs, FeaturesDisplayedI displayedFeatures)
188   {
189     List<SequenceFeaturesPojo> sequenceFeaturesPojo = new ArrayList<SequenceFeaturesPojo>();
190     for (SequenceI seq : seqs)
191     {
192       SequenceI dataSetSequence = seq.getDatasetSequence();
193       SequenceFeature[] seqFeatures = (dataSetSequence == null) ? null
194               : seq.getDatasetSequence().getSequenceFeatures();
195       for (SequenceFeature sf : seqFeatures)
196       {
197         if (displayedFeatures != null
198                 && displayedFeatures.isVisible(sf.getType()))
199         {
200           // String fillColor = ((fr != null) ? jalview.util.Format
201           // .getHexString(fr.findFeatureColour(Color.white, seq,
202           // seq.findIndex(sf.getBegin()))) : null);
203           SequenceFeaturesPojo jsonFeature = new SequenceFeaturesPojo(
204                   seq.getName() + "_" + seq.hashCode());
205           jsonFeature.setXstart(seq.findIndex(sf.getBegin()) - 1);
206           jsonFeature.setXend(seq.findIndex(sf.getEnd()));
207           jsonFeature.setType(sf.getType());
208           jsonFeature.setDescription(sf.getDescription());
209           jsonFeature.setLinks(sf.links);
210           jsonFeature.setOtherDetails(sf.otherDetails);
211           jsonFeature.setScore(sf.getScore());
212           // jsonFeature.setFillColor(fillColor);
213           jsonFeature.setFeatureGroup(sf.getFeatureGroup());
214           sequenceFeaturesPojo.add(jsonFeature);
215         }
216       }
217     }
218     return sequenceFeaturesPojo;
219   }
220
221   public static List<AlignmentAnnotationPojo> annotationToJsonPojo(
222           Vector<AlignmentAnnotation> annotations)
223   {
224     List<AlignmentAnnotationPojo> jsonAnnotations = new ArrayList<AlignmentAnnotationPojo>();
225     for (AlignmentAnnotation annot : annotations)
226     {
227       AlignmentAnnotationPojo alignAnnotPojo = new AlignmentAnnotationPojo();
228       alignAnnotPojo.setDescription(annot.description);
229       alignAnnotPojo.setLabel(annot.label);
230       for (Annotation annotation : annot.annotations)
231       {
232         AnnotationPojo annotationPojo = new AnnotationPojo();
233         if (annotation != null)
234         {
235           annotationPojo.setDescription(annotation.description);
236           annotationPojo.setValue(annotation.value);
237           annotationPojo
238                   .setSecondaryStructure(annotation.secondaryStructure);
239           annotationPojo.setDisplayCharacter(annotation.displayCharacter);
240           alignAnnotPojo.getAnnotations().add(annotationPojo);
241         }
242         else
243         {
244           alignAnnotPojo.getAnnotations().add(annotationPojo);
245         }
246       }
247       jsonAnnotations.add(alignAnnotPojo);
248     }
249     return jsonAnnotations;
250   }
251
252   public void parse(String jsonAlignmentString)
253   {
254     try
255     {
256       JSONParser jsonParser = new JSONParser();
257       JSONObject alignmentJsonObj = (JSONObject) jsonParser
258               .parse(jsonAlignmentString);
259       JSONArray seqJsonArray = (JSONArray) alignmentJsonObj.get("seqs");
260       JSONArray alAnnotJsonArray = (JSONArray) alignmentJsonObj
261               .get("alignAnnotation");
262       JSONArray jsonSeqArray = (JSONArray) alignmentJsonObj
263               .get("seqFeatures");
264       JSONArray seqGrpJsonArray = (JSONArray) alignmentJsonObj
265               .get("seqGroups");
266       JSONObject jvSettingsJsonObj = (JSONObject) alignmentJsonObj
267               .get("jalviewSettings");
268
269       if (jvSettingsJsonObj != null)
270       {
271         String jsColourScheme = (String) jvSettingsJsonObj
272                 .get("globalColorScheme");
273         Boolean showFeatures = Boolean.valueOf(jvSettingsJsonObj.get(
274                 "showSeqFeatures").toString());
275         cs = getJalviewColorScheme(jsColourScheme);
276         Desktop.setCurrentSeqFeaturesVisible(showFeatures);
277       }
278
279       seqMap = new Hashtable<String, Sequence>();
280       Desktop.setCurrentGlobalColourScheme(cs);
281       for (Iterator<JSONObject> sequenceIter = seqJsonArray.iterator(); sequenceIter
282               .hasNext();)
283       {
284         JSONObject sequence = sequenceIter.next();
285         String sequcenceString = sequence.get("seq").toString();
286         String sequenceName = sequence.get("name").toString();
287         String seqUniqueId = sequence.get("id").toString();
288         int start = Integer.valueOf(sequence.get("start").toString());
289         int end = Integer.valueOf(sequence.get("end").toString());
290         Sequence seq = new Sequence(sequenceName, sequcenceString, start,
291                 end);
292         seqs.add(seq);
293         seqMap.put(seqUniqueId, seq);
294       }
295       parseFeatures(jsonSeqArray);
296
297       for (Iterator<JSONObject> seqGrpIter = seqGrpJsonArray.iterator(); seqGrpIter
298               .hasNext();)
299       {
300         JSONObject seqGrpObj = seqGrpIter.next();
301         String grpName = seqGrpObj.get("groupName").toString();
302         String colourScheme = seqGrpObj.get("colourScheme").toString();
303         String description = (seqGrpObj.get("description") == null) ? null
304                 : seqGrpObj.get("description").toString();
305         boolean displayBoxes = Boolean.valueOf(seqGrpObj
306                 .get("displayBoxes").toString());
307         boolean displayText = Boolean.valueOf(seqGrpObj.get("displayText")
308                 .toString());
309         boolean colourText = Boolean.valueOf(seqGrpObj.get("colourText")
310                 .toString());
311         boolean showNonconserved = Boolean.valueOf(seqGrpObj.get(
312                 "showNonconserved").toString());
313         int startRes = Integer
314                 .valueOf(seqGrpObj.get("startRes").toString());
315         int endRes = Integer.valueOf(seqGrpObj.get("endRes").toString());
316         JSONArray seqsHashArray = (JSONArray) seqGrpObj.get("seqsHash");
317
318         ArrayList<SequenceI> grpSeqs = new ArrayList<SequenceI>();
319         if (seqsHashArray.size() > 0)
320         {
321           Iterator<String> seqHashIter = seqsHashArray.iterator();
322           while (seqHashIter.hasNext())
323           {
324             String seqHash = seqHashIter.next();
325             Sequence sequence = seqMap.get(seqHash);
326             if (sequence != null)
327             {
328               grpSeqs.add(sequence);
329             }
330           }
331         }
332         ColourSchemeI scheme = getJalviewColorScheme(colourScheme);
333         SequenceGroup seqGrp = new SequenceGroup(grpSeqs, grpName, scheme,
334                 displayBoxes, displayText, colourText, startRes, endRes);
335         seqGrp.setShowNonconserved(showNonconserved);
336         seqGrp.setDescription(description);
337         this.seqGroups.add(seqGrp);
338
339       }
340
341       for (Iterator<JSONObject> alAnnotIter = alAnnotJsonArray.iterator(); alAnnotIter
342               .hasNext();)
343       {
344         JSONObject alAnnot = alAnnotIter.next();
345         JSONArray annotJsonArray = (JSONArray) alAnnot.get("annotations");
346         Annotation[] annotations = new Annotation[annotJsonArray.size()];
347         int count = 0;
348         for (Iterator<JSONObject> annotIter = annotJsonArray.iterator(); annotIter
349                 .hasNext();)
350         {
351           JSONObject annot = annotIter.next();
352           if (annot == null)
353           {
354             annotations[count] = null;
355           }
356           else
357           {
358             float val = annot.get("value") == null ? null : Float
359                     .valueOf(annot.get("value").toString());
360             String desc = annot.get("description") == null ? null : annot
361                     .get("description").toString();
362
363             char ss = annot.get("secondaryStructure") == null ? null
364                     : annot.get("secondaryStructure").toString().charAt(0);
365             String displayChar = annot.get("displayCharacter").toString();
366
367             annotations[count] = new Annotation(displayChar, desc, ss, val);
368           }
369           ++count;
370         }
371
372         AlignmentAnnotation alignAnnot = new AlignmentAnnotation(alAnnot
373                 .get("label").toString(), alAnnot.get("description")
374                 .toString(), annotations);
375         this.annotations.add(alignAnnot);
376       }
377
378     } catch (Exception e)
379     {
380       e.printStackTrace();
381     }
382   }
383
384
385   private void parseFeatures(JSONArray jsonSeqFeatures)
386   {
387     if (jsonSeqFeatures != null)
388     {
389       for (@SuppressWarnings("unchecked")
390       Iterator<JSONObject> seqFeatureItr = jsonSeqFeatures.iterator(); seqFeatureItr
391               .hasNext();)
392       {
393         JSONObject jsonFeature = seqFeatureItr.next();
394         Long begin = (Long) jsonFeature.get("xStart");
395         Long end = (Long) jsonFeature.get("xEnd");
396         String type = (String) jsonFeature.get("type");
397         String color = (String) jsonFeature.get("fillColor");
398         String featureGrp = (String) jsonFeature.get("featureGroup");
399         String descripiton = (String) jsonFeature.get("description");
400         String seqRef = (String) jsonFeature.get("sequenceRef");
401         Float score = Float.valueOf(jsonFeature.get("score").toString());
402         // Hashtable otherDetails = (Hashtable) jsonFeature
403         // .get("otherDetails");
404         // sequenceFeature.otherDetails = otherDetails;
405
406         Sequence seq = seqMap.get(seqRef);
407         SequenceFeature sequenceFeature = new SequenceFeature();
408         JSONArray linksJsonArray = (JSONArray) jsonFeature.get("links");
409         if (linksJsonArray != null && linksJsonArray.size() > 0)
410         {
411           Iterator<String> linkList = linksJsonArray.iterator();
412           while (linkList.hasNext())
413           {
414             String link = linkList.next();
415             sequenceFeature.addLink(link);
416           }
417         }
418         sequenceFeature.setFeatureGroup(featureGrp);
419         sequenceFeature.setScore(score);
420         sequenceFeature.setDescription(descripiton);
421         sequenceFeature.setType(type);
422         sequenceFeature.setBegin(seq.findPosition(begin.intValue()));
423         sequenceFeature.setEnd(seq.findPosition(end.intValue()) - 1);
424         seq.addSequenceFeature(sequenceFeature);
425       }
426     }
427   }
428
429   private ColourSchemeI getJalviewColorScheme(String bioJsColourSchemeName)
430   {
431     ColourSchemeI jalviewColor = null;
432     for (JalviewBioJsColorSchemeMapper cs : JalviewBioJsColorSchemeMapper
433             .values())
434     {
435       if (cs.getBioJsName().equalsIgnoreCase(bioJsColourSchemeName))
436       {
437         jalviewColor = cs.getJvColourScheme();
438         break;
439       }
440     }
441     return jalviewColor;
442   }
443
444   public void LoadAlignmentFeatures(AlignFrame af)
445   {
446     af.setShowSeqFeatures(Desktop.isCurrentSeqFeaturesVisible());
447     af.changeColour(Desktop.getCurrentGlobalColourScheme());
448     af.setMenusForViewport();
449   }
450
451   public String getGlobalColorScheme()
452   {
453     return globalColorScheme;
454   }
455
456   public void setGlobalColorScheme(String globalColorScheme)
457   {
458     this.globalColorScheme = globalColorScheme;
459   }
460
461   public class JSONExportSettings
462   {
463     private boolean exportSequence;
464
465     private boolean exportSequenceFeatures;
466
467     private boolean exportAnnotations;
468
469     private boolean exportGroups;
470
471     private boolean exportJalviewSettings;
472
473     public boolean isExportSequence()
474     {
475       return exportSequence;
476     }
477
478     public void setExportSequence(boolean exportSequence)
479     {
480       this.exportSequence = exportSequence;
481     }
482
483     public boolean isExportSequenceFeatures()
484     {
485       return exportSequenceFeatures;
486     }
487
488     public void setExportSequenceFeatures(boolean exportSequenceFeatures)
489     {
490       this.exportSequenceFeatures = exportSequenceFeatures;
491     }
492
493     public boolean isExportAnnotations()
494     {
495       return exportAnnotations;
496     }
497
498     public void setExportAnnotations(boolean exportAnnotations)
499     {
500       this.exportAnnotations = exportAnnotations;
501     }
502
503     public boolean isExportGroups()
504     {
505       return exportGroups;
506     }
507
508     public void setExportGroups(boolean exportGroups)
509     {
510       this.exportGroups = exportGroups;
511     }
512
513     public boolean isExportJalviewSettings()
514     {
515       return exportJalviewSettings;
516     }
517
518     public void setExportJalviewSettings(boolean exportJalviewSettings)
519     {
520       this.exportJalviewSettings = exportJalviewSettings;
521     }
522   }
523 }