2018-11-19 15:16:12 +01:00
|
|
|
package org.warp.jcwdb;
|
|
|
|
|
2018-11-20 18:39:48 +01:00
|
|
|
import java.io.IOException;
|
2018-12-07 00:26:38 +01:00
|
|
|
import java.util.function.Function;
|
2018-11-20 18:39:48 +01:00
|
|
|
|
2018-11-21 01:02:25 +01:00
|
|
|
/**
|
|
|
|
* You must have only a maximum of 1 reference for each index
|
|
|
|
* @param <T>
|
|
|
|
*/
|
2018-12-05 02:39:41 +01:00
|
|
|
public class EntryReference<T> implements Castable {
|
|
|
|
private final JCWDatabase.EntryReferenceTools db;
|
2018-11-21 01:02:25 +01:00
|
|
|
private final long entryIndex;
|
2018-11-20 18:39:48 +01:00
|
|
|
private final DBTypeParser<T> parser;
|
2018-12-07 00:26:38 +01:00
|
|
|
private T value;
|
2018-11-21 01:02:25 +01:00
|
|
|
private volatile boolean closed;
|
|
|
|
private final Object closeLock = new Object();
|
2018-11-19 15:16:12 +01:00
|
|
|
|
2018-12-05 02:39:41 +01:00
|
|
|
public EntryReference(JCWDatabase.EntryReferenceTools db, long entryId, DBTypeParser<T> parser) throws IOException {
|
2018-11-19 15:16:12 +01:00
|
|
|
this.db = db;
|
2018-11-21 01:02:25 +01:00
|
|
|
this.entryIndex = entryId;
|
2018-11-19 15:16:12 +01:00
|
|
|
this.parser = parser;
|
2018-12-05 02:39:41 +01:00
|
|
|
this.value = db.read(entryId, parser.getReader());
|
2018-11-21 01:02:25 +01:00
|
|
|
}
|
|
|
|
|
2018-12-05 02:39:41 +01:00
|
|
|
public EntryReference(JCWDatabase.EntryReferenceTools db, long entryId, DBTypeParser<T> parser, T value) {
|
2018-11-22 23:31:41 +01:00
|
|
|
this.db = db;
|
|
|
|
this.entryIndex = entryId;
|
|
|
|
this.parser = parser;
|
|
|
|
this.value = value;
|
|
|
|
}
|
|
|
|
|
2018-11-21 01:02:25 +01:00
|
|
|
public DBTypeParser<T> getParser() {
|
|
|
|
return parser;
|
|
|
|
}
|
|
|
|
|
|
|
|
public long getIndex() {
|
|
|
|
return entryIndex;
|
2018-11-19 15:16:12 +01:00
|
|
|
}
|
2018-12-04 23:57:49 +01:00
|
|
|
|
|
|
|
public long calculateHash() {
|
|
|
|
return parser.calculateHash(value);
|
|
|
|
}
|
2018-11-19 15:16:12 +01:00
|
|
|
|
2018-12-04 23:57:49 +01:00
|
|
|
/**
|
|
|
|
* Note that this method won't be called when closing without saving
|
|
|
|
* @throws IOException
|
|
|
|
*/
|
2018-11-20 18:39:48 +01:00
|
|
|
public void save() throws IOException {
|
2018-11-21 01:02:25 +01:00
|
|
|
if (!closed) {
|
2018-12-05 02:39:41 +01:00
|
|
|
db.write(entryIndex, parser.getWriter(value));
|
2018-11-21 01:02:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-07 00:26:38 +01:00
|
|
|
public void editValue(Function<T, T> editFunction) throws IOException {
|
|
|
|
this.value = editFunction.apply(this.value);
|
|
|
|
this.save();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Use editValue instead
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
@Deprecated()
|
|
|
|
public T getValue() {
|
|
|
|
return this.value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* DO NOT ATTEMPT TO MODIFY THE VALUE RETURNED
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public T getValueUnsafe() {
|
|
|
|
return this.value;
|
|
|
|
}
|
|
|
|
|
2018-11-21 01:02:25 +01:00
|
|
|
@Override
|
|
|
|
public <T> T cast() {
|
|
|
|
return (T) this;
|
|
|
|
}
|
|
|
|
|
2018-12-05 02:39:41 +01:00
|
|
|
protected void close() throws IOException {
|
2018-11-21 01:02:25 +01:00
|
|
|
if (closed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
synchronized (closeLock) {
|
|
|
|
if (closed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
save();
|
|
|
|
|
|
|
|
closed = true;
|
|
|
|
}
|
2018-11-19 15:16:12 +01:00
|
|
|
}
|
2018-12-04 23:57:49 +01:00
|
|
|
|
|
|
|
public void closeWithoutSaving() {
|
|
|
|
if (closed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
synchronized (closeLock) {
|
|
|
|
if (closed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-11-21 01:02:25 +01:00
|
|
|
closed = true;
|
|
|
|
}
|
2018-11-19 15:16:12 +01:00
|
|
|
}
|
|
|
|
}
|