/*
* Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
* Copyright (C) $$Year-Rel$$ The Jalview Authors
*
* This file is part of Jalview.
*
* Jalview is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* Jalview is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jalview. If not, see .
* The Jalview Authors are detailed in the 'AUTHORS' file.
*/
package jalview.io;
import jalview.api.AlignViewControllerGuiI;
import jalview.api.AlignViewportI;
import jalview.api.FeatureRenderer;
import jalview.api.FeaturesDisplayedI;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.Annotation;
import jalview.datamodel.HiddenSequences;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.json.binding.v1.AlignmentAnnotationPojo;
import jalview.json.binding.v1.AlignmentPojo;
import jalview.json.binding.v1.AlignmentPojo.JalviewBioJsColorSchemeMapper;
import jalview.json.binding.v1.AnnotationPojo;
import jalview.json.binding.v1.SequenceFeaturesPojo;
import jalview.json.binding.v1.SequenceGrpPojo;
import jalview.json.binding.v1.SequencePojo;
import jalview.schemes.ColourSchemeI;
import jalview.schemes.ColourSchemeProperty;
import java.awt.Color;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
public class JSONFile extends AlignFile
{
private ColourSchemeI colourScheme;
private String version = "2.9";
private String webstartUrl = "www.jalview.org/services/launchApp";
private String application = "Jalview";
public static final String FILE_EXT = "json";
public static final String FILE_DESC = "JSON";
private String globalColorScheme;
private boolean showSeqFeatures;
private Hashtable seqMap;
private FeaturesDisplayedI displayedFeatures;
private FeatureRenderer fr;
private JSONExportSettings jsonExportSettings;
public JSONFile()
{
super();
}
public JSONFile(FileParse source) throws IOException
{
super(source);
}
public JSONFile(String inFile, String type) throws IOException
{
super(inFile, type);
}
@Override
public void parse() throws IOException
{
StringBuilder jsonStringBuilder = new StringBuilder();
String currentLine;
while ((currentLine = nextLine()) != null)
{
jsonStringBuilder.append(currentLine);
}
parse(jsonStringBuilder.toString());
}
@Override
public String print()
{
String jsonOutput = null;
try
{
if (getJsonExportSettings() == null)
{
jsonExportSettings = new JSONExportSettings();
jsonExportSettings.setExportAnnotations(true);
jsonExportSettings.setExportGroups(true);
jsonExportSettings.setExportJalviewSettings(true);
jsonExportSettings.setExportSequenceFeatures(true);
}
AlignmentPojo jsonAlignmentPojo = new AlignmentPojo();
if (getViewport() != null)
{
globalColorScheme = ColourSchemeProperty
.getColourName(getViewport()
.getGlobalColourScheme());
setDisplayedFeatures(getViewport().getFeaturesDisplayed());
showSeqFeatures = getViewport().isShowSequenceFeatures();
fr = getViewport().getFeatureRenderer();
}
int count = 0;
for (SequenceI seq : seqs)
{
StringBuilder name = new StringBuilder();
name.append(seq.getName()).append("/").append(seq.getStart())
.append("-").append(seq.getEnd());
SequencePojo jsonSeqPojo = new SequencePojo();
jsonSeqPojo.setId(seq.getName() + "_" + seq.hashCode());
jsonSeqPojo.setOrder(++count);
jsonSeqPojo.setEnd(seq.getEnd());
jsonSeqPojo.setStart(seq.getStart());
jsonSeqPojo.setName(name.toString());
jsonSeqPojo.setSeq(seq.getSequenceAsString());
jsonAlignmentPojo.getSeqs().add(jsonSeqPojo);
}
if (jsonExportSettings.isExportJalviewSettings())
{
jsonAlignmentPojo.setGlobalColorScheme(globalColorScheme);
jsonAlignmentPojo.getAppSettings().put("application", application);
jsonAlignmentPojo.getAppSettings().put("version", version);
jsonAlignmentPojo.getAppSettings().put("webStartUrl", webstartUrl);
jsonAlignmentPojo.getAppSettings().put("showSeqFeatures",
String.valueOf(showSeqFeatures));
String[] hiddenSections = exportHiddenSections();
if (hiddenSections != null)
{
jsonAlignmentPojo.getAppSettings().put("hiddenCols",
String.valueOf(hiddenSections[0]));
jsonAlignmentPojo.getAppSettings().put("hiddenSeqs",
String.valueOf(hiddenSections[1]));
}
}
if (jsonExportSettings.isExportAnnotations())
{
jsonAlignmentPojo
.setAlignAnnotation(annotationToJsonPojo(annotations));
}
if (jsonExportSettings.isExportSequenceFeatures())
{
jsonAlignmentPojo
.setSeqFeatures(sequenceFeatureToJsonPojo(seqs, fr));
}
if (jsonExportSettings.isExportGroups() && seqGroups != null
&& seqGroups.size() > 0)
{
for (SequenceGroup seqGrp : seqGroups)
{
SequenceGrpPojo seqGrpPojo = new SequenceGrpPojo();
seqGrpPojo.setGroupName(seqGrp.getName());
seqGrpPojo.setColourScheme(ColourSchemeProperty
.getColourName(seqGrp.cs));
seqGrpPojo.setColourText(seqGrp.getColourText());
seqGrpPojo.setDescription(seqGrp.getDescription());
seqGrpPojo.setDisplayBoxes(seqGrp.getDisplayBoxes());
seqGrpPojo.setDisplayText(seqGrp.getDisplayText());
seqGrpPojo.setEndRes(seqGrp.getEndRes());
seqGrpPojo.setStartRes(seqGrp.getStartRes());
seqGrpPojo.setShowNonconserved(seqGrp.getShowNonconserved());
for (SequenceI seq : seqGrp.getSequences())
{
seqGrpPojo.getSeqsHash().add(
seq.getName() + "_" + seq.hashCode());
}
jsonAlignmentPojo.getSeqGroups().add(seqGrpPojo);
}
}
org.json.JSONObject generatedJSon = new org.json.JSONObject(
jsonAlignmentPojo);
jsonOutput = generatedJSon.toString();
return jsonOutput.replaceAll("xstart", "xStart").replaceAll("xend",
"xEnd");
} catch (Exception e)
{
e.printStackTrace();
}
return jsonOutput;
}
public String[] exportHiddenSections()
{
String[] hiddenSections = new String[2];
if (getViewport() == null)
{
return null;
}
System.out.println("--- Hidden Sections ---");
// hidden column business
if (getViewport().hasHiddenColumns())
{
System.out.print("Hidden Cols : ");
List hiddenCols = getViewport().getColumnSelection()
.getHiddenColumns();
StringBuilder hiddenColsBuilder = new StringBuilder();
for (int[] range : hiddenCols)
{
hiddenColsBuilder.append(";").append(range[0]).append("-")
.append(range[1]);
}
hiddenColsBuilder.deleteCharAt(0);
hiddenSections[0] = hiddenColsBuilder.toString();
System.out.println(hiddenSections[0]);
}
// hidden rows/seqs business
HiddenSequences hiddenSeqsObj = getViewport().getAlignment()
.getHiddenSequences();
if (hiddenSeqsObj == null)
{
return hiddenSections;
}
SequenceI[] hiddenSeqs = hiddenSeqsObj.hiddenSequences;
System.out.print("Hidden Seqs : ");
StringBuilder hiddenSeqsBuilder = new StringBuilder();
for (SequenceI hiddenSeq : hiddenSeqs)
{
if (hiddenSeq != null)
{
hiddenSeqsBuilder.append(";").append(hiddenSeq.hashCode());
}
}
if (hiddenSeqsBuilder.length() > 0)
{
hiddenSeqsBuilder.deleteCharAt(0);
}
hiddenSections[1] = hiddenSeqsBuilder.toString();
System.out.println(hiddenSections[1]);
return hiddenSections;
}
public static List sequenceFeatureToJsonPojo(
List seqs, FeatureRenderer fr)
{
FeaturesDisplayedI displayedFeatures = (fr == null) ? null : fr
.getFeaturesDisplayed();
List sequenceFeaturesPojo = new ArrayList();
for (SequenceI seq : seqs)
{
SequenceI dataSetSequence = seq.getDatasetSequence();
SequenceFeature[] seqFeatures = (dataSetSequence == null) ? null
: seq.getDatasetSequence().getSequenceFeatures();
if (seqFeatures == null)
{
continue;
}
for (SequenceFeature sf : seqFeatures)
{
if (displayedFeatures != null
&& displayedFeatures.isVisible(sf.getType()))
{
SequenceFeaturesPojo jsonFeature = new SequenceFeaturesPojo(
seq.getName() + "_" + seq.hashCode());
String featureColour = (fr == null) ? null : jalview.util.Format
.getHexString(fr
.findFeatureColour(Color.white, seq,
seq.findIndex(sf.getBegin())));
jsonFeature.setXstart(seq.findIndex(sf.getBegin()) - 1);
jsonFeature.setXend(seq.findIndex(sf.getEnd()));
jsonFeature.setType(sf.getType());
jsonFeature.setDescription(sf.getDescription());
jsonFeature.setLinks(sf.links);
jsonFeature.setOtherDetails(sf.otherDetails);
jsonFeature.setScore(sf.getScore());
jsonFeature.setFillColor(featureColour);
jsonFeature.setFeatureGroup(sf.getFeatureGroup());
sequenceFeaturesPojo.add(jsonFeature);
}
}
}
return sequenceFeaturesPojo;
}
public static List annotationToJsonPojo(
Vector annotations)
{
List jsonAnnotations = new ArrayList();
if (annotations == null)
{
return jsonAnnotations;
}
for (AlignmentAnnotation annot : annotations)
{
AlignmentAnnotationPojo alignAnnotPojo = new AlignmentAnnotationPojo();
alignAnnotPojo.setDescription(annot.description);
alignAnnotPojo.setLabel(annot.label);
for (Annotation annotation : annot.annotations)
{
AnnotationPojo annotationPojo = new AnnotationPojo();
if (annotation != null)
{
annotationPojo.setDescription(annotation.description);
annotationPojo.setValue(annotation.value);
annotationPojo
.setSecondaryStructure(annotation.secondaryStructure);
annotationPojo.setDisplayCharacter(annotation.displayCharacter);
alignAnnotPojo.getAnnotations().add(annotationPojo);
}
else
{
alignAnnotPojo.getAnnotations().add(annotationPojo);
}
}
jsonAnnotations.add(alignAnnotPojo);
}
return jsonAnnotations;
}
@SuppressWarnings("unchecked")
public JSONFile parse(String jsonAlignmentString)
{
try
{
JSONParser jsonParser = new JSONParser();
JSONObject alignmentJsonObj = (JSONObject) jsonParser
.parse(jsonAlignmentString);
JSONArray seqJsonArray = (JSONArray) alignmentJsonObj.get("seqs");
JSONArray alAnnotJsonArray = (JSONArray) alignmentJsonObj
.get("alignAnnotation");
JSONArray jsonSeqArray = (JSONArray) alignmentJsonObj
.get("seqFeatures");
JSONArray seqGrpJsonArray = (JSONArray) alignmentJsonObj
.get("seqGroups");
JSONObject jvSettingsJsonObj = (JSONObject) alignmentJsonObj
.get("appSettings");
if (jvSettingsJsonObj != null)
{
String jsColourScheme = (String) jvSettingsJsonObj
.get("globalColorScheme");
Boolean showFeatures = Boolean.valueOf(jvSettingsJsonObj.get(
"showSeqFeatures").toString());
setColourScheme(getJalviewColorScheme(jsColourScheme));
setShowSeqFeatures(showFeatures);
}
seqMap = new Hashtable();
for (Iterator sequenceIter = seqJsonArray.iterator(); sequenceIter
.hasNext();)
{
JSONObject sequence = sequenceIter.next();
String sequcenceString = sequence.get("seq").toString();
String sequenceName = sequence.get("name").toString();
String seqUniqueId = sequence.get("id").toString();
int start = Integer.valueOf(sequence.get("start").toString());
int end = Integer.valueOf(sequence.get("end").toString());
Sequence seq = new Sequence(sequenceName, sequcenceString, start,
end);
seqs.add(seq);
seqMap.put(seqUniqueId, seq);
}
parseFeatures(jsonSeqArray);
for (Iterator seqGrpIter = seqGrpJsonArray.iterator(); seqGrpIter
.hasNext();)
{
JSONObject seqGrpObj = seqGrpIter.next();
String grpName = seqGrpObj.get("groupName").toString();
String colourScheme = seqGrpObj.get("colourScheme").toString();
String description = (seqGrpObj.get("description") == null) ? null
: seqGrpObj.get("description").toString();
boolean displayBoxes = Boolean.valueOf(seqGrpObj
.get("displayBoxes").toString());
boolean displayText = Boolean.valueOf(seqGrpObj.get("displayText")
.toString());
boolean colourText = Boolean.valueOf(seqGrpObj.get("colourText")
.toString());
boolean showNonconserved = Boolean.valueOf(seqGrpObj.get(
"showNonconserved").toString());
int startRes = Integer
.valueOf(seqGrpObj.get("startRes").toString());
int endRes = Integer.valueOf(seqGrpObj.get("endRes").toString());
JSONArray seqsHashArray = (JSONArray) seqGrpObj.get("seqsHash");
ArrayList grpSeqs = new ArrayList();
if (seqsHashArray.size() > 0)
{
Iterator seqHashIter = seqsHashArray.iterator();
while (seqHashIter.hasNext())
{
String seqHash = seqHashIter.next();
Sequence sequence = seqMap.get(seqHash);
if (sequence != null)
{
grpSeqs.add(sequence);
}
}
}
ColourSchemeI scheme = getJalviewColorScheme(colourScheme);
SequenceGroup seqGrp = new SequenceGroup(grpSeqs, grpName, scheme,
displayBoxes, displayText, colourText, startRes, endRes);
seqGrp.setShowNonconserved(showNonconserved);
seqGrp.setDescription(description);
this.seqGroups.add(seqGrp);
}
for (Iterator alAnnotIter = alAnnotJsonArray.iterator(); alAnnotIter
.hasNext();)
{
JSONObject alAnnot = alAnnotIter.next();
JSONArray annotJsonArray = (JSONArray) alAnnot.get("annotations");
Annotation[] annotations = new Annotation[annotJsonArray.size()];
int count = 0;
for (Iterator annotIter = annotJsonArray.iterator(); annotIter
.hasNext();)
{
JSONObject annot = annotIter.next();
if (annot == null)
{
annotations[count] = null;
}
else
{
float val = annot.get("value") == null ? null : Float
.valueOf(annot.get("value").toString());
String desc = annot.get("description") == null ? null : annot
.get("description").toString();
char ss = annot.get("secondaryStructure") == null ? ' '
: annot.get("secondaryStructure").toString().charAt(0);
String displayChar = annot.get("displayCharacter").toString();
annotations[count] = new Annotation(displayChar, desc, ss, val);
}
++count;
}
AlignmentAnnotation alignAnnot = new AlignmentAnnotation(alAnnot
.get("label").toString(), alAnnot.get("description")
.toString(), annotations);
this.annotations.add(alignAnnot);
}
} catch (Exception e)
{
e.printStackTrace();
}
return this;
}
@SuppressWarnings("unchecked")
private void parseFeatures(JSONArray jsonSeqFeatures)
{
if (jsonSeqFeatures != null)
{
for (Iterator seqFeatureItr = jsonSeqFeatures.iterator(); seqFeatureItr
.hasNext();)
{
JSONObject jsonFeature = seqFeatureItr.next();
Long begin = (Long) jsonFeature.get("xStart");
Long end = (Long) jsonFeature.get("xEnd");
String type = (String) jsonFeature.get("type");
String featureGrp = (String) jsonFeature.get("featureGroup");
String descripiton = (String) jsonFeature.get("description");
String seqRef = (String) jsonFeature.get("sequenceRef");
Float score = Float.valueOf(jsonFeature.get("score").toString());
// Hashtable otherDetails = (Hashtable) jsonFeature
// .get("otherDetails");
// sequenceFeature.otherDetails = otherDetails;
Sequence seq = seqMap.get(seqRef);
SequenceFeature sequenceFeature = new SequenceFeature();
JSONArray linksJsonArray = (JSONArray) jsonFeature.get("links");
if (linksJsonArray != null && linksJsonArray.size() > 0)
{
Iterator linkList = linksJsonArray.iterator();
while (linkList.hasNext())
{
String link = linkList.next();
sequenceFeature.addLink(link);
}
}
sequenceFeature.setFeatureGroup(featureGrp);
sequenceFeature.setScore(score);
sequenceFeature.setDescription(descripiton);
sequenceFeature.setType(type);
sequenceFeature.setBegin(seq.findPosition(begin.intValue()));
sequenceFeature.setEnd(seq.findPosition(end.intValue()) - 1);
seq.addSequenceFeature(sequenceFeature);
}
}
}
public static ColourSchemeI getJalviewColorScheme(
String bioJsColourSchemeName)
{
ColourSchemeI jalviewColor = null;
for (JalviewBioJsColorSchemeMapper cs : JalviewBioJsColorSchemeMapper
.values())
{
if (cs.getBioJsName().equalsIgnoreCase(bioJsColourSchemeName))
{
jalviewColor = cs.getJvColourScheme();
break;
}
}
return jalviewColor;
}
public void applySettingsToAlignFrame(AlignViewControllerGuiI af)
{
af.setShowSeqFeatures(isShowSeqFeatures());
af.changeColour(getColourScheme());
af.setMenusForViewport();
}
public String getGlobalColorScheme()
{
return globalColorScheme;
}
public void setGlobalColorScheme(String globalColorScheme)
{
this.globalColorScheme = globalColorScheme;
}
public ColourSchemeI getColourScheme()
{
return colourScheme;
}
public void setColourScheme(ColourSchemeI colourScheme)
{
this.colourScheme = colourScheme;
}
public FeaturesDisplayedI getDisplayedFeatures()
{
return displayedFeatures;
}
public void setDisplayedFeatures(FeaturesDisplayedI displayedFeatures)
{
this.displayedFeatures = displayedFeatures;
}
public JSONExportSettings getJsonExportSettings()
{
return jsonExportSettings;
}
public void setJsonExportSettings(JSONExportSettings jsonExportSettings)
{
this.jsonExportSettings = jsonExportSettings;
}
public static String getJSONData(AlignViewportI av)
{
JSONFile jsonFile = new JSONFile();
jsonFile.setViewport(av);
jsonFile.seqGroups = av.getAlignment().getGroups();
jsonFile.setDisplayedFeatures(av.getFeaturesDisplayed());
for (SequenceI seq : av.getAlignment().getSequences())
{
jsonFile.seqs.add(seq);
}
// Add non auto calculated annotation to AlignFile
for (AlignmentAnnotation annot : av.getAlignment()
.getAlignmentAnnotation())
{
if (annot != null && !annot.autoCalculated)
{
if (annot.label.equals("PDB.CATempFactor"))
{
continue;
}
jsonFile.annotations.add(annot);
}
}
String jsonString = jsonFile.print();
return jsonString;
}
public boolean isShowSeqFeatures()
{
return showSeqFeatures;
}
public void setShowSeqFeatures(boolean showSeqFeatures)
{
this.showSeqFeatures = showSeqFeatures;
}
public Vector getAnnotations()
{
return annotations;
}
public class JSONExportSettings
{
private boolean exportSequence;
private boolean exportSequenceFeatures;
private boolean exportAnnotations;
private boolean exportGroups;
private boolean exportJalviewSettings;
public boolean isExportSequence()
{
return exportSequence;
}
public void setExportSequence(boolean exportSequence)
{
this.exportSequence = exportSequence;
}
public boolean isExportSequenceFeatures()
{
return exportSequenceFeatures;
}
public void setExportSequenceFeatures(boolean exportSequenceFeatures)
{
this.exportSequenceFeatures = exportSequenceFeatures;
}
public boolean isExportAnnotations()
{
return exportAnnotations;
}
public void setExportAnnotations(boolean exportAnnotations)
{
this.exportAnnotations = exportAnnotations;
}
public boolean isExportGroups()
{
return exportGroups;
}
public void setExportGroups(boolean exportGroups)
{
this.exportGroups = exportGroups;
}
public boolean isExportJalviewSettings()
{
return exportJalviewSettings;
}
public void setExportJalviewSettings(boolean exportJalviewSettings)
{
this.exportJalviewSettings = exportJalviewSettings;
}
}
}