From 94668ada1c2f3326264877969598cfa99e08d98e Mon Sep 17 00:00:00 2001 From: jprocter Date: Fri, 22 Feb 2008 16:32:57 +0000 Subject: [PATCH] sequenceId is a string, not an integer - allows generation of unlimited unique sequential sequence Ids --- schemas/jalview.xsd | 4 +- src/jalview/gui/Jalview2XML.java | 181 +++++++++++++++++------- src/jalview/schemabinding/version2/.castor.cdr | 8 +- src/jalview/schemabinding/version2/JGroup.java | 48 +++---- src/jalview/schemabinding/version2/JSeq.java | 29 +--- 5 files changed, 159 insertions(+), 111 deletions(-) diff --git a/schemas/jalview.xsd b/schemas/jalview.xsd index 72a3273..b643d67 100755 --- a/schemas/jalview.xsd +++ b/schemas/jalview.xsd @@ -40,14 +40,14 @@ - + - + diff --git a/src/jalview/gui/Jalview2XML.java b/src/jalview/gui/Jalview2XML.java index 9a56150..5c08fb0 100755 --- a/src/jalview/gui/Jalview2XML.java +++ b/src/jalview/gui/Jalview2XML.java @@ -48,8 +48,45 @@ 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 @@ -139,8 +176,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(); @@ -185,14 +222,23 @@ 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, + JarEntry entry = new JarEntry(fileName); + jout.putNextEntry(entry); + out = new PrintWriter(new OutputStreamWriter(jout, "UTF-8")); + SaveState(apanel, fileName, jout, out); } } } - - out.close(); + try { out.flush(); } catch (Exception foo) {}; + jout.closeEntry(); + try { jout.flush(); } catch (Exception foo) {}; jout.close(); } catch (Exception ex) { @@ -210,17 +256,25 @@ 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"; + } + JarEntry entry = new JarEntry(jfileName); + jout.putNextEntry(entry); + PrintWriter out = new PrintWriter(new OutputStreamWriter(jout, + "UTF-8")); + SaveState(apanel, jfileName, jout, out); + try { out.flush(); } catch (Exception foo) {}; + jout.closeEntry(); } - out.close(); + try { jout.flush(); } catch (Exception foo) {}; jout.close(); return true; } catch (Exception ex) @@ -242,11 +296,8 @@ public class Jalview2XML public JalviewModel SaveState(AlignmentPanel ap, String fileName, JarOutputStream jout, PrintWriter out) { - if (seqRefIds == null) - { - seqRefIds = new Hashtable(); - } - + initSeqRefs(); + Vector userColours = new Vector(); AlignViewport av = ap.av; @@ -291,22 +342,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(); + id = seqHash(jds); - if (seqRefIds.get(id + "") != null) + 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(); @@ -314,7 +372,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) { @@ -449,6 +507,7 @@ public class Jalview2XML DataOutputStream dout = new DataOutputStream(jout); dout.write(data, 0, data.length); + dout.flush(); jout.closeEntry(); } } catch (Exception ex) @@ -730,7 +789,7 @@ public class Jalview2XML { jalview.datamodel.Sequence seq = (jalview.datamodel.Sequence) sg .getSequenceAt(s); - groups[i].addSeq(seq.hashCode()); + groups[i].addSeq(seqHash(seq)); } } @@ -929,20 +988,14 @@ public class Jalview2XML if (out != 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); + org.exolab.castor.xml.Marshaller marshaller = new org.exolab.castor.xml.Marshaller(out); + marshaller.marshal(object); + out.flush(); } catch (Exception ex) { ex.printStackTrace(); @@ -951,23 +1004,23 @@ public class Jalview2XML 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(); @@ -975,7 +1028,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) @@ -1032,24 +1085,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"); @@ -1330,6 +1383,7 @@ public class Jalview2XML { out.println(data); } + try { out.flush(); } catch (Exception foo) {}; out.close(); alreadyLoadedPDB.put(pdbId, outFile.getAbsolutePath()); @@ -1364,6 +1418,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() + ""; @@ -1375,14 +1430,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()) @@ -1596,9 +1652,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()); } @@ -2224,7 +2285,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); @@ -2382,7 +2443,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) { @@ -2415,7 +2476,7 @@ public class Jalview2XML if (!keepSeqRefs) { - seqRefIds.clear(); + clearSeqRefs(); jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null); } else @@ -2443,4 +2504,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(); + } + } diff --git a/src/jalview/schemabinding/version2/.castor.cdr b/src/jalview/schemabinding/version2/.castor.cdr index 6de5c73..ada30ce 100644 --- a/src/jalview/schemabinding/version2/.castor.cdr +++ b/src/jalview/schemabinding/version2/.castor.cdr @@ -1,4 +1,4 @@ -#Wed Aug 29 14:54:33 BST 2007 +#Sun Feb 03 18:54:37 GMT 2008 jalview.schemabinding.version2.ThresholdLine=jalview.schemabinding.version2.descriptors.ThresholdLineDescriptor jalview.schemabinding.version2.SequenceSetProperties=jalview.schemabinding.version2.descriptors.SequenceSetPropertiesDescriptor jalview.schemabinding.version2.StructureState=jalview.schemabinding.version2.descriptors.StructureStateDescriptor @@ -33,12 +33,12 @@ jalview.schemabinding.version2.MapListFrom=jalview.schemabinding.version2.descri jalview.schemabinding.version2.PdbentryItem=jalview.schemabinding.version2.descriptors.PdbentryItemDescriptor jalview.schemabinding.version2.FeatureSettings=jalview.schemabinding.version2.descriptors.FeatureSettingsDescriptor jalview.schemabinding.version2.JGroup=jalview.schemabinding.version2.descriptors.JGroupDescriptor -jalview.schemabinding.version2.MapListTo=jalview.schemabinding.version2.descriptors.MapListToDescriptor -jalview.schemabinding.version2.JalviewUserColours=jalview.schemabinding.version2.descriptors.JalviewUserColoursDescriptor jalview.schemabinding.version2.VamsasModel=jalview.schemabinding.version2.descriptors.VamsasModelDescriptor +jalview.schemabinding.version2.JalviewUserColours=jalview.schemabinding.version2.descriptors.JalviewUserColoursDescriptor +jalview.schemabinding.version2.MapListTo=jalview.schemabinding.version2.descriptors.MapListToDescriptor jalview.schemabinding.version2.Pdbentry=jalview.schemabinding.version2.descriptors.PdbentryDescriptor jalview.schemabinding.version2.HiddenColumns=jalview.schemabinding.version2.descriptors.HiddenColumnsDescriptor -jalview.schemabinding.version2.DseqFor=jalview.schemabinding.version2.descriptors.DseqForDescriptor jalview.schemabinding.version2.Features=jalview.schemabinding.version2.descriptors.FeaturesDescriptor +jalview.schemabinding.version2.DseqFor=jalview.schemabinding.version2.descriptors.DseqForDescriptor jalview.schemabinding.version2.VAMSAS=jalview.schemabinding.version2.descriptors.VAMSASDescriptor jalview.schemabinding.version2.MappingChoiceItem=jalview.schemabinding.version2.descriptors.MappingChoiceItemDescriptor diff --git a/src/jalview/schemabinding/version2/JGroup.java b/src/jalview/schemabinding/version2/JGroup.java index 86458e6..ca77ed2 100755 --- a/src/jalview/schemabinding/version2/JGroup.java +++ b/src/jalview/schemabinding/version2/JGroup.java @@ -174,9 +174,9 @@ public class JGroup implements java.io.Serializable { * given is outside the bounds of the collection */ public void addSeq( - final int vSeq) + final java.lang.String vSeq) throws java.lang.IndexOutOfBoundsException { - this._seqList.addElement(new java.lang.Integer(vSeq)); + this._seqList.addElement(vSeq); } /** @@ -189,9 +189,9 @@ public class JGroup implements java.io.Serializable { */ public void addSeq( final int index, - final int vSeq) + final java.lang.String vSeq) throws java.lang.IndexOutOfBoundsException { - this._seqList.add(index, new java.lang.Integer(vSeq)); + this._seqList.add(index, vSeq); } /** @@ -274,7 +274,7 @@ public class JGroup implements java.io.Serializable { /** * Method enumerateSeq. * - * @return an Enumeration over all int elements + * @return an Enumeration over all java.lang.String elements */ public java.util.Enumeration enumerateSeq( ) { @@ -377,9 +377,9 @@ public class JGroup implements java.io.Serializable { * @param index * @throws java.lang.IndexOutOfBoundsException if the index * given is outside the bounds of the collection - * @return the value of the int at the given index + * @return the value of the java.lang.String at the given index */ - public int getSeq( + public java.lang.String getSeq( final int index) throws java.lang.IndexOutOfBoundsException { // check bounds for index @@ -387,24 +387,22 @@ public class JGroup implements java.io.Serializable { throw new IndexOutOfBoundsException("getSeq: Index value '" + index + "' not in range [0.." + (this._seqList.size() - 1) + "]"); } - return ((java.lang.Integer) _seqList.get(index)).intValue(); + return (java.lang.String) _seqList.get(index); } /** * Method getSeq.Returns the contents of the collection in an - * Array. + * Array.

