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