X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FJalview2XML.java;h=ebf7aba0e1addc316c183227aac793c79b4e8c4d;hb=60f2d6c034560415fd0139c8bc7df0c19cae1186;hp=4f764451008c1e67f475d4f56cea036ffc2374b1;hpb=0186df13dc1482c575ce210c3b854186f923b243;p=jalview.git diff --git a/src/jalview/gui/Jalview2XML.java b/src/jalview/gui/Jalview2XML.java index 4f76445..ebf7aba 100755 --- a/src/jalview/gui/Jalview2XML.java +++ b/src/jalview/gui/Jalview2XML.java @@ -48,10 +48,55 @@ import jalview.structure.StructureSelectionManager; */ public class Jalview2XML { - - Hashtable seqRefIds = null; + /** + * create/return unique hash string for sq + * @param sq + * @return new or existing unique string for sq + */ + String seqHash(SequenceI sq) + { + if (seqsToIds==null) + { + initSeqRefs(); + } + if (seqsToIds.containsKey(sq)) + { + return (String) seqsToIds.get(sq); + } else { + // create sequential key + String key = "sq"+(seqsToIds.size()+1); + seqsToIds.put(sq, key); + return key; + } + } + void clearSeqRefs() + { + seqRefIds.clear(); + seqsToIds.clear(); + } + void initSeqRefs() + { + if (seqsToIds==null) + { + seqsToIds = new IdentityHashMap(); + } + if (seqRefIds==null) + { + seqRefIds = new Hashtable(); + } + } + java.util.IdentityHashMap seqsToIds = null; // SequenceI->key resolution + java.util.Hashtable seqRefIds = null; // key->SequenceI resolution Vector frefedSequence = null; + boolean raiseGUI = true; // whether errors are raised in dialog boxes or not + public Jalview2XML() + { + } + public Jalview2XML(boolean raiseGUI) + { + this.raiseGUI = raiseGUI; + } public void resolveFrefedSequences() { @@ -77,15 +122,40 @@ public class Jalview2XML } else { - System.err - .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for " - + ref[1].getClass() + " type objects."); + if (ref[1] instanceof jalview.datamodel.AlignedCodonFrame) + { + SequenceI seq = (SequenceI) seqRefIds.get(sref); + while (seq.getDatasetSequence() != null) + { + 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."); + } + frefedSequence.remove(r); + rSize--; } - frefedSequence.remove(r); - rSize--; } else { + System.err.println("IMPLEMENTATION WARNING: Unresolved forward reference for hash string "+ref[0]+" with objecttype "+ref[1].getClass()); r++; } } @@ -131,8 +201,8 @@ public class Jalview2XML //NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS //////////////////////////////////////////////////// - PrintWriter out = new PrintWriter(new OutputStreamWriter(jout, - "UTF-8")); + //NOTE ALSO new PrintWriter must be used for each new JarEntry + PrintWriter out = null; Vector shortNames = new Vector(); @@ -177,14 +247,17 @@ public class Jalview2XML { AlignmentPanel apanel = (AlignmentPanel) af.alignPanels .elementAt(ap); + String fileName = apSize == 1 ? shortName : ap + shortName; + if (!fileName.endsWith(".xml")) + { + fileName = fileName + ".xml"; + } - SaveState(apanel, apSize == 1 ? shortName : ap + shortName, - jout, out); + SaveState(apanel, fileName, jout); } } } - - out.close(); + try { jout.flush(); } catch (Exception foo) {}; jout.close(); } catch (Exception ex) { @@ -202,17 +275,19 @@ public class Jalview2XML int ap, apSize = af.alignPanels.size(); FileOutputStream fos = new FileOutputStream(jarFile); JarOutputStream jout = new JarOutputStream(fos); - PrintWriter out = new PrintWriter(new OutputStreamWriter(jout, - "UTF-8")); for (ap = 0; ap < apSize; ap++) { AlignmentPanel apanel = (AlignmentPanel) af.alignPanels .elementAt(ap); - - SaveState(apanel, apSize == 1 ? fileName : fileName + ap, jout, out); + String jfileName = apSize == 1 ? fileName : fileName + ap; + if (!jfileName.endsWith(".xml")) + { + jfileName = jfileName + ".xml"; + } + SaveState(apanel, jfileName, jout); } - out.close(); + try { jout.flush(); } catch (Exception foo) {}; jout.close(); return true; } catch (Exception ex) @@ -223,22 +298,19 @@ public class Jalview2XML } /** - * DOCUMENT ME! + * create a JalviewModel from an algnment view and marshall it + * to a JarOutputStream * - * @param af DOCUMENT ME! - * @param timeStamp DOCUMENT ME! - * @param fileName DOCUMENT ME! - * @param jout DOCUMENT ME! - * @param out DOCUMENT ME! + * @param ap panel to create jalview model for + * @param fileName name of alignment panel written to output stream + * @param jout jar output stream + * @param out jar entry name */ public JalviewModel SaveState(AlignmentPanel ap, String fileName, - JarOutputStream jout, PrintWriter out) + JarOutputStream jout) { - if (seqRefIds == null) - { - seqRefIds = new Hashtable(); - } - + initSeqRefs(); + Vector userColours = new Vector(); AlignViewport av = ap.av; @@ -283,22 +355,29 @@ public class Jalview2XML JSeq jseq; //SAVE SEQUENCES - int id = 0; + String id = ""; jalview.datamodel.SequenceI jds; for (int i = 0; i < jal.getHeight(); i++) { jds = jal.getSequenceAt(i); - id = jds.hashCode(); - - if (seqRefIds.get(id + "") != null) - { - + id = seqHash(jds); + + if (seqRefIds.get(id) != null) + { + // This happens for two reasons: 1. multiple views are being serialised. 2. the hashCode has collided with another sequence's code. This DOES HAPPEN! (PF00072.15.stk does this) + // JBPNote: Uncomment to debug writing out of files that do not read back in due to ArrayOutOfBoundExceptions. + //System.err.println("vamsasSeq backref: "+id+""); + //System.err.println(jds.getName()+" "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString()); + //System.err.println("Hashcode: "+seqHash(jds)); + //SequenceI rsq = (SequenceI) seqRefIds.get(id + ""); + //System.err.println(rsq.getName()+" "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString()); + //System.err.println("Hashcode: "+seqHash(rsq)); } else { vamsasSeq = createVamsasSequence(id, jds); vamsasSet.addSequence(vamsasSeq); - seqRefIds.put(id + "", jal.getSequenceAt(i)); + seqRefIds.put(id, jds); } jseq = new JSeq(); @@ -306,7 +385,7 @@ public class Jalview2XML jseq.setEnd(jds.getEnd()); jseq.setColour(av.getSequenceColour(jds).getRGB()); - jseq.setId(id); + jseq.setId(id); // jseq id should be a string not a number if (av.hasHiddenRows) { @@ -441,6 +520,7 @@ public class Jalview2XML DataOutputStream dout = new DataOutputStream(jout); dout.write(data, 0, data.length); + dout.flush(); jout.closeEntry(); } } catch (Exception ex) @@ -722,7 +802,7 @@ public class Jalview2XML { jalview.datamodel.Sequence seq = (jalview.datamodel.Sequence) sg .getSequenceAt(s); - groups[i].addSeq(seq.hashCode()); + groups[i].addSeq(seqHash(seq)); } } @@ -919,47 +999,47 @@ public class Jalview2XML object.setJalviewModelSequence(jms); object.getVamsasModel().addSequenceSet(vamsasSet); - if (out != null) + if (jout!=null && fileName!=null) { - //We may not want to right the object to disk, + //We may not want to write the object to disk, //eg we can copy the alignViewport to a new view object //using save and then load try { - if (!fileName.endsWith(".xml")) - { - fileName = fileName + ".xml"; - } - JarEntry entry = new JarEntry(fileName); jout.putNextEntry(entry); - - object.marshal(out); + PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout, + "UTF-8")); + org.exolab.castor.xml.Marshaller marshaller = new org.exolab.castor.xml.Marshaller(pout); + marshaller.marshal(object); + pout.flush(); + jout.closeEntry(); } catch (Exception ex) { + // TODO: raise error in GUI if marshalling failed. ex.printStackTrace(); } } return object; } - private Sequence createVamsasSequence(int id, SequenceI jds) + private Sequence createVamsasSequence(String id, SequenceI jds) { return createVamsasSequence(true, id, jds, null); } - private Sequence createVamsasSequence(boolean recurse, int id, + private Sequence createVamsasSequence(boolean recurse, String id, SequenceI jds, SequenceI parentseq) { Sequence vamsasSeq = new Sequence(); - vamsasSeq.setId(id + ""); + vamsasSeq.setId(id); vamsasSeq.setName(jds.getName()); vamsasSeq.setSequence(jds.getSequenceAsString()); vamsasSeq.setDescription(jds.getDescription()); jalview.datamodel.DBRefEntry[] dbrefs = null; if (jds.getDatasetSequence() != null) { - vamsasSeq.setDsseqid(jds.getDatasetSequence().hashCode() + ""); + vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence())); if (jds.getDatasetSequence().getDBRef() != null) { dbrefs = jds.getDatasetSequence().getDBRef(); @@ -967,7 +1047,7 @@ public class Jalview2XML } else { - vamsasSeq.setDsseqid(id + ""); // so we can tell which sequences really are dataset sequences only + vamsasSeq.setDsseqid(id); // so we can tell which sequences really are dataset sequences only dbrefs = jds.getDBRef(); } if (dbrefs != null) @@ -1024,24 +1104,24 @@ public class Jalview2XML && (parentseq != jmp.getTo() || parentseq .getDatasetSequence() != jmp.getTo())) { - mpc.setSequence(createVamsasSequence(false, jmp.getTo() - .hashCode(), jmp.getTo(), jds)); + mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()) + , jmp.getTo(), jds)); } else { - long jmpid = 0; + String jmpid = ""; SequenceI ps = null; if (parentseq != jmp.getTo() && parentseq.getDatasetSequence() != jmp.getTo()) { // chaining dbref rather than a handshaking one - jmpid = (ps = jmp.getTo()).hashCode(); + jmpid = seqHash(ps = jmp.getTo()); } else { - jmpid = (ps = parentseq).hashCode(); + jmpid = seqHash(ps = parentseq); } - mpc.setDseqFor("" + jmpid); + mpc.setDseqFor(jmpid); if (!seqRefIds.containsKey(mpc.getDseqFor())) { jalview.bin.Cache.log.debug("creatign new DseqFor ID"); @@ -1226,9 +1306,22 @@ public class Jalview2XML + ex + "\n"); } catch (Exception ex) { + System.err.println("Parsing as Jalview Version 2 file failed."); + ex.printStackTrace(System.err); + //Is Version 1 Jar file? - af = new Jalview2XML_V1().LoadJalviewAlign(file); + try { + af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(file); + } catch (Exception ex2) { + System.err.println("Exception whilst loading as jalviewXMLV1:"); + ex2.printStackTrace(); + af = null; + } + if (Desktop.instance != null) + { + Desktop.instance.stopLoading(); + } if (af != null) { System.out.println("Successfully loaded archive file"); @@ -1254,15 +1347,20 @@ public class Jalview2XML if (errorMessage != null) { final String finalErrorMessage = errorMessage; - javax.swing.SwingUtilities.invokeLater(new Runnable() - { - public void run() + if (raiseGUI) + { + javax.swing.SwingUtilities.invokeLater(new Runnable() + { + public void run() { JOptionPane.showInternalMessageDialog(Desktop.desktop, finalErrorMessage, "Error loading Jalview file", JOptionPane.WARNING_MESSAGE); } }); + } else { + System.err.println("Problem loading Jalview file: "+errorMessage); + } } return af; @@ -1307,6 +1405,7 @@ public class Jalview2XML { out.println(data); } + try { out.flush(); } catch (Exception foo) {}; out.close(); alreadyLoadedPDB.put(pdbId, outFile.getAbsolutePath()); @@ -1341,6 +1440,7 @@ public class Jalview2XML boolean multipleView = false; JSeq[] JSEQ = object.getJalviewModelSequence().getJSeq(); + int vi=0; // counter in vamsasSeq array for (int i = 0; i < JSEQ.length; i++) { String seqId = JSEQ[i].getId() + ""; @@ -1352,14 +1452,15 @@ public class Jalview2XML } else { - jseq = new jalview.datamodel.Sequence(vamsasSeq[i].getName(), - vamsasSeq[i].getSequence()); - jseq.setDescription(vamsasSeq[i].getDescription()); + jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(), + vamsasSeq[vi].getSequence()); + jseq.setDescription(vamsasSeq[vi].getDescription()); jseq.setStart(JSEQ[i].getStart()); jseq.setEnd(JSEQ[i].getEnd()); jseq.setVamsasId(uniqueSetSuffix + seqId); - seqRefIds.put(vamsasSeq[i].getId(), jseq); + seqRefIds.put(vamsasSeq[vi].getId()+"", jseq); tmpseqs.add(jseq); + vi++; } if (JSEQ[i].getHidden()) @@ -1499,15 +1600,19 @@ public class Jalview2XML SequenceI dnaseq = (SequenceI) seqRefIds .get(maps[m].getDnasq()); // Load Mapping + jalview.datamodel.Mapping mapping = null; // attach to dna sequence reference. + if (maps[m].getMapping() != null) + { + mapping = addMapping(maps[m] + .getMapping()); + } if (dnaseq != null) { - if (maps[m].getMapping() != null) - { - jalview.datamodel.Mapping mapping = addMapping(maps[m] - .getMapping()); cf.addMap(dnaseq, mapping.getTo(), mapping.getMap()); - } + } else { + // defer to later + frefedSequence.add(new Object[] { maps[m].getDnasq(), cf, mapping}); } } } @@ -1573,9 +1678,14 @@ public class Jalview2XML .getSecondaryStructure() == null || ae[aa] .getSecondaryStructure().length() == 0) ? ' ' : ae[aa] .getSecondaryStructure().charAt(0), ae[aa].getValue() - + ); - + // JBPNote: Consider verifying dataflow for IO of secondary structure annotation read from Stockholm files + // this was added to try to ensure that + //if (anot[ae[aa].getPosition()].secondaryStructure>' ') + //{ + // anot[ae[aa].getPosition()].displayCharacter = ""; + //} anot[ae[aa].getPosition()].colour = new java.awt.Color(ae[aa] .getColour()); } @@ -2178,6 +2288,7 @@ public class Jalview2XML */ private void ensureJalviewDatasetSequence(Sequence vamsasSeq, AlignmentI ds, Vector dseqs) { + // JBP TODO: Check this is called for AlCodonFrames to support recovery of xRef Codon Maps jalview.datamodel.Sequence sq = (jalview.datamodel.Sequence) seqRefIds.get(vamsasSeq.getId()); jalview.datamodel.SequenceI dsq = null; if (sq!=null && sq.getDatasetSequence()!=null) @@ -2201,7 +2312,7 @@ public class Jalview2XML if (sqid == null) { // make up a new dataset reference for this sequence - sqid = "" + dsq.hashCode(); + sqid = seqHash(dsq); } dsq.setVamsasId(uniqueSetSuffix + sqid); seqRefIds.put(sqid, dsq); @@ -2359,7 +2470,7 @@ public class Jalview2XML djs = (jalview.datamodel.Sequence) seqRefIds.get(sqid); } else { System.err.println("Warning - making up dataset sequence id for DbRef sequence map reference"); - sqid = ""+ms.hashCode(); // make up a new hascode for undefined dataset sequence hash (unlikely to happen) + sqid = ((Object)ms).toString(); // make up a new hascode for undefined dataset sequence hash (unlikely to happen) } if (djs==null) { @@ -2387,12 +2498,12 @@ public class Jalview2XML public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap, boolean keepSeqRefs) { - jalview.schemabinding.version2.JalviewModel jm = SaveState(ap, null, - null, null); + jalview.schemabinding.version2.JalviewModel jm = + SaveState(ap, null, null); if (!keepSeqRefs) { - seqRefIds.clear(); + clearSeqRefs(); jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null); } else @@ -2420,4 +2531,16 @@ public class Jalview2XML return af.alignPanel; } + /* (non-Javadoc) + * @see java.lang.Object#finalize() + */ + protected void finalize() throws Throwable + { + // really make sure we have no buried refs left. + clearSeqRefs(); + this.seqRefIds = null; + this.seqsToIds = null; + super.finalize(); + } + }