X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FJalview2XML.java;h=945651b9dcefd8ec123d90d1a3acb23a1293bb57;hb=8dfdafee89d06dd397c392619b4b285f0dc35430;hp=e65f37d23474bc7a5f31ec9b7c5068c251c92fa7;hpb=51eebe77f74dda2f4ff336dfe0fea0ed68b86e5b;p=jalview.git diff --git a/src/jalview/gui/Jalview2XML.java b/src/jalview/gui/Jalview2XML.java old mode 100755 new mode 100644 index e65f37d..945651b --- a/src/jalview/gui/Jalview2XML.java +++ b/src/jalview/gui/Jalview2XML.java @@ -1,1462 +1,5344 @@ /* - * Jalview - A Sequence Alignment Editor and Viewer - * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle - * - * This program 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 2 + * 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. - * - * This program 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. - * + * + * 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. */ package jalview.gui; - -import jalview.schemes.*; - -import jalview.gui.*; - -import java.io.*; - -import java.net.*; - -import java.util.*; - -import java.util.jar.*; - -import javax.swing.*; - -import org.exolab.castor.xml.*; - -import jalview.schemabinding.version2.*; - - - +import jalview.api.FeatureColourI; +import jalview.api.ViewStyleI; +import jalview.api.structures.JalviewStructureDisplayI; +import jalview.bin.Cache; +import jalview.datamodel.AlignedCodonFrame; +import jalview.datamodel.Alignment; +import jalview.datamodel.AlignmentAnnotation; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.PDBEntry; +import jalview.datamodel.RnaViewerModel; +import jalview.datamodel.SequenceGroup; +import jalview.datamodel.SequenceI; +import jalview.datamodel.StructureViewerModel; +import jalview.datamodel.StructureViewerModel.StructureData; +import jalview.ext.varna.RnaModel; +import jalview.gui.StructureViewer.ViewerType; +import jalview.schemabinding.version2.AlcodMap; +import jalview.schemabinding.version2.AlcodonFrame; +import jalview.schemabinding.version2.Annotation; +import jalview.schemabinding.version2.AnnotationColours; +import jalview.schemabinding.version2.AnnotationElement; +import jalview.schemabinding.version2.CalcIdParam; +import jalview.schemabinding.version2.DBRef; +import jalview.schemabinding.version2.Features; +import jalview.schemabinding.version2.Group; +import jalview.schemabinding.version2.HiddenColumns; +import jalview.schemabinding.version2.JGroup; +import jalview.schemabinding.version2.JSeq; +import jalview.schemabinding.version2.JalviewModel; +import jalview.schemabinding.version2.JalviewModelSequence; +import jalview.schemabinding.version2.MapListFrom; +import jalview.schemabinding.version2.MapListTo; +import jalview.schemabinding.version2.Mapping; +import jalview.schemabinding.version2.MappingChoice; +import jalview.schemabinding.version2.OtherData; +import jalview.schemabinding.version2.PdbentryItem; +import jalview.schemabinding.version2.Pdbids; +import jalview.schemabinding.version2.Property; +import jalview.schemabinding.version2.RnaViewer; +import jalview.schemabinding.version2.SecondaryStructure; +import jalview.schemabinding.version2.Sequence; +import jalview.schemabinding.version2.SequenceSet; +import jalview.schemabinding.version2.SequenceSetProperties; +import jalview.schemabinding.version2.Setting; +import jalview.schemabinding.version2.StructureState; +import jalview.schemabinding.version2.ThresholdLine; +import jalview.schemabinding.version2.Tree; +import jalview.schemabinding.version2.UserColours; +import jalview.schemabinding.version2.Viewport; +import jalview.schemes.AnnotationColourGradient; +import jalview.schemes.ColourSchemeI; +import jalview.schemes.ColourSchemeProperty; +import jalview.schemes.FeatureColour; +import jalview.schemes.ResidueColourScheme; +import jalview.schemes.ResidueProperties; +import jalview.schemes.UserColourScheme; +import jalview.structure.StructureSelectionManager; +import jalview.structures.models.AAStructureBindingModel; +import jalview.util.MessageManager; +import jalview.util.Platform; +import jalview.util.StringUtils; +import jalview.util.jarInputStreamProvider; +import jalview.viewmodel.AlignmentViewport; +import jalview.viewmodel.seqfeatures.FeatureRendererSettings; +import jalview.viewmodel.seqfeatures.FeaturesDisplayed; +import jalview.ws.jws2.Jws2Discoverer; +import jalview.ws.jws2.dm.AAConSettings; +import jalview.ws.jws2.jabaws2.Jws2Instance; +import jalview.ws.params.ArgumentI; +import jalview.ws.params.AutoCalcSetting; +import jalview.ws.params.WsParamSetI; + +import java.awt.Color; +import java.awt.Rectangle; +import java.io.BufferedReader; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.Vector; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; +import java.util.jar.JarOutputStream; + +import javax.swing.JInternalFrame; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; + +import org.exolab.castor.xml.Marshaller; +import org.exolab.castor.xml.Unmarshaller; /** - * DOCUMENT ME! - * + * Write out the current jalview desktop state as a Jalview XML stream. + * + * Note: the vamsas objects referred to here are primitive versions of the + * VAMSAS project schema elements - they are not the same and most likely never + * will be :) + * * @author $author$ - * @version $Revision$ + * @version $Revision: 1.134 $ */ public class Jalview2XML { - // SAVES SEVERAL ALIGNEMENT WINDOWS TO SAME JARFILE - public void SaveState(File statefile) + private static final String VIEWER_PREFIX = "viewer_"; + + private static final String RNA_PREFIX = "rna_"; + + private static final String UTF_8 = "UTF-8"; + + // use this with nextCounter() to make unique names for entities + private int counter = 0; + + /* + * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps + * of sequence objects are created. + */ + IdentityHashMap seqsToIds = null; + + /** + * jalview XML Sequence ID to jalview sequence object reference (both dataset + * and alignment sequences. Populated as XML reps of sequence objects are + * created.) + */ + Map seqRefIds = null; + + Vector frefedSequence = null; + + boolean raiseGUI = true; // whether errors are raised in dialog boxes or not + + /* + * Map of reconstructed AlignFrame objects that appear to have come from + * SplitFrame objects (have a dna/protein complement view). + */ + private Map splitFrameCandidates = new HashMap(); + + /* + * Map from displayed rna structure models to their saved session state jar + * entry names + */ + private Map rnaSessions = new HashMap(); + + /** + * create/return unique hash string for sq + * + * @param sq + * @return new or existing unique string for sq + */ + String seqHash(SequenceI sq) + { + if (seqsToIds == null) { - long creation = System.currentTimeMillis(); - JInternalFrame[] frames = Desktop.desktop.getAllFrames(); + initSeqRefs(); + } + if (seqsToIds.containsKey(sq)) + { + return seqsToIds.get(sq); + } + else + { + // create sequential key + String key = "sq" + (seqsToIds.size() + 1); + key = makeHashCode(sq, key); // check we don't have an external reference + // for it already. + seqsToIds.put(sq, key); + return key; + } + } - if (frames == null) - { - return; - } + void clearSeqRefs() + { + if (_cleartables) + { + if (seqRefIds != null) + { + seqRefIds.clear(); + } + if (seqsToIds != null) + { + seqsToIds.clear(); + } + // seqRefIds = null; + // seqsToIds = null; + } + else + { + // do nothing + warn("clearSeqRefs called when _cleartables was not set. Doing nothing."); + // seqRefIds = new Hashtable(); + // seqsToIds = new IdentityHashMap(); + } + } - try - { - FileOutputStream fos = new FileOutputStream(statefile); - JarOutputStream jout = new JarOutputStream(fos); + void initSeqRefs() + { + if (seqsToIds == null) + { + seqsToIds = new IdentityHashMap(); + } + if (seqRefIds == null) + { + seqRefIds = new HashMap(); + } + } - //NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS - //////////////////////////////////////////////////// - PrintWriter out = new PrintWriter(new OutputStreamWriter(jout, - "UTF-8")); + public Jalview2XML() + { + } - Vector shortNames = new Vector(); + public Jalview2XML(boolean raiseGUI) + { + this.raiseGUI = raiseGUI; + } - //REVERSE ORDER - for (int i = frames.length - 1; i > -1; i--) + public void resolveFrefedSequences() + { + if (frefedSequence.size() > 0) + { + int r = 0, rSize = frefedSequence.size(); + while (r < rSize) + { + Object[] ref = frefedSequence.elementAt(r); + if (ref != null) + { + String sref = (String) ref[0]; + if (seqRefIds.containsKey(sref)) + { + if (ref[1] instanceof jalview.datamodel.Mapping) + { + SequenceI seq = seqRefIds.get(sref); + while (seq.getDatasetSequence() != null) + { + seq = seq.getDatasetSequence(); + } + ((jalview.datamodel.Mapping) ref[1]).setTo(seq); + } + else { - if (frames[i] instanceof AlignFrame) + if (ref[1] instanceof jalview.datamodel.AlignedCodonFrame) + { + SequenceI seq = seqRefIds.get(sref); + while (seq.getDatasetSequence() != null) { - AlignFrame af = (AlignFrame) frames[i]; - - String shortName = af.getTitle(); - - if (shortName.indexOf(File.separatorChar) > -1) - { - shortName = shortName.substring(shortName.lastIndexOf( - File.separatorChar) + 1); - } - - int count = 1; - - while (shortNames.contains(shortName)) - { - if (shortName.endsWith("_" + (count - 1))) - { - shortName = shortName.substring(0, - shortName.lastIndexOf("_")); - } - - shortName = shortName.concat("_" + count); - count++; - } - - shortNames.addElement(shortName); - - if (!shortName.endsWith(".xml")) - { - shortName = shortName + ".xml"; - } - - SaveState(af, creation, shortName, jout, out); + seq = seq.getDatasetSequence(); + } + if (ref[2] != null + && ref[2] instanceof jalview.datamodel.Mapping) + { + jalview.datamodel.Mapping mp = (jalview.datamodel.Mapping) ref[2]; + ((jalview.datamodel.AlignedCodonFrame) ref[1]).addMap( + seq, mp.getTo(), mp.getMap()); + } + else + { + System.err + .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for AlcodonFrames involving " + + ref[2].getClass() + " type objects."); } + } + else + { + System.err + .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for " + + ref[1].getClass() + " type objects."); + } } - - out.close(); - jout.close(); + frefedSequence.remove(r); + rSize--; + } + else + { + System.err + .println("IMPLEMENTATION WARNING: Unresolved forward reference for hash string " + + ref[0] + + " with objecttype " + + ref[1].getClass()); + r++; + } } - catch (Exception ex) + else { - ex.printStackTrace(); + // empty reference + frefedSequence.remove(r); + rSize--; } + } } + } + + /** + * This maintains a map of viewports, the key being the seqSetId. Important to + * set historyItem and redoList for multiple views + */ + Map viewportsAdded = new HashMap(); + + Map annotationIds = new HashMap(); + + String uniqueSetSuffix = ""; + + /** + * List of pdbfiles added to Jar + */ + List pdbfiles = null; + + // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE + public void saveState(File statefile) + { + FileOutputStream fos = null; + try + { + fos = new FileOutputStream(statefile); + JarOutputStream jout = new JarOutputStream(fos); + saveState(jout); - // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW - public void SaveAlignment(AlignFrame af, String jarFile, - String fileName) + } catch (Exception e) { + // TODO: inform user of the problem - they need to know if their data was + // not saved ! + if (errorMessage == null) + { + errorMessage = "Couldn't write Jalview Archive to output file '" + + statefile + "' - See console error log for details"; + } + else + { + errorMessage += "(output file was '" + statefile + "')"; + } + e.printStackTrace(); + } finally + { + if (fos != null) + { try { - FileOutputStream fos = new FileOutputStream(jarFile); - JarOutputStream jout = new JarOutputStream(fos); - - //NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS - //////////////////////////////////////////////////// - PrintWriter out = new PrintWriter(new OutputStreamWriter(jout, - "UTF-8")); - - SaveState(af, System.currentTimeMillis(), fileName, jout, out); - out.close(); - jout.close(); - } - catch (Exception ex) + fos.close(); + } catch (IOException e) { - ex.printStackTrace(); + // ignore } + } + } + reportErrors(); + } + + /** + * Writes a jalview project archive to the given Jar output stream. + * + * @param jout + */ + public void saveState(JarOutputStream jout) + { + AlignFrame[] frames = Desktop.getAlignFrames(); + + if (frames == null) + { + return; } - /** - * DOCUMENT ME! - * - * @param af DOCUMENT ME! - * @param timeStamp DOCUMENT ME! - * @param fileName DOCUMENT ME! - * @param jout DOCUMENT ME! - * @param out DOCUMENT ME! + Hashtable dsses = new Hashtable(); + + /* + * ensure cached data is clear before starting */ - public void SaveState(AlignFrame af, long timeStamp, - String fileName, JarOutputStream jout, PrintWriter out) + // todo tidy up seqRefIds, seqsToIds initialisation / reset + rnaSessions.clear(); + splitFrameCandidates.clear(); + + try { - Vector seqids = new Vector(); - Vector userColours = new Vector(); - AlignViewport av = af.viewport; + // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS + // ////////////////////////////////////////////////// + + List shortNames = new ArrayList(); + List viewIds = new ArrayList(); - JalviewModel object = new JalviewModel(); - object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel()); + // REVERSE ORDER + for (int i = frames.length - 1; i > -1; i--) + { + AlignFrame af = frames[i]; + // skip ? + if (skipList != null + && skipList + .containsKey(af.getViewport().getSequenceSetId())) + { + continue; + } - object.setCreationDate(new java.util.Date(timeStamp)); - object.setVersion(jalview.bin.Cache.getProperty("VERSION")); + String shortName = makeFilename(af, shortNames); - jalview.datamodel.AlignmentI jal = af.viewport.alignment; - jalview.datamodel.AlignmentI jalhidden = null; + int ap, apSize = af.alignPanels.size(); - if(av.hasHiddenRows) + for (ap = 0; ap < apSize; ap++) { - jalhidden = jal; - jal = jal.getHiddenSequences().getFullAlignment(); - } + AlignmentPanel apanel = af.alignPanels.get(ap); + String fileName = apSize == 1 ? shortName : ap + shortName; + if (!fileName.endsWith(".xml")) + { + fileName = fileName + ".xml"; + } + saveState(apanel, fileName, jout, viewIds); + + String dssid = getDatasetIdRef(af.getViewport().getAlignment() + .getDataset()); + if (!dsses.containsKey(dssid)) + { + dsses.put(dssid, af); + } + } + } - SequenceSet vamsasSet = new SequenceSet(); - Sequence vamsasSeq; - JalviewModelSequence jms = new JalviewModelSequence(); + writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix, + jout); - vamsasSet.setGapChar(jal.getGapCharacter() + ""); + try + { + jout.flush(); + } catch (Exception foo) + { + } + ; + jout.close(); + } catch (Exception ex) + { + // TODO: inform user of the problem - they need to know if their data was + // not saved ! + if (errorMessage == null) + { + errorMessage = "Couldn't write Jalview Archive - see error output for details"; + } + ex.printStackTrace(); + } + } + + /** + * Generates a distinct file name, based on the title of the AlignFrame, by + * appending _n for increasing n until an unused name is generated. The new + * name (without its extension) is added to the list. + * + * @param af + * @param namesUsed + * @return the generated name, with .xml extension + */ + protected String makeFilename(AlignFrame af, List namesUsed) + { + String shortName = af.getTitle(); + + if (shortName.indexOf(File.separatorChar) > -1) + { + shortName = shortName.substring(shortName + .lastIndexOf(File.separatorChar) + 1); + } - JSeq jseq; - Vector pdbfiles = null; + int count = 1; - //SAVE SEQUENCES - int id = 0; - for (int i = 0; i < jal.getHeight(); i++) - { - seqids.add(jal.getSequenceAt(i)); - vamsasSeq = new Sequence(); - vamsasSeq.setId(id + ""); - vamsasSeq.setName(jal.getSequenceAt(i).getName()); - vamsasSeq.setSequence(jal.getSequenceAt(i).getSequence()); - vamsasSeq.setDescription(jal.getSequenceAt(i).getDescription()); + while (namesUsed.contains(shortName)) + { + if (shortName.endsWith("_" + (count - 1))) + { + shortName = shortName.substring(0, shortName.lastIndexOf("_")); + } - if(jal.getSequenceAt(i).getDatasetSequence().getDBRef()!=null) - { - jalview.datamodel.DBRefEntry [] dbrefs = - jal.getSequenceAt(i).getDatasetSequence().getDBRef(); + shortName = shortName.concat("_" + count); + count++; + } - for(int d=0; d dsses = new Hashtable(); + List viewIds = new ArrayList(); + + for (AlignmentPanel apanel : af.alignPanels) + { + String jfileName = apSize == 1 ? fileName : fileName + ap; + ap++; + if (!jfileName.endsWith(".xml")) + { + jfileName = jfileName + ".xml"; + } + saveState(apanel, jfileName, jout, viewIds); + String dssid = getDatasetIdRef(af.getViewport().getAlignment() + .getDataset()); + if (!dsses.containsKey(dssid)) + { + dsses.put(dssid, af); + } + } + writeDatasetFor(dsses, fileName, jout); + try + { + jout.flush(); + } catch (Exception foo) + { + } + ; + jout.close(); + return true; + } catch (Exception ex) + { + errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details"; + ex.printStackTrace(); + return false; + } + } - jseq.setId(id); + private void writeDatasetFor(Hashtable dsses, + String fileName, JarOutputStream jout) + { - if (av.hasHiddenRows) - { - jseq.setHidden(jalhidden.getHiddenSequences().isHidden( - jal.getSequenceAt(i))); + for (String dssids : dsses.keySet()) + { + AlignFrame _af = dsses.get(dssids); + String jfileName = fileName + " Dataset for " + _af.getTitle(); + if (!jfileName.endsWith(".xml")) + { + jfileName = jfileName + ".xml"; + } + saveState(_af.alignPanel, jfileName, true, jout, null); + } + } + + /** + * create a JalviewModel from an alignment view and marshall it to a + * JarOutputStream + * + * @param ap + * panel to create jalview model for + * @param fileName + * name of alignment panel written to output stream + * @param jout + * jar output stream + * @param viewIds + * @param out + * jar entry name + */ + public JalviewModel saveState(AlignmentPanel ap, String fileName, + JarOutputStream jout, List viewIds) + { + return saveState(ap, fileName, false, jout, viewIds); + } + + /** + * create a JalviewModel from an alignment view and marshall it to a + * JarOutputStream + * + * @param ap + * panel to create jalview model for + * @param fileName + * name of alignment panel written to output stream + * @param storeDS + * when true, only write the dataset for the alignment, not the data + * associated with the view. + * @param jout + * jar output stream + * @param out + * jar entry name + */ + public JalviewModel saveState(AlignmentPanel ap, String fileName, + boolean storeDS, JarOutputStream jout, List viewIds) + { + if (viewIds == null) + { + viewIds = new ArrayList(); + } - if(jal.getSequenceAt(i).getHiddenSequences()!=null) - { - jalview.datamodel.SequenceI [] reps = - jal.getSequenceAt(i).getHiddenSequences().getSequencesInOrder(jal); + initSeqRefs(); - for(int h=0; h userColours = new ArrayList(); + AlignViewport av = ap.av; - if(jal.getSequenceAt(i).getDatasetSequence().getSequenceFeatures()!=null) - { - jalview.datamodel.SequenceFeature[] sf - = jal.getSequenceAt(i).getDatasetSequence().getSequenceFeatures(); - int index = 0; - while(index < sf.length) - { - Features features = new Features(); - - features.setBegin(sf[index].getBegin()); - features.setEnd(sf[index].getEnd()); - features.setDescription(sf[index].getDescription()); - features.setType(sf[index].getType()); - features.setFeatureGroup(sf[index].getFeatureGroup()); - features.setScore(sf[index].getScore()); - if(sf[index].links!=null) - { - for(int l=0; l