proper vamsas style binding of alignment sequence objects to newick node labels....
[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.getSequenceSetId()); // this is so we can get
335                                                         // the alignviewport
336                                                         // back
337       if (alignment == null)
338       {
339         alignment = new Alignment();
340         bindjvvobj(av.getSequenceSetId(), 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=findViewport(alignment);
1111             
1112             jalview.datamodel.AlignmentI jal = null;
1113             if (av != null)
1114             {
1115               jal = av.getAlignment();
1116             }
1117             iSize = alignment.getAlignmentSequenceCount();
1118             boolean newal = (jal == null) ? true : false;
1119             Vector newasAnnots = new Vector();
1120             char gapChar = ' '; // default for new alignments read in from the
1121                                 // document
1122             if (jal != null)
1123             {
1124               dsseqs = jal.getSequences(); // for merge/update
1125               gapChar = jal.getGapCharacter();
1126             }
1127             else
1128             {
1129               dsseqs = new Vector();
1130             }
1131             char valGapchar = alignment.getGapChar().charAt(0);
1132             for (i = 0; i < iSize; i++)
1133             {
1134               AlignmentSequence valseq = alignment.getAlignmentSequence(i);
1135               jalview.datamodel.SequenceI alseq = (SequenceI) getvObj2jv(valseq);
1136               if (alseq != null)
1137               {
1138                 // TODO: upperCase/LowerCase situation here ? do we allow it ?
1139                 // if (!alseq.getSequence().equals(valseq.getSequence())) {
1140                 // throw new Error("Broken! - mismatch of dataset sequence and
1141                 // jalview internal dataset sequence.");
1142                 if (Cache.log.isDebugEnabled())
1143                 {
1144                   Cache.log.debug("Updating apparently edited sequence "
1145                           + alseq.getName());
1146                 }
1147                 // this might go *horribly* wrong
1148                 alseq.setSequence(new String(valseq.getSequence()).replace(
1149                         valGapchar, gapChar));
1150                 jremain--;
1151               }
1152               else
1153               {
1154                 alseq = new jalview.datamodel.Sequence(valseq.getName(),
1155                         valseq.getSequence().replace(valGapchar, gapChar),
1156                         (int) valseq.getStart(), (int) valseq.getEnd());
1157
1158                 Vobject datsetseq = (Vobject) valseq.getRefid();
1159                 if (datsetseq != null)
1160                 {
1161                   alseq
1162                           .setDatasetSequence((SequenceI) getvObj2jv(datsetseq)); // exceptions
1163                                                                                   // if
1164                                                                                   // AlignemntSequence
1165                                                                                   // reference
1166                                                                                   // isn't
1167                                                                                   // a
1168                                                                                   // simple
1169                                                                                   // SequenceI
1170                 }
1171                 else
1172                 {
1173                   Cache.log
1174                           .error("Invalid dataset sequence id (null) for alignment sequence "
1175                                   + valseq.getVorbaId());
1176                 }
1177                 bindjvvobj(alseq, valseq);
1178                 alseq.setVamsasId(valseq.getVorbaId().getId());
1179                 dsseqs.add(alseq);
1180               }
1181               if (valseq.getAlignmentSequenceAnnotationCount() > 0)
1182               {
1183                 AlignmentSequenceAnnotation[] vasannot = valseq
1184                         .getAlignmentSequenceAnnotation();
1185                 for (int a = 0; a < vasannot.length; a++)
1186                 {
1187                   jalview.datamodel.AlignmentAnnotation asa = (jalview.datamodel.AlignmentAnnotation) getvObj2jv(vasannot[a]); // TODO:
1188                                                                                                                                 // 1:many
1189                                                                                                                                 // jalview
1190                                                                                                                                 // alignment
1191                                                                                                                                 // sequence
1192                                                                                                                                 // annotations
1193                   if (asa == null)
1194                   {
1195                     int se[] = getBounds(vasannot[a]);
1196                     asa = getjAlignmentAnnotation(jal, vasannot[a]);
1197                     asa.setSequenceRef(alseq);
1198                     asa.createSequenceMapping(alseq, se[0], false); // TODO:
1199                                                                     // verify
1200                                                                     // that
1201                                                                     // positions
1202                                                                     // in
1203                                                                     // alseqAnnotation
1204                                                                     // correspond
1205                                                                     // to
1206                                                                     // ungapped
1207                                                                     // residue
1208                                                                     // positions.
1209                     alseq.addAlignmentAnnotation(asa);
1210                     bindjvvobj(asa, vasannot[a]);
1211                     newasAnnots.add(asa);
1212                   }
1213                   else
1214                   {
1215                     // update existing annotation - can do this in place
1216                     if (vasannot[a].getModifiable() == null) // TODO: USE
1217                                                               // VAMSAS LIBRARY
1218                                                               // OBJECT LOCK
1219                                                               // METHODS)
1220                     {
1221                       Cache.log
1222                               .info("UNIMPLEMENTED: not recovering user modifiable sequence alignment annotation");
1223                       // TODO: should at least replace with new one - otherwise
1224                       // things will break
1225                       // basically do this:
1226                       // int se[] = getBounds(vasannot[a]);
1227                       // asa.update(getjAlignmentAnnotation(jal, vasannot[a]));
1228                       // // update from another annotation object in place.
1229                       // asa.createSequenceMapping(alseq, se[0], false);
1230
1231                     }
1232                   }
1233                 }
1234               }
1235             }
1236             if (jal == null)
1237             {
1238               SequenceI[] seqs = new SequenceI[dsseqs.size()];
1239               for (i = 0, iSize = dsseqs.size(); i < iSize; i++)
1240               {
1241                 seqs[i] = (SequenceI) dsseqs.elementAt(i);
1242                 dsseqs.setElementAt(null, i);
1243               }
1244               jal = new jalview.datamodel.Alignment(seqs);
1245               Cache.log.debug("New vamsas alignment imported into jalview "
1246                       + alignment.getVorbaId().getId());
1247               jal.setDataset(jdataset);
1248             }
1249             if (newasAnnots != null && newasAnnots.size() > 0)
1250             {
1251               // Add the new sequence annotations in to the alignment.
1252               for (int an = 0, anSize = newasAnnots.size(); an < anSize; an++)
1253               {
1254                 jal.addAnnotation((AlignmentAnnotation) newasAnnots
1255                         .elementAt(an));
1256                 // TODO: check if anything has to be done - like calling
1257                 // adjustForAlignment or something.
1258                 newasAnnots.setElementAt(null, an);
1259               }
1260               newasAnnots = null;
1261             }
1262             // //////////////////////////////////////////
1263             // //LOAD ANNOTATIONS FOR THE ALIGNMENT
1264             // ////////////////////////////////////
1265             if (alignment.getAlignmentAnnotationCount() > 0)
1266             {
1267               uk.ac.vamsas.objects.core.AlignmentAnnotation[] an = alignment
1268                       .getAlignmentAnnotation();
1269
1270               for (int j = 0; j < an.length; j++)
1271               {
1272                 jalview.datamodel.AlignmentAnnotation jan = (jalview.datamodel.AlignmentAnnotation) getvObj2jv(an[j]);
1273                 if (jan != null)
1274                 {
1275                   // update or stay the same.
1276                   // TODO: should at least replace with a new one - otherwise
1277                   // things will break
1278                   // basically do this:
1279                   // jan.update(getjAlignmentAnnotation(jal, an[a])); // update
1280                   // from another annotation object in place.
1281
1282                   Cache.log
1283                           .debug("update from vamsas alignment annotation to existing jalview alignment annotation.");
1284                   if (an[j].getModifiable() == null) // TODO: USE VAMSAS
1285                                                       // LIBRARY OBJECT LOCK
1286                                                       // METHODS)
1287                   {
1288                     // TODO: user defined annotation is totally mutable... - so
1289                     // load it up or throw away if locally edited.
1290                     Cache.log
1291                             .info("NOT IMPLEMENTED - Recovering user-modifiable annotation - yet...");
1292                   }
1293                   // TODO: compare annotation element rows
1294                   // TODO: compare props.
1295                 }
1296                 else
1297                 {
1298                   jan = getjAlignmentAnnotation(jal, an[j]);
1299                   jal.addAnnotation(jan);
1300                   bindjvvobj(jan, an[j]);
1301                 }
1302               }
1303             }
1304             AlignFrame alignFrame;
1305             if (av == null)
1306             {
1307               Cache.log.debug("New alignframe for alignment "
1308                       + alignment.getVorbaId());
1309               // ///////////////////////////////
1310               // construct alignment view
1311               alignFrame = new AlignFrame(jal, AlignFrame.DEFAULT_WIDTH,
1312                       AlignFrame.DEFAULT_HEIGHT);
1313               av = alignFrame.getViewport();
1314               String title = alignment.getProvenance().getEntry(
1315                       alignment.getProvenance().getEntryCount() - 1)
1316                       .getAction();
1317               if (alignment.getPropertyCount() > 0)
1318               {
1319                 for (int p = 0, pe = alignment.getPropertyCount(); p < pe; p++)
1320                 {
1321                   if (alignment.getProperty(p).getName().equals(
1322                           "title"))
1323                   {
1324                     title = alignment.getProperty(p).getContent();
1325                   }
1326                 }
1327               }
1328               // TODO: automatically create meaningful title for a vamsas
1329               // alignment using its provenance.
1330               if (Cache.log.isDebugEnabled())
1331               {
1332                 title = title + "("
1333                  + alignment.getVorbaId() + ")";
1334                 
1335               }
1336               jalview.gui.Desktop.addInternalFrame(alignFrame, title 
1337                       ,
1338                       AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
1339               bindjvvobj(av.getSequenceSetId(), alignment);
1340             }
1341             else
1342             {
1343               // find the alignFrame for jal.
1344               // TODO: fix this so we retrieve the alignFrame handing av
1345               // *directly*
1346               alignFrame = getAlignFrameFor(av);
1347             }
1348             // LOAD TREES
1349             // /////////////////////////////////////
1350             if (alignment.getTreeCount() > 0)
1351             {
1352
1353               for (int t = 0; t < alignment.getTreeCount(); t++)
1354               {
1355                 jalview.io.vamsas.Tree vstree = new jalview.io.vamsas.Tree(
1356                         this, alignFrame, alignment.getTree(t));
1357                 TreePanel tp = null;
1358                 if (vstree.isValidTree())
1359                 { 
1360                   tp = alignFrame
1361                         .ShowNewickTree(vstree.getNewickTree(), vstree
1362                                 .getTitle(), vstree.getInputData(), 600,
1363                                 500, t * 20 + 50, t * 20 + 50);
1364                   
1365                 }
1366                 if (tp!=null)
1367                 { 
1368                   bindjvvobj(tp, alignment.getTree(t));
1369                   try
1370                   {
1371                     vstree.UpdateSequenceTreeMap(tp);
1372                   } catch (RuntimeException e)
1373                   {
1374                     Cache.log.warn("update of labels failed.",e);
1375                   }
1376                 }
1377                 else
1378                 {
1379                   Cache.log.warn("Cannot create tree for tree "+t+" in document ("+alignment.getTree(t).getVorbaId());
1380                 }
1381
1382               }
1383             }
1384           }
1385         }
1386       }
1387       // we do sequenceMappings last because they span all datasets in a vamsas
1388       // root
1389       for (int _ds = 0, _nds = root.getDataSetCount(); _ds < _nds; _ds++)
1390       {
1391         DataSet dataset = root.getDataSet(_ds);
1392         if (dataset.getSequenceMappingCount() > 0)
1393         {
1394           for (int sm = 0, smCount = dataset.getSequenceMappingCount(); sm < smCount; sm++)
1395           {
1396             Rangetype seqmap = new jalview.io.vamsas.Sequencemapping(this,
1397                     dataset.getSequenceMapping(sm));
1398           }
1399         }
1400       }
1401     }
1402   }
1403
1404   public AlignViewport findViewport(Alignment alignment)
1405   {
1406     AlignViewport av=null;
1407     AlignViewport[] avs = findViewportForSequenceSetId((String)getvObj2jv(alignment));
1408     if (avs!=null)
1409     {
1410       av = avs[0];
1411     }
1412     return av;
1413   }
1414
1415   private AlignViewport[] findViewportForSequenceSetId(String sequenceSetId)
1416   {
1417     Vector viewp = new Vector();
1418     if (Desktop.desktop != null)
1419     {
1420       javax.swing.JInternalFrame[] frames = Desktop.instance.getAllFrames();
1421
1422       for (int t = 0; t < frames.length; t++)
1423       {
1424         if (frames[t] instanceof AlignFrame)
1425         {
1426           if (((AlignFrame) frames[t]).getViewport().getSequenceSetId().equals(sequenceSetId))
1427           {
1428             viewp.addElement(((AlignFrame) frames[t]).getViewport());
1429           }
1430         }
1431       }
1432       if (viewp.size()>0)
1433       {
1434         AlignViewport[] vp = new AlignViewport[viewp.size()];
1435         viewp.copyInto(vp);
1436         return vp;
1437       }
1438     }
1439     return null;
1440   }
1441
1442   // bitfields - should be a template in j1.5
1443   private static int HASSECSTR = 0;
1444
1445   private static int HASVALS = 1;
1446
1447   private static int HASHPHOB = 2;
1448
1449   private static int HASDC = 3;
1450
1451   private static int HASDESCSTR = 4;
1452
1453   private static int HASTWOSTATE = 5; // not used yet.
1454
1455   /**
1456    * parses the AnnotationElements - if they exist - into
1457    * jalview.datamodel.Annotation[] rows Two annotation rows are made if there
1458    * are distinct annotation for both at 'pos' and 'after pos' at any particular
1459    * site.
1460    * 
1461    * @param annotation
1462    * @return { boolean[static int constants ], int[ae.length] - map to annotated
1463    *         object frame, jalview.datamodel.Annotation[],
1464    *         jalview.datamodel.Annotation[] (after)}
1465    */
1466   private Object[] parseRangeAnnotation(
1467           uk.ac.vamsas.objects.core.RangeAnnotation annotation)
1468   {
1469     // set these attributes by looking in the annotation to decide what kind of
1470     // alignment annotation rows will be made
1471     // TODO: potentially we might make several annotation rows from one vamsas
1472     // alignment annotation. the jv2Vobj binding mechanism
1473     // may not quite cope with this (without binding an array of annotations to
1474     // a vamsas alignment annotation)
1475     // summary flags saying what we found over the set of annotation rows.
1476     boolean[] AeContent = new boolean[]
1477     { false, false, false, false, false };
1478     int[] rangeMap = getMapping(annotation);
1479     jalview.datamodel.Annotation[][] anot = new jalview.datamodel.Annotation[][]
1480     { new jalview.datamodel.Annotation[rangeMap.length],
1481         new jalview.datamodel.Annotation[rangeMap.length] };
1482     boolean mergeable = true; // false if 'after positions cant be placed on
1483                               // same annotation row as positions.
1484
1485     if (annotation.getAnnotationElementCount() > 0)
1486     {
1487       AnnotationElement ae[] = annotation.getAnnotationElement();
1488       for (int aa = 0; aa < ae.length; aa++)
1489       {
1490         int pos = (int) ae[aa].getPosition() - 1; // pos counts from 1 to
1491                                                   // (|seg.start-seg.end|+1)
1492         if (pos >= 0 && pos < rangeMap.length)
1493         {
1494           int row = ae[aa].getAfter() ? 1 : 0;
1495           if (anot[row][pos] != null)
1496           {
1497             // only time this should happen is if the After flag is set.
1498             Cache.log.debug("Ignoring duplicate annotation site at " + pos);
1499             continue;
1500           }
1501           if (anot[1 - row][pos] != null)
1502           {
1503             mergeable = false;
1504           }
1505           String desc = "";
1506           if (ae[aa].getDescription() != null)
1507           {
1508             desc = ae[aa].getDescription();
1509             if (desc.length() > 0)
1510             {
1511               // have imported valid description string
1512               AeContent[HASDESCSTR] = true;
1513             }
1514           }
1515           String dc = null; // ae[aa].getDisplayCharacter()==null ? "dc" :
1516                             // ae[aa].getDisplayCharacter();
1517           String ss = null; // ae[aa].getSecondaryStructure()==null ? "ss" :
1518                             // ae[aa].getSecondaryStructure();
1519           java.awt.Color colour = null;
1520           if (ae[aa].getGlyphCount() > 0)
1521           {
1522             Glyph[] glyphs = ae[aa].getGlyph();
1523             for (int g = 0; g < glyphs.length; g++)
1524             {
1525               if (glyphs[g]
1526                       .getDict()
1527                       .equals(
1528                               uk.ac.vamsas.objects.utils.GlyphDictionary.PROTEIN_SS_3STATE))
1529               {
1530                 ss = glyphs[g].getContent();
1531                 AeContent[HASSECSTR] = true;
1532               }
1533               else if (glyphs[g]
1534                       .getDict()
1535                       .equals(
1536                               uk.ac.vamsas.objects.utils.GlyphDictionary.PROTEIN_HD_HYDRO))
1537               {
1538                 Cache.log.debug("ignoring hydrophobicity glyph marker.");
1539                 AeContent[HASHPHOB] = true;
1540                 char c = (dc = glyphs[g].getContent()).charAt(0);
1541                 // dc may get overwritten - but we still set the colour.
1542                 colour = new java.awt.Color(c == '+' ? 255 : 0,
1543                         c == '.' ? 255 : 0, c == '-' ? 255 : 0);
1544
1545               }
1546               else if (glyphs[g].getDict().equals(
1547                       uk.ac.vamsas.objects.utils.GlyphDictionary.DEFAULT))
1548               {
1549                 dc = glyphs[g].getContent();
1550                 AeContent[HASDC] = true;
1551               }
1552               else
1553               {
1554                 Cache.log.debug("IMPLEMENTATION TODO: Ignoring unknown glyph type "
1555                         + glyphs[g].getDict());
1556               }
1557             }
1558           }
1559           float val = 0;
1560           if (ae[aa].getValueCount() > 0)
1561           {
1562             AeContent[HASVALS] = true;
1563             if (ae[aa].getValueCount() > 1)
1564             {
1565               Cache.log.warn("ignoring additional "
1566                       + (ae[aa].getValueCount() - 1)
1567                       + "values in annotation element.");
1568             }
1569             val = ae[aa].getValue(0);
1570           }
1571           if (colour == null)
1572           {
1573             anot[row][pos] = new jalview.datamodel.Annotation(
1574                     (dc != null) ? dc : "", desc, (ss != null) ? ss
1575                             .charAt(0) : ' ', val);
1576           }
1577           else
1578           {
1579             anot[row][pos] = new jalview.datamodel.Annotation(
1580                     (dc != null) ? dc : "", desc, (ss != null) ? ss
1581                             .charAt(0) : ' ', val, colour);
1582           }
1583         }
1584         else
1585         {
1586           Cache.log.warn("Ignoring out of bound annotation element " + aa
1587                   + " in " + annotation.getVorbaId().getId());
1588         }
1589       }
1590       // decide on how many annotation rows are needed.
1591       if (mergeable)
1592       {
1593         for (int i = 0; i < anot[0].length; i++)
1594         {
1595           if (anot[1][i] != null)
1596           {
1597             anot[0][i] = anot[1][i];
1598             anot[0][i].description = anot[0][i].description + " (after)";
1599             AeContent[HASDESCSTR] = true; // we have valid description string
1600                                           // data
1601             anot[1][i] = null;
1602           }
1603         }
1604         anot[1] = null;
1605       }
1606       else
1607       {
1608         for (int i = 0; i < anot[0].length; i++)
1609         {
1610           anot[1][i].description = anot[1][i].description + " (after)";
1611         }
1612       }
1613       return new Object[]
1614       { AeContent, rangeMap, anot[0], anot[1] };
1615     }
1616     else
1617     {
1618       // no annotations to parse. Just return an empty annotationElement[]
1619       // array.
1620       return new Object[]
1621       { AeContent, rangeMap, anot[0], anot[1] };
1622     }
1623     // return null;
1624   }
1625
1626   /**
1627    * @param jal
1628    *          the jalview alignment to which the annotation will be attached
1629    *          (ideally - freshly updated from corresponding vamsas alignment)
1630    * @param annotation
1631    * @return unbound jalview alignment annotation object.
1632    */
1633   private jalview.datamodel.AlignmentAnnotation getjAlignmentAnnotation(
1634           jalview.datamodel.AlignmentI jal,
1635           uk.ac.vamsas.objects.core.RangeAnnotation annotation)
1636   {
1637     if (annotation == null)
1638     {
1639       return null;
1640     }
1641     // boolean
1642     // hasSequenceRef=annotation.getClass().equals(uk.ac.vamsas.objects.core.AlignmentSequenceAnnotation.class);
1643     // boolean hasProvenance=hasSequenceRef ||
1644     // (annotation.getClass().equals(uk.ac.vamsas.objects.core.AlignmentAnnotation.class));
1645     /*
1646      * int se[] = getBounds(annotation); if (se==null) se=new int[]
1647      * {0,jal.getWidth()-1};
1648      */
1649     Object[] parsedRangeAnnotation = parseRangeAnnotation(annotation);
1650     String a_label = annotation.getLabel();
1651     String a_descr = annotation.getDescription();
1652     GraphLine gl=null;
1653     int type=0;
1654     boolean interp=true; // cleared if annotation is DISCRETE
1655     // set type and other attributes from properties
1656     if (annotation.getPropertyCount() > 0)
1657     {
1658       // look for special jalview properties
1659       uk.ac.vamsas.objects.core.Property[] props = annotation
1660               .getProperty();
1661       for (int p = 0; p < props.length; p++)
1662       {
1663         if (props[p].getName().equalsIgnoreCase(DISCRETE_ANNOTATION))
1664         {
1665           type = AlignmentAnnotation.BAR_GRAPH;
1666           interp=false;
1667         } else if
1668          (props[p].getName().equalsIgnoreCase(CONTINUOUS_ANNOTATION)) {
1669           type = AlignmentAnnotation.LINE_GRAPH;
1670         } else if
1671         (props[p].getName().equalsIgnoreCase(THRESHOLD))
1672         {
1673           Float val=null;
1674           try {
1675             val = new Float(props[p].getContent());
1676           }catch (Exception e)
1677           {
1678             Cache.log.warn("Failed to parse threshold property");
1679           }
1680           if (val!=null)
1681           if (gl==null)
1682           {
1683             gl = new GraphLine(val.floatValue(), "", java.awt.Color.black);
1684           } else
1685           {
1686             gl.value = val.floatValue();
1687           }
1688         }
1689         else if (props[p].getName().equalsIgnoreCase(THRESHOLD+"Name"))
1690         {
1691           if (gl==null)
1692             gl = new GraphLine(0, "", java.awt.Color.black);
1693           gl.label = props[p].getContent();
1694         }
1695       }
1696     }
1697     jalview.datamodel.AlignmentAnnotation jan = null;
1698     if (a_label == null || a_label.length() == 0)
1699     {
1700       a_label = annotation.getType();
1701       if (a_label.length() == 0)
1702       {
1703         a_label = "Unamed annotation";
1704       }
1705     }
1706     if (a_descr == null || a_descr.length() == 0)
1707     {
1708       a_descr = "Annotation of type '" + annotation.getType() + "'";
1709     }
1710     if (parsedRangeAnnotation == null)
1711     {
1712       Cache.log
1713               .debug("Inserting empty annotation row elements for a whole-alignment annotation.");
1714     }
1715     else
1716     {
1717       if (parsedRangeAnnotation[3] != null)
1718       {
1719         Cache.log.warn("Ignoring 'After' annotation row in "
1720                 + annotation.getVorbaId());
1721       }
1722       jalview.datamodel.Annotation[] arow = (jalview.datamodel.Annotation[]) parsedRangeAnnotation[2];
1723       boolean[] has = (boolean[]) parsedRangeAnnotation[0];
1724       // VAMSAS: getGraph is only on derived annotation for alignments - in this
1725       // way its 'odd' - there is already an existing TODO about removing this
1726       // flag as being redundant
1727       /*
1728        * if
1729        * ((annotation.getClass().equals(uk.ac.vamsas.objects.core.AlignmentAnnotation.class) &&
1730        * ((uk.ac.vamsas.objects.core.AlignmentAnnotation)annotation).getGraph()) ||
1731        * (hasSequenceRef=true &&
1732        * ((uk.ac.vamsas.objects.core.AlignmentSequenceAnnotation)annotation).getGraph())) {
1733        */
1734       if (has[HASVALS])
1735       {
1736         if (type==0)
1737         {
1738           type = jalview.datamodel.AlignmentAnnotation.BAR_GRAPH; // default type of value annotation
1739           if (has[HASHPHOB])
1740           {
1741             // no hints - so we ensure HPHOB display is like this.
1742             type = jalview.datamodel.AlignmentAnnotation.BAR_GRAPH;
1743           }
1744         }
1745         // make bounds and automatic description strings for jalview user's
1746         // benefit (these shouldn't be written back to vamsas document)
1747         boolean first = true;
1748         float min = 0, max = 1;
1749         int lastval = 0;
1750         for (int i = 0; i < arow.length; i++)
1751         {
1752           if (arow[i] != null)
1753           {
1754             if (i - lastval > 1 && interp)
1755             {
1756               // do some interpolation *between* points
1757               if (arow[lastval] != null)
1758               {
1759                 float interval = arow[i].value - arow[lastval].value;
1760                 interval /= i - lastval;
1761                 float base = arow[lastval].value;
1762                 for (int ip = lastval + 1, np = 0; ip < i; np++, ip++)
1763                 {
1764                   arow[ip] = new jalview.datamodel.Annotation("", "", ' ',
1765                           interval * np + base);
1766                   // NB - Interpolated points don't get a tooltip and
1767                   // description.
1768                 }
1769               }
1770             }
1771             lastval = i;
1772             // check range - shouldn't we have a min and max property in the
1773             // annotation object ?
1774             if (first)
1775             {
1776               min = max = arow[i].value;
1777               first = false;
1778             }
1779             else
1780             {
1781               if (arow[i].value < min)
1782               {
1783                 min = arow[i].value;
1784               }
1785               else if (arow[i].value > max)
1786               {
1787                 max = arow[i].value;
1788               }
1789             }
1790             // make tooltip and display char value
1791             if (!has[HASDESCSTR])
1792             {
1793               arow[i].description = arow[i].value + "";
1794             }
1795             if (!has[HASDC])
1796             {
1797               if (!interp)
1798                 {
1799                 if (arow[i].description!=null && arow[i].description.length()<3)
1800                 {
1801                   // copy over the description as the display char.
1802                   arow[i].displayCharacter = new String(arow[i].description);
1803                 }
1804                 } else
1805                 {
1806                   // mark the position as a point used for the interpolation.
1807                 arow[i].displayCharacter = arow[i].value + "";
1808                 }
1809             }
1810           }
1811         }
1812         jan = new jalview.datamodel.AlignmentAnnotation(a_label, a_descr,
1813                 arow, min, max, type);
1814       }
1815       else
1816       {
1817         if (annotation.getAnnotationElementCount()==0)
1818         {
1819           // empty annotation array
1820           // TODO: alignment 'features' compare rangeType spec to alignment width - if it is not complete, then mark regions on the annotation row.
1821         }
1822         jan = new jalview.datamodel.AlignmentAnnotation(a_label, a_descr,
1823                 arow);
1824         jan.setThreshold(null);
1825       }
1826       if (annotation.getLinkCount() > 0)
1827       {
1828         Cache.log.warn("Ignoring " + annotation.getLinkCount()
1829                 + "links added to AlignmentAnnotation.");
1830       }
1831       if (annotation.getModifiable() == null) // TODO: USE VAMSAS LIBRARY OBJECT
1832                                               // LOCK METHODS)
1833       {
1834         jan.editable = true;
1835       }
1836       try
1837       {
1838         if (annotation.getGroup() != null
1839                 && annotation.getGroup().length() > 0)
1840         {
1841           jan.graphGroup = Integer.parseInt(annotation.getGroup());
1842         }
1843       } catch (Exception e)
1844       {
1845         Cache.log
1846                 .info("UNIMPLEMENTED : Couldn't parse non-integer group value for setting graphGroup correctly.");
1847       }
1848       return jan;
1849
1850     }
1851
1852     return null;
1853   }
1854
1855   private SequenceFeature getJalviewSeqFeature(RangeAnnotation dseta)
1856   {
1857     int[] se = getBounds(dseta);
1858     SequenceFeature sf = new jalview.datamodel.SequenceFeature(dseta
1859             .getType(), dseta.getDescription(), dseta.getStatus(), se[0],
1860             se[1], dseta.getGroup());
1861     if (dseta.getLinkCount() > 0)
1862     {
1863       Link[] links = dseta.getLink();
1864       for (int i = 0; i < links.length; i++)
1865       {
1866         sf.addLink(links[i].getContent() + "|" + links[i].getHref());
1867       }
1868     }
1869     return sf;
1870   }
1871
1872   /**
1873    * get real bounds of a RangeType's specification. start and end are an
1874    * inclusive range within which all segments and positions lie. TODO: refactor
1875    * to vamsas utils
1876    * 
1877    * @param dseta
1878    * @return int[] { start, end}
1879    */
1880   private int[] getBounds(RangeType dseta)
1881   {
1882     if (dseta != null)
1883     {
1884       int[] se = null;
1885       if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)
1886       {
1887         throw new Error(
1888                 "Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");
1889       }
1890       if (dseta.getSegCount() > 0)
1891       {
1892         se = getSegRange(dseta.getSeg(0), true);
1893         for (int s = 1, sSize = dseta.getSegCount(); s < sSize; s++)
1894         {
1895           int nse[] = getSegRange(dseta.getSeg(s), true);
1896           if (se[0] > nse[0])
1897           {
1898             se[0] = nse[0];
1899           }
1900           if (se[1] < nse[1])
1901           {
1902             se[1] = nse[1];
1903           }
1904         }
1905       }
1906       if (dseta.getPosCount() > 0)
1907       {
1908         // could do a polarity for pos range too. and pass back indication of
1909         // discontinuities.
1910         int pos = dseta.getPos(0).getI();
1911         se = new int[]
1912         { pos, pos };
1913         for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)
1914         {
1915           pos = dseta.getPos(p).getI();
1916           if (se[0] > pos)
1917           {
1918             se[0] = pos;
1919           }
1920           if (se[1] < pos)
1921           {
1922             se[1] = pos;
1923           }
1924         }
1925       }
1926       return se;
1927     }
1928     return null;
1929   }
1930
1931   /**
1932    * map from a rangeType's internal frame to the referenced object's coordinate
1933    * frame.
1934    * 
1935    * @param dseta
1936    * @return int [] { ref(pos)...} for all pos in rangeType's frame.
1937    */
1938   private int[] getMapping(RangeType dseta)
1939   {
1940     Vector posList = new Vector();
1941     if (dseta != null)
1942     {
1943       int[] se = null;
1944       if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)
1945       {
1946         throw new Error(
1947                 "Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");
1948       }
1949       if (dseta.getSegCount() > 0)
1950       {
1951         for (int s = 0, sSize = dseta.getSegCount(); s < sSize; s++)
1952         {
1953           se = getSegRange(dseta.getSeg(s), false);
1954           int se_end = se[1 - se[2]] + (se[2] == 0 ? 1 : -1);
1955           for (int p = se[se[2]]; p != se_end; p += se[2] == 0 ? 1 : -1)
1956           {
1957             posList.add(new Integer(p));
1958           }
1959         }
1960       }
1961       else if (dseta.getPosCount() > 0)
1962       {
1963         int pos = dseta.getPos(0).getI();
1964
1965         for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)
1966         {
1967           pos = dseta.getPos(p).getI();
1968           posList.add(new Integer(pos));
1969         }
1970       }
1971     }
1972     if (posList != null && posList.size() > 0)
1973     {
1974       int[] range = new int[posList.size()];
1975       for (int i = 0; i < range.length; i++)
1976       {
1977         range[i] = ((Integer) posList.elementAt(i)).intValue();
1978       }
1979       posList.clear();
1980       return range;
1981     }
1982     return null;
1983   }
1984
1985   /**
1986    * 
1987    * @param maprange
1988    *          where the from range is the local mapped range, and the to range
1989    *          is the 'mapped' range in the MapRangeType
1990    * @param default
1991    *          unit for local
1992    * @param default
1993    *          unit for mapped
1994    * @return MapList
1995    */
1996   private jalview.util.MapList parsemapType(MapType maprange, int localu,
1997           int mappedu)
1998   {
1999     jalview.util.MapList ml = null;
2000     int[] localRange = getMapping(maprange.getLocal());
2001     int[] mappedRange = getMapping(maprange.getMapped());
2002     long lu = maprange.getLocal().hasUnit() ? maprange.getLocal().getUnit()
2003             : localu;
2004     long mu = maprange.getMapped().hasUnit() ? maprange.getMapped()
2005             .getUnit() : mappedu;
2006     ml = new jalview.util.MapList(localRange, mappedRange, (int) lu,
2007             (int) mu);
2008     return ml;
2009   }
2010
2011   /**
2012    * initialise a range type object from a set of start/end inclusive intervals
2013    * 
2014    * @param mrt
2015    * @param range
2016    */
2017   private void initRangeType(RangeType mrt, int[] range)
2018   {
2019     for (int i = 0; i < range.length; i += 2)
2020     {
2021       Seg vSeg = new Seg();
2022       vSeg.setStart(range[i]);
2023       vSeg.setEnd(range[i + 1]);
2024       mrt.addSeg(vSeg);
2025     }
2026   }
2027
2028   /**
2029    * initialise a MapType object from a MapList object.
2030    * 
2031    * @param maprange
2032    * @param ml
2033    * @param setUnits
2034    */
2035   private void initMapType(MapType maprange, jalview.util.MapList ml,
2036           boolean setUnits)
2037   {
2038     maprange.setLocal(new Local());
2039     maprange.setMapped(new Mapped());
2040     initRangeType(maprange.getLocal(), ml.getFromRanges());
2041     initRangeType(maprange.getMapped(), ml.getToRanges());
2042     if (setUnits)
2043     {
2044       maprange.getLocal().setUnit(ml.getFromRatio());
2045       maprange.getLocal().setUnit(ml.getToRatio());
2046     }
2047   }
2048
2049   /*
2050    * not needed now. Provenance getVamsasProvenance(jalview.datamodel.Provenance
2051    * jprov) { jalview.datamodel.ProvenanceEntry[] entries = null; // TODO: fix
2052    * App and Action here. Provenance prov = new Provenance();
2053    * org.exolab.castor.types.Date date = new org.exolab.castor.types.Date( new
2054    * java.util.Date()); Entry provEntry;
2055    * 
2056    * if (jprov != null) { entries = jprov.getEntries(); for (int i = 0; i <
2057    * entries.length; i++) { provEntry = new Entry(); try { date = new
2058    * org.exolab.castor.types.Date(entries[i].getDate()); } catch (Exception ex) {
2059    * ex.printStackTrace();
2060    * 
2061    * date = new org.exolab.castor.types.Date(entries[i].getDate()); }
2062    * provEntry.setDate(date); provEntry.setUser(entries[i].getUser());
2063    * provEntry.setAction(entries[i].getAction()); prov.addEntry(provEntry); } }
2064    * else { provEntry = new Entry(); provEntry.setDate(date);
2065    * provEntry.setUser(System.getProperty("user.name")); // TODO: ext string
2066    * provEntry.setApp("JVAPP"); // TODO: ext string provEntry.setAction(action);
2067    * prov.addEntry(provEntry); }
2068    * 
2069    * return prov; }
2070    */
2071   jalview.datamodel.Provenance getJalviewProvenance(Provenance prov)
2072   {
2073     // TODO: fix App and Action entries and check use of provenance in jalview.
2074     jalview.datamodel.Provenance jprov = new jalview.datamodel.Provenance();
2075     for (int i = 0; i < prov.getEntryCount(); i++)
2076     {
2077       jprov.addEntry(prov.getEntry(i).getUser(), prov.getEntry(i)
2078               .getAction(), prov.getEntry(i).getDate(), prov.getEntry(i)
2079               .getId());
2080     }
2081
2082     return jprov;
2083   }
2084
2085   /**
2086    * 
2087    * @return default initial provenance list for a Jalview created vamsas
2088    *         object.
2089    */
2090   Provenance dummyProvenance()
2091   {
2092     return dummyProvenance(null);
2093   }
2094
2095   Entry dummyPEntry(String action)
2096   {
2097     Entry entry = new Entry();
2098     entry.setApp(this.provEntry.getApp());
2099     if (action != null)
2100     {
2101       entry.setAction(action);
2102     }
2103     else
2104     {
2105       entry.setAction("created.");
2106     }
2107     entry.setDate(new java.util.Date());
2108     entry.setUser(this.provEntry.getUser());
2109     return entry;
2110   }
2111
2112   Provenance dummyProvenance(String action)
2113   {
2114     Provenance prov = new Provenance();
2115     prov.addEntry(dummyPEntry(action));
2116     return prov;
2117   }
2118
2119   void addProvenance(Provenance p, String action)
2120   {
2121     p.addEntry(dummyPEntry(action));
2122   }
2123
2124   public Entry getProvEntry()
2125   {
2126     return provEntry;
2127   }
2128
2129   public IClientDocument getClientDocument()
2130   {
2131     return cdoc;
2132   }
2133
2134   public IdentityHashMap getJvObjectBinding()
2135   {
2136     return jv2vobj;
2137   }
2138
2139   public Hashtable getVamsasObjectBinding()
2140   {
2141     return vobj2jv;
2142   }
2143
2144   public void storeSequenceMappings(AlignViewport viewport, String title)
2145           throws Exception
2146   {
2147     AlignViewport av = viewport;
2148     try
2149     {
2150       jalview.datamodel.AlignmentI jal = av.getAlignment();
2151       // /////////////////////////////////////////
2152       // SAVE THE DATASET
2153       DataSet dataset = null;
2154       if (jal.getDataset() == null)
2155       {
2156         Cache.log.warn("Creating new dataset for an alignment.");
2157         jal.setDataset(null);
2158       }
2159       dataset = (DataSet) getjv2vObj(jal.getDataset());
2160       // Store any sequence mappings.
2161       if (av.getAlignment().getCodonFrames() != null
2162               && av.getAlignment().getCodonFrames().length > 0)
2163       {
2164         jalview.datamodel.AlignedCodonFrame[] cframes = av.getAlignment()
2165                 .getCodonFrames();
2166         for (int cf = 0; cf < cframes.length; cf++)
2167         {
2168           if (cframes[cf].getdnaSeqs().length > 0)
2169           {
2170             jalview.datamodel.SequenceI[] dmps = cframes[cf].getdnaSeqs();
2171             jalview.datamodel.Mapping[] mps = cframes[cf].getProtMappings();
2172             for (int smp = 0; smp < mps.length; smp++)
2173             {
2174               uk.ac.vamsas.objects.core.SequenceType mfrom = (SequenceType) getjv2vObj(dmps[smp]);
2175               if (mfrom != null)
2176               {
2177                 new jalview.io.vamsas.Sequencemapping(this, mps[smp],
2178                         mfrom, dataset);
2179               }
2180               else
2181               {
2182                 Cache.log
2183                         .warn("NO Vamsas Binding for local sequence! NOT CREATING MAPPING FOR "
2184                                 + dmps[smp].getDisplayId(true)
2185                                 + " to "
2186                                 + mps[smp].getTo().getName());
2187               }
2188             }
2189           }
2190         }
2191       }
2192     } catch (Exception e)
2193     {
2194       throw new Exception("Couldn't store sequence mappings for " + title,
2195               e);
2196     }
2197   }
2198 }