JAL-3954 Implement phmmer action and task as alignment actions
authorMateusz Warowny <mmzwarowny@dundee.ac.uk>
Tue, 16 May 2023 12:47:01 +0000 (14:47 +0200)
committerMateusz Warowny <mmzwarowny@dundee.ac.uk>
Tue, 16 May 2023 12:47:01 +0000 (14:47 +0200)
src/jalview/ws2/actions/hmmer/PhmmerAction.java [new file with mode: 0644]
src/jalview/ws2/actions/hmmer/PhmmerTask.java [new file with mode: 0644]
src/jalview/ws2/client/ebi/JobDispatcherWSDiscoverer.java

diff --git a/src/jalview/ws2/actions/hmmer/PhmmerAction.java b/src/jalview/ws2/actions/hmmer/PhmmerAction.java
new file mode 100644 (file)
index 0000000..5e6ef08
--- /dev/null
@@ -0,0 +1,73 @@
+package jalview.ws2.actions.hmmer;
+
+import java.util.List;
+import java.util.Objects;
+
+import jalview.datamodel.AlignmentI;
+import jalview.viewmodel.AlignmentViewport;
+import jalview.ws.params.ArgumentI;
+import jalview.ws2.actions.BaseAction;
+import jalview.ws2.actions.api.TaskEventListener;
+import jalview.ws2.actions.api.TaskI;
+import jalview.ws2.api.Credentials;
+import jalview.ws2.client.api.AlignmentWebServiceClientI;
+import jalview.ws2.client.api.WebServiceClientI;
+
+/**
+ * Implementation of the {@link BaseAction} for the phmmer client. This is NOT
+ * how you should implement it. The action should be more generic and cover
+ * range of similar services.
+ * 
+ * @author mmwarowny
+ *
+ */
+// FIXME: Not an alignment action (temporary hack)
+public class PhmmerAction extends BaseAction<AlignmentI>
+{
+  public static class Builder extends BaseAction.Builder<PhmmerAction>
+  {
+    protected AlignmentWebServiceClientI client;
+
+    private Builder(AlignmentWebServiceClientI client)
+    {
+      super();
+      Objects.requireNonNull(client);
+      this.client = client;
+    }
+
+    public PhmmerAction build()
+    {
+      return new PhmmerAction(this);
+    }
+  }
+
+  public static Builder newBuilder(AlignmentWebServiceClientI client)
+  {
+    return new Builder(client);
+  }
+
+  protected final AlignmentWebServiceClientI client;
+
+  public PhmmerAction(Builder builder)
+  {
+    super(builder);
+    client = builder.client;
+  }
+
+  @Override
+  public TaskI<AlignmentI> perform(AlignmentViewport viewport,
+          List<ArgumentI> args, Credentials credentials,
+          TaskEventListener<AlignmentI> handler)
+  {
+    var task = new PhmmerTask(client, args, credentials,
+            viewport.getAlignmentView(true), handler);
+    task.start(viewport.getServiceExecutor());
+    return task;
+  }
+
+  @Override
+  public boolean isActive(AlignmentViewport viewport)
+  {
+    return false;
+  }
+}
diff --git a/src/jalview/ws2/actions/hmmer/PhmmerTask.java b/src/jalview/ws2/actions/hmmer/PhmmerTask.java
new file mode 100644 (file)
index 0000000..0565300
--- /dev/null
@@ -0,0 +1,66 @@
+package jalview.ws2.actions.hmmer;
+
+import static jalview.util.Comparison.GapChars;
+
+import java.io.IOException;
+import java.util.List;
+
+import jalview.analysis.AlignSeq;
+import jalview.bin.Console;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.AlignmentView;
+import jalview.datamodel.Sequence;
+import jalview.ws.params.ArgumentI;
+import jalview.ws2.actions.AbstractPollableTask;
+import jalview.ws2.actions.BaseJob;
+import jalview.ws2.actions.ServiceInputInvalidException;
+import jalview.ws2.actions.api.TaskEventListener;
+import jalview.ws2.api.Credentials;
+import jalview.ws2.api.JobStatus;
+import jalview.ws2.client.api.AlignmentWebServiceClientI;
+
+class PhmmerTask extends AbstractPollableTask<BaseJob, AlignmentI>
+{
+  private final AlignmentWebServiceClientI client;
+  private final AlignmentView view;
+
+  PhmmerTask(AlignmentWebServiceClientI client, List<ArgumentI> args,
+          Credentials credentials, AlignmentView view,
+          TaskEventListener<AlignmentI> eventListener)
+  {
+    super(client, args, credentials, eventListener);
+    this.client = client;
+    this.view = view;
+  }
+
+  @Override
+  protected List<BaseJob> prepare() throws ServiceInputInvalidException
+  {
+    Console.info("Preparing sequence for phmmer job");
+    var sequence = view.getVisibleAlignment('-').getSequenceAt(0);
+    var seq = new Sequence(sequence.getName(),
+            AlignSeq.extractGaps(GapChars, sequence.getSequenceAsString()));
+    var job = new BaseJob(List.of(seq))
+    {
+      @Override
+      public boolean isInputValid()
+      {
+        return true;
+      }
+    };
+    job.setStatus(JobStatus.READY);
+    return List.of(job);
+  }
+
+  @Override
+  protected AlignmentI done() throws IOException
+  {
+    var job = getSubJobs().get(0);
+    var jobId = job.getServerJob().getJobId();
+    var status = job.getStatus();
+    Console.info(String.format("phmmer finished job \"%s\" with status %s",
+            jobId, status));
+    return client.getAlignment(job.getServerJob());
+  }
+
+}
index 11fbf2a..a20575d 100644 (file)
@@ -10,6 +10,7 @@ import jalview.bin.Console;
 import jalview.ws.params.ParamManager;
 import jalview.ws2.actions.NullAction;
 import jalview.ws2.actions.api.ActionI;