Note: Just in case the collection contents are + * changing in another thread, we pass a 0-length Array of the + * correct type into the API call. This way we know + * that the Array returned is of exactly the correct length. * * @return this collection as an Array */ - public int[] getSeq( + public java.lang.String[] getSeq( ) { - int size = this._seqList.size(); - int[] array = new int[size]; - java.util.Iterator iter = _seqList.iterator(); - for (int index = 0; index < size; index++) { - array[index] = ((java.lang.Integer) iter.next()).intValue(); - } - return array; + java.lang.String[] array = new java.lang.String[0]; + return (java.lang.String[]) this._seqList.toArray(array); } /** @@ -658,8 +656,8 @@ public class JGroup implements java.io.Serializable { * @return true if the object was removed from the collection. */ public boolean removeSeq( - final int vSeq) { - boolean removed = _seqList.remove(new java.lang.Integer(vSeq)); + final java.lang.String vSeq) { + boolean removed = _seqList.remove(vSeq); return removed; } @@ -669,10 +667,10 @@ public class JGroup implements java.io.Serializable { * @param index * @return the element removed from the collection */ - public int removeSeqAt( + public java.lang.String removeSeqAt( final int index) { java.lang.Object obj = this._seqList.remove(index); - return ((java.lang.Integer) obj).intValue(); + return (java.lang.String) obj; } /** @@ -782,14 +780,14 @@ public class JGroup implements java.io.Serializable { */ public void setSeq( final int index, - final int vSeq) + final java.lang.String vSeq) throws java.lang.IndexOutOfBoundsException { // check bounds for index if (index < 0 || index >= this._seqList.size()) { throw new IndexOutOfBoundsException("setSeq: Index value '" + index + "' not in range [0.." + (this._seqList.size() - 1) + "]"); } - this._seqList.set(index, new java.lang.Integer(vSeq)); + this._seqList.set(index, vSeq); } /** @@ -798,12 +796,12 @@ public class JGroup implements java.io.Serializable { * @param vSeqArray */ public void setSeq( - final int[] vSeqArray) { + final java.lang.String[] vSeqArray) { //-- copy array _seqList.clear(); for (int i = 0; i < vSeqArray.length; i++) { - this._seqList.add(new java.lang.Integer(vSeqArray[i])); + this._seqList.add(vSeqArray[i]); } } diff --git a/src/jalview/schemabinding/version2/JSeq.java b/src/jalview/schemabinding/version2/JSeq.java index 9010829..a5dc2f7 100755 --- a/src/jalview/schemabinding/version2/JSeq.java +++ b/src/jalview/schemabinding/version2/JSeq.java @@ -59,12 +59,7 @@ public class JSeq implements java.io.Serializable { /** * Field _id. */ - private int _id; - - /** - * keeps track of state for field: _id - */ - private boolean _has_id; + private java.lang.String _id; /** * Field _hidden. @@ -215,13 +210,6 @@ public class JSeq implements java.io.Serializable { /** */ - public void deleteId( - ) { - this._has_id= false; - } - - /** - */ public void deleteStart( ) { this._has_start= false; @@ -385,7 +373,7 @@ public class JSeq implements java.io.Serializable { * * @return the value of field 'Id'. */ - public int getId( + public java.lang.String getId( ) { return this._id; } @@ -476,16 +464,6 @@ public class JSeq implements java.io.Serializable { } /** - * Method hasId. - * - * @return true if at least one Id has been added - */ - public boolean hasId( - ) { - return this._has_id; - } - - /** * Method hasStart. * * @return true if at least one Start has been added @@ -754,9 +732,8 @@ public class JSeq implements java.io.Serializable { * @param id the value of field 'id'. */ public void setId( - final int id) { + final java.lang.String id) { this._id = id; - this._has_id = true; } /** -- 1.7.10.2