package de.hub.emffrag.fragmentation;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.emf.common.util.URI;
public abstract class FragmentsCache {
private static class E {
E next;
E prev;
Fragment entry;
E(Fragment entry) { this.entry = entry; }
void move(E newPrev) {
remove();
add(newPrev);
}
void add(E newPrev) {
prev = newPrev;
next = newPrev.next;
newPrev.next = this;
next.prev = this;
}
void remove() {
prev.next = next;
next.prev = prev;
next = null;
prev = null;
}
boolean isProtected() {
return next == null;
}
}
private final E start;
private final E end;
private int size = 0;
private final Map<URI, E> uriMap = new HashMap<URI, E>();
private final int maxSize;
public FragmentsCache(int maxSize) {
this.maxSize = maxSize;
start = new E(null);
end = new E(null);
start.next = end;
end.prev = start;
}
public void protect(Fragment fragment) {
E e = uriMap.get(fragment.getURI());
if (!e.isProtected()) {
e.remove();
size--;
}
}
public void unprotect(Fragment fragment) {
E e = uriMap.get(fragment.getURI());
if (e.isProtected()) {
e.add(start);
size++;
} else {
e.move(start);
}
evictIfNecessary();
}
private void evictIfNecessary() {
while (size > maxSize) {
E r = end.prev;
r.remove();
size--;
uriMap.remove(r.entry.getURI());
onEvict(r.entry);
}
}
public void put(URI uri, Fragment fragment) {
assert (uriMap.get(uri) == null);
E e = new E(fragment);
uriMap.put(uri, e);
e.add(start);
size++;
evictIfNecessary();
}
public void remove(URI uri) {
E e = uriMap.remove(uri);
if (!e.isProtected()) {
e.remove();
size--;
}
}
public void touch(Fragment fragment) {
E e = uriMap.get(fragment.getURI());
if (!e.isProtected()) {
e.move(start);
}
}
protected abstract void onEvict(Fragment fragment);
public int size() {
return size;
}
}