JAL-3878 Code reformatting.
[jalview.git] / src / jalview / ws2 / slivka / SlivkaWebService.java
1 package jalview.ws2.slivka;
2
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;
12 import java.util.Set;
13
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;
37
38 public class SlivkaWebService implements WebServiceI
39 {
40   protected final SlivkaClient client;
41
42   protected final SlivkaService service;
43
44   protected SlivkaDatastore store = null;
45
46   protected final String operation;
47
48   protected final ArrayList<Operation> operations = new ArrayList<>();
49
50   protected int typeFlags = 0;
51
52   protected static final EnumMap<Job.Status, WsJob.JobState> stateMap = new EnumMap<>(
53           Job.Status.class);
54   {
55     stateMap.put(Job.Status.PENDING, WsJob.JobState.QUEUED);
56     stateMap.put(Job.Status.REJECTED, WsJob.JobState.INVALID);
57     stateMap.put(Job.Status.ACCEPTED, WsJob.JobState.QUEUED);
58     stateMap.put(Job.Status.QUEUED, WsJob.JobState.QUEUED);
59     stateMap.put(Job.Status.RUNNING, WsJob.JobState.RUNNING);
60     stateMap.put(Job.Status.COMPLETED, WsJob.JobState.FINISHED);
61     stateMap.put(Job.Status.INTERRUPTED, WsJob.JobState.CANCELLED);
62     stateMap.put(Job.Status.DELETED, WsJob.JobState.CANCELLED);
63     stateMap.put(Job.Status.FAILED, WsJob.JobState.FAILED);
64     stateMap.put(Job.Status.ERROR, WsJob.JobState.SERVERERROR);
65     stateMap.put(Job.Status.UNKNOWN, WsJob.JobState.UNKNOWN);
66   }
67
68   protected final Set<WsJob.JobState> failedStates = new HashSet<>(
69           Arrays.asList(WsJob.JobState.INVALID, WsJob.JobState.BROKEN,
70                   WsJob.JobState.FAILED, WsJob.JobState.SERVERERROR,
71                   WsJob.JobState.CANCELLED));
72
73   public SlivkaWebService(SlivkaClient client, SlivkaService service,
74           String operation)
75   {
76     this.client = client;
77     this.service = service;
78     this.operation = operation;
79   }
80
81   @Override
82   public String getHostName()
83   {
84     return client.getUrl().toString();
85   }
86
87   @Override
88   public String getProviderName()
89   {
90     return "slivka";
91   }
92
93   @Override
94   public String getName()
95   {
96     return service.getName();
97   }
98
99   @Override
100   public String getDescription()
101   {
102     return service.getDescription();
103   }
104
105   @Override
106   public String getOperationType()
107   {
108     return operation;
109   }
110
111   @Override
112   public List<Operation> getOperations()
113   {
114     return operations;
115   }
116
117   void addOperation(Operation operation)
118   {
119     operations.add(operation);
120   }
121
122   void removeOperation(Operation operation)
123   {
124     operations.remove(operation);
125   }
126
127   @Override
128   public boolean hasParameters()
129   {
130     return getParamStore().getServiceParameters().size() > 0;
131   }
132
133   @Override
134   public ParamDatastoreI getParamStore()
135   {
136     if (store == null)
137     {
138       store = new SlivkaDatastore(service);
139     }
140     return store;
141   }
142
143   @Override
144   public String submit(List<SequenceI> sequences, List<ArgumentI> args)
145           throws IOException
146   {
147     var request = new uk.ac.dundee.compbio.slivkaclient.JobRequest();
148     for (Parameter param : service.getParameters())
149     {
150       if (param instanceof Parameter.FileParameter)
151       {
152         // if finds a file input, gives it sequences stream
153         Parameter.FileParameter fileParam = (Parameter.FileParameter) param;
154         FileFormat format;
155         switch (fileParam.getMediaType())
156         {
157         case "application/pfam":
158           format = FileFormat.Pfam;
159           break;
160         case "application/stockholm":
161           format = FileFormat.Stockholm;
162           break;
163         case "application/clustal":
164           format = FileFormat.Clustal;
165           break;
166         case "application/fasta":
167         default:
168           format = FileFormat.Fasta;
169           break;
170         }
171         InputStream stream = new ByteArrayInputStream(format.getWriter(null)
172                 .print(sequences.toArray(new SequenceI[0]), false)
173                 .getBytes());
174         request.addFile(param.getId(), stream);
175       }
176     }
177     if (args != null)
178     {
179       for (ArgumentI arg : args)
180       {
181         // multiple choice field names are name$number to avoid duplications
182         // the number is stripped here
183         String paramId = arg.getName().split("\\$", 2)[0];
184         Parameter param = service.getParameter(paramId);
185         if (param instanceof Parameter.FlagParameter)
186         {
187           if (arg.getValue() != null && !arg.getValue().isBlank())
188             request.addData(paramId, true);
189           else
190             request.addData(paramId, false);
191         }
192         else
193         {
194           request.addData(paramId, arg.getValue());
195         }
196       }
197     }
198     var job = service.submitJob(request);
199     return job.getId();
200   }
201
202   @Override
203   public void updateProgress(WSJob job) throws IOException
204   {
205     // TODO Auto-generated method stub
206
207   }
208
209   @Override
210   public void cancel(WSJob job) throws IOException
211   {
212     Cache.log.warn("Slivka does not support job cancellation yet.");
213   }
214
215   @Override
216   public boolean handleSubmissionError(WSJob job, Exception ex)
217   {
218     if (ex instanceof ClientProtocolException)
219     {
220       Cache.log.error("Job submission failed due to exception.", ex);
221       return true;
222     }
223     return false;
224   }
225
226   @Override
227   public boolean handleCollectionError(WSJob job, Exception ex)
228   {
229     // TODO Auto-generated method stub
230     return false;
231   }
232
233   public AlignmentI getAlignment(WSJob job) throws IOException
234   {
235     Collection<RemoteFile> files;
236     var slivkaJob = client.getJob(job.getJobId());
237     files = slivkaJob.getResults();
238     for (RemoteFile f : files)
239     {
240       if (f.getMediaType().equals("application/clustal"))
241       {
242         return new FormatAdapter().readFile(f.getContentUrl().toString(),
243                 DataSourceType.URL, FileFormat.Clustal);
244       }
245       else if (f.getMediaType().equals("application/fasta"))
246       {
247         return new FormatAdapter().readFile(f.getContentUrl().toString(),
248                 DataSourceType.URL, FileFormat.Fasta);
249       }
250     }
251     return null;
252   }
253
254   @Override
255   public String toString()
256   {
257     return String.format("SlivkaWebService[%s]", getName());
258   }
259 }