package jalview.ws.slivkaws; import jalview.gui.WebserviceInfo; import jalview.ws.api.JalviewServiceEndpointProviderI; import jalview.ws.api.JalviewWebServiceI; import jalview.ws.api.ServiceWithParameters; import jalview.ws.gui.WsJob; import jalview.ws.params.ParamDatastoreI; import jalview.ws.params.ParamManager; import java.io.IOError; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Arrays; import java.util.EnumMap; import java.util.HashSet; import java.util.Optional; import java.util.Set; 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.SlivkaService; import uk.ac.dundee.compbio.slivkaclient.ValidationException; public abstract class SlivkaWSInstance extends ServiceWithParameters implements JalviewServiceEndpointProviderI, JalviewWebServiceI { protected final SlivkaClient client; protected final SlivkaService service; protected SlivkaDatastore store = null; protected static final 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); } protected final Set failedStates = new HashSet<>(Arrays.asList( WsJob.JobState.INVALID, WsJob.JobState.BROKEN, WsJob.JobState.FAILED, WsJob.JobState.SERVERERROR, WsJob.JobState.CANCELLED )); public SlivkaWSInstance(SlivkaClient client, SlivkaService service, String action) { super(service.getName(), action, service.getLabel(), "Slivka", client.getUrl().toString()); this.client = client; this.service = service; } @Override public final void updateStatus(WsJob job) { try { job.setState(stateMap.get(client.getJobState(job.getJobId()))); } catch (IOException e) { throw new IOError(e); } } @Override public final boolean updateJobProgress(WsJob job) throws IOException { Optional logFile = client.getJobResults(job.getJobId()).stream() .filter(f -> f.getLabel() == "log").findFirst(); if (logFile.isPresent()) { InputStream stream = logFile.get().getContent(); long nextChunk = stream.skip(job.getNextChunk()); job.setnextChunk(nextChunk + appendJobStatus(job, stream)); } if (failedStates.contains(job.getJobState())) { Optional errLogFile = client.getJobResults(job.getJobId()).stream() .filter(f -> f.getLabel() == "error-log").findFirst(); if (errLogFile.isPresent()) { appendJobStatus(job, errLogFile.get().getContent()); } } return false; } private int appendJobStatus(WsJob job, InputStream stream) throws IOException { StringBuilder builder = new StringBuilder(job.getStatus()); InputStreamReader reader = new InputStreamReader(stream); char[] buffer = new char[4096]; int chunkLen = 0; int len = 0; while ((len = reader.read(buffer)) != -1) { chunkLen += len; builder.append(buffer, 0, len); } job.setStatus(builder.toString()); return chunkLen; } @Override public final 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 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 final 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 final ParamDatastoreI getParamStore() { if (store == null) { initParamStore(null); } return store; } }