added store of undo/redo hash for each alignment so local state changes can be detect...
authorjprocter <Jim Procter>
Tue, 25 Sep 2007 09:30:29 +0000 (09:30 +0000)
committerjprocter <Jim Procter>
Tue, 25 Sep 2007 09:30:29 +0000 (09:30 +0000)
src/jalview/gui/VamsasApplication.java
src/jalview/io/VamsasAppDatastore.java

index 65212a6..50670a0 100644 (file)
@@ -283,7 +283,7 @@ public class VamsasApplication
     Cache.log.debug("Jalview updating from sesion document ..");
     ensureJvVamsas();
     VamsasAppDatastore vds = new VamsasAppDatastore(cdoc, vobj2jv, jv2vobj,
-            baseProvEntry());
+            baseProvEntry(), alRedoState);
     vds.updateToJalview();
     Cache.log.debug(".. finished updating from sesion document.");
 
@@ -295,6 +295,7 @@ public class VamsasApplication
     {
       jv2vobj = new IdentityHashMap();
       vobj2jv = new Hashtable();
+      alRedoState = new Hashtable();
     }
   }
 
@@ -304,12 +305,12 @@ public class VamsasApplication
   IdentityHashMap jv2vobj = null;
 
   Hashtable vobj2jv = null;
-
+  Hashtable alRedoState = null;
   public void updateVamsasDocument(IClientDocument doc)
   {
     ensureJvVamsas();
     VamsasAppDatastore vds = new VamsasAppDatastore(doc, vobj2jv, jv2vobj,
-            baseProvEntry());
+            baseProvEntry(), alRedoState);
     // wander through frames
     JInternalFrame[] frames = Desktop.desktop.getAllFrames();
 
index aaaf589..7e0513d 100644 (file)
@@ -79,13 +79,16 @@ public class VamsasAppDatastore
 
   IdentityHashMap jv2vobj;
 
