package jalview.ws.slivkaws; import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceI; import jalview.gui.WebserviceInfo; import jalview.io.DataSourceType; import jalview.io.FileFormat; import jalview.io.FormatAdapter; import jalview.ws.api.JalviewServiceEndpointProviderI; import jalview.ws.api.JobId; import jalview.ws.api.MultipleSequenceAlignmentI; import jalview.ws.api.ServiceWithParameters; import jalview.ws.gui.WsJob; import jalview.ws.params.ArgumentI; import jalview.ws.params.InvalidArgumentException; import jalview.ws.params.ParamDatastoreI; import jalview.ws.params.ParamManager; import jalview.ws.params.WsParamSetI; import java.io.ByteArrayInputStream; import java.io.IOError; import java.io.IOException; import java.io.InputStream; import java.rmi.ServerError; import java.util.EnumMap; import java.util.HashMap; import java.util.List; import uk.ac.dundee.compbio.slivkaclient.FormField; import uk.ac.dundee.compbio.slivkaclient.FormValidationException; import uk.ac.dundee.compbio.slivkaclient.JobState; import uk.ac.dundee.compbio.slivkaclient.RemoteFile; import uk.ac.dundee.compbio.slivkaclient.SlivkaClient; import uk.ac.dundee.compbio.slivkaclient.SlivkaForm; import uk.ac.dundee.compbio.slivkaclient.SlivkaService; import uk.ac.dundee.compbio.slivkaclient.ValidationException; public class SlivkaWSInstance extends ServiceWithParameters implements MultipleSequenceAlignmentI, JalviewServiceEndpointProviderI { private SlivkaClient client; private SlivkaService service; private SlivkaDatastore store = null; private EnumMap stateMap = new EnumMap<>(JobState.class); { stateMap.put(JobState.PENDING, WsJob.JobState.QUEUED); stateMap.put(JobState.QUEUED, WsJob.JobState.QUEUED); stateMap.put(JobState.RUNNING, WsJob.JobState.RUNNING); stateMap.put(JobState.COMPLETED, WsJob.JobState.FINISHED); stateMap.put(JobState.FAILED, WsJob.JobState.FAILED); stateMap.put(JobState.ERROR, WsJob.JobState.SERVERERROR); stateMap.put(JobState.UNKNOWN, WsJob.JobState.UNKNOWN); } SlivkaWSInstance(SlivkaClient client, SlivkaService service) { super(service.getName(), "Alignment", service.getName(), "Slivka", client.getUrl().toString()); this.client = client; this.service = service; } @Override public void updateStatus(WsJob job) { try { job.setState(stateMap.get(client.getJobState(job.getJobId()))); } catch (IOException e) { throw new RuntimeException(e); } } SlivkaService getService() { return service; } @Override public boolean updateJobProgress(WsJob job) { return false; } @Override public boolean handleSubmitError(Throwable _lex, WsJob j, WebserviceInfo wsInfo) { if (_lex instanceof FormValidationException) { FormValidationException formError = (FormValidationException) _lex; String[] messages = new String[formError.getErrors().size()]; int i = 0; for (ValidationException e : formError.getErrors()) { messages[i++] = String.format("%s: %s,", e.getField().getName(), e.getMessage()); } j.setState(WsJob.JobState.INVALID); j.setStatus(String.join(", ", messages)); return true; } return false; } @Override public boolean handleCollectionException(Exception e, WsJob msjob, WebserviceInfo wsInfo) { return false; } @Override public JobId align(List toalign, WsParamSetI parameters, List list) throws Throwable { StringBuilder builder = new StringBuilder(); for (SequenceI seq : toalign) { builder.append(">").append(seq.getName()).append("\n"); builder.append(seq.getSequence()).append("\n"); } InputStream stream = new ByteArrayInputStream(builder.toString().getBytes()); RemoteFile file = client.uploadFile(stream, "input.fasta", "application/fasta"); SlivkaForm form = service.getForm(); HashMap values = new HashMap<>(list != null ? list.size() : 0); if (list != null) { for (ArgumentI arg : list) { values.put(arg.getName(), arg.getValue()); } } for (FormField field : form.getFields()) { switch (field.getType()) { case FILE: form.insert(field.getName(), file); break; case BOOLEAN: String value = values.get(field.getName()); form.insert(field.getName(), (value != null && !value.isBlank()) ? true : false); break; default: form.insert(field.getName(), field.valueOf(values.get(field.getName()))); } } return new JobId(service.getName(), service.getName(), form.submit()); } @Override public AlignmentI getAlignmentFor(JobId jobId) throws InvalidArgumentException, ServerError, IOError { List files; try { files = client.getJobResults(jobId.getJobId()); for (RemoteFile f : files) { if (f.getMimeType().equals("application/clustal")) { return new FormatAdapter().readFile(f.getURL().toString(), DataSourceType.URL, FileFormat.Clustal); } } } catch (IOException e) { throw new IOError(e); } return null; } @Override public Object getEndpoint() { return this; } @Override public void initParamStore(ParamManager userParameterStore) { if (store == null) { try { store = new SlivkaDatastore(service); } catch (IOException e) { throw new IOError(e); } } } @Override public boolean hasParameters() { return true; } @Override public ParamDatastoreI getParamStore() { return store; } }