X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fws%2Fslivkaws%2FSlivkaWSInstance.java;h=d3701acec26ff83e4755f4c63f9fe2de760e2c64;hb=80d446099e8d1a83a73e64870c8e08903a003b00;hp=8bb554a3ef0fb83f062c84a0f241784897b9da25;hpb=d3f8117988649e07fcd27a5e5623a1af6391b508;p=jalview.git diff --git a/src/jalview/ws/slivkaws/SlivkaWSInstance.java b/src/jalview/ws/slivkaws/SlivkaWSInstance.java index 8bb554a..d3701ac 100644 --- a/src/jalview/ws/slivkaws/SlivkaWSInstance.java +++ b/src/jalview/ws/slivkaws/SlivkaWSInstance.java @@ -1,5 +1,16 @@ package jalview.ws.slivkaws; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOError; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.EnumMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceI; import jalview.gui.WebserviceInfo; @@ -7,186 +18,218 @@ import jalview.io.DataSourceType; import jalview.io.FileFormat; import jalview.io.FormatAdapter; import jalview.ws.api.JalviewServiceEndpointProviderI; +import jalview.ws.api.JalviewWebServiceI; 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 javajs.http.ClientProtocolException; -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 java.util.Collection; +import uk.ac.dundee.compbio.slivkaclient.Job; +import uk.ac.dundee.compbio.slivkaclient.RequestValues; +import uk.ac.dundee.compbio.slivkaclient.Parameter; 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 +public abstract class SlivkaWSInstance extends ServiceWithParameters + implements JalviewServiceEndpointProviderI, JalviewWebServiceI { - private SlivkaClient client; - private SlivkaService service; - private SlivkaDatastore store = null; + protected final SlivkaClient client; + + protected final SlivkaService service; - private EnumMap stateMap = new EnumMap<>(JobState.class); + protected SlivkaDatastore store = null; + + protected static final EnumMap stateMap = new EnumMap<>(Job.Status.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); + stateMap.put(Job.Status.PENDING, WsJob.JobState.QUEUED); + stateMap.put(Job.Status.REJECTED, WsJob.JobState.INVALID); + stateMap.put(Job.Status.ACCEPTED, WsJob.JobState.QUEUED); + stateMap.put(Job.Status.QUEUED, WsJob.JobState.QUEUED); + stateMap.put(Job.Status.RUNNING, WsJob.JobState.RUNNING); + stateMap.put(Job.Status.COMPLETED, WsJob.JobState.FINISHED); + stateMap.put(Job.Status.INTERRUPTED, WsJob.JobState.CANCELLED); + stateMap.put(Job.Status.DELETED, WsJob.JobState.CANCELLED); + stateMap.put(Job.Status.FAILED, WsJob.JobState.FAILED); + stateMap.put(Job.Status.ERROR, WsJob.JobState.SERVERERROR); + stateMap.put(Job.Status.UNKNOWN, WsJob.JobState.UNKNOWN); } + protected final Set failedStates = new HashSet<>(Arrays.asList( + WsJob.JobState.INVALID, WsJob.JobState.BROKEN, WsJob.JobState.FAILED, + WsJob.JobState.SERVERERROR, WsJob.JobState.CANCELLED + )); - SlivkaWSInstance(SlivkaClient client, SlivkaService service) { - super(service.getName(), "Alignment", service.getName(), "Slivka", client.getUrl().toString()); + public SlivkaWSInstance(SlivkaClient client, SlivkaService service, String action) + { + super(action, action, service.getName(), "Slivka", client.getUrl().toString()); this.client = client; this.service = service; } - @Override - public void updateStatus(WsJob job) + protected final JobId submit(List sequences, + WsParamSetI preset, List args) throws Throwable { - try - { - job.setState(stateMap.get(client.getJobState(job.getJobId()))); - } catch (IOException e) + var parameters = service.getParameters(); + var request = new RequestValues(); + for (Parameter param : parameters) { - throw new RuntimeException(e); + if (param instanceof Parameter.FileParameter) + { + FormatAdapter fa = new FormatAdapter(); + fa.setNewlineString("\r\n"); + Parameter.FileParameter fileParam = (Parameter.FileParameter) param; + FileFormat format; + switch (fileParam.getMediaType()) + { + case "application/pfam": + format = FileFormat.Pfam; + break; + case "application/stockholm": + format = FileFormat.Stockholm; + break; + default: + case "application/fasta": + format = FileFormat.Fasta; + break; + } + + // we avoid any use of Jalview's user facing export routines here + + InputStream stream = new ByteArrayInputStream(format.getWriter(null) + .print(sequences.toArray(new SequenceI[0]), false) + .getBytes()); + request.addFile(param.getId(), stream); + } } - } - - 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) + if (args != null) { - FormValidationException formError = (FormValidationException) _lex; - String[] messages = new String[formError.getErrors().size()]; - int i = 0; - for (ValidationException e : formError.getErrors()) + for (ArgumentI arg : args) { - messages[i++] = String.format("%s: %s,", e.getField().getName(), e.getMessage()); + // multiple choice field names are name$number to avoid duplications + // the number is stripped here + String paramId = arg.getName().split("\\$", 2)[0]; + Parameter param = service.getParameter(paramId); + if (param instanceof Parameter.FlagParameter) { + if (arg.getValue() != null && !arg.getValue().isBlank()) + request.addData(paramId, true); + else + request.addData(paramId, false); + } + else + { + request.addData(paramId, arg.getValue()); + } } - j.setState(WsJob.JobState.INVALID); - j.setStatus(String.join(", ", messages)); - return true; } - return false; + var jobId = client.submitJob(service, request); + return new JobId(service.getName(), service.getName(), jobId); } @Override - public boolean handleCollectionException(Exception e, WsJob msjob, WebserviceInfo wsInfo) + public final void updateStatus(WsJob job) { - return false; + try + { + job.setState(stateMap.get(client.fetchJobStatus(job.getJobId()))); + } catch (IOException e) + { + throw new IOError(e); + } } @Override - public JobId align(List toalign, WsParamSetI parameters, List list) throws Throwable - { - StringBuilder builder = new StringBuilder(); - for (SequenceI seq : toalign) + public final boolean updateJobProgress(WsJob job) throws IOException + { + Collection files = client.fetchFilesList(job.getJobId()); + RemoteFile logFile=null; + for (RemoteFile f : files) { - 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) + if (f.getLabel().equals("log")) { - values.put(arg.getName(), arg.getValue()); + logFile = f; break; } } - for (FormField field : form.getFields()) + + boolean newContent = false; + if (logFile!=null) { - 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()))); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + client.writeFileTo(logFile, output); + if (output.size() > job.getNextChunk()) + { + newContent = true; + job.setStatus(output.toString("UTF-8")); + job.setnextChunk(output.size()); } } - return new JobId(service.getName(), service.getName(), form.submit()); - } - - @Override - public AlignmentI getAlignmentFor(JobId jobId) throws InvalidArgumentException, ServerError, IOError - { - List files; - try + if (failedStates.contains(job.getJobState())) { - files = client.getJobResults(jobId.getJobId()); + + RemoteFile errLogFile = null; for (RemoteFile f : files) { - if (f.getMimeType().equals("application/clustal")) + if (f.getLabel().equals("error-log")) { - return new FormatAdapter().readFile(f.getURL().toString(), DataSourceType.URL, FileFormat.Clustal); + errLogFile = f; + break; } - else if (f.getMimeType().equals("application/fasta")) + } + + if (errLogFile!=null) + { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + client.writeFileTo(errLogFile, output); + if (output.size() > 0) { - return new FormatAdapter().readFile(f.getURL().toString(), DataSourceType.URL, FileFormat.Fasta); + newContent = true; + job.setStatus(job.getStatus() + "\n" + output.toString("UTF-8")); } } - } catch (IOException e) + } + return newContent; + } + + @Override + public final boolean handleSubmitError(Throwable _lex, WsJob j, WebserviceInfo wsInfo) + { + if (_lex instanceof ClientProtocolException) { - throw new IOError(e); + j.setState(WsJob.JobState.INVALID); + j.setStatus(_lex.getMessage()); + return true; } - return null; + return false; } @Override - public Object getEndpoint() + public final boolean handleCollectionException(Exception e, WsJob msjob, WebserviceInfo wsInfo) + { + // TODO + return false; + } + + final SlivkaService getService() + { + return service; + } + + @Override + public final Object getEndpoint() { return this; } @Override - public void initParamStore(ParamManager userParameterStore) + public final void initParamStore(ParamManager userParameterStore) { if (store == null) { - try - { - store = new SlivkaDatastore(service); - } catch (IOException e) - { - throw new IOError(e); - } + store = new SlivkaDatastore(service); } } @@ -197,8 +240,27 @@ public class SlivkaWSInstance extends ServiceWithParameters } @Override - public ParamDatastoreI getParamStore() + public final ParamDatastoreI getParamStore() { + if (store == null) + { + initParamStore(null); + } return store; } + + public static AlignmentI readAlignment(RemoteFile f) throws IOException + { + final var mimetype = f.getMediaType(); + FileFormat format; + if (mimetype.equals("application/clustal")) + format = FileFormat.Clustal; + else if (mimetype.equals("application/fasta")) + format = FileFormat.Fasta; + else + return null; + return new FormatAdapter().readFile(f.getContentUrl().toString(), + DataSourceType.URL, format); + } + }