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