package org.drugis.common.threading.status;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.drugis.common.threading.Task;
import org.drugis.common.threading.TaskListener;
import org.drugis.common.threading.event.PhaseEvent;
import org.drugis.common.threading.event.TaskEvent;
import org.drugis.common.threading.event.TaskEvent.EventType;
import org.drugis.common.threading.event.TaskProgressEvent;
public class TaskProgressModel extends AbstractProgressModel {
private final class PhaseListener implements TaskListener {
public void taskEvent(TaskEvent event) {
synchronized(d_lock) {
if (event.getType().equals(TaskEvent.EventType.TASK_PROGRESS)) {
d_phaseProgress.put(event.getSource(), calcProgress((TaskProgressEvent) event));
setDeterminate(calcDeterminate());
setProgress(calcProgress());
}
}
}
}
private Map<Task, Double> d_phaseProgress = new HashMap<Task, Double>();
List<Task> d_phases = new ArrayList<Task>();
private PhaseListener d_phaseListener = new PhaseListener();
private Object d_lock = new Object();
private TaskListener d_taskListener = new PhaseTaskListener();
public TaskProgressModel(Task task) {
setTask(task);
}
public void setTask(Task task) {
if (d_task != null) {
d_task.removeTaskListener(d_taskListener);
}
d_task = task;
if(task.isFinished()) {
setProgress(1.0);
}
removePhases();
setDeterminate(task.isFinished());
task.addTaskListener(d_taskListener);
}
public Task getTask() {
return d_task;
}
private void removePhases() {
for (Task t : d_phases) {
t.removeTaskListener(d_phaseListener);
}
d_phases.clear();
d_phaseProgress.clear();
}
@Override
protected boolean calcDeterminate() {
if (d_phases.isEmpty()) {
return false;
}
for(Task p : d_phases) {
if (d_phaseProgress.get(p) == null)
return false;
}
return true;
}
@Override
protected Double calcProgress() {
Set<Double> values = new HashSet<Double>(d_phaseProgress.values());
values.remove(null);
if(!values.isEmpty()) {
return Collections.min(values);
}
return 0.0;
}
protected List<String> getPhaseStrings() {
List<String> phaseStrings = new ArrayList<String>();
synchronized (d_lock) {
for (Task p : d_phases) {
phaseStrings.add(p.toString() + ": " + formatProgress(d_phaseProgress.get(p)));
}
}
return phaseStrings;
}
protected class PhaseTaskListener implements TaskListener {
public void taskEvent(TaskEvent e) {
synchronized(d_lock) {
EventType type = e.getType();
if (type.equals(TaskEvent.EventType.TASK_STARTED)) {
setProgress(0.0);
} else if (type.equals(TaskEvent.EventType.TASK_PROGRESS)) {
setDeterminate(true);
setProgress(calcProgress((TaskProgressEvent) e));
} else if (type.equals(TaskEvent.EventType.TASK_FINISHED)) {
setDeterminate(true);
setProgress(1.0);
} else if (type.equals(TaskEvent.EventType.TASK_FAILED)) {
setDeterminate(true);
setProgress(0.0);
} else if (type.equals(TaskEvent.EventType.TASK_ABORTED)) {
setDeterminate(true);
setProgress(0.0);
} else if (type.equals(TaskEvent.EventType.TASK_RESTARTED)) {
setDeterminate(true);
setProgress(0.0);
} else if (e instanceof PhaseEvent) {
PhaseEvent evt = (PhaseEvent) e;
Task phase = evt.getPhase();
if (type.equals(TaskEvent.EventType.PHASE_STARTED)) {
d_phases.add(phase);
phase.addTaskListener(d_phaseListener);
d_phaseProgress.put(phase, null);
} else if (type.equals(TaskEvent.EventType.PHASE_FINISHED)) {
phase.removeTaskListener(d_phaseListener);
d_phaseProgress.remove(phase);
d_phases.remove(phase);
}
setDeterminate(calcDeterminate());
setProgress(calcProgress());
}
}
}
}
}