+import jalview.ws2.actions.hmmer.PhmmerAction;
 import jalview.ws2.api.WebService;
 import jalview.ws2.client.api.AbstractWebServiceDiscoverer;
 import uk.ac.dundee.compbio.hmmerclient.PhmmerClient;
@@ -73,18 +74,18 @@ public final class JobDispatcherWSDiscoverer extends AbstractWebServiceDiscovere
   @Override
   protected List<WebService<?>> fetchServices(URL url) throws IOException
   {
-    PhmmerClient client;
+    PhmmerClient phmmerClient;
     try {
-      client = new PhmmerClient(url);
+      phmmerClient = new PhmmerClient(url);
     }
     catch (URISyntaxException e) {
       throw new MalformedURLException(e.getMessage());
     }
-    if (!client.testEndpoint())
+    if (!phmmerClient.testEndpoint())
       throw new IOException(
               "unable to reach dispatcher server at " + url);
     // TODO change once a concrete action is implemented
-    var wsBuilder = WebService.<NullAction> newBuilder();
+    var wsBuilder = WebService.<PhmmerAction> newBuilder();
     wsBuilder.url(url);
     wsBuilder.clientName("job dispatcher");
     wsBuilder.category("Database search");
@@ -92,10 +93,11 @@ public final class JobDispatcherWSDiscoverer extends AbstractWebServiceDiscovere
     wsBuilder.description("Hmmer3 phmmer is used to search one or more query sequences against a sequence database.");
     wsBuilder.interactive(false);
     wsBuilder.paramDatastore(ParamStores.newPhmmerDatastore(url, paramManager));
-    wsBuilder.actionClass(NullAction.class);
+    wsBuilder.actionClass(PhmmerAction.class);
     var webService = wsBuilder.build(); 
     
-    var actionBuilder = NullAction.newBuilder();
+    var client = new PhmmerWSClient(phmmerClient);
+    var actionBuilder = PhmmerAction.newBuilder(client);
     actionBuilder.webService(webService);
     actionBuilder.name("");
     webService.addAction(actionBuilder.build());