1 package jalview.ws2.slivka;
3 import java.io.ByteArrayInputStream;
4 import java.io.ByteArrayOutputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.util.ArrayList;
8 import java.util.Arrays;
9 import java.util.Collection;
10 import java.util.EnumMap;
11 import java.util.HashSet;
12 import java.util.List;
15 import jalview.bin.Cache;
16 import jalview.datamodel.AlignmentI;
17 import jalview.datamodel.SequenceI;
18 import jalview.io.AnnotationFile;
19 import jalview.io.DataSourceType;
20 import jalview.io.FeaturesFile;
21 import jalview.io.FileFormat;
22 import jalview.io.FileFormatI;
23 import jalview.io.FormatAdapter;
24 import jalview.ws.gui.WsJob;
25 import jalview.ws.params.ArgumentI;
26 import jalview.ws.params.ParamDatastoreI;
27 import jalview.ws.params.WsParamSetI;
28 import jalview.ws.slivkaws.SlivkaDatastore;
29 import jalview.ws2.WebServiceI;
30 import jalview.ws2.operations.Operation;
31 import jalview.ws2.ResultSupplier;
32 import jalview.ws2.WSJob;
33 import jalview.ws2.WSJobStatus;
34 import javajs.http.ClientProtocolException;
35 import uk.ac.dundee.compbio.slivkaclient.Job;
36 import uk.ac.dundee.compbio.slivkaclient.Parameter;
37 import uk.ac.dundee.compbio.slivkaclient.RemoteFile;
38 import uk.ac.dundee.compbio.slivkaclient.SlivkaClient;
39 import uk.ac.dundee.compbio.slivkaclient.SlivkaService;
41 public class SlivkaWebService implements WebServiceI
43 protected final SlivkaClient client;
45 protected final SlivkaService service;
47 protected SlivkaDatastore store = null;
49 protected final ArrayList<Operation> operations = new ArrayList<>();
51 protected int typeFlags = 0;
53 protected static final EnumMap<Job.Status, WSJobStatus> statusMap = new EnumMap<>(
56 statusMap.put(Job.Status.PENDING, WSJobStatus.SUBMITTED);
57 statusMap.put(Job.Status.REJECTED, WSJobStatus.INVALID);
58 statusMap.put(Job.Status.ACCEPTED, WSJobStatus.QUEUED);
59 statusMap.put(Job.Status.QUEUED, WSJobStatus.QUEUED);
60 statusMap.put(Job.Status.RUNNING, WSJobStatus.RUNNING);
61 statusMap.put(Job.Status.COMPLETED, WSJobStatus.FINISHED);
62 statusMap.put(Job.Status.INTERRUPTED, WSJobStatus.CANCELLED);
63 statusMap.put(Job.Status.DELETED, WSJobStatus.CANCELLED);
64 statusMap.put(Job.Status.FAILED, WSJobStatus.FAILED);
65 statusMap.put(Job.Status.ERROR, WSJobStatus.SERVER_ERROR);
66 statusMap.put(Job.Status.UNKNOWN, WSJobStatus.UNKNOWN);
69 public SlivkaWebService(SlivkaClient client, SlivkaService service)
72 this.service = service;
76 public String getHostName()
78 return client.getUrl().toString();
82 public String getProviderName()
88 public String getName()
90 return service.getName();
94 public String getDescription()
96 return service.getDescription();
100 public List<Operation> getOperations()
105 void addOperation(Operation operation)
107 operations.add(operation);
110 void removeOperation(Operation operation)
112 operations.remove(operation);
116 public boolean hasParameters()
118 return getParamStore().getServiceParameters().size() > 0;
122 public ParamDatastoreI getParamStore()
126 store = new SlivkaDatastore(service);
132 public String submit(List<SequenceI> sequences, List<ArgumentI> args)
135 var request = new uk.ac.dundee.compbio.slivkaclient.JobRequest();
136 for (Parameter param : service.getParameters())
138 if (param instanceof Parameter.FileParameter)
140 // if finds a file input, gives it sequences stream
141 Parameter.FileParameter fileParam = (Parameter.FileParameter) param;
143 switch (fileParam.getMediaType())
145 case "application/pfam":
146 format = FileFormat.Pfam;
148 case "application/stockholm":
149 format = FileFormat.Stockholm;
151 case "application/clustal":
152 format = FileFormat.Clustal;
154 case "application/fasta":
156 format = FileFormat.Fasta;
159 InputStream stream = new ByteArrayInputStream(format.getWriter(null)
160 .print(sequences.toArray(new SequenceI[0]), false)
162 request.addFile(param.getId(), stream);
167 for (ArgumentI arg : args)
169 // multiple choice field names are name$number to avoid duplications
170 // the number is stripped here
171 String paramId = arg.getName().split("\\$", 2)[0];
172 Parameter param = service.getParameter(paramId);
173 if (param instanceof Parameter.FlagParameter)
175 if (arg.getValue() != null && !arg.getValue().isBlank())
176 request.addData(paramId, true);
178 request.addData(paramId, false);
182 request.addData(paramId, arg.getValue());
186 var job = service.submitJob(request);
191 public void updateProgress(WSJob job) throws IOException
193 var slivkaJob = client.getJob(job.getJobId());
194 job.setStatus(statusMap.get(slivkaJob.getStatus()));
195 Collection<RemoteFile> files = slivkaJob.getResults();
196 for (RemoteFile f : files)
198 if (f.getLabel().equals("log"))
200 ByteArrayOutputStream stream = new ByteArrayOutputStream();
202 job.setLog(stream.toString("UTF-8"));
204 else if (f.getLabel().equals("error-log"))
206 ByteArrayOutputStream stream = new ByteArrayOutputStream();
208 job.setErrorLog(stream.toString("UTF-8"));
214 public void cancel(WSJob job) throws IOException
216 Cache.log.warn("Slivka does not support job cancellation yet.");
220 public boolean handleSubmissionError(WSJob job, Exception ex)
222 if (ex instanceof ClientProtocolException)
224 Cache.log.error("Job submission failed due to exception.", ex);
231 public boolean handleCollectionError(WSJob job, Exception ex)
233 // TODO Auto-generated method stub
237 public AlignmentI getAlignment(WSJob job) throws IOException
239 Collection<RemoteFile> files;
240 var slivkaJob = client.getJob(job.getJobId());
241 files = slivkaJob.getResults();
242 for (RemoteFile f : files)
244 if (f.getMediaType().equals("application/clustal"))
246 return new FormatAdapter().readFile(f.getContentUrl().toString(),
247 DataSourceType.URL, FileFormat.Clustal);
249 else if (f.getMediaType().equals("application/fasta"))
251 return new FormatAdapter().readFile(f.getContentUrl().toString(),
252 DataSourceType.URL, FileFormat.Fasta);
258 public FeaturesFile getFeaturesFile(WSJob job) throws IOException
260 var slivkaJob = client.getJob(job.getJobId());
261 Collection<RemoteFile> files = slivkaJob.getResults();
262 for (RemoteFile f : files)
264 if (f.getMediaType().equals("application/jalview-features"))
266 return new FeaturesFile(f.getContentUrl().toString(), DataSourceType.URL);
272 public AnnotationFile getAnnotationFile(WSJob job) throws IOException
274 var slivkaJob = client.getJob(job.getJobId());
275 Collection<RemoteFile> files = slivkaJob.getResults();
276 for (RemoteFile f : files)
278 if (f.getMediaType().equals("application/jalview-annotations"))
280 // return new AnnorationFile(...);
287 public String toString()
289 return String.format("SlivkaWebService[%s]", getName());