--- /dev/null
+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);
+ }
+}
--- /dev/null
+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);
+ }
+}