+  Hashtable alignRDHash;
+
   public VamsasAppDatastore(IClientDocument cdoc, Hashtable vobj2jv,
-          IdentityHashMap jv2vobj, Entry provEntry)
+          IdentityHashMap jv2vobj, Entry provEntry, Hashtable alignRDHash)
   {
     this.cdoc = cdoc;
     this.vobj2jv = vobj2jv;
     this.jv2vobj = jv2vobj;
     this.provEntry = provEntry;
+    this.alignRDHash = alignRDHash; 
   }
 
   /**
@@ -235,7 +238,7 @@ public class VamsasAppDatastore
         root.addDataSet(dataset);
         bindjvvobj(jal.getDataset(), dataset);
         dataset.setProvenance(dummyProvenance());
-        dataset.getProvenance().addEntry(provEntry);
+        // dataset.getProvenance().addEntry(provEntry);
         nw = true;
       }
       else
@@ -251,6 +254,7 @@ public class VamsasAppDatastore
       // acid sequences.
       String dict = jal.isNucleotide() ? uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA
               : uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_AA;
+      Vector dssmods = new Vector();
       for (int i = 0; i < jal.getHeight(); i++)
       {
         SequenceI sq = jal.getSequenceAt(i).getDatasetSequence(); // only insert
@@ -265,25 +269,56 @@ public class VamsasAppDatastore
           sq.setVamsasId(sequence.getVorbaId().getId());
           sequence.setSequence(sq.getSequenceAsString());
           sequence.setDictionary(dict);
-          sequence.setName(jal.getDataset().getSequenceAt(i).getName());
-          sequence.setStart(jal.getDataset().getSequenceAt(i).getStart());
-          sequence.setEnd(jal.getDataset().getSequenceAt(i).getEnd());
-          sequence.setDescription(jal.getDataset().getSequenceAt(i)
-                  .getDescription());
+          sequence.setName(sq.getName());
+          sequence.setStart(sq.getStart());
+          sequence.setEnd(sq.getEnd());
+          sequence.setDescription(sq.getDescription());
           dataset.addSequence(sequence);
+          dssmods.addElement(dssmods);
         }
         else
         {
-          // verify principal attributes. and update any new
-          // features/references.
-          System.out.println("update dataset sequence object.");
+          boolean dsmod = false;
+          // verify and update principal attributes.
+          if (sq.getDescription()!=null && (sequence.getDescription()==null || !sequence.getDescription().equals(sq.getDescription())))
+          {
+            sequence.setDescription(sq.getDescription());
+            dsmod = true;
+          }
+          if (sequence.getSequence()==null || !sequence.getSequence().equals(sq.getSequenceAsString()))
+          {
+            if (sequence.getStart()!=sq.getStart() || sequence.getEnd()!=sq.getEnd())
+            {
+              // update modified sequence.
+              sequence.setSequence(sq.getSequenceAsString());
+              sequence.setStart(sq.getStart());
+              sequence.setEnd(sq.getEnd());
+              dsmod = true;
+            }
+          }
+          if (!dict.equals(sequence.getDictionary()))
+          { 
+            sequence.setDictionary(dict);
+            dsmod = true;
+          }
+          if (!sequence.getName().equals(sq.getName()))
+          {
+            sequence.setName(sq.getName());
+            dsmod = true;
+          }
+          if (dsmod)
+          {
+            dssmods.addElement(sequence);
+          }
         }
+        // add or update any new features/references on dataset sequence
         if (sq.getSequenceFeatures() != null)
         {
           int sfSize = sq.getSequenceFeatures().length;
 
           for (int sf = 0; sf < sfSize; sf++)
           {
+            // TODO: update/modifiable synchronizer 
             jalview.datamodel.SequenceFeature feature = (jalview.datamodel.SequenceFeature) sq
                     .getSequenceFeatures()[sf];
 
@@ -323,11 +358,19 @@ public class VamsasAppDatastore
 
         }
       }
+      if (dssmods.size()>0)
+      {
+        if (!nw)
+        {
+          Entry pentry = this.addProvenance(dataset.getProvenance(), "updated sequences");
+          // pentry.addInput(vInput); could write in which sequences were modified.
+          dssmods.removeAllElements();
+        }
+      }
       // dataset.setProvenance(getVamsasProvenance(jal.getDataset().getProvenance()));
       // ////////////////////////////////////////////
       if (!av.getAlignment().isAligned())
         return; // TODO: trees could be written - but for the moment we just skip
-      
       // ////////////////////////////////////////////
       // Save the Alignments
 
@@ -354,33 +397,36 @@ public class VamsasAppDatastore
           alignment.addProperty(title);
         }
         alignment.setGapChar(String.valueOf(av.getGapCharacter()));
-        AlignmentSequence alseq = null;
         for (int i = 0; i < jal.getHeight(); i++)
         {
-          alseq = new AlignmentSequence();
-          // TODO: VAMSAS: translate lowercase symbols to annotation ?
-          alseq.setSequence(jal.getSequenceAt(i).getSequenceAsString());
-          alseq.setName(jal.getSequenceAt(i).getName());
-          alseq.setStart(jal.getSequenceAt(i).getStart());
-          alseq.setEnd(jal.getSequenceAt(i).getEnd());
-          if (getjv2vObj(jal.getSequenceAt(i).getDatasetSequence()) == null)
-          {
-            Cache.log
-                    .warn("Serious. Unbound dataset sequence in alignment: "
-                            + jal.getSequenceAt(i).getDatasetSequence());
-          }
-          alseq.setRefid(getjv2vObj(jal.getSequenceAt(i)
-                  .getDatasetSequence()));
-          alignment.addAlignmentSequence(alseq);
-          bindjvvobj(jal.getSequenceAt(i), alseq);
+          syncToAlignmentSequence(jal.getSequenceAt(i), alignment);
         }
+        alignRDHash.put(av.getSequenceSetId(),av.getUndoRedoHash());
       }
       else
       {
+        boolean alismod = av.isUndoRedoHashModified((long[]) alignRDHash.get(av.getSequenceSetId()));
         // todo: verify and update mutable alignment props.
-        if (alignment.getModifiable() == null) // TODO: USE VAMSAS LIBRARY
-                                                // OBJECT LOCK METHODS
+        // TODO: Use isLocked methods
+        if (alignment.getModifiable() == null || alignment.getModifiable().length()==0)
         {
+          boolean modified = false;
+          for (int i = 0; i < jal.getHeight(); i++)
+          {
+            modified |= syncToAlignmentSequence(jal.getSequenceAt(i), alignment);
+          }
+          if (modified)
+          {
+            if (alismod)
+            {
+              // info in the undo
+              addProvenance(alignment.getProvenance(), "Edited"); // TODO: insert something sensible here again 
+                      }
+            else {
+              // info in the undo
+              addProvenance(alignment.getProvenance(), "Attributes Edited"); // TODO: insert something sensible here again 
+            }
+          }
           System.out.println("update alignment in document.");
         }
         else
@@ -617,6 +663,147 @@ public class VamsasAppDatastore
     }
 
   }
+  /**
+   *  sync a jalview alignment seuqence into a vamsas alignment
+   *  assumes all lock transformation/bindings have been sorted out before hand.
+   *  creates/syncs the vamsas alignment sequence for jvalsq and adds it to the alignment if necessary.
+   */
+  private boolean syncToAlignmentSequence(SequenceI jvalsq,
+          Alignment alignment)
+  {
+    boolean modal = false;
+    // todo: islocked method here
+    boolean up2doc=false;
+    AlignmentSequence alseq = (AlignmentSequence) getjv2vObj(jvalsq);
+    if (alseq==null)
+    {
+      alseq = new AlignmentSequence();
+      up2doc = true;
+    }
+    // boolean locked = (alignment.getModifiable()==null || alignment.getModifiable().length()>0);
+    // TODO: VAMSAS: translate lowercase symbols to annotation ?
+    if (up2doc || !alseq.getSequence().equals(jvalsq.getSequenceAsString()))
+    {
+      alseq.setSequence(jvalsq.getSequenceAsString());
+      alseq.setStart(jvalsq.getStart());
+      alseq.setEnd(jvalsq.getEnd());
+      modal = true;
+    }
+    if (up2doc || !alseq.getName().equals(jvalsq.getName()))
+    {
+      modal = true;
+      alseq.setName(jvalsq.getName());
+    }
+    if (jvalsq.getDescription()!=null && (alseq.getDescription()==null || !jvalsq.getDescription().equals(alseq.getDescription())))
+    {
+      modal = true;
+      alseq.setDescription(jvalsq.getDescription());
+    }
+    if (getjv2vObj(jvalsq.getDatasetSequence()) == null)
+    {
+      Cache.log
+      .warn("Serious Implementation error - Unbound dataset sequence in alignment: "
+              + jvalsq.getDatasetSequence());
+    }
+    alseq.setRefid(getjv2vObj(jvalsq
+            .getDatasetSequence()));
+    if (up2doc)
+    {
+      
+      alignment.addAlignmentSequence(alseq);
+      bindjvvobj(jvalsq, alseq);
+    }
+    return up2doc || modal;
+  }
+  /**
+   *  locally sync a jalview alignment seuqence from a vamsas alignment
+   *  assumes all lock transformation/bindings have been sorted out before hand.
+   *  creates/syncs the jvalsq from the alignment sequence
+   */
+  private boolean syncFromAlignmentSequence(AlignmentSequence valseq, char valGapchar, char gapChar, Vector dsseqs)
+          
+  {
+    boolean modal = false;
+    // todo: islocked method here
+    boolean upFromdoc=false;
+    jalview.datamodel.SequenceI alseq = (SequenceI) getvObj2jv(valseq);
+    if (alseq==null)
+    {
+      upFromdoc = true;
+    }
+    if (alseq != null)
+    {
+
+      // boolean locked = (alignment.getModifiable()==null || alignment.getModifiable().length()>0);
+      // TODO: VAMSAS: translate lowercase symbols to annotation ?
+      if (upFromdoc || !valseq.getSequence().equals(alseq.getSequenceAsString()))
+      {
+        // this might go *horribly* wrong
+        alseq.setSequence(new String(valseq.getSequence()).replace(
+                valGapchar, gapChar));
+        alseq.setStart((int) valseq.getStart());
+        alseq.setEnd((int) valseq.getEnd());
+        modal = true;
+      }
+      if (!valseq.getName().equals(alseq.getName()))
+      {
+        modal = true;
+        alseq.setName(valseq.getName());
+      }
+      if (alseq.getDescription()==null 
+              || (valseq.getDescription()==null 
+                      || alseq.getDescription().equals(valseq.getDescription())))
+      {
+        alseq.setDescription(valseq.getDescription());
+        modal = true;
+      }
+      if (modal && Cache.log.isDebugEnabled())
+      {
+        Cache.log.debug("Updating apparently edited sequence "
+                + alseq.getName());
+      }
+    }
+    else
+    {
+      alseq = new jalview.datamodel.Sequence(valseq.getName(),
+              valseq.getSequence().replace(valGapchar, gapChar),
+              (int) valseq.getStart(), (int) valseq.getEnd());
+
+      Vobject datsetseq = (Vobject) valseq.getRefid();
+      if (datsetseq != null)
+      {
+        alseq
+                .setDatasetSequence((SequenceI) getvObj2jv(datsetseq)); // exceptions
+                                                                        // if
+                                                                        // AlignemntSequence
+                                                                        // reference
+                                                                        // isn't
+                                                                        // a
+                                                                        // simple
+                                                                        // SequenceI
+      }
+      else
+      {
+        Cache.log
+                .error("Invalid dataset sequence id (null) for alignment sequence "
+                        + valseq.getVorbaId());
+      }
+      bindjvvobj(alseq, valseq);
+      alseq.setVamsasId(valseq.getVorbaId().getId());
+      dsseqs.add(alseq);
+    }
+    Vobject datsetseq = (Vobject) valseq.getRefid();
+    if (datsetseq != null)
+    {
+      if (datsetseq != alseq.getDatasetSequence())
+      {
+        modal = true;
+      }
+      alseq
+              .setDatasetSequence((SequenceI) getvObj2jv(datsetseq)); // exceptions
+    }
+    return upFromdoc || modal;
+  }
 
   private void initRangeAnnotationType(RangeAnnotation an,
           AlignmentAnnotation alan, int[] gapMap)
