strangedb/src/main/java/it/cavallium/strangedb/java/objects/lists/EnhancedObjectStrangeDbList...

190 lines
6.9 KiB
Java

package it.cavallium.strangedb.java.objects.lists;
import it.cavallium.strangedb.java.database.IObjectsIO;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import it.cavallium.strangedb.java.objects.EnhancedObject;
import it.cavallium.strangedb.java.database.IDatabaseTools;
import it.cavallium.strangedb.java.annotations.DbDataType;
import it.cavallium.strangedb.java.annotations.DbField;
import java.io.IOException;
public class EnhancedObjectStrangeDbList<T extends EnhancedObject> extends StrangeDbList<T> {
@DbField(id = 0, type = DbDataType.REFERENCES_LIST)
private LongArrayList indices;
@DbField(id = 1, type = DbDataType.OBJECT)
private Class<T> type;
@Override
protected LongArrayList getIndices() {
return indices;
}
public EnhancedObjectStrangeDbList() {
super();
}
public EnhancedObjectStrangeDbList(IDatabaseTools databaseTools, Class<T> type) throws IOException {
super(databaseTools);
this.type = type;
indices = new LongArrayList();
}
@Override
protected T loadItem(long uid) throws IOException {
return databaseTools.getObjectsIO().loadEnhancedObject(uid);
}
@Override
protected void writeItemToDisk(long uid, T item) throws IOException {
databaseTools.getObjectsIO().setEnhancedObject(uid, item);
}
public ElementsArrayList<EnhancedObjectIndices> queryUids(ListQuery query) throws IOException {
ElementsArrayList<EnhancedObjectIndices> uids = executeQuery(query, this, databaseTools.getObjectsIO());
return uids;
}
public ElementsArrayList<T> query(ListQuery query) throws IOException {
ElementsArrayList<EnhancedObjectIndices> uids = queryUids(query);
ElementsArrayList<T> elements = new ElementsArrayList<>(uids.size());
for (int i = 0; i < uids.size(); i++) {
T element = databaseTools.getObjectsIO().loadEnhancedObject(uids.get(i).objectUid);
elements.add(element);
}
return elements;
}
private ElementsArrayList<EnhancedObjectIndices> executeQuery(ListQuery query, ElementsList<?> inputList, IObjectsIO dbio) throws IOException {
if (query instanceof ListQuery.ListQueryElement) {
return executeQueryElement((ListQuery.ListQueryElement) query, inputList, dbio);
} else if (query instanceof ListQuery.ListQueryAnd) {
ListQuery[] children = ((ListQuery.ListQueryAnd) query).getQueryChildren();
ElementsArrayList<EnhancedObjectIndices> results = null;
for (ListQuery childQuery : children) {
results = executeQuery(childQuery, results == null ? inputList : results, dbio);
if (results.size() == 0) break;
}
return results;
} else if (query instanceof ListQuery.ListQueryOr) {
ListQuery[] children = ((ListQuery.ListQueryOr) query).getQueryChildren();
ElementsArrayList<EnhancedObjectIndices> results = new ElementsArrayList<>();
for (ListQuery childQuery : children) {
ElementsArrayList<EnhancedObjectIndices> childResults = executeQuery(childQuery, inputList, dbio);
int childResultsSize = childResults.size();
if (childResultsSize == inputList.size()) {
return childResults;
}
addMissingElements(results, childResults);
}
return results;
} else {
throw new RuntimeException("Not implemented!");
}
}
static void addMissingElements(ElementsArrayList<EnhancedObjectIndices> main, ElementsList<EnhancedObjectIndices> elementsToAdd) throws IOException {
int elementsSize = elementsToAdd.size();
for (int i = 0; i < elementsSize; i++) {
EnhancedObjectIndices childResultElement = elementsToAdd.get(i);
if (!main.contains(childResultElement)) {
main.add(childResultElement);
}
}
}
@SuppressWarnings("unchecked")
static ElementsArrayList<Long> toElementsArrayList(ElementsList<?> elementsList) {
if (elementsList instanceof EnhancedObjectStrangeDbList<?>) {
return new ElementsArrayList<>(((EnhancedObjectStrangeDbList) elementsList).getIndices());
} else if (elementsList instanceof ElementsArrayList<?>) {
return (ElementsArrayList<Long>) elementsList;
} else {
throw new UnsupportedOperationException();
}
}
@SuppressWarnings("unchecked")
private static ElementsArrayList<EnhancedObjectIndices> executeQueryElement(ListQuery.ListQueryElement query, ElementsList<?> inputList, IObjectsIO dbio) throws IOException {
ElementsArrayList<EnhancedObjectIndices> results = new ElementsArrayList<>();
if (inputList instanceof EnhancedObjectStrangeDbList<?>) {
EnhancedObjectStrangeDbList<?> dbList = ((EnhancedObjectStrangeDbList<?>) inputList);
final int listSize = inputList.size();
final LongArrayList indices = dbList.getIndices();
for (int i = 0; i < listSize; i++) {
Long elementUid = indices.get(i);
EnhancedObjectIndices elementUids = dbio.loadEnhancedObjectUids(elementUid);
Object result = resolveItemFromDb(query.valuePointer, dbio, elementUids);
if (query.valueOperation.evaluate(result)) {
results.add(elementUids);
}
}
} else if (inputList instanceof ElementsArrayList<?>) {
final int listSize = inputList.size();
ElementsArrayList<EnhancedObjectIndices> elementsUids = ((ElementsArrayList<EnhancedObjectIndices>) inputList);
for (int i = 0; i < listSize; i++) {
EnhancedObjectIndices elementUid = elementsUids.get(i);
Object result = resolveItemFromDb(query.valuePointer, dbio, elementUid);
if (query.valueOperation.evaluate(result)) {
results.add(elementUid);
}
}
}
return results;
}
static Object resolveItemFromDb(ValuePointer pointer, IObjectsIO objectsIO, EnhancedObjectIndices element) throws IOException {
EnhancedObjectIndices currentElement = element;
boolean isLastElement;
for (int i = 0; i < pointer.size(); i++) {
isLastElement = i >= pointer.size() - 1;
ValuePointer currentPointer = pointer.at(i);
int pathNumber = currentPointer.getPathNumber();
ValueType valueType = currentPointer.getPathType();
Object value;
switch (valueType) {
case FIELD: {
if (isLastElement) {
//TODO: get field data type. it can be an enhancedObject or an object
value = objectsIO.loadObject(currentElement.fieldUids[pathNumber]);
} else {
value = objectsIO.loadEnhancedObjectUids(currentElement.fieldUids[pathNumber]);
}
break;
}
case PRIMITIVE_FIELD: {
if (isLastElement) {
//TODO: get primitive type
value = objectsIO.loadPrimitiveData(currentElement.nativeDataUid).getLong(pathNumber);
} else {
throw new IllegalArgumentException("You can access to a type field only in the last pointer");
}
break;
}
case PROPERTY: {
if (isLastElement) {
//TODO: get field data type. it can be an enhancedObject or an object
value = objectsIO.loadObject(currentElement.fieldUids[pathNumber]);
} else {
value = objectsIO.loadEnhancedObjectUids(currentElement.propertyUids[pathNumber]);
}
}
default: {
throw new IllegalArgumentException("Not implemented");
}
}
if (isLastElement) {
return value;
} else {
currentElement = (EnhancedObjectIndices) value;
}
}
throw new IOException("The pointer is empty");
}
}