package org.drugis.common.threading.status;
import static org.apache.commons.collections15.CollectionUtils.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.collections15.PredicateUtils;
import org.drugis.common.threading.IterativeTask;
import org.drugis.common.threading.Task;
import org.drugis.common.threading.TaskListener;
import org.drugis.common.threading.activity.ActivityTask;
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 ActivityTaskProgressModel extends AbstractProgressModel {
private final class PhaseListener implements TaskListener {
public void taskEvent(TaskEvent event) {
synchronized(d_lock) {
Task source = event.getSource();
if(d_progress.containsKey(source)) {
updateTaskProgress(source, event);
}
}
}
private void updateTaskProgress(Task source, TaskEvent event) {
EventType type = event.getType();
switch (type) {
case TASK_FINISHED:
d_progress.put(source, 1.0);
break;
case TASK_PROGRESS:
d_progress.put(source, calcProgress((TaskProgressEvent) event));
break;
case TASK_RESTARTED:
case TASK_STARTED:
d_progress.put(source, 0.0);
default:
break;
}
setProgress(calcProgress());
setDeterminate(calcDeterminate());
}
}
private Set<Task> d_runningTasks = new HashSet<Task>();
private Set<Task> d_iterables = new HashSet<Task>();
private HashMap<Task, Double> d_progress = new HashMap<Task, Double>();
private PhaseListener d_listener = new PhaseListener();
private Object d_lock = new Object();
public ActivityTaskProgressModel(ActivityTask activity) {
d_task = activity;
Set<Task> states = activity.getModel().getStates();
if(!d_task.isFinished()) {
for(Task state : states) {
d_progress.put(state, 0.0);
state.addTaskListener(d_listener);
}
}
d_task.addTaskListener(new TaskListener() {
public void taskEvent(TaskEvent e) {
synchronized(d_lock) {
if (e instanceof PhaseEvent) {
Task phase = ((PhaseEvent) e).getPhase();
if (e.getType().equals(TaskEvent.EventType.PHASE_STARTED)) {
d_runningTasks.add(phase);
} else if (e.getType().equals(TaskEvent.EventType.PHASE_FINISHED)) {
d_runningTasks.remove(phase);
}
setDeterminate(calcDeterminate());
setProgress(calcProgress());
}
}
}
});
d_iterables.addAll(findIterables(states));
}
@SuppressWarnings("unchecked")
private Collection<? extends IterativeTask> findIterables(Collection<? extends Task> collection) {
return select(collection, PredicateUtils.instanceofPredicate(IterativeTask.class));
}
@Override
protected Double calcProgress() {
double progress = 0;
for(Task task : d_iterables) {
Double value = d_progress.get(task);
progress = progress + ((value == null) ? 0 : value);
}
return progress / d_iterables.size();
}
protected List<String> getPhaseStrings() {
List<String> phaseStrings = new ArrayList<String>();
synchronized (d_lock) {
for (Task p : d_runningTasks) {
phaseStrings.add(p.toString() + ((p instanceof IterativeTask) ? ": " + formatProgress(d_progress.get(p)) : ""));
}
}
return phaseStrings;
}
@Override
protected boolean calcDeterminate() {
return !intersection(d_runningTasks, d_iterables).isEmpty() || d_task.isFinished();
}
}