package elw.dao.ctx;
import elw.vo.*;
import elw.vo.Class;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
/**
* Parameter Object, storing the full Class/Task/Version context.
*/
public class CtxTask extends CtxStudent {
public final IndexEntry indexEntry;
public final TaskType tType;
public final Task task;
public final Version ver;
public final Iterable<CtxSlot> slots;
public CtxTask(
Enrollment enr,
Course course,
Group group,
Student student,
IndexEntry indexEntry,
Task task,
TaskType tType,
Version ver
) {
super(enr, course, group, student);
this.indexEntry = indexEntry;
this.tType = tType;
this.task = task;
this.ver = ver;
this.slots = new Iterable<CtxSlot>() {
public Iterator<CtxSlot> iterator() {
final Iterator<Map.Entry<String, FileSlot>> slotIterator =
CtxTask.this.tType.getFileSlots().entrySet().iterator();
return new Iterator<CtxSlot>() {
public boolean hasNext() {
return slotIterator.hasNext();
}
public CtxSlot next() {
return slot(slotIterator.next().getValue());
}
public void remove() {
slotIterator.remove();
}
};
}
};
}
protected static String safeClassKey(
final SortedMap<String, Class> classMap,
final String classKey
) {
final SortedMap<String, Class> tailMap =
classMap.tailMap(classKey);
if (!tailMap.isEmpty()) {
return tailMap.firstKey();
}
return classMap.lastKey();
}
public static Class classForKey(
final SortedMap<String, Class> classMap,
final String classKey
) {
return classMap.get(safeClassKey(classMap, classKey));
}
public CtxSlot slot(final String slotId) {
final FileSlot slot = tType.getFileSlots().get(slotId);
// LATER these checks somehow duplicate Ctx resolution code
// maybe a custom exception here would fit better
if (slot == null) {
throw new IllegalStateException(
"slot '" + slotId + "' not found: " + String.valueOf(this)
);
}
return slot(slot);
}
public CtxSlot slot(final FileSlot slot) {
final CtxSlot ctxSlot = new CtxSlot(
enr, group, student, course,
indexEntry, task, tType, ver,
slot
);
return propagateTZCache(ctxSlot);
}
public Class openClass() {
return classForKey(
enr.getClasses(),
indexEntry.getClassFrom()
);
}
public long openMillis() {
final Class classOpen = openClass();
return classOpen.getFromDateTime().getMillis();
}
public boolean open() {
long now = System.currentTimeMillis();
return openMillis() <= now;
}
// some tasks consist completely or partially of shared versions
// solutions to which may queried or uploaded by students
public CtxTask overrideToShared(Version sharedVersion) {
if (!sharedVersion.isShared()) {
throw new IllegalStateException("overriding to non-shared version");
}
final CtxTask ctxTask = new CtxTask(
enr, course, group,
student,
indexEntry, task, tType,
sharedVersion
);
return propagateTZCache(ctxTask);
}
public static interface StateForSlot {
State getState(FileSlot slot);
}
public boolean writable(
final FileSlot slot,
final StateForSlot stateForSlot
) {
if (!slot.isWritable()) {
return false;
}
final List<String> writeApprovals =
slot.getWriteApprovals();
for (String writeApproval : writeApprovals) {
final FileSlot approvalSlot =
tType.getFileSlots().get(writeApproval);
if (State.APPROVED != stateForSlot.getState(approvalSlot)) {
return false;
}
}
return true;
}
public boolean readable(FileSlot slot, StateForSlot stateForSlot) {
final List<String> readApprovals =
slot.getReadApprovals();
for (String readApproval : readApprovals) {
final FileSlot approvalSlot =
tType.getFileSlots().get(readApproval);
if (State.APPROVED != stateForSlot.getState(approvalSlot)) {
return false;
}
}
return true;
}
}