sequenceId is a string, not an integer - allows generation of unlimited unique sequen...
[jalview.git] / src / jalview / gui / Jalview2XML.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.gui;
20
21 import java.io.*;
22 import java.net.*;
23 import java.util.*;
24 import java.util.jar.*;
25
26 import javax.swing.*;
27
28 import org.exolab.castor.xml.*;
29
30 import uk.ac.vamsas.objects.utils.MapList;
31 import jalview.datamodel.Alignment;
32 import jalview.datamodel.AlignmentI;
33 import jalview.datamodel.SequenceI;
34 import jalview.schemabinding.version2.*;
35 import jalview.schemes.*;
36 import jalview.structure.StructureSelectionManager;
37
38 /**
39  * Write out the current jalview desktop state
40  * as a Jalview XML stream.
41  * 
42  * Note: the vamsas objects referred to here are primitive
43  * versions of the VAMSAS project schema elements - they are
44  * not the same and most likely never will be :)
45  *
46  * @author $author$
47  * @version $Revision$
48  */
49 public class Jalview2XML
50 {
51   /**
52    * create/return unique hash string for sq
53    * @param sq
54    * @return new or existing unique string for sq
55    */
56   String seqHash(SequenceI sq)
57   {
58     if (seqsToIds==null)
59     {
60       initSeqRefs();
61     }
62     if (seqsToIds.containsKey(sq))
63     {
64       return (String) seqsToIds.get(sq);
65     } else {
66       //         create sequential key
67       String key = "sq"+(seqsToIds.size()+1);
68       seqsToIds.put(sq, key);
69       return key;
70     }
71   }
72   void clearSeqRefs()
73   {
74     seqRefIds.clear();
75     seqsToIds.clear();
76   }
77   void initSeqRefs()
78   {
79     if (seqsToIds==null)
80     {
81       seqsToIds = new IdentityHashMap();
82     }
83     if (seqRefIds==null)
84     {
85       seqRefIds = new Hashtable();
86     }
87   }
88   java.util.IdentityHashMap seqsToIds = null; // SequenceI->key resolution
89   java.util.Hashtable seqRefIds = null; // key->SequenceI resolution
90
91   Vector frefedSequence = null;
92   boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
93   public Jalview2XML()
94   {
95   }
96   public Jalview2XML(boolean raiseGUI)
97   {
98     this.raiseGUI = raiseGUI;
99   }
100
101   public void resolveFrefedSequences()
102   {
103     if (frefedSequence.size() > 0)
104     {
105       int r = 0, rSize = frefedSequence.size();
106       while (r < rSize)
107       {
108         Object[] ref = (Object[]) frefedSequence.elementAt(r);
109         if (ref != null)
110         {
111           String sref = (String) ref[0];
112           if (seqRefIds.containsKey(sref))
113           {
114             if (ref[1] instanceof jalview.datamodel.Mapping)
115             {
116               SequenceI seq = (SequenceI) seqRefIds.get(sref);
117               while (seq.getDatasetSequence() != null)
118               {
119                 seq = seq.getDatasetSequence();
120               }
121               ((jalview.datamodel.Mapping) ref[1]).setTo(seq);
122             }
123             else
124             {
125               System.err
126                       .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for "
127                               + ref[1].getClass() + " type objects.");
128             }
129             frefedSequence.remove(r);
130             rSize--;
131           }
132           else
133           {
134             r++;
135           }
136         }
137         else
138         {
139           frefedSequence.remove(r);
140           rSize--;
141         }
142       }
143     }
144   }
145
146   /**
147    * This maintains a list of viewports, the key being the
148    * seqSetId. Important to set historyItem and redoList
149    * for multiple views
150    */
151   Hashtable viewportsAdded;
152
153   Hashtable annotationIds = new Hashtable();
154
155   String uniqueSetSuffix = "";
156
157   /**
158    * List of pdbfiles added to Jar
159    */
160   Vector pdbfiles = null;
161
162   // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
163   public void SaveState(File statefile)
164   {
165     JInternalFrame[] frames = Desktop.desktop.getAllFrames();
166
167     if (frames == null)
168     {
169       return;
170     }
171
172     try
173     {
174       FileOutputStream fos = new FileOutputStream(statefile);
175       JarOutputStream jout = new JarOutputStream(fos);
176
177       //NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
178       ////////////////////////////////////////////////////
179       //NOTE ALSO new PrintWriter must be used for each new JarEntry
180       PrintWriter out = null;
181
182       Vector shortNames = new Vector();
183
184       //REVERSE ORDER
185       for (int i = frames.length - 1; i > -1; i--)
186       {
187         if (frames[i] instanceof AlignFrame)
188         {
189           AlignFrame af = (AlignFrame) frames[i];
190
191           String shortName = af.getTitle();
192
193           if (shortName.indexOf(File.separatorChar) > -1)
194           {
195             shortName = shortName.substring(shortName
196                     .lastIndexOf(File.separatorChar) + 1);
197           }
198
199           int count = 1;
200
201           while (shortNames.contains(shortName))
202           {
203             if (shortName.endsWith("_" + (count - 1)))
204             {
205               shortName = shortName
206                       .substring(0, shortName.lastIndexOf("_"));
207             }
208
209             shortName = shortName.concat("_" + count);
210             count++;
211           }
212
213           shortNames.addElement(shortName);
214
215           if (!shortName.endsWith(".xml"))
216           {
217             shortName = shortName + ".xml";
218           }
219
220           int ap, apSize = af.alignPanels.size();
221           for (ap = 0; ap < apSize; ap++)
222           {
223             AlignmentPanel apanel = (AlignmentPanel) af.alignPanels
224                     .elementAt(ap);
225             String fileName = apSize == 1 ? shortName : ap + shortName;
226             if (!fileName.endsWith(".xml"))
227             {
228               fileName = fileName + ".xml";
229             }
230
231             JarEntry entry = new JarEntry(fileName);
232             jout.putNextEntry(entry);
233             out = new PrintWriter(new OutputStreamWriter(jout, "UTF-8"));
234             SaveState(apanel, fileName,
235                     jout, out);
236           }
237         }
238       }
239       try { out.flush(); } catch (Exception foo) {};
240       jout.closeEntry();
241       try { jout.flush(); } catch (Exception foo) {};
242       jout.close();
243     } catch (Exception ex)
244     {
245       //TODO: inform user of the problem - they need to know if their data was not saved !
246       ex.printStackTrace();
247     }
248   }
249
250   // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
251   public boolean SaveAlignment(AlignFrame af, String jarFile,
252           String fileName)
253   {
254     try
255     {
256       int ap, apSize = af.alignPanels.size();
257       FileOutputStream fos = new FileOutputStream(jarFile);
258       JarOutputStream jout = new JarOutputStream(fos);
259       for (ap = 0; ap < apSize; ap++)
260       {
261         AlignmentPanel apanel = (AlignmentPanel) af.alignPanels
262                 .elementAt(ap);
263         String jfileName = apSize == 1 ? fileName : fileName + ap;
264         if (!jfileName.endsWith(".xml"))
265         {
266           jfileName = jfileName + ".xml";
267         }
268         JarEntry entry = new JarEntry(jfileName);
269         jout.putNextEntry(entry);
270         PrintWriter out = new PrintWriter(new OutputStreamWriter(jout,
271         "UTF-8"));
272         SaveState(apanel, jfileName, jout, out);
273         try { out.flush(); } catch (Exception foo) {};
274         jout.closeEntry();
275       }
276
277       try { jout.flush(); } catch (Exception foo) {};
278       jout.close();
279       return true;
280     } catch (Exception ex)
281     {
282       ex.printStackTrace();
283       return false;
284     }
285   }
286
287   /**
288    * DOCUMENT ME!
289    *
290    * @param af DOCUMENT ME!
291    * @param timeStamp DOCUMENT ME!
292    * @param fileName DOCUMENT ME!
293    * @param jout DOCUMENT ME!
294    * @param out DOCUMENT ME!
295    */
296   public JalviewModel SaveState(AlignmentPanel ap, String fileName,
297           JarOutputStream jout, PrintWriter out)
298   {
299     initSeqRefs();
300     
301     Vector userColours = new Vector();
302
303     AlignViewport av = ap.av;
304
305     JalviewModel object = new JalviewModel();
306     object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
307
308     object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
309     object.setVersion(jalview.bin.Cache.getProperty("VERSION"));
310
311     jalview.datamodel.AlignmentI jal = av.alignment;
312
313     if (av.hasHiddenRows)
314     {
315       jal = jal.getHiddenSequences().getFullAlignment();
316     }
317
318     SequenceSet vamsasSet = new SequenceSet();
319     Sequence vamsasSeq;
320     JalviewModelSequence jms = new JalviewModelSequence();
321
322     vamsasSet.setGapChar(jal.getGapCharacter() + "");
323
324     if (jal.getDataset() != null)
325     {
326       // dataset id is the dataset's hashcode
327       vamsasSet.setDatasetId(jal.getDataset().hashCode() + "");
328     }
329     if (jal.getProperties() != null)
330     {
331       Enumeration en = jal.getProperties().keys();
332       while (en.hasMoreElements())
333       {
334         String key = en.nextElement().toString();
335         SequenceSetProperties ssp = new SequenceSetProperties();
336         ssp.setKey(key);
337         ssp.setValue(jal.getProperties().get(key).toString());
338         vamsasSet.addSequenceSetProperties(ssp);
339       }
340     }
341
342     JSeq jseq;
343
344     //SAVE SEQUENCES
345     String id = "";
346     jalview.datamodel.SequenceI jds;
347     for (int i = 0; i < jal.getHeight(); i++)
348     {
349       jds = jal.getSequenceAt(i);
350       id = seqHash(jds);
351
352       if (seqRefIds.get(id) != null)
353       {
354         // 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)
355         // JBPNote: Uncomment to debug writing out of files that do not read back in due to ArrayOutOfBoundExceptions.
356         //System.err.println("vamsasSeq backref: "+id+"");
357         //System.err.println(jds.getName()+" "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
358         //System.err.println("Hashcode: "+seqHash(jds));
359         //SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
360         //System.err.println(rsq.getName()+" "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
361         //System.err.println("Hashcode: "+seqHash(rsq));
362       }
363       else
364       {
365         vamsasSeq = createVamsasSequence(id, jds);
366         vamsasSet.addSequence(vamsasSeq);
367         seqRefIds.put(id, jds);
368       }
369
370       jseq = new JSeq();
371       jseq.setStart(jds.getStart());
372       jseq.setEnd(jds.getEnd());
373       jseq.setColour(av.getSequenceColour(jds).getRGB());
374
375       jseq.setId(id); // jseq id should be a string not a number
376
377       if (av.hasHiddenRows)
378       {
379         jseq.setHidden(av.alignment.getHiddenSequences().isHidden(jds));
380
381         if (av.hiddenRepSequences != null
382                 && av.hiddenRepSequences.containsKey(jal.getSequenceAt(i)))
383         {
384           jalview.datamodel.SequenceI[] reps = ((jalview.datamodel.SequenceGroup) av.hiddenRepSequences
385                   .get(jal.getSequenceAt(i))).getSequencesInOrder(jal);
386
387           for (int h = 0; h < reps.length; h++)
388           {
389             if (reps[h] != jal.getSequenceAt(i))
390             {
391               jseq.addHiddenSequences(jal.findIndex(reps[h]));
392             }
393           }
394         }
395       }
396
397       if (jds.getDatasetSequence().getSequenceFeatures() != null)
398       {
399         jalview.datamodel.SequenceFeature[] sf = jds.getDatasetSequence()
400                 .getSequenceFeatures();
401         int index = 0;
402         while (index < sf.length)
403         {
404           Features features = new Features();
405
406           features.setBegin(sf[index].getBegin());
407           features.setEnd(sf[index].getEnd());
408           features.setDescription(sf[index].getDescription());
409           features.setType(sf[index].getType());
410           features.setFeatureGroup(sf[index].getFeatureGroup());
411           features.setScore(sf[index].getScore());
412           if (sf[index].links != null)
413           {
414             for (int l = 0; l < sf[index].links.size(); l++)
415             {
416               OtherData keyValue = new OtherData();
417               keyValue.setKey("LINK_" + l);
418               keyValue.setValue(sf[index].links.elementAt(l).toString());
419               features.addOtherData(keyValue);
420             }
421           }
422           if (sf[index].otherDetails != null)
423           {
424             String key;
425             Enumeration keys = sf[index].otherDetails.keys();
426             while (keys.hasMoreElements())
427             {
428               key = keys.nextElement().toString();
429               OtherData keyValue = new OtherData();
430               keyValue.setKey(key);
431               keyValue.setValue(sf[index].otherDetails.get(key).toString());
432               features.addOtherData(keyValue);
433             }
434           }
435
436           jseq.addFeatures(features);
437           index++;
438         }
439       }
440
441       if (jds.getDatasetSequence().getPDBId() != null)
442       {
443         Enumeration en = jds.getDatasetSequence().getPDBId().elements();
444         while (en.hasMoreElements())
445         {
446           Pdbids pdb = new Pdbids();
447           jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
448                   .nextElement();
449
450           pdb.setId(entry.getId());
451           pdb.setType(entry.getType());
452
453           AppJmol jmol;
454           //This must have been loaded, is it still visible?
455           JInternalFrame[] frames = Desktop.desktop.getAllFrames();
456           for (int f = frames.length - 1; f > -1; f--)
457           {
458             if (frames[f] instanceof AppJmol)
459             {
460               jmol = (AppJmol) frames[f];
461               if (!jmol.pdbentry.getId().equals(entry.getId()))
462                 continue;
463
464               StructureState state = new StructureState();
465               state.setVisible(true);
466               state.setXpos(jmol.getX());
467               state.setYpos(jmol.getY());
468               state.setWidth(jmol.getWidth());
469               state.setHeight(jmol.getHeight());
470
471               String statestring = jmol.viewer.getStateInfo();
472               if (state != null)
473               {
474                 state.setContent(statestring.replaceAll("\n", ""));
475               }
476               for (int s = 0; s < jmol.sequence.length; s++)
477               {
478                 if (jal.findIndex(jmol.sequence[s]) > -1)
479                 {
480                   pdb.addStructureState(state);
481                 }
482               }
483             }
484           }
485
486           if (entry.getFile() != null)
487           {
488             pdb.setFile(entry.getFile());
489             if (pdbfiles == null)
490             {
491               pdbfiles = new Vector();
492             }
493
494             if (!pdbfiles.contains(entry.getId()))
495             {
496               pdbfiles.addElement(entry.getId());
497               try
498               {
499                 File file = new File(entry.getFile());
500                 if (file.exists() && jout != null)
501                 {
502                   byte[] data = new byte[(int) file.length()];
503                   jout.putNextEntry(new JarEntry(entry.getId()));
504                   DataInputStream dis = new DataInputStream(
505                           new FileInputStream(file));
506                   dis.readFully(data);
507
508                   DataOutputStream dout = new DataOutputStream(jout);
509                   dout.write(data, 0, data.length);
510                   dout.flush();
511                   jout.closeEntry();
512                 }
513               } catch (Exception ex)
514               {
515                 ex.printStackTrace();
516               }
517
518             }
519           }
520
521           if (entry.getProperty() != null)
522           {
523             PdbentryItem item = new PdbentryItem();
524             Hashtable properties = entry.getProperty();
525             Enumeration en2 = properties.keys();
526             while (en2.hasMoreElements())
527             {
528               Property prop = new Property();
529               String key = en2.nextElement().toString();
530               prop.setName(key);
531               prop.setValue(properties.get(key).toString());
532               item.addProperty(prop);
533             }
534             pdb.addPdbentryItem(item);
535           }
536
537           jseq.addPdbids(pdb);
538         }
539       }
540
541       jms.addJSeq(jseq);
542     }
543
544     if (av.hasHiddenRows)
545     {
546       jal = av.alignment;
547     }
548     // SAVE MAPPINGS
549     if (jal.getCodonFrames() != null && jal.getCodonFrames().length > 0)
550     {
551       jalview.datamodel.AlignedCodonFrame[] jac = jal.getCodonFrames();
552       for (int i = 0; i < jac.length; i++)
553       {
554         AlcodonFrame alc = new AlcodonFrame();
555         vamsasSet.addAlcodonFrame(alc);
556         for (int p = 0; p < jac[i].aaWidth; p++)
557         {
558           Alcodon cmap = new Alcodon();
559           cmap.setPos1(jac[i].codons[p][0]);
560           cmap.setPos2(jac[i].codons[p][1]);
561           cmap.setPos3(jac[i].codons[p][2]);
562           alc.addAlcodon(cmap);
563         }
564         if (jac[i].getProtMappings() != null
565                 && jac[i].getProtMappings().length > 0)
566         {
567           SequenceI[] dnas = jac[i].getdnaSeqs();
568           jalview.datamodel.Mapping[] pmaps = jac[i].getProtMappings();
569           for (int m = 0; m < pmaps.length; m++)
570           {
571             AlcodMap alcmap = new AlcodMap();
572             alcmap.setDnasq("" + dnas[m].hashCode());
573             alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
574                     false));
575             alc.addAlcodMap(alcmap);
576           }
577         }
578       }
579     }
580
581     //SAVE TREES
582     ///////////////////////////////////
583     if (av.currentTree != null)
584     {
585       // FIND ANY ASSOCIATED TREES
586       // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
587       if (Desktop.desktop != null)
588       {
589         JInternalFrame[] frames = Desktop.desktop.getAllFrames();
590
591         for (int t = 0; t < frames.length; t++)
592         {
593           if (frames[t] instanceof TreePanel)
594           {
595             TreePanel tp = (TreePanel) frames[t];
596
597             if (tp.treeCanvas.av.alignment == jal)
598             {
599               Tree tree = new Tree();
600               tree.setTitle(tp.getTitle());
601               tree.setCurrentTree((av.currentTree == tp.getTree()));
602               tree.setNewick(tp.getTree().toString());
603               tree.setThreshold(tp.treeCanvas.threshold);
604
605               tree.setFitToWindow(tp.fitToWindow.getState());
606               tree.setFontName(tp.getTreeFont().getName());
607               tree.setFontSize(tp.getTreeFont().getSize());
608               tree.setFontStyle(tp.getTreeFont().getStyle());
609               tree.setMarkUnlinked(tp.placeholdersMenu.getState());
610
611               tree.setShowBootstrap(tp.bootstrapMenu.getState());
612               tree.setShowDistances(tp.distanceMenu.getState());
613
614               tree.setHeight(tp.getHeight());
615               tree.setWidth(tp.getWidth());
616               tree.setXpos(tp.getX());
617               tree.setYpos(tp.getY());
618
619               jms.addTree(tree);
620             }
621           }
622         }
623       }
624     }
625
626     //SAVE ANNOTATIONS
627     if (jal.getAlignmentAnnotation() != null)
628     {
629       jalview.datamodel.AlignmentAnnotation[] aa = jal
630               .getAlignmentAnnotation();
631
632       for (int i = 0; i < aa.length; i++)
633       {
634         Annotation an = new Annotation();
635
636         if (aa[i].annotationId != null)
637         {
638           annotationIds.put(aa[i].annotationId, aa[i]);
639         }
640
641         an.setId(aa[i].annotationId);
642
643         if (aa[i] == av.quality || aa[i] == av.conservation
644                 || aa[i] == av.consensus)
645         {
646           an.setLabel(aa[i].label);
647           an.setGraph(true);
648           vamsasSet.addAnnotation(an);
649           continue;
650         }
651
652         an.setVisible(aa[i].visible);
653
654         an.setDescription(aa[i].description);
655
656         if (aa[i].sequenceRef != null)
657         {
658           an.setSequenceRef(aa[i].sequenceRef.getName());
659         }
660
661         if (aa[i].graph > 0)
662         {
663           an.setGraph(true);
664           an.setGraphType(aa[i].graph);
665           an.setGraphGroup(aa[i].graphGroup);
666           if (aa[i].getThreshold() != null)
667           {
668             ThresholdLine line = new ThresholdLine();
669             line.setLabel(aa[i].getThreshold().label);
670             line.setValue(aa[i].getThreshold().value);
671             line.setColour(aa[i].getThreshold().colour.getRGB());
672             an.setThresholdLine(line);
673           }
674         }
675         else
676         {
677           an.setGraph(false);
678         }
679
680         an.setLabel(aa[i].label);
681         if (aa[i].hasScore())
682         {
683           an.setScore(aa[i].getScore());
684         }
685         AnnotationElement ae;
686         if (aa[i].annotations != null)
687         {
688           an.setScoreOnly(false);
689           for (int a = 0; a < aa[i].annotations.length; a++)
690           {
691             if ((aa[i] == null) || (aa[i].annotations[a] == null))
692             {
693               continue;
694             }
695
696             ae = new AnnotationElement();
697             if (aa[i].annotations[a].description != null)
698               ae.setDescription(aa[i].annotations[a].description);
699             if (aa[i].annotations[a].displayCharacter != null)
700               ae.setDisplayCharacter(aa[i].annotations[a].displayCharacter);
701
702             if (!Float.isNaN(aa[i].annotations[a].value))
703               ae.setValue(aa[i].annotations[a].value);
704
705             ae.setPosition(a);
706             if (aa[i].annotations[a].secondaryStructure != ' '
707                     && aa[i].annotations[a].secondaryStructure != '\0')
708               ae
709                       .setSecondaryStructure(aa[i].annotations[a].secondaryStructure
710                               + "");
711
712             if (aa[i].annotations[a].colour != null
713                     && aa[i].annotations[a].colour != java.awt.Color.black)
714             {
715               ae.setColour(aa[i].annotations[a].colour.getRGB());
716             }
717
718             an.addAnnotationElement(ae);
719           }
720         }
721         else
722         {
723           an.setScoreOnly(true);
724         }
725         vamsasSet.addAnnotation(an);
726       }
727     }
728
729     //SAVE GROUPS
730     if (jal.getGroups() != null)
731     {
732       JGroup[] groups = new JGroup[jal.getGroups().size()];
733
734       for (int i = 0; i < groups.length; i++)
735       {
736         groups[i] = new JGroup();
737
738         jalview.datamodel.SequenceGroup sg = (jalview.datamodel.SequenceGroup) jal
739                 .getGroups().elementAt(i);
740         groups[i].setStart(sg.getStartRes());
741         groups[i].setEnd(sg.getEndRes());
742         groups[i].setName(sg.getName());
743         if (sg.cs != null)
744         {
745           if (sg.cs.conservationApplied())
746           {
747             groups[i].setConsThreshold(sg.cs.getConservationInc());
748
749             if (sg.cs instanceof jalview.schemes.UserColourScheme)
750             {
751               groups[i].setColour(SetUserColourScheme(sg.cs, userColours,
752                       jms));
753             }
754             else
755             {
756               groups[i]
757                       .setColour(ColourSchemeProperty.getColourName(sg.cs));
758             }
759           }
760           else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
761           {
762             groups[i]
763                     .setColour(ColourSchemeProperty
764                             .getColourName(((jalview.schemes.AnnotationColourGradient) sg.cs)
765                                     .getBaseColour()));
766           }
767           else if (sg.cs instanceof jalview.schemes.UserColourScheme)
768           {
769             groups[i]
770                     .setColour(SetUserColourScheme(sg.cs, userColours, jms));
771           }
772           else
773           {
774             groups[i].setColour(ColourSchemeProperty.getColourName(sg.cs));
775           }
776
777           groups[i].setPidThreshold(sg.cs.getThreshold());
778         }
779
780         groups[i].setOutlineColour(sg.getOutlineColour().getRGB());
781         groups[i].setDisplayBoxes(sg.getDisplayBoxes());
782         groups[i].setDisplayText(sg.getDisplayText());
783         groups[i].setColourText(sg.getColourText());
784         groups[i].setTextCol1(sg.textColour.getRGB());
785         groups[i].setTextCol2(sg.textColour2.getRGB());
786         groups[i].setTextColThreshold(sg.thresholdTextColour);
787
788         for (int s = 0; s < sg.getSize(); s++)
789         {
790           jalview.datamodel.Sequence seq = (jalview.datamodel.Sequence) sg
791                   .getSequenceAt(s);
792           groups[i].addSeq(seqHash(seq));
793         }
794       }
795
796       jms.setJGroup(groups);
797     }
798
799     ///////////SAVE VIEWPORT
800     Viewport view = new Viewport();
801     view.setTitle(ap.alignFrame.getTitle());
802     view.setSequenceSetId(av.getSequenceSetId());
803     view.setViewName(av.viewName);
804     view.setGatheredViews(av.gatherViewsHere);
805
806     if (ap.av.explodedPosition != null)
807     {
808       view.setXpos(av.explodedPosition.x);
809       view.setYpos(av.explodedPosition.y);
810       view.setWidth(av.explodedPosition.width);
811       view.setHeight(av.explodedPosition.height);
812     }
813     else
814     {
815       view.setXpos(ap.alignFrame.getBounds().x);
816       view.setYpos(ap.alignFrame.getBounds().y);
817       view.setWidth(ap.alignFrame.getBounds().width);
818       view.setHeight(ap.alignFrame.getBounds().height);
819     }
820
821     view.setStartRes(av.startRes);
822     view.setStartSeq(av.startSeq);
823
824     if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
825     {
826       view.setBgColour(SetUserColourScheme(av.getGlobalColourScheme(),
827               userColours, jms));
828     }
829     else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
830     {
831       jalview.schemes.AnnotationColourGradient acg = (jalview.schemes.AnnotationColourGradient) av
832               .getGlobalColourScheme();
833
834       AnnotationColours ac = new AnnotationColours();
835       ac.setAboveThreshold(acg.getAboveThreshold());
836       ac.setThreshold(acg.getAnnotationThreshold());
837       ac.setAnnotation(acg.getAnnotation());
838       if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
839       {
840         ac.setColourScheme(SetUserColourScheme(acg.getBaseColour(),
841                 userColours, jms));
842       }
843       else
844       {
845         ac.setColourScheme(ColourSchemeProperty.getColourName(acg
846                 .getBaseColour()));
847       }
848
849       ac.setMaxColour(acg.getMaxColour().getRGB());
850       ac.setMinColour(acg.getMinColour().getRGB());
851       view.setAnnotationColours(ac);
852       view.setBgColour("AnnotationColourGradient");
853     }
854     else
855     {
856       view.setBgColour(ColourSchemeProperty.getColourName(av
857               .getGlobalColourScheme()));
858     }
859
860     ColourSchemeI cs = av.getGlobalColourScheme();
861
862     if (cs != null)
863     {
864       if (cs.conservationApplied())
865       {
866         view.setConsThreshold(cs.getConservationInc());
867         if (cs instanceof jalview.schemes.UserColourScheme)
868         {
869           view.setBgColour(SetUserColourScheme(cs, userColours, jms));
870         }
871       }
872
873       if (cs instanceof ResidueColourScheme)
874       {
875         view.setPidThreshold(cs.getThreshold());
876       }
877     }
878
879     view.setConservationSelected(av.getConservationSelected());
880     view.setPidSelected(av.getAbovePIDThreshold());
881     view.setFontName(av.font.getName());
882     view.setFontSize(av.font.getSize());
883     view.setFontStyle(av.font.getStyle());
884     view.setRenderGaps(av.renderGaps);
885     view.setShowAnnotation(av.getShowAnnotation());
886     view.setShowBoxes(av.getShowBoxes());
887     view.setShowColourText(av.getColourText());
888     view.setShowFullId(av.getShowJVSuffix());
889     view.setRightAlignIds(av.rightAlignIds);
890     view.setShowSequenceFeatures(av.showSequenceFeatures);
891     view.setShowText(av.getShowText());
892     view.setWrapAlignment(av.getWrapAlignment());
893     view.setTextCol1(av.textColour.getRGB());
894     view.setTextCol2(av.textColour2.getRGB());
895     view.setTextColThreshold(av.thresholdTextColour);
896
897     if (av.featuresDisplayed != null)
898     {
899       jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
900
901       String[] renderOrder = ap.seqPanel.seqCanvas.getFeatureRenderer().renderOrder;
902
903       Vector settingsAdded = new Vector();
904       for (int ro = 0; ro < renderOrder.length; ro++)
905       {
906         Setting setting = new Setting();
907         setting.setType(renderOrder[ro]);
908         setting.setColour(ap.seqPanel.seqCanvas.getFeatureRenderer()
909                 .getColour(renderOrder[ro]).getRGB());
910
911         setting.setDisplay(av.featuresDisplayed
912                 .containsKey(renderOrder[ro]));
913         float rorder = ap.seqPanel.seqCanvas.getFeatureRenderer().getOrder(
914                 renderOrder[ro]);
915         if (rorder > -1)
916         {
917           setting.setOrder(rorder);
918         }
919         fs.addSetting(setting);
920         settingsAdded.addElement(renderOrder[ro]);
921       }
922
923       //Make sure we save none displayed feature settings
924       Enumeration en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureColours
925               .keys();
926       while (en.hasMoreElements())
927       {
928         String key = en.nextElement().toString();
929         if (settingsAdded.contains(key))
930         {
931           continue;
932         }
933
934         Setting setting = new Setting();
935         setting.setType(key);
936         setting.setColour(ap.seqPanel.seqCanvas.getFeatureRenderer()
937                 .getColour(key).getRGB());
938
939         setting.setDisplay(false);
940         float rorder = ap.seqPanel.seqCanvas.getFeatureRenderer().getOrder(
941                 key);
942         if (rorder > -1)
943         {
944           setting.setOrder(rorder);
945         }
946         fs.addSetting(setting);
947         settingsAdded.addElement(key);
948       }
949       en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureGroups.keys();
950       Vector groupsAdded = new Vector();
951       while (en.hasMoreElements())
952       {
953         String grp = en.nextElement().toString();
954         if (groupsAdded.contains(grp))
955         {
956           continue;
957         }
958         Group g = new Group();
959         g.setName(grp);
960         g
961                 .setDisplay(((Boolean) ap.seqPanel.seqCanvas
962                         .getFeatureRenderer().featureGroups.get(grp))
963                         .booleanValue());
964         fs.addGroup(g);
965         groupsAdded.addElement(grp);
966       }
967       jms.setFeatureSettings(fs);
968
969     }
970
971     if (av.hasHiddenColumns)
972     {
973       for (int c = 0; c < av.getColumnSelection().getHiddenColumns().size(); c++)
974       {
975         int[] region = (int[]) av.getColumnSelection().getHiddenColumns()
976                 .elementAt(c);
977         HiddenColumns hc = new HiddenColumns();
978         hc.setStart(region[0]);
979         hc.setEnd(region[1]);
980         view.addHiddenColumns(hc);
981       }
982     }
983
984     jms.addViewport(view);
985
986     object.setJalviewModelSequence(jms);
987     object.getVamsasModel().addSequenceSet(vamsasSet);
988
989     if (out != null)
990     {
991       //We may not want to write the object to disk,
992       //eg we can copy the alignViewport to a new view object
993       //using save and then load
994       try
995       {
996         org.exolab.castor.xml.Marshaller marshaller = new org.exolab.castor.xml.Marshaller(out);
997         marshaller.marshal(object);
998         out.flush();
999       } catch (Exception ex)
1000       {
1001         ex.printStackTrace();
1002       }
1003     }
1004     return object;
1005   }
1006
1007   private Sequence createVamsasSequence(String id, SequenceI jds)
1008   {
1009     return createVamsasSequence(true, id, jds, null);
1010   }
1011
1012   private Sequence createVamsasSequence(boolean recurse, String id,
1013           SequenceI jds, SequenceI parentseq)
1014   {
1015     Sequence vamsasSeq = new Sequence();
1016     vamsasSeq.setId(id);
1017     vamsasSeq.setName(jds.getName());
1018     vamsasSeq.setSequence(jds.getSequenceAsString());
1019     vamsasSeq.setDescription(jds.getDescription());
1020     jalview.datamodel.DBRefEntry[] dbrefs = null;
1021     if (jds.getDatasetSequence() != null)
1022     {
1023       vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
1024       if (jds.getDatasetSequence().getDBRef() != null)
1025       {
1026         dbrefs = jds.getDatasetSequence().getDBRef();
1027       }
1028     }
1029     else
1030     {
1031       vamsasSeq.setDsseqid(id); // so we can tell which sequences really are dataset sequences only
1032       dbrefs = jds.getDBRef();
1033     }
1034     if (dbrefs != null)
1035     {
1036       for (int d = 0; d < dbrefs.length; d++)
1037       {
1038         DBRef dbref = new DBRef();
1039         dbref.setSource(dbrefs[d].getSource());
1040         dbref.setVersion(dbrefs[d].getVersion());
1041         dbref.setAccessionId(dbrefs[d].getAccessionId());
1042         if (dbrefs[d].hasMap())
1043         {
1044           Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
1045                   jds, recurse);
1046           dbref.setMapping(mp);
1047         }
1048         vamsasSeq.addDBRef(dbref);
1049       }
1050     }
1051     return vamsasSeq;
1052   }
1053
1054   private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
1055           SequenceI parentseq, SequenceI jds, boolean recurse)
1056   {
1057     Mapping mp = null;
1058     if (jmp.getMap() != null)
1059     {
1060       mp = new Mapping();
1061
1062       jalview.util.MapList mlst = jmp.getMap();
1063       int r[] = mlst.getFromRanges();
1064       for (int s = 0; s < r.length; s += 2)
1065       {
1066         MapListFrom mfrom = new MapListFrom();
1067         mfrom.setStart(r[s]);
1068         mfrom.setEnd(r[s + 1]);
1069         mp.addMapListFrom(mfrom);
1070       }
1071       r = mlst.getToRanges();
1072       for (int s = 0; s < r.length; s += 2)
1073       {
1074         MapListTo mto = new MapListTo();
1075         mto.setStart(r[s]);
1076         mto.setEnd(r[s + 1]);
1077         mp.addMapListTo(mto);
1078       }
1079       mp.setMapFromUnit(mlst.getFromRatio());
1080       mp.setMapToUnit(mlst.getToRatio());
1081       if (jmp.getTo() != null)
1082       {
1083         MappingChoice mpc = new MappingChoice();
1084         if (recurse
1085                 && (parentseq != jmp.getTo() || parentseq
1086                         .getDatasetSequence() != jmp.getTo()))
1087         {
1088           mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo())
1089                   , jmp.getTo(), jds));
1090         }
1091         else
1092         {
1093           String jmpid = "";
1094           SequenceI ps = null;
1095           if (parentseq != jmp.getTo()
1096                   && parentseq.getDatasetSequence() != jmp.getTo())
1097           {
1098             // chaining dbref rather than a handshaking one
1099             jmpid = seqHash(ps = jmp.getTo());
1100           }
1101           else
1102           {
1103             jmpid = seqHash(ps = parentseq);
1104           }
1105           mpc.setDseqFor(jmpid);
1106           if (!seqRefIds.containsKey(mpc.getDseqFor()))
1107           {
1108             jalview.bin.Cache.log.debug("creatign new DseqFor ID");
1109             seqRefIds.put(mpc.getDseqFor(), ps);
1110           }
1111           else
1112           {
1113             jalview.bin.Cache.log.debug("reusing DseqFor ID");
1114           }
1115         }
1116         mp.setMappingChoice(mpc);
1117       }
1118     }
1119     return mp;
1120   }
1121
1122   String SetUserColourScheme(jalview.schemes.ColourSchemeI cs,
1123           Vector userColours, JalviewModelSequence jms)
1124   {
1125     String id = null;
1126     jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
1127
1128     if (!userColours.contains(ucs))
1129     {
1130       userColours.add(ucs);
1131
1132       java.awt.Color[] colours = ucs.getColours();
1133       jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
1134       jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
1135
1136       for (int i = 0; i < colours.length; i++)
1137       {
1138         jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
1139         col.setName(ResidueProperties.aa[i]);
1140         col.setRGB(jalview.util.Format.getHexString(colours[i]));
1141         jbucs.addColour(col);
1142       }
1143       if (ucs.getLowerCaseColours() != null)
1144       {
1145         colours = ucs.getLowerCaseColours();
1146         for (int i = 0; i < colours.length; i++)
1147         {
1148           jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
1149           col.setName(ResidueProperties.aa[i].toLowerCase());
1150           col.setRGB(jalview.util.Format.getHexString(colours[i]));
1151           jbucs.addColour(col);
1152         }
1153       }
1154
1155       id = "ucs" + userColours.indexOf(ucs);
1156       uc.setId(id);
1157       uc.setUserColourScheme(jbucs);
1158       jms.addUserColours(uc);
1159     }
1160
1161     return id;
1162   }
1163
1164   jalview.schemes.UserColourScheme GetUserColourScheme(
1165           JalviewModelSequence jms, String id)
1166   {
1167     UserColours[] uc = jms.getUserColours();
1168     UserColours colours = null;
1169
1170     for (int i = 0; i < uc.length; i++)
1171     {
1172       if (uc[i].getId().equals(id))
1173       {
1174         colours = uc[i];
1175
1176         break;
1177       }
1178     }
1179
1180     java.awt.Color[] newColours = new java.awt.Color[24];
1181
1182     for (int i = 0; i < 24; i++)
1183     {
1184       newColours[i] = new java.awt.Color(Integer.parseInt(colours
1185               .getUserColourScheme().getColour(i).getRGB(), 16));
1186     }
1187
1188     jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
1189             newColours);
1190
1191     if (colours.getUserColourScheme().getColourCount() > 24)
1192     {
1193       newColours = new java.awt.Color[23];
1194       for (int i = 0; i < 23; i++)
1195       {
1196         newColours[i] = new java.awt.Color(Integer.parseInt(colours
1197                 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
1198       }
1199       ucs.setLowerCaseColours(newColours);
1200     }
1201
1202     return ucs;
1203   }
1204
1205   /**
1206    * DOCUMENT ME!
1207    *
1208    * @param file DOCUMENT ME!
1209    */
1210   public AlignFrame LoadJalviewAlign(final String file)
1211   {
1212     uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
1213
1214     jalview.gui.AlignFrame af = null;
1215
1216     seqRefIds = new Hashtable();
1217     viewportsAdded = new Hashtable();
1218     frefedSequence = new Vector();
1219     Hashtable gatherToThisFrame = new Hashtable();
1220
1221     String errorMessage = null;
1222
1223     try
1224     {
1225       //UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
1226       URL url = null;
1227
1228       if (file.startsWith("http://"))
1229       {
1230         url = new URL(file);
1231       }
1232
1233       JarInputStream jin = null;
1234       JarEntry jarentry = null;
1235       int entryCount = 1;
1236
1237       do
1238       {
1239         if (url != null)
1240         {
1241           jin = new JarInputStream(url.openStream());
1242         }
1243         else
1244         {
1245           jin = new JarInputStream(new FileInputStream(file));
1246         }
1247
1248         for (int i = 0; i < entryCount; i++)
1249         {
1250           jarentry = jin.getNextJarEntry();
1251         }
1252
1253         if (jarentry != null && jarentry.getName().endsWith(".xml"))
1254         {
1255           InputStreamReader in = new InputStreamReader(jin, "UTF-8");
1256           JalviewModel object = new JalviewModel();
1257
1258           Unmarshaller unmar = new Unmarshaller(object);
1259           unmar.setValidation(false);
1260           object = (JalviewModel) unmar.unmarshal(in);
1261
1262           af = LoadFromObject(object, file, true);
1263           if (af.viewport.gatherViewsHere)
1264           {
1265             gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
1266           }
1267           entryCount++;
1268         }
1269         else if (jarentry != null)
1270         {
1271           //Some other file here.
1272           entryCount++;
1273         }
1274       } while (jarentry != null);
1275       resolveFrefedSequences();
1276     } catch (java.io.FileNotFoundException ex)
1277     {
1278       ex.printStackTrace();
1279       errorMessage = "Couldn't locate Jalview XML file : " + file;
1280       System.err.println("Exception whilst loading jalview XML file : "
1281               + ex + "\n");
1282     } catch (java.net.UnknownHostException ex)
1283     {
1284       ex.printStackTrace();
1285       errorMessage = "Couldn't locate Jalview XML file : " + file;
1286       System.err.println("Exception whilst loading jalview XML file : "
1287               + ex + "\n");
1288     } catch (Exception ex)
1289     {
1290       //Is Version 1 Jar file?
1291       try {
1292         af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(file);
1293       } catch (Exception ex2) {
1294         System.err.println("Exception whilst loading as jalviewXMLV1:");
1295         ex2.printStackTrace();
1296         af = null;
1297       }
1298
1299       if (Desktop.instance != null)
1300       {
1301         Desktop.instance.stopLoading();
1302       }
1303       if (af != null)
1304       {
1305         System.out.println("Successfully loaded archive file");
1306         return af;
1307       }
1308       ex.printStackTrace();
1309
1310       System.err.println("Exception whilst loading jalview XML file : "
1311               + ex + "\n");
1312     }
1313
1314     if (Desktop.instance != null)
1315     {
1316       Desktop.instance.stopLoading();
1317     }
1318
1319     Enumeration en = gatherToThisFrame.elements();
1320     while (en.hasMoreElements())
1321     {
1322       Desktop.instance.gatherViews((AlignFrame) en.nextElement());
1323     }
1324
1325     if (errorMessage != null)
1326     {
1327       final String finalErrorMessage = errorMessage;
1328       if (raiseGUI)
1329         {
1330         javax.swing.SwingUtilities.invokeLater(new Runnable()
1331         {
1332           public void run()
1333         {
1334           JOptionPane.showInternalMessageDialog(Desktop.desktop,
1335                   finalErrorMessage, "Error loading Jalview file",
1336                   JOptionPane.WARNING_MESSAGE);
1337         }
1338       });
1339         } else {
1340           System.err.println("Problem loading Jalview file: "+errorMessage);
1341         }
1342     }
1343
1344     return af;
1345   }
1346
1347   Hashtable alreadyLoadedPDB;
1348
1349   String loadPDBFile(String file, String pdbId)
1350   {
1351     if (alreadyLoadedPDB == null)
1352       alreadyLoadedPDB = new Hashtable();
1353
1354     if (alreadyLoadedPDB.containsKey(pdbId))
1355       return alreadyLoadedPDB.get(pdbId).toString();
1356
1357     try
1358     {
1359       JarInputStream jin = null;
1360
1361       if (file.startsWith("http://"))
1362       {
1363         jin = new JarInputStream(new URL(file).openStream());
1364       }
1365       else
1366       {
1367         jin = new JarInputStream(new FileInputStream(file));
1368       }
1369
1370       JarEntry entry = null;
1371       do
1372       {
1373         entry = jin.getNextJarEntry();
1374       } while (!entry.getName().equals(pdbId));
1375
1376       BufferedReader in = new BufferedReader(new InputStreamReader(jin));
1377       File outFile = File.createTempFile("jalview_pdb", ".txt");
1378       outFile.deleteOnExit();
1379       PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
1380       String data;
1381
1382       while ((data = in.readLine()) != null)
1383       {
1384         out.println(data);
1385       }
1386       try { out.flush(); } catch (Exception foo) {};
1387       out.close();
1388
1389       alreadyLoadedPDB.put(pdbId, outFile.getAbsolutePath());
1390       return outFile.getAbsolutePath();
1391
1392     } catch (Exception ex)
1393     {
1394       ex.printStackTrace();
1395     }
1396
1397     return null;
1398   }
1399
1400   AlignFrame LoadFromObject(JalviewModel object, String file,
1401           boolean loadTreesAndStructures)
1402   {
1403     SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
1404     Sequence[] vamsasSeq = vamsasSet.getSequence();
1405
1406     JalviewModelSequence jms = object.getJalviewModelSequence();
1407
1408     Viewport view = jms.getViewport(0);
1409
1410     //////////////////////////////////
1411     //LOAD SEQUENCES
1412
1413     Vector hiddenSeqs = null;
1414     jalview.datamodel.Sequence jseq;
1415
1416     ArrayList tmpseqs = new ArrayList();
1417
1418     boolean multipleView = false;
1419
1420     JSeq[] JSEQ = object.getJalviewModelSequence().getJSeq();
1421     int vi=0; // counter in vamsasSeq array
1422     for (int i = 0; i < JSEQ.length; i++)
1423     {
1424       String seqId = JSEQ[i].getId() + "";
1425
1426       if (seqRefIds.get(seqId) != null)
1427       {
1428         tmpseqs.add((jalview.datamodel.Sequence) seqRefIds.get(seqId));
1429         multipleView = true;
1430       }
1431       else
1432       {
1433         jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
1434                 vamsasSeq[vi].getSequence());
1435         jseq.setDescription(vamsasSeq[vi].getDescription());
1436         jseq.setStart(JSEQ[i].getStart());
1437         jseq.setEnd(JSEQ[i].getEnd());
1438         jseq.setVamsasId(uniqueSetSuffix + seqId);
1439         seqRefIds.put(vamsasSeq[vi].getId()+"", jseq);
1440         tmpseqs.add(jseq);
1441         vi++;
1442       }
1443
1444       if (JSEQ[i].getHidden())
1445       {
1446         if (hiddenSeqs == null)
1447         {
1448           hiddenSeqs = new Vector();
1449         }
1450
1451         hiddenSeqs.addElement((jalview.datamodel.Sequence) seqRefIds
1452                 .get(seqId));
1453       }
1454
1455     }
1456
1457     ///
1458     // Create the alignment object from the sequence set
1459     /////////////////////////////////
1460     jalview.datamodel.Sequence[] orderedSeqs = new jalview.datamodel.Sequence[tmpseqs
1461             .size()];
1462
1463     tmpseqs.toArray(orderedSeqs);
1464
1465     jalview.datamodel.Alignment al = new jalview.datamodel.Alignment(
1466             orderedSeqs);
1467
1468     /// Add the alignment properties
1469     for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
1470     {
1471       SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
1472       al.setProperty(ssp.getKey(), ssp.getValue());
1473     }
1474
1475     ///
1476     // SequenceFeatures are added to the DatasetSequence,
1477     // so we must create or recover the dataset before loading features
1478     /////////////////////////////////
1479     if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
1480     {
1481       // older jalview projects do not have a dataset id.
1482       al.setDataset(null);
1483     }
1484     else
1485     {
1486       recoverDatasetFor(vamsasSet, al);
1487     }
1488     /////////////////////////////////
1489
1490     Hashtable pdbloaded = new Hashtable();
1491     if (!multipleView)
1492     {
1493       for (int i = 0; i < vamsasSeq.length; i++)
1494       {
1495         if (JSEQ[i].getFeaturesCount() > 0)
1496         {
1497           Features[] features = JSEQ[i].getFeatures();
1498           for (int f = 0; f < features.length; f++)
1499           {
1500             jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
1501                     features[f].getType(), features[f].getDescription(),
1502                     features[f].getStatus(), features[f].getBegin(),
1503                     features[f].getEnd(), features[f].getFeatureGroup());
1504
1505             sf.setScore(features[f].getScore());
1506             for (int od = 0; od < features[f].getOtherDataCount(); od++)
1507             {
1508               OtherData keyValue = features[f].getOtherData(od);
1509               if (keyValue.getKey().startsWith("LINK"))
1510               {
1511                 sf.addLink(keyValue.getValue());
1512               }
1513               else
1514               {
1515                 sf.setValue(keyValue.getKey(), keyValue.getValue());
1516               }
1517
1518             }
1519
1520             al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
1521           }
1522         }
1523         if (vamsasSeq[i].getDBRefCount() > 0)
1524         {
1525           addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
1526         }
1527         if (JSEQ[i].getPdbidsCount() > 0)
1528         {
1529           Pdbids[] ids = JSEQ[i].getPdbids();
1530           for (int p = 0; p < ids.length; p++)
1531           {
1532             jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
1533             entry.setId(ids[p].getId());
1534             entry.setType(ids[p].getType());
1535             if (ids[p].getFile() != null)
1536             {
1537               if (!pdbloaded.containsKey(ids[p].getFile()))
1538               {
1539                 entry.setFile(loadPDBFile(file, ids[p].getId()));
1540               }
1541               else
1542               {
1543                 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
1544               }
1545             }
1546
1547             al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
1548           }
1549         }
1550       }
1551     }
1552
1553     /////////////////////////////////
1554     // LOAD SEQUENCE MAPPINGS
1555     if (vamsasSet.getAlcodonFrameCount() > 0)
1556     {
1557       AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
1558       for (int i = 0; i < alc.length; i++)
1559       {
1560         jalview.datamodel.AlignedCodonFrame cf = new jalview.datamodel.AlignedCodonFrame(
1561                 alc[i].getAlcodonCount());
1562         if (alc[i].getAlcodonCount() > 0)
1563         {
1564           Alcodon[] alcods = alc[i].getAlcodon();
1565           for (int p = 0; p < cf.codons.length; p++)
1566           {
1567             cf.codons[p] = new int[3];
1568             cf.codons[p][0] = (int) alcods[p].getPos1();
1569             cf.codons[p][1] = (int) alcods[p].getPos2();
1570             cf.codons[p][2] = (int) alcods[p].getPos3();
1571           }
1572         }
1573         if (alc[i].getAlcodMapCount() > 0)
1574         {
1575           AlcodMap[] maps = alc[i].getAlcodMap();
1576           for (int m = 0; m < maps.length; m++)
1577           {
1578             SequenceI dnaseq = (SequenceI) seqRefIds
1579                     .get(maps[m].getDnasq());
1580             // Load Mapping
1581             // attach to dna sequence reference.
1582             if (dnaseq != null)
1583             {
1584               if (maps[m].getMapping() != null)
1585               {
1586                 jalview.datamodel.Mapping mapping = addMapping(maps[m]
1587                         .getMapping());
1588                 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
1589               }
1590             }
1591           }
1592         }
1593         al.addCodonFrame(cf);
1594       }
1595
1596     }
1597
1598     //////////////////////////////////
1599     //LOAD ANNOTATIONS
1600     boolean hideQuality = true, hideConservation = true, hideConsensus = true;
1601
1602     if (vamsasSet.getAnnotationCount() > 0)
1603     {
1604       Annotation[] an = vamsasSet.getAnnotation();
1605
1606       for (int i = 0; i < an.length; i++)
1607       {
1608         if (an[i].getLabel().equals("Quality"))
1609         {
1610           hideQuality = false;
1611           continue;
1612         }
1613         else if (an[i].getLabel().equals("Conservation"))
1614         {
1615           hideConservation = false;
1616           continue;
1617         }
1618         else if (an[i].getLabel().equals("Consensus"))
1619         {
1620           hideConsensus = false;
1621           continue;
1622         }
1623
1624         if (an[i].getId() != null
1625                 && annotationIds.containsKey(an[i].getId()))
1626         {
1627           jalview.datamodel.AlignmentAnnotation jda = (jalview.datamodel.AlignmentAnnotation) annotationIds
1628                   .get(an[i].getId());
1629           if (an[i].hasVisible())
1630             jda.visible = an[i].getVisible();
1631
1632           al.addAnnotation(jda);
1633
1634           continue;
1635         }
1636
1637         AnnotationElement[] ae = an[i].getAnnotationElement();
1638         jalview.datamodel.Annotation[] anot = null;
1639
1640         if (!an[i].getScoreOnly())
1641         {
1642           anot = new jalview.datamodel.Annotation[al.getWidth()];
1643
1644           for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
1645           {
1646             if (ae[aa].getPosition() >= anot.length)
1647               continue;
1648
1649             anot[ae[aa].getPosition()] = new jalview.datamodel.Annotation(
1650
1651             ae[aa].getDisplayCharacter(), ae[aa].getDescription(), (ae[aa]
1652                     .getSecondaryStructure() == null || ae[aa]
1653                     .getSecondaryStructure().length() == 0) ? ' ' : ae[aa]
1654                     .getSecondaryStructure().charAt(0), ae[aa].getValue()
1655                     
1656             );
1657             // JBPNote: Consider verifying dataflow for IO of secondary structure annotation read from Stockholm files
1658             // this was added to try to ensure that 
1659             //if (anot[ae[aa].getPosition()].secondaryStructure>' ')
1660             //{
1661             //  anot[ae[aa].getPosition()].displayCharacter = "";
1662             //}
1663             anot[ae[aa].getPosition()].colour = new java.awt.Color(ae[aa]
1664                     .getColour());
1665           }
1666         }
1667         jalview.datamodel.AlignmentAnnotation jaa = null;
1668
1669         if (an[i].getGraph())
1670         {
1671           jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
1672                   an[i].getDescription(), anot, 0, 0, an[i].getGraphType());
1673
1674           jaa.graphGroup = an[i].getGraphGroup();
1675
1676           if (an[i].getThresholdLine() != null)
1677           {
1678             jaa.setThreshold(new jalview.datamodel.GraphLine(an[i]
1679                     .getThresholdLine().getValue(), an[i]
1680                     .getThresholdLine().getLabel(), new java.awt.Color(
1681                     an[i].getThresholdLine().getColour())));
1682
1683           }
1684
1685         }
1686         else
1687         {
1688           jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
1689                   an[i].getDescription(), anot);
1690         }
1691
1692         if (an[i].getId() != null)
1693         {
1694           annotationIds.put(an[i].getId(), jaa);
1695           jaa.annotationId = an[i].getId();
1696         }
1697
1698         if (an[i].getSequenceRef() != null)
1699         {
1700           if (al.findName(an[i].getSequenceRef()) != null)
1701           {
1702             jaa.createSequenceMapping(al.findName(an[i].getSequenceRef()),
1703                     1, true);
1704             al.findName(an[i].getSequenceRef()).addAlignmentAnnotation(jaa);
1705           }
1706         }
1707         if (an[i].hasScore())
1708         {
1709           jaa.setScore(an[i].getScore());
1710         }
1711
1712         if (an[i].hasVisible())
1713           jaa.visible = an[i].getVisible();
1714
1715         al.addAnnotation(jaa);
1716       }
1717     }
1718
1719     /////////////////////////
1720     //LOAD GROUPS
1721     if (jms.getJGroupCount() > 0)
1722     {
1723       JGroup[] groups = jms.getJGroup();
1724
1725       for (int i = 0; i < groups.length; i++)
1726       {
1727         ColourSchemeI cs = null;
1728
1729         if (groups[i].getColour() != null)
1730         {
1731           if (groups[i].getColour().startsWith("ucs"))
1732           {
1733             cs = GetUserColourScheme(jms, groups[i].getColour());
1734           }
1735           else
1736           {
1737             cs = ColourSchemeProperty.getColour(al, groups[i].getColour());
1738           }
1739
1740           if (cs != null)
1741           {
1742             cs.setThreshold(groups[i].getPidThreshold(), true);
1743           }
1744         }
1745
1746         Vector seqs = new Vector();
1747
1748         for (int s = 0; s < groups[i].getSeqCount(); s++)
1749         {
1750           String seqId = groups[i].getSeq(s) + "";
1751           jalview.datamodel.SequenceI ts = (jalview.datamodel.SequenceI) seqRefIds
1752                   .get(seqId);
1753
1754           if (ts != null)
1755           {
1756             seqs.addElement(ts);
1757           }
1758         }
1759
1760         if (seqs.size() < 1)
1761         {
1762           continue;
1763         }
1764
1765         jalview.datamodel.SequenceGroup sg = new jalview.datamodel.SequenceGroup(
1766                 seqs, groups[i].getName(), cs, groups[i].getDisplayBoxes(),
1767                 groups[i].getDisplayText(), groups[i].getColourText(),
1768                 groups[i].getStart(), groups[i].getEnd());
1769
1770         sg
1771                 .setOutlineColour(new java.awt.Color(groups[i]
1772                         .getOutlineColour()));
1773
1774         sg.textColour = new java.awt.Color(groups[i].getTextCol1());
1775         sg.textColour2 = new java.awt.Color(groups[i].getTextCol2());
1776         sg.thresholdTextColour = groups[i].getTextColThreshold();
1777
1778         if (groups[i].getConsThreshold() != 0)
1779         {
1780           jalview.analysis.Conservation c = new jalview.analysis.Conservation(
1781                   "All", ResidueProperties.propHash, 3, sg
1782                           .getSequences(null), 0, sg.getWidth() - 1);
1783           c.calculate();
1784           c.verdict(false, 25);
1785           sg.cs.setConservation(c);
1786         }
1787
1788         al.addGroup(sg);
1789       }
1790     }
1791
1792     /////////////////////////////////
1793     // LOAD VIEWPORT
1794
1795     AlignFrame af = new AlignFrame(al, view.getWidth(), view.getHeight());
1796
1797     af.setFileName(file, "Jalview");
1798
1799     for (int i = 0; i < JSEQ.length; i++)
1800     {
1801       af.viewport.setSequenceColour(af.viewport.alignment.getSequenceAt(i),
1802               new java.awt.Color(JSEQ[i].getColour()));
1803     }
1804
1805     //If we just load in the same jar file again, the sequenceSetId
1806     //will be the same, and we end up with multiple references
1807     //to the same sequenceSet. We must modify this id on load
1808     //so that each load of the file gives a unique id
1809     String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
1810
1811     af.viewport.gatherViewsHere = view.getGatheredViews();
1812
1813     if (view.getSequenceSetId() != null)
1814     {
1815       jalview.gui.AlignViewport av = (jalview.gui.AlignViewport) viewportsAdded
1816               .get(uniqueSeqSetId);
1817
1818       af.viewport.sequenceSetID = uniqueSeqSetId;
1819       if (av != null)
1820       {
1821
1822         af.viewport.historyList = av.historyList;
1823         af.viewport.redoList = av.redoList;
1824       }
1825       else
1826       {
1827         viewportsAdded.put(uniqueSeqSetId, af.viewport);
1828       }
1829
1830       PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
1831     }
1832     if (hiddenSeqs != null)
1833     {
1834       for (int s = 0; s < JSEQ.length; s++)
1835       {
1836         jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
1837
1838         for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
1839         {
1840           hidden.addSequence(al
1841                   .getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
1842         }
1843         af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
1844       }
1845
1846       jalview.datamodel.SequenceI[] hseqs = new jalview.datamodel.SequenceI[hiddenSeqs
1847               .size()];
1848
1849       for (int s = 0; s < hiddenSeqs.size(); s++)
1850       {
1851         hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
1852       }
1853
1854       af.viewport.hideSequence(hseqs);
1855
1856     }
1857
1858     if ((hideConsensus || hideQuality || hideConservation)
1859             && al.getAlignmentAnnotation() != null)
1860     {
1861       int hSize = al.getAlignmentAnnotation().length;
1862       for (int h = 0; h < hSize; h++)
1863       {
1864         if ((hideConsensus && al.getAlignmentAnnotation()[h].label
1865                 .equals("Consensus"))
1866                 || (hideQuality && al.getAlignmentAnnotation()[h].label
1867                         .equals("Quality"))
1868                 || (hideConservation && al.getAlignmentAnnotation()[h].label
1869                         .equals("Conservation")))
1870         {
1871           al.deleteAnnotation(al.getAlignmentAnnotation()[h]);
1872           hSize--;
1873           h--;
1874         }
1875       }
1876       af.alignPanel.adjustAnnotationHeight();
1877     }
1878
1879     if (view.getViewName() != null)
1880     {
1881       af.viewport.viewName = view.getViewName();
1882       af.setInitialTabVisible();
1883     }
1884     af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(), view
1885             .getHeight());
1886
1887     af.viewport.setShowAnnotation(view.getShowAnnotation());
1888     af.viewport.setAbovePIDThreshold(view.getPidSelected());
1889
1890     af.viewport.setColourText(view.getShowColourText());
1891
1892     af.viewport.setConservationSelected(view.getConservationSelected());
1893     af.viewport.setShowJVSuffix(view.getShowFullId());
1894     af.viewport.rightAlignIds = view.getRightAlignIds();
1895     af.viewport.setFont(new java.awt.Font(view.getFontName(), view
1896             .getFontStyle(), view.getFontSize()));
1897     af.alignPanel.fontChanged();
1898     af.viewport.setRenderGaps(view.getRenderGaps());
1899     af.viewport.setWrapAlignment(view.getWrapAlignment());
1900     af.alignPanel.setWrapAlignment(view.getWrapAlignment());
1901     af.viewport.setShowAnnotation(view.getShowAnnotation());
1902     af.alignPanel.setAnnotationVisible(view.getShowAnnotation());
1903
1904     af.viewport.setShowBoxes(view.getShowBoxes());
1905
1906     af.viewport.setShowText(view.getShowText());
1907
1908     af.viewport.textColour = new java.awt.Color(view.getTextCol1());
1909     af.viewport.textColour2 = new java.awt.Color(view.getTextCol2());
1910     af.viewport.thresholdTextColour = view.getTextColThreshold();
1911
1912     af.viewport.setStartRes(view.getStartRes());
1913     af.viewport.setStartSeq(view.getStartSeq());
1914
1915     ColourSchemeI cs = null;
1916
1917     if (view.getBgColour() != null)
1918     {
1919       if (view.getBgColour().startsWith("ucs"))
1920       {
1921         cs = GetUserColourScheme(jms, view.getBgColour());
1922       }
1923       else if (view.getBgColour().startsWith("Annotation"))
1924       {
1925         //int find annotation
1926         for (int i = 0; i < af.viewport.alignment.getAlignmentAnnotation().length; i++)
1927         {
1928           if (af.viewport.alignment.getAlignmentAnnotation()[i].label
1929                   .equals(view.getAnnotationColours().getAnnotation()))
1930           {
1931             if (af.viewport.alignment.getAlignmentAnnotation()[i]
1932                     .getThreshold() == null)
1933             {
1934               af.viewport.alignment.getAlignmentAnnotation()[i]
1935                       .setThreshold(new jalview.datamodel.GraphLine(view
1936                               .getAnnotationColours().getThreshold(),
1937                               "Threshold", java.awt.Color.black)
1938
1939                       );
1940             }
1941
1942             if (view.getAnnotationColours().getColourScheme()
1943                     .equals("None"))
1944             {
1945               cs = new AnnotationColourGradient(af.viewport.alignment
1946                       .getAlignmentAnnotation()[i], new java.awt.Color(view
1947                       .getAnnotationColours().getMinColour()),
1948                       new java.awt.Color(view.getAnnotationColours()
1949                               .getMaxColour()), view.getAnnotationColours()
1950                               .getAboveThreshold());
1951             }
1952             else if (view.getAnnotationColours().getColourScheme()
1953                     .startsWith("ucs"))
1954             {
1955               cs = new AnnotationColourGradient(af.viewport.alignment
1956                       .getAlignmentAnnotation()[i], GetUserColourScheme(
1957                       jms, view.getAnnotationColours().getColourScheme()),
1958                       view.getAnnotationColours().getAboveThreshold());
1959             }
1960             else
1961             {
1962               cs = new AnnotationColourGradient(af.viewport.alignment
1963                       .getAlignmentAnnotation()[i], ColourSchemeProperty
1964                       .getColour(al, view.getAnnotationColours()
1965                               .getColourScheme()), view
1966                       .getAnnotationColours().getAboveThreshold());
1967             }
1968
1969             // Also use these settings for all the groups
1970             if (al.getGroups() != null)
1971             {
1972               for (int g = 0; g < al.getGroups().size(); g++)
1973               {
1974                 jalview.datamodel.SequenceGroup sg = (jalview.datamodel.SequenceGroup) al
1975                         .getGroups().elementAt(g);
1976
1977                 if (sg.cs == null)
1978                 {
1979                   continue;
1980                 }
1981
1982                 /*    if (view.getAnnotationColours().getColourScheme().equals("None"))
1983                     {
1984                       sg.cs = new AnnotationColourGradient(
1985                           af.viewport.alignment.getAlignmentAnnotation()[i],
1986                           new java.awt.Color(view.getAnnotationColours().
1987                                              getMinColour()),
1988                           new java.awt.Color(view.getAnnotationColours().
1989                                              getMaxColour()),
1990                           view.getAnnotationColours().getAboveThreshold());
1991                     }
1992                     else*/
1993                 {
1994                   sg.cs = new AnnotationColourGradient(
1995                           af.viewport.alignment.getAlignmentAnnotation()[i],
1996                           sg.cs, view.getAnnotationColours()
1997                                   .getAboveThreshold());
1998                 }
1999
2000               }
2001             }
2002
2003             break;
2004           }
2005
2006         }
2007       }
2008       else
2009       {
2010         cs = ColourSchemeProperty.getColour(al, view.getBgColour());
2011       }
2012
2013       if (cs != null)
2014       {
2015         cs.setThreshold(view.getPidThreshold(), true);
2016         cs.setConsensus(af.viewport.hconsensus);
2017       }
2018     }
2019
2020     af.viewport.setGlobalColourScheme(cs);
2021     af.viewport.setColourAppliesToAllGroups(false);
2022
2023     if (view.getConservationSelected() && cs != null)
2024     {
2025       cs.setConservationInc(view.getConsThreshold());
2026     }
2027
2028     af.changeColour(cs);
2029
2030     af.viewport.setColourAppliesToAllGroups(true);
2031
2032     if (view.getShowSequenceFeatures())
2033     {
2034       af.viewport.showSequenceFeatures = true;
2035     }
2036
2037     if (jms.getFeatureSettings() != null)
2038     {
2039       af.viewport.featuresDisplayed = new Hashtable();
2040       String[] renderOrder = new String[jms.getFeatureSettings()
2041               .getSettingCount()];
2042       for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
2043       {
2044         Setting setting = jms.getFeatureSettings().getSetting(fs);
2045
2046         af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
2047                 setting.getType(), new java.awt.Color(setting.getColour()));
2048         renderOrder[fs] = setting.getType();
2049         if (setting.hasOrder())
2050           af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
2051                   setting.getType(), setting.getOrder());
2052         else
2053           af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
2054                   setting.getType(),
2055                   fs / jms.getFeatureSettings().getSettingCount());
2056         if (setting.getDisplay())
2057         {
2058           af.viewport.featuresDisplayed.put(setting.getType(), new Integer(
2059                   setting.getColour()));
2060         }
2061       }
2062       af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().renderOrder = renderOrder;
2063       Hashtable fgtable;
2064       af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().featureGroups = fgtable = new Hashtable();
2065       for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
2066       {
2067         Group grp = jms.getFeatureSettings().getGroup(gs);
2068         fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
2069       }
2070     }
2071
2072     if (view.getHiddenColumnsCount() > 0)
2073     {
2074       for (int c = 0; c < view.getHiddenColumnsCount(); c++)
2075       {
2076         af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
2077                 .getHiddenColumns(c).getEnd() //+1
2078                 );
2079       }
2080     }
2081
2082     af.setMenusFromViewport(af.viewport);
2083
2084     Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(), view
2085             .getHeight());
2086
2087     //LOAD TREES
2088     ///////////////////////////////////////
2089     if (loadTreesAndStructures && jms.getTreeCount() > 0)
2090     {
2091       try
2092       {
2093         for (int t = 0; t < jms.getTreeCount(); t++)
2094         {
2095
2096           Tree tree = jms.getTree(t);
2097
2098           TreePanel tp = af.ShowNewickTree(new jalview.io.NewickFile(tree
2099                   .getNewick()), tree.getTitle(), tree.getWidth(), tree
2100                   .getHeight(), tree.getXpos(), tree.getYpos());
2101
2102           tp.fitToWindow.setState(tree.getFitToWindow());
2103           tp.fitToWindow_actionPerformed(null);
2104
2105           if (tree.getFontName() != null)
2106           {
2107             tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
2108                     .getFontStyle(), tree.getFontSize()));
2109           }
2110           else
2111           {
2112             tp.setTreeFont(new java.awt.Font(view.getFontName(), view
2113                     .getFontStyle(), tree.getFontSize()));
2114           }
2115
2116           tp.showPlaceholders(tree.getMarkUnlinked());
2117           tp.showBootstrap(tree.getShowBootstrap());
2118           tp.showDistances(tree.getShowDistances());
2119
2120           tp.treeCanvas.threshold = tree.getThreshold();
2121
2122           if (tree.getCurrentTree())
2123           {
2124             af.viewport.setCurrentTree(tp.getTree());
2125           }
2126         }
2127
2128       } catch (Exception ex)
2129       {
2130         ex.printStackTrace();
2131       }
2132     }
2133
2134     ////LOAD STRUCTURES
2135     if (loadTreesAndStructures)
2136     {
2137       for (int i = 0; i < JSEQ.length; i++)
2138       {
2139         if (JSEQ[i].getPdbidsCount() > 0)
2140         {
2141           Pdbids[] ids = JSEQ[i].getPdbids();
2142           for (int p = 0; p < ids.length; p++)
2143           {
2144             for (int s = 0; s < ids[p].getStructureStateCount(); s++)
2145             {
2146               jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
2147
2148               jpdb.setFile(loadPDBFile(ids[p].getFile(), ids[p].getId()));
2149               jpdb.setId(ids[p].getId());
2150
2151               int x = ids[p].getStructureState(s).getXpos();
2152               int y = ids[p].getStructureState(s).getYpos();
2153               int width = ids[p].getStructureState(s).getWidth();
2154               int height = ids[p].getStructureState(s).getHeight();
2155
2156               java.awt.Component comp = null;
2157               
2158               JInternalFrame[] frames = null;
2159               do {
2160                 try {
2161                   frames = Desktop.desktop.getAllFrames();
2162                 }
2163                 catch (ArrayIndexOutOfBoundsException e)
2164                 {
2165                   // occasional No such child exceptions are thrown here...
2166                   frames = null;
2167                   try {
2168                     Thread.sleep(10);
2169                   } catch (Exception f) {};
2170                 }
2171               } while (frames==null);
2172               for (int f = 0; f < frames.length; f++)
2173               {
2174                 if (frames[f] instanceof AppJmol)
2175                 {
2176                   if (frames[f].getX() == x && frames[f].getY() == y
2177                           && frames[f].getHeight() == height
2178                           && frames[f].getWidth() == width)
2179                   {
2180                     comp = frames[f];
2181                     break;
2182                   }
2183                 }
2184               }
2185
2186               Desktop.desktop.getComponentAt(x, y);
2187
2188               String pdbFile = loadPDBFile(file, ids[p].getId());
2189
2190               jalview.datamodel.SequenceI[] seq = new jalview.datamodel.SequenceI[]
2191               { (jalview.datamodel.SequenceI) seqRefIds.get(JSEQ[i].getId()
2192                       + "") };
2193
2194               if (comp == null)
2195               {
2196                 String state = ids[p].getStructureState(s).getContent();
2197
2198                 StringBuffer newFileLoc = new StringBuffer(state.substring(
2199                         0, state.indexOf("\"", state.indexOf("load")) + 1));
2200
2201                 newFileLoc.append(jpdb.getFile());
2202                 newFileLoc.append(state.substring(state.indexOf("\"", state
2203                         .indexOf("load \"") + 6)));
2204
2205                 new AppJmol(pdbFile, ids[p].getId(), seq, af.alignPanel,
2206                         newFileLoc.toString(), new java.awt.Rectangle(x, y,
2207                                 width, height));
2208
2209               }
2210               else if (comp != null)
2211               {
2212                 StructureSelectionManager.getStructureSelectionManager()
2213                         .setMapping(seq, null, pdbFile,
2214                                 jalview.io.AppletFormatAdapter.FILE);
2215
2216                 ((AppJmol) comp).addSequence(seq);
2217               }
2218             }
2219           }
2220         }
2221       }
2222     }
2223
2224     return af;
2225   }
2226
2227   private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al)
2228   {
2229     jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
2230     Vector dseqs = null;
2231     if (ds == null)
2232     {
2233       // create a list of new dataset sequences
2234       dseqs = new Vector();
2235     }
2236     for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
2237     {
2238       Sequence vamsasSeq = vamsasSet.getSequence(i);
2239       ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs);
2240     }
2241     // create a new dataset
2242     if (ds == null)
2243     {
2244       SequenceI[] dsseqs = new SequenceI[dseqs.size()];
2245       dseqs.copyInto(dsseqs);
2246       ds = new jalview.datamodel.Alignment(dsseqs);
2247       addDatasetRef(vamsasSet.getDatasetId(), ds);
2248     }
2249     // set the dataset for the newly imported alignment.
2250     if (al.getDataset() == null)
2251     {
2252       al.setDataset(ds);
2253     }
2254   }
2255   
2256
2257   /**
2258    * 
2259    * @param vamsasSeq sequence definition to create/merge dataset sequence for
2260    * @param ds dataset alignment 
2261    * @param dseqs vector to add new dataset sequence to
2262    */
2263   private void ensureJalviewDatasetSequence(Sequence vamsasSeq, AlignmentI ds, Vector dseqs)
2264   {
2265     jalview.datamodel.Sequence sq = (jalview.datamodel.Sequence) seqRefIds.get(vamsasSeq.getId());
2266     jalview.datamodel.SequenceI dsq = null;
2267     if (sq!=null && sq.getDatasetSequence()!=null)
2268     {
2269       dsq = (jalview.datamodel.SequenceI) sq.getDatasetSequence();
2270     }
2271     
2272     String sqid = vamsasSeq.getDsseqid();
2273     if (dsq==null)
2274     {
2275       // need to create or add a new dataset sequence reference to this sequence
2276       if (sqid != null)
2277       {
2278         dsq = (jalview.datamodel.SequenceI) seqRefIds.get(sqid);
2279       }
2280       // check again
2281       if (dsq == null)
2282       {
2283         // make a new dataset sequence
2284         dsq = sq.createDatasetSequence();
2285         if (sqid == null)
2286         {
2287           // make up a new dataset reference for this sequence
2288           sqid = seqHash(dsq);
2289         }
2290         dsq.setVamsasId(uniqueSetSuffix + sqid);
2291         seqRefIds.put(sqid, dsq);
2292         if (ds == null)
2293         {
2294           if (dseqs!=null)
2295           {
2296             dseqs.addElement(dsq);
2297           }
2298         }
2299         else
2300         {
2301           ds.addSequence(dsq);
2302         }
2303       } else {
2304         if (sq!=dsq)
2305         {  // make this dataset sequence sq's dataset sequence
2306           sq.setDatasetSequence(dsq);
2307         }
2308       }
2309     }
2310     // TODO: refactor this as a merge dataset sequence function
2311     // now check that sq (the dataset sequence) sequence really is the union of all references to it
2312     //boolean pre = sq.getStart() < dsq.getStart();
2313     //boolean post = sq.getEnd() > dsq.getEnd();
2314     //if (pre || post)
2315     if (sq!=dsq)
2316     {
2317       StringBuffer sb = new StringBuffer();
2318       String newres = jalview.analysis.AlignSeq.extractGaps(
2319               jalview.util.Comparison.GapChars, sq.getSequenceAsString());
2320       if (!newres.equalsIgnoreCase(dsq.getSequenceAsString()) && newres.length()>dsq.getLength())
2321       {
2322         // Update with the longer sequence.
2323         synchronized (dsq)
2324         {
2325         /*if (pre)
2326         {
2327           sb.insert(0, newres
2328                   .substring(0, dsq.getStart() - sq.getStart()));
2329           dsq.setStart(sq.getStart());
2330         }
2331         if (post)
2332         {
2333           sb.append(newres.substring(newres.length() - sq.getEnd()
2334                   - dsq.getEnd()));
2335           dsq.setEnd(sq.getEnd());
2336         }
2337         */
2338         dsq.setSequence(sb.toString());
2339         }
2340         //TODO: merges will never happen if we 'know' we have the real dataset sequence - this should be detected when id==dssid
2341         System.err
2342               .println("DEBUG Notice:  Merged dataset sequence"); // ("
2343                       // + (pre ? "prepended" : "") + " "
2344                       //+ (post ? "appended" : ""));
2345       }
2346     }
2347   }
2348
2349   java.util.Hashtable datasetIds = null;
2350
2351   private Alignment getDatasetFor(String datasetId)
2352   {
2353     if (datasetIds == null)
2354     {
2355       datasetIds = new Hashtable();
2356       return null;
2357     }
2358     if (datasetIds.containsKey(datasetId))
2359     {
2360       return (Alignment) datasetIds.get(datasetId);
2361     }
2362     return null;
2363   }
2364
2365   private void addDatasetRef(String datasetId, Alignment dataset)
2366   {
2367     if (datasetIds == null)
2368     {
2369       datasetIds = new Hashtable();
2370     }
2371     datasetIds.put(datasetId, dataset);
2372   }
2373
2374   private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
2375   {
2376     for (int d = 0; d < sequence.getDBRefCount(); d++)
2377     {
2378       DBRef dr = sequence.getDBRef(d);
2379       jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
2380               sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
2381                       .getVersion(), sequence.getDBRef(d).getAccessionId());
2382       if (dr.getMapping() != null)
2383       {
2384         entry.setMap(addMapping(dr.getMapping()));
2385       }
2386       datasetSequence.addDBRef(entry);
2387     }
2388   }
2389
2390   private jalview.datamodel.Mapping addMapping(Mapping m)
2391   {
2392     SequenceI dsto = null;
2393     // Mapping m = dr.getMapping();
2394     int fr[] = new int[m.getMapListFromCount() * 2];
2395     Enumeration f = m.enumerateMapListFrom();
2396     for (int _i = 0; f.hasMoreElements(); _i += 2)
2397     {
2398       MapListFrom mf = (MapListFrom) f.nextElement();
2399       fr[_i] = mf.getStart();
2400       fr[_i + 1] = mf.getEnd();
2401     }
2402     int fto[] = new int[m.getMapListToCount() * 2];
2403     f = m.enumerateMapListTo();
2404     for (int _i = 0; f.hasMoreElements(); _i += 2)
2405     {
2406       MapListTo mf = (MapListTo) f.nextElement();
2407       fto[_i] = mf.getStart();
2408       fto[_i + 1] = mf.getEnd();
2409     }
2410     jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
2411             fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
2412     if (m.getMappingChoice() != null)
2413     {
2414       MappingChoice mc = m.getMappingChoice();
2415       if (mc.getDseqFor() != null)
2416       {
2417         if (seqRefIds.containsKey(mc.getDseqFor()))
2418         {
2419           /**
2420            * recover from hash
2421            */
2422           jmap.setTo((SequenceI) seqRefIds.get(mc.getDseqFor()));
2423         }
2424         else
2425         {
2426           frefedSequence.add(new Object[]
2427           { mc.getDseqFor(), jmap });
2428         }
2429       }
2430       else
2431       {
2432         /**
2433          * local sequence definition
2434          */
2435         Sequence ms = mc.getSequence();
2436         jalview.datamodel.Sequence djs=null;
2437         String sqid = ms.getDsseqid();
2438         if (sqid!=null && sqid.length()>0)
2439         {
2440           /*
2441            * recover dataset sequence
2442            */
2443           djs = (jalview.datamodel.Sequence) seqRefIds.get(sqid);
2444         } else {
2445           System.err.println("Warning - making up dataset sequence id for DbRef sequence map reference");
2446           sqid = ((Object)ms).toString(); // make up a new hascode for undefined dataset sequence hash (unlikely to happen)
2447         }
2448         
2449         if (djs==null) {
2450           /**
2451            * make a new dataset sequence and add it to refIds hash
2452            */
2453           djs = new jalview.datamodel.Sequence(ms
2454                 .getName(), ms.getSequence());
2455           djs.setStart(jmap.getMap().getToLowest());
2456           djs.setEnd(jmap.getMap().getToHighest());
2457           djs.setVamsasId(uniqueSetSuffix + sqid);
2458           jmap.setTo(djs);
2459           seqRefIds.put(sqid, djs);
2460           
2461         }
2462         jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
2463         addDBRefs(djs, ms);
2464         
2465       }
2466     }
2467     return (jmap);
2468
2469   }
2470
2471   public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
2472           boolean keepSeqRefs)
2473   {
2474     jalview.schemabinding.version2.JalviewModel jm = SaveState(ap, null,
2475             null, null);
2476
2477     if (!keepSeqRefs)
2478     {
2479       clearSeqRefs();
2480       jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
2481     }
2482     else
2483     {
2484       uniqueSetSuffix = "";
2485     }
2486
2487     viewportsAdded = new Hashtable();
2488
2489     AlignFrame af = LoadFromObject(jm, null, false);
2490     af.alignPanels.clear();
2491     af.closeMenuItem_actionPerformed(true);
2492
2493     /*  if(ap.av.alignment.getAlignmentAnnotation()!=null)
2494       {
2495         for(int i=0; i<ap.av.alignment.getAlignmentAnnotation().length; i++)
2496         {
2497           if(!ap.av.alignment.getAlignmentAnnotation()[i].autoCalculated)
2498           {
2499             af.alignPanel.av.alignment.getAlignmentAnnotation()[i] =
2500                 ap.av.alignment.getAlignmentAnnotation()[i];
2501           }
2502         }
2503       }   */
2504
2505     return af.alignPanel;
2506   }
2507   /* (non-Javadoc)
2508    * @see java.lang.Object#finalize()
2509    */
2510   protected void finalize() throws Throwable
2511   {
2512     // really make sure we have no buried refs left.
2513     clearSeqRefs();
2514     this.seqRefIds = null;
2515     this.seqsToIds = null;
2516     super.finalize();
2517   }
2518   
2519 }