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;
41 protected final SlivkaService service;
42 protected SlivkaDatastore store = null;
43 protected final String operation;
44 protected final ArrayList<Operation> operations = new ArrayList<>();
45 protected int typeFlags = 0;
47 protected static final EnumMap<Job.Status, WsJob.JobState> stateMap = new EnumMap<>(Job.Status.class);
49 stateMap.put(Job.Status.PENDING, WsJob.JobState.QUEUED);
50 stateMap.put(Job.Status.REJECTED, WsJob.JobState.INVALID);
51 stateMap.put(Job.Status.ACCEPTED, WsJob.JobState.QUEUED);
52 stateMap.put(Job.Status.QUEUED, WsJob.JobState.QUEUED);
53 stateMap.put(Job.Status.RUNNING, WsJob.JobState.RUNNING);
54 stateMap.put(Job.Status.COMPLETED, WsJob.JobState.FINISHED);
55 stateMap.put(Job.Status.INTERRUPTED, WsJob.JobState.CANCELLED);
56 stateMap.put(Job.Status.DELETED, WsJob.JobState.CANCELLED);
57 stateMap.put(Job.Status.FAILED, WsJob.JobState.FAILED);
58 stateMap.put(Job.Status.ERROR, WsJob.JobState.SERVERERROR);
59 stateMap.put(Job.Status.UNKNOWN, WsJob.JobState.UNKNOWN);
61 protected final Set<WsJob.JobState> failedStates = new HashSet<>(Arrays.asList(
62 WsJob.JobState.INVALID, WsJob.JobState.BROKEN, WsJob.JobState.FAILED,
63 WsJob.JobState.SERVERERROR, WsJob.JobState.CANCELLED
66 public SlivkaWebService(SlivkaClient client, SlivkaService service, String operation) {
68 this.service = service;
69 this.operation = operation;
73 public String getHostName() { return client.getUrl().toString(); }
76 public String getName() { return service.getName(); }
79 public String getDescription() { return service.getDescription(); }
82 public String getOperationType() { return operation; }
85 public List<Operation> getOperations() {
89 void addOperation(Operation operation) {
90 operations.add(operation);
93 void removeOperation(Operation operation) {
94 operations.remove(operation);
98 public boolean hasParameters() {
99 return getParamStore().getServiceParameters().size() > 0;
103 public ParamDatastoreI getParamStore() {
105 store = new SlivkaDatastore(service);
111 public WSJob submit(List<SequenceI> sequences, List<ArgumentI> args) throws IOException
113 var request = new uk.ac.dundee.compbio.slivkaclient.JobRequest();
114 for (Parameter param : service.getParameters()) {
115 if (param instanceof Parameter.FileParameter) {
116 // if finds a file input, gives it sequences stream
117 Parameter.FileParameter fileParam = (Parameter.FileParameter) param;
119 switch (fileParam.getMediaType()) {
120 case "application/pfam":
121 format = FileFormat.Pfam;
123 case "application/stockholm":
124 format = FileFormat.Stockholm;
126 case "application/clustal":
127 format = FileFormat.Clustal;
129 case "application/fasta":
131 format = FileFormat.Fasta;
134 InputStream stream = new ByteArrayInputStream(
135 format.getWriter(null)
136 .print(sequences.toArray(new SequenceI[0]), false)
138 request.addFile(param.getId(), stream);
142 for (ArgumentI arg : args) {
143 // multiple choice field names are name$number to avoid duplications
144 // the number is stripped here
145 String paramId = arg.getName().split("\\$", 2)[0];
146 Parameter param = service.getParameter(paramId);
147 if (param instanceof Parameter.FlagParameter) {
148 if (arg.getValue() != null && !arg.getValue().isBlank())
149 request.addData(paramId, true);
151 request.addData(paramId, false);
155 request.addData(paramId, arg.getValue());
159 var job = service.submitJob(request);
160 return new WSJob("slivka", getName(), job.getId(), getHostName());
164 public void updateProgress(WSJob job)
167 // TODO Auto-generated method stub
172 public void cancel(WSJob job) throws IOException
174 Cache.log.warn("Slivka does not support job cancellation yet.");
178 public boolean handleSubmissionError(WSJob job, Exception ex)
180 if (ex instanceof ClientProtocolException) {
181 Cache.log.error("Job submission failed due to exception.", ex);
188 public boolean handleCollectionError(WSJob job, Exception ex)
190 // TODO Auto-generated method stub
194 public AlignmentI getAlignment(WSJob job) throws IOException {
195 Collection<RemoteFile> files;
196 var slivkaJob = client.getJob(job.getJobID());
197 files = slivkaJob.getResults();
198 for (RemoteFile f : files) {
199 if (f.getMediaType().equals("application/clustal")) {
200 return new FormatAdapter().readFile(
201 f.getContentUrl().toString(), DataSourceType.URL, FileFormat.Clustal);
203 else if (f.getMediaType().equals("application/fasta")) {
204 return new FormatAdapter().readFile(
205 f.getContentUrl().toString(), DataSourceType.URL, FileFormat.Fasta);
212 public String toString() {
213 return String.format("SlivkaWebService[%s]", getName());