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