1 package jalview.ws2.slivka;
3 import java.io.ByteArrayInputStream;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.util.ArrayList;
7 import java.util.Arrays;
8 import java.util.Collection;
9 import java.util.EnumMap;
10 import java.util.HashSet;
11 import java.util.List;
14 import jalview.bin.Cache;
15 import jalview.datamodel.AlignmentI;
16 import jalview.datamodel.SequenceI;
17 import jalview.io.DataSourceType;
18 import jalview.io.FileFormat;
19 import jalview.io.FileFormatI;
20 import jalview.io.FormatAdapter;
21 import jalview.ws.gui.WsJob;
22 import jalview.ws.params.ArgumentI;
23 import jalview.ws.params.ParamDatastoreI;
24 import jalview.ws.params.WsParamSetI;
25 import jalview.ws.slivkaws.SlivkaDatastore;
26 import jalview.ws2.WebServiceI;
27 import jalview.ws2.operations.Operation;
28 import jalview.ws2.ResultSupplier;
29 import jalview.ws2.WSJob;
30 import jalview.ws2.WSJobStatus;
31 import javajs.http.ClientProtocolException;
32 import uk.ac.dundee.compbio.slivkaclient.Job;
33 import uk.ac.dundee.compbio.slivkaclient.Parameter;
34 import uk.ac.dundee.compbio.slivkaclient.RemoteFile;
35 import uk.ac.dundee.compbio.slivkaclient.SlivkaClient;
36 import uk.ac.dundee.compbio.slivkaclient.SlivkaService;
38 public class SlivkaWebService implements WebServiceI
40 protected final SlivkaClient client;
42 protected final SlivkaService service;
44 protected SlivkaDatastore store = null;
46 protected final ArrayList<Operation> operations = new ArrayList<>();
48 protected int typeFlags = 0;
50 protected static final EnumMap<Job.Status, WSJobStatus> statusMap = new EnumMap<>(
53 statusMap.put(Job.Status.PENDING, WSJobStatus.SUBMITTED);
54 statusMap.put(Job.Status.REJECTED, WSJobStatus.INVALID);
55 statusMap.put(Job.Status.ACCEPTED, WSJobStatus.QUEUED);
56 statusMap.put(Job.Status.QUEUED, WSJobStatus.QUEUED);
57 statusMap.put(Job.Status.RUNNING, WSJobStatus.RUNNING);
58 statusMap.put(Job.Status.COMPLETED, WSJobStatus.FINISHED);
59 statusMap.put(Job.Status.INTERRUPTED, WSJobStatus.CANCELLED);
60 statusMap.put(Job.Status.DELETED, WSJobStatus.CANCELLED);
61 statusMap.put(Job.Status.FAILED, WSJobStatus.FAILED);
62 statusMap.put(Job.Status.ERROR, WSJobStatus.SERVER_ERROR);
63 statusMap.put(Job.Status.UNKNOWN, WSJobStatus.UNKNOWN);
66 public SlivkaWebService(SlivkaClient client, SlivkaService service)
69 this.service = service;
73 public String getHostName()
75 return client.getUrl().toString();
79 public String getProviderName()
85 public String getName()
87 return service.getName();
91 public String getDescription()
93 return service.getDescription();
97 public List<Operation> getOperations()
102 void addOperation(Operation operation)
104 operations.add(operation);
107 void removeOperation(Operation operation)
109 operations.remove(operation);
113 public boolean hasParameters()
115 return getParamStore().getServiceParameters().size() > 0;
119 public ParamDatastoreI getParamStore()
123 store = new SlivkaDatastore(service);
129 public String submit(List<SequenceI> sequences, List<ArgumentI> args)
132 var request = new uk.ac.dundee.compbio.slivkaclient.JobRequest();
133 for (Parameter param : service.getParameters())
135 if (param instanceof Parameter.FileParameter)
137 // if finds a file input, gives it sequences stream
138 Parameter.FileParameter fileParam = (Parameter.FileParameter) param;
140 switch (fileParam.getMediaType())
142 case "application/pfam":
143 format = FileFormat.Pfam;
145 case "application/stockholm":
146 format = FileFormat.Stockholm;
148 case "application/clustal":
149 format = FileFormat.Clustal;
151 case "application/fasta":
153 format = FileFormat.Fasta;
156 InputStream stream = new ByteArrayInputStream(format.getWriter(null)
157 .print(sequences.toArray(new SequenceI[0]), false)
159 request.addFile(param.getId(), stream);
164 for (ArgumentI arg : args)
166 // multiple choice field names are name$number to avoid duplications
167 // the number is stripped here
168 String paramId = arg.getName().split("\\$", 2)[0];
169 Parameter param = service.getParameter(paramId);
170 if (param instanceof Parameter.FlagParameter)
172 if (arg.getValue() != null && !arg.getValue().isBlank())
173 request.addData(paramId, true);
175 request.addData(paramId, false);
179 request.addData(paramId, arg.getValue());
183 var job = service.submitJob(request);
188 public void updateProgress(WSJob job) throws IOException
190 var slivkaJob = client.getJob(job.getJobId());
191 job.setStatus(statusMap.get(slivkaJob.getStatus()));
195 public void cancel(WSJob job) throws IOException
197 Cache.log.warn("Slivka does not support job cancellation yet.");
201 public boolean handleSubmissionError(WSJob job, Exception ex)
203 if (ex instanceof ClientProtocolException)
205 Cache.log.error("Job submission failed due to exception.", ex);
212 public boolean handleCollectionError(WSJob job, Exception ex)
214 // TODO Auto-generated method stub
218 public AlignmentI getAlignment(WSJob job) throws IOException
220 Collection<RemoteFile> files;
221 var slivkaJob = client.getJob(job.getJobId());
222 files = slivkaJob.getResults();
223 for (RemoteFile f : files)
225 if (f.getMediaType().equals("application/clustal"))
227 return new FormatAdapter().readFile(f.getContentUrl().toString(),
228 DataSourceType.URL, FileFormat.Clustal);
230 else if (f.getMediaType().equals("application/fasta"))
232 return new FormatAdapter().readFile(f.getContentUrl().toString(),
233 DataSourceType.URL, FileFormat.Fasta);
240 public String toString()
242 return String.format("SlivkaWebService[%s]", getName());