/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2016 Neil C Smith.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 3 for more details.
*
* You should have received a copy of the GNU General Public License version 3
* along with this work; if not, see http://www.gnu.org/licenses/
*
*
* Please visit http://neilcsmith.net if you need additional information or
* have any questions.
*/
package net.neilcsmith.praxis.live.util;
import java.awt.EventQueue;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import net.neilcsmith.praxis.live.core.api.Task;
/**
*
* @author Neil C Smith (http://neilcsmith.net)
*/
public abstract class AbstractTask implements Task {
private final PropertyChangeSupport pcs;
private State state;
protected AbstractTask() {
pcs = new PropertyChangeSupport(this);
state = State.NEW;
}
@Override
public final State execute() {
if (!EventQueue.isDispatchThread()) {
throw new IllegalStateException("execute() must be called on event thread");
}
if (state != State.NEW) {
throw new IllegalStateException("task has already been executed or cancelled");
}
updateState(State.RUNNING);
try {
handleExecute();
} catch (Exception ex) {
updateState(State.ERROR);
}
return state;
}
@Override
public final State getState() {
return state;
}
@Override
public final void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
@Override
public final void removePropertyChangeListener(PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener);
}
@Override
public final boolean cancel() {
if (!EventQueue.isDispatchThread()) {
throw new IllegalStateException("cancel() must be called on event thread");
}
if (state == State.NEW || state == State.RUNNING) {
if (handleCancel()) {
updateState(State.CANCELLED);
return true;
}
}
return false;
}
protected final void updateState(State newState) {
if (!EventQueue.isDispatchThread()) {
throw new IllegalStateException("updateState() must be called on event thread");
}
if (this.state == newState) {
return;
}
switch (newState) {
case RUNNING :
if (this.state != State.NEW) {
throw new IllegalStateException("Trying to set finished task back to running");
}
break;
case COMPLETED :
case ERROR :
case CANCELLED :
if (this.state != State.NEW && this.state != State.RUNNING) {
throw new IllegalStateException("Trying to set state of finished task");
}
break;
default:
throw new IllegalStateException();
}
State old = this.state;
this.state = newState;
pcs.firePropertyChange(PROP_STATE, old, state);
}
protected abstract void handleExecute() throws Exception;
protected boolean handleCancel() {
return false;
}
}