package jalview.ws2.actions; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.List; import jalview.datamodel.SequenceI; import jalview.util.MathUtils; import jalview.ws2.actions.api.JobI; import jalview.ws2.actions.api.TaskEventListener; import jalview.ws2.api.JobStatus; import jalview.ws2.api.WebServiceJobHandle; /** * Basic implementation of the {@link JobI} interface which stores internal job * id, status, log and error log and provides getters to those fields. * Additionally, it stores sequences that will be submitted as job input and the * handle to the job on the server. Extending classes can add extra fields in * order to associate additional data with the job. * * Observers can be registered with this bean-like object to listen to changes * to {@code status}, {@code log}, and {@code errorLog} properties. Typically, * the events are delegated to the {@link TaskEventListener} objects observing * the task that created this job. * * @author mmwarowny */ // TODO: make class non-abstract by removing isInputValid() public abstract class BaseJob implements JobI { protected final long internalId = MathUtils.getUID(); protected final List inputSeqs; protected JobStatus status = null; protected String log = ""; protected String errorLog = ""; /* FIXME: server job is not specific to the BaseJob and should preferably * be managed by classes using clients (tasks). */ protected WebServiceJobHandle serverJob; public BaseJob(List inputSeqs) { this.inputSeqs = inputSeqs; } /** * {@inheritDoc} */ @Override public final long getInternalId() { return internalId; } /** * Return the list of input sequences associated with this job. * * @return input sequences */ public List getInputSequences() { return inputSeqs; } /** * Check if inputs make a valid job. * * @return {@code true} if the input is valid. */ // FIXME: method not necessary, may incorporate into task#prepare() public abstract boolean isInputValid(); /** * Check if the job is completed, This includes jobs with invalid input, * successful and unsuccessful termination. * * @return {@code true} if job is completed successfully or not */ public boolean isCompleted() { return !isInputValid() || getStatus().isDone(); } @Override public final JobStatus getStatus() { return status; } /** * Set new status of the job and notify listeners of the change. Job status is * managed internally by tasks and should not be modified outside the task * which created this job. * * @param status * new job status */ public final void setStatus(JobStatus status) { JobStatus oldStatus = this.status; this.status = status; pcs.firePropertyChange("status", oldStatus, status); } @Override public final String getLog() { return log; } /** * Set log text and notify listeners of the change. Log is managed by tasks * which created the job and should not be modified by other classes. * * @param log * new log */ public final void setLog(String log) { String oldLog = this.log; this.log = log; pcs.firePropertyChange("log", oldLog, log); } @Override public final String getErrorLog() { return errorLog; } /** * Set error log text and notify listeners of the change. Error log is managed * by tasks which created the job and should not be modified by other classes. * * @param errorLog */ public final void setErrorLog(String errorLog) { String oldLog = this.errorLog; this.errorLog = errorLog; pcs.firePropertyChange("errorLog", oldLog, errorLog); } /** * Return the job handle that identifies this job running on the server or * {@code null} if the job was not submitted. * * @return server job handle */ public final WebServiceJobHandle getServerJob() { return serverJob; } /** * Set the server job handle once the job was submitted to the server. The * handler is managed by the task which created this job and should not be * modified by other classes. * * @param job */ public final void setServerJob(WebServiceJobHandle job) { this.serverJob = job; } private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); /** * Register an observer that will be notified of changes to status, log and * error log. * * @param listener * property change listener */ public final void addPropertyChagneListener(PropertyChangeListener listener) { pcs.addPropertyChangeListener(listener); } /** * Remove the property listener from this object. * * @param listener * listener to remove */ public final void removePropertyChangeListener(PropertyChangeListener listener) { pcs.removePropertyChangeListener(listener); } }