JAL-1136 JAL-811 JAL-812 store/recover autocalc alignment annotation based on calcId...
[jalview.git] / src / jalview / gui / Jalview2XML.java
index 14650a9..7fb7f0b 100644 (file)
@@ -38,6 +38,13 @@ import jalview.schemabinding.version2.*;
 import jalview.schemes.*;
 import jalview.util.Platform;
 import jalview.util.jarInputStreamProvider;
+import jalview.ws.jws2.AAConsClient;
+import jalview.ws.jws2.Jws2Discoverer;
+import jalview.ws.jws2.dm.AAConsSettings;
+import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.AutoCalcSetting;
+import jalview.ws.params.WsParamSetI;
 
 /**
  * Write out the current jalview desktop state as a Jalview XML stream.
@@ -457,6 +464,7 @@ public class Jalview2XML
     }
 
     JSeq jseq;
+    Set<String> calcIdSet=new HashSet<String>();
 
     // SAVE SEQUENCES
     String id = "";
@@ -790,7 +798,6 @@ public class Jalview2XML
         }
       }
     }
-
     // SAVE ANNOTATIONS
     /**
      * store forward refs from an annotationRow to any groups
@@ -876,6 +883,7 @@ public class Jalview2XML
 
         if (aa[i].getCalcId()!=null)
         {
+          calcIdSet.add(aa[i].getCalcId());
           an.setCalcId(aa[i].getCalcId());
         }
 
@@ -1162,11 +1170,11 @@ public class Jalview2XML
       }
 
       // Make sure we save none displayed feature settings
-      Enumeration en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureColours
-              .keys();
-      while (en.hasMoreElements())
+      Iterator en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureColours
+              .keySet().iterator();
+      while (en.hasNext())
       {
-        String key = en.nextElement().toString();
+        String key = en.next().toString();
         if (settingsAdded.contains(key))
         {
           continue;
@@ -1187,11 +1195,11 @@ public class Jalview2XML
         fs.addSetting(setting);
         settingsAdded.addElement(key);
       }
-      en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureGroups.keys();
+      en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureGroups.keySet().iterator();
       Vector groupsAdded = new Vector();
-      while (en.hasMoreElements())
+      while (en.hasNext())
       {
-        String grp = en.nextElement().toString();
+        String grp = en.next().toString();
         if (groupsAdded.contains(grp))
         {
           continue;
@@ -1228,6 +1236,15 @@ public class Jalview2XML
         }
       }
     }
+    if (calcIdSet.size()>0)
+    {
+      for (String calcId:calcIdSet)
+      {
+        if (calcId.trim().length()>0) {
+          view.addCalcIdParam(createCalcIdParam(calcId, av));
+        }
+      }
+    }
 
     jms.addViewport(view);
 
@@ -1259,6 +1276,84 @@ public class Jalview2XML
     return object;
   }
 
+  private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
+  {
+    AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
+    if (settings != null)
+    {
+      CalcIdParam vCalcIdParam = new CalcIdParam();
+      vCalcIdParam.setCalcId(calcId);
+      vCalcIdParam.addServiceURL(settings.getServiceURI());
+      // generic URI allowing a third party to resolve another instance of the
+      // service used for this calculation
+      for (String urls:settings.getServiceURLs())
+      {
+        vCalcIdParam.addServiceURL(urls);
+      }
+      vCalcIdParam.setVersion("1.0");
+      if (settings.getPreset() != null)
+      {
+        WsParamSetI setting = settings.getPreset();
+        vCalcIdParam.setName(setting.getName());
+        vCalcIdParam.setDescription(setting.getDescription());
+      }
+      else
+      {
+        vCalcIdParam.setName("");
+        vCalcIdParam.setDescription("Last used parameters");
+      }
+      // need to be able to recover 1) settings 2) user-defined presets or
+      // recreate settings from preset 3) predefined settings provided by
+      // service - or settings that can be transferred (or discarded)
+      vCalcIdParam.setParameters(settings
+              .getWsParamFile().replace("\n", "|\\n|"));
+      vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
+      // todo - decide if updateImmediately is needed for any projects.
+
+      return vCalcIdParam;
+    }
+    return null;
+  }
+
+  private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
+          AlignViewport av)
+  {
+    if (calcIdParam.getVersion().equals("1.0"))
+    {
+      Jws2Instance service=Jws2Discoverer.getDiscoverer().getPreferredServiceFor(calcIdParam.getServiceURL());
+      if (service!=null)
+      {
+        WsParamSetI parmSet=null;
+        try {
+          parmSet = service.getParamStore().parseServiceParameterFile(calcIdParam.getName(), calcIdParam.getDescription(), calcIdParam.getServiceURL(), calcIdParam.getParameters().replace("|\\n|", "\n"));
+        } catch (IOException x)
+        {
+          warn("Couldn't parse parameter data for "+calcIdParam.getCalcId(), x);
+          return false;
+        }
+        List<ArgumentI> argList=null;
+        if (calcIdParam.getName().length()>0) {
+          parmSet = service.getParamStore().getPreset(calcIdParam.getName());
+          if (parmSet!=null)
+          {
+            // TODO : check we have a good match with settings in AACons - otherwise we'll need to create a new preset
+          }
+        }
+        else {
+          argList = parmSet.getArguments();
+          parmSet=null;
+        }
+        AAConsSettings settings = new AAConsSettings(calcIdParam.isAutoUpdate(), service, parmSet, argList);
+        av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings, calcIdParam.isNeedsUpdate());
+        return true;
+      } else {
+        warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
+        return false;
+      }
+    }
+    throw new Error("Unsupported Version for calcIdparam "
+            + calcIdParam.toString());
+  }
   /**
    * External mapping between jalview objects and objects yielding a valid and
    * unique object ID string. This is null for normal Jalview project IO, but
@@ -3272,7 +3367,16 @@ public class Jalview2XML
                 );
       }
     }
-
+    if (view.getCalcIdParam()!=null)
+    {
+      for (CalcIdParam calcIdParam:view.getCalcIdParam())
+      {
+        if (recoverCalcIdParam(calcIdParam, af.viewport)) {
+        } else {
+          warn("Couldn't recover parameters for "+calcIdParam.getCalcId());
+        }
+      }
+    }
     af.setMenusFromViewport(af.viewport);
     // TODO: we don't need to do this if the viewport is aready visible.
     Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
@@ -3302,10 +3406,13 @@ public class Jalview2XML
       }
       for (JvAnnotRow auan : autoAlan)
       {
-        visan.put(auan.template.label, auan);
+        visan.put(auan.template.label+(auan.template.getCalcId()==null ? "" : "\t"+auan.template.getCalcId()), auan);
       }
       int hSize = al.getAlignmentAnnotation().length;
       ArrayList<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
+      // work through any autoCalculated annotation already on the view
+      // removing it if it should be placed in a different location on the
+      // annotation panel.
       for (int h = 0; h < hSize; h++)
       {
         jalview.datamodel.AlignmentAnnotation jalan = al
@@ -3313,10 +3420,15 @@ public class Jalview2XML
         if (jalan.autoCalculated)
         {
           JvAnnotRow valan = visan.get(jalan.label);
+          if (jalan.getCalcId()!=null)
+          {
+            valan = visan.get(jalan.label+ "\t"+jalan.getCalcId());
+          }
+          
           if (valan != null)
           {
             // delete the auto calculated row from the alignment
-            al.deleteAnnotation(al.getAlignmentAnnotation()[h], false);
+            al.deleteAnnotation(jalan, false);
             hSize--;
             h--;
             if (valan != nullAnnot)