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