bugfix for vamsas demo
[jalview.git] / src / jalview / io / VamsasAppDatastore.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2005 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
20 package jalview.io;
21
22 import jalview.bin.Cache;
23 import jalview.datamodel.AlignmentAnnotation;
24 import jalview.datamodel.AlignmentI;
25 import jalview.datamodel.AlignmentView;
26 import jalview.datamodel.DBRefEntry;
27 import jalview.datamodel.GraphLine;
28 import jalview.datamodel.SequenceFeature;
29 import jalview.datamodel.SequenceI;
30 import jalview.gui.AlignFrame;
31 import jalview.gui.AlignViewport;
32 import jalview.gui.Desktop;
33 import jalview.gui.TreePanel;
34 import jalview.io.vamsas.DatastoreItem;
35 import jalview.io.vamsas.Rangetype;
36
37 import java.util.Enumeration;
38 import java.util.HashMap;
39 import java.util.Hashtable;
40 import java.util.IdentityHashMap;
41 import java.util.Vector;
42
43 import uk.ac.vamsas.client.*;
44 import uk.ac.vamsas.objects.core.*;
45
46 /*
47  * 
48  * static {
49  * org.exolab.castor.util.LocalConfiguration.getInstance().getProperties().setProperty(
50  * "org.exolab.castor.serializer", "org.apache.xml.serialize.XMLSerilazizer"); }
51  * 
52  */
53
54 public class VamsasAppDatastore
55 {
56   /**
57    * Type used for general jalview generated annotation added to vamsas document
58    */
59   public static final String JALVIEW_ANNOTATION_ROW = "JalviewAnnotation";
60
61   /**
62    * AlignmentAnnotation property to indicate that values should not be interpolated
63    */
64   public static final String DISCRETE_ANNOTATION = "discrete";
65   /**
66    * continuous property - optional to specify that annotation should be represented
67    * as a continous graph line
68    */
69   private static final String CONTINUOUS_ANNOTATION = "continuous";
70
71   private static final String THRESHOLD = "threshold"; 
72   
73
74   Entry provEntry = null;
75
76   IClientDocument cdoc;
77
78   Hashtable vobj2jv;
79
80   IdentityHashMap jv2vobj;
81
82   public VamsasAppDatastore(IClientDocument cdoc, Hashtable vobj2jv,
83           IdentityHashMap jv2vobj, Entry provEntry)
84   {
85     this.cdoc = cdoc;
86     this.vobj2jv = vobj2jv;
87     this.jv2vobj = jv2vobj;
88     this.provEntry = provEntry;
89   }
90
91   /**
92    * @return the Vobject bound to Jalview datamodel object
93    */
94   protected Vobject getjv2vObj(Object jvobj)
95   {
96     if (jv2vobj.containsKey(jvobj))
97     {
98       return cdoc.getObject((VorbaId) jv2vobj.get(jvobj));
99     }
100     if (Cache.log.isDebugEnabled())
101     {
102       Cache.log.debug("Returning null VorbaID binding for jalview object "
103               + jvobj);
104     }
105     return null;
106   }
107
108   /**
109    * 
110    * @param vobj
111    * @return Jalview datamodel object bound to the vamsas document object
112    */
113   protected Object getvObj2jv(uk.ac.vamsas.client.Vobject vobj)
114   {
115     VorbaId id = vobj.getVorbaId();
116     if (id == null)
117     {
118       id = cdoc.registerObject(vobj);
119       Cache.log
120               .debug("Registering new object and returning null for getvObj2jv");
121       return null;
122     }
123     if (vobj2jv.containsKey(vobj.getVorbaId()))
124     {
125       return vobj2jv.get(vobj.getVorbaId());
126     }
127     return null;
128   }
129
130   protected void bindjvvobj(Object jvobj, uk.ac.vamsas.client.Vobject vobj)
131   {
132     VorbaId id = vobj.getVorbaId();
133     if (id == null)
134     {
135       id = cdoc.registerObject(vobj);
136       if (id == null || vobj.getVorbaId() == null
137               || cdoc.getObject(id) != vobj)
138       {
139         Cache.log.error("Failed to get id for "
140                 + (vobj.isRegisterable() ? "registerable"
141                         : "unregisterable") + " object " + vobj);
142       }
143     }
144
145     if (vobj2jv.containsKey(vobj.getVorbaId())
146             && !((VorbaId) vobj2jv.get(vobj.getVorbaId())).equals(jvobj))
147     {
148       Cache.log.debug(
149               "Warning? Overwriting existing vamsas id binding for "
150                       + vobj.getVorbaId(), new Exception(
151                       "Overwriting vamsas id binding."));
152     }
153     else if (jv2vobj.containsKey(jvobj)
154             && !((VorbaId) jv2vobj.get(jvobj)).equals(vobj.getVorbaId()))
155     {
156       Cache.log.debug(
157               "Warning? Overwriting existing jalview object binding for "
158                       + jvobj, new Exception(
159                       "Overwriting jalview object binding."));
160     }
161     /*
162      * Cache.log.error("Attempt to make conflicting object binding! "+vobj+" id "
163      * +vobj.getVorbaId()+" already bound to "+getvObj2jv(vobj)+" and "+jvobj+"
164      * already bound to "+getjv2vObj(jvobj),new Exception("Excessive call to
165      * bindjvvobj")); }
166      */
167     // we just update the hash's regardless!
168     Cache.log.debug("Binding " + vobj.getVorbaId() + " to " + jvobj);
169     vobj2jv.put(vobj.getVorbaId(), jvobj);
170     // JBPNote - better implementing a hybrid invertible hash.
171     jv2vobj.put(jvobj, vobj.getVorbaId());
172   }
173
174   /**
175    * put the alignment viewed by AlignViewport into cdoc.
176    * 
177    * @param av
178    *          alignViewport to be stored
179    * @param aFtitle
180    *          title for alignment
181    */
182   public void storeVAMSAS(AlignViewport av, String aFtitle)
183   {
184     try
185     {
186       jalview.datamodel.AlignmentI jal = av.getAlignment();
187       boolean nw = false;
188       VAMSAS root = null; // will be resolved based on Dataset Parent.
189       // /////////////////////////////////////////
190       // SAVE THE DATASET
191       DataSet dataset = null;
192       if (jal.getDataset() == null)
193       {
194         Cache.log.warn("Creating new dataset for an alignment.");
195         jal.setDataset(null);
196       }
197       dataset = (DataSet) getjv2vObj(jal.getDataset());
198       if (dataset == null)
199       {
200         // it might be that one of the dataset sequences does actually have a
201         // binding, so search for it indirectly.
202         jalview.datamodel.SequenceI[] jdatset = jal.getDataset()
203                 .getSequencesArray();
204         for (int i = 0; i < jdatset.length; i++)
205         {
206           Vobject vbound = getjv2vObj(jdatset[i]);
207           if (vbound != null)
208           {
209             if (vbound instanceof uk.ac.vamsas.objects.core.Sequence)
210             {
211               if (dataset == null)
212               {
213                 dataset = (DataSet) vbound.getV_parent();
214               }
215               else
216               {
217                 if (dataset != vbound.getV_parent())
218                 {
219                   throw new Error(
220                           "IMPLEMENTATION ERROR: Cannot map an alignment of sequences from datasets into the vamsas document.");
221                   // This occurs because the dataset for the alignment we are
222                   // trying to
223                 }
224               }
225             }
226           }
227         }
228       }
229
230       if (dataset == null)
231       {
232         // we create a new dataset on the default vamsas root.
233         root = cdoc.getVamsasRoots()[0]; // default vamsas root for modifying.
234         dataset = new DataSet();
235         root.addDataSet(dataset);
236         bindjvvobj(jal.getDataset(), dataset);
237         dataset.setProvenance(dummyProvenance());
238         dataset.getProvenance().addEntry(provEntry);
239         nw = true;
240       }
241       else
242       {
243         root = (VAMSAS) dataset.getV_parent();
244       }
245       // update dataset
246       Sequence sequence;
247       DbRef dbref;
248       // set new dataset and alignment sequences based on alignment Nucleotide
249       // flag.
250       // this *will* break when alignment contains both nucleotide and amino
251       // acid sequences.
252       String dict = jal.isNucleotide() ? uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA
253               : uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_AA;
254       for (int i = 0; i < jal.getHeight(); i++)
255       {
256         SequenceI sq = jal.getSequenceAt(i).getDatasetSequence(); // only insert
257         // referenced
258         // sequences
259         // to dataset.
260         sequence = (Sequence) getjv2vObj(sq);
261         if (sequence == null)
262         {
263           sequence = new Sequence();
264           bindjvvobj(sq, sequence);
265           sq.setVamsasId(sequence.getVorbaId().getId());
266           sequence.setSequence(sq.getSequenceAsString());
267           sequence.setDictionary(dict);
268           sequence.setName(jal.getDataset().getSequenceAt(i).getName());
269           sequence.setStart(jal.getDataset().getSequenceAt(i).getStart());
270           sequence.setEnd(jal.getDataset().getSequenceAt(i).getEnd());
271           sequence.setDescription(jal.getDataset().getSequenceAt(i)
272                   .getDescription());
273           dataset.addSequence(sequence);
274         }
275         else
276         {
277           // verify principal attributes. and update any new
278           // features/references.
279           System.out.println("update dataset sequence object.");
280         }
281         if (sq.getSequenceFeatures() != null)
282         {
283           int sfSize = sq.getSequenceFeatures().length;
284
285           for (int sf = 0; sf < sfSize; sf++)
286           {
287             jalview.datamodel.SequenceFeature feature = (jalview.datamodel.SequenceFeature) sq
288                     .getSequenceFeatures()[sf];
289
290             DataSetAnnotations dsa = (DataSetAnnotations) getjv2vObj(feature);
291             if (dsa == null)
292             {
293               dsa = (DataSetAnnotations) getDSAnnotationFromJalview(
294                       new DataSetAnnotations(), feature);
295               if (dsa.getProvenance() == null)
296               {
297                 dsa.setProvenance(new Provenance());
298               }
299               addProvenance(dsa.getProvenance(), "created"); // JBPNote - need
300               // to update
301               dsa.addSeqRef(sequence); // we have just created this annotation
302                                         // - so safe to use this
303               bindjvvobj(feature, dsa);
304               dataset.addDataSetAnnotations(dsa);
305             }
306             else
307             {
308               // todo: verify and update dataset annotations for sequence
309               System.out.println("update dataset sequence annotations.");
310             }
311           }
312         }
313
314         if (sq.getDBRef() != null)
315         {
316           DBRefEntry[] entries = sq.getDBRef();
317           jalview.datamodel.DBRefEntry dbentry;
318           for (int db = 0; db < entries.length; db++)
319           {
320             Rangetype dbr = new jalview.io.vamsas.Dbref(this,
321                     dbentry = entries[db], sq, sequence);
322           }
323
324         }
325       }
326       // dataset.setProvenance(getVamsasProvenance(jal.getDataset().getProvenance()));
327       // ////////////////////////////////////////////
328       if (!av.getAlignment().isAligned())
329         return; // TODO: trees could be written - but for the moment we just skip
330       
331       // ////////////////////////////////////////////
332       // Save the Alignments
333
334       Alignment alignment = (Alignment) getjv2vObj(av); // this is so we can get
335                                                         // the alignviewport
336                                                         // back
337       if (alignment == null)
338       {
339         alignment = new Alignment();
340         bindjvvobj(av, alignment);
341         if (alignment.getProvenance() == null)
342         {
343           alignment.setProvenance(new Provenance());
344         }
345         addProvenance(alignment.getProvenance(), "added"); // TODO: insert some
346         // sensible source
347         // here
348         dataset.addAlignment(alignment);
349         {
350           Property title = new Property();
351           title.setName("title");
352           title.setType("string");
353           title.setContent(aFtitle);
354           alignment.addProperty(title);
355         }
356         alignment.setGapChar(String.valueOf(av.getGapCharacter()));
357         AlignmentSequence alseq = null;
358         for (int i = 0; i < jal.getHeight(); i++)
359         {
360           alseq = new AlignmentSequence();
361           // TODO: VAMSAS: translate lowercase symbols to annotation ?
362           alseq.setSequence(jal.getSequenceAt(i).getSequenceAsString());
363           alseq.setName(jal.getSequenceAt(i).getName());
364           alseq.setStart(jal.getSequenceAt(i).getStart());
365           alseq.setEnd(jal.getSequenceAt(i).getEnd());
366           if (getjv2vObj(jal.getSequenceAt(i).getDatasetSequence()) == null)
367           {
368             Cache.log
369                     .warn("Serious. Unbound dataset sequence in alignment: "
370                             + jal.getSequenceAt(i).getDatasetSequence());
371           }
372           alseq.setRefid(getjv2vObj(jal.getSequenceAt(i)
373                   .getDatasetSequence()));
374           alignment.addAlignmentSequence(alseq);
375           bindjvvobj(jal.getSequenceAt(i), alseq);
376         }
377       }
378       else
379       {
380         // todo: verify and update mutable alignment props.
381         if (alignment.getModifiable() == null) // TODO: USE VAMSAS LIBRARY
382                                                 // OBJECT LOCK METHODS
383         {
384           System.out.println("update alignment in document.");
385         }
386         else
387         {
388           System.out
389                   .println("update edited alignment to new alignment in document.");
390         }
391       }
392       // ////////////////////////////////////////////
393       // SAVE Alignment Sequence Features
394       for (int i = 0, iSize = alignment.getAlignmentSequenceCount(); i < iSize; i++)
395       {
396         AlignmentSequence valseq;
397         SequenceI alseq = (SequenceI) getvObj2jv(valseq = alignment
398                 .getAlignmentSequence(i));
399         if (alseq != null && alseq.getSequenceFeatures() != null)
400         {
401           /*
402            * We do not put local Alignment Sequence Features into the vamsas
403            * document yet.
404            * 
405            * 
406            * jalview.datamodel.SequenceFeature[] features = alseq
407            * .getSequenceFeatures(); for (int f = 0; f < features.length; f++) {
408            * if (features[f] != null) { AlignmentSequenceAnnotation valseqf = (
409            * AlignmentSequenceAnnotation) getjv2vObj(features[i]); if (valseqf ==
410            * null) {
411            * 
412            * valseqf = (AlignmentSequenceAnnotation) getDSAnnotationFromJalview(
413            * new AlignmentSequenceAnnotation(), features[i]);
414            * valseqf.setGraph(false);
415            * valseqf.addProperty(newProperty("jalview:feature","boolean","true"));
416            * if (valseqf.getProvenance() == null) { valseqf.setProvenance(new
417            * Provenance()); } addProvenance(valseqf.getProvenance(), "created"); //
418            * JBPNote - // need to // update bindjvvobj(features[i], valseqf);
419            * valseq.addAlignmentSequenceAnnotation(valseqf); } }
420            *  }
421            */
422         }
423       }
424
425       // ////////////////////////////////////////////
426       // SAVE ANNOTATIONS
427       if (jal.getAlignmentAnnotation() != null)
428       {
429         jalview.datamodel.AlignmentAnnotation[] aa = jal
430                 .getAlignmentAnnotation();
431         java.util.HashMap AlSeqMaps = new HashMap(); // stores int maps from
432         // alignment columns to
433         // sequence positions.
434         for (int i = 0; i < aa.length; i++)
435         {
436           if (aa[i] == null || isJalviewOnly(aa[i]))
437           {
438             continue;
439           }
440           if (aa[i].sequenceRef != null)
441           {
442             // Deal with sequence associated annotation
443             Vobject sref = getjv2vObj(aa[i].sequenceRef);
444             if (sref instanceof uk.ac.vamsas.objects.core.AlignmentSequence)
445             {
446               saveAlignmentSequenceAnnotation(AlSeqMaps,
447                       (AlignmentSequence) sref, aa[i]);
448             }
449             else
450             {
451               // first find the alignment sequence to associate this with.
452               SequenceI jvalsq = null;
453               Enumeration jval = av.getAlignment().getSequences()
454                       .elements();
455               while (jval.hasMoreElements())
456               {
457                 jvalsq = (SequenceI) jval.nextElement();
458                 // saveDatasetSequenceAnnotation(AlSeqMaps,(uk.ac.vamsas.objects.core.Sequence)
459                 // sref, aa[i]);
460                 if (jvalsq.getDatasetSequence() == aa[i].sequenceRef)
461                 {
462                   Vobject alsref = getjv2vObj(jvalsq);
463                   saveAlignmentSequenceAnnotation(AlSeqMaps,
464                           (AlignmentSequence) alsref, aa[i]);
465                   break;
466                 }
467                 ;
468               }
469             }
470           }
471           else
472           {
473             // add Alignment Annotation
474             uk.ac.vamsas.objects.core.AlignmentAnnotation an = (uk.ac.vamsas.objects.core.AlignmentAnnotation) getjv2vObj(aa[i]);
475             if (an == null)
476             {
477               an = new uk.ac.vamsas.objects.core.AlignmentAnnotation();
478               an.setType(JALVIEW_ANNOTATION_ROW);
479               an.setDescription(aa[i].description);
480               alignment.addAlignmentAnnotation(an);
481               Seg vSeg = new Seg(); // TODO: refactor to have a default
482                                     // rangeAnnotationType initer/updater that
483                                     // takes a set of int ranges.
484               vSeg.setStart(1);
485               vSeg.setInclusive(true);
486               vSeg.setEnd(jal.getWidth());
487               an.addSeg(vSeg);
488               if (aa[i].graph > 0)
489               {
490                 an.setGraph(true); // aa[i].graph);
491               }
492               an.setLabel(aa[i].label);
493               an.setProvenance(dummyProvenance());
494               if (aa[i].graph != AlignmentAnnotation.NO_GRAPH)
495               {
496                 an.setGroup(Integer.toString(aa[i].graphGroup)); // // JBPNote
497                                                                   // -
498                 // originally we
499                 // were going to
500                 // store
501                 // graphGroup in
502                 // the Jalview
503                 // specific
504                 // bits.
505                 an.setGraph(true);
506               }
507               else
508               {
509                 an.setGraph(false);
510               }
511               AnnotationElement ae;
512
513               for (int a = 0; a < aa[i].annotations.length; a++)
514               {
515                 if ((aa[i] == null) || (aa[i].annotations[a] == null))
516                 {
517                   continue;
518                 }
519
520                 ae = new AnnotationElement();
521                 ae.setDescription(aa[i].annotations[a].description);
522                 ae.addGlyph(new Glyph());
523                 ae.getGlyph(0).setContent(
524                         aa[i].annotations[a].displayCharacter); // assume
525                 // jax-b
526                 // takes
527                 // care
528                 // of
529                 // utf8
530                 // translation
531                 ae.addValue(aa[i].annotations[a].value);
532                 ae.setPosition(a + 1);
533                 if (aa[i].annotations[a].secondaryStructure != ' ')
534                 {
535                   Glyph ss = new Glyph();
536                   ss
537                           .setDict(uk.ac.vamsas.objects.utils.GlyphDictionary.PROTEIN_SS_3STATE);
538                   ss
539                           .setContent(String
540                                   .valueOf(aa[i].annotations[a].secondaryStructure));
541                   ae.addGlyph(ss);
542                 }
543                 an.addAnnotationElement(ae);
544               }
545               if (aa[i].editable)
546               {
547                 // an.addProperty(newProperty("jalview:editable", null,
548                 // "true"));
549                 // an.setModifiable(""); // TODO: This is not the way the
550                 // modifiable flag is supposed to be used.
551               }
552               setAnnotationType(an, aa[i]);
553               
554               if (aa[i].graph != jalview.datamodel.AlignmentAnnotation.NO_GRAPH)
555               {
556                 an.setGraph(true);
557                 an.setGroup(Integer.toString(aa[i].graphGroup));
558                 if (aa[i].threshold!=null && aa[i].threshold.displayed)
559                   an.addProperty(newProperty(THRESHOLD, "float", ""+aa[i].threshold.value));
560                   if (aa[i].threshold.label!=null)
561                     an.addProperty(newProperty(THRESHOLD+"Name", "string", ""+aa[i].threshold.label));
562                 }
563               
564               }
565             
566             else
567             {
568               if (an.getModifiable() == null) // TODO: USE VAMSAS LIBRARY OBJECT
569                                               // LOCK METHODS)
570               {
571                 // verify annotation - update (perhaps)
572                 Cache.log
573                         .info("update alignment sequence annotation. not yet implemented.");
574               }
575               else
576               {
577                 // verify annotation - update (perhaps)
578                 Cache.log
579                         .info("updated alignment sequence annotation added.");
580               }
581             }
582           }
583         }
584       }
585       // /////////////////////////////////////////////////////
586
587       // //////////////////////////////////////////////
588       // /SAVE THE TREES
589       // /////////////////////////////////
590       // FIND ANY ASSOCIATED TREES
591       if (Desktop.desktop != null)
592       {
593         javax.swing.JInternalFrame[] frames = Desktop.instance
594                 .getAllFrames();
595
596         for (int t = 0; t < frames.length; t++)
597         {
598           if (frames[t] instanceof TreePanel)
599           {
600             TreePanel tp = (TreePanel) frames[t];
601
602             if (tp.getAlignment() == jal)
603             {
604               DatastoreItem vtree = new jalview.io.vamsas.Tree(this, tp,
605                       jal, alignment);
606             }
607           }
608         }
609       }
610       // Store Jalview specific stuff in the Jalview appData
611       // not implemented in the SimpleDoc interface.
612     }
613
614     catch (Exception ex)
615     {
616       ex.printStackTrace();
617     }
618
619   }
620
621   private void initRangeAnnotationType(RangeAnnotation an,
622           AlignmentAnnotation alan, int[] gapMap)
623   {
624     Seg vSeg = new Seg();
625     vSeg.setStart(1);
626     vSeg.setInclusive(true);
627     vSeg.setEnd(gapMap.length);
628     an.addSeg(vSeg);
629
630     // LATER: much of this is verbatim from the alignmentAnnotation
631     // method below. suggests refactoring to make rangeAnnotation the
632     // base class
633     an.setDescription(alan.description);
634     an.setLabel(alan.label);
635     an.setGroup(Integer.toString(alan.graphGroup));
636     // // JBPNote -
637     // originally we
638     // were going to
639     // store
640     // graphGroup in
641     // the Jalview
642     // specific
643     // bits.
644     AnnotationElement ae;
645     for (int a = 0; a < alan.annotations.length; a++)
646     {
647       if (alan.annotations[a] == null)
648       {
649         continue;
650       }
651
652       ae = new AnnotationElement();
653       ae.setDescription(alan.annotations[a].description);
654       ae.addGlyph(new Glyph());
655       ae.getGlyph(0).setContent(alan.annotations[a].displayCharacter); // assume
656       // jax-b
657       // takes
658       // care
659       // of
660       // utf8
661       // translation
662       if (alan.graph != jalview.datamodel.AlignmentAnnotation.NO_GRAPH)
663       {
664         ae.addValue(alan.annotations[a].value);
665       }
666       ae.setPosition(gapMap[a] + 1); // position w.r.t. AlignmentSequence
667       // symbols
668       if (alan.annotations[a].secondaryStructure != ' ')
669       {
670         // we only write an annotation where it really exists.
671         Glyph ss = new Glyph();
672         ss
673                 .setDict(uk.ac.vamsas.objects.utils.GlyphDictionary.PROTEIN_SS_3STATE);
674         ss.setContent(String
675                 .valueOf(alan.annotations[a].secondaryStructure));
676         ae.addGlyph(ss);
677       }
678       an.addAnnotationElement(ae);
679     }
680
681   }
682
683   private void saveDatasetSequenceAnnotation(HashMap AlSeqMaps,
684           uk.ac.vamsas.objects.core.Sequence sref, AlignmentAnnotation alan)
685   {
686     // {
687     // uk.ac.vamsas.
688     // objects.core.AlignmentSequence alsref = (uk.ac.vamsas.
689     // objects.core.AlignmentSequence) sref;
690     uk.ac.vamsas.objects.core.DataSetAnnotations an = (uk.ac.vamsas.objects.core.DataSetAnnotations) getjv2vObj(alan);
691     int[] gapMap = getGapMap(AlSeqMaps, alan);
692     if (an == null)
693     {
694       an = new uk.ac.vamsas.objects.core.DataSetAnnotations();
695       initRangeAnnotationType(an, alan, gapMap);
696
697       an.setProvenance(dummyProvenance()); // get provenance as user
698       // created, or jnet, or
699       // something else.
700       setAnnotationType(an, alan);
701       an.setGroup(Integer.toString(alan.graphGroup)); // // JBPNote -
702       // originally we
703       // were going to
704       // store
705       // graphGroup in
706       // the Jalview
707       // specific
708       // bits.
709       if (alan.getThreshold()!=null && alan.getThreshold().displayed)
710       {
711         an.addProperty(newProperty(THRESHOLD, "float", ""+alan.getThreshold().value));
712         if (alan.getThreshold().label!=null)
713           an.addProperty(newProperty(THRESHOLD+"Name", "string", ""+alan.getThreshold().label));
714       }
715       ((DataSet) sref.getV_parent()).addDataSetAnnotations(an);
716       bindjvvobj(alan, an);
717     }
718     else
719     {
720       // update reference sequence Annotation
721       if (an.getModifiable() == null) // TODO: USE VAMSAS LIBRARY OBJECT LOCK
722                                       // METHODS)
723       {
724         // verify existing alignment sequence annotation is up to date
725         System.out.println("update dataset sequence annotation.");
726       }
727       else
728       {
729         // verify existing alignment sequence annotation is up to date
730         System.out
731                 .println("make new alignment dataset sequence annotation if modification has happened.");
732       }
733     }
734
735   }
736
737   private int[] getGapMap(HashMap AlSeqMaps, AlignmentAnnotation alan)
738   {
739     int[] gapMap;
740     if (AlSeqMaps.containsKey(alan.sequenceRef))
741     {
742       gapMap = (int[]) AlSeqMaps.get(alan.sequenceRef);
743     }
744     else
745     {
746       gapMap = new int[alan.sequenceRef.getLength()];
747       // map from alignment position to sequence position.
748       int[] sgapMap = alan.sequenceRef.gapMap();
749       for (int a = 0; a < sgapMap.length; a++)
750       {
751         gapMap[sgapMap[a]] = a;
752       }
753     }
754     return gapMap;
755   }
756
757   private void saveAlignmentSequenceAnnotation(HashMap AlSeqMaps,
758           AlignmentSequence alsref, AlignmentAnnotation alan)
759   {
760     // {
761     // uk.ac.vamsas.
762     // objects.core.AlignmentSequence alsref = (uk.ac.vamsas.
763     // objects.core.AlignmentSequence) sref;
764     uk.ac.vamsas.objects.core.AlignmentSequenceAnnotation an = (uk.ac.vamsas.objects.core.AlignmentSequenceAnnotation) getjv2vObj(alan);
765     int[] gapMap = getGapMap(AlSeqMaps, alan);
766     if (an == null)
767     {
768       an = new uk.ac.vamsas.objects.core.AlignmentSequenceAnnotation();
769       initRangeAnnotationType(an, alan, gapMap);
770       /**
771        * I mean here that we don't actually have a semantic 'type' for the
772        * annotation (this might be - score, intrinsic property, measurement,
773        * something extracted from another program, etc)
774        */
775       an.setType(JALVIEW_ANNOTATION_ROW); // TODO: better fix
776                                                           // this rough guess ;)
777       alsref.addAlignmentSequenceAnnotation(an);
778       bindjvvobj(alan, an);
779       // These properties are directly supported by the
780       // AlignmentSequenceAnnotation type.
781       setAnnotationType(an, alan);
782       an.setProvenance(dummyProvenance()); // get provenance as user
783       // created, or jnet, or
784       // something else.
785     }
786     else
787     {
788       // update reference sequence Annotation
789       if (an.getModifiable() == null) // TODO: USE VAMSAS LIBRARY OBJECT LOCK
790                                       // METHODS)
791       {
792         // verify existing alignment sequence annotation is up to date
793         System.out.println("update alignment sequence annotation.");
794       }
795       else
796       {
797         // verify existing alignment sequence annotation is up to date
798         System.out
799                 .println("make new alignment sequence annotation if modification has happened.");
800       }
801     }
802   }
803
804   /**
805    * set vamsas annotation object type from jalview annotation
806    * @param an
807    * @param alan
808    */
809   private void setAnnotationType(RangeAnnotation an, AlignmentAnnotation alan)
810   {
811     if (an instanceof AlignmentSequenceAnnotation)
812     {
813       if (alan.graph != AlignmentAnnotation.NO_GRAPH)
814       {
815         ((AlignmentSequenceAnnotation)an).setGraph(true);
816       } else
817       {
818       ((AlignmentSequenceAnnotation)an).setGraph(false);
819       }
820     }
821     if (an instanceof uk.ac.vamsas.objects.core.AlignmentAnnotation)
822     {
823       if (alan.graph != AlignmentAnnotation.NO_GRAPH)
824       {
825         ((uk.ac.vamsas.objects.core.AlignmentAnnotation)an).setGraph(true);
826       } else
827       {
828       ((uk.ac.vamsas.objects.core.AlignmentAnnotation)an).setGraph(false);
829       }
830     }
831     switch (alan.graph)
832     {
833       case AlignmentAnnotation.BAR_GRAPH:
834         an.addProperty(newProperty(DISCRETE_ANNOTATION, "boolean","true"));
835         break;
836       case AlignmentAnnotation.LINE_GRAPH:
837         an.addProperty(newProperty(CONTINUOUS_ANNOTATION, "boolean","true"));
838         break;
839         default:
840           // don't add any kind of discrete or continous property info.
841     }
842   }
843
844   private Property newProperty(String name, String type, String content)
845   {
846     Property vProperty = new Property();
847     vProperty.setName(name);
848     if (type != null)
849     {
850       vProperty.setType(type);
851     }
852     else
853     {
854       vProperty.setType("String");
855     }
856     vProperty.setContent(content);
857     return vProperty;
858   }
859
860   /**
861    * correctly create a RangeAnnotation from a jalview sequence feature
862    * 
863    * @param dsa
864    *          (typically DataSetAnnotations or AlignmentSequenceAnnotation)
865    * @param feature
866    *          (the feature to be mapped from)
867    * @return
868    */
869   private RangeAnnotation getDSAnnotationFromJalview(RangeAnnotation dsa,
870           SequenceFeature feature)
871   {
872     dsa.setType(feature.getType());
873     Seg vSeg = new Seg();
874     vSeg.setStart(feature.getBegin());
875     vSeg.setEnd(feature.getEnd());
876     vSeg.setInclusive(true);
877     dsa.addSeg(vSeg);
878     dsa.setDescription(feature.getDescription());
879     dsa.setStatus(feature.getStatus());
880     if (feature.links != null && feature.links.size() > 0)
881     {
882       for (int i = 0, iSize = feature.links.size(); i < iSize; i++)
883       {
884         String link = (String) feature.links.elementAt(i);
885         int sep = link.indexOf('|');
886         if (sep > -1)
887         {
888           Link vLink = new Link();
889           if (sep > 0)
890           {
891             vLink.setContent(link.substring(0, sep - 1));
892           }
893           else
894           {
895             vLink.setContent("");
896           }
897           vLink.setHref(link.substring(sep + 1)); // TODO: validate href.
898           dsa.addLink(vLink);
899         }
900       }
901     }
902     dsa.setGroup(feature.getFeatureGroup());
903     return dsa;
904   }
905
906   /**
907    * get start<end range of segment, adjusting for inclusivity flag and
908    * polarity.
909    * 
910    * @param visSeg
911    * @param ensureDirection
912    *          when true - always ensure start is less than end.
913    * @return int[] { start, end, direction} where direction==1 for range running
914    *         from end to start.
915    */
916   private int[] getSegRange(Seg visSeg, boolean ensureDirection)
917   {
918     boolean incl = visSeg.getInclusive();
919     // adjust for inclusive flag.
920     int pol = (visSeg.getStart() <= visSeg.getEnd()) ? 1 : -1; // polarity of
921     // region.
922     int start = visSeg.getStart() + (incl ? 0 : pol);
923     int end = visSeg.getEnd() + (incl ? 0 : -pol);
924     if (ensureDirection && pol == -1)
925     {
926       // jalview doesn't deal with inverted ranges, yet.
927       int t = end;
928       end = start;
929       start = t;
930     }
931     return new int[]
932     { start, end, pol < 0 ? 1 : 0 };
933   }
934
935   /**
936    * 
937    * @param annotation
938    * @return true if annotation is not to be stored in document
939    */
940   private boolean isJalviewOnly(AlignmentAnnotation annotation)
941   {
942     return annotation.label.equals("Quality")
943             || annotation.label.equals("Conservation")
944             || annotation.label.equals("Consensus");
945   }
946
947   /**
948    * This will return the first AlignFrame viewing AlignViewport av. It will
949    * break if there are more than one AlignFrames viewing a particular av. This
950    * also shouldn't be in the io package.
951    * 
952    * @param av
953    * @return alignFrame for av
954    */
955   public AlignFrame getAlignFrameFor(AlignViewport av)
956   {
957     if (Desktop.desktop != null)
958     {
959       javax.swing.JInternalFrame[] frames = Desktop.instance.getAllFrames();
960
961       for (int t = 0; t < frames.length; t++)
962       {
963         if (frames[t] instanceof AlignFrame)
964         {
965           if (((AlignFrame) frames[t]).getViewport() == av)
966           {
967             return (AlignFrame) frames[t];
968           }
969         }
970       }
971     }
972     return null;
973   }
974
975   public void updateToJalview()
976   {
977     VAMSAS _roots[] = cdoc.getVamsasRoots();
978
979     for (int _root = 0; _root < _roots.length; _root++)
980     {
981       VAMSAS root = _roots[_root];
982       boolean newds = false;
983       for (int _ds = 0, _nds = root.getDataSetCount(); _ds < _nds; _ds++)
984       {
985         // ///////////////////////////////////
986         // ///LOAD DATASET
987         DataSet dataset = root.getDataSet(_ds);
988         int i, iSize = dataset.getSequenceCount();
989         Vector dsseqs;
990         jalview.datamodel.Alignment jdataset = (jalview.datamodel.Alignment) getvObj2jv(dataset);
991         int jremain = 0;
992         if (jdataset == null)
993         {
994           Cache.log.debug("Initialising new jalview dataset fields");
995           newds = true;
996           dsseqs = new Vector();
997         }
998         else
999         {
1000           Cache.log.debug("Update jalview dataset from vamsas.");
1001           jremain = jdataset.getHeight();
1002           dsseqs = jdataset.getSequences();
1003         }
1004
1005         // TODO: test sequence merging - we preserve existing non vamsas
1006         // sequences but add in any new vamsas ones, and don't yet update any
1007         // sequence attributes
1008         for (i = 0; i < iSize; i++)
1009         {
1010           Sequence vdseq = dataset.getSequence(i);
1011           jalview.datamodel.SequenceI dsseq = (SequenceI) getvObj2jv(vdseq);
1012           if (dsseq != null)
1013           {
1014             if (!dsseq.getSequenceAsString().equals(vdseq.getSequence()))
1015             {
1016               throw new Error(
1017                       "Broken! - mismatch of dataset sequence: and jalview internal dataset sequence.");
1018             }
1019             jremain--;
1020           }
1021           else
1022           {
1023             dsseq = new jalview.datamodel.Sequence(dataset.getSequence(i)
1024                     .getName(), dataset.getSequence(i).getSequence(),
1025                     (int) dataset.getSequence(i).getStart(), (int) dataset
1026                             .getSequence(i).getEnd());
1027             dsseq.setDescription(dataset.getSequence(i).getDescription());
1028             bindjvvobj(dsseq, dataset.getSequence(i));
1029             dsseq.setVamsasId(dataset.getSequence(i).getVorbaId().getId());
1030             dsseqs.add(dsseq);
1031           }
1032           if (vdseq.getDbRefCount() > 0)
1033           {
1034             DbRef[] dbref = vdseq.getDbRef();
1035             for (int db = 0; db < dbref.length; db++)
1036             {
1037               new jalview.io.vamsas.Dbref(this, dbref[db], vdseq, dsseq);
1038
1039             }
1040           }
1041         }
1042
1043         if (newds)
1044         {
1045           SequenceI[] seqs = new SequenceI[dsseqs.size()];
1046           for (i = 0, iSize = dsseqs.size(); i < iSize; i++)
1047           {
1048             seqs[i] = (SequenceI) dsseqs.elementAt(i);
1049             dsseqs.setElementAt(null, i);
1050           }
1051           jdataset = new jalview.datamodel.Alignment(seqs);
1052           Cache.log.debug("New vamsas dataset imported into jalview.");
1053           bindjvvobj(jdataset, dataset);
1054         }
1055         // ////////
1056         // add any new dataset sequence feature annotations
1057         if (dataset.getDataSetAnnotations() != null)
1058         {
1059           for (int dsa = 0; dsa < dataset.getDataSetAnnotationsCount(); dsa++)
1060           {
1061             DataSetAnnotations dseta = dataset.getDataSetAnnotations(dsa);
1062             // TODO: deal with group annotation on datset sequences.
1063             if (dseta.getSeqRefCount() == 1)
1064             {
1065               SequenceI dsSeq = (SequenceI) getvObj2jv((Vobject) dseta
1066                       .getSeqRef(0)); // TODO: deal with group dataset
1067                                       // annotations
1068               if (dsSeq == null)
1069               {
1070                 jalview.bin.Cache.log
1071                         .warn("Couldn't resolve jalview sequenceI for dataset object reference "
1072                                 + ((Vobject) dataset.getDataSetAnnotations(
1073                                         dsa).getSeqRef(0)).getVorbaId()
1074                                         .getId());
1075               }
1076               else
1077               {
1078                 if (dseta.getAnnotationElementCount() == 0)
1079                 {
1080                   jalview.datamodel.SequenceFeature sf = (jalview.datamodel.SequenceFeature) getvObj2jv(dseta);
1081                   if (sf == null)
1082                   {
1083                     dsSeq
1084                             .addSequenceFeature(sf = getJalviewSeqFeature(dseta));
1085                     bindjvvobj(sf, dseta);
1086                   }
1087                 }
1088                 else
1089                 {
1090                   // TODO: deal with alignmentAnnotation style annotation
1091                   // appearing on dataset sequences.
1092                   // JBPNote: we could just add them to all alignments but
1093                   // that may complicate cross references in the jalview
1094                   // datamodel
1095                   Cache.log
1096                           .warn("Ignoring dataset annotation with annotationElements. Not yet supported in jalview.");
1097                 }
1098               }
1099             }
1100           }
1101         }
1102         if (dataset.getAlignmentCount() > 0)
1103         {
1104           // LOAD ALIGNMENTS from DATASET
1105
1106           for (int al = 0, nal = dataset.getAlignmentCount(); al < nal; al++)
1107           {
1108             uk.ac.vamsas.objects.core.Alignment alignment = dataset
1109                     .getAlignment(al);
1110             AlignViewport av = (AlignViewport) getvObj2jv(alignment);
1111             jalview.datamodel.AlignmentI jal = null;
1112             if (av != null)
1113             {
1114               jal = av.getAlignment();
1115             }
1116             iSize = alignment.getAlignmentSequenceCount();
1117             boolean newal = (jal == null) ? true : false;
1118             Vector newasAnnots = new Vector();
1119             char gapChar = ' '; // default for new alignments read in from the
1120                                 // document
1121             if (jal != null)
1122             {
1123               dsseqs = jal.getSequences(); // for merge/update
1124               gapChar = jal.getGapCharacter();
1125             }
1126             else
1127             {
1128               dsseqs = new Vector();
1129             }
1130             char valGapchar = alignment.getGapChar().charAt(0);
1131             for (i = 0; i < iSize; i++)
1132             {
1133               AlignmentSequence valseq = alignment.getAlignmentSequence(i);
1134               jalview.datamodel.SequenceI alseq = (SequenceI) getvObj2jv(valseq);
1135               if (alseq != null)
1136               {
1137                 // TODO: upperCase/LowerCase situation here ? do we allow it ?
1138                 // if (!alseq.getSequence().equals(valseq.getSequence())) {
1139                 // throw new Error("Broken! - mismatch of dataset sequence and
1140                 // jalview internal dataset sequence.");
1141                 if (Cache.log.isDebugEnabled())
1142                 {
1143                   Cache.log.debug("Updating apparently edited sequence "
1144                           + alseq.getName());
1145                 }
1146                 // this might go *horribly* wrong
1147                 alseq.setSequence(new String(valseq.getSequence()).replace(
1148                         valGapchar, gapChar));
1149                 jremain--;
1150               }
1151               else
1152               {
1153                 alseq = new jalview.datamodel.Sequence(valseq.getName(),
1154                         valseq.getSequence().replace(valGapchar, gapChar),
1155                         (int) valseq.getStart(), (int) valseq.getEnd());
1156
1157                 Vobject datsetseq = (Vobject) valseq.getRefid();
1158                 if (datsetseq != null)
1159                 {
1160                   alseq
1161                           .setDatasetSequence((SequenceI) getvObj2jv(datsetseq)); // exceptions
1162                                                                                   // if
1163                                                                                   // AlignemntSequence
1164                                                                                   // reference
1165                                                                                   // isn't
1166                                                                                   // a
1167                                                                                   // simple
1168                                                                                   // SequenceI
1169                 }
1170                 else
1171                 {
1172                   Cache.log
1173                           .error("Invalid dataset sequence id (null) for alignment sequence "
1174                                   + valseq.getVorbaId());
1175                 }
1176                 bindjvvobj(alseq, valseq);
1177                 alseq.setVamsasId(valseq.getVorbaId().getId());
1178                 dsseqs.add(alseq);
1179               }
1180               if (valseq.getAlignmentSequenceAnnotationCount() > 0)
1181               {
1182                 AlignmentSequenceAnnotation[] vasannot = valseq
1183                         .getAlignmentSequenceAnnotation();
1184                 for (int a = 0; a < vasannot.length; a++)
1185                 {
1186                   jalview.datamodel.AlignmentAnnotation asa = (jalview.datamodel.AlignmentAnnotation) getvObj2jv(vasannot[a]); // TODO:
1187                                                                                                                                 // 1:many
1188                                                                                                                                 // jalview
1189                                                                                                                                 // alignment
1190                                                                                                                                 // sequence
1191                                                                                                                                 // annotations
1192                   if (asa == null)
1193                   {
1194                     int se[] = getBounds(vasannot[a]);
1195                     asa = getjAlignmentAnnotation(jal, vasannot[a]);
1196                     asa.setSequenceRef(alseq);
1197                     asa.createSequenceMapping(alseq, se[0], false); // TODO:
1198                                                                     // verify
1199                                                                     // that
1200                                                                     // positions
1201                                                                     // in
1202                                                                     // alseqAnnotation
1203                                                                     // correspond
1204                                                                     // to
1205                                                                     // ungapped
1206                                                                     // residue
1207                                                                     // positions.
1208                     alseq.addAlignmentAnnotation(asa);
1209                     bindjvvobj(asa, vasannot[a]);
1210                     newasAnnots.add(asa);
1211                   }
1212                   else
1213                   {
1214                     // update existing annotation - can do this in place
1215                     if (vasannot[a].getModifiable() == null) // TODO: USE
1216                                                               // VAMSAS LIBRARY
1217                                                               // OBJECT LOCK
1218                                                               // METHODS)
1219                     {
1220                       Cache.log
1221                               .info("UNIMPLEMENTED: not recovering user modifiable sequence alignment annotation");
1222                       // TODO: should at least replace with new one - otherwise
1223                       // things will break
1224                       // basically do this:
1225                       // int se[] = getBounds(vasannot[a]);
1226                       // asa.update(getjAlignmentAnnotation(jal, vasannot[a]));
1227                       // // update from another annotation object in place.
1228                       // asa.createSequenceMapping(alseq, se[0], false);
1229
1230                     }
1231                   }
1232                 }
1233               }
1234             }
1235             if (jal == null)
1236             {
1237               SequenceI[] seqs = new SequenceI[dsseqs.size()];
1238               for (i = 0, iSize = dsseqs.size(); i < iSize; i++)
1239               {
1240                 seqs[i] = (SequenceI) dsseqs.elementAt(i);
1241                 dsseqs.setElementAt(null, i);
1242               }
1243               jal = new jalview.datamodel.Alignment(seqs);
1244               Cache.log.debug("New vamsas alignment imported into jalview "
1245                       + alignment.getVorbaId().getId());
1246               jal.setDataset(jdataset);
1247             }
1248             if (newasAnnots != null && newasAnnots.size() > 0)
1249             {
1250               // Add the new sequence annotations in to the alignment.
1251               for (int an = 0, anSize = newasAnnots.size(); an < anSize; an++)
1252               {
1253                 jal.addAnnotation((AlignmentAnnotation) newasAnnots
1254                         .elementAt(an));
1255                 // TODO: check if anything has to be done - like calling
1256                 // adjustForAlignment or something.
1257                 newasAnnots.setElementAt(null, an);
1258               }
1259               newasAnnots = null;
1260             }
1261             // //////////////////////////////////////////
1262             // //LOAD ANNOTATIONS FOR THE ALIGNMENT
1263             // ////////////////////////////////////
1264             if (alignment.getAlignmentAnnotationCount() > 0)
1265             {
1266               uk.ac.vamsas.objects.core.AlignmentAnnotation[] an = alignment
1267                       .getAlignmentAnnotation();
1268
1269               for (int j = 0; j < an.length; j++)
1270               {
1271                 jalview.datamodel.AlignmentAnnotation jan = (jalview.datamodel.AlignmentAnnotation) getvObj2jv(an[j]);
1272                 if (jan != null)
1273                 {
1274                   // update or stay the same.
1275                   // TODO: should at least replace with a new one - otherwise
1276                   // things will break
1277                   // basically do this:
1278                   // jan.update(getjAlignmentAnnotation(jal, an[a])); // update
1279                   // from another annotation object in place.
1280
1281                   Cache.log
1282                           .debug("update from vamsas alignment annotation to existing jalview alignment annotation.");
1283                   if (an[j].getModifiable() == null) // TODO: USE VAMSAS
1284                                                       // LIBRARY OBJECT LOCK
1285                                                       // METHODS)
1286                   {
1287                     // TODO: user defined annotation is totally mutable... - so
1288                     // load it up or throw away if locally edited.
1289                     Cache.log
1290                             .info("NOT IMPLEMENTED - Recovering user-modifiable annotation - yet...");
1291                   }
1292                   // TODO: compare annotation element rows
1293                   // TODO: compare props.
1294                 }
1295                 else
1296                 {
1297                   jan = getjAlignmentAnnotation(jal, an[j]);
1298                   jal.addAnnotation(jan);
1299                   bindjvvobj(jan, an[j]);
1300                 }
1301               }
1302             }
1303             AlignFrame alignFrame;
1304             if (av == null)
1305             {
1306               Cache.log.debug("New alignframe for alignment "
1307                       + alignment.getVorbaId());
1308               // ///////////////////////////////
1309               // construct alignment view
1310               alignFrame = new AlignFrame(jal, AlignFrame.DEFAULT_WIDTH,
1311                       AlignFrame.DEFAULT_HEIGHT);
1312               av = alignFrame.getViewport();
1313               String title = alignment.getProvenance().getEntry(
1314                       alignment.getProvenance().getEntryCount() - 1)
1315                       .getAction();
1316               if (alignment.getPropertyCount() > 0)
1317               {
1318                 for (int p = 0, pe = alignment.getPropertyCount(); p < pe; p++)
1319                 {
1320                   if (alignment.getProperty(p).getName().equals(
1321                           "title"))
1322                   {
1323                     title = alignment.getProperty(p).getContent();
1324                   }
1325                 }
1326               }
1327               // TODO: automatically create meaningful title for a vamsas
1328               // alignment using its provenance.
1329               if (Cache.log.isDebugEnabled())
1330               {
1331                 title = title + "("
1332                  + alignment.getVorbaId() + ")";
1333                 
1334               }
1335               jalview.gui.Desktop.addInternalFrame(alignFrame, title 
1336                       ,
1337                       AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
1338               bindjvvobj(av, alignment);
1339             }
1340             else
1341             {
1342               // find the alignFrame for jal.
1343               // TODO: fix this so we retrieve the alignFrame handing av
1344               // *directly*
1345               alignFrame = getAlignFrameFor(av);
1346             }
1347             // LOAD TREES
1348             // /////////////////////////////////////
1349             if (alignment.getTreeCount() > 0)
1350             {
1351
1352               for (int t = 0; t < alignment.getTreeCount(); t++)
1353               {
1354                 jalview.io.vamsas.Tree vstree = new jalview.io.vamsas.Tree(
1355                         this, alignFrame, alignment.getTree(t));
1356                 TreePanel tp = null;
1357                 if (vstree.isValidTree())
1358                 { 
1359                   tp = alignFrame
1360                         .ShowNewickTree(vstree.getNewickTree(), vstree
1361                                 .getTitle(), vstree.getInputData(), 600,
1362                                 500, t * 20 + 50, t * 20 + 50);
1363                 }
1364                 if (tp!=null)
1365                   bindjvvobj(tp, alignment.getTree(t));
1366                 else
1367                 {
1368                   Cache.log.warn("Cannot create tree for tree "+t+" in document ("+alignment.getTree(t).getVorbaId());
1369                 }
1370
1371               }
1372             }
1373           }
1374         }
1375       }
1376       // we do sequenceMappings last because they span all datasets in a vamsas
1377       // root
1378       for (int _ds = 0, _nds = root.getDataSetCount(); _ds < _nds; _ds++)
1379       {
1380         DataSet dataset = root.getDataSet(_ds);
1381         if (dataset.getSequenceMappingCount() > 0)
1382         {
1383           for (int sm = 0, smCount = dataset.getSequenceMappingCount(); sm < smCount; sm++)
1384           {
1385             Rangetype seqmap = new jalview.io.vamsas.Sequencemapping(this,
1386                     dataset.getSequenceMapping(sm));
1387           }
1388         }
1389       }
1390     }
1391   }
1392
1393   // bitfields - should be a template in j1.5
1394   private static int HASSECSTR = 0;
1395
1396   private static int HASVALS = 1;
1397
1398   private static int HASHPHOB = 2;
1399
1400   private static int HASDC = 3;
1401
1402   private static int HASDESCSTR = 4;
1403
1404   private static int HASTWOSTATE = 5; // not used yet.
1405
1406   /**
1407    * parses the AnnotationElements - if they exist - into
1408    * jalview.datamodel.Annotation[] rows Two annotation rows are made if there
1409    * are distinct annotation for both at 'pos' and 'after pos' at any particular
1410    * site.
1411    * 
1412    * @param annotation
1413    * @return { boolean[static int constants ], int[ae.length] - map to annotated
1414    *         object frame, jalview.datamodel.Annotation[],
1415    *         jalview.datamodel.Annotation[] (after)}
1416    */
1417   private Object[] parseRangeAnnotation(
1418           uk.ac.vamsas.objects.core.RangeAnnotation annotation)
1419   {
1420     // set these attributes by looking in the annotation to decide what kind of
1421     // alignment annotation rows will be made
1422     // TODO: potentially we might make several annotation rows from one vamsas
1423     // alignment annotation. the jv2Vobj binding mechanism
1424     // may not quite cope with this (without binding an array of annotations to
1425     // a vamsas alignment annotation)
1426     // summary flags saying what we found over the set of annotation rows.
1427     boolean[] AeContent = new boolean[]
1428     { false, false, false, false, false };
1429     int[] rangeMap = getMapping(annotation);
1430     jalview.datamodel.Annotation[][] anot = new jalview.datamodel.Annotation[][]
1431     { new jalview.datamodel.Annotation[rangeMap.length],
1432         new jalview.datamodel.Annotation[rangeMap.length] };
1433     boolean mergeable = true; // false if 'after positions cant be placed on
1434                               // same annotation row as positions.
1435
1436     if (annotation.getAnnotationElementCount() > 0)
1437     {
1438       AnnotationElement ae[] = annotation.getAnnotationElement();
1439       for (int aa = 0; aa < ae.length; aa++)
1440       {
1441         int pos = (int) ae[aa].getPosition() - 1; // pos counts from 1 to
1442                                                   // (|seg.start-seg.end|+1)
1443         if (pos >= 0 && pos < rangeMap.length)
1444         {
1445           int row = ae[aa].getAfter() ? 1 : 0;
1446           if (anot[row][pos] != null)
1447           {
1448             // only time this should happen is if the After flag is set.
1449             Cache.log.debug("Ignoring duplicate annotation site at " + pos);
1450             continue;
1451           }
1452           if (anot[1 - row][pos] != null)
1453           {
1454             mergeable = false;
1455           }
1456           String desc = "";
1457           if (ae[aa].getDescription() != null)
1458           {
1459             desc = ae[aa].getDescription();
1460             if (desc.length() > 0)
1461             {
1462               // have imported valid description string
1463               AeContent[HASDESCSTR] = true;
1464             }
1465           }
1466           String dc = null; // ae[aa].getDisplayCharacter()==null ? "dc" :
1467                             // ae[aa].getDisplayCharacter();
1468           String ss = null; // ae[aa].getSecondaryStructure()==null ? "ss" :
1469                             // ae[aa].getSecondaryStructure();
1470           java.awt.Color colour = null;
1471           if (ae[aa].getGlyphCount() > 0)
1472           {
1473             Glyph[] glyphs = ae[aa].getGlyph();
1474             for (int g = 0; g < glyphs.length; g++)
1475             {
1476               if (glyphs[g]
1477                       .getDict()
1478                       .equals(
1479                               uk.ac.vamsas.objects.utils.GlyphDictionary.PROTEIN_SS_3STATE))
1480               {
1481                 ss = glyphs[g].getContent();
1482                 AeContent[HASSECSTR] = true;
1483               }
1484               else if (glyphs[g]
1485                       .getDict()
1486                       .equals(
1487                               uk.ac.vamsas.objects.utils.GlyphDictionary.PROTEIN_HD_HYDRO))
1488               {
1489                 Cache.log.debug("ignoring hydrophobicity glyph marker.");
1490                 AeContent[HASHPHOB] = true;
1491                 char c = (dc = glyphs[g].getContent()).charAt(0);
1492                 // dc may get overwritten - but we still set the colour.
1493                 colour = new java.awt.Color(c == '+' ? 255 : 0,
1494                         c == '.' ? 255 : 0, c == '-' ? 255 : 0);
1495
1496               }
1497               else if (glyphs[g].getDict().equals(
1498                       uk.ac.vamsas.objects.utils.GlyphDictionary.DEFAULT))
1499               {
1500                 dc = glyphs[g].getContent();
1501                 AeContent[HASDC] = true;
1502               }
1503               else
1504               {
1505                 Cache.log.debug("IMPLEMENTATION TODO: Ignoring unknown glyph type "
1506                         + glyphs[g].getDict());
1507               }
1508             }
1509           }
1510           float val = 0;
1511           if (ae[aa].getValueCount() > 0)
1512           {
1513             AeContent[HASVALS] = true;
1514             if (ae[aa].getValueCount() > 1)
1515             {
1516               Cache.log.warn("ignoring additional "
1517                       + (ae[aa].getValueCount() - 1)
1518                       + "values in annotation element.");
1519             }
1520             val = ae[aa].getValue(0);
1521           }
1522           if (colour == null)
1523           {
1524             anot[row][pos] = new jalview.datamodel.Annotation(
1525                     (dc != null) ? dc : "", desc, (ss != null) ? ss
1526                             .charAt(0) : ' ', val);
1527           }
1528           else
1529           {
1530             anot[row][pos] = new jalview.datamodel.Annotation(
1531                     (dc != null) ? dc : "", desc, (ss != null) ? ss
1532                             .charAt(0) : ' ', val, colour);
1533           }
1534         }
1535         else
1536         {
1537           Cache.log.warn("Ignoring out of bound annotation element " + aa
1538                   + " in " + annotation.getVorbaId().getId());
1539         }
1540       }
1541       // decide on how many annotation rows are needed.
1542       if (mergeable)
1543       {
1544         for (int i = 0; i < anot[0].length; i++)
1545         {
1546           if (anot[1][i] != null)
1547           {
1548             anot[0][i] = anot[1][i];
1549             anot[0][i].description = anot[0][i].description + " (after)";
1550             AeContent[HASDESCSTR] = true; // we have valid description string
1551                                           // data
1552             anot[1][i] = null;
1553           }
1554         }
1555         anot[1] = null;
1556       }
1557       else
1558       {
1559         for (int i = 0; i < anot[0].length; i++)
1560         {
1561           anot[1][i].description = anot[1][i].description + " (after)";
1562         }
1563       }
1564       return new Object[]
1565       { AeContent, rangeMap, anot[0], anot[1] };
1566     }
1567     else
1568     {
1569       // no annotations to parse. Just return an empty annotationElement[]
1570       // array.
1571       return new Object[]
1572       { AeContent, rangeMap, anot[0], anot[1] };
1573     }
1574     // return null;
1575   }
1576
1577   /**
1578    * @param jal
1579    *          the jalview alignment to which the annotation will be attached
1580    *          (ideally - freshly updated from corresponding vamsas alignment)
1581    * @param annotation
1582    * @return unbound jalview alignment annotation object.
1583    */
1584   private jalview.datamodel.AlignmentAnnotation getjAlignmentAnnotation(
1585           jalview.datamodel.AlignmentI jal,
1586           uk.ac.vamsas.objects.core.RangeAnnotation annotation)
1587   {
1588     if (annotation == null)
1589     {
1590       return null;
1591     }
1592     // boolean
1593     // hasSequenceRef=annotation.getClass().equals(uk.ac.vamsas.objects.core.AlignmentSequenceAnnotation.class);
1594     // boolean hasProvenance=hasSequenceRef ||
1595     // (annotation.getClass().equals(uk.ac.vamsas.objects.core.AlignmentAnnotation.class));
1596     /*
1597      * int se[] = getBounds(annotation); if (se==null) se=new int[]
1598      * {0,jal.getWidth()-1};
1599      */
1600     Object[] parsedRangeAnnotation = parseRangeAnnotation(annotation);
1601     String a_label = annotation.getLabel();
1602     String a_descr = annotation.getDescription();
1603     GraphLine gl=null;
1604     int type=0;
1605     boolean interp=true; // cleared if annotation is DISCRETE
1606     // set type and other attributes from properties
1607     if (annotation.getPropertyCount() > 0)
1608     {
1609       // look for special jalview properties
1610       uk.ac.vamsas.objects.core.Property[] props = annotation
1611               .getProperty();
1612       for (int p = 0; p < props.length; p++)
1613       {
1614         if (props[p].getName().equalsIgnoreCase(DISCRETE_ANNOTATION))
1615         {
1616           type = AlignmentAnnotation.BAR_GRAPH;
1617           interp=false;
1618         } else if
1619          (props[p].getName().equalsIgnoreCase(CONTINUOUS_ANNOTATION)) {
1620           type = AlignmentAnnotation.LINE_GRAPH;
1621         } else if
1622         (props[p].getName().equalsIgnoreCase(THRESHOLD))
1623         {
1624           Float val=null;
1625           try {
1626             val = new Float(props[p].getContent());
1627           }catch (Exception e)
1628           {
1629             Cache.log.warn("Failed to parse threshold property");
1630           }
1631           if (val!=null)
1632           if (gl==null)
1633           {
1634             gl = new GraphLine(val.floatValue(), "", java.awt.Color.black);
1635           } else
1636           {
1637             gl.value = val.floatValue();
1638           }
1639         }
1640         else if (props[p].getName().equalsIgnoreCase(THRESHOLD+"Name"))
1641         {
1642           if (gl==null)
1643             gl = new GraphLine(0, "", java.awt.Color.black);
1644           gl.label = props[p].getContent();
1645         }
1646       }
1647     }
1648     jalview.datamodel.AlignmentAnnotation jan = null;
1649     if (a_label == null || a_label.length() == 0)
1650     {
1651       a_label = annotation.getType();
1652       if (a_label.length() == 0)
1653       {
1654         a_label = "Unamed annotation";
1655       }
1656     }
1657     if (a_descr == null || a_descr.length() == 0)
1658     {
1659       a_descr = "Annotation of type '" + annotation.getType() + "'";
1660     }
1661     if (parsedRangeAnnotation == null)
1662     {
1663       Cache.log
1664               .debug("Inserting empty annotation row elements for a whole-alignment annotation.");
1665     }
1666     else
1667     {
1668       if (parsedRangeAnnotation[3] != null)
1669       {
1670         Cache.log.warn("Ignoring 'After' annotation row in "
1671                 + annotation.getVorbaId());
1672       }
1673       jalview.datamodel.Annotation[] arow = (jalview.datamodel.Annotation[]) parsedRangeAnnotation[2];
1674       boolean[] has = (boolean[]) parsedRangeAnnotation[0];
1675       // VAMSAS: getGraph is only on derived annotation for alignments - in this
1676       // way its 'odd' - there is already an existing TODO about removing this
1677       // flag as being redundant
1678       /*
1679        * if
1680        * ((annotation.getClass().equals(uk.ac.vamsas.objects.core.AlignmentAnnotation.class) &&
1681        * ((uk.ac.vamsas.objects.core.AlignmentAnnotation)annotation).getGraph()) ||
1682        * (hasSequenceRef=true &&
1683        * ((uk.ac.vamsas.objects.core.AlignmentSequenceAnnotation)annotation).getGraph())) {
1684        */
1685       if (has[HASVALS])
1686       {
1687         if (type==0)
1688         {
1689           type = jalview.datamodel.AlignmentAnnotation.BAR_GRAPH; // default type of value annotation
1690           if (has[HASHPHOB])
1691           {
1692             // no hints - so we ensure HPHOB display is like this.
1693             type = jalview.datamodel.AlignmentAnnotation.BAR_GRAPH;
1694           }
1695         }
1696         // make bounds and automatic description strings for jalview user's
1697         // benefit (these shouldn't be written back to vamsas document)
1698         boolean first = true;
1699         float min = 0, max = 1;
1700         int lastval = 0;
1701         for (int i = 0; i < arow.length; i++)
1702         {
1703           if (arow[i] != null)
1704           {
1705             if (i - lastval > 1 && interp)
1706             {
1707               // do some interpolation *between* points
1708               if (arow[lastval] != null)
1709               {
1710                 float interval = arow[i].value - arow[lastval].value;
1711                 interval /= i - lastval;
1712                 float base = arow[lastval].value;
1713                 for (int ip = lastval + 1, np = 0; ip < i; np++, ip++)
1714                 {
1715                   arow[ip] = new jalview.datamodel.Annotation("", "", ' ',
1716                           interval * np + base);
1717                   // NB - Interpolated points don't get a tooltip and
1718                   // description.
1719                 }
1720               }
1721             }
1722             lastval = i;
1723             // check range - shouldn't we have a min and max property in the
1724             // annotation object ?
1725             if (first)
1726             {
1727               min = max = arow[i].value;
1728               first = false;
1729             }
1730             else
1731             {
1732               if (arow[i].value < min)
1733               {
1734                 min = arow[i].value;
1735               }
1736               else if (arow[i].value > max)
1737               {
1738                 max = arow[i].value;
1739               }
1740             }
1741             // make tooltip and display char value
1742             if (!has[HASDESCSTR])
1743             {
1744               arow[i].description = arow[i].value + "";
1745             }
1746             if (!has[HASDC])
1747             {
1748               if (!interp)
1749                 {
1750                 if (arow[i].description!=null && arow[i].description.length()<3)
1751                 {
1752                   // copy over the description as the display char.
1753                   arow[i].displayCharacter = new String(arow[i].description);
1754                 }
1755                 } else
1756                 {
1757                   // mark the position as a point used for the interpolation.
1758                 arow[i].displayCharacter = arow[i].value + "";
1759                 }
1760             }
1761           }
1762         }
1763         jan = new jalview.datamodel.AlignmentAnnotation(a_label, a_descr,
1764                 arow, min, max, type);
1765       }
1766       else
1767       {
1768         if (annotation.getAnnotationElementCount()==0)
1769         {
1770           // empty annotation array
1771           // TODO: alignment 'features' compare rangeType spec to alignment width - if it is not complete, then mark regions on the annotation row.
1772         }
1773         jan = new jalview.datamodel.AlignmentAnnotation(a_label, a_descr,
1774                 arow);
1775         jan.setThreshold(null);
1776       }
1777       if (annotation.getLinkCount() > 0)
1778       {
1779         Cache.log.warn("Ignoring " + annotation.getLinkCount()
1780                 + "links added to AlignmentAnnotation.");
1781       }
1782       if (annotation.getModifiable() == null) // TODO: USE VAMSAS LIBRARY OBJECT
1783                                               // LOCK METHODS)
1784       {
1785         jan.editable = true;
1786       }
1787       try
1788       {
1789         if (annotation.getGroup() != null
1790                 && annotation.getGroup().length() > 0)
1791         {
1792           jan.graphGroup = Integer.parseInt(annotation.getGroup());
1793         }
1794       } catch (Exception e)
1795       {
1796         Cache.log
1797                 .info("UNIMPLEMENTED : Couldn't parse non-integer group value for setting graphGroup correctly.");
1798       }
1799       return jan;
1800
1801     }
1802
1803     return null;
1804   }
1805
1806   private SequenceFeature getJalviewSeqFeature(RangeAnnotation dseta)
1807   {
1808     int[] se = getBounds(dseta);
1809     SequenceFeature sf = new jalview.datamodel.SequenceFeature(dseta
1810             .getType(), dseta.getDescription(), dseta.getStatus(), se[0],
1811             se[1], dseta.getGroup());
1812     if (dseta.getLinkCount() > 0)
1813     {
1814       Link[] links = dseta.getLink();
1815       for (int i = 0; i < links.length; i++)
1816       {
1817         sf.addLink(links[i].getContent() + "|" + links[i].getHref());
1818       }
1819     }
1820     return sf;
1821   }
1822
1823   /**
1824    * get real bounds of a RangeType's specification. start and end are an
1825    * inclusive range within which all segments and positions lie. TODO: refactor
1826    * to vamsas utils
1827    * 
1828    * @param dseta
1829    * @return int[] { start, end}
1830    */
1831   private int[] getBounds(RangeType dseta)
1832   {
1833     if (dseta != null)
1834     {
1835       int[] se = null;
1836       if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)
1837       {
1838         throw new Error(
1839                 "Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");
1840       }
1841       if (dseta.getSegCount() > 0)
1842       {
1843         se = getSegRange(dseta.getSeg(0), true);
1844         for (int s = 1, sSize = dseta.getSegCount(); s < sSize; s++)
1845         {
1846           int nse[] = getSegRange(dseta.getSeg(s), true);
1847           if (se[0] > nse[0])
1848           {
1849             se[0] = nse[0];
1850           }
1851           if (se[1] < nse[1])
1852           {
1853             se[1] = nse[1];
1854           }
1855         }
1856       }
1857       if (dseta.getPosCount() > 0)
1858       {
1859         // could do a polarity for pos range too. and pass back indication of
1860         // discontinuities.
1861         int pos = dseta.getPos(0).getI();
1862         se = new int[]
1863         { pos, pos };
1864         for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)
1865         {
1866           pos = dseta.getPos(p).getI();
1867           if (se[0] > pos)
1868           {
1869             se[0] = pos;
1870           }
1871           if (se[1] < pos)
1872           {
1873             se[1] = pos;
1874           }
1875         }
1876       }
1877       return se;
1878     }
1879     return null;
1880   }
1881
1882   /**
1883    * map from a rangeType's internal frame to the referenced object's coordinate
1884    * frame.
1885    * 
1886    * @param dseta
1887    * @return int [] { ref(pos)...} for all pos in rangeType's frame.
1888    */
1889   private int[] getMapping(RangeType dseta)
1890   {
1891     Vector posList = new Vector();
1892     if (dseta != null)
1893     {
1894       int[] se = null;
1895       if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)
1896       {
1897         throw new Error(
1898                 "Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");
1899       }
1900       if (dseta.getSegCount() > 0)
1901       {
1902         for (int s = 0, sSize = dseta.getSegCount(); s < sSize; s++)
1903         {
1904           se = getSegRange(dseta.getSeg(s), false);
1905           int se_end = se[1 - se[2]] + (se[2] == 0 ? 1 : -1);
1906           for (int p = se[se[2]]; p != se_end; p += se[2] == 0 ? 1 : -1)
1907           {
1908             posList.add(new Integer(p));
1909           }
1910         }
1911       }
1912       else if (dseta.getPosCount() > 0)
1913       {
1914         int pos = dseta.getPos(0).getI();
1915
1916         for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)
1917         {
1918           pos = dseta.getPos(p).getI();
1919           posList.add(new Integer(pos));
1920         }
1921       }
1922     }
1923     if (posList != null && posList.size() > 0)
1924     {
1925       int[] range = new int[posList.size()];
1926       for (int i = 0; i < range.length; i++)
1927       {
1928         range[i] = ((Integer) posList.elementAt(i)).intValue();
1929       }
1930       posList.clear();
1931       return range;
1932     }
1933     return null;
1934   }
1935
1936   /**
1937    * 
1938    * @param maprange
1939    *          where the from range is the local mapped range, and the to range
1940    *          is the 'mapped' range in the MapRangeType
1941    * @param default
1942    *          unit for local
1943    * @param default
1944    *          unit for mapped
1945    * @return MapList
1946    */
1947   private jalview.util.MapList parsemapType(MapType maprange, int localu,
1948           int mappedu)
1949   {
1950     jalview.util.MapList ml = null;
1951     int[] localRange = getMapping(maprange.getLocal());
1952     int[] mappedRange = getMapping(maprange.getMapped());
1953     long lu = maprange.getLocal().hasUnit() ? maprange.getLocal().getUnit()
1954             : localu;
1955     long mu = maprange.getMapped().hasUnit() ? maprange.getMapped()
1956             .getUnit() : mappedu;
1957     ml = new jalview.util.MapList(localRange, mappedRange, (int) lu,
1958             (int) mu);
1959     return ml;
1960   }
1961
1962   /**
1963    * initialise a range type object from a set of start/end inclusive intervals
1964    * 
1965    * @param mrt
1966    * @param range
1967    */
1968   private void initRangeType(RangeType mrt, int[] range)
1969   {
1970     for (int i = 0; i < range.length; i += 2)
1971     {
1972       Seg vSeg = new Seg();
1973       vSeg.setStart(range[i]);
1974       vSeg.setEnd(range[i + 1]);
1975       mrt.addSeg(vSeg);
1976     }
1977   }
1978
1979   /**
1980    * initialise a MapType object from a MapList object.
1981    * 
1982    * @param maprange
1983    * @param ml
1984    * @param setUnits
1985    */
1986   private void initMapType(MapType maprange, jalview.util.MapList ml,
1987           boolean setUnits)
1988   {
1989     maprange.setLocal(new Local());
1990     maprange.setMapped(new Mapped());
1991     initRangeType(maprange.getLocal(), ml.getFromRanges());
1992     initRangeType(maprange.getMapped(), ml.getToRanges());
1993     if (setUnits)
1994     {
1995       maprange.getLocal().setUnit(ml.getFromRatio());
1996       maprange.getLocal().setUnit(ml.getToRatio());
1997     }
1998   }
1999
2000   /*
2001    * not needed now. Provenance getVamsasProvenance(jalview.datamodel.Provenance
2002    * jprov) { jalview.datamodel.ProvenanceEntry[] entries = null; // TODO: fix
2003    * App and Action here. Provenance prov = new Provenance();
2004    * org.exolab.castor.types.Date date = new org.exolab.castor.types.Date( new
2005    * java.util.Date()); Entry provEntry;
2006    * 
2007    * if (jprov != null) { entries = jprov.getEntries(); for (int i = 0; i <
2008    * entries.length; i++) { provEntry = new Entry(); try { date = new
2009    * org.exolab.castor.types.Date(entries[i].getDate()); } catch (Exception ex) {
2010    * ex.printStackTrace();
2011    * 
2012    * date = new org.exolab.castor.types.Date(entries[i].getDate()); }
2013    * provEntry.setDate(date); provEntry.setUser(entries[i].getUser());
2014    * provEntry.setAction(entries[i].getAction()); prov.addEntry(provEntry); } }
2015    * else { provEntry = new Entry(); provEntry.setDate(date);
2016    * provEntry.setUser(System.getProperty("user.name")); // TODO: ext string
2017    * provEntry.setApp("JVAPP"); // TODO: ext string provEntry.setAction(action);
2018    * prov.addEntry(provEntry); }
2019    * 
2020    * return prov; }
2021    */
2022   jalview.datamodel.Provenance getJalviewProvenance(Provenance prov)
2023   {
2024     // TODO: fix App and Action entries and check use of provenance in jalview.
2025     jalview.datamodel.Provenance jprov = new jalview.datamodel.Provenance();
2026     for (int i = 0; i < prov.getEntryCount(); i++)
2027     {
2028       jprov.addEntry(prov.getEntry(i).getUser(), prov.getEntry(i)
2029               .getAction(), prov.getEntry(i).getDate(), prov.getEntry(i)
2030               .getId());
2031     }
2032
2033     return jprov;
2034   }
2035
2036   /**
2037    * 
2038    * @return default initial provenance list for a Jalview created vamsas
2039    *         object.
2040    */
2041   Provenance dummyProvenance()
2042   {
2043     return dummyProvenance(null);
2044   }
2045
2046   Entry dummyPEntry(String action)
2047   {
2048     Entry entry = new Entry();
2049     entry.setApp(this.provEntry.getApp());
2050     if (action != null)
2051     {
2052       entry.setAction(action);
2053     }
2054     else
2055     {
2056       entry.setAction("created.");
2057     }
2058     entry.setDate(new java.util.Date());
2059     entry.setUser(this.provEntry.getUser());
2060     return entry;
2061   }
2062
2063   Provenance dummyProvenance(String action)
2064   {
2065     Provenance prov = new Provenance();
2066     prov.addEntry(dummyPEntry(action));
2067     return prov;
2068   }
2069
2070   void addProvenance(Provenance p, String action)
2071   {
2072     p.addEntry(dummyPEntry(action));
2073   }
2074
2075   public Entry getProvEntry()
2076   {
2077     return provEntry;
2078   }
2079
2080   public IClientDocument getClientDocument()
2081   {
2082     return cdoc;
2083   }
2084
2085   public IdentityHashMap getJvObjectBinding()
2086   {
2087     return jv2vobj;
2088   }
2089
2090   public Hashtable getVamsasObjectBinding()
2091   {
2092     return vobj2jv;
2093   }
2094
2095   public void storeSequenceMappings(AlignViewport viewport, String title)
2096           throws Exception
2097   {
2098     AlignViewport av = viewport;
2099     try
2100     {
2101       jalview.datamodel.AlignmentI jal = av.getAlignment();
2102       // /////////////////////////////////////////
2103       // SAVE THE DATASET
2104       DataSet dataset = null;
2105       if (jal.getDataset() == null)
2106       {
2107         Cache.log.warn("Creating new dataset for an alignment.");
2108         jal.setDataset(null);
2109       }
2110       dataset = (DataSet) getjv2vObj(jal.getDataset());
2111       // Store any sequence mappings.
2112       if (av.getAlignment().getCodonFrames() != null
2113               && av.getAlignment().getCodonFrames().length > 0)
2114       {
2115         jalview.datamodel.AlignedCodonFrame[] cframes = av.getAlignment()
2116                 .getCodonFrames();
2117         for (int cf = 0; cf < cframes.length; cf++)
2118         {
2119           if (cframes[cf].getdnaSeqs().length > 0)
2120           {
2121             jalview.datamodel.SequenceI[] dmps = cframes[cf].getdnaSeqs();
2122             jalview.datamodel.Mapping[] mps = cframes[cf].getProtMappings();
2123             for (int smp = 0; smp < mps.length; smp++)
2124             {
2125               uk.ac.vamsas.objects.core.SequenceType mfrom = (SequenceType) getjv2vObj(dmps[smp]);
2126               if (mfrom != null)
2127               {
2128                 new jalview.io.vamsas.Sequencemapping(this, mps[smp],
2129                         mfrom, dataset);
2130               }
2131               else
2132               {
2133                 Cache.log
2134                         .warn("NO Vamsas Binding for local sequence! NOT CREATING MAPPING FOR "
2135                                 + mfrom.getName()
2136                                 + " to "
2137                                 + mps[smp].getTo().getName());
2138               }
2139             }
2140           }
2141         }
2142       }
2143     } catch (Exception e)
2144     {
2145       throw new Exception("Couldn't store sequence mappings for " + title,
2146               e);
2147     }
2148   }
2149 }