X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fws%2Fgui%2FMsaWSThread.java;fp=src%2Fjalview%2Fws%2Fjws2%2FMsaWSThread.java;h=7141e73d23dd878c6abfeeb1ce34212ede40d45e;hb=02c1474aa3b80a034a475edd9dc77fe8928ad1f1;hp=b1d6452712e6a542d70256bf2171b7d0668e95b0;hpb=8590d9e6944ed8d8d624d04eac5e56d0ca97c0ed;p=jalview.git diff --git a/src/jalview/ws/jws2/MsaWSThread.java b/src/jalview/ws/gui/MsaWSThread.java similarity index 54% rename from src/jalview/ws/jws2/MsaWSThread.java rename to src/jalview/ws/gui/MsaWSThread.java index b1d6452..7141e73 100644 --- a/src/jalview/ws/jws2/MsaWSThread.java +++ b/src/jalview/ws/gui/MsaWSThread.java @@ -18,42 +18,37 @@ * along with Jalview. If not, see . * The Jalview Authors are detailed in the 'AUTHORS' file. */ -package jalview.ws.jws2; +package jalview.ws.gui; -import jalview.analysis.AlignSeq; import jalview.bin.Cache; import jalview.datamodel.Alignment; import jalview.datamodel.AlignmentI; import jalview.datamodel.AlignmentOrder; import jalview.datamodel.AlignmentView; import jalview.datamodel.HiddenColumns; -import jalview.datamodel.Sequence; import jalview.datamodel.SequenceI; import jalview.gui.AlignFrame; import jalview.gui.Desktop; import jalview.gui.SplitFrame; import jalview.gui.WebserviceInfo; import jalview.util.MessageManager; +import jalview.ws.AWSThread; import jalview.ws.AWsJob; import jalview.ws.JobStateSummary; import jalview.ws.WSClientI; -import jalview.ws.jws2.dm.JabaWsParamSet; +import jalview.ws.api.CancellableI; +import jalview.ws.api.JobId; +import jalview.ws.api.MultipleSequenceAlignmentI; +import jalview.ws.gui.WsJob.JobState; import jalview.ws.params.ArgumentI; import jalview.ws.params.WsParamSetI; import java.util.ArrayList; import java.util.List; -import java.util.Vector; import javax.swing.JInternalFrame; -import compbio.data.msa.MsaWS; -import compbio.metadata.Argument; -import compbio.metadata.ChunkHolder; -import compbio.metadata.JobStatus; -import compbio.metadata.Preset; - -class MsaWSThread extends AWS2Thread implements WSClientI +public class MsaWSThread extends AWSThread implements WSClientI { boolean submitGaps = false; // pass sequences including gaps to alignment @@ -63,377 +58,13 @@ class MsaWSThread extends AWS2Thread implements WSClientI // order - class MsaWSJob extends JWs2Job - { - long lastChunk = 0; - - /** - * input - */ - ArrayList seqs = new ArrayList<>(); - - /** - * output - */ - compbio.data.sequence.Alignment alignment; - - // set if the job didn't get run - then the input is simply returned to the - // user - private boolean returnInput = false; - - /** - * MsaWSJob - * - * @param jobNum - * int - * @param jobId - * String - */ - public MsaWSJob(int jobNum, SequenceI[] inSeqs) - { - this.jobnum = jobNum; - if (!prepareInput(inSeqs, 2)) - { - submitted = true; - subjobComplete = true; - returnInput = true; - } - - } - - Vector emptySeqs = new Vector(); - - /** - * prepare input sequences for MsaWS service - * - * @param seqs - * jalview sequences to be prepared - * @param minlen - * minimum number of residues required for this MsaWS service - * @return true if seqs contains sequences to be submitted to service. - */ - // TODO: return compbio.seqs list or nothing to indicate validity. - private boolean prepareInput(SequenceI[] seqs, int minlen) - { - int nseqs = 0; - if (minlen < 0) - { - throw new Error(MessageManager.getString( - "error.implementation_error_minlen_must_be_greater_zero")); - } - for (int i = 0; i < seqs.length; i++) - { - if (seqs[i].getEnd() - seqs[i].getStart() > minlen - 1) - { - nseqs++; - } - } - boolean valid = nseqs > 1; // need at least two seqs - compbio.data.sequence.FastaSequence seq; - for (int i = 0, n = 0; i < seqs.length; i++) - { - String newname = jalview.analysis.SeqsetUtils.unique_name(i); // same - // for - // any - // subjob - SeqNames.put(newname, - jalview.analysis.SeqsetUtils.SeqCharacterHash(seqs[i])); - if (valid && seqs[i].getEnd() - seqs[i].getStart() > minlen - 1) - { - // make new input sequence with or without gaps - seq = new compbio.data.sequence.FastaSequence(newname, - (submitGaps) ? seqs[i].getSequenceAsString() - : AlignSeq.extractGaps( - jalview.util.Comparison.GapChars, - seqs[i].getSequenceAsString())); - this.seqs.add(seq); - } - else - { - String empty = null; - if (seqs[i].getEnd() >= seqs[i].getStart()) - { - empty = (submitGaps) ? seqs[i].getSequenceAsString() - : AlignSeq.extractGaps(jalview.util.Comparison.GapChars, - seqs[i].getSequenceAsString()); - } - emptySeqs.add(new String[] { newname, empty }); - } - } - return valid; - } - - /** - * - * @return true if getAlignment will return a valid alignment result. - */ - @Override - public boolean hasResults() - { - if (subjobComplete && isFinished() && (alignment != null - || (emptySeqs != null && emptySeqs.size() > 0))) - { - return true; - } - return false; - } - - /** - * - * get the alignment including any empty sequences in the original order - * with original ids. Caller must access the alignment.getMetadata() object - * to annotate the final result passsed to the user. - * - * @return { SequenceI[], AlignmentOrder } - */ - public Object[] getAlignment() - { - // is this a generic subjob or a Jws2 specific Object[] return signature - if (hasResults()) - { - SequenceI[] alseqs = null; - char alseq_gapchar = '-'; - int alseq_l = 0; - if (alignment.getSequences().size() > 0) - { - alseqs = new SequenceI[alignment.getSequences().size()]; - for (compbio.data.sequence.FastaSequence seq : alignment - .getSequences()) - { - alseqs[alseq_l++] = new Sequence(seq.getId(), - seq.getSequence()); - } - alseq_gapchar = alignment.getMetadata().getGapchar(); - - } - // add in the empty seqs. - if (emptySeqs.size() > 0) - { - SequenceI[] t_alseqs = new SequenceI[alseq_l + emptySeqs.size()]; - // get width - int i, w = 0; - if (alseq_l > 0) - { - for (i = 0, w = alseqs[0].getLength(); i < alseq_l; i++) - { - if (w < alseqs[i].getLength()) - { - w = alseqs[i].getLength(); - } - t_alseqs[i] = alseqs[i]; - alseqs[i] = null; - } - } - // check that aligned width is at least as wide as emptySeqs width. - int ow = w, nw = w; - for (i = 0, w = emptySeqs.size(); i < w; i++) - { - String[] es = emptySeqs.get(i); - if (es != null && es[1] != null) - { - int sw = es[1].length(); - if (nw < sw) - { - nw = sw; - } - } - } - // make a gapped string. - StringBuffer insbuff = new StringBuffer(w); - for (i = 0; i < nw; i++) - { - insbuff.append(alseq_gapchar); - } - if (ow < nw) - { - for (i = 0; i < alseq_l; i++) - { - int sw = t_alseqs[i].getLength(); - if (nw > sw) - { - // pad at end - alseqs[i].setSequence(t_alseqs[i].getSequenceAsString() - + insbuff.substring(0, sw - nw)); - } - } - } - for (i = 0, w = emptySeqs.size(); i < w; i++) - { - String[] es = emptySeqs.get(i); - if (es[1] == null) - { - t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(es[0], - insbuff.toString(), 1, 0); - } - else - { - if (es[1].length() < nw) - { - t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence( - es[0], - es[1] + insbuff.substring(0, nw - es[1].length()), - 1, 1 + es[1].length()); - } - else - { - t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence( - es[0], es[1]); - } - } - } - alseqs = t_alseqs; - } - AlignmentOrder msaorder = new AlignmentOrder(alseqs); - // always recover the order - makes parseResult()'s life easier. - jalview.analysis.AlignmentSorter.recoverOrder(alseqs); - // account for any missing sequences - jalview.analysis.SeqsetUtils.deuniquify(SeqNames, alseqs); - return new Object[] { alseqs, msaorder }; - } - return null; - } - - /** - * mark subjob as cancelled and set result object appropriatly - */ - void cancel() - { - cancelled = true; - subjobComplete = true; - alignment = null; - } - - /** - * - * @return boolean true if job can be submitted. - */ - @Override - public boolean hasValidInput() - { - // TODO: get attributes for this MsaWS instance to check if it can do two - // sequence alignment. - if (seqs != null && seqs.size() >= 2) // two or more sequences is valid ? - { - return true; - } - return false; - } - - StringBuffer jobProgress = new StringBuffer(); - - public void setStatus(String string) - { - jobProgress.setLength(0); - jobProgress.append(string); - } - - @Override - public String getStatus() - { - return jobProgress.toString(); - } - - @Override - public boolean hasStatus() - { - return jobProgress != null; - } - - /** - * @return the lastChunk - */ - public long getLastChunk() - { - return lastChunk; - } - - /** - * @param lastChunk - * the lastChunk to set - */ - public void setLastChunk(long lastChunk) - { - this.lastChunk = lastChunk; - } - - String alignmentProgram = null; - - public String getAlignmentProgram() - { - return alignmentProgram; - } - - public boolean hasArguments() - { - return (arguments != null && arguments.size() > 0) - || (preset != null && preset instanceof JabaWsParamSet); - } - - public List getJabaArguments() - { - List newargs = new ArrayList<>(); - if (preset != null && preset instanceof JabaWsParamSet) - { - newargs.addAll(((JabaWsParamSet) preset).getjabaArguments()); - } - if (arguments != null && arguments.size() > 0) - { - newargs.addAll(JabaParamStore.getJabafromJwsArgs(arguments)); - } - return newargs; - } - - /** - * add a progess header to status string containing presets/args used - */ - public void addInitialStatus() - { - if (preset != null) - { - jobProgress.append("Using " - + (preset instanceof JabaPreset ? "Server" : "User") - + "Preset: " + preset.getName()); - if (preset instanceof JabaWsParamSet) - { - for (Argument opt : getJabaArguments()) - { - jobProgress.append( - opt.getName() + " " + opt.getDefaultValue() + "\n"); - } - } - } - if (arguments != null && arguments.size() > 0) - { - jobProgress.append("With custom parameters : \n"); - // merge arguments with preset's own arguments. - for (Argument opt : getJabaArguments()) - { - jobProgress.append( - opt.getName() + " " + opt.getDefaultValue() + "\n"); - } - } - jobProgress.append("\nJob Output:\n"); - } - - public boolean isPresetJob() - { - return preset != null && preset instanceof JabaPreset; - } - - public Preset getServerPreset() - { - return (isPresetJob()) ? ((JabaPreset) preset).p : null; - } - } - String alTitle; // name which will be used to form new alignment window. AlignmentI dataset; // dataset to which the new alignment will be // associated. - @SuppressWarnings("unchecked") - MsaWS server = null; + MultipleSequenceAlignmentI server = null; /** * set basic options for this (group) of Msa jobs @@ -443,7 +74,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI * @param presorder * boolean */ - private MsaWSThread(MsaWS server, String wsUrl, WebserviceInfo wsinfo, + private MsaWSThread(MultipleSequenceAlignmentI server, String wsUrl, + WebserviceInfo wsinfo, jalview.gui.AlignFrame alFrame, AlignmentView alview, String wsname, boolean subgaps, boolean presorder) { @@ -454,7 +86,7 @@ class MsaWSThread extends AWS2Thread implements WSClientI } /** - * create one or more Msa jobs to align visible seuqences in _msa + * create one or more Msa jobs to align visible sequences in _msa * * @param title * String @@ -467,7 +99,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI * @param seqset * Alignment */ - MsaWSThread(MsaWS server2, WsParamSetI preset, List paramset, + public MsaWSThread(MultipleSequenceAlignmentI server2, WsParamSetI preset, + List paramset, String wsUrl, WebserviceInfo wsinfo, jalview.gui.AlignFrame alFrame, String wsname, String title, AlignmentView _msa, boolean subgaps, boolean presorder, @@ -487,11 +120,11 @@ class MsaWSThread extends AWS2Thread implements WSClientI { if (j != 0) { - jobs[j] = new MsaWSJob(wsinfo.addJobPane(), conmsa[j]); + jobs[j] = new MsaWSJob(this, wsinfo.addJobPane(), conmsa[j]); } else { - jobs[j] = new MsaWSJob(0, conmsa[j]); + jobs[j] = new MsaWSJob(this, 0, conmsa[j]); } if (jobs[j].hasValidInput()) { @@ -525,12 +158,14 @@ class MsaWSThread extends AWS2Thread implements WSClientI @Override public boolean isCancellable() { - return true; + return server instanceof CancellableI; } @Override public void cancelJob() { + // TODO decide if when some jobs are not cancellable to shut down the thread + // anyhow ? if (!jobComplete && jobs != null) { boolean cancelled = true; @@ -541,13 +176,11 @@ class MsaWSThread extends AWS2Thread implements WSClientI String cancelledMessage = ""; try { - boolean cancelledJob = server.cancelJob(jobs[job].getJobId()); - if (true) // cancelledJob || true) + CancellableI service = (CancellableI) server; + boolean cancelledJob = service.cancel((WsJob) jobs[job]); + if (cancelledJob) { // CANCELLED_JOB - // if the Jaba server indicates the job can't be cancelled, its - // because its running on the server's local execution engine - // so we just close the window anyway. cancelledMessage = "Job cancelled."; ((MsaWSJob) jobs[job]).cancel(); // TODO: refactor to avoid this // ugliness - @@ -607,42 +240,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI // this is standard code, but since the interface doesn't comprise of a // basic one that implements (getJobStatus, pullExecStatistics) we have to // repeat the code for all jw2s services. - j.setjobStatus(server.getJobStatus(job.getJobId())); - updateJobProgress(j); - } - - /** - * - * @param j - * @return true if more job progress data was available - * @throws Exception - */ - protected boolean updateJobProgress(MsaWSJob j) throws Exception - { - StringBuffer response = j.jobProgress; - long lastchunk = j.getLastChunk(); - boolean changed = false; - do - { - j.setLastChunk(lastchunk); - ChunkHolder chunk = server.pullExecStatistics(j.getJobId(), - lastchunk); - if (chunk != null) - { - changed |= chunk.getChunk().length() > 0; - response.append(chunk.getChunk()); - lastchunk = chunk.getNextPosition(); - try - { - Thread.sleep(50); - } catch (InterruptedException x) - { - } - ; - } - ; - } while (lastchunk >= 0 && j.getLastChunk() != lastchunk); - return changed; + server.updateStatus(j); + server.updateJobProgress(j); } @Override @@ -671,26 +270,37 @@ class MsaWSThread extends AWS2Thread implements WSClientI if (j.seqs == null || j.seqs.size() == 0) { // special case - selection consisted entirely of empty sequences... - j.setjobStatus(JobStatus.FINISHED); + j.setState(JobState.FINISHED); j.setStatus(MessageManager.getString("label.empty_alignment_job")); } try { j.addInitialStatus(); // list the presets/parameters used for the job in // status - if (j.isPresetJob()) + try { - j.setJobId(server.presetAlign(j.seqs, j.getServerPreset())); - } - else if (j.hasArguments()) - { - j.setJobId(server.customAlign(j.seqs, j.getJabaArguments())); - } - else + JobId jobHandle = server.align(j.seqs, j.getPreset(), + j.getArguments()); + if (jobHandle != null) + { + j.setJobHandle(jobHandle); + } + + } catch (Throwable throwable) { - j.setJobId(server.align(j.seqs)); + if (!server.handleSubmitError(throwable, j, wsInfo)) + { + if (throwable instanceof Exception) + { + throw ((Exception) throwable); + } + if (throwable instanceof Error) + { + throw ((Error) throwable); + } + } } - + ///// generic if (j.getJobId() != null) { j.setSubmitted(true); @@ -705,40 +315,11 @@ class MsaWSThread extends AWS2Thread implements WSClientI new String[] { WsUrl })); } - } catch (compbio.metadata.UnsupportedRuntimeException _lex) - { - lex = _lex; - wsInfo.appendProgressText(MessageManager.formatMessage( - "info.job_couldnt_be_run_server_doesnt_support_program", - new String[] - { _lex.getMessage() })); - wsInfo.warnUser(_lex.getMessage(), - MessageManager.getString("warn.service_not_supported")); - wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR); - wsInfo.setStatus(j.getJobnum(), - WebserviceInfo.STATE_STOPPED_SERVERERROR); - } catch (compbio.metadata.LimitExceededException _lex) - { - lex = _lex; - wsInfo.appendProgressText(MessageManager.formatMessage( - "info.job_couldnt_be_run_exceeded_hard_limit", new String[] - { _lex.getMessage() })); - wsInfo.warnUser(_lex.getMessage(), - MessageManager.getString("warn.input_is_too_big")); - wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR); - wsInfo.setStatus(j.getJobnum(), WebserviceInfo.STATE_STOPPED_ERROR); - } catch (compbio.metadata.WrongParameterException _lex) - { - lex = _lex; - wsInfo.warnUser(_lex.getMessage(), - MessageManager.getString("warn.invalid_job_param_set")); - wsInfo.appendProgressText(MessageManager.formatMessage( - "info.job_couldnt_be_run_incorrect_param_setting", - new String[] - { _lex.getMessage() })); - wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR); - wsInfo.setStatus(j.getJobnum(), WebserviceInfo.STATE_STOPPED_ERROR); - } catch (Error e) + } + //// jabaws specific + + //// generic + catch (Error e) { // For unexpected errors System.err.println(WebServiceName @@ -794,7 +375,7 @@ class MsaWSThread extends AWS2Thread implements WSClientI { try { - jpchanged = updateJobProgress(msjob); + jpchanged = server.updateJobProgress(msjob); jpex = false; if (jpchanged) { @@ -835,25 +416,18 @@ class MsaWSThread extends AWS2Thread implements WSClientI System.out.println("*** End of status"); } + ///// jabaws specific(ish) Get Result from Server when available try { - msjob.alignment = server.getResult(msjob.getJobId()); - } catch (compbio.metadata.ResultNotAvailableException e) - { - // job has failed for some reason - probably due to invalid - // parameters - Cache.log.debug( - "Results not available for finished job - marking as broken job.", - e); - msjob.jobProgress.append( - "\nResult not available. Probably due to invalid input or parameter settings. Server error message below:\n\n" - + e.getLocalizedMessage()); - msjob.setjobStatus(JobStatus.FAILED); + msjob.alignment = server.getAlignmentFor(msjob.getJobHandle()); } catch (Exception e) { - Cache.log.error("Couldn't get Alignment for job.", e); - // TODO: Increment count and retry ? - msjob.setjobStatus(JobStatus.UNDEFINED); + if (!server.handleCollectionException(e, msjob, wsInfo)) + { + Cache.log.error("Couldn't get Alignment for job.", e); + // TODO: Increment count and retry ? + msjob.setState(JobState.SERVERERROR); + } } } finalState.updateJobPanelState(wsInfo, OutputHeader, jobs[j]); @@ -861,19 +435,6 @@ class MsaWSThread extends AWS2Thread implements WSClientI && jobs[j].hasResults()) { results++; - compbio.data.sequence.Alignment alignment = ((MsaWSJob) jobs[j]).alignment; - if (alignment != null) - { - // server.close(jobs[j].getJobnum()); - // wsInfo.appendProgressText(jobs[j].getJobnum(), - // "\nAlignment Object Method Notes\n"); - // wsInfo.appendProgressText(jobs[j].getJobnum(), - // "Calculated with - // "+alignment.getMetadata().getProgram().toString()); - // JBPNote The returned files from a webservice could be - // hidden behind icons in the monitor window that, - // when clicked, pop up their corresponding data - } } } } catch (Exception ex)