JAL-1601 Implement JPred4 client and discoverer
authorMateusz Warowny <mmzwarowny@dundee.ac.uk>
Thu, 5 Oct 2023 13:10:21 +0000 (15:10 +0200)
committerMateusz Warowny <mmzwarowny@dundee.ac.uk>
Thu, 5 Oct 2023 13:10:21 +0000 (15:10 +0200)
j11lib/jpred-client-1.0-SNAPSHOT.jar [new file with mode: 0644]
src/jalview/ws2/client/jpred4/JPred4WSClient.java [new file with mode: 0644]
src/jalview/ws2/client/jpred4/JPred4WSDiscoverer.java [new file with mode: 0644]

diff --git a/j11lib/jpred-client-1.0-SNAPSHOT.jar b/j11lib/jpred-client-1.0-SNAPSHOT.jar
new file mode 100644 (file)
index 0000000..826f028
Binary files /dev/null and b/j11lib/jpred-client-1.0-SNAPSHOT.jar differ
diff --git a/src/jalview/ws2/client/jpred4/JPred4WSClient.java b/src/jalview/ws2/client/jpred4/JPred4WSClient.java
new file mode 100644 (file)
index 0000000..36cc6c2
--- /dev/null
@@ -0,0 +1,115 @@
+package jalview.ws2.client.jpred4;
+
+import java.io.IOException;
+import java.util.List;
+
+import jalview.datamodel.SequenceI;
+import jalview.io.AlignFile;
+import jalview.io.DataSourceType;
+import jalview.io.FastaFile;
+import jalview.io.FileFormat;
+import jalview.io.FormatAdapter;
+import jalview.io.JPredFile;
+import jalview.ws.params.ArgumentI;
+import jalview.ws2.api.Credentials;
+import jalview.ws2.api.JobStatus;
+import jalview.ws2.api.WebServiceJobHandle;
+import jalview.ws2.client.api.SecStructPredWebServiceClientI;
+import uk.ac.dundee.compbio.jpred.JPredClient;
+import uk.ac.dundee.compbio.jpred.JPredRequest;
+import uk.ac.dundee.compbio.jpred.ResultTypes;
+
+public class JPred4WSClient implements SecStructPredWebServiceClientI
+{
+  final JPredClient client;
+
+  JPred4WSClient(JPredClient client)
+  {
+    this.client = client;
+  }
+
+  @Override
+  public String getUrl()
+  {
+    return client.getURL().toString();
+  }
+
+  @Override
+  public String getClientName()
+  {
+    return "jpred4";
+  }
+
+  @Override
+  public WebServiceJobHandle submit(List<SequenceI> sequences,
+      List<ArgumentI> args, Credentials credentials) throws IOException
+  {
+    var input = FileFormat.Fasta
+        .getWriter(null)
+        .print(sequences.toArray(SequenceI[]::new), false);
+    JPredRequest request = JPredRequest
+        .newBuilder()
+        .mode(JPredRequest.Mode.MSA)
+        .format(JPredRequest.Format.FASTA)
+        .input(input)
+        .build();
+    var jobId = client.submit(request);
+    return new WebServiceJobHandle(getClientName(), "jpred4", getUrl(), jobId);
+  }
+
+  @Override
+  public JobStatus getStatus(WebServiceJobHandle job) throws IOException
+  {
+    var status = client.getStatus(job.getJobId());
+    switch (status)
+    {
+    case RUNNING:
+      return JobStatus.RUNNING;
+    case FINISHED:
+      return JobStatus.COMPLETED;
+    case NO_JOB:
+      return JobStatus.SERVER_ERROR;
+    case MALFORMED:
+      return JobStatus.INVALID;
+    case NOT_EXIST:
+      return JobStatus.SERVER_ERROR;
+    default:
+      return JobStatus.UNKNOWN;
+    }
+  }
+
+  @Override
+  public String getLog(WebServiceJobHandle job) throws IOException
+  {
+    var stream = client.getResultStream(job.getJobId(), ResultTypes.LOG);
+    // FIXME: potential OOM
+    return new String(stream.readAllBytes());
+  }
+
+  @Override
+  public String getErrorLog(WebServiceJobHandle job) throws IOException
+  {
+    return "";
+  }
+
+  @Override
+  public void cancel(WebServiceJobHandle job)
+      throws IOException, UnsupportedOperationException
+  {
+    
+  }
+  
+  @Override
+  public AlignFile getAlignmentFile(WebServiceJobHandle job) throws IOException
+  {
+    var url = client.getResultURL(job.getJobId(), ResultTypes.PSIBLAST_ALIGN);
+    return new FastaFile(url.toString(), DataSourceType.URL);
+  }
+  
+  @Override
+  public JPredFile getPredictionFile(WebServiceJobHandle job) throws IOException
+  {
+    var url = client.getResultURL(job.getJobId(), ResultTypes.CONCISE);
+    return new JPredFile(url.toString(), DataSourceType.URL);
+  }
+}
diff --git a/src/jalview/ws2/client/jpred4/JPred4WSDiscoverer.java b/src/jalview/ws2/client/jpred4/JPred4WSDiscoverer.java
new file mode 100644 (file)
index 0000000..99c3f28
--- /dev/null
@@ -0,0 +1,97 @@
+package jalview.ws2.client.jpred4;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.ParamManager;
+import jalview.ws2.actions.secstructpred.SecStructPredAction;
+import jalview.ws2.api.WebService;
+import jalview.ws2.client.api.AbstractWebServiceDiscoverer;
+import jalview.ws2.client.ebi.JobDispatcherWSDiscoverer;
+import jalview.ws2.params.SimpleParamDatastore;
+import uk.ac.dundee.compbio.jpred.JPredClient;
+
+public class JPred4WSDiscoverer extends AbstractWebServiceDiscoverer
+{
+  private static final URL DEFAULT_URL;
+  static
+  {
+    try
+    {
+      DEFAULT_URL = new URL("https://www.compbio.dundee.ac.uk/jpred4/");
+    } catch (MalformedURLException e)
+    {
+      throw new ExceptionInInitializerError(e);
+    }
+  }
+
+  private static JPred4WSDiscoverer instance = null;
+
+  private static ParamManager paramManager = null;
+
+  private JPred4WSDiscoverer()
+  {
+  }
+
+  public static JPred4WSDiscoverer getInstance()
+  {
+    if (instance == null)
+      instance = new JPred4WSDiscoverer();
+    return instance;
+  }
+
+  public static void setParamManager(ParamManager manager)
+  {
+    paramManager = manager;
+  }
+
+  @Override
+  public int getStatusForUrl(URL url)
+  {
+    // TODO: implement actual status check
+    return STATUS_OK;
+  }
+
+  @Override
+  public String getUrlsPropertyKey()
+  {
+    return null;
+  }
+
+  @Override
+  protected URL getDefaultUrl()
+  {
+    return DEFAULT_URL;
+  }
+
+  @Override
+  protected List<WebService<?>> fetchServices(URL url) throws IOException
+  {
+    JPredClient client = new JPredClient(url);
+    var wsBuilder = WebService.<SecStructPredAction> newBuilder();
+    wsBuilder.url(url);
+    wsBuilder.clientName("jpred4");
+    wsBuilder.category("Secondary structure prediction");
+    wsBuilder.name("jpred4");
+    wsBuilder.description("JPred4 Secondary Structure Prediction.");
+    wsBuilder.interactive(false);
+
+    wsBuilder
+        .paramDatastore(new SimpleParamDatastore(url, Collections.emptyList(),
+            Collections.emptyList(), paramManager));
+    wsBuilder.actionClass(SecStructPredAction.class);
+    var webService = wsBuilder.build();
+
+    var wsClient = new JPred4WSClient(client);
+    var actionBuilder = SecStructPredAction.newBuilder(wsClient);
+    actionBuilder.webService(webService);
+    actionBuilder.name("");
+    webService.addAction(actionBuilder.build());
+
+    return List.of(webService);
+  }
+}