/**
*
*/
package com.yoursway.model.repository;
import java.util.LinkedList;
import com.yoursway.model.timeline.PointInTime;
class PerModelStorage {
private class Tuple {
PointInTime point;
ISnapshot snapshot;
public Tuple(PointInTime point, ISnapshot snapshot) {
this.point = point;
this.snapshot = snapshot;
}
}
private class FakeProxySnapshot implements ISnapshot {
private ISnapshot fullSnapshot;
private final Object flag = new Object();
public FakeProxySnapshot() {
fullSnapshot = null;
}
public ISnapshot getFullSnapshot() {
synchronized (flag) {
while (fullSnapshot == null) {
try {
flag.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return fullSnapshot;
}
public void setFullSnapshot(ISnapshot snapshot) {
fullSnapshot = snapshot;
synchronized (flag) {
flag.notifyAll();
}
}
}
private final LinkedList<Tuple> snapshots = new LinkedList<Tuple>();
public PerModelStorage(Class<?> modelRoot) {
}
public ISnapshot getLast(PointInTime point) {
ISnapshot snapshot = findSnapshot(point, true);
if (snapshot instanceof FakeProxySnapshot) {
FakeProxySnapshot fakeProxySnapshot = (FakeProxySnapshot) snapshot;
return fakeProxySnapshot.getFullSnapshot();
}
return snapshot;
}
public ISnapshot getLastAccessible(PointInTime point) {
return findSnapshot(point, false);
}
private ISnapshot findSnapshot(PointInTime point, boolean allowNotComplete) {
ISnapshot winner = null;
synchronized (snapshots) { //TODO, use binary search
for (Tuple t : snapshots) {
if (!allowNotComplete && t.snapshot instanceof FakeProxySnapshot)
break;
if (t.point.compareTo(point) <= 0)
winner = t.snapshot;
else
break;
}
}
return winner;
}
synchronized public void pushSnapshot(PointInTime point, ISnapshotBuilder snapshotBuilder) {
FakeProxySnapshot proxySnapshot = new FakeProxySnapshot();
synchronized (snapshots) {
snapshots.add(new Tuple(point, proxySnapshot));
}
// this may execute long
ISnapshot snapshot = snapshotBuilder.buildSnapshot();
if (snapshot == null)
throw new RuntimeException("SnapshotBuilder returned null snapshot!");
synchronized (snapshots) {
snapshots.removeLast();
snapshots.add(new Tuple(point, snapshot));
proxySnapshot.setFullSnapshot(snapshot);
}
}
}