From 4c565a64e0601ea344f1d587851d0aa48ff5c388 Mon Sep 17 00:00:00 2001 From: Mateusz Warowny Date: Mon, 20 Sep 2021 18:13:21 +0200 Subject: [PATCH] JAL-3878 Create base interfaces for new web services. --- src/jalview/ws2/JalviewWebServiceI.java | 67 -------- src/jalview/ws2/MenuEntryProviderI.java | 3 +- src/jalview/ws2/MsaMenuEntryProvider.java | 211 ------------------------ src/jalview/ws2/ResultSupplier.java | 9 + src/jalview/ws2/WSJob.java | 198 ++++++++++++++++++++++ src/jalview/ws2/WSJobID.java | 69 -------- src/jalview/ws2/WSJobState.java | 57 ------- src/jalview/ws2/WSJobStatus.java | 103 ++++++++++++ src/jalview/ws2/WSJobTrackerI.java | 9 - src/jalview/ws2/WebServiceDiscoverer.java | 58 +++++++ src/jalview/ws2/WebServiceI.java | 53 ++++++ src/jalview/ws2/WebServiceInfoUpdater.java | 89 ++++++++++ src/jalview/ws2/WebServiceThreadListenerI.java | 14 ++ src/jalview/ws2/WebServiceWorkerI.java | 70 ++------ src/jalview/ws2/utils/WSJobList.java | 64 +++++++ 15 files changed, 606 insertions(+), 468 deletions(-) delete mode 100755 src/jalview/ws2/JalviewWebServiceI.java delete mode 100755 src/jalview/ws2/MsaMenuEntryProvider.java create mode 100644 src/jalview/ws2/ResultSupplier.java create mode 100755 src/jalview/ws2/WSJob.java delete mode 100755 src/jalview/ws2/WSJobID.java delete mode 100755 src/jalview/ws2/WSJobState.java create mode 100755 src/jalview/ws2/WSJobStatus.java delete mode 100755 src/jalview/ws2/WSJobTrackerI.java create mode 100644 src/jalview/ws2/WebServiceDiscoverer.java create mode 100755 src/jalview/ws2/WebServiceI.java create mode 100644 src/jalview/ws2/WebServiceInfoUpdater.java create mode 100644 src/jalview/ws2/WebServiceThreadListenerI.java create mode 100644 src/jalview/ws2/utils/WSJobList.java diff --git a/src/jalview/ws2/JalviewWebServiceI.java b/src/jalview/ws2/JalviewWebServiceI.java deleted file mode 100755 index 6e65dd0..0000000 --- a/src/jalview/ws2/JalviewWebServiceI.java +++ /dev/null @@ -1,67 +0,0 @@ -package jalview.ws2; - -import java.io.IOException; -import java.util.List; - -import jalview.datamodel.SequenceI; -import jalview.ws.params.ArgumentI; -import jalview.ws.params.ParamDatastoreI; -import jalview.ws.params.WsParamSetI; - -/** - * Provides information about the web service and sub-routines - * to submit and track the jobs running on the server as well as - * retrieve the results. - * The instances should not depend on any other jalview components, especially - * must be oblivious to the existence of any UI. - * They are used by other classes such as WebServiceWorkers rather than - * manipulate data themselves. - * - * @author mmwarowny - * - * @param - */ -public interface JalviewWebServiceI -{ - public static final int PROTEIN_SERVICE = 0x01; - public static final int NUCLEOTIDE_SERVICE = 0x02; - public static final int ALIGNMENT_ANALYSIS = 0x04; - - public String getHostName(); - public String getName(); - public String getDescription(); - public String getOperationType(); - public int getTypeFlags(); - public boolean canSubmitGaps(); - public int getMinSequences(); - public int getMaxSequences(); - public boolean hasParameters(); - public ParamDatastoreI getParamStore(); - - public default boolean isProteinService() { - return (getTypeFlags() & PROTEIN_SERVICE) > 0; - } - public default boolean isNucleotideService() { - return (getTypeFlags() & NUCLEOTIDE_SERVICE) > 0; - } - public default boolean isAlignmentAnalysis() { - return (getTypeFlags() & ALIGNMENT_ANALYSIS) > 0; - } - - public WSJobID submit(List sequences, WsParamSetI preset, - List parameters) throws IOException; - - public void updateProgress(WSJobID id, WSJobTrackerI tracker) - throws IOException; - - public R getResult(WSJobID id) throws IOException; - - public void cancel(WSJobID id) throws IOException; - - public boolean handleSubmissionError(WSJobID id, Throwable th, - WSJobTrackerI tracker); - - public boolean handleCollectionError(WSJobID id, Throwable th, - WSJobTrackerI tracker); - -} diff --git a/src/jalview/ws2/MenuEntryProviderI.java b/src/jalview/ws2/MenuEntryProviderI.java index ac08c49..a5e2d0f 100755 --- a/src/jalview/ws2/MenuEntryProviderI.java +++ b/src/jalview/ws2/MenuEntryProviderI.java @@ -7,6 +7,5 @@ import jalview.gui.AlignFrame; @FunctionalInterface public interface MenuEntryProviderI { - public void buildMenu(JMenu parent, JalviewWebServiceI service, - AlignFrame frame); + public void buildMenu(JMenu parent, AlignFrame frame); } diff --git a/src/jalview/ws2/MsaMenuEntryProvider.java b/src/jalview/ws2/MsaMenuEntryProvider.java deleted file mode 100755 index d29f638..0000000 --- a/src/jalview/ws2/MsaMenuEntryProvider.java +++ /dev/null @@ -1,211 +0,0 @@ -package jalview.ws2; - -import java.util.List; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.Collections; - -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.ToolTipManager; - -import jalview.datamodel.AlignmentI; -import jalview.datamodel.AlignmentView; -import jalview.datamodel.SequenceI; -import jalview.gui.AlignFrame; -import jalview.gui.JvSwingUtils; -import jalview.gui.WsJobParameters; -import jalview.util.MathUtils; -import jalview.util.MessageManager; -import jalview.ws.params.ArgumentI; -import jalview.ws.params.WsParamSetI; -import static java.lang.String.format; - - -class MsaWSWorker implements WebServiceWorkerI -{ - private long uid = MathUtils.getUID(); - - JalviewWebServiceI> service; - - private final AlignmentView msa; - - private final AlignmentI seqdataset; - - private boolean submitGaps = false; - - private boolean preserveOrder = false; - - private List parameters = Collections.emptyList(); - - MsaWSWorker(JalviewWebServiceI> service, AlignmentView msa, - boolean submitGaps, boolean preserveOrder, AlignmentI seqdataset) - { - this.service = service; - this.msa = msa; - this.seqdataset = seqdataset; - this.submitGaps = submitGaps; - this.preserveOrder = preserveOrder; - } - - @Override public long getUID() { - return uid; - }; - - void setParameters(List parameters) - { - this.parameters = parameters; - } - - @Override - public WSJobID startJob(WSJob job) { - return new WSJobID(service.getName(), service.getClass().toString(), "0"); - } - - @Override - public List getJobs() { - return Collections.emptyList(); - } - - @Override - public boolean pollJob(WSJob job) { - return false; - } - -} - -public class MsaMenuEntryProvider implements MenuEntryProviderI -{ - WebServiceExecutor executor; - - public MsaMenuEntryProvider(WebServiceExecutor executor) - { - this.executor = executor; - } - - @Override - public void buildMenu(JMenu parent, JalviewWebServiceI service, AlignFrame frame) - { - if (service.canSubmitGaps()) - { - var alignSubmenu = new JMenu(service.getName()); - buildMenu(alignSubmenu, service, frame, false); - parent.add(alignSubmenu); - var realignSubmenu = new JMenu(MessageManager.formatMessage( - "label.realign_with_params", service.getName())); - realignSubmenu.setToolTipText(MessageManager - .getString("label.align_sequences_to_existing_alignment")); - buildMenu(realignSubmenu, service, frame, true); - parent.add(realignSubmenu); - } - else - { - buildMenu(parent, service, frame, false); - } - } - - private void buildMenu(JMenu parent, JalviewWebServiceI> service, - AlignFrame frame, boolean submitGaps) - { - final String action = submitGaps ? "Align" : "Realign"; - final var calcName = service.getName(); - - { - var item = new JMenuItem(MessageManager.formatMessage( - "label.calcname_with_default_settings", calcName)); - item.setToolTipText(MessageManager.formatMessage( - "label.action_with_default_settings", action)); - item.addActionListener((event) -> { - AlignmentView msa = frame.gatherSequencesForAlignment(); - AlignmentI dataset = frame.getViewport().getAlignment().getDataset(); - if (msa != null) - { - executor.submit(new MsaWSWorker(service, msa, submitGaps, true, dataset)); - } - }); - parent.add(item); - } - - if (service.hasParameters()) - { - var item = new JMenuItem(MessageManager.getString("label.edit_settings_and_run")); - item.setToolTipText(MessageManager.getString( - "label.view_and_change_parameters_before_alignment")); - item.addActionListener((event) -> { - AlignmentView msa = frame.gatherSequencesForAlignment(); - AlignmentI dataset = frame.getViewport().getAlignment().getDataset(); - if (msa != null) - { - var parameters = openEditParamsDialog(service, null, null); - if (parameters != null) - { - var thread = new MsaWSWorker(service, msa, submitGaps, true, dataset); - thread.setParameters(parameters); - executor.submit(thread); - } - } - }); - parent.add(item); - } - - var presets = service.getParamStore().getPresets(); - if (presets != null && presets.size() > 0) - { - final var presetList = new JMenu(MessageManager.formatMessage( - "label.run_with_preset_params", calcName)); - final var showToolTipFor = ToolTipManager.sharedInstance().getDismissDelay(); - for (final var preset : presets) - { - var item = new JMenuItem(preset.getName()); - final int QUICK_TOOLTIP = 1500; - item.addMouseListener(new MouseAdapter() - { - @Override public void mouseEntered(MouseEvent e) - { - ToolTipManager.sharedInstance().setDismissDelay(QUICK_TOOLTIP); - } - @Override public void mouseExited(MouseEvent e) - { - ToolTipManager.sharedInstance().setDismissDelay(showToolTipFor); - } - }); - String tooltip = JvSwingUtils.wrapTooltip(true, format( - "%s
%s", - MessageManager.getString(preset.isModifiable() ? - "label.user_preset" : "label.service_preset"), - preset.getDescription())); - item.setToolTipText(tooltip); - item.addActionListener((event) -> { - AlignmentView msa = frame.gatherSequencesForAlignment(); - AlignmentI dataset = frame.getViewport().getAlignment().getDataset(); - if (msa != null) - { - var thread = new MsaWSWorker(service, msa, submitGaps, true, dataset); - thread.setParameters(preset.getArguments()); - executor.submit(thread); - } - }); - presetList.add(item); - } - parent.add(presetList); - } - - } - - private List openEditParamsDialog(JalviewWebServiceI service, - WsParamSetI preset, List arguments) - { - WsJobParameters jobParams; - if (preset == null && arguments != null && arguments.size() > 0) - jobParams = new WsJobParameters(service.getParamStore(), preset, arguments); - else - jobParams = new WsJobParameters(service.getParamStore(), preset, null); - if (!jobParams.showRunDialog()) - // cancelled - return null; - if (jobParams.getPreset() == null) - return jobParams.getJobParams(); - else - return jobParams.getPreset().getArguments(); - } -} diff --git a/src/jalview/ws2/ResultSupplier.java b/src/jalview/ws2/ResultSupplier.java new file mode 100644 index 0000000..e691b80 --- /dev/null +++ b/src/jalview/ws2/ResultSupplier.java @@ -0,0 +1,9 @@ +package jalview.ws2; + +import java.io.IOException; + +@FunctionalInterface +public interface ResultSupplier +{ + public T getResult(WSJob job) throws IOException; +} diff --git a/src/jalview/ws2/WSJob.java b/src/jalview/ws2/WSJob.java new file mode 100755 index 0000000..90ee0b7 --- /dev/null +++ b/src/jalview/ws2/WSJob.java @@ -0,0 +1,198 @@ +package jalview.ws2; + +import java.io.Serializable; +import java.net.URI; +import java.util.Date; + +import jalview.util.MathUtils; + +import static java.lang.String.format; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +/** + * An id handler to the external job running on the server. This is the smallest + * job unit which might me a part of a larger multi-stage or parallel task + * handled by the WebServiceWorker. Jobs are created by the JalviewWebService on + * job submission and are used to identify that job during its lifetime. It can + * be serialized and used between application launches. + * + * @author mmwarowny + * + */ +public final class WSJob implements Serializable +{ + private static final long serialVersionUID = -4600214977954333787L; + + /* Client-side identifier */ + public final long uid = MathUtils.getUID(); + + private int jobNum = 0; + + /* Shortened server name e.g. "slivka" or "jabaws" */ + private String serviceProvider = ""; + + /* Name of the service e.g. "ClustalW2" */ + private String serviceName = ""; + + /* Server-side identifier */ + private String jobID = ""; + + private WSJobStatus status = WSJobStatus.UNKNOWN; + + private String log = ""; + + private String errorLog = ""; + + /* Base url of the server associated with the job */ + private String hostName = ""; + + private Date creationTime = new Date(); + + public PropertyChangeSupport pcs = new PropertyChangeSupport(this); + + public WSJob() + { + } + + public WSJob(String serviceProvider, String serviceName, String jobID, + String hostName) + { + this.serviceProvider = serviceProvider; + this.serviceName = serviceName; + this.jobID = jobID; + this.hostName = hostName; + } + + @Override + public String toString() + { + return format("%s:%s [%s] Created %s", serviceProvider, serviceName, + jobID, creationTime); + } + + public int getJobNum() + { + return jobNum; + } + + public void setJobNum(int jobNum) + { + this.jobNum = jobNum; + } + + public WSJobStatus getStatus() + { + return status; + } + + public void setStatus(WSJobStatus status) + { + var oldStatus = this.status; + this.status = status; + pcs.firePropertyChange("status", oldStatus, status); + } + + public String getLog() + { + return log; + } + + public void setLog(String log) + { + var oldLog = this.log; + this.log = log; + pcs.firePropertyChange("log", oldLog, log); + } + + public String getErrorLog() + { + return errorLog; + } + + public void setErrorLog(String log) + { + String oldErrorLog = this.errorLog; + this.errorLog = log; + pcs.firePropertyChange("errorLog", oldErrorLog, this.errorLog); + } + + public long getUid() + { + return uid; + } + + public String getServiceProvider() + { + return serviceProvider; + } + + public void setServiceProvider(String serviceProvider) + { + this.serviceProvider = serviceProvider; + } + + public String getServiceName() + { + return serviceName; + } + + public void setServiceName(String serviceName) + { + this.serviceName = serviceName; + } + + public String getJobID() + { + return jobID; + } + + public void setJobID(String jobID) + { + this.jobID = jobID; + } + + public String getHostName() + { + return hostName; + } + + public void setHostName(String hostName) + { + this.hostName = hostName; + } + + public Date getCreationTime() + { + return creationTime; + } + + public void setCreationTime(Date creationTime) + { + this.creationTime = creationTime; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) + { + pcs.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) + { + pcs.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) + { + pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChagneListener(String propertyName, + PropertyChangeListener listener) + { + pcs.removePropertyChangeListener(propertyName, listener); + } + +} diff --git a/src/jalview/ws2/WSJobID.java b/src/jalview/ws2/WSJobID.java deleted file mode 100755 index 97a1f1a..0000000 --- a/src/jalview/ws2/WSJobID.java +++ /dev/null @@ -1,69 +0,0 @@ -package jalview.ws2; - -import java.io.Serializable; -import java.util.Date; -import static java.lang.String.format; - -public final class WSJobID implements Serializable -{ - private static final long serialVersionUID = -4600214977954333787L; - private String serviceType = ""; - private String serviceImpl = ""; - private String jobID = ""; - private Date creationTime = new Date(); - - public WSJobID() {} - - public WSJobID(String serviceType, String serviceImpl, String jobID) { - this.serviceType = serviceType; - this.serviceImpl = serviceImpl; - this.jobID = jobID; - } - - @Override - public String toString() { - return format("%s:%s [%s] Created %s", - serviceType, serviceImpl, jobID, creationTime); - } - - public String getServiceType() - { - return serviceType; - } - - public void setServiceType(String serviceType) - { - this.serviceType = serviceType; - } - - public String getServiceImpl() - { - return serviceImpl; - } - - public void setServiceImpl(String serviceImpl) - { - this.serviceImpl = serviceImpl; - } - - public String getJobID() - { - return jobID; - } - - public void setJobID(String jobID) - { - this.jobID = jobID; - } - - public Date getCreationTime() - { - return creationTime; - } - - public void setCreationTime(Date creationTime) - { - this.creationTime = creationTime; - } - -} diff --git a/src/jalview/ws2/WSJobState.java b/src/jalview/ws2/WSJobState.java deleted file mode 100755 index 719fdbd..0000000 --- a/src/jalview/ws2/WSJobState.java +++ /dev/null @@ -1,57 +0,0 @@ -package jalview.ws2; - - -public enum WSJobState -{ - INVALID, READY, SUBMITTED, QUEUED, RUNNING, FINISHED, BROKEN, FAILED, - UNKNOWN, SERVER_ERROR, CANCELLED; - - public boolean isSubmitted() - { - switch (this) - { - case INVALID: - case READY: - return false; - default: - return true; - } - } - - public boolean isCancelled() - { - return this == WSJobState.CANCELLED; - } - - public boolean isDone() - { - switch (this) - { - case INVALID: - case READY: - case SUBMITTED: - case QUEUED: - case RUNNING: - return false; - default: - return true; - } - } - - public boolean isRunning() - { - switch (this) - { - case QUEUED: - case RUNNING: - return true; - default: - return false; - } - } - - public boolean isQueued() - { - return this == WSJobState.SUBMITTED; - } -} \ No newline at end of file diff --git a/src/jalview/ws2/WSJobStatus.java b/src/jalview/ws2/WSJobStatus.java new file mode 100755 index 0000000..056decf --- /dev/null +++ b/src/jalview/ws2/WSJobStatus.java @@ -0,0 +1,103 @@ +package jalview.ws2; + + +public enum WSJobStatus +{ + /** Job has invalid parameters and cannot be started. */ + INVALID, + /** Job is ready to be submitted. */ + READY, + /** Job has been submitted and awaits processing. */ + SUBMITTED, + /** Job has been queued for execution. */ + QUEUED, + /** Job is running. */ + RUNNING, + /** Job has finished with no errors. */ + FINISHED, + BROKEN, + /** Job has finished with errors. */ + FAILED, + /** Job cannot be processed or completed due to server error. */ + SERVER_ERROR, + /** Job has been cancelled. */ + CANCELLED, + /** Status cannot be determined. */ + UNKNOWN; + + + public boolean isSubmitted() + { + switch (this) + { + case SUBMITTED: + case QUEUED: + case RUNNING: + case FINISHED: + case BROKEN: + case FAILED: + case SERVER_ERROR: + case CANCELLED: + return true; + case INVALID: + case READY: + default: + return false; + } + } + + public boolean isCancelled() + { + return this == WSJobStatus.CANCELLED; + } + + public boolean isDone() + { + switch (this) + { + case FINISHED: + case BROKEN: + case FAILED: + case SERVER_ERROR: + case CANCELLED: + return true; + case INVALID: + case READY: + case SUBMITTED: + case QUEUED: + case RUNNING: + default: + return false; + } + } + + public boolean isFailed() + { + switch (this) + { + case INVALID: + case BROKEN: + case FAILED: + case SERVER_ERROR: + return true; + case READY: + case SUBMITTED: + case QUEUED: + case RUNNING: + case FINISHED: + case CANCELLED: + default: + return false; + } + } + + public boolean isRunning() + { + return this == WSJobStatus.RUNNING; + } + + public boolean isQueuing() + { + return this == WSJobStatus.SUBMITTED || this == WSJobStatus.QUEUED; + } +} \ No newline at end of file diff --git a/src/jalview/ws2/WSJobTrackerI.java b/src/jalview/ws2/WSJobTrackerI.java deleted file mode 100755 index 671610a..0000000 --- a/src/jalview/ws2/WSJobTrackerI.java +++ /dev/null @@ -1,9 +0,0 @@ -package jalview.ws2; - -public interface WSJobTrackerI { - public void setState(WSJobState state); - public int getLogSize(); - public void appendLog(String log); - public int getErrorLogSize(); - public void appendErrorLog(String log); -} \ No newline at end of file diff --git a/src/jalview/ws2/WebServiceDiscoverer.java b/src/jalview/ws2/WebServiceDiscoverer.java new file mode 100644 index 0000000..0a1565e --- /dev/null +++ b/src/jalview/ws2/WebServiceDiscoverer.java @@ -0,0 +1,58 @@ +package jalview.ws2; + +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CopyOnWriteArrayList; + +public interface WebServiceDiscoverer +{ + public static final int STATUS_OK = 1; + public static final int STATUS_NO_SERVICES = 0; + public static final int STATUS_INVALID = -1; + public static final int STATUS_UNKNOWN = -2; + + public List getUrls(); + + public void setUrls(List wsUrls); + + public boolean testUrl(URL url); + + public int getStatusForUrl(String url); + + public List getServices(); + + public boolean hasServices(); + + public boolean isRunning(); + + public boolean isDone(); + + public CompletableFuture startDiscoverer(); + + public String getErrorMessages(); + + @FunctionalInterface + static interface ServiceChangeListener { + public void servicesChanged(WebServiceDiscoverer discoverer, + Collection services); + } + + List serviceListeners = new CopyOnWriteArrayList<>(); + + public default void addServiceChangeListener(ServiceChangeListener listener) { + serviceListeners.add(listener); + } + + public default void removeServiceChangeListener(ServiceChangeListener listener) { + serviceListeners.remove(listener); + } + + default void fireServicesChanged(List services) { + for (var listener: serviceListeners) { + listener.servicesChanged(this, services); + } + } +} diff --git a/src/jalview/ws2/WebServiceI.java b/src/jalview/ws2/WebServiceI.java new file mode 100755 index 0000000..d93dd9a --- /dev/null +++ b/src/jalview/ws2/WebServiceI.java @@ -0,0 +1,53 @@ +package jalview.ws2; + +import java.io.IOException; +import java.util.List; + +import jalview.datamodel.SequenceI; +import jalview.ws.params.ArgumentI; +import jalview.ws.params.ParamDatastoreI; +import jalview.ws.params.WsParamSetI; +import jalview.ws2.operations.Operation; + +/** + * Provides information about the web service and sub-routines + * to submit, track and cancel the jobs running on the server as well as + * retrieve the results. + * The instances should not depend on any other jalview components, especially + * must be oblivious to the existence of any UI. + * They are used by other classes such as WebServiceWorkers rather than + * manipulate data themselves. + * + * @author mmwarowny + */ +public interface WebServiceI +{ + public String getHostName(); + public String getName(); + public String getDescription(); + public String getOperationType(); + public List getOperations(); + public boolean hasParameters(); + public ParamDatastoreI getParamStore(); + + public WSJob submit(List sequences, List args) + throws IOException; + + public void updateProgress(WSJob job) + throws IOException; + +// public ResultSupplier getResultSupplier(Class type); + + public void cancel(WSJob job) throws IOException; + + /** + * Handle an exception that happened during job submission. + * If the exception was handled property by this method, it + * returns true. Otherwise, returns false indicating the exception + * should be handled by the caller. + */ + public boolean handleSubmissionError(WSJob job, Exception ex); + + public boolean handleCollectionError(WSJob job, Exception ex); + +} diff --git a/src/jalview/ws2/WebServiceInfoUpdater.java b/src/jalview/ws2/WebServiceInfoUpdater.java new file mode 100644 index 0000000..eb3e350 --- /dev/null +++ b/src/jalview/ws2/WebServiceInfoUpdater.java @@ -0,0 +1,89 @@ +package jalview.ws2; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Objects; + +import jalview.gui.WebserviceInfo; + +public class WebServiceInfoUpdater implements PropertyChangeListener +{ + private final WebserviceInfo wsInfo; + private String outputHeader = ""; + + public WebServiceInfoUpdater(WebserviceInfo wsInfo) { + this.wsInfo = wsInfo; + } + + public String getOutputHeader() { + return outputHeader; + } + + public void setOutputHeader(String header) { + this.outputHeader = header; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) + { + switch (evt.getPropertyName()) { + case "status": + statusChanged(evt); + break; + case "log": + logChanged(evt); + break; + case "errorLog": + errorLogChanged(evt); + break; + } + } + + private void statusChanged(PropertyChangeEvent evt) { + WSJob job = (WSJob) evt.getSource(); + WSJobStatus status = (WSJobStatus) evt.getNewValue(); + int wsInfoStatus = 0; + switch (status) { + case READY: + case SUBMITTED: + case QUEUED: + wsInfoStatus = WebserviceInfo.STATE_QUEUING; + break; + case RUNNING: + wsInfoStatus = WebserviceInfo.STATE_RUNNING; + break; + case FINISHED: + wsInfoStatus = WebserviceInfo.STATE_STOPPED_OK; + break; + case CANCELLED: + wsInfoStatus = WebserviceInfo.STATE_CANCELLED_OK; + break; + case INVALID: + case BROKEN: + case FAILED: + case UNKNOWN: + wsInfoStatus = WebserviceInfo.STATE_STOPPED_ERROR; + break; + case SERVER_ERROR: + wsInfoStatus = WebserviceInfo.STATE_STOPPED_SERVERERROR; + break; + } + wsInfo.setStatus(job.getJobNum(), wsInfoStatus); + } + + private void logChanged(PropertyChangeEvent evt) { + WSJob job = (WSJob) evt.getSource(); + String oldLog = (String) evt.getOldValue(); + String newLog = (String) evt.getNewValue(); + wsInfo.appendProgressText(job.getJobNum(), newLog.substring(oldLog.length())); + } + + private void errorLogChanged(PropertyChangeEvent evt) { + WSJob job = (WSJob) evt.getSource(); + String oldLog = (String) evt.getOldValue(); + String newLog = (String) evt.getNewValue(); + wsInfo.appendProgressText(job.getJobNum(), newLog.substring(oldLog.length())); + } + + +} diff --git a/src/jalview/ws2/WebServiceThreadListenerI.java b/src/jalview/ws2/WebServiceThreadListenerI.java new file mode 100644 index 0000000..386c6ac --- /dev/null +++ b/src/jalview/ws2/WebServiceThreadListenerI.java @@ -0,0 +1,14 @@ +package jalview.ws2; + +public interface WebServiceThreadListenerI +{ + public void submitted(WebServiceWorkerI thread); + + public void submissionFailed(WebServiceWorkerI thread, Exception e); + + public void pollFailed(WebServiceWorkerI thread, Exception e); + + public void cancelled(WebServiceWorkerI thread); + + public void done(WebServiceWorkerI thread); +} \ No newline at end of file diff --git a/src/jalview/ws2/WebServiceWorkerI.java b/src/jalview/ws2/WebServiceWorkerI.java index 1c40eb8..da6e540 100644 --- a/src/jalview/ws2/WebServiceWorkerI.java +++ b/src/jalview/ws2/WebServiceWorkerI.java @@ -9,65 +9,29 @@ import jalview.util.MathUtils; public interface WebServiceWorkerI { - public class WSJob - { - public final long uid = MathUtils.getUID(); - - protected WSJobState state = WSJobState.UNKNOWN; + long getUID(); - protected String jobID = ""; + List getJobs(); - protected int jobNum = 0; + void startJobs() throws IOException; - protected int allowedExceptions = 3; + boolean pollJobs() throws IOException; - public long getUID() { - return uid; - } - - public WSJobState getState() - { - return state; - } - - public void setState(WSJobState state) - { - this.state = state; - } - - public String getJobID() - { - return jobID; - } - - public void setJobID(String jobID) { - this.jobID = jobID; - } - - public int getJobNum() - { - return jobNum; - } + WebServiceI getWebService(); - public int getAllowedExceptions() - { - return allowedExceptions; - } - - public boolean deductAllowedExceptions() { - return allowedExceptions-- > 0; - } - - public void resetAllowedExceptions() { - allowedExceptions = 3; + default boolean isDone() { + if (getJobs().size() == 0) + return false; + for (WSJob job : getJobs()) { + if (!job.getStatus().isDone()) + return false; } + return true; } - public long getUID(); - - public List getJobs(); - - public WSJobID startJob(WSJob job) throws IOException; - - public boolean pollJob(WSJob job) throws IOException; + /* + * Called by the executor when the worker transitions to the done state + * either normally or exceptionally. + */ + void done(); } diff --git a/src/jalview/ws2/utils/WSJobList.java b/src/jalview/ws2/utils/WSJobList.java new file mode 100644 index 0000000..181a7ed --- /dev/null +++ b/src/jalview/ws2/utils/WSJobList.java @@ -0,0 +1,64 @@ +package jalview.ws2.utils; + +import java.util.ArrayList; + +import jalview.ws2.WSJob; + +public class WSJobList extends ArrayList +{ + private static final long serialVersionUID = -1684855135603987602L; + + public int countSubmitted() { + int count = 0; + for (WSJob job : this) { + if (job.getStatus().isSubmitted()) { + count++; + } + } + return count; + } + + public int countQueuing() { + int count = 0; + for (WSJob job : this) { + if (job.getStatus().isQueuing()) count++; + } + return count; + } + + public int countRunning() { + int count = 0; + for (WSJob job : this) { + if (job.getStatus().isRunning()) count++; + } + return count; + } + + public int countDone() { + int count = 0; + for (WSJob job : this) { + if (job.getStatus().isDone()) count++; + } + return count; + } + + public int countFailed() { + int count = 0; + for (WSJob job : this) { + if (job.getStatus().isFailed()) count++; + } + return count; + } + + public int countSuccessful() { + return countDone() - countFailed() - countCancelled(); + } + + public int countCancelled() { + int count = 0; + for (WSJob job : this) { + if (job.getStatus().isCancelled()) count++; + } + return count; + } +} -- 1.7.10.2