Merge branch 'tasks/JAL-3070_wsinterfaces' into alpha/JAL-3362_Jalview_212_alpha
authorJim Procter <jprocter@issues.jalview.org>
Wed, 10 Jul 2019 14:53:07 +0000 (15:53 +0100)
committerJim Procter <jprocter@issues.jalview.org>
Wed, 10 Jul 2019 15:10:55 +0000 (16:10 +0100)
50 files changed:
doc/addingWebClient.md [new file with mode: 0644]
src/jalview/gui/AlignFrame.java
src/jalview/gui/WsJobParameters.java
src/jalview/ws/AWsJob.java
src/jalview/ws/WSClient.java
src/jalview/ws/api/CancellableI.java [new file with mode: 0644]
src/jalview/ws/api/DistanceMatrixResultI.java [new file with mode: 0644]
src/jalview/ws/api/JalviewServiceEndpointProviderI.java [new file with mode: 0644]
src/jalview/ws/api/JalviewWebServiceI.java [new file with mode: 0644]
src/jalview/ws/api/JobId.java [new file with mode: 0644]
src/jalview/ws/api/MsaI.java [new file with mode: 0644]
src/jalview/ws/api/MsaResultI.java [new file with mode: 0644]
src/jalview/ws/api/MsaWithGuideTreeI.java [new file with mode: 0644]
src/jalview/ws/api/MultipleSequenceAlignmentI.java [new file with mode: 0644]
src/jalview/ws/api/ServiceWithParameters.java [new file with mode: 0644]
src/jalview/ws/api/TreeResultI.java [new file with mode: 0644]
src/jalview/ws/api/UIinfo.java [new file with mode: 0644]
src/jalview/ws/gui/MsaWSJob.java [new file with mode: 0644]
src/jalview/ws/gui/MsaWSThread.java [moved from src/jalview/ws/jws2/MsaWSThread.java with 53% similarity]
src/jalview/ws/gui/WsJob.java [new file with mode: 0644]
src/jalview/ws/jws1/MsaWSClient.java
src/jalview/ws/jws1/MsaWSThread.java
src/jalview/ws/jws1/SeqSearchWSClient.java
src/jalview/ws/jws1/SeqSearchWSThread.java
src/jalview/ws/jws2/AAConClient.java
src/jalview/ws/jws2/AADisorderClient.java
src/jalview/ws/jws2/AbstractJabaCalcWorker.java
src/jalview/ws/jws2/JabaParamStore.java
src/jalview/ws/jws2/JabaPreset.java
src/jalview/ws/jws2/JabaWsParamTest.java [new file with mode: 0644]
src/jalview/ws/jws2/JabawsCalcWorker.java
src/jalview/ws/jws2/JabawsMsaInterfaceAlignCalcWorker.java
src/jalview/ws/jws2/Jws2Client.java
src/jalview/ws/jws2/Jws2Discoverer.java
src/jalview/ws/jws2/MsaWSClient.java
src/jalview/ws/jws2/RNAalifoldClient.java
src/jalview/ws/jws2/SequenceAnnotationWSClient.java
src/jalview/ws/jws2/dm/AAConSettings.java
src/jalview/ws/jws2/jabaws2/JabawsMsaInstance.java [new file with mode: 0644]
src/jalview/ws/jws2/jabaws2/Jws2Instance.java
src/jalview/ws/rest/RestClient.java
src/jalview/ws/rest/RestJobThread.java
src/jalview/ws/rest/RestServiceDescription.java
test/jalview/gui/PopupMenuTest.java
test/jalview/util/FileUtilsTest.java
test/jalview/ws/gui/Jws2ParamView.java
test/jalview/ws/jabaws/DisorderAnnotExportImport.java
test/jalview/ws/jabaws/RNAStructExportImport.java
test/jalview/ws/jws2/ParameterUtilsTest.java
test/jalview/ws/rest/ShmmrRSBSService.java

