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