@@ -1116,6 +1303,7 @@ public class VamsasAppDatastore
             }
             iSize = alignment.getAlignmentSequenceCount();
             boolean newal = (jal == null) ? true : false;
+            boolean refreshal = false;
             Vector newasAnnots = new Vector();
             char gapChar = ' '; // default for new alignments read in from the
                                 // document
@@ -1132,51 +1320,13 @@ public class VamsasAppDatastore
             for (i = 0; i < iSize; i++)
             {
               AlignmentSequence valseq = alignment.getAlignmentSequence(i);
-              jalview.datamodel.SequenceI alseq = (SequenceI) getvObj2jv(valseq);
-              if (alseq != null)
+              jalview.datamodel.Sequence alseq = (jalview.datamodel.Sequence) getvObj2jv(valseq);
+              if (syncFromAlignmentSequence(valseq, valGapchar, gapChar, dsseqs) && alseq!=null)
               {
-                // TODO: upperCase/LowerCase situation here ? do we allow it ?
-                // if (!alseq.getSequence().equals(valseq.getSequence())) {
-                // throw new Error("Broken! - mismatch of dataset sequence and
-                // jalview internal dataset sequence.");
-                if (Cache.log.isDebugEnabled())
-                {
-                  Cache.log.debug("Updating apparently edited sequence "
-                          + alseq.getName());
-                }
-                // this might go *horribly* wrong
-                alseq.setSequence(new String(valseq.getSequence()).replace(
-                        valGapchar, gapChar));
+                
+                // updated to sequence from the document
                 jremain--;
-              }
-              else
-              {
-                alseq = new jalview.datamodel.Sequence(valseq.getName(),
-                        valseq.getSequence().replace(valGapchar, gapChar),
-                        (int) valseq.getStart(), (int) valseq.getEnd());
-
-                Vobject datsetseq = (Vobject) valseq.getRefid();
-                if (datsetseq != null)
-                {
-                  alseq
-                          .setDatasetSequence((SequenceI) getvObj2jv(datsetseq)); // exceptions
-                                                                                  // if
-                                                                                  // AlignemntSequence
-                                                                                  // reference
-                                                                                  // isn't
-                                                                                  // a
-                                                                                  // simple
-                                                                                  // SequenceI
-                }
-                else
-                {
-                  Cache.log
-                          .error("Invalid dataset sequence id (null) for alignment sequence "
-                                  + valseq.getVorbaId());
-                }
-                bindjvvobj(alseq, valseq);
-                alseq.setVamsasId(valseq.getVorbaId().getId());
-                dsseqs.add(alseq);
+                refreshal = true;
               }
               if (valseq.getAlignmentSequenceAnnotationCount() > 0)
               {
@@ -1344,6 +1494,10 @@ public class VamsasAppDatastore
               // TODO: fix this so we retrieve the alignFrame handing av
               // *directly*
               alignFrame = getAlignFrameFor(av);
+              if (refreshal)
+              {
+                av.alignmentChanged(alignFrame.alignPanel);
+              }
             }
             // LOAD TREES
             // /////////////////////////////////////
@@ -2116,9 +2270,11 @@ public class VamsasAppDatastore
     return prov;
   }
 
-  void addProvenance(Provenance p, String action)
+  Entry addProvenance(Provenance p, String action)
   {
-    p.addEntry(dummyPEntry(action));
+    Entry dentry = dummyPEntry(action);
+    p.addEntry(dentry);
+    return dentry;
   }
 
   public Entry getProvEntry()