172 lines
4.1 KiB
Java
172 lines
4.1 KiB
Java
package org.warp.jcwdb.ann;
|
|
|
|
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
|
|
|
import java.io.IOError;
|
|
import java.io.IOException;
|
|
import java.util.LinkedList;
|
|
import java.util.StringJoiner;
|
|
|
|
public abstract class DBList<T> extends DBObject {
|
|
@DBField(id = 0, type = DBDataType.INTEGER)
|
|
private int maxLoadedItems;
|
|
|
|
@DBField(id = 1, type = DBDataType.UID_LIST)
|
|
private LongArrayList itemIndices;
|
|
|
|
public DBList(JCWDatabase db, int maxLoadedItems) {
|
|
super(db);
|
|
this.maxLoadedItems = maxLoadedItems;
|
|
this.itemIndices = new LongArrayList();
|
|
}
|
|
|
|
public DBList(JCWDatabase database, DBObjectIndicesManager.DBObjectInfo objectInfo) throws IOException {
|
|
super(database, objectInfo);
|
|
}
|
|
|
|
public int getMaxLoadedItems() {
|
|
return maxLoadedItems;
|
|
}
|
|
|
|
public void add(T obj) {
|
|
try {
|
|
itemIndices.add(saveObjectToDatabase(database.allocateNullValue(), obj));
|
|
} catch (IOException e) {
|
|
throw new IOError(e);
|
|
}
|
|
}
|
|
|
|
public int size() {
|
|
return this.itemIndices.size();
|
|
}
|
|
|
|
private T loadObjectAt(int i) throws IOException {
|
|
return loadObjectFromDatabase(itemIndices.getLong(i));
|
|
}
|
|
|
|
protected abstract T loadObjectFromDatabase(long uid) throws IOException;
|
|
|
|
protected abstract long saveObjectToDatabase(long uid, T value) throws IOException;
|
|
|
|
public DBListIterator<T> iterator() {
|
|
return new DBListIterator<>() {
|
|
private int position = itemIndices.size();
|
|
private LinkedList<T> cachedItems;
|
|
|
|
private int objectToSavePosition;
|
|
private T objectToSave;
|
|
|
|
@Override
|
|
public boolean hasNext() {
|
|
if (position > 0) {
|
|
return true;
|
|
} else {
|
|
try {
|
|
saveObservedObject();
|
|
} catch (IOException e) {
|
|
throw new IOError(e);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public T next() {
|
|
position--;
|
|
if (position < 0) {
|
|
throw new NullPointerException("Position < 0");
|
|
}
|
|
if (cachedItems == null || cachedItems.size() == 0) {
|
|
try {
|
|
cachedItems = fillCache(position);
|
|
} catch (IOException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
try {
|
|
return switchObservedObject(position, cachedItems.removeFirst());
|
|
} catch (IOException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void remove() {
|
|
try {
|
|
saveObservedObject();
|
|
} catch (IOException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
itemIndices.removeLong(position);
|
|
}
|
|
|
|
@Override
|
|
public void insert(T obj) {
|
|
try {
|
|
itemIndices.add(position, saveObjectToDatabase(database.allocateNullValue(), obj));
|
|
} catch (IOException e) {
|
|
throw new IOError(e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void set(T obj) {
|
|
try {
|
|
itemIndices.set(position, saveObjectToDatabase(database.allocateNullValue(), obj));
|
|
} catch (IOException e) {
|
|
throw new IOError(e);
|
|
}
|
|
}
|
|
|
|
private LinkedList<T> fillCache(int position) throws IOException {
|
|
LinkedList<T> cachedItems = new LinkedList<>();
|
|
int firstObjectIndex = position;
|
|
int lastObjectIndex = firstObjectIndex - maxLoadedItems;
|
|
if (lastObjectIndex < 0) {
|
|
lastObjectIndex = 0;
|
|
}
|
|
for (int i = firstObjectIndex; i >= lastObjectIndex; i--) {
|
|
cachedItems.addLast(loadObjectAt(i));
|
|
}
|
|
return cachedItems;
|
|
}
|
|
|
|
private void saveObservedObject() throws IOException {
|
|
if (objectToSave != null) {
|
|
itemIndices.set(objectToSavePosition, saveObjectToDatabase(database.allocateNullValue(), objectToSave));
|
|
objectToSave = null;
|
|
objectToSavePosition = 0;
|
|
}
|
|
}
|
|
|
|
private T switchObservedObject(int position, T obj) throws IOException {
|
|
saveObservedObject();
|
|
objectToSave = obj;
|
|
objectToSavePosition = position;
|
|
return obj;
|
|
}
|
|
};
|
|
}
|
|
|
|
public interface DBListIterator<T> {
|
|
boolean hasNext();
|
|
|
|
T next();
|
|
|
|
void remove();
|
|
|
|
void insert(T obj);
|
|
|
|
void set(T obj);
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return new StringJoiner(", ", DBList.class.getSimpleName() + "[", "]")
|
|
.add("size=" + size())
|
|
.add("maxLoadedItems=" + maxLoadedItems)
|
|
.add("itemIndices=" + (itemIndices.size() < 100 ? itemIndices : "["+itemIndices.size()+" items]"))
|
|
.toString();
|
|
}
|
|
}
|