+++ /dev/null
-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 <R>
- */
-public interface JalviewWebServiceI<R>
-{
- 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<SequenceI> sequences, WsParamSetI preset,
- List<ArgumentI> 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);
-
-}
@FunctionalInterface
public interface MenuEntryProviderI
{
- public void buildMenu(JMenu parent, JalviewWebServiceI<?> service,
- AlignFrame frame);
+ public void buildMenu(JMenu parent, AlignFrame frame);
}
+++ /dev/null
-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<List<SequenceI>> service;
-
- private final AlignmentView msa;
-
- private final AlignmentI seqdataset;
-
- private boolean submitGaps = false;
-
- private boolean preserveOrder = false;
-
- private List<ArgumentI> parameters = Collections.emptyList();
-
- MsaWSWorker(JalviewWebServiceI<List<SequenceI>> 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<ArgumentI> parameters)
- {
- this.parameters = parameters;
- }
-
- @Override
- public WSJobID startJob(WSJob job) {
- return new WSJobID(service.getName(), service.getClass().toString(), "0");
- }
-
- @Override
- public List<WSJob> 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<List<SequenceI>> 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(
- "<strong>%s</strong><br/>%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<ArgumentI> openEditParamsDialog(JalviewWebServiceI service,
- WsParamSetI preset, List<ArgumentI> 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();
- }
-}
--- /dev/null
+package jalview.ws2;
+
+import java.io.IOException;
+
+@FunctionalInterface
+public interface ResultSupplier<T>
+{
+ public T getResult(WSJob job) throws IOException;
+}
--- /dev/null
+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);
+ }
+
+}
+++ /dev/null
-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;
- }
-
-}
+++ /dev/null
-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
--- /dev/null
+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
+++ /dev/null
-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
--- /dev/null
+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<String> getUrls();
+
+ public void setUrls(List<String> wsUrls);
+
+ public boolean testUrl(URL url);
+
+ public int getStatusForUrl(String url);
+
+ public List<WebServiceI> getServices();
+
+ public boolean hasServices();
+
+ public boolean isRunning();
+
+ public boolean isDone();
+
+ public CompletableFuture<WebServiceDiscoverer> startDiscoverer();
+
+ public String getErrorMessages();
+
+ @FunctionalInterface
+ static interface ServiceChangeListener {
+ public void servicesChanged(WebServiceDiscoverer discoverer,
+ Collection<? extends WebServiceI> services);
+ }
+
+ List<ServiceChangeListener> 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<WebServiceI> services) {
+ for (var listener: serviceListeners) {
+ listener.servicesChanged(this, services);
+ }
+ }
+}
--- /dev/null
+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<Operation> getOperations();
+ public boolean hasParameters();
+ public ParamDatastoreI getParamStore();
+
+ public WSJob submit(List<SequenceI> sequences, List<ArgumentI> args)
+ throws IOException;
+
+ public void updateProgress(WSJob job)
+ throws IOException;
+
+// public <T> ResultSupplier<T> getResultSupplier(Class<T> 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);
+
+}
--- /dev/null
+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()));
+ }
+
+
+}
--- /dev/null
+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
public interface WebServiceWorkerI
{
- public class WSJob
- {
- public final long uid = MathUtils.getUID();
-
- protected WSJobState state = WSJobState.UNKNOWN;
+ long getUID();
- protected String jobID = "";
+ List<WSJob> 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<WSJob> 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();
}
--- /dev/null
+package jalview.ws2.utils;
+
+import java.util.ArrayList;
+
+import jalview.ws2.WSJob;
+
+public class WSJobList extends ArrayList<WSJob>
+{
+ 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;
+ }
+}