diff --git a/doc/addingWebClient.md b/doc/addingWebClient.md
new file mode 100644 (file)
index 0000000..0d0ee1d
--- /dev/null
@@ -0,0 +1,68 @@
+# How to add a web service backend to Jalview's web services UI
+
+### Document Status: *Work in progress !*
+
+There are two phases to services.
+
+ *Discovery* threads are started by jalview.gui.Desktop (or other UI components or the CLI if they are headless services accessible via commandline). Your service discovery thread registers discovered instances so they can be accessed by the user.
+
+ *Access* most services are accessed by selecting a menu item, option, or specifying a nickname for the service instance as a Jalview command line parameter. Different access patterns are used for the various services: seqeunce data source, sequence feature annotation source, multiple sequence alignment, multiple alignment annotation source, etc. There should be no need for your code to create UI components (if there is then Jalview's UI needs to be refactored to avoid this).
+
+## Discovery
+
+*jalview.gui.Desktop*
+- start a discovery thread to discover services provided by your framework. The discoverer should generate a list of objects that either implement WsMenuEntryProviderI or provide another mechanism to add themselves to Jalview's menus (via jalview.gui.AlignFrame.BuildWebServiceMenu() below)
+
+*jalview.gui.AlignFrame*
+- BuildWebServiceMenu()
+ This method creates a runnable that's called when the available set of web services changes (e.g. when a discovery thread completes). Add code to the Runnable's run method to create Menu Items in the web services menu via jalview.ws.WSMenuEntryProviderI instances generated by your discoverer. 
+
+
+## Types of service
+
+### Services that create new alignments or windows, optionally with a progress log
+
+The pattern for these services requires a Client that initates a thread which creates, and montors one or more jobs based on input data.
+
+jalview.ws.MsaWSClient -- currently does double duty with Jaba services for alignment analysis and instantiation of alignment services.
+
+jalview.ws.gui.MSAThread -- UI model and controller for a running MSA service. Instantiated with an instance of jalview.ws.MultipleSequenceAlignmentI provided by the service endpoint factory.
+
+
+## Other classes of interest
+
+### jalview.ws.api
+
+Interfaces and base classes to be implemented and used by a service endpoint.
+
+ jalview.ws.api.CancellableI.java - implement if the service is cancellable
+ jalview.ws.api.JalviewWebServiceI.java - base service interface
+ jalview.ws.api.JobId.java - a timestamped job id that can be saved in a Jalview project
+
+#### submission interfaces
+jalview.ws.api.MsaI.java
+jalview.ws.api.MsaWithGuideTreeI.java
+
+
+#### result interfaces
+jalview.ws.api.MsaResultI.java
+jalview.ws.api.TreeResultI.java
+jalview.ws.api.DistanceMatrixResultI.java
+
+
+#### minimal composed interfaces for a complete functional analysis 
+
+jalview.ws.api.MultipleSequenceAlignmentI.java
+
+
+#### base class for a service endpoint instance - to be materialised by service discoverers
+
+jalview.ws.api.UIinfo.java - basic information 
+jalview.ws.api.ServiceWithParameters.java
+
+jalview.ws.api.JalviewServiceEndpointProviderI - implemented by service endpoint factories (typically extended from UIinfo or ServiceWithParameters).
+
+
+## Analysis services
+
+These have not yet been refactored. Feel free to look at how jalview.ws.jws2.AACons and Disorder clients operate and adapt the pattern for your own services. The Groovy example in the help [[help/html/groovy/featuresCounter.html]] for creating custom annotation tracks uses the same basic 'alignment analysis worker' mechanism to provide dynamically executed alignment analysis calculations that result in annotation tracks displayed below the alginment.
index 12f04be..ddebe02 100644 (file)
@@ -4401,7 +4401,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                       jws2servs.attachWSMenuEntry(webService, me);
                       for (Jws2Instance sv : jws2servs.getServices())
                       {
-                        if (sv.description.toLowerCase().contains("jpred"))
+                        if (sv.getName().toLowerCase().contains("jpred"))
                         {
                           for (JMenuItem jmi : legacyItems)
                           {
@@ -4421,6 +4421,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                   }
                 }
                 build_urlServiceMenu(me.webService);
+
+                // TODO Mateusz - follow pattern for adding web service
+                // JMenuItems for slivka-based services
+
                 build_fetchdbmenu(webService);
                 for (JMenu item : wsmenu)
                 {
index 8377a16..f7906e5 100644 (file)
@@ -23,10 +23,7 @@ package jalview.gui;
 import jalview.gui.OptsAndParamsPage.OptionBox;
 import jalview.gui.OptsAndParamsPage.ParamBox;
 import jalview.util.MessageManager;
-import jalview.ws.jws2.JabaParamStore;
-import jalview.ws.jws2.JabaPreset;
-import jalview.ws.jws2.Jws2Discoverer;
-import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.api.UIinfo;
 import jalview.ws.params.ArgumentI;
 import jalview.ws.params.OptionI;
 import jalview.ws.params.ParamDatastoreI;
@@ -48,17 +45,13 @@ import java.awt.event.HierarchyBoundsListener;
 import java.awt.event.HierarchyEvent;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
-import java.awt.event.WindowEvent;
-import java.awt.event.WindowListener;
 import java.util.Hashtable;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Vector;
 
 import javax.swing.JButton;
 import javax.swing.JComboBox;
 import javax.swing.JDialog;
-import javax.swing.JFrame;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
@@ -67,11 +60,6 @@ import javax.swing.border.TitledBorder;
 import javax.swing.event.DocumentEvent;
 import javax.swing.event.DocumentListener;
 
-import compbio.metadata.Argument;
-import compbio.metadata.Option;
-import compbio.metadata.Parameter;
-import compbio.metadata.Preset;
-import compbio.metadata.PresetManager;
 import net.miginfocom.swing.MigLayout;
 
 /**
@@ -103,8 +91,10 @@ public class WsJobParameters extends JPanel implements ItemListener,
 
   // URL linkImageURL = getClass().getResource("/images/link.gif");
 
-  /*
-   * controller for options and parameters layout
+  // TODO ABSRACT FROM JABAWS CLASSES
+
+  /**
+   * manager for options and parameters.
    */
   OptsAndParamsPage opanp;
 
@@ -141,7 +131,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
 
   JDialog frame = null;
 
-  Jws2Instance service;
+  UIinfo service;
 
   /*
    * list of service presets in the gui
@@ -180,8 +170,8 @@ public class WsJobParameters extends JPanel implements ItemListener,
    * @param preset
    * @param jobArgset
    */
-  public WsJobParameters(ParamDatastoreI paramStorei, Jws2Instance service,
-          WsParamSetI preset, List<Argument> jobArgset)
+  public WsJobParameters(ParamDatastoreI paramStorei, UIinfo service,
+          WsParamSetI preset, List<ArgumentI> jobArgset)
   {
     super();
 
@@ -504,19 +494,11 @@ public class WsJobParameters extends JPanel implements ItemListener,
     }
   }
 
-  void initForService(WsParamSetI jabap, List<Argument> jabajobArgset)
+  void initForService(WsParamSetI paramSet, List<ArgumentI> jobArgset)
   {
-    WsParamSetI p = null;
-    List<ArgumentI> jobArgset = null;
     settingDialog = true;
-    { // instantiate the abstract proxy for Jaba objects
-      jobArgset = jabajobArgset == null ? null
-              : JabaParamStore.getJwsArgsfromJaba(jabajobArgset);
-      p = jabap; // (jabap != null) ? paramStore.getPreset(jabap.getName()) :
-                 // null;
-    }
 
-    init(p, jobArgset);
+    init(paramSet, jobArgset);
 
   }
 
@@ -925,243 +907,6 @@ public class WsJobParameters extends JPanel implements ItemListener,
     revalidate();
   }
 
-  /**
-   * testing method - grab a service and parameter set and show the window
-   * 
-   * @param args
-   */
-  public static void main(String[] args)
-  {
-    jalview.ws.jws2.Jws2Discoverer disc = jalview.ws.jws2.Jws2Discoverer
-            .getDiscoverer();
-    int p = 0;
-    if (args.length > 0)
-    {
-      Vector<String> services = new Vector<>();
-      services.addElement(args[p++]);
-      Jws2Discoverer.getDiscoverer().setServiceUrls(services);
-    }
-    try
-    {
-      disc.run();
-    } catch (Exception e)
-    {
-      System.err.println("Aborting. Problem discovering services.");
-      e.printStackTrace();
-      return;
-    }
-    Jws2Instance lastserv = null;
-    for (Jws2Instance service : disc.getServices())
-    {
-      lastserv = service;
-      if (p >= args.length || service.serviceType.equalsIgnoreCase(args[p]))
-      {
-        if (lastserv != null)
-        {
-          List<Preset> prl = null;
-          Preset pr = null;
-          if (++p < args.length)
-          {
-            PresetManager prman = lastserv.getPresets();
-            if (prman != null)
-            {
-              pr = prman.getPresetByName(args[p]);
-              if (pr == null)
-              {
-                // just grab the last preset.
-                prl = prman.getPresets();
-              }
-            }
-          }
-          else
-          {
-            PresetManager prman = lastserv.getPresets();
-            if (prman != null)
-            {
-              prl = prman.getPresets();
-            }
-          }
-          Iterator<Preset> en = (prl == null) ? null : prl.iterator();
-          while (en != null && en.hasNext())
-          {
-            if (en != null)
-            {
-              if (!en.hasNext())
-              {
-                en = prl.iterator();
-              }
-              pr = en.next();
-            }
-            {
-              System.out.println("Testing opts dupes for "
-                      + lastserv.getUri() + " : " + lastserv.getActionText()
-                      + ":" + pr.getName());
-              List<Option> rg = lastserv.getRunnerConfig().getOptions();
-              for (Option o : rg)
-              {
-                try
-                {
-                  Option cpy = jalview.ws.jws2.ParameterUtils.copyOption(o);
-                } catch (Exception e)
-                {
-                  System.err.println("Failed to copy " + o.getName());
-                  e.printStackTrace();
-                } catch (Error e)
-                {
-                  System.err.println("Failed to copy " + o.getName());
-                  e.printStackTrace();
-                }
-              }
-            }
-            {
-              System.out.println("Testing param dupes:");
-              List<Parameter> rg = lastserv.getRunnerConfig()
-                      .getParameters();
-              for (Parameter o : rg)
-              {
-                try
-                {
-                  Parameter cpy = jalview.ws.jws2.ParameterUtils
-                          .copyParameter(o);
-                } catch (Exception e)
-                {
-                  System.err.println("Failed to copy " + o.getName());
-                  e.printStackTrace();
-                } catch (Error e)
-                {
-                  System.err.println("Failed to copy " + o.getName());
-                  e.printStackTrace();
-                }
-              }
-            }
-            {
-              System.out.println("Testing param write:");
-              List<String> writeparam = null, readparam = null;
-              try
-              {
-                writeparam = jalview.ws.jws2.ParameterUtils
-                        .writeParameterSet(
-                                pr.getArguments(lastserv.getRunnerConfig()),
-                                " ");
-                System.out.println("Testing param read :");
-                List<Option> pset = jalview.ws.jws2.ParameterUtils
-                        .processParameters(writeparam,
-                                lastserv.getRunnerConfig(), " ");
-                readparam = jalview.ws.jws2.ParameterUtils
-                        .writeParameterSet(pset, " ");
-                Iterator<String> o = pr.getOptions().iterator(),
-                        s = writeparam.iterator(), t = readparam.iterator();
-                boolean failed = false;
-                while (s.hasNext() && t.hasNext())
-                {
-                  String on = o.next(), sn = s.next(), st = t.next();
-                  if (!sn.equals(st))
-                  {
-                    System.out.println(
-                            "Original was " + on + " Phase 1 wrote " + sn
-                                    + "\tPhase 2 wrote " + st);
-                    failed = true;
-                  }
-                }
-                if (failed)
-                {
-                  System.out.println(
-                          "Original parameters:\n" + pr.getOptions());
-                  System.out.println(
-                          "Wrote parameters in first set:\n" + writeparam);
-                  System.out.println(
-                          "Wrote parameters in second set:\n" + readparam);
-
-                }
-              } catch (Exception e)
-              {
-                e.printStackTrace();
-              }
-            }
-            WsJobParameters pgui = new WsJobParameters(null, lastserv,
-                    new JabaPreset(lastserv, pr), null);
-            JFrame jf = new JFrame(MessageManager
-                    .formatMessage("label.ws_parameters_for", new String[]
-                    { lastserv.getActionText() }));
-            JPanel cont = new JPanel(new BorderLayout());
-            pgui.validate();
-            cont.setPreferredSize(pgui.getPreferredSize());
-            cont.add(pgui, BorderLayout.CENTER);
-            jf.setLayout(new BorderLayout());
-            jf.add(cont, BorderLayout.CENTER);
-            jf.validate();
-            final Thread thr = Thread.currentThread();
-            jf.addWindowListener(new WindowListener()
-            {
-
-              @Override
-              public void windowActivated(WindowEvent e)
-              {
-                // TODO Auto-generated method stub
-
-              }
-
-              @Override
-              public void windowClosed(WindowEvent e)
-              {
-              }
-
-              @Override
-              public void windowClosing(WindowEvent e)
-              {
-                thr.interrupt();
-
-              }
-
-              @Override
-              public void windowDeactivated(WindowEvent e)
-              {
-                // TODO Auto-generated method stub
-
-              }
-
-              @Override
-              public void windowDeiconified(WindowEvent e)
-              {
-                // TODO Auto-generated method stub
-
-              }
-
-              @Override
-              public void windowIconified(WindowEvent e)
-              {
-                // TODO Auto-generated method stub
-
-              }
-
-              @Override
-              public void windowOpened(WindowEvent e)
-              {
-                // TODO Auto-generated method stub
-
-              }
-
-            });
-            jf.setVisible(true);
-            boolean inter = false;
-            while (!inter)
-            {
-              try
-              {
-                Thread.sleep(10000);
-              } catch (Exception e)
-              {
-                inter = true;
-              }
-              ;
-            }
-            jf.dispose();
-          }
-        }
-      }
-    }
-  }
-
   public boolean isServiceDefaults()
   {
     return (!isModified()
@@ -1294,6 +1039,10 @@ public class WsJobParameters extends JPanel implements ItemListener,
    */
   protected void updateWebServiceMenus()
   {
+    if (Desktop.instance == null)
+    {
+      return;
+    }
     for (AlignFrame alignFrame : Desktop.getAlignFrames())
     {
       alignFrame.BuildWebServiceMenu();
@@ -1366,12 +1115,6 @@ public class WsJobParameters extends JPanel implements ItemListener,
 
   }
 
-  private void _renameExistingPreset(String oldName, String curSetName2)
-  {
-    paramStore.updatePreset(oldName, curSetName2, setDescr.getText(),
-            getJobParams());
-  }
-
   /**
    * store current settings as given name. You should then reset gui.
    * 
index f5f9377..4a9cb74 100644 (file)
  */
 package jalview.ws;
 
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.WsParamSetI;
+
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
 /**
  * Generic properties for an individual job within a Web Service Client thread.
  * Derived from jalview web services version 1 statuses, and revised for Jws2.
@@ -145,6 +152,12 @@ public abstract class AWsJob
    */
   protected boolean subjobComplete = false;
 
+  protected WsParamSetI preset = null;
+
+  protected List<ArgumentI> arguments = null;
+
+  protected Hashtable<String, Map> SeqNames = new Hashtable();
+
   public AWsJob()
   {
   }
@@ -227,4 +240,47 @@ public abstract class AWsJob
     String state = "";
     return state;
   }
+
+  public void setPreset(WsParamSetI jobpreset)
+  {
+    preset = jobpreset;
+  }
+
+  public void setArguments(List<ArgumentI> paramset)
+  {
+    arguments = paramset;
+
+  }
+
+  public boolean isPresetJob()
+  {
+    return preset!=null && arguments==null; 
+  }
+
+  public List<ArgumentI> getArguments()
+  {
+    return arguments;
+  }
+
+  public WsParamSetI getPreset()
+  {
+    return preset;
+  }
+
+  long nextChunk = 0;
+
+  /**
+   * update the record of the last position in the log file read for this job
+   * 
+   * @param nextChunk
+   */
+  public void setnextChunk(long nextChunk)
+  {
+    this.nextChunk = nextChunk;
+  }
+
+  public long getNextChunk()
+  {
+    return nextChunk;
+  }
 }
index 0f5cee8..33aea90 100755 (executable)
  */
 package jalview.ws;
 
+import jalview.gui.AlignFrame;
+import jalview.gui.Desktop;
 import jalview.gui.WebserviceInfo;
+import jalview.gui.WsJobParameters;
+import jalview.util.MessageManager;
+import jalview.ws.api.ServiceWithParameters;
+import jalview.ws.api.UIinfo;
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.ParamDatastoreI;
+import jalview.ws.params.WsParamSetI;
+
+import java.util.List;
 
 public abstract class WSClient // implements WSMenuEntryProviderI
 {
@@ -56,6 +67,11 @@ public abstract class WSClient // implements WSMenuEntryProviderI
   protected WebserviceInfo wsInfo;
 
   /**
+   * the root object for the service client
+   */
+  protected UIinfo serviceHandle;
+
+  /**
    * total number of jobs managed by this web service client instance.
    */
   int jobsRunning = 0;
@@ -65,13 +81,119 @@ public abstract class WSClient // implements WSMenuEntryProviderI
    * mappings between abstract interface names and menu entries
    */
   protected java.util.Hashtable ServiceActions;
+
+  /**
+   * alignFrame associated with this client
+   */
+  protected AlignFrame alignFrame;
   {
     ServiceActions = new java.util.Hashtable();
     ServiceActions.put("MsaWS", "Multiple Sequence Alignment");
     ServiceActions.put("SecStrPred", "Secondary Structure Prediction");
   };
 
+  /**
+   * The preset for the job executed by this client (may be null)
+   */
+  protected WsParamSetI preset;
+
+  /**
+   * The parameters for the job executed by this client (may be null)
+   */
+  protected List<ArgumentI> paramset;
+
   public WSClient()
   {
   }
+
+  /**
+   * base constructor for a web service with parameters. Extending classes
+   * should implement this constructor with additional logic to verify that
+   * preset and arguments are compatible with the service being configured.
+   * 
+   * @param _alignFrame
+   * @param preset
+   * @param arguments
+   */
+  public WSClient(AlignFrame _alignFrame, WsParamSetI preset,
+          List<ArgumentI> arguments)
+  {
+    alignFrame = _alignFrame;
+    this.preset = preset;
+    this.paramset = arguments;
+  }
+
+  protected WebserviceInfo setWebService(UIinfo serv, boolean b)
+  {
+    WebServiceName = serv.getName();
+    WebServiceJobTitle = serv.getActionText();
+    WsURL = serv.getHostURL();
+    if (!b)
+    {
+      return new WebserviceInfo(WebServiceJobTitle,
+              WebServiceJobTitle + " using service hosted at "
+                      + WsURL + "\n"
+                      + (serv.getDescription() != null
+                              ? serv.getDescription()
+                              : ""),
+              false);
+    }
+    return null;
+  }
+
+  /**
+   * called to open a parameter editing dialog for parameterised services
+   * 
+   * @param sh
+   * @param editParams
+   * @return
+   */
+  protected boolean processParams(ServiceWithParameters sh,
+          boolean editParams)
+  {
+    return processParams(sh, editParams, false);
+  }
+
+  protected boolean processParams(ServiceWithParameters sh,
+          boolean editParams,
+          boolean adjustingExisting)
+  {
+
+    if (editParams)
+    {
+      // always do this
+      sh.initParamStore(Desktop.getUserParameterStore());
+
+      WsJobParameters jobParams = (preset == null && paramset != null
+              && paramset.size() > 0)
+                      ? new WsJobParameters((ParamDatastoreI) null, sh,
+                              (WsParamSetI) null, paramset)
+                      : new WsJobParameters((ParamDatastoreI) null, sh,
+                              preset, (List<ArgumentI>) null);
+      if (adjustingExisting)
+      {
+        jobParams.setName(MessageManager
+                .getString("label.adjusting_parameters_for_calculation"));
+      }
+      if (!jobParams.showRunDialog())
+      {
+        return false; // dialog cancelled
+      }
+
+      WsParamSetI prset = jobParams.getPreset();
+      if (prset == null)
+      {
+        paramset = jobParams.isServiceDefaults() ? null
+                : jobParams.getJobParams();
+        this.preset = null;
+      }
+      else
+      {
+        this.preset = prset; // ((JabaPreset) prset).p;
+        paramset = null; // no user supplied parameters.
+      }
+    }
+    return true;
+  }
+
 }
diff --git a/src/jalview/ws/api/CancellableI.java b/src/jalview/ws/api/CancellableI.java
new file mode 100644 (file)
index 0000000..adef2b9
--- /dev/null
@@ -0,0 +1,8 @@
+package jalview.ws.api;
+
+import jalview.ws.gui.WsJob;
+
+public interface CancellableI
+{
+  public boolean cancel(WsJob job);
+}
diff --git a/src/jalview/ws/api/DistanceMatrixResultI.java b/src/jalview/ws/api/DistanceMatrixResultI.java
new file mode 100644 (file)
index 0000000..a40d256
--- /dev/null
@@ -0,0 +1,16 @@
+package jalview.ws.api;
+
+import jalview.math.MatrixI;
+import jalview.ws.params.InvalidArgumentException;
+
+import java.io.IOError;
+import java.rmi.ServerError;
+
+public interface DistanceMatrixResultI
+{
+
+  public MatrixI getDistanceMatrixFor(JobId jobId)
+          throws InvalidArgumentException, ServerError, IOError;
+
+
+}
\ No newline at end of file
diff --git a/src/jalview/ws/api/JalviewServiceEndpointProviderI.java b/src/jalview/ws/api/JalviewServiceEndpointProviderI.java
new file mode 100644 (file)
index 0000000..b9b5109
--- /dev/null
@@ -0,0 +1,13 @@
+package jalview.ws.api;
+
+public interface JalviewServiceEndpointProviderI
+{
+
+  /**
+   * 
+   * @return endpoint instance implementing one or more jalview.ws.api
+   *         interfaces
+   */
+  Object getEndpoint();
+
+}
diff --git a/src/jalview/ws/api/JalviewWebServiceI.java b/src/jalview/ws/api/JalviewWebServiceI.java
new file mode 100644 (file)
index 0000000..ecc8bab
--- /dev/null
@@ -0,0 +1,19 @@
+package jalview.ws.api;
+
+import jalview.gui.WebserviceInfo;
+import jalview.ws.gui.WsJob;
+
+public interface JalviewWebServiceI
+{
+
+  void updateStatus(WsJob job);
+
+  boolean updateJobProgress(WsJob job) throws Exception;
+
+  boolean handleSubmitError(Throwable _lex, WsJob j, WebserviceInfo wsInfo)
+          throws Exception, Error;
+
+  boolean handleCollectionException(Exception e, WsJob msjob,
+          WebserviceInfo wsInfo);
+
+}
diff --git a/src/jalview/ws/api/JobId.java b/src/jalview/ws/api/JobId.java
new file mode 100644 (file)
index 0000000..2a092bd
--- /dev/null
@@ -0,0 +1,59 @@
+package jalview.ws.api;
+
+import java.time.Instant;
+import java.util.Date;
+
+public class JobId
+{
+  // TODO: JobId could include sequenceI anonymisation stuff
+  // TODO: getProgress() -> input stream to log file for job.
+  private String serviceType;
+
+  private String serviceImpl;
+
+  private String jobId;
+
+  private Instant creationTime;
+
+  public JobId(String serviceType, String serviceImpl, String id)
+  {
+    this.serviceType = serviceType;
+    this.serviceImpl = serviceImpl;
+    jobId = id;
+    creationTime = Instant.now();
+  }
+
+  @Override
+  public String toString()
+  {
+    return "" + serviceType + ":" + serviceImpl + ":" + jobId + "\nCreated "
+            + Date.from(creationTime);
+  }
+  /**
+   * a stringified version of the Job Id that can be saved in project.
+   */
+  public String getURI()
+  {
+    return jobId;
+  }
+
+  public String getServiceType()
+  {
+    return serviceType;
+  }
+
+  public String getServiceImpl()
+  {
+    return serviceImpl;
+  }
+
+  public String getJobId()
+  {
+    return jobId;
+  }
+
+  public Instant getCreationTime()
+  {
+    return creationTime;
+  }
+}
diff --git a/src/jalview/ws/api/MsaI.java b/src/jalview/ws/api/MsaI.java
new file mode 100644 (file)
index 0000000..3c426c0
--- /dev/null
@@ -0,0 +1,36 @@
+package jalview.ws.api;
+
+import jalview.datamodel.SequenceI;
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.WsParamSetI;
+
+import java.util.List;
+
+/**
+ * MSA analysis interface
+ * 
+ * @author jprocter
+ * 
+ *         Generic job submission/management model: - A service instance
+ *         implements one or more analysis interfaces, a status interface, a
+ *         progress interface, and one or more results interface, plus any
+ *         informational/descriptional interfaces - analysis interfaces return
+ *         JobId or throw exceptions/errors.
+ * 
+ *
+ */
+public interface MsaI
+{
+  /**
+   * Given a set of sequences
+   * 
+   * @param toalign
+   * @param parameters
+   * @param list
+   * @return JobId or exceptions are thrown.
+   * @throws Throwable
+   */
+  public JobId align(List<SequenceI> toalign, WsParamSetI parameters,
+          List<ArgumentI> list)
+          throws Throwable;
+}
diff --git a/src/jalview/ws/api/MsaResultI.java b/src/jalview/ws/api/MsaResultI.java
new file mode 100644 (file)
index 0000000..38c0a0a
--- /dev/null
@@ -0,0 +1,13 @@
+package jalview.ws.api;
+
+import jalview.datamodel.AlignmentI;
+import jalview.ws.params.InvalidArgumentException;
+
+import java.io.IOError;
+import java.rmi.ServerError;
+
+public interface MsaResultI
+{
+  public AlignmentI getAlignmentFor(JobId jobId)
+          throws InvalidArgumentException, ServerError, IOError;
+}
\ No newline at end of file
diff --git a/src/jalview/ws/api/MsaWithGuideTreeI.java b/src/jalview/ws/api/MsaWithGuideTreeI.java
new file mode 100644 (file)
index 0000000..6c2ff53
--- /dev/null
@@ -0,0 +1,24 @@
+package jalview.ws.api;
+
+import jalview.analysis.NJTree;
+import jalview.datamodel.SequenceI;
+import jalview.ws.params.InvalidArgumentException;
+import jalview.ws.params.WsParamSetI;
+
+import java.io.IOError;
+import java.rmi.ServerError;
+import java.util.List;
+
+public interface MsaWithGuideTreeI
+{
+  /**
+   * Given a set of sequences
+   * 
+   * @param toalign
+   * @param parameters
+   * @return JobId or exceptions are thrown.
+   */
+  public JobId align(List<SequenceI> toalign, NJTree guideTree,
+          WsParamSetI parameters)
+          throws InvalidArgumentException, ServerError, IOError;
+}
\ No newline at end of file
diff --git a/src/jalview/ws/api/MultipleSequenceAlignmentI.java b/src/jalview/ws/api/MultipleSequenceAlignmentI.java
new file mode 100644 (file)
index 0000000..10b8383
--- /dev/null
@@ -0,0 +1,13 @@
+package jalview.ws.api;
+
+/**
+ * A simple parameterisable multiple sequence alignment service
+ * 
+ * @author jprocter
+ *
+ */
+public interface MultipleSequenceAlignmentI
+        extends JalviewWebServiceI, MsaI, MsaResultI
+{
+
+}
diff --git a/src/jalview/ws/api/ServiceWithParameters.java b/src/jalview/ws/api/ServiceWithParameters.java
new file mode 100644 (file)
index 0000000..cf82708
--- /dev/null
@@ -0,0 +1,16 @@
+package jalview.ws.api;
+
+import jalview.ws.params.ParamManager;
+
+public abstract class ServiceWithParameters extends UIinfo
+{
+
+  public ServiceWithParameters(String serviceType, String action,
+          String name, String description, String hosturl)
+  {
+    super(serviceType, action, name, description, hosturl);
+  }
+
+  public abstract void initParamStore(ParamManager userParameterStore);
+
+}
diff --git a/src/jalview/ws/api/TreeResultI.java b/src/jalview/ws/api/TreeResultI.java
new file mode 100644 (file)
index 0000000..1a0c3bd
--- /dev/null
@@ -0,0 +1,14 @@
+package jalview.ws.api;
+
+import jalview.analysis.NJTree;
+import jalview.ws.params.InvalidArgumentException;
+
+import java.io.IOError;
+import java.rmi.ServerError;
+
+public interface TreeResultI
+{
+
+  public NJTree getTreeFor(JobId jobId)
+          throws InvalidArgumentException, ServerError, IOError;
+}
\ No newline at end of file
diff --git a/src/jalview/ws/api/UIinfo.java b/src/jalview/ws/api/UIinfo.java
new file mode 100644 (file)
index 0000000..01fb809
--- /dev/null
@@ -0,0 +1,142 @@
+package jalview.ws.api;
+
+import jalview.ws.params.ParamDatastoreI;
+
+/**
+ * Service UI Info { Action, Specific Name of Service, Brief Description }
+ */
+
+public class UIinfo
+{
+  private String ServiceType;
+
+  public UIinfo(String serviceType, String action, String name,
+          String description, String hosturl)
+  {
+    this.setServiceType(serviceType == null ? "" : serviceType);
+    this.Action = action == null ? "" : action;
+    this.description = description == null ? "" : description;
+    this.Name = name == null ? "" : name;
+    this.hostURL = hosturl;
+  }
+
+  /**
+   * The type of analysis the service performs
+   */
+  public String getServiceType()
+  {
+    return ServiceType;
+  }
+
+  public void setServiceType(String serviceType)
+  {
+    ServiceType = serviceType;
+  }
+
+  /**
+   * The action when the service performs the analysis
+   */
+  public String getAction()
+  {
+    return Action;
+  }
+
+  public void setAction(String action)
+  {
+    Action = action;
+  }
+
+  /**
+   * name shown to user
+   * 
+   * @return
+   */
+  public String getName()
+  {
+    return Name;
+  }
+
+  public void setName(String name)
+  {
+    Name = name;
+  }
+
+  /**
+   * Detailed description (may include references, URLs, html,etc)
+   * 
+   * @return
+   */
+  public String getDescription()
+  {
+    return description;
+  }
+
+  public void setDescription(String description)
+  {
+    this.description = description;
+  }
+
+  @Override
+  public boolean equals(Object object)
+  {
+    if (object == null || !(object instanceof UIinfo))
+    {
+      return false;
+    }
+    UIinfo other = (UIinfo) object;
+
+    return (ServiceType == null && other.getServiceType() == null
+            || ServiceType != null && other.getServiceType() != null
+                    && ServiceType.equals(other.getServiceType()))
+            && (hostURL == null && other.getHostURL() == null
+                    || hostURL != null && other.getHostURL() != null
+                            && hostURL.equals(other.getHostURL()))
+            && (Name == null && other.getName() == null
+                    || Name != null && other.getName() != null
+                            && Name.equals(other.getName()))
+            && (Action == null && other.getAction() == null
+                    || Action != null && other.getAction() != null
+                            && Action.equals(other.getAction()))
+            && (description == null && other.getDescription() == null
+                    || description != null && other.getDescription() != null
+                            && description.equals(other.getDescription()));
+  }
+
+  /**
+   * @return short description of what the service will do
+   */
+  public String getActionText()
+  {
+    return getAction() + " with " + getName();
+  }
+
+  String Action;
+
+  String Name;
+
+  String description;
+
+  String hostURL;
+
+  public String getHostURL()
+  {
+    return hostURL;
+  }
+
+  public ParamDatastoreI getParamStore()
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  /**
+   * 
+   * @return true if the service has parameters (ie is instance of
+   *         jalview.ws.api.ServiceWithParameters)
+   */
+  public boolean hasParameters()
+  {
+    // TODO Auto-generated method stub
+    return false;
+  }
+}
\ No newline at end of file
diff --git a/src/jalview/ws/gui/MsaWSJob.java b/src/jalview/ws/gui/MsaWSJob.java
new file mode 100644 (file)
index 0000000..86d299a
--- /dev/null
@@ -0,0 +1,381 @@
+package jalview.ws.gui;
+
+import jalview.analysis.AlignSeq;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.AlignmentOrder;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+import jalview.util.MessageManager;
+import jalview.ws.api.JobId;
+import jalview.ws.jws2.dm.JabaWsParamSet;
+import jalview.ws.params.ArgumentI;
+
+import java.util.ArrayList;
+import java.util.Vector;
+
+class MsaWSJob extends WsJob
+{
+  /**
+   * holds basic MSA analysis configuration - todo - encapsulate
+   */
+  private final MsaWSThread msaWSThread;
+
+  long lastChunk = 0;
+
+  /**
+   * input
+   */
+  ArrayList<SequenceI> seqs = new ArrayList<>();
+
+  /**
+   * output
+   */
+  AlignmentI alignment;
+
+  // set if the job didn't get run - then the input is simply returned to the
+  // user
+  private boolean returnInput = false;
+
+  /**
+   * MsaWSJob
+   * 
+   * @param jobNum
+   *          int
+   * @param msaWSThread
+   *          TODO - abstract the properties provided by the thread
+   * @param jobId
+   *          String
+   */
+  public MsaWSJob(MsaWSThread msaWSThread, int jobNum, SequenceI[] inSeqs)
+  {
+    this.msaWSThread = msaWSThread;
+    this.jobnum = jobNum;
+    if (!prepareInput(inSeqs, 2))
+    {
+      submitted = true;
+      subjobComplete = true;
+      returnInput = true;
+    }
+
+  }
+
+  Vector<String[]> emptySeqs = new Vector();
+
+  /**
+   * prepare input sequences for MsaWS service
+   * 
+   * @param seqs
+   *          jalview sequences to be prepared
+   * @param minlen
+   *          minimum number of residues required for this MsaWS service
+   * @return true if seqs contains sequences to be submitted to service.
+   */
+  // TODO: return compbio.seqs list or nothing to indicate validity.
+  private boolean prepareInput(SequenceI[] seqs, int minlen)
+  {
+    // TODO: service specific input data is generated in this method - for
+    // JABAWS it is client-side
+    // prepared, but for Slivka it could be uploaded at this stage.
+
+    int nseqs = 0;
+    if (minlen < 0)
+    {
+      throw new Error(MessageManager.getString(
+              "error.implementation_error_minlen_must_be_greater_zero"));
+    }
+    for (int i = 0; i < seqs.length; i++)
+    {
+      if (seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
+      {
+        nseqs++;
+      }
+    }
+    boolean valid = nseqs > 1; // need at least two seqs
+    Sequence seq;
+    for (int i = 0, n = 0; i < seqs.length; i++)
+    {
+      String newname = jalview.analysis.SeqsetUtils.unique_name(i); // same
+      // for
+      // any
+      // subjob
+      SeqNames.put(newname,
+              jalview.analysis.SeqsetUtils.SeqCharacterHash(seqs[i]));
+      if (valid && seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
+      {
+        // make new input sequence with or without gaps
+        seq = new Sequence(newname,
+                (this.msaWSThread.submitGaps) ? seqs[i].getSequenceAsString()
+                        : AlignSeq.extractGaps(
+                                jalview.util.Comparison.GapChars,
+                                seqs[i].getSequenceAsString()));
+        this.seqs.add(seq);
+      }
+      else
+      {
+        String empty = null;
+        if (seqs[i].getEnd() >= seqs[i].getStart())
+        {
+          empty = (this.msaWSThread.submitGaps) ? seqs[i].getSequenceAsString()
+                  : AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
+                          seqs[i].getSequenceAsString());
+        }
+        emptySeqs.add(new String[] { newname, empty });
+      }
+    }
+    return valid;
+  }
+
+  /**
+   * 
+   * @return true if getAlignment will return a valid alignment result.
+   */
+  @Override
+  public boolean hasResults()
+  {
+    if (subjobComplete && isFinished() && (alignment != null
+            || (emptySeqs != null && emptySeqs.size() > 0)))
+    {
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * 
+   * get the alignment including any empty sequences in the original order
+   * with original ids. Caller must access the alignment.getMetadata() object
+   * to annotate the final result passsed to the user.
+   * 
+   * @return { SequenceI[], AlignmentOrder }
+   */
+  public Object[] getAlignment()
+  {
+    // TODO: make this generic based on MsaResultI
+    // TODO: decide if the data loss for this return signature is avoidable
+    // (ie should we just return AlignmentI instead ?)
+    if (hasResults())
+    {
+      SequenceI[] alseqs = null;
+      char alseq_gapchar = '-';
+      int alseq_l = 0;
+      alseqs = new SequenceI[alignment.getSequences().size()];
+      if (alignment.getSequences().size() > 0)
+      {
+        for (SequenceI seq : alignment
+                .getSequences())
+        {
+          alseqs[alseq_l++] = new Sequence(seq);
+        }
+        alseq_gapchar = alignment.getGapCharacter();
+
+      }
+      // add in the empty seqs.
+      if (emptySeqs.size() > 0)
+      {
+        SequenceI[] t_alseqs = new SequenceI[alseq_l + emptySeqs.size()];
+        // get width
+        int i, w = 0;
+        if (alseq_l > 0)
+        {
+          for (i = 0, w = alseqs[0].getLength(); i < alseq_l; i++)
+          {
+            if (w < alseqs[i].getLength())
+            {
+              w = alseqs[i].getLength();
+            }
+            t_alseqs[i] = alseqs[i];
+            alseqs[i] = null;
+          }
+        }
+        // check that aligned width is at least as wide as emptySeqs width.
+        int ow = w, nw = w;
+        for (i = 0, w = emptySeqs.size(); i < w; i++)
+        {
+          String[] es = emptySeqs.get(i);
+          if (es != null && es[1] != null)
+          {
+            int sw = es[1].length();
+            if (nw < sw)
+            {
+              nw = sw;
+            }
+          }
+        }
+        // make a gapped string.
+        StringBuffer insbuff = new StringBuffer(w);
+        for (i = 0; i < nw; i++)
+        {
+          insbuff.append(alseq_gapchar);
+        }
+        if (ow < nw)
+        {
+          for (i = 0; i < alseq_l; i++)
+          {
+            int sw = t_alseqs[i].getLength();
+            if (nw > sw)
+            {
+              // pad at end
+              alseqs[i].setSequence(t_alseqs[i].getSequenceAsString()
+                      + insbuff.substring(0, sw - nw));
+            }
+          }
+        }
+        for (i = 0, w = emptySeqs.size(); i < w; i++)
+        {
+          String[] es = emptySeqs.get(i);
+          if (es[1] == null)
+          {
+            t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(es[0],
+                    insbuff.toString(), 1, 0);
+          }
+          else
+          {
+            if (es[1].length() < nw)
+            {
+              t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
+                      es[0],
+                      es[1] + insbuff.substring(0, nw - es[1].length()),
+                      1, 1 + es[1].length());
+            }
+            else
+            {
+              t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
+                      es[0], es[1]);
+            }
+          }
+        }
+        alseqs = t_alseqs;
+      }
+      AlignmentOrder msaorder = new AlignmentOrder(alseqs);
+      // always recover the order - makes parseResult()'s life easier.
+      jalview.analysis.AlignmentSorter.recoverOrder(alseqs);
+      // account for any missing sequences
+      jalview.analysis.SeqsetUtils.deuniquify(SeqNames, alseqs);
+      return new Object[] { alseqs, msaorder };
+    }
+    return null;
+  }
+
+  /**
+   * mark subjob as cancelled and set result object appropriatly
+   */
+  void cancel()
+  {
+    cancelled = true;
+    subjobComplete = true;
+    alignment = null;
+  }
+
+  /**
+   * 
+   * @return boolean true if job can be submitted.
+   */
+  @Override
+  public boolean hasValidInput()
+  {
+    // TODO: get attributes for this MsaWS instance to check if it can do two
+    // sequence alignment.
+    if (seqs != null && seqs.size() >= 2) // two or more sequences is valid ?
+    {
+      return true;
+    }
+    return false;
+  }
+
+  StringBuffer jobProgress = new StringBuffer();
+
+  @Override
+  public void setStatus(String string)
+  {
+    jobProgress.setLength(0);
+    jobProgress.append(string);
+  }
+
+  @Override
+  public String getStatus()
+  {
+    return jobProgress.toString();
+  }
+
+  @Override
+  public boolean hasStatus()
+  {
+    return jobProgress != null;
+  }
+
+  /**
+   * @return the lastChunk
+   */
+  public long getLastChunk()
+  {
+    return lastChunk;
+  }
+
+  /**
+   * @param lastChunk
+   *          the lastChunk to set
+   */
+  public void setLastChunk(long lastChunk)
+  {
+    this.lastChunk = lastChunk;
+  }
+
+  String alignmentProgram = null;
+
+  public String getAlignmentProgram()
+  {
+    return alignmentProgram;
+  }
+
+  public boolean hasArguments()
+  {
+    return (arguments != null && arguments.size() > 0)
+            || (preset != null && preset instanceof JabaWsParamSet);
+  }
+
+  /**
+   * add a progess header to status string containing presets/args used
+   */
+  public void addInitialStatus()
+  {
+    // TODO: decide if it is useful to report 'JABAWS format' argument lists
+    // rather than generic Jalview service arguments
+    if (preset != null)
+    {
+      jobProgress.append(
+              "Using " + (preset.isModifiable() ? "Server" : "User")
+                      + "Preset: " + preset.getName());
+      for (ArgumentI opt : preset.getArguments())
+      {
+        jobProgress.append(opt.getName() + " " + opt.getValue() + "\n");
+      }
+    }
+    else
+    {
+      if (arguments != null && arguments.size() > 0)
+      {
+        jobProgress.append("With custom parameters : \n");
+        // merge arguments with preset's own arguments.
+        for (ArgumentI opt : arguments)
+        {
+          jobProgress.append(opt.getName() + " " + opt.getValue() + "\n");
+        }
+      }
+      jobProgress.append("\nJob Output:\n");
+    }
+  }
+
+  JobId jobHandle = null;
+  public void setJobHandle(JobId align)
+  {
+    jobHandle = align;
+    setJobId(jobHandle.getJobId());
+
+  }
+
+  public JobId getJobHandle()
+  {
+    return jobHandle;
+  }
+
+}
\ No newline at end of file
similarity index 53%
rename from src/jalview/ws/jws2/MsaWSThread.java
rename to src/jalview/ws/gui/MsaWSThread.java
index c4fc66b..7141e73 100644 (file)
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-package jalview.ws.jws2;
+package jalview.ws.gui;
 
-import jalview.analysis.AlignSeq;
 import jalview.bin.Cache;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AlignmentOrder;
 import jalview.datamodel.AlignmentView;
 import jalview.datamodel.HiddenColumns;
-import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
 import jalview.gui.Desktop;
 import jalview.gui.SplitFrame;
 import jalview.gui.WebserviceInfo;
 import jalview.util.MessageManager;
+import jalview.ws.AWSThread;
 import jalview.ws.AWsJob;
 import jalview.ws.JobStateSummary;
 import jalview.ws.WSClientI;
-import jalview.ws.jws2.dm.JabaWsParamSet;
+import jalview.ws.api.CancellableI;
+import jalview.ws.api.JobId;
+import jalview.ws.api.MultipleSequenceAlignmentI;
+import jalview.ws.gui.WsJob.JobState;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 
 import java.util.ArrayList;
-import java.util.Hashtable;
 import java.util.List;
-import java.util.Map;
-import java.util.Vector;
 
 import javax.swing.JInternalFrame;
 
-import compbio.data.msa.MsaWS;
-import compbio.metadata.Argument;
-import compbio.metadata.ChunkHolder;
-import compbio.metadata.JobStatus;
-import compbio.metadata.Preset;
-
-class MsaWSThread extends AWS2Thread implements WSClientI
+public class MsaWSThread extends AWSThread implements WSClientI
 {
   boolean submitGaps = false; // pass sequences including gaps to alignment
 
@@ -64,383 +58,13 @@ class MsaWSThread extends AWS2Thread implements WSClientI
 
   // order
 
-  class MsaWSJob extends JWs2Job
-  {
-    long lastChunk = 0;
-
-    WsParamSetI preset = null;
-
-    List<Argument> arguments = null;
-
-    /**
-     * input
-     */
-    ArrayList<compbio.data.sequence.FastaSequence> seqs = new ArrayList<>();
-
-    /**
-     * output
-     */
-    compbio.data.sequence.Alignment alignment;
-
-    // set if the job didn't get run - then the input is simply returned to the
-    // user
-    private boolean returnInput = false;
-
-    /**
-     * MsaWSJob
-     * 
-     * @param jobNum
-     *          int
-     * @param jobId
-     *          String
-     */
-    public MsaWSJob(int jobNum, SequenceI[] inSeqs)
-    {
-      this.jobnum = jobNum;
-      if (!prepareInput(inSeqs, 2))
-      {
-        submitted = true;
-        subjobComplete = true;
-        returnInput = true;
-      }
-
-    }
-
-    Hashtable<String, Map> SeqNames = new Hashtable();
-
-    Vector<String[]> emptySeqs = new Vector();
-
-    /**
-     * prepare input sequences for MsaWS service
-     * 
-     * @param seqs
-     *          jalview sequences to be prepared
-     * @param minlen
-     *          minimum number of residues required for this MsaWS service
-     * @return true if seqs contains sequences to be submitted to service.
-     */
-    // TODO: return compbio.seqs list or nothing to indicate validity.
-    private boolean prepareInput(SequenceI[] seqs, int minlen)
-    {
-      int nseqs = 0;
-      if (minlen < 0)
-      {
-        throw new Error(MessageManager.getString(
-                "error.implementation_error_minlen_must_be_greater_zero"));
-      }
-      for (int i = 0; i < seqs.length; i++)
-      {
-        if (seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
-        {
-          nseqs++;
-        }
-      }
-      boolean valid = nseqs > 1; // need at least two seqs
-      compbio.data.sequence.FastaSequence seq;
-      for (int i = 0, n = 0; i < seqs.length; i++)
-      {
-        String newname = jalview.analysis.SeqsetUtils.unique_name(i); // same
-        // for
-        // any
-        // subjob
-        SeqNames.put(newname,
-                jalview.analysis.SeqsetUtils.SeqCharacterHash(seqs[i]));
-        if (valid && seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
-        {
-          // make new input sequence with or without gaps
-          seq = new compbio.data.sequence.FastaSequence(newname,
-                  (submitGaps) ? seqs[i].getSequenceAsString()
-                          : AlignSeq.extractGaps(
-                                  jalview.util.Comparison.GapChars,
-                                  seqs[i].getSequenceAsString()));
-          this.seqs.add(seq);
-        }
-        else
-        {
-          String empty = null;
-          if (seqs[i].getEnd() >= seqs[i].getStart())
-          {
-            empty = (submitGaps) ? seqs[i].getSequenceAsString()
-                    : AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
-                            seqs[i].getSequenceAsString());
-          }
-          emptySeqs.add(new String[] { newname, empty });
-        }
-      }
-      return valid;
-    }
-
-    /**
-     * 
-     * @return true if getAlignment will return a valid alignment result.
-     */
-    @Override
-    public boolean hasResults()
-    {
-      if (subjobComplete && isFinished() && (alignment != null
-              || (emptySeqs != null && emptySeqs.size() > 0)))
-      {
-        return true;
-      }
-      return false;
-    }
-
-    /**
-     * 
-     * get the alignment including any empty sequences in the original order
-     * with original ids. Caller must access the alignment.getMetadata() object
-     * to annotate the final result passsed to the user.
-     * 
-     * @return { SequenceI[], AlignmentOrder }
-     */
-    public Object[] getAlignment()
-    {
-      // is this a generic subjob or a Jws2 specific Object[] return signature
-      if (hasResults())
-      {
-        SequenceI[] alseqs = null;
-        char alseq_gapchar = '-';
-        int alseq_l = 0;
-        if (alignment.getSequences().size() > 0)
-        {
-          alseqs = new SequenceI[alignment.getSequences().size()];
-          for (compbio.data.sequence.FastaSequence seq : alignment
-                  .getSequences())
-          {
-            alseqs[alseq_l++] = new Sequence(seq.getId(),
-                    seq.getSequence());
-          }
-          alseq_gapchar = alignment.getMetadata().getGapchar();
-
-        }
-        // add in the empty seqs.
-        if (emptySeqs.size() > 0)
-        {
-          SequenceI[] t_alseqs = new SequenceI[alseq_l + emptySeqs.size()];
-          // get width
-          int i, w = 0;
-          if (alseq_l > 0)
-          {
-            for (i = 0, w = alseqs[0].getLength(); i < alseq_l; i++)
-            {
-              if (w < alseqs[i].getLength())
-              {
-                w = alseqs[i].getLength();
-              }
-              t_alseqs[i] = alseqs[i];
-              alseqs[i] = null;
-            }
-          }
-          // check that aligned width is at least as wide as emptySeqs width.
-          int ow = w, nw = w;
-          for (i = 0, w = emptySeqs.size(); i < w; i++)
-          {
-            String[] es = emptySeqs.get(i);
-            if (es != null && es[1] != null)
-            {
-              int sw = es[1].length();
-              if (nw < sw)
-              {
-                nw = sw;
-              }
-            }
-          }
-          // make a gapped string.
-          StringBuffer insbuff = new StringBuffer(w);
-          for (i = 0; i < nw; i++)
-          {
-            insbuff.append(alseq_gapchar);
-          }
-          if (ow < nw)
-          {
-            for (i = 0; i < alseq_l; i++)
-            {
-              int sw = t_alseqs[i].getLength();
-              if (nw > sw)
-              {
-                // pad at end
-                alseqs[i].setSequence(t_alseqs[i].getSequenceAsString()
-                        + insbuff.substring(0, sw - nw));
-              }
-            }
-          }
-          for (i = 0, w = emptySeqs.size(); i < w; i++)
-          {
-            String[] es = emptySeqs.get(i);
-            if (es[1] == null)
-            {
-              t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(es[0],
-                      insbuff.toString(), 1, 0);
-            }
-            else
-            {
-              if (es[1].length() < nw)
-              {
-                t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
-                        es[0],
-                        es[1] + insbuff.substring(0, nw - es[1].length()),
-                        1, 1 + es[1].length());
-              }
-              else
-              {
-                t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
-                        es[0], es[1]);
-              }
-            }
-          }
-          alseqs = t_alseqs;
-        }
-        AlignmentOrder msaorder = new AlignmentOrder(alseqs);
-        // always recover the order - makes parseResult()'s life easier.
-        jalview.analysis.AlignmentSorter.recoverOrder(alseqs);
-        // account for any missing sequences
-        jalview.analysis.SeqsetUtils.deuniquify(SeqNames, alseqs);
-        return new Object[] { alseqs, msaorder };
-      }
-      return null;
-    }
-
-    /**
-     * mark subjob as cancelled and set result object appropriatly
-     */
-    void cancel()
-    {
-      cancelled = true;
-      subjobComplete = true;
-      alignment = null;
-    }
-
-    /**
-     * 
-     * @return boolean true if job can be submitted.
-     */
-    @Override
-    public boolean hasValidInput()
-    {
-      // TODO: get attributes for this MsaWS instance to check if it can do two
-      // sequence alignment.
-      if (seqs != null && seqs.size() >= 2) // two or more sequences is valid ?
-      {
-        return true;
-      }
-      return false;
-    }
-
-    StringBuffer jobProgress = new StringBuffer();
-
-    public void setStatus(String string)
-    {
-      jobProgress.setLength(0);
-      jobProgress.append(string);
-    }
-
-    @Override
-    public String getStatus()
-    {
-      return jobProgress.toString();
-    }
-
-    @Override
-    public boolean hasStatus()
-    {
-      return jobProgress != null;
-    }
-
-    /**
-     * @return the lastChunk
-     */
-    public long getLastChunk()
-    {
-      return lastChunk;
-    }
-
-    /**
-     * @param lastChunk
-     *          the lastChunk to set
-     */
-    public void setLastChunk(long lastChunk)
-    {
-      this.lastChunk = lastChunk;
-    }
-
-    String alignmentProgram = null;
-
-    public String getAlignmentProgram()
-    {
-      return alignmentProgram;
-    }
-
-    public boolean hasArguments()
-    {
-      return (arguments != null && arguments.size() > 0)
-              || (preset != null && preset instanceof JabaWsParamSet);
-    }
-
-    public List<Argument> getJabaArguments()
-    {
-      List<Argument> newargs = new ArrayList<>();
-      if (preset != null && preset instanceof JabaWsParamSet)
-      {
-        newargs.addAll(((JabaWsParamSet) preset).getjabaArguments());
-      }
-      if (arguments != null && arguments.size() > 0)
-      {
-        newargs.addAll(arguments);
-      }
-      return newargs;
-    }
-
-    /**
-     * add a progess header to status string containing presets/args used
-     */
-    public void addInitialStatus()
-    {
-      if (preset != null)
-      {
-        jobProgress.append("Using "
-                + (preset instanceof JabaPreset ? "Server" : "User")
-                + "Preset: " + preset.getName());
-        if (preset instanceof JabaWsParamSet)
-        {
-          for (Argument opt : ((JabaWsParamSet) preset).getjabaArguments())
-          {
-            jobProgress.append(
-                    opt.getName() + " " + opt.getDefaultValue() + "\n");
-          }
-        }
-      }
-      if (arguments != null && arguments.size() > 0)
-      {
-        jobProgress.append("With custom parameters : \n");
-        // merge arguments with preset's own arguments.
-        for (Argument opt : arguments)
-        {
-          jobProgress.append(
-                  opt.getName() + " " + opt.getDefaultValue() + "\n");
-        }
-      }
-      jobProgress.append("\nJob Output:\n");
-    }
-
-    public boolean isPresetJob()
-    {
-      return preset != null && preset instanceof JabaPreset;
-    }
-
-    public Preset getServerPreset()
-    {
-      return (isPresetJob()) ? ((JabaPreset) preset).p : null;
-    }
-  }
-
   String alTitle; // name which will be used to form new alignment window.
 
   AlignmentI dataset; // dataset to which the new alignment will be
 
   // associated.
 
-  @SuppressWarnings("unchecked")
-  MsaWS server = null;
+  MultipleSequenceAlignmentI server = null;
 
   /**
    * set basic options for this (group) of Msa jobs
@@ -450,7 +74,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
    * @param presorder
    *          boolean
    */
-  private MsaWSThread(MsaWS server, String wsUrl, WebserviceInfo wsinfo,
+  private MsaWSThread(MultipleSequenceAlignmentI server, String wsUrl,
+          WebserviceInfo wsinfo,
           jalview.gui.AlignFrame alFrame, AlignmentView alview,
           String wsname, boolean subgaps, boolean presorder)
   {
@@ -461,7 +86,7 @@ class MsaWSThread extends AWS2Thread implements WSClientI
   }
 
   /**
-   * create one or more Msa jobs to align visible seuqences in _msa
+   * create one or more Msa jobs to align visible sequences in _msa
    * 
    * @param title
    *          String
@@ -474,7 +99,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
    * @param seqset
    *          Alignment
    */
-  MsaWSThread(MsaWS server2, WsParamSetI preset, List<Argument> paramset,
+  public MsaWSThread(MultipleSequenceAlignmentI server2, WsParamSetI preset,
+          List<ArgumentI> paramset,
           String wsUrl, WebserviceInfo wsinfo,
           jalview.gui.AlignFrame alFrame, String wsname, String title,
           AlignmentView _msa, boolean subgaps, boolean presorder,
@@ -489,23 +115,23 @@ class MsaWSThread extends AWS2Thread implements WSClientI
     if (conmsa != null)
     {
       int nvalid = 0, njobs = conmsa.length;
-      jobs = new MsaWSJob[njobs];
+      jobs = new AWsJob[njobs];
       for (int j = 0; j < njobs; j++)
       {
         if (j != 0)
         {
-          jobs[j] = new MsaWSJob(wsinfo.addJobPane(), conmsa[j]);
+          jobs[j] = new MsaWSJob(this, wsinfo.addJobPane(), conmsa[j]);
         }
         else
         {
-          jobs[j] = new MsaWSJob(0, conmsa[j]);
+          jobs[j] = new MsaWSJob(this, 0, conmsa[j]);
         }
-        if (((MsaWSJob) jobs[j]).hasValidInput())
+        if (jobs[j].hasValidInput())
         {
           nvalid++;
         }
-        ((MsaWSJob) jobs[j]).preset = preset;
-        ((MsaWSJob) jobs[j]).arguments = paramset;
+        jobs[j].setPreset(preset);
+        jobs[j].setArguments(paramset);
         ((MsaWSJob) jobs[j]).alignmentProgram = wsname;
         if (njobs > 0)
         {
@@ -532,12 +158,14 @@ class MsaWSThread extends AWS2Thread implements WSClientI
   @Override
   public boolean isCancellable()
   {
-    return true;
+    return server instanceof CancellableI;
   }
 
   @Override
   public void cancelJob()
   {
+    // TODO decide if when some jobs are not cancellable to shut down the thread
+    // anyhow ?
     if (!jobComplete && jobs != null)
     {
       boolean cancelled = true;
@@ -548,13 +176,11 @@ class MsaWSThread extends AWS2Thread implements WSClientI
           String cancelledMessage = "";
           try
           {
-            boolean cancelledJob = server.cancelJob(jobs[job].getJobId());
-            if (true) // cancelledJob || true)
+            CancellableI service = (CancellableI) server;
+            boolean cancelledJob = service.cancel((WsJob) jobs[job]);
+            if (cancelledJob)
             {
               // CANCELLED_JOB
-              // if the Jaba server indicates the job can't be cancelled, its
-              // because its running on the server's local execution engine
-              // so we just close the window anyway.
               cancelledMessage = "Job cancelled.";
               ((MsaWSJob) jobs[job]).cancel(); // TODO: refactor to avoid this
                                                // ugliness -
@@ -614,42 +240,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
     // this is standard code, but since the interface doesn't comprise of a
     // basic one that implements (getJobStatus, pullExecStatistics) we have to
     // repeat the code for all jw2s services.
-    j.setjobStatus(server.getJobStatus(job.getJobId()));
-    updateJobProgress(j);
-  }
-
-  /**
-   * 
-   * @param j
-   * @return true if more job progress data was available
-   * @throws Exception
-   */
-  protected boolean updateJobProgress(MsaWSJob j) throws Exception
-  {
-    StringBuffer response = j.jobProgress;
-    long lastchunk = j.getLastChunk();
-    boolean changed = false;
-    do
-    {
-      j.setLastChunk(lastchunk);
-      ChunkHolder chunk = server.pullExecStatistics(j.getJobId(),
-              lastchunk);
-      if (chunk != null)
-      {
-        changed |= chunk.getChunk().length() > 0;
-        response.append(chunk.getChunk());
-        lastchunk = chunk.getNextPosition();
-        try
-        {
-          Thread.sleep(50);
-        } catch (InterruptedException x)
-        {
-        }
-        ;
-      }
-      ;
-    } while (lastchunk >= 0 && j.getLastChunk() != lastchunk);
-    return changed;
+    server.updateStatus(j);
+    server.updateJobProgress(j);
   }
 
   @Override
@@ -678,26 +270,37 @@ class MsaWSThread extends AWS2Thread implements WSClientI
     if (j.seqs == null || j.seqs.size() == 0)
     {
       // special case - selection consisted entirely of empty sequences...
-      j.setjobStatus(JobStatus.FINISHED);
+      j.setState(JobState.FINISHED);
       j.setStatus(MessageManager.getString("label.empty_alignment_job"));
     }
     try
     {
       j.addInitialStatus(); // list the presets/parameters used for the job in
                             // status
-      if (j.isPresetJob())
-      {
-        j.setJobId(server.presetAlign(j.seqs, j.getServerPreset()));
-      }
-      else if (j.hasArguments())
+      try
       {
-        j.setJobId(server.customAlign(j.seqs, j.getJabaArguments()));
-      }
-      else
+        JobId jobHandle = server.align(j.seqs, j.getPreset(),
+                j.getArguments());
+        if (jobHandle != null)
+        {
+          j.setJobHandle(jobHandle);
+        }
+
+      } catch (Throwable throwable)
       {
-        j.setJobId(server.align(j.seqs));
+        if (!server.handleSubmitError(throwable, j, wsInfo))
+        {
+          if (throwable instanceof Exception)
+          {
+            throw ((Exception) throwable);
+          }
+          if (throwable instanceof Error)
+          {
+            throw ((Error) throwable);
+          }
+        }
       }
-
+      ///// generic
       if (j.getJobId() != null)
       {
         j.setSubmitted(true);
@@ -712,40 +315,11 @@ class MsaWSThread extends AWS2Thread implements WSClientI
                 new String[]
                 { WsUrl }));
       }
-    } catch (compbio.metadata.UnsupportedRuntimeException _lex)
-    {
-      lex = _lex;
-      wsInfo.appendProgressText(MessageManager.formatMessage(
-              "info.job_couldnt_be_run_server_doesnt_support_program",
-              new String[]
-              { _lex.getMessage() }));
-      wsInfo.warnUser(_lex.getMessage(),
-              MessageManager.getString("warn.service_not_supported"));
-      wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
-      wsInfo.setStatus(j.getJobnum(),
-              WebserviceInfo.STATE_STOPPED_SERVERERROR);
-    } catch (compbio.metadata.LimitExceededException _lex)
-    {
-      lex = _lex;
-      wsInfo.appendProgressText(MessageManager.formatMessage(
-              "info.job_couldnt_be_run_exceeded_hard_limit", new String[]
-              { _lex.getMessage() }));
-      wsInfo.warnUser(_lex.getMessage(),
-              MessageManager.getString("warn.input_is_too_big"));
-      wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
-      wsInfo.setStatus(j.getJobnum(), WebserviceInfo.STATE_STOPPED_ERROR);
-    } catch (compbio.metadata.WrongParameterException _lex)
-    {
-      lex = _lex;
-      wsInfo.warnUser(_lex.getMessage(),
-              MessageManager.getString("warn.invalid_job_param_set"));
-      wsInfo.appendProgressText(MessageManager.formatMessage(
-              "info.job_couldnt_be_run_incorrect_param_setting",
-              new String[]
-              { _lex.getMessage() }));
-      wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
-      wsInfo.setStatus(j.getJobnum(), WebserviceInfo.STATE_STOPPED_ERROR);
-    } catch (Error e)
+    }
+    //// jabaws specific
+
+    //// generic
+    catch (Error e)
     {
       // For unexpected errors
       System.err.println(WebServiceName
@@ -801,7 +375,7 @@ class MsaWSThread extends AWS2Thread implements WSClientI
           {
             try
             {
-              jpchanged = updateJobProgress(msjob);
+              jpchanged = server.updateJobProgress(msjob);
               jpex = false;
               if (jpchanged)
               {
@@ -842,25 +416,18 @@ class MsaWSThread extends AWS2Thread implements WSClientI
             System.out.println("*** End of status");
 
           }
+          ///// jabaws specific(ish) Get Result from Server when available
           try
           {
-            msjob.alignment = server.getResult(msjob.getJobId());
-          } catch (compbio.metadata.ResultNotAvailableException e)
-          {
-            // job has failed for some reason - probably due to invalid
-            // parameters
-            Cache.log.debug(
-                    "Results not available for finished job - marking as broken job.",
-                    e);
-            msjob.jobProgress.append(
-                    "\nResult not available. Probably due to invalid input or parameter settings. Server error message below:\n\n"
-                            + e.getLocalizedMessage());
-            msjob.setjobStatus(JobStatus.FAILED);
+            msjob.alignment = server.getAlignmentFor(msjob.getJobHandle());
           } catch (Exception e)
           {
-            Cache.log.error("Couldn't get Alignment for job.", e);
-            // TODO: Increment count and retry ?
-            msjob.setjobStatus(JobStatus.UNDEFINED);
+            if (!server.handleCollectionException(e, msjob, wsInfo))
+            {
+              Cache.log.error("Couldn't get Alignment for job.", e);
+              // TODO: Increment count and retry ?
+              msjob.setState(JobState.SERVERERROR);
+            }
           }
         }
         finalState.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
@@ -868,19 +435,6 @@ class MsaWSThread extends AWS2Thread implements WSClientI
                 && jobs[j].hasResults())
         {
           results++;
-          compbio.data.sequence.Alignment alignment = ((MsaWSJob) jobs[j]).alignment;
-          if (alignment != null)
-          {
-            // server.close(jobs[j].getJobnum());
-            // wsInfo.appendProgressText(jobs[j].getJobnum(),
-            // "\nAlignment Object Method Notes\n");
-            // wsInfo.appendProgressText(jobs[j].getJobnum(),
-            // "Calculated with
-            // "+alignment.getMetadata().getProgram().toString());
-            // JBPNote The returned files from a webservice could be
-            // hidden behind icons in the monitor window that,
-            // when clicked, pop up their corresponding data
-          }
         }
       }
     } catch (Exception ex)
diff --git a/src/jalview/ws/gui/WsJob.java b/src/jalview/ws/gui/WsJob.java
new file mode 100644 (file)
index 0000000..05379d7
--- /dev/null
@@ -0,0 +1,176 @@
+/**
+ * 
+ */
+package jalview.ws.gui;
+
+import jalview.ws.AWsJob;
+
+/**
+ * Bean that holds state for a job
+ * 
+ * @author jprocter
+ *
+ */
+public class WsJob extends AWsJob
+{
+
+  public enum JobState
+  {
+    INVALID, READY, SUBMITTED, QUEUED, RUNNING, FINISHED, BROKEN, FAILED,
+    UNKNOWN, SERVERERROR, CANCELLED;
+  };
+
+  JobState state = JobState.UNKNOWN;
+
+  boolean hasResults = false, validInput = false;
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#hasResults()
+   */
+  @Override
+  public boolean hasResults()
+  {
+    return hasResults;
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#hasValidInput()
+   */
+  @Override
+  public boolean hasValidInput()
+  {
+    return validInput;
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#isRunning()
+   */
+  @Override
+  public boolean isRunning()
+  {
+    return JobState.RUNNING.equals(state);
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#isQueued()
+   */
+  @Override
+  public boolean isQueued()
+  {
+    return JobState.QUEUED.equals(state);
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#isFinished()
+   */
+  @Override
+  public boolean isFinished()
+  {
+    // TODO isSubjobComplete and finished flags mean same thing ?
+    return JobState.FINISHED.equals(state);
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#isFailed()
+   */
+  @Override
+  public boolean isFailed()
+  {
+    return JobState.FAILED.equals(state);
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#isBroken()
+   */
+  @Override
+  public boolean isBroken()
+  {
+    return JobState.BROKEN.equals(state);
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#isServerError()
+   */
+  @Override
+  public boolean isServerError()
+  {
+    return JobState.SERVERERROR.equals(state);
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#hasStatus()
+   */
+  @Override
+  public boolean hasStatus()
+  {
+    return status != null && status.length() > 0;
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#getStatus()
+   */
+  @Override
+  public String getStatus()
+  {
+    return status;
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#hasResponse()
+   */
+  @Override
+  public boolean hasResponse()
+  {
+    // TODO Auto-generated method stub
+    return hasStatus();
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#clearResponse()
+   */
+  @Override
+  public void clearResponse()
+  {
+    status = "";
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#getState()
+   */
+  @Override
+  public String getState()
+  {
+    return state.toString();
+  }
+
+  /**
+   * @return the current JobState
+   */
+  public JobState getJobState()
+  {
+    return state;
+  }
+
+  /**
+   * set the job state
+   * 
+   * @param state
+   */
+  public void setState(JobState state)
+  {
+    this.state = state;
+  }
+
+  String status = "";
+
+  /**
+   * Set the log for this job
+   * 
+   * @parag log
+   */
+  public void setStatus(String log)
+  {
+    status = log;
+
+  }
+
+}
index 4a09625..e627699 100644 (file)
@@ -51,8 +51,6 @@ public class MsaWSClient extends WS1Client
    */
   ext.vamsas.MuscleWS server;
 
-  AlignFrame alignFrame;
-
   /**
    * Creates a new MsaWSClient object that uses a service given by an externally
    * retrieved ServiceHandle
index 006f014..7b3df82 100644 (file)
@@ -36,7 +36,6 @@ import jalview.ws.AWsJob;
 import jalview.ws.JobStateSummary;
 import jalview.ws.WSClientI;
 
-import java.util.Hashtable;
 import java.util.Vector;
 
 import vamsas.objects.simple.MsaResult;
@@ -78,8 +77,6 @@ class MsaWSThread extends JWS1Thread implements WSClientI
 
     }
 
-    Hashtable SeqNames = new Hashtable();
-
     Vector emptySeqs = new Vector();
 
     /**
index 53338d3..49de37e 100644 (file)
@@ -56,8 +56,6 @@ public class SeqSearchWSClient extends WS1Client
    */
   ext.vamsas.SeqSearchI server;
 
-  AlignFrame alignFrame;
-
   /**
    * Creates a new MsaWSClient object that uses a service given by an externally
    * retrieved ServiceHandle
index 761b758..2f2bf2c 100644 (file)
@@ -37,7 +37,6 @@ import jalview.ws.JobStateSummary;
 import jalview.ws.WSClientI;
 
 import java.util.HashMap;
-import java.util.Hashtable;
 import java.util.Map;
 import java.util.Vector;
 
@@ -77,8 +76,6 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
 
     }
 
-    Hashtable SeqNames = new Hashtable();
-
     Vector emptySeqs = new Vector();
 
     /**
index 327864a..ddd69a7 100644 (file)
@@ -24,6 +24,7 @@ import jalview.datamodel.AlignmentAnnotation;
 import jalview.gui.AlignFrame;
 import jalview.util.MessageManager;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 import jalview.ws.uimodel.AlignAnalysisUIText;
 
@@ -35,13 +36,12 @@ import java.util.TreeSet;
 
 import compbio.data.sequence.FastaSequence;
 import compbio.data.sequence.Score;
-import compbio.metadata.Argument;
 
 public class AAConClient extends JabawsCalcWorker
 {
 
   public AAConClient(Jws2Instance service, AlignFrame alignFrame,
-          WsParamSetI preset, List<Argument> paramset)
+          WsParamSetI preset, List<ArgumentI> paramset)
   {
     super(service, alignFrame, preset, paramset);
     submitGaps = true;
index a1b8e7a..91db7c3 100644 (file)
@@ -30,6 +30,7 @@ import jalview.gui.AlignFrame;
 import jalview.schemes.FeatureColour;
 import jalview.util.ColorUtils;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 
 import java.awt.Color;
@@ -44,7 +45,6 @@ import compbio.data.sequence.FastaSequence;
 import compbio.data.sequence.Range;
 import compbio.data.sequence.Score;
 import compbio.data.sequence.ScoreManager.ScoreHolder;
-import compbio.metadata.Argument;
 
 public class AADisorderClient extends JabawsCalcWorker
 {
@@ -62,12 +62,12 @@ public class AADisorderClient extends JabawsCalcWorker
   AlignFrame af;
 
   public AADisorderClient(Jws2Instance sh, AlignFrame alignFrame,
-          WsParamSetI thePreset, List<Argument> paramset)
+          WsParamSetI thePreset, List<ArgumentI> paramset)
   {
     super(sh, alignFrame, thePreset, paramset);
     af = alignFrame;
-    typeName = sh.action;
-    methodName = sh.serviceType;
+    typeName = sh.getAction();
+    methodName = sh.getName();
 
     submitGaps = false;
     alignedSeqs = false;
@@ -169,9 +169,9 @@ public class AADisorderClient extends JabawsCalcWorker
     if (immediate || !calcMan.isWorking(this) && scoremanager != null)
     {
       Map<String, String[]> featureTypeMap = featureMap
-              .get(service.serviceType);
+              .get(service.getName());
       Map<String, Map<String, Object>> annotTypeMap = annotMap
-              .get(service.serviceType);
+              .get(service.getName());
       boolean dispFeatures = false;
       Map<String, Object> fc = new Hashtable<>();
       List<AlignmentAnnotation> ourAnnot = new ArrayList<>();
@@ -265,9 +265,9 @@ public class AADisorderClient extends JabawsCalcWorker
               String typename, calcName;
               AlignmentAnnotation annot = createAnnotationRowsForScores(
                       ourAnnot,
-                      typename = service.serviceType + " ("
+                      typename = service.getName() + " ("
                               + scr.getMethod() + ")",
-                      calcName = service.getServiceTypeURI() + "/"
+                      calcName = service.getNameURI() + "/"
                               + scr.getMethod(),
                       aseq, base + 1, scr);
               annot.graph = AlignmentAnnotation.LINE_GRAPH;
index dd64e77..1a361c4 100644 (file)
@@ -36,6 +36,7 @@ import jalview.workers.AlignCalcWorker;
 import jalview.ws.jws2.dm.AAConSettings;
 import jalview.ws.jws2.dm.JabaWsParamSet;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 
 import java.util.ArrayList;
@@ -44,7 +45,6 @@ import java.util.List;
 import java.util.Map;
 
 import compbio.data.sequence.FastaSequence;
-import compbio.metadata.Argument;
 import compbio.metadata.ChunkHolder;
 import compbio.metadata.JobStatus;
 import compbio.metadata.JobSubmissionException;
@@ -58,7 +58,7 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
 
   protected WsParamSetI preset;
 
-  protected List<Argument> arguments;
+  protected List<ArgumentI> arguments;
 
   protected IProgressIndicator guiProgress;
 
@@ -78,10 +78,7 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
     {
       ((jalview.gui.AlignViewport) alignViewport).setCalcIdSettingsFor(
               getCalcId(),
-              new AAConSettings(true, service, this.preset,
-                      (arguments != null)
-                              ? JabaParamStore.getJwsArgsfromJaba(arguments)
-                              : null),
+              new AAConSettings(true, service, this.preset, arguments),
               true);
     }
   }
@@ -98,7 +95,7 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
     return preset;
   }
 
-  public List<Argument> getArguments()
+  public List<ArgumentI> getArguments()
   {
     return arguments;
   }
@@ -112,7 +109,7 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
    * @param newarguments
    */
   public void updateParameters(final WsParamSetI newpreset,
-          final List<Argument> newarguments)
+          final List<ArgumentI> newarguments)
   {
     preset = newpreset;
     arguments = newarguments;
@@ -129,7 +126,7 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
     }
     if (arguments != null && arguments.size() > 0)
     {
-      for (Argument rg : arguments)
+      for (Object rg : JabaParamStore.getJabafromJwsArgs(arguments))
       {
         if (Option.class.isAssignableFrom(rg.getClass()))
         {
@@ -168,7 +165,7 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
   }
 
   public AbstractJabaCalcWorker(Jws2Instance service, AlignFrame alignFrame,
-          WsParamSetI preset, List<Argument> paramset)
+          WsParamSetI preset, List<ArgumentI> paramset)
   {
     this(alignFrame.getCurrentView(), alignFrame.alignPanel);
     this.guiProgress = alignFrame;
index 10ec812..0257a76 100644 (file)
@@ -47,7 +47,7 @@ import compbio.metadata.RunnerConfig;
 public class JabaParamStore implements ParamDatastoreI
 {
 
-  Hashtable<String, JabaWsParamSet> editedParams = new Hashtable<String, JabaWsParamSet>();
+  Hashtable<String, JabaWsParamSet> editedParams = new Hashtable<>();
 
   private Jws2Instance service;
 
@@ -101,7 +101,7 @@ public class JabaParamStore implements ParamDatastoreI
     List<WsParamSetI> prefs = new ArrayList();
     if (servicePresets == null)
     {
-      servicePresets = new Hashtable<String, JabaPreset>();
+      servicePresets = new Hashtable<>();
       PresetManager prman;
       if ((prman = service.getPresets()) != null)
       {
@@ -148,8 +148,8 @@ public class JabaParamStore implements ParamDatastoreI
   public static List<ArgumentI> getJwsArgsfromJaba(List jabargs,
           boolean sortByOpt)
   {
-    List<ArgumentI> rgs = new ArrayList<ArgumentI>();
-    List<String> rgnames = new ArrayList<String>();
+    List<ArgumentI> rgs = new ArrayList<>();
+    List<String> rgnames = new ArrayList<>();
     for (Object rg : jabargs)
     {
       ArgumentI narg = null;
@@ -309,7 +309,7 @@ public class JabaParamStore implements ParamDatastoreI
     boolean found = false;
     for (String url : urls)
     {
-      if (service.getServiceTypeURI().equals(url)
+      if (service.getNameURI().equals(url)
               || service.getUri().equalsIgnoreCase(url))
       {
         found = true;
@@ -334,7 +334,7 @@ public class JabaParamStore implements ParamDatastoreI
     wsp.setDescription(descr);
     wsp.setApplicableUrls(urls.clone());
 
-    List<String> lines = new ArrayList<String>();
+    List<String> lines = new ArrayList<>();
     StringTokenizer st = new StringTokenizer(parameterfile, "\n");
     while (st.hasMoreTokens())
     {
index 981b288..b6a18dd 100644 (file)
@@ -100,4 +100,9 @@ public class JabaPreset implements WsParamSetI
     throw new Error(MessageManager
             .getString("error.cannot_set_params_for_ws_preset"));
   }
+
+  public Preset getJabaPreset()
+  {
+    return p;
+  }
 }
diff --git a/src/jalview/ws/jws2/JabaWsParamTest.java b/src/jalview/ws/jws2/JabaWsParamTest.java
new file mode 100644 (file)
index 0000000..8c57529
--- /dev/null
@@ -0,0 +1,262 @@
+package jalview.ws.jws2;
+
+import jalview.gui.WsJobParameters;
+import jalview.util.MessageManager;
+import jalview.ws.jws2.jabaws2.Jws2Instance;
+
+import java.awt.BorderLayout;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+import compbio.metadata.Option;
+import compbio.metadata.Parameter;
+import compbio.metadata.Preset;
+import compbio.metadata.PresetManager;
+
+public class JabaWsParamTest
+{
+
+  /**
+   * testing method - grab a service and parameter set and show the window
+   * 
+   * @param args
+   */
+  public static void main(String[] args)
+  {
+    jalview.ws.jws2.Jws2Discoverer disc = jalview.ws.jws2.Jws2Discoverer
+            .getDiscoverer();
+    int p = 0;
+    if (args.length > 0)
+    {
+      Vector<String> services = new Vector<>();
+      services.addElement(args[p++]);
+      Jws2Discoverer.getDiscoverer().setServiceUrls(services);
+    }
+    try
+    {
+      disc.run();
+    } catch (Exception e)
+    {
+      System.err.println("Aborting. Problem discovering services.");
+      e.printStackTrace();
+      return;
+    }
+    Jws2Instance lastserv = null;
+    for (Jws2Instance service : disc.getServices())
+    {
+      lastserv = service;
+      if (p >= args.length || service.getName().equalsIgnoreCase(args[p]))
+      {
+        if (lastserv != null)
+        {
+          List<Preset> prl = null;
+          Preset pr = null;
+          if (++p < args.length)
+          {
+            PresetManager prman = lastserv.getPresets();
+            if (prman != null)
+            {
+              pr = prman.getPresetByName(args[p]);
+              if (pr == null)
+              {
+                // just grab the last preset.
+                prl = prman.getPresets();
+              }
+            }
+          }
+          else
+          {
+            PresetManager prman = lastserv.getPresets();
+            if (prman != null)
+            {
+              prl = prman.getPresets();
+            }
+          }
+          Iterator<Preset> en = (prl == null) ? null : prl.iterator();
+          while (en != null && en.hasNext())
+          {
+            if (en != null)
+            {
+              if (!en.hasNext())
+              {
+                en = prl.iterator();
+              }
+              pr = en.next();
+            }
+            {
+              System.out.println("Testing opts dupes for "
+                      + lastserv.getUri() + " : " + lastserv.getActionText()
+                      + ":" + pr.getName());
+              List<Option> rg = lastserv.getRunnerConfig().getOptions();
+              for (Option o : rg)
+              {
+                try
+                {
+                  Option cpy = jalview.ws.jws2.ParameterUtils.copyOption(o);
+                } catch (Exception e)
+                {
+                  System.err.println("Failed to copy " + o.getName());
+                  e.printStackTrace();
+                } catch (Error e)
+                {
+                  System.err.println("Failed to copy " + o.getName());
+                  e.printStackTrace();
+                }
+              }
+            }
+            {
+              System.out.println("Testing param dupes:");
+              List<Parameter> rg = lastserv.getRunnerConfig()
+                      .getParameters();
+              for (Parameter o : rg)
+              {
+                try
+                {
+                  Parameter cpy = jalview.ws.jws2.ParameterUtils
+                          .copyParameter(o);
+                } catch (Exception e)
+                {
+                  System.err.println("Failed to copy " + o.getName());
+                  e.printStackTrace();
+                } catch (Error e)
+                {
+                  System.err.println("Failed to copy " + o.getName());
+                  e.printStackTrace();
+                }
+              }
+            }
+            {
+              System.out.println("Testing param write:");
+              List<String> writeparam = null, readparam = null;
+              try
+              {
+                writeparam = jalview.ws.jws2.ParameterUtils
+                        .writeParameterSet(
+                                pr.getArguments(lastserv.getRunnerConfig()),
+                                " ");
+                System.out.println("Testing param read :");
+                List<Option> pset = jalview.ws.jws2.ParameterUtils
+                        .processParameters(writeparam,
+                                lastserv.getRunnerConfig(), " ");
+                readparam = jalview.ws.jws2.ParameterUtils
+                        .writeParameterSet(pset, " ");
+                Iterator<String> o = pr.getOptions().iterator(),
+                        s = writeparam.iterator(), t = readparam.iterator();
+                boolean failed = false;
+                while (s.hasNext() && t.hasNext())
+                {
+                  String on = o.next(), sn = s.next(), st = t.next();
+                  if (!sn.equals(st))
+                  {
+                    System.out.println(
+                            "Original was " + on + " Phase 1 wrote " + sn
+                                    + "\tPhase 2 wrote " + st);
+                    failed = true;
+                  }
+                }
+                if (failed)
+                {
+                  System.out.println(
+                          "Original parameters:\n" + pr.getOptions());
+                  System.out.println(
+                          "Wrote parameters in first set:\n" + writeparam);
+                  System.out.println(
+                          "Wrote parameters in second set:\n" + readparam);
+
+                }
+              } catch (Exception e)
+              {
+                e.printStackTrace();
+              }
+            }
+            WsJobParameters pgui = new WsJobParameters(null, lastserv,
+                    new JabaPreset(lastserv, pr), null);
+            JFrame jf = new JFrame(MessageManager
+                    .formatMessage("label.ws_parameters_for", new String[]
+                    { lastserv.getActionText() }));
+            JPanel cont = new JPanel(new BorderLayout());
+            pgui.validate();
+            cont.setPreferredSize(pgui.getPreferredSize());
+            cont.add(pgui, BorderLayout.CENTER);
+            jf.setLayout(new BorderLayout());
+            jf.add(cont, BorderLayout.CENTER);
+            jf.validate();
+            final Thread thr = Thread.currentThread();
+            jf.addWindowListener(new WindowListener()
+            {
+
+              @Override
+              public void windowActivated(WindowEvent e)
+              {
+                // TODO Auto-generated method stub
+
+              }
+
+              @Override
+              public void windowClosed(WindowEvent e)
+              {
+              }
+
+              @Override
+              public void windowClosing(WindowEvent e)
+              {
+                thr.interrupt();
+
+              }
+
+              @Override
+              public void windowDeactivated(WindowEvent e)
+              {
+                // TODO Auto-generated method stub
+
+              }
+
+              @Override
+              public void windowDeiconified(WindowEvent e)
+              {
+                // TODO Auto-generated method stub
+
+              }
+
+              @Override
+              public void windowIconified(WindowEvent e)
+              {
+                // TODO Auto-generated method stub
+
+              }
+
+              @Override
+              public void windowOpened(WindowEvent e)
+              {
+                // TODO Auto-generated method stub
+
+              }
+
+            });
+            jf.setVisible(true);
+            boolean inter = false;
+            while (!inter)
+            {
+              try
+              {
+                Thread.sleep(10000);
+              } catch (Exception e)
+              {
+                inter = true;
+              }
+              ;
+            }
+            jf.dispose();
+          }
+        }
+      }
+    }
+  }
+
+}
index fc36205..c70e721 100644 (file)
@@ -26,6 +26,7 @@ import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
 import jalview.util.MessageManager;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 
 import java.util.Iterator;
@@ -34,7 +35,6 @@ import java.util.List;
 import compbio.data.msa.SequenceAnnotation;
 import compbio.data.sequence.Score;
 import compbio.data.sequence.ScoreManager;
-import compbio.metadata.Argument;
 import compbio.metadata.ChunkHolder;
 import compbio.metadata.JobStatus;
 import compbio.metadata.JobSubmissionException;
@@ -50,7 +50,7 @@ public abstract class JabawsCalcWorker extends AbstractJabaCalcWorker
   protected ScoreManager scoremanager;
 
   public JabawsCalcWorker(Jws2Instance service, AlignFrame alignFrame,
-          WsParamSetI preset, List<Argument> paramset)
+          WsParamSetI preset, List<ArgumentI> paramset)
   {
     super(service, alignFrame, preset, paramset);
     aaservice = (SequenceAnnotation) service.service;
index ee36d4a..5ccef8a 100644 (file)
@@ -28,6 +28,7 @@ import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
 import jalview.util.MessageManager;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 
 import java.util.Iterator;
@@ -36,7 +37,6 @@ import java.util.List;
 import compbio.data.msa.MsaWS;
 import compbio.data.sequence.Alignment;
 import compbio.data.sequence.Score;
-import compbio.metadata.Argument;
 import compbio.metadata.ChunkHolder;
 import compbio.metadata.JobStatus;
 import compbio.metadata.JobSubmissionException;
@@ -60,7 +60,7 @@ public abstract class JabawsMsaInterfaceAlignCalcWorker
 
   public JabawsMsaInterfaceAlignCalcWorker(Jws2Instance service,
           AlignFrame alignFrame, WsParamSetI preset,
-          List<Argument> paramset)
+          List<ArgumentI> paramset)
   {
     this(alignFrame.getCurrentView(), alignFrame.alignPanel);
     this.guiProgress = alignFrame;
index 7d661a4..b4d498d 100644 (file)
@@ -23,15 +23,12 @@ package jalview.ws.jws2;
 import jalview.api.AlignCalcWorkerI;
 import jalview.bin.Cache;
 import jalview.gui.AlignFrame;
-import jalview.gui.Desktop;
 import jalview.gui.JvSwingUtils;
-import jalview.gui.WebserviceInfo;
-import jalview.gui.WsJobParameters;
 import jalview.util.MessageManager;
 import jalview.ws.jws2.dm.AAConSettings;
 import jalview.ws.jws2.dm.JabaWsParamSet;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
-import jalview.ws.params.ParamDatastoreI;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 import jalview.ws.uimodel.AlignAnalysisUIText;
 
@@ -45,8 +42,6 @@ import javax.swing.JMenuItem;
 import javax.swing.event.MenuEvent;
 import javax.swing.event.MenuListener;
 
-import compbio.metadata.Argument;
-
 /**
  * provides metadata for a jabaws2 service instance - resolves names, etc.
  * 
@@ -55,17 +50,10 @@ import compbio.metadata.Argument;
  */
 public abstract class Jws2Client extends jalview.ws.WSClient
 {
-  protected AlignFrame alignFrame;
-
-  protected WsParamSetI preset;
-
-  protected List<Argument> paramset;
-
   public Jws2Client(AlignFrame _alignFrame, WsParamSetI preset,
-          List<Argument> arguments)
+          List<ArgumentI> arguments)
   {
-    alignFrame = _alignFrame;
-    this.preset = preset;
+    super(_alignFrame, preset, arguments);
     if (preset != null)
     {
       if (!((preset instanceof JabaPreset)
@@ -86,61 +74,9 @@ public abstract class Jws2Client extends jalview.ws.WSClient
     }
     else
     {
-      // just provided with a bunch of arguments
-      this.paramset = arguments;
-    }
-  }
-
-  boolean processParams(Jws2Instance sh, boolean editParams)
-  {
-    return processParams(sh, editParams, false);
-  }
-
-  protected boolean processParams(Jws2Instance sh, boolean editParams,
-          boolean adjustingExisting)
-  {
-
-    if (editParams)
-    {
-      if (sh.paramStore == null)
-      {
-        sh.paramStore = new JabaParamStore(sh,
-                Desktop.getUserParameterStore());
-      }
-      WsJobParameters jobParams = (preset == null && paramset != null
-              && paramset.size() > 0)
-                      ? new WsJobParameters((ParamDatastoreI) null, sh,
-                              (WsParamSetI) null,
-                              paramset)
-                      : new WsJobParameters((ParamDatastoreI) null, sh,
-                              preset,
-                              (List<Argument>) null);
-      if (adjustingExisting)
-      {
-        jobParams.setName(MessageManager
-                .getString("label.adjusting_parameters_for_calculation"));
-      }
-      if (!jobParams.showRunDialog())
-      {
-        return false; // dialog cancelled
-      }
-
-      WsParamSetI prset = jobParams.getPreset();
-      if (prset == null)
-      {
-        paramset = jobParams.isServiceDefaults() ? null
-                : JabaParamStore
-                        .getJabafromJwsArgs(jobParams.getJobParams());
-        this.preset = null;
-      }
-      else
-      {
-        this.preset = prset; // ((JabaPreset) prset).p;
-        paramset = null; // no user supplied parameters.
-      }
+      // TODO: verify that paramset is compatible with the service being
+      // contacted
     }
-    return true;
-
   }
 
   public Jws2Client()
@@ -148,24 +84,6 @@ public abstract class Jws2Client extends jalview.ws.WSClient
     // anonymous constructor - used for headless method calls only
   }
 
-  protected WebserviceInfo setWebService(Jws2Instance serv, boolean b)
-  {
-    // serviceHandle = serv;
-    String serviceInstance = serv.action; // serv.service.getClass().getName();
-    WebServiceName = serv.serviceType;
-    WebServiceJobTitle = serv.getActionText();
-    WsURL = serv.hosturl;
-    if (!b)
-    {
-      return new WebserviceInfo(WebServiceJobTitle,
-              WebServiceJobTitle + " using service hosted at "
-                      + serv.hosturl + "\n"
-                      + (serv.description != null ? serv.description : ""),
-              false);
-    }
-    return null;
-  }
-
   /*
    * Jws2Instance serviceHandle; (non-Javadoc)
    * 
@@ -187,7 +105,7 @@ public abstract class Jws2Client extends jalview.ws.WSClient
   abstract void attachWSMenuEntry(JMenu wsmenu, final Jws2Instance service,
           final AlignFrame alignFrame);
 
-  protected boolean registerAAConWSInstance(final JMenu wsmenu,
+  static boolean registerAAConWSInstance(final JMenu wsmenu,
           final Jws2Instance service, final AlignFrame alignFrame)
   {
     final AlignAnalysisUIText aaui = service.getAlignAnalysisUI(); // null ; //
@@ -220,7 +138,7 @@ public abstract class Jws2Client extends jalview.ws.WSClient
       {
         AbstractJabaCalcWorker worker = (AbstractJabaCalcWorker) aaconClient
                 .get(0);
-        if (!worker.service.hosturl.equals(service.hosturl))
+        if (!worker.service.getHostURL().equals(service.getHostURL()))
         {
           // javax.swing.SwingUtilities.invokeLater(new Runnable()
           {
@@ -371,10 +289,11 @@ public abstract class Jws2Client extends jalview.ws.WSClient
     else
     {
       if (service != null
-              && !fave.getService().hosturl.equals(service.hosturl))
+              && !fave.getService().getHostURL()
+                      .equals(service.getHostURL()))
       {
-        Cache.log.debug("Changing AACon service to " + service.hosturl
-                + " from " + fave.getService().hosturl);
+        Cache.log.debug("Changing AACon service to " + service.getHostURL()
+                + " from " + fave.getService().getHostURL());
         fave.setService(service);
       }
     }
@@ -392,12 +311,12 @@ public abstract class Jws2Client extends jalview.ws.WSClient
   {
     if (service != null)
     {
-      if (!service.serviceType.toString()
+      if (!service.getServiceType()
               .equals(compbio.ws.client.Services.AAConWS.toString()))
       {
         Cache.log.warn(
                 "Ignoring invalid preferred service for AACon calculations (service type was "
-                        + service.serviceType + ")");
+                        + service.getServiceType() + ")");
         service = null;
       }
       else
index 5319eab..e4ff459 100644 (file)
@@ -178,7 +178,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     running = true;
 
     // first set up exclusion list if needed
-    final Set<String> ignoredServices = new HashSet<String>();
+    final Set<String> ignoredServices = new HashSet<>();
     for (String ignored : Cache
             .getDefault("IGNORED_JABAWS_SERVICETYPES", "").split("\\|"))
     {
@@ -217,9 +217,9 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     {
       validServiceUrls.removeAllElements();
     }
-    ArrayList<String> svctypes = new ArrayList<String>();
+    ArrayList<String> svctypes = new ArrayList<>();
 
-    List<JabaWsServerQuery> qrys = new ArrayList<JabaWsServerQuery>();
+    List<JabaWsServerQuery> qrys = new ArrayList<>();
     for (final String jwsserver : getServiceUrls())
     {
       JabaWsServerQuery squery = new JabaWsServerQuery(this, jwsserver);
@@ -281,14 +281,14 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
         for (Jws2Instance svc : services)
         {
           svcs[ipos] = svc;
-          spos[ipos++] = 1000 * svcUrls.indexOf(svc.getHost()) + 1
-                  + svctypes.indexOf(svc.serviceType);
+          spos[ipos++] = 1000 * svcUrls.indexOf(svc.getHostURL()) + 1
+                  + svctypes.indexOf(svc.getName());
         }
         jalview.util.QuickSort.sort(spos, svcs);
-        services = new Vector<Jws2Instance>();
+        services = new Vector<>();
         for (Jws2Instance svc : svcs)
         {
-          if (!ignoredServices.contains(svc.serviceType))
+          if (!ignoredServices.contains(svc.getName()))
           {
             services.add(svc);
           }
@@ -312,7 +312,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
   {
     if (services == null)
     {
-      services = new Vector<Jws2Instance>();
+      services = new Vector<>();
     }
     System.out.println(
             "Discovered service: " + jwsservers + " " + service.toString());
@@ -329,7 +329,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     service.hasParameters();
     if (validServiceUrls == null)
     {
-      validServiceUrls = new Vector<String>();
+      validServiceUrls = new Vector<>();
     }
     validServiceUrls.add(jwsservers);
   }
@@ -363,13 +363,14 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
      * for moment we keep them separate.
      */
     JMenu atpoint;
-    List<Jws2Instance> enumerableServices = new ArrayList<Jws2Instance>();
+    List<Jws2Instance> enumerableServices = new ArrayList<>();
     // jws2al.removeAll();
-    Map<String, Jws2Instance> preferredHosts = new HashMap<String, Jws2Instance>();
-    Map<String, List<Jws2Instance>> alternates = new HashMap<String, List<Jws2Instance>>();
+    Map<String, Jws2Instance> preferredHosts = new HashMap<>();
+    Map<String, List<Jws2Instance>> alternates = new HashMap<>();
     for (Jws2Instance service : services.toArray(new Jws2Instance[0]))
     {
-      if (!isRecalculable(service.action))
+      // TODO: check this behaves with refactored serviceType to getName
+      if (!isRecalculable(service.getName()))
       {
         // add 'one shot' services to be displayed using the classic menu
         // structure
@@ -377,28 +378,28 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
       }
       else
       {
-        if (!preferredHosts.containsKey(service.serviceType))
+        if (!preferredHosts.containsKey(service.getName()))
         {
           Jws2Instance preferredInstance = getPreferredServiceFor(
-                  alignFrame, service.serviceType);
+                  alignFrame, service.getName());
           if (preferredInstance != null)
           {
-            preferredHosts.put(service.serviceType, preferredInstance);
+            preferredHosts.put(service.getName(), preferredInstance);
           }
           else
           {
-            preferredHosts.put(service.serviceType, service);
+            preferredHosts.put(service.getName(), service);
           }
         }
-        List<Jws2Instance> ph = alternates.get(service.serviceType);
-        if (preferredHosts.get(service.serviceType) != service)
+        List<Jws2Instance> ph = alternates.get(service.getName());
+        if (preferredHosts.get(service.getName()) != service)
         {
           if (ph == null)
           {
-            ph = new ArrayList<Jws2Instance>();
+            ph = new ArrayList<>();
           }
           ph.add(service);
-          alternates.put(service.serviceType, ph);
+          alternates.put(service.getName(), ph);
         }
       }
 
@@ -409,14 +410,15 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     // and the instantaneous services
     for (final Jws2Instance service : preferredHosts.values())
     {
-      atpoint = JvSwingUtils.findOrCreateMenu(jws2al, service.action);
+      atpoint = JvSwingUtils.findOrCreateMenu(jws2al,
+              service.getServiceType());
       JMenuItem hitm;
       if (atpoint.getItemCount() > 1)
       {
         // previous service of this type already present
         atpoint.addSeparator();
       }
-      atpoint.add(hitm = new JMenuItem(service.getHost()));
+      atpoint.add(hitm = new JMenuItem(service.getHostURL()));
       hitm.setForeground(Color.blue);
       hitm.addActionListener(new ActionListener()
       {
@@ -424,23 +426,23 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
         @Override
         public void actionPerformed(ActionEvent e)
         {
-          Desktop.showUrl(service.getHost());
+          Desktop.showUrl(service.getHostURL());
         }
       });
       hitm.setToolTipText(JvSwingUtils.wrapTooltip(false,
               MessageManager.getString("label.open_jabaws_web_page")));
 
       service.attachWSMenuEntry(atpoint, alignFrame);
-      if (alternates.containsKey(service.serviceType))
+      if (alternates.containsKey(service.getName()))
       {
         atpoint.add(hitm = new JMenu(
                 MessageManager.getString("label.switch_server")));
         hitm.setToolTipText(JvSwingUtils.wrapTooltip(false,
                 MessageManager.getString("label.choose_jabaws_server")));
-        for (final Jws2Instance sv : alternates.get(service.serviceType))
+        for (final Jws2Instance sv : alternates.get(service.getName()))
         {
           JMenuItem itm;
-          hitm.add(itm = new JMenuItem(sv.getHost()));
+          hitm.add(itm = new JMenuItem(sv.getHostURL()));
           itm.setForeground(Color.blue);
           itm.addActionListener(new ActionListener()
           {
@@ -453,8 +455,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
                 @Override
                 public void run()
                 {
-                  setPreferredServiceFor(alignFrame, sv.serviceType,
-                          sv.action, sv);
+                  setPreferredServiceFor(alignFrame, sv.getName(),
+                          sv.getServiceType(), sv);
                   changeSupport.firePropertyChange("services",
                           new Vector<Jws2Instance>(), services);
                 };
@@ -483,18 +485,19 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
      */
     JMenu atpoint;
 
-    List<String> hostLabels = new ArrayList<String>();
-    Hashtable<String, String> lasthostFor = new Hashtable<String, String>();
-    Hashtable<String, ArrayList<Jws2Instance>> hosts = new Hashtable<String, ArrayList<Jws2Instance>>();
-    ArrayList<String> hostlist = new ArrayList<String>();
+    List<String> hostLabels = new ArrayList<>();
+    Hashtable<String, String> lasthostFor = new Hashtable<>();
+    Hashtable<String, ArrayList<Jws2Instance>> hosts = new Hashtable<>();
+    ArrayList<String> hostlist = new ArrayList<>();
     for (Jws2Instance service : enumerableServices)
     {
-      ArrayList<Jws2Instance> hostservices = hosts.get(service.getHost());
+      ArrayList<Jws2Instance> hostservices = hosts
+              .get(service.getHostURL());
       if (hostservices == null)
       {
-        hosts.put(service.getHost(),
-                hostservices = new ArrayList<Jws2Instance>());
-        hostlist.add(service.getHost());
+        hosts.put(service.getHostURL(),
+                hostservices = new ArrayList<>());
+        hostlist.add(service.getHostURL());
       }
       hostservices.add(service);
     }
@@ -506,13 +509,14 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
       String sortbytype[] = new String[orderedsvcs.length];
       for (int i = 0; i < sortbytype.length; i++)
       {
-        sortbytype[i] = orderedsvcs[i].serviceType;
+        sortbytype[i] = orderedsvcs[i].getName();
       }
       jalview.util.QuickSort.sort(sortbytype, orderedsvcs);
       for (final Jws2Instance service : orderedsvcs)
       {
-        atpoint = JvSwingUtils.findOrCreateMenu(jws2al, service.action);
-        String type = service.serviceType;
+        atpoint = JvSwingUtils.findOrCreateMenu(jws2al,
+                service.getAction());
+        String type = service.getName();
         if (byhost)
         {
           atpoint = JvSwingUtils.findOrCreateMenu(atpoint, host);
@@ -532,7 +536,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
           }
         }
         if (!byhost && !hostLabels.contains(
-                host + service.serviceType + service.getActionText()))
+                host + service.getName() + service.getActionText()))
         // !hostLabels.contains(host + (bytype ?
         // service.serviceType+service.getActionText() : "")))
         {
@@ -549,8 +553,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
           {
             hostLabels.add(host);
           }
-          if (lasthostFor.get(service.action) == null
-                  || !lasthostFor.get(service.action).equals(host))
+          if (lasthostFor.get(service.getAction()) == null
+                  || !lasthostFor.get(service.getAction()).equals(host))
           {
             atpoint.add(hitm = new JMenuItem(host));
             hitm.setForeground(Color.blue);
@@ -560,16 +564,16 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                Desktop.showUrl(service.getHost());
+                Desktop.showUrl(service.getHostURL());
               }
             });
             hitm.setToolTipText(
                     JvSwingUtils.wrapTooltip(true, MessageManager
                             .getString("label.open_jabaws_web_page")));
-            lasthostFor.put(service.action, host);
+            lasthostFor.put(service.getAction(), host);
           }
           hostLabels.add(
-                  host + service.serviceType + service.getActionText());
+                  host + service.getName() + service.getActionText());
         }
 
         service.attachWSMenuEntry(atpoint, alignFrame);
@@ -581,7 +585,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
   {
     if (args.length > 0)
     {
-      testUrls = new ArrayList<String>();
+      testUrls = new ArrayList<>();
       for (String url : args)
       {
         testUrls.add(url);
@@ -603,7 +607,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
                   for (Jws2Instance instance : getDiscoverer().services)
                   {
                     System.out.println("Service " + i++ + " "
-                            + instance.getClass() + "@" + instance.getHost()
+                            + instance.getClass() + "@"
+                            + instance.getHostURL()
                             + ": " + instance.getActionText());
                   }
 
@@ -685,7 +690,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
       // return test urls, if there are any, instead of touching cache
       return testUrls;
     }
-    List<String> urls = new ArrayList<String>();
+    List<String> urls = new ArrayList<>();
 
     if (this.preferredUrl != null)
     {
@@ -733,8 +738,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
 
   public Vector<Jws2Instance> getServices()
   {
-    return (services == null) ? new Vector<Jws2Instance>()
-            : new Vector<Jws2Instance>(services);
+    return (services == null) ? new Vector<>()
+            : new Vector<>(services);
   }
 
   /**
@@ -839,7 +844,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
   {
     if (urlsWithoutServices == null)
     {
-      urlsWithoutServices = new Vector<String>();
+      urlsWithoutServices = new Vector<>();
     }
 
     if ((invalidServiceUrls == null
@@ -859,7 +864,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
   {
     if (invalidServiceUrls == null)
     {
-      invalidServiceUrls = new Vector<String>();
+      invalidServiceUrls = new Vector<>();
     }
     if (!invalidServiceUrls.contains(jwsservers))
     {
@@ -947,14 +952,16 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
    */
   public Jws2Instance getPreferredServiceFor(String[] serviceURLs)
   {
-    HashSet<String> urls = new HashSet<String>();
+    HashSet<String> urls = new HashSet<>();
     urls.addAll(Arrays.asList(serviceURLs));
     Jws2Instance match = null;
     if (services != null)
     {
       for (Jws2Instance svc : services)
       {
-        if (urls.contains(svc.getServiceTypeURI()))
+        // TODO getNameURI Should return a versioned URI for the service, but
+        // doesn't as of 2.11
+        if (urls.contains(svc.getNameURI()))
         {
           if (match == null)
           {
@@ -974,20 +981,21 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     return match;
   }
 
-  Map<String, Map<String, String>> preferredServiceMap = new HashMap<String, Map<String, String>>();;
+  Map<String, Map<String, String>> preferredServiceMap = new HashMap<>();;
 
   /**
-   * get current preferred service of the given type, or global default
+   * get current preferred endpoint of the given Jabaws service, or global
+   * default
    * 
    * @param af
    *          null or a specific alignFrame
-   * @param serviceType
-   *          Jws2Instance.serviceType for service
+   * @param serviceName
+   *          Jws2Instance.getName() for service
    * @return null if no service of this type is available, the preferred service
    *         for the serviceType and af if specified and if defined.
    */
   public Jws2Instance getPreferredServiceFor(AlignFrame af,
-          String serviceType)
+          String serviceName)
   {
     String serviceurl = null;
     synchronized (preferredServiceMap)
@@ -1001,16 +1009,16 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
       }
       if (prefmap != null)
       {
-        serviceurl = prefmap.get(serviceType);
+        serviceurl = prefmap.get(serviceName);
       }
 
     }
     Jws2Instance response = null;
     for (Jws2Instance svc : services)
     {
-      if (svc.serviceType.equals(serviceType))
+      if (svc.getName().equals(serviceName))
       {
-        if (serviceurl == null || serviceurl.equals(svc.getHost()))
+        if (serviceurl == null || serviceurl.equals(svc.getHostURL()))
         {
           response = svc;
           break;
@@ -1020,22 +1028,23 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     return response;
   }
 
-  public void setPreferredServiceFor(AlignFrame af, String serviceType,
+  public void setPreferredServiceFor(AlignFrame af, String serviceName,
           String serviceAction, Jws2Instance selectedServer)
   {
+    // TODO: pull out and generalise for the selectedServer's attributes
     String afid = (af == null) ? "" : af.getViewport().getSequenceSetId();
     if (preferredServiceMap == null)
     {
-      preferredServiceMap = new HashMap<String, Map<String, String>>();
+      preferredServiceMap = new HashMap<>();
     }
     Map<String, String> prefmap = preferredServiceMap.get(afid);
     if (prefmap == null)
     {
-      prefmap = new HashMap<String, String>();
+      prefmap = new HashMap<>();
       preferredServiceMap.put(afid, prefmap);
     }
-    prefmap.put(serviceType, selectedServer.getHost());
-    prefmap.put(serviceAction, selectedServer.getHost());
+    prefmap.put(serviceName, selectedServer.getHostURL());
+    prefmap.put(serviceAction, selectedServer.getHostURL());
   }
 
   public void setPreferredServiceFor(String serviceType,
index 7e68d3b..7a3d9d3 100644 (file)
@@ -27,7 +27,13 @@ import jalview.gui.Desktop;
 import jalview.gui.JvOptionPane;
 import jalview.gui.JvSwingUtils;
 import jalview.util.MessageManager;
+import jalview.ws.WSMenuEntryProviderI;
+import jalview.ws.api.JalviewServiceEndpointProviderI;
+import jalview.ws.api.MultipleSequenceAlignmentI;
+import jalview.ws.api.ServiceWithParameters;
+import jalview.ws.gui.MsaWSThread;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 
 import java.awt.event.ActionEvent;
@@ -40,23 +46,28 @@ import javax.swing.JMenu;
 import javax.swing.JMenuItem;
 import javax.swing.ToolTipManager;
 
-import compbio.data.msa.MsaWS;
-import compbio.metadata.Argument;
-
 /**
- * DOCUMENT ME!
+ * MsaWSClient
+ * 
+ * Instantiates web service menu items for multiple alignment services, and
+ * holds logic for constructing a web service thread.
  * 
- * @author $author$
+ * TODO remove dependency on Jws2Client methods for creating AACon service UI
+ * elements.
+ * 
+ * @author Jim Procter et al
  * @version $Revision$
  */
-public class MsaWSClient extends Jws2Client
+public class MsaWSClient extends Jws2Client implements WSMenuEntryProviderI
 {
   /**
-   * server is a WSDL2Java generated stub for an archetypal MsaWSI service.
+   * server is a proxy class implementing the core methods for submitting,
+   * monitoring and retrieving results from a multiple sequence alignment
+   * service
    */
-  MsaWS server;
+  MultipleSequenceAlignmentI server;
 
-  public MsaWSClient(Jws2Instance sh, String altitle,
+  public MsaWSClient(ServiceWithParameters sh, String altitle,
           jalview.datamodel.AlignmentView msa, boolean submitGaps,
           boolean preserveOrder, AlignmentI seqdataset,
           AlignFrame _alignFrame)
@@ -66,7 +77,8 @@ public class MsaWSClient extends Jws2Client
     // TODO Auto-generated constructor stub
   }
 
-  public MsaWSClient(Jws2Instance sh, WsParamSetI preset, String altitle,
+  public MsaWSClient(ServiceWithParameters sh, WsParamSetI preset,
+          String altitle,
           jalview.datamodel.AlignmentView msa, boolean submitGaps,
           boolean preserveOrder, AlignmentI seqdataset,
           AlignFrame _alignFrame)
@@ -92,8 +104,8 @@ public class MsaWSClient extends Jws2Client
    *          DOCUMENT ME!
    */
 
-  public MsaWSClient(Jws2Instance sh, WsParamSetI preset,
-          List<Argument> arguments, boolean editParams, String altitle,
+  public MsaWSClient(ServiceWithParameters sh, WsParamSetI preset,
+          List<ArgumentI> arguments, boolean editParams, String altitle,
           jalview.datamodel.AlignmentView msa, boolean submitGaps,
           boolean preserveOrder, AlignmentI seqdataset,
           AlignFrame _alignFrame)
@@ -104,25 +116,29 @@ public class MsaWSClient extends Jws2Client
       return;
     }
 
-    if (!(sh.service instanceof MsaWS))
+    if (!(sh instanceof JalviewServiceEndpointProviderI
+            && ((JalviewServiceEndpointProviderI) sh)
+                    .getEndpoint() instanceof MultipleSequenceAlignmentI))
     {
       // redundant at mo - but may change
       JvOptionPane.showMessageDialog(Desktop.desktop,
               MessageManager.formatMessage(
                       "label.service_called_is_not_msa_service",
                       new String[]
-                      { sh.serviceType }),
+                      { sh.getName() }),
               MessageManager.getString("label.internal_jalview_error"),
               JvOptionPane.WARNING_MESSAGE);
 
       return;
     }
-    server = (MsaWS) sh.service;
+    serviceHandle = sh;
+    server = (MultipleSequenceAlignmentI) ((JalviewServiceEndpointProviderI) sh)
+            .getEndpoint();
     if ((wsInfo = setWebService(sh, false)) == null)
     {
       JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
               .formatMessage("label.msa_service_is_unknown", new String[]
-              { sh.serviceType }),
+              { sh.getName() }),
               MessageManager.getString("label.internal_jalview_error"),
               JvOptionPane.WARNING_MESSAGE);
 
@@ -226,9 +242,20 @@ public class MsaWSClient extends Jws2Client
       // Alignment dependent analysis calculation WS gui
       return;
     }
+    serviceHandle = service;
     setWebService(service, true); // headless
+    attachWSMenuEntry(rmsawsmenu, alignFrame);
+  }
+
+  @Override
+  public void attachWSMenuEntry(JMenu wsmenu, AlignFrame alignFrame)
+  {
     boolean finished = true, submitGaps = false;
-    JMenu msawsmenu = rmsawsmenu;
+    /**
+     * temp variables holding msa service submenu or root service menu
+     */
+    JMenu msawsmenu = wsmenu;
+    JMenu rmsawsmenu = wsmenu;
     String svcname = WebServiceName;
     if (svcname.endsWith("WS"))
     {
@@ -241,7 +268,8 @@ public class MsaWSClient extends Jws2Client
       rmsawsmenu.add(msawsmenu);
       calcName = "";
     }
-    boolean hasparams = service.hasParameters();
+    boolean hasparams = serviceHandle.hasParameters();
+    ServiceWithParameters service = (ServiceWithParameters) serviceHandle;
     do
     {
       String action = "Align ";
index f9e597f..7d6d341 100644 (file)
@@ -25,6 +25,7 @@ import jalview.datamodel.Annotation;
 import jalview.gui.AlignFrame;
 import jalview.util.MessageManager;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 import jalview.ws.uimodel.AlignAnalysisUIText;
 
@@ -40,7 +41,6 @@ import compbio.data.sequence.RNAStructReader.AlifoldResult;
 import compbio.data.sequence.RNAStructScoreManager;
 import compbio.data.sequence.Range;
 import compbio.data.sequence.Score;
-import compbio.metadata.Argument;
 
 /**
  * Client for the JABA RNA Alifold Service
@@ -61,11 +61,11 @@ public class RNAalifoldClient extends JabawsCalcWorker
   boolean bpScores;
 
   public RNAalifoldClient(Jws2Instance sh, AlignFrame alignFrame,
-          WsParamSetI preset, List<Argument> paramset)
+          WsParamSetI preset, List<ArgumentI> paramset)
   {
     super(sh, alignFrame, preset, paramset);
     af = alignFrame;
-    methodName = sh.serviceType;
+    methodName = sh.getName();
     alignedSeqs = true;
     submitGaps = true;
     nucleotidesAllowed = true;
@@ -112,7 +112,7 @@ public class RNAalifoldClient extends JabawsCalcWorker
     if (immediate || !calcMan.isWorking(this) && scoremanager != null)
     {
 
-      List<AlignmentAnnotation> ourAnnot = new ArrayList<AlignmentAnnotation>();
+      List<AlignmentAnnotation> ourAnnot = new ArrayList<>();
 
       // Unpack the ScoreManager
       List<String> structs = ((RNAStructScoreManager) scoremanager)
@@ -231,7 +231,7 @@ public class RNAalifoldClient extends JabawsCalcWorker
 
       // The base pair probabilities are stored in a set in scoreholder. we want
       // a map
-      LinkedHashMap<Range, Float> basePairs = new LinkedHashMap<Range, Float>();
+      LinkedHashMap<Range, Float> basePairs = new LinkedHashMap<>();
       for (Score score : data)
       {
         // The Score objects contain a set of size one containing the range and
@@ -377,7 +377,7 @@ public class RNAalifoldClient extends JabawsCalcWorker
   private LinkedHashMap<Range, Float> isContact(
           LinkedHashMap<Range, Float> basePairs, int i)
   {
-    LinkedHashMap<Range, Float> contacts = new LinkedHashMap<Range, Float>();
+    LinkedHashMap<Range, Float> contacts = new LinkedHashMap<>();
 
     for (Range contact : basePairs.keySet())
     {
index 45bddac..eb08848 100644 (file)
@@ -128,7 +128,7 @@ public class SequenceAnnotationWSClient extends Jws2Client
         worker.updateParameters(this.preset, paramset);
       }
     }
-    if (sh.action.toLowerCase().contains("disorder"))
+    if (sh.getAction().toLowerCase().contains("disorder"))
     {
       // build IUPred style client. take sequences, returns annotation per
       // sequence.
@@ -145,7 +145,7 @@ public class SequenceAnnotationWSClient extends Jws2Client
   public SequenceAnnotationWSClient(AAConSettings fave,
           AlignFrame alignFrame, boolean b)
   {
-    super(alignFrame, fave.getPreset(), fave.getJobArgset());
+    super(alignFrame, fave.getPreset(), fave.getArgumentSet());
     initSequenceAnnotationWSClient(fave.getService(), alignFrame,
             fave.getPreset(), b);
   }
@@ -156,6 +156,7 @@ public class SequenceAnnotationWSClient extends Jws2Client
    * @see jalview.ws.jws2.Jws2Client#attachWSMenuEntry(javax.swing.JMenu,
    * jalview.ws.jws2.jabaws2.Jws2Instance, jalview.gui.AlignFrame)
    */
+  @Override
   public void attachWSMenuEntry(JMenu wsmenu, final Jws2Instance service,
           final AlignFrame alignFrame)
   {
@@ -166,8 +167,8 @@ public class SequenceAnnotationWSClient extends Jws2Client
     }
     boolean hasparams = service.hasParameters();
     // Assume name ends in WS
-    String calcName = service.serviceType.substring(0,
-            service.serviceType.length() - 2);
+    String calcName = service.getName().substring(0,
+            service.getName().length() - 2);
 
     JMenuItem annotservice = new JMenuItem(MessageManager.formatMessage(
             "label.calcname_with_default_settings", new String[]
@@ -193,6 +194,7 @@ public class SequenceAnnotationWSClient extends Jws2Client
 
       annotservice.addActionListener(new ActionListener()
       {
+        @Override
         public void actionPerformed(ActionEvent e)
         {
           new SequenceAnnotationWSClient(service, alignFrame, null, true);
@@ -217,6 +219,7 @@ public class SequenceAnnotationWSClient extends Jws2Client
                   + "</strong><br/>" + preset.getDescription()));
           methodR.addActionListener(new ActionListener()
           {
+            @Override
             public void actionPerformed(ActionEvent e)
             {
               new SequenceAnnotationWSClient(service, alignFrame, preset,
index 708787e..5cc8f66 100644 (file)
@@ -76,8 +76,8 @@ public class AAConSettings extends jalview.ws.params.AutoCalcSetting
         preset = pr;
         return;
       }
-      List<ArgumentI> oldargs = new ArrayList<ArgumentI>(),
-              newargs = new ArrayList<ArgumentI>();
+      List<ArgumentI> oldargs = new ArrayList<>(),
+              newargs = new ArrayList<>();
       oldargs.addAll(preset.getArguments());
       // need to compare parameters
       for (ArgumentI newparg : pr.getArguments())
@@ -112,6 +112,7 @@ public class AAConSettings extends jalview.ws.params.AutoCalcSetting
             : JabaParamStore.getJwsArgsfromJaba(jobArgset);
   }
 
+  @Override
   public String getWsParamFile()
   {
     List<Option> opts = null;
@@ -142,7 +143,7 @@ public class AAConSettings extends jalview.ws.params.AutoCalcSetting
   @Override
   public String getServiceURI()
   {
-    return service.getServiceTypeURI();
+    return service.getNameURI();
   }
 
   @Override
diff --git a/src/jalview/ws/jws2/jabaws2/JabawsMsaInstance.java b/src/jalview/ws/jws2/jabaws2/JabawsMsaInstance.java
new file mode 100644 (file)
index 0000000..80de5b2
--- /dev/null
@@ -0,0 +1,285 @@
+package jalview.ws.jws2.jabaws2;
+
+import jalview.bin.Cache;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+import jalview.gui.WebserviceInfo;
+import jalview.util.MessageManager;
+import jalview.ws.api.CancellableI;
+import jalview.ws.api.JobId;
+import jalview.ws.api.MultipleSequenceAlignmentI;
+import jalview.ws.gui.WsJob;
+import jalview.ws.gui.WsJob.JobState;
+import jalview.ws.jws2.JabaParamStore;
+import jalview.ws.jws2.JabaPreset;
+import jalview.ws.jws2.dm.JabaWsParamSet;
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.InvalidArgumentException;
+import jalview.ws.params.WsParamSetI;
+
+import java.io.IOError;
+import java.rmi.ServerError;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import compbio.data.msa.MsaWS;
+import compbio.data.sequence.Alignment;
+import compbio.data.sequence.FastaSequence;
+import compbio.metadata.Argument;
+import compbio.metadata.ChunkHolder;
+import compbio.metadata.JobStatus;
+import compbio.metadata.Preset;
+import compbio.metadata.ResultNotAvailableException;
+
+public class JabawsMsaInstance
+        implements MultipleSequenceAlignmentI, CancellableI
+{
+  /**
+   * our service instance handler generated by the discoverer
+   */
+  Jws2Instance our;
+
+  MsaWS<?> service;
+
+  @Override
+  public JobId align(List<SequenceI> toalign, WsParamSetI parameters,
+          List<ArgumentI> arguments) throws Throwable
+  {
+    List<compbio.data.sequence.FastaSequence> seqs = new ArrayList<>();
+    for (SequenceI seq : toalign)
+    {
+      seqs.add(new FastaSequence(seq.getName(), seq.getSequenceAsString()));
+    }
+    String jobid = null;
+    if (parameters != null)
+    {
+      if (parameters instanceof JabaPreset)
+      {
+        jobid = service.presetAlign(seqs,
+                ((JabaPreset) parameters).getJabaPreset());
+      }
+      else
+      {
+        jobid = service.customAlign(seqs, JabaParamStore
+                .getJabafromJwsArgs(parameters.getArguments()));
+      }
+    }
+    else if (arguments != null && arguments.size() > 0)
+    {
+      jobid = service.customAlign(seqs,
+              JabaParamStore.getJabafromJwsArgs(arguments));
+    }
+    else
+    {
+      jobid = service.align(seqs);
+    }
+
+    if (jobid == null)
+    {
+      return null;
+    }
+    return new JobId(our.getServiceType(), our.getName(), jobid);
+  }
+
+  @Override
+  public AlignmentI getAlignmentFor(JobId jobId)
+          throws InvalidArgumentException, ServerError, IOError
+  {
+    Alignment alignment = null;
+    try
+    {
+      alignment = service.getResult(jobId.getJobId());
+    } catch (ResultNotAvailableException rnotav)
+    {
+
+      // TODO - migrate JABA exception
+      // throw new ServerError("Couldn't get result for job",rnotav);
+    }
+    SequenceI[] alseqs;
+    int alseq_l = 0;
+    if (alignment.getSequences().size() == 0)
+    {
+      return null;
+    }
+
+    alseqs = new SequenceI[alignment.getSequences().size()];
+    for (compbio.data.sequence.FastaSequence seq : alignment.getSequences())
+    {
+      alseqs[alseq_l++] = new Sequence(seq.getId(), seq.getSequence());
+    }
+    AlignmentI jv_al = new jalview.datamodel.Alignment(alseqs);
+    jv_al.setGapCharacter(alignment.getMetadata().getGapchar());
+    return jv_al;
+
+  }
+
+  public JabawsMsaInstance(Jws2Instance handle)
+  {
+    our = handle;
+    service = (MsaWS<?>) our.service;
+  }
+
+  @Override
+  public boolean cancel(WsJob job)
+  {
+    service.cancelJob(job.getJobId());
+    // if the Jaba server indicates the job can't be cancelled, its
+    // because its running on the server's local execution engine
+    // so we just close the window anyway.
+
+    return true;
+  }
+
+  Map<JobStatus, JobState> jwsState = new HashMap<>();
+  {
+    jwsState.put(JobStatus.CANCELLED, JobState.CANCELLED);
+    jwsState.put(JobStatus.COLLECTED, JobState.FINISHED);
+    jwsState.put(JobStatus.FAILED, JobState.FAILED);
+    jwsState.put(JobStatus.FINISHED, JobState.FINISHED);
+    jwsState.put(JobStatus.PENDING, JobState.QUEUED);
+    jwsState.put(JobStatus.RUNNING, JobState.RUNNING);
+    jwsState.put(JobStatus.STARTED, JobState.RUNNING);
+    jwsState.put(JobStatus.SUBMITTED, JobState.SUBMITTED);
+    jwsState.put(JobStatus.UNDEFINED, JobState.UNKNOWN);
+  }
+  @Override
+  public void updateStatus(WsJob job)
+  {
+    JobStatus jwsstatus = service.getJobStatus(job.getJobId());
+    job.setState(jwsState.get(jwsstatus));
+  }
+
+  @Override
+  public boolean updateJobProgress(WsJob job) throws Exception
+  {
+    StringBuilder response = new StringBuilder(job.getStatus());
+    long lastchunk = job.getNextChunk();
+    boolean changed = false;
+    do
+    {
+      ChunkHolder chunk = service.pullExecStatistics(job.getJobId(),
+              lastchunk);
+      if (chunk != null)
+      {
+        changed |= chunk.getChunk().length() > 0;
+        response.append(chunk.getChunk());
+        lastchunk = chunk.getNextPosition();
+        try
+        {
+          Thread.sleep(50);
+        } catch (InterruptedException x)
+        {
+        }
+        ;
+      }
+      ;
+      job.setnextChunk(lastchunk);
+    } while (lastchunk >= 0 && job.getNextChunk() != lastchunk);
+    if (job instanceof WsJob)
+    {
+      // TODO decide if WsJob will be the bean for all ng-webservices
+      job.setStatus(response.toString());
+    }
+    return changed;
+  }
+
+  public boolean isPresetJob(WsJob job)
+  {
+    return job.getPreset() != null && job.getPreset() instanceof JabaPreset;
+  }
+
+  public Preset getServerPreset(WsJob job)
+  {
+    return (isPresetJob(job))
+            ? ((JabaPreset) job.getPreset()).getJabaPreset()
+            : null;
+  }
+
+  public List<Argument> getJabaArguments(WsParamSetI preset)
+  {
+    List<Argument> newargs = new ArrayList<>();
+    if (preset != null)
+    {
+      if (preset instanceof JabaWsParamSet)
+      {
+        newargs.addAll(((JabaWsParamSet) preset).getjabaArguments());
+      }
+      else
+      {
+        newargs.addAll(
+                JabaParamStore.getJabafromJwsArgs(preset.getArguments()));
+      }
+    }
+    return newargs;
+  }
+
+  @Override
+  public boolean handleSubmitError(Throwable _lex, WsJob j,
+          WebserviceInfo wsInfo) throws Exception, Error
+  {
+    if (_lex instanceof compbio.metadata.UnsupportedRuntimeException)
+    {
+      wsInfo.appendProgressText(MessageManager.formatMessage(
+              "info.job_couldnt_be_run_server_doesnt_support_program",
+              new String[]
+              { _lex.getMessage() }));
+      wsInfo.warnUser(_lex.getMessage(),
+              MessageManager.getString("warn.service_not_supported"));
+      wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
+      wsInfo.setStatus(j.getJobnum(),
+              WebserviceInfo.STATE_STOPPED_SERVERERROR);
+      return true;
+    }
+    if (_lex instanceof compbio.metadata.LimitExceededException)
+    {
+      wsInfo.appendProgressText(MessageManager.formatMessage(
+              "info.job_couldnt_be_run_exceeded_hard_limit", new String[]
+              { _lex.getMessage() }));
+      wsInfo.warnUser(_lex.getMessage(),
+              MessageManager.getString("warn.input_is_too_big"));
+      wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
+      wsInfo.setStatus(j.getJobnum(), WebserviceInfo.STATE_STOPPED_ERROR);
+      return true;
+    }
+    if (_lex instanceof compbio.metadata.WrongParameterException)
+    {
+      wsInfo.warnUser(_lex.getMessage(),
+              MessageManager.getString("warn.invalid_job_param_set"));
+      wsInfo.appendProgressText(MessageManager.formatMessage(
+              "info.job_couldnt_be_run_incorrect_param_setting",
+              new String[]
+              { _lex.getMessage() }));
+      wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
+      wsInfo.setStatus(j.getJobnum(), WebserviceInfo.STATE_STOPPED_ERROR);
+      return true;
+    }
+    // pass on to generic error handler
+    return false;
+  }
+
+  @Override
+  public boolean handleCollectionException(Exception ex, WsJob msjob,
+          WebserviceInfo wsInfo)
+  {
+    if (ex instanceof compbio.metadata.ResultNotAvailableException)
+    {
+      // job has failed for some reason - probably due to invalid
+      // parameters
+      Cache.log.debug(
+              "Results not available for finished job - marking as broken job.",
+              ex);
+      String status = msjob.getStatus();
+
+      msjob.setStatus(status
+              +
+              "\nResult not available. Probably due to invalid input or parameter settings. Server error message below:\n\n"
+                      + ex.getLocalizedMessage());
+      msjob.setState(WsJob.JobState.BROKEN);
+      return true;
+    }
+    return false;
+  }
+}
index e092192..143bc1c 100644 (file)
@@ -23,10 +23,13 @@ package jalview.ws.jws2.jabaws2;
 import jalview.gui.AlignFrame;
 import jalview.gui.Desktop;
 import jalview.util.MessageManager;
+import jalview.ws.api.JalviewServiceEndpointProviderI;
+import jalview.ws.api.ServiceWithParameters;
 import jalview.ws.jws2.JabaParamStore;
 import jalview.ws.jws2.MsaWSClient;
 import jalview.ws.jws2.SequenceAnnotationWSClient;
 import jalview.ws.params.ParamDatastoreI;
+import jalview.ws.params.ParamManager;
 
 import java.io.Closeable;
 
@@ -38,18 +41,12 @@ import compbio.data.msa.SequenceAnnotation;
 import compbio.metadata.PresetManager;
 import compbio.metadata.RunnerConfig;
 
-public class Jws2Instance implements AutoCloseable
+public class Jws2Instance extends ServiceWithParameters
+        implements JalviewServiceEndpointProviderI, AutoCloseable
 {
-  public String hosturl;
-
-  public String serviceType;
-
-  public String action;
 
   public JABAService service;
 
-  public String description;
-
   public String docUrl;
 
   /**
@@ -69,12 +66,8 @@ public class Jws2Instance implements AutoCloseable
   public Jws2Instance(String hosturl, String serviceType, String action,
           String description, JABAService service)
   {
-    super();
-    this.hosturl = hosturl;
-    this.serviceType = serviceType;
+    super(action, action, serviceType, description, hosturl);
     this.service = service;
-    this.action = action;
-    this.description = description;
     int p = description.indexOf("MORE INFORMATION:");
     if (p > -1)
     {
@@ -115,32 +108,12 @@ public class Jws2Instance implements AutoCloseable
       } catch (Exception ex)
       {
         System.err.println("Exception when retrieving presets for service "
-                + serviceType + " at " + hosturl);
+                + getServiceType() + " at " + getHostURL());
       }
     }
     return presets;
   }
 
-  public String getHost()
-  {
-    return hosturl;
-    /*
-     * try { URL serviceurl = new URL(hosturl); if (serviceurl.getPort()!=80) {
-     * return serviceurl.getHost()+":"+serviceurl.getPort(); } return
-     * serviceurl.getHost(); } catch (Exception e) {
-     * System.err.println("Failed to parse service URL '" + hosturl +
-     * "' as a valid URL!"); } return null;
-     */
-  }
-
-  /**
-   * @return short description of what the service will do
-   */
-  public String getActionText()
-  {
-    return action + " with " + serviceType;
-  }
-
   /**
    * non-thread safe - blocks whilst accessing service to get complete set of
    * available options and parameters
@@ -160,7 +133,7 @@ public class Jws2Instance implements AutoCloseable
     throw new Error(MessageManager.formatMessage(
             "error.implementation_error_runner_config_not_available",
             new String[]
-            { serviceType, service.getClass().toString() }));
+            { getServiceType(), service.getClass().toString() }));
   }
 
   @Override
@@ -179,6 +152,7 @@ public class Jws2Instance implements AutoCloseable
     // super.finalize();
   }
 
+  @Override
   public ParamDatastoreI getParamStore()
   {
     if (paramStore == null)
@@ -200,15 +174,19 @@ public class Jws2Instance implements AutoCloseable
 
   public String getUri()
   {
+    // TODO verify that service parameter sets in projects are consistent with
+    // Jalview 2.10.4
     // this is only valid for Jaba 1.0 - this formula might have to change!
-    return hosturl
-            + (hosturl.lastIndexOf("/") == (hosturl.length() - 1) ? ""
+    return getHostURL()
+            + (getHostURL().lastIndexOf("/") == (getHostURL().length() - 1)
+                    ? ""
                     : "/")
-            + serviceType;
+            + getName();
   }
 
   private boolean hasParams = false, lookedForParams = false;
 
+  @Override
   public boolean hasParameters()
   {
     if (!lookedForParams)
@@ -238,9 +216,9 @@ public class Jws2Instance implements AutoCloseable
     }
   }
 
-  public String getServiceTypeURI()
+  public String getNameURI()
   {
-    return "java:" + serviceType;
+    return "java:" + getName();
   }
 
   jalview.ws.uimodel.AlignAnalysisUIText aaui;
@@ -249,4 +227,42 @@ public class Jws2Instance implements AutoCloseable
   {
     return aaui;
   }
+
+  /**
+   * initialise a parameter store for this service
+   * 
+   * @param userParameterStore
+   *          - the user ParamManager (e.g. Desktop.getUserParameterStore() )
+   */
+  @Override
+  public void initParamStore(ParamManager userParameterStore)
+  {
+    if (paramStore == null)
+    {
+      paramStore = new JabaParamStore(this, userParameterStore);
+    }
+  }
+
+  /**
+   * an object that implements one or more interfaces in jalview.ws.api
+   * 
+   * @return
+   */
+  @Override
+  public Object getEndpoint()
+  {
+    if (aaui!=null) {
+      // TODO complete
+      return null;
+    } else {
+      if (service instanceof MsaWS<?>)
+      {
+      return new JabawsMsaInstance(this);
+    } else {
+        // TODO complete
+        // service is for sequence analysis
+        return null;
+    }
+  }
+}
 }
index b04030d..d84206f 100644 (file)
@@ -98,12 +98,12 @@ public class RestClient extends WSClient
   {
     WebServiceJobTitle = MessageManager
             .formatMessage("label.webservice_job_title", new String[]
-            { service.details.Action, service.details.Name });
-    WebServiceName = service.details.Name;
+            { service.details.getAction(), service.details.getName() });
+    WebServiceName = service.details.getName();
     WebServiceReference = "No reference - go to url for more info";
-    if (service.details.description != null)
+    if (service.details.getDescription() != null)
     {
-      WebServiceReference = service.details.description;
+      WebServiceReference = service.details.getDescription();
     }
     if (!headless)
     {
@@ -140,10 +140,10 @@ public class RestClient extends WSClient
   public void attachWSMenuEntry(final JMenu wsmenu,
           final AlignFrame alignFrame)
   {
-    JMenuItem submit = new JMenuItem(service.details.Name);
+    JMenuItem submit = new JMenuItem(service.details.getName());
     submit.setToolTipText(MessageManager
             .formatMessage("label.rest_client_submit", new String[]
-            { service.details.Action, service.details.Name }));
+            { service.details.getAction(), service.details.getName() }));
     submit.addActionListener(new ActionListener()
     {
 
@@ -366,7 +366,7 @@ public class RestClient extends WSClient
   {
     if (services == null)
     {
-      services = new Vector<String>();
+      services = new Vector<>();
       try
       {
         for (RestServiceDescription descr : RestServiceDescription
@@ -395,7 +395,7 @@ public class RestClient extends WSClient
 
   public String getAction()
   {
-    return service.details.Action;
+    return service.details.getAction();
   }
 
   public RestServiceDescription getRestDescription()
@@ -405,7 +405,7 @@ public class RestClient extends WSClient
 
   public static Vector<String> getRsbsDescriptions()
   {
-    Vector<String> rsbsDescrs = new Vector<String>();
+    Vector<String> rsbsDescrs = new Vector<>();
     for (RestClient rsbs : getRestClients())
     {
       rsbsDescrs.add(rsbs.getRestDescription().toString());
@@ -418,7 +418,7 @@ public class RestClient extends WSClient
     if (rsbsUrls != null)
     {
       // TODO: consider validating services ?
-      services = new Vector<String>(rsbsUrls);
+      services = new Vector<>(rsbsUrls);
       StringBuffer sprop = new StringBuffer();
       for (String s : services)
       {
index e397c79..f60ff0c 100644 (file)
@@ -609,12 +609,12 @@ public class RestJobThread extends AWSThread
     /**
      * alignment panels derived from each alignment set returned by service.
      */
-    ArrayList<jalview.gui.AlignmentPanel> destPanels = new ArrayList<jalview.gui.AlignmentPanel>();
+    ArrayList<jalview.gui.AlignmentPanel> destPanels = new ArrayList<>();
     /**
      * list of instructions for how to process each distinct alignment set
      * returned by the job set
      */
-    ArrayList<AddDataTo> resultDest = new ArrayList<AddDataTo>();
+    ArrayList<AddDataTo> resultDest = new ArrayList<>();
     /**
      * when false, zeroth pane is panel derived from input deta.
      */
@@ -633,9 +633,9 @@ public class RestJobThread extends AWSThread
     boolean vsepjobs = restClient.service.isVseparable();
     // total number of distinct alignment sets generated by job set.
     int numAlSets = 0, als = 0;
-    List<AlignmentI> destAls = new ArrayList<AlignmentI>();
-    List<jalview.datamodel.HiddenColumns> destColsel = new ArrayList<jalview.datamodel.HiddenColumns>();
-    List<List<NewickFile>> trees = new ArrayList<List<NewickFile>>();
+    List<AlignmentI> destAls = new ArrayList<>();
+    List<jalview.datamodel.HiddenColumns> destColsel = new ArrayList<>();
+    List<List<NewickFile>> trees = new ArrayList<>();
 
     do
     {
@@ -694,7 +694,7 @@ public class RestJobThread extends AWSThread
 
               if (alset.trees != null)
               {
-                trees.add(new ArrayList<NewickFile>(alset.trees));
+                trees.add(new ArrayList<>(alset.trees));
               }
               else
               {
@@ -722,8 +722,8 @@ public class RestJobThread extends AWSThread
        */
       int vrestjob = 0;
       // Destination alignments for all result data.
-      ArrayList<SequenceGroup> visgrps = new ArrayList<SequenceGroup>();
-      Hashtable<String, SequenceGroup> groupNames = new Hashtable<String, SequenceGroup>();
+      ArrayList<SequenceGroup> visgrps = new ArrayList<>();
+      Hashtable<String, SequenceGroup> groupNames = new Hashtable<>();
       ArrayList<AlignmentAnnotation> visAlAn = null;
       for (nvertsep = 0; nvertsep < nvertseps; nvertsep++)
       {
@@ -987,7 +987,7 @@ public class RestJobThread extends AWSThread
                 }
                 if (visAlAn == null)
                 {
-                  visAlAn = new ArrayList<AlignmentAnnotation>();
+                  visAlAn = new ArrayList<>();
                 }
                 AlignmentAnnotation visan = null;
                 for (AlignmentAnnotation v : visAlAn)
@@ -1071,8 +1071,9 @@ public class RestJobThread extends AWSThread
       HiddenColumns destcs;
       String alTitle = MessageManager
               .formatMessage("label.webservice_job_title_on", new String[]
-              { restClient.service.details.Action,
-                  restClient.service.details.Name, restClient.viewTitle });
+              { restClient.service.details.getAction(),
+                  restClient.service.details.getName(),
+                  restClient.viewTitle });
       switch (action)
       {
       case newAlignment:
@@ -1282,7 +1283,7 @@ public class RestJobThread extends AWSThread
    */
   public boolean isValid()
   {
-    ArrayList<String> _warnings = new ArrayList<String>();
+    ArrayList<String> _warnings = new ArrayList<>();
     boolean validt = true;
     if (jobs != null)
     {
index 5533406..b07f3b6 100644 (file)
@@ -23,6 +23,7 @@ package jalview.ws.rest;
 import jalview.datamodel.SequenceI;
 import jalview.io.packed.DataProvider.JvDataType;
 import jalview.util.StringUtils;
+import jalview.ws.api.UIinfo;
 import jalview.ws.rest.params.Alignment;
 import jalview.ws.rest.params.AnnotationFile;
 import jalview.ws.rest.params.SeqGroupIndexVector;
@@ -66,10 +67,7 @@ public class RestServiceDescription
           boolean vseparable, char gapCharacter)
   {
     super();
-    this.details = new UIinfo();
-    details.Action = action == null ? "" : action;
-    details.description = description == null ? "" : description;
-    details.Name = name == null ? "" : name;
+    this.details = new UIinfo(action, action, name, description, postUrl);
     this.postUrl = postUrl == null ? "" : postUrl;
     this.urlSuffix = urlSuffix == null ? "" : urlSuffix;
     if (inputParams != null)
@@ -98,56 +96,11 @@ public class RestServiceDescription
     // TODO - robust diff that includes constants and reordering of URL
     // diff |= !(postUrl.equals(other.postUrl));
     // diff |= !inputParams.equals(other.inputParams);
-    diff |= !details.Name.equals(other.details.Name);
-    diff |= !details.Action.equals(other.details.Action);
-    diff |= !details.description.equals(other.details.description);
+    diff |= !details.equals(other.details);
     return !diff;
   }
 
-  /**
-   * Service UI Info { Action, Specific Name of Service, Brief Description }
-   */
-
-  public class UIinfo
-  {
-    public String getAction()
-    {
-      return Action;
-    }
-
-    public void setAction(String action)
-    {
-      Action = action;
-    }
-
-    public String getName()
-    {
-      return Name;
-    }
-
-    public void setName(String name)
-    {
-      Name = name;
-    }
-
-    public String getDescription()
-    {
-      return description;
-    }
-
-    public void setDescription(String description)
-    {
-      this.description = description;
-    }
-
-    String Action;
-
-    String Name;
-
-    String description;
-  }
-
-  public UIinfo details = new UIinfo();
+  public UIinfo details;
 
   public String getAction()
   {
@@ -238,7 +191,7 @@ public class RestServiceDescription
   /**
    * input info given as key/value pairs - mapped to post arguments
    */
-  Map<String, InputType> inputParams = new HashMap<String, InputType>();
+  Map<String, InputType> inputParams = new HashMap<>();
 
   /**
    * assigns the given inputType it to its corresponding input parameter token
@@ -455,7 +408,7 @@ public class RestServiceDescription
     }
     StringTokenizer st = new StringTokenizer(outstring, ";");
     String tok = "";
-    resultData = new ArrayList<JvDataType>();
+    resultData = new ArrayList<>();
     while (st.hasMoreTokens())
     {
       try
@@ -479,7 +432,7 @@ public class RestServiceDescription
 
   private String getServiceIOProperties()
   {
-    ArrayList<String> vls = new ArrayList<String>();
+    ArrayList<String> vls = new ArrayList<>();
     if (isHseparable())
     {
       vls.add("hseparable");
@@ -496,17 +449,18 @@ public class RestServiceDescription
             ",");
   }
 
+  @Override
   public String toString()
   {
     StringBuffer result = new StringBuffer();
     result.append("|");
-    result.append(details.Name);
+    result.append(details.getName());
     result.append('|');
-    result.append(details.Action);
+    result.append(details.getAction());
     result.append('|');
-    if (details.description != null)
+    if (details.getDescription() != null)
     {
-      result.append(details.description);
+      result.append(details.getDescription());
     }
     ;
     // list job input flags
@@ -567,9 +521,8 @@ public class RestServiceDescription
     {
       p++;
     }
-    details.Name = list[p];
-    details.Action = list[p + 1];
-    details.description = list[p + 2];
+    String action = list[p + 1], name = list[p], descrip = list[p + 2];
+
     invalid |= !configureFromServiceInputProperties(list[p + 3], warnings);
     if (list.length - p > 5 && list[p + 5] != null
             && list[p + 5].trim().length() > 5)
@@ -589,6 +542,7 @@ public class RestServiceDescription
         p += 5;
       }
     }
+    details = new UIinfo(action, action, name, descrip, postUrl);
     return invalid ? -1 : p;
   }
 
@@ -667,7 +621,7 @@ public class RestServiceDescription
     int lastp = 0;
     String url = new String();
     Matcher prms = PARAM_ENCODED_URL_PATTERN.matcher(ipurl);
-    Map<String, InputType> iparams = new Hashtable<String, InputType>();
+    Map<String, InputType> iparams = new Hashtable<>();
     InputType jinput;
     while (prms.find())
     {
@@ -728,7 +682,7 @@ public class RestServiceDescription
         jinput = (InputType) (type.getConstructor().newInstance());
         if (iprm.equalsIgnoreCase(jinput.getURLtokenPrefix()))
         {
-          ArrayList<String> al = new ArrayList<String>();
+          ArrayList<String> al = new ArrayList<>();
           for (String prprm : StringUtils.separatorListToArray(iprmparams,
                   ","))
           {
@@ -838,7 +792,7 @@ public class RestServiceDescription
     return jobId + urlSuffix;
   }
 
-  private List<JvDataType> resultData = new ArrayList<JvDataType>();
+  private List<JvDataType> resultData = new ArrayList<>();
 
   /**
    * 
@@ -852,7 +806,7 @@ public class RestServiceDescription
   {
     if (resultData == null)
     {
-      resultData = new ArrayList<JvDataType>();
+      resultData = new ArrayList<>();
     }
     resultData.add(dt);
   }
@@ -883,7 +837,7 @@ public class RestServiceDescription
           String services) throws Exception
   {
     String[] list = StringUtils.separatorListToArray(services, "|");
-    List<RestServiceDescription> svcparsed = new ArrayList<RestServiceDescription>();
+    List<RestServiceDescription> svcparsed = new ArrayList<>();
     int p = 0, lastp = 0;
     StringBuffer warnings = new StringBuffer();
     do
index df30935..42024ce 100644 (file)
@@ -238,6 +238,7 @@ public class PopupMenuTest
     // PDB.secondary structure on Sequence0
     AlignmentAnnotation annotation = new AlignmentAnnotation(
             "secondary structure", "", 0);
+    annotation.annotations = new Annotation[] { new Annotation(2f) };
     annotation.setCalcId("PDB");
     seqs.get(0).getDatasetSequence().addAlignmentAnnotation(annotation);
     if (addToSequence)
@@ -252,6 +253,7 @@ public class PopupMenuTest
     // PDB.Temp on Sequence1
     annotation = new AlignmentAnnotation("Temp", "", 0);
     annotation.setCalcId("PDB");
+    annotation.annotations = new Annotation[] { new Annotation(2f) };
     seqs.get(1).getDatasetSequence().addAlignmentAnnotation(annotation);
     if (addToSequence)
     {
@@ -265,6 +267,7 @@ public class PopupMenuTest
     // JMOL.secondary structure on Sequence0
     annotation = new AlignmentAnnotation("secondary structure", "", 0);
     annotation.setCalcId("Jmol");
+    annotation.annotations = new Annotation[] { new Annotation(2f) };
     seqs.get(0).getDatasetSequence().addAlignmentAnnotation(annotation);
     if (addToSequence)
     {
index 07fd375..909d0c8 100644 (file)
@@ -24,7 +24,7 @@ public class FileUtilsTest
 
     List<String> matches = FileUtils
             .findMatchingPaths(Paths.get(".."),
-            ".*[/\\\\]plant.*\\.f.*");
+                    ".*[\\\\/]plant.*\\.f.*");
     System.out.println(matches);
     assertTrue(matches.contains(expect1));
     assertTrue(matches.contains(expect2));
index 134fbd1..428f263 100644 (file)
@@ -28,6 +28,7 @@ import jalview.ws.jabaws.JalviewJabawsTestUtils;
 import jalview.ws.jws2.JabaPreset;
 import jalview.ws.jws2.Jws2Discoverer;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.ParamDatastoreI;
 
 import java.awt.BorderLayout;
@@ -43,7 +44,6 @@ import javax.swing.JPanel;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
-import compbio.metadata.Argument;
 import compbio.metadata.Preset;
 import compbio.metadata.PresetManager;
 
@@ -93,7 +93,7 @@ public class Jws2ParamView
     for (Jws2Instance service : disc.getServices())
     {
       if (serviceTests.size() == 0
-              || serviceTests.contains(service.serviceType.toLowerCase()))
+              || serviceTests.contains(service.getName().toLowerCase()))
       {
         List<Preset> prl = null;
         Preset pr = null;
@@ -131,7 +131,7 @@ public class Jws2ParamView
           }
           WsJobParameters pgui = new WsJobParameters((ParamDatastoreI) null,
                   service, new JabaPreset(service, pr),
-                  (List<Argument>) null);
+                  (List<ArgumentI>) null);
           JFrame jf = new JFrame(MessageManager
                   .formatMessage("label.ws_parameters_for", new String[]
                   { service.getActionText() }));
index e8b6c2b..6698ed1 100644 (file)
@@ -82,10 +82,10 @@ public class DisorderAnnotExportImport
       Thread.sleep(100);
     }
 
-    iupreds = new ArrayList<Jws2Instance>();
+    iupreds = new ArrayList<>();
     for (Jws2Instance svc : disc.getServices())
     {
-      if (svc.getServiceTypeURI().toLowerCase().contains("iupredws"))
+      if (svc.getNameURI().toLowerCase().contains("iupredws"))
       {
         iupreds.add(svc);
       }
@@ -129,7 +129,7 @@ public class DisorderAnnotExportImport
     AlignmentI orig_alig = af.getViewport().getAlignment();
     // NOTE: Consensus annotation row cannot be exported and reimported
     // faithfully - so we remove them
-    List<AlignmentAnnotation> toremove = new ArrayList<AlignmentAnnotation>();
+    List<AlignmentAnnotation> toremove = new ArrayList<>();
     for (AlignmentAnnotation aa : orig_alig.getAlignmentAnnotation())
     {
       if (aa.autoCalculated)
index 889c003..3c83b71 100644 (file)
@@ -33,6 +33,7 @@ import jalview.io.FileFormat;
 import jalview.io.FormatAdapter;
 import jalview.io.StockholmFileTest;
 import jalview.project.Jalview2XML;
+import jalview.ws.jws2.JabaParamStore;
 import jalview.ws.jws2.Jws2Discoverer;
 import jalview.ws.jws2.RNAalifoldClient;
 import jalview.ws.jws2.SequenceAnnotationWSClient;
@@ -98,7 +99,7 @@ public class RNAStructExportImport
     for (Jws2Instance svc : disc.getServices())
     {
 
-      if (svc.getServiceTypeURI().toLowerCase().contains("rnaalifoldws"))
+      if (svc.getNameURI().toLowerCase().contains("rnaalifoldws"))
       {
         rnaalifoldws = svc;
       }
@@ -280,7 +281,8 @@ public class RNAStructExportImport
         opts.add(rg);
       }
     }
-    alifoldClient = new RNAalifoldClient(rnaalifoldws, af, null, opts);
+    alifoldClient = new RNAalifoldClient(rnaalifoldws, af, null,
+            JabaParamStore.getJwsArgsfromJaba(opts));
 
     af.getViewport().getCalcManager().startWorker(alifoldClient);
 
index c0aa2ee..66ce169 100644 (file)
@@ -26,6 +26,7 @@ import static org.testng.AssertJUnit.assertTrue;
 
 import jalview.bin.Cache;
 import jalview.gui.JvOptionPane;
+import jalview.ws.api.UIinfo;
 import jalview.ws.jabaws.JalviewJabawsTestUtils;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
 
@@ -61,7 +62,7 @@ public class ParameterUtilsTest
    * To limit tests to specify services, add them to this list; leave list empty
    * to test all
    */
-  private static List<String> serviceTests = new ArrayList<String>();
+  private static List<String> serviceTests = new ArrayList<>();
 
   private static Jws2Discoverer disc = null;
 
@@ -128,10 +129,10 @@ public class ParameterUtilsTest
    * @param service
    * @return
    */
-  public boolean isForTesting(Jws2Instance service)
+  public boolean isForTesting(UIinfo service)
   {
     return serviceTests.size() == 0
-            || serviceTests.contains(service.serviceType.toLowerCase());
+            || serviceTests.contains(service.getName().toLowerCase());
   }
 
   @Test(groups = { "Network" })
index 61ad91f..261c059 100644 (file)
@@ -128,6 +128,12 @@ public class ShmmrRSBSService
       if (!service.equals(newService))
       {
         System.err.println("Failed for service (" + desc + ").");
+        if (fromservicetostring.equals(newService.toString()))
+        {
+          System.err.println(
+                  "Description strings are equivalent: fault during RestServiceDescription.equals()");
+          return false;
+        }
         System.err.println("Original service and parsed service differ.");
         System.err.println("Original: " + fromservicetostring);
         System.err.println("Parsed  : " + newService.toString());