From a1624bf91e35e69fb991cc576945c0ed5287eb14 Mon Sep 17 00:00:00 2001 From: Andrea Cavalli Date: Thu, 18 Apr 2019 16:08:22 +0200 Subject: [PATCH] Added queries --- pom.xml | 4 +- .../strangedb/java/annotations/DbField.java | 1 + .../java/annotations/DbPrimitiveField.java | 1 + .../java/annotations/DbProperty.java | 14 ++ .../java/annotations/DbPropertyGetter.java | 2 - .../java/annotations/DbPropertySetter.java | 2 - .../database/DatabaseDataInitializer.java | 10 +- .../DatabaseEnhancedObjectUpgrader.java | 8 +- .../strangedb/java/database/DatabaseJava.java | 4 +- .../java/database/DatabaseObjectsIO.java | 87 ++++++++-- .../strangedb/java/database/IObjectsIO.java | 8 +- .../java/objects/EnhancedObject.java | 12 +- .../java/objects/EnhancedObjectIndices.java | 15 ++ .../java/objects/EnhancedObjectUpgrader.java | 12 +- .../java/objects/lists/ElementsArrayList.java | 70 +++++++++ .../java/objects/lists/ElementsList.java | 14 ++ .../lists/EnhancedObjectStrangeDbList.java | 148 +++++++++++++++++- .../strangedb/java/objects/lists/KMP.java | 58 +++++++ .../java/objects/lists/ListQuery.java | 105 +++++++++++++ .../objects/lists/ObjectStrangeDbList.java | 2 +- .../java/objects/lists/StrangeDbList.java | 17 +- .../java/objects/lists/ValueOperation.java | 5 + .../java/objects/lists/ValuePointer.java | 139 ++++++++++++++++ .../java/objects/lists/ValueType.java | 7 + .../objects/lists/operations/Contains.java | 25 +++ .../lists/operations/ContainsIgnoreCase.java | 25 +++ .../java/objects/lists/operations/Equals.java | 21 +++ .../it/cavallium/strangedb/tests/Clean.java | 21 +-- .../strangedb/tests/EnhancedClassUpdate.java | 4 +- .../strangedb/tests/ListContainer.java | 44 ++++++ .../tests/MultipleEnhancedObjects.java | 19 +-- .../strangedb/tests/ObjectListTests.java | 139 ++++++++++++++++ .../strangedb/tests/Performance.java | 30 ++-- .../cavallium/strangedb/tests/QueryTests.java | 59 +++++++ .../it/cavallium/strangedb/tests/User.java | 40 +++++ .../strangedb/tests/UserFullInfo.java | 31 ++++ .../cavallium/strangedb/utils/NTestUtils.java | 18 ++- 37 files changed, 1122 insertions(+), 99 deletions(-) create mode 100644 src/main/java/it/cavallium/strangedb/java/annotations/DbProperty.java create mode 100644 src/main/java/it/cavallium/strangedb/java/objects/EnhancedObjectIndices.java create mode 100644 src/main/java/it/cavallium/strangedb/java/objects/lists/ElementsArrayList.java create mode 100644 src/main/java/it/cavallium/strangedb/java/objects/lists/ElementsList.java create mode 100644 src/main/java/it/cavallium/strangedb/java/objects/lists/KMP.java create mode 100644 src/main/java/it/cavallium/strangedb/java/objects/lists/ListQuery.java create mode 100644 src/main/java/it/cavallium/strangedb/java/objects/lists/ValueOperation.java create mode 100644 src/main/java/it/cavallium/strangedb/java/objects/lists/ValuePointer.java create mode 100644 src/main/java/it/cavallium/strangedb/java/objects/lists/ValueType.java create mode 100644 src/main/java/it/cavallium/strangedb/java/objects/lists/operations/Contains.java create mode 100644 src/main/java/it/cavallium/strangedb/java/objects/lists/operations/ContainsIgnoreCase.java create mode 100644 src/main/java/it/cavallium/strangedb/java/objects/lists/operations/Equals.java create mode 100644 src/test/java/it/cavallium/strangedb/tests/ListContainer.java create mode 100644 src/test/java/it/cavallium/strangedb/tests/ObjectListTests.java create mode 100644 src/test/java/it/cavallium/strangedb/tests/QueryTests.java create mode 100644 src/test/java/it/cavallium/strangedb/tests/User.java create mode 100644 src/test/java/it/cavallium/strangedb/tests/UserFullInfo.java diff --git a/pom.xml b/pom.xml index 5ead887..8b1b990 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ it.cavallium strangedb - 1.5.5 + 1.5.7 strangedb-java https://git.ignuranza.net/andreacavalli/strangedb @@ -45,7 +45,7 @@ it.cavallium strangedb-core - 1.5.5 + 1.5.7 diff --git a/src/main/java/it/cavallium/strangedb/java/annotations/DbField.java b/src/main/java/it/cavallium/strangedb/java/annotations/DbField.java index 489b1a1..1ea47df 100644 --- a/src/main/java/it/cavallium/strangedb/java/annotations/DbField.java +++ b/src/main/java/it/cavallium/strangedb/java/annotations/DbField.java @@ -10,4 +10,5 @@ import java.lang.annotation.Target; public @interface DbField { int id(); DbDataType type() default DbDataType.OBJECT; + String name() default ""; } diff --git a/src/main/java/it/cavallium/strangedb/java/annotations/DbPrimitiveField.java b/src/main/java/it/cavallium/strangedb/java/annotations/DbPrimitiveField.java index eb50598..aad0385 100644 --- a/src/main/java/it/cavallium/strangedb/java/annotations/DbPrimitiveField.java +++ b/src/main/java/it/cavallium/strangedb/java/annotations/DbPrimitiveField.java @@ -10,4 +10,5 @@ import java.lang.annotation.Target; public @interface DbPrimitiveField { int id(); DbPrimitiveType type(); + String name() default ""; } diff --git a/src/main/java/it/cavallium/strangedb/java/annotations/DbProperty.java b/src/main/java/it/cavallium/strangedb/java/annotations/DbProperty.java new file mode 100644 index 0000000..8258179 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/java/annotations/DbProperty.java @@ -0,0 +1,14 @@ +package it.cavallium.strangedb.java.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface DbProperty { + int id(); + DbDataType type() default DbDataType.OBJECT; + String name() default ""; +} diff --git a/src/main/java/it/cavallium/strangedb/java/annotations/DbPropertyGetter.java b/src/main/java/it/cavallium/strangedb/java/annotations/DbPropertyGetter.java index 808045e..43e4522 100644 --- a/src/main/java/it/cavallium/strangedb/java/annotations/DbPropertyGetter.java +++ b/src/main/java/it/cavallium/strangedb/java/annotations/DbPropertyGetter.java @@ -8,6 +8,4 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface DbPropertyGetter { - int id(); - DbDataType type() default DbDataType.OBJECT; } diff --git a/src/main/java/it/cavallium/strangedb/java/annotations/DbPropertySetter.java b/src/main/java/it/cavallium/strangedb/java/annotations/DbPropertySetter.java index b7f5593..b6debbd 100644 --- a/src/main/java/it/cavallium/strangedb/java/annotations/DbPropertySetter.java +++ b/src/main/java/it/cavallium/strangedb/java/annotations/DbPropertySetter.java @@ -8,6 +8,4 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface DbPropertySetter { - int id(); - DbDataType type() default DbDataType.OBJECT; } diff --git a/src/main/java/it/cavallium/strangedb/java/database/DatabaseDataInitializer.java b/src/main/java/it/cavallium/strangedb/java/database/DatabaseDataInitializer.java index 792fd7f..cef698b 100644 --- a/src/main/java/it/cavallium/strangedb/java/database/DatabaseDataInitializer.java +++ b/src/main/java/it/cavallium/strangedb/java/database/DatabaseDataInitializer.java @@ -120,7 +120,7 @@ public class DatabaseDataInitializer implements IDataInitializer { long[] propertyUIDs = objectsIO.allocateNewUIDs(biggestPropertyId + 1); for (Method property : unorderedPropertySetters) { - DbPropertySetter fieldAnnotation = property.getAnnotation(DbPropertySetter.class); + DbProperty fieldAnnotation = property.getAnnotation(DbProperty.class); int propertyId = fieldAnnotation.id(); if (propertyId > biggestPropertyId) { biggestPropertyId = propertyId; @@ -131,12 +131,12 @@ public class DatabaseDataInitializer implements IDataInitializer { DbDataType[] propertyTypes = new DbDataType[biggestPropertyId + 1]; Method[] propertyGetters = new Method[biggestPropertyId + 1]; Method[] propertySetters = new Method[biggestPropertyId + 1]; - Map setterMethods = new LinkedHashMap<>(); - Map getterMethods = new LinkedHashMap<>(); + Map setterMethods = new LinkedHashMap<>(); + Map getterMethods = new LinkedHashMap<>(); // Load the properties metadata for (Method property : unorderedPropertyGetters) { - DbPropertyGetter propertyAnnotation = property.getAnnotation(DbPropertyGetter.class); + DbProperty propertyAnnotation = property.getAnnotation(DbProperty.class); int propertyId = propertyAnnotation.id(); DbDataType propertyType = propertyAnnotation.type(); propertyTypes[propertyId] = propertyType; @@ -144,7 +144,7 @@ public class DatabaseDataInitializer implements IDataInitializer { getterMethods.put(property.getName(), propertyAnnotation); } for (Method property : unorderedPropertySetters) { - DbPropertySetter propertyAnnotation = property.getAnnotation(DbPropertySetter.class); + DbProperty propertyAnnotation = property.getAnnotation(DbProperty.class); int propertyId = propertyAnnotation.id(); DbDataType propertyType = propertyAnnotation.type(); propertyTypes[propertyId] = propertyType; diff --git a/src/main/java/it/cavallium/strangedb/java/database/DatabaseEnhancedObjectUpgrader.java b/src/main/java/it/cavallium/strangedb/java/database/DatabaseEnhancedObjectUpgrader.java index c820dfa..96d73d7 100644 --- a/src/main/java/it/cavallium/strangedb/java/database/DatabaseEnhancedObjectUpgrader.java +++ b/src/main/java/it/cavallium/strangedb/java/database/DatabaseEnhancedObjectUpgrader.java @@ -23,14 +23,14 @@ public class DatabaseEnhancedObjectUpgrader implements EnhancedObjectUpgrader { @Override @SuppressWarnings("unchecked") - public Object getField(int id, DbDataType type, Supplier> enhancedClassType) throws IOException { - return objectsIO.loadData(type, fieldRefs[id], enhancedClassType); + public Object getField(int id, DbDataType type) throws IOException { + return objectsIO.loadData(type, fieldRefs[id]); } @Override @SuppressWarnings("unchecked") - public Object getMethod(int id, DbDataType type, Supplier> enhancedClassType) throws IOException { - return objectsIO.loadData(type, methodRefs[id], enhancedClassType); + public Object getMethod(int id, DbDataType type) throws IOException { + return objectsIO.loadData(type, methodRefs[id]); } @SuppressWarnings("unchecked") diff --git a/src/main/java/it/cavallium/strangedb/java/database/DatabaseJava.java b/src/main/java/it/cavallium/strangedb/java/database/DatabaseJava.java index 630834f..82abe62 100644 --- a/src/main/java/it/cavallium/strangedb/java/database/DatabaseJava.java +++ b/src/main/java/it/cavallium/strangedb/java/database/DatabaseJava.java @@ -27,13 +27,13 @@ public class DatabaseJava extends DatabaseCore implements IDatabaseTools { super.close(); } - public T loadRoot(Class type, FunctionWithIO ifAbsent) throws IOException { + public T loadRoot(FunctionWithIO ifAbsent) throws IOException { if (loadedRootObject != null) { throw new RuntimeException("Root already set!"); } T root; if (referencesMetadata.getFirstFreeReference() > 0) { - root = objectsIO.loadEnhancedObject(0, type); + root = objectsIO.loadEnhancedObject(0); } else { if (objectsIO.newNullObject() != 0) { throw new IOException("Can't allocate root!"); diff --git a/src/main/java/it/cavallium/strangedb/java/database/DatabaseObjectsIO.java b/src/main/java/it/cavallium/strangedb/java/database/DatabaseObjectsIO.java index 5e2dde1..3768406 100644 --- a/src/main/java/it/cavallium/strangedb/java/database/DatabaseObjectsIO.java +++ b/src/main/java/it/cavallium/strangedb/java/database/DatabaseObjectsIO.java @@ -7,6 +7,12 @@ import it.cavallium.strangedb.java.objects.EnhancedObject; import it.cavallium.strangedb.java.objects.EnhancedObjectFullInfo; import it.cavallium.strangedb.database.references.DatabaseReferencesIO; import it.cavallium.strangedb.java.annotations.*; +import it.cavallium.strangedb.java.objects.EnhancedObject; +import it.cavallium.strangedb.java.objects.EnhancedObjectFullInfo; +import it.cavallium.strangedb.java.objects.EnhancedObjectIndices; +import it.cavallium.strangedb.java.objects.lists.EnhancedObjectStrangeDbList; +import it.cavallium.strangedb.java.objects.lists.ObjectStrangeDbList; +import it.cavallium.strangedb.java.objects.lists.StrangeDbList; import it.unimi.dsi.fastutil.booleans.BooleanArrayList; import it.unimi.dsi.fastutil.bytes.ByteArrayList; import it.unimi.dsi.fastutil.chars.CharArrayList; @@ -92,8 +98,14 @@ public class DatabaseObjectsIO implements IObjectsIO { registerClass(TreeSet.class, id++); registerClass(SortedSet.class, id++); registerClass(SortedMap.class, id++); + + registerClass(EnhancedObject.class, id++); + registerClass(EnhancedObjectStrangeDbList.class, id++); + registerClass(ObjectStrangeDbList.class, id++); + registerClass(StrangeDbList.class, id++); } + @SuppressWarnings("unchecked") @Override public T loadEnhancedObject(long reference, Class objectType) throws IOException { synchronized (accessLock) { @@ -101,6 +113,10 @@ public class DatabaseObjectsIO implements IObjectsIO { if (buffer.limit() == 0) { return null; } + int serializedClassLength = 0xFF & buffer.get(); + byte[] serializedClassData = new byte[serializedClassLength]; + buffer.get(serializedClassData); + Class objectType = kryo.readClass(new Input(serializedClassData)).getType(); int serializedVersion = Byte.toUnsignedInt(buffer.get()); int fieldsCount = buffer.getInt(); int methodsCount = buffer.getInt(); @@ -118,11 +134,43 @@ public class DatabaseObjectsIO implements IObjectsIO { } } - @SuppressWarnings("unchecked") - Object loadData(DbDataType propertyType, long dataReference, Supplier> returnType) throws IOException { + @Override + public EnhancedObjectIndices loadEnhancedObjectUids(long reference) throws IOException { + lock.readLock().lock(); + readLock.lock(); + try { + ByteBuffer buffer = referencesIO.readFromReference(reference); + if (buffer.limit() == 0) { + return null; + } + //noinspection unused + int serializedClassLength = 0xFF & buffer.get(); + byte[] serializedClassData = new byte[serializedClassLength]; + buffer.get(serializedClassData); + int serializedVersion = Byte.toUnsignedInt(buffer.get()); + int fieldsCount = buffer.getInt(); + int methodsCount = buffer.getInt(); + long[] fieldRefs = new long[fieldsCount]; + long[] methodRefs = new long[methodsCount]; + for (int i = 0; i < fieldsCount; i++) { + fieldRefs[i] = buffer.getLong(); + } + for (int i = 0; i < methodsCount; i++) { + methodRefs[i] = buffer.getLong(); + } + long nativeFieldsDataReference = buffer.getLong(); + return new EnhancedObjectIndices(reference, fieldRefs, methodRefs, nativeFieldsDataReference); + } finally { + readLock.unlock(); + lock.readLock().unlock(); + } + +} + + Object loadData(DbDataType propertyType, long dataReference) throws IOException { switch (propertyType) { case ENHANCED_OBJECT: - return loadEnhancedObject(dataReference, (Class) returnType.get()); + return loadEnhancedObject(dataReference); case OBJECT: return loadObject(dataReference); case REFERENCES_LIST: @@ -211,9 +259,17 @@ public class DatabaseObjectsIO implements IObjectsIO { final long[] propertyReferences = objectFullInfo.getPropertyReferences(); final DbDataType[] propertyTypes = objectFullInfo.getPropertyTypes(); final Object[] propertyValues = objectFullInfo.getLoadedPropertyValues(); - final int totalSize = Byte.BYTES + Integer.BYTES * 2 + fieldReferences.length * Long.BYTES + Output serializedClassDataStream = new Output(1024, 8192); + kryo.writeClass(serializedClassDataStream, value.getClass()); + byte[] serializedClassData = serializedClassDataStream.toBytes(); + final int totalSize = Byte.BYTES + serializedClassData.length + Byte.BYTES + Integer.BYTES * 2 + fieldReferences.length * Long.BYTES + propertyReferences.length * Long.BYTES + Long.BYTES; ByteBuffer buffer = ByteBuffer.allocate(totalSize); + if (serializedClassData.length > 255) { + throw new IndexOutOfBoundsException("The class name is too long!"); + } + buffer.put((byte) serializedClassData.length); + buffer.put(serializedClassData); buffer.put((byte) objectFullInfo.getVersion()); buffer.putInt(fieldReferences.length); buffer.putInt(propertyReferences.length); @@ -337,10 +393,11 @@ public class DatabaseObjectsIO implements IObjectsIO { } @Override - public void loadProperty(EnhancedObject obj, int propertyId, Method property, DbDataType propertyType, + public void loadProperty(EnhancedObject obj, int propertyId, DbDataType propertyType, long propertyUID) throws IOException { synchronized (accessLock) { obj.setProperty(propertyId, loadData(propertyType, propertyUID, property::getReturnType)); + obj.setProperty(propertyId, loadData(propertyType, propertyUID)); } } @@ -363,7 +420,7 @@ public class DatabaseObjectsIO implements IObjectsIO { int biggestPropertyId = biggestGetter > biggestSetter ? biggestGetter : biggestSetter; for (Method property : unorderedPropertySetters) { - DbPropertySetter fieldAnnotation = property.getAnnotation(DbPropertySetter.class); + DbProperty fieldAnnotation = property.getAnnotation(DbProperty.class); int propertyId = fieldAnnotation.id(); if (propertyId > biggestPropertyId) { biggestPropertyId = propertyId; @@ -374,12 +431,12 @@ public class DatabaseObjectsIO implements IObjectsIO { DbDataType[] propertyTypes = new DbDataType[biggestPropertyId + 1]; Method[] propertyGetters = new Method[biggestPropertyId + 1]; Method[] propertySetters = new Method[biggestPropertyId + 1]; - Map setterMethods = new LinkedHashMap<>(); - Map getterMethods = new LinkedHashMap<>(); + Map setterMethods = new LinkedHashMap<>(); + Map getterMethods = new LinkedHashMap<>(); // Load the properties metadata for (Method property : unorderedPropertyGetters) { - DbPropertyGetter propertyAnnotation = property.getAnnotation(DbPropertyGetter.class); + DbProperty propertyAnnotation = property.getAnnotation(DbProperty.class); int propertyId = propertyAnnotation.id(); DbDataType propertyType = propertyAnnotation.type(); propertyTypes[propertyId] = propertyType; @@ -387,7 +444,7 @@ public class DatabaseObjectsIO implements IObjectsIO { getterMethods.put(property.getName(), propertyAnnotation); } for (Method property : unorderedPropertySetters) { - DbPropertySetter propertyAnnotation = property.getAnnotation(DbPropertySetter.class); + DbProperty propertyAnnotation = property.getAnnotation(DbProperty.class); int propertyId = propertyAnnotation.id(); DbDataType propertyType = propertyAnnotation.type(); propertyTypes[propertyId] = propertyType; @@ -402,7 +459,7 @@ public class DatabaseObjectsIO implements IObjectsIO { int getBiggestPropertyGetterId(Method[] unorderedPropertyGetters) { int biggestPropertyId = -1; for (Method property : unorderedPropertyGetters) { - DbPropertyGetter fieldAnnotation = property.getAnnotation(DbPropertyGetter.class); + DbProperty fieldAnnotation = property.getAnnotation(DbProperty.class); int propertyId = fieldAnnotation.id(); if (propertyId > biggestPropertyId) { biggestPropertyId = propertyId; @@ -414,7 +471,7 @@ public class DatabaseObjectsIO implements IObjectsIO { int getBiggestPropertySetterId(Method[] unorderedPropertySetters) { int biggestPropertyId = -1; for (Method property : unorderedPropertySetters) { - DbPropertySetter fieldAnnotation = property.getAnnotation(DbPropertySetter.class); + DbProperty fieldAnnotation = property.getAnnotation(DbProperty.class); int propertyId = fieldAnnotation.id(); if (propertyId > biggestPropertyId) { biggestPropertyId = propertyId; @@ -513,10 +570,10 @@ public class DatabaseObjectsIO implements IObjectsIO { void loadField(T obj, Field field, DbDataType fieldType, long fieldReference) throws IOException { - Object data = loadData(fieldType, fieldReference, field::getType); + lock.readLock().lock(); try { - if (fieldType == DbDataType.OBJECT && data != null) { - if (!field.getType().isInstance(data)) { + Object data = loadData(fieldType, fieldReference); + try { throw new IOException("There is an attempt to load an object of type " + data.getClass() + " into a field of type " + field.getType()); } diff --git a/src/main/java/it/cavallium/strangedb/java/database/IObjectsIO.java b/src/main/java/it/cavallium/strangedb/java/database/IObjectsIO.java index b5f7504..542a1a8 100644 --- a/src/main/java/it/cavallium/strangedb/java/database/IObjectsIO.java +++ b/src/main/java/it/cavallium/strangedb/java/database/IObjectsIO.java @@ -2,6 +2,7 @@ package it.cavallium.strangedb.java.database; import it.cavallium.strangedb.java.objects.EnhancedObject; import it.cavallium.strangedb.java.annotations.DbDataType; +import it.cavallium.strangedb.java.objects.EnhancedObjectIndices; import it.unimi.dsi.fastutil.longs.LongArrayList; import it.unimi.dsi.fastutil.longs.LongList; @@ -9,7 +10,10 @@ import java.io.IOException; import java.lang.reflect.Method; public interface IObjectsIO { - T loadEnhancedObject(long reference, Class objectType) throws IOException; + @SuppressWarnings("unchecked") + T loadEnhancedObject(long reference) throws IOException; + + EnhancedObjectIndices loadEnhancedObjectUids(long reference) throws IOException; T loadObject(long reference) throws IOException; @@ -47,7 +51,7 @@ public interface IObjectsIO { return reference; } - void loadProperty(EnhancedObject enhancedObject, int propertyId, Method propertyGetter, DbDataType propertyType, long propertyUID) throws IOException; + void loadProperty(EnhancedObject enhancedObject, int propertyId, DbDataType propertyType, long propertyUID) throws IOException; void registerClass(Class type, int id); diff --git a/src/main/java/it/cavallium/strangedb/java/objects/EnhancedObject.java b/src/main/java/it/cavallium/strangedb/java/objects/EnhancedObject.java index 07b4b1f..44ea376 100644 --- a/src/main/java/it/cavallium/strangedb/java/objects/EnhancedObject.java +++ b/src/main/java/it/cavallium/strangedb/java/objects/EnhancedObject.java @@ -29,8 +29,8 @@ public abstract class EnhancedObject { private long[] propertyReferences; private boolean[] loadedProperties; private Object[] loadedPropertyValues; - private Map setterMethods; - private Map getterMethods; + private Map setterMethods; + private Map getterMethods; public EnhancedObject() { version = getClassVersion(); @@ -82,7 +82,7 @@ public abstract class EnhancedObject { StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); StackWalker.StackFrame stackFrame = walker.walk(f -> f.skip(1).findFirst().orElse(null)); try { - int propertyId = stackFrame.getDeclaringClass().getDeclaredMethod(stackFrame.getMethodName()).getAnnotation(DbPropertyGetter.class).id(); + int propertyId = stackFrame.getDeclaringClass().getDeclaredMethod(stackFrame.getMethodName()).getAnnotation(DbProperty.class).id(); return getProperty(propertyId); } catch (IOException | NoSuchMethodException e) { throw new RuntimeException(e); @@ -90,10 +90,10 @@ public abstract class EnhancedObject { } @SuppressWarnings("unchecked") - private T getProperty(int propertyId) throws IOException { + public T getProperty(int propertyId) throws IOException { if (!loadedProperties[propertyId]) { long propertyUID = propertyReferences[propertyId]; - databaseTools.getObjectsIO().loadProperty(this, propertyId, propertyGetters[propertyId], propertyTypes[propertyId], propertyUID); + databaseTools.getObjectsIO().loadProperty(this, propertyId, propertyTypes[propertyId], propertyUID); } return (T) loadedPropertyValues[propertyId]; } @@ -101,7 +101,7 @@ public abstract class EnhancedObject { public void setProperty(T value) { StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); StackWalker.StackFrame stackFrame = walker.walk(f -> f.skip(1).findFirst().orElse(null)); - DbPropertySetter propertyAnnotation = setterMethods.get(stackFrame.getMethodName()); + DbProperty propertyAnnotation = setterMethods.get(stackFrame.getMethodName()); setProperty(propertyAnnotation.id(), value); } diff --git a/src/main/java/it/cavallium/strangedb/java/objects/EnhancedObjectIndices.java b/src/main/java/it/cavallium/strangedb/java/objects/EnhancedObjectIndices.java new file mode 100644 index 0000000..242c2cc --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/java/objects/EnhancedObjectIndices.java @@ -0,0 +1,15 @@ +package it.cavallium.strangedb.java.objects; + +public class EnhancedObjectIndices { + public final long objectUid; + public final long[] fieldUids; + public final long[] propertyUids; + public final long nativeDataUid; + + public EnhancedObjectIndices(long objectUid, long[] fieldUids, long[] propertyUids, long nativeDataUid) { + this.objectUid = objectUid; + this.fieldUids = fieldUids; + this.propertyUids = propertyUids; + this.nativeDataUid = nativeDataUid; + } +} diff --git a/src/main/java/it/cavallium/strangedb/java/objects/EnhancedObjectUpgrader.java b/src/main/java/it/cavallium/strangedb/java/objects/EnhancedObjectUpgrader.java index dfa40c7..89c7836 100644 --- a/src/main/java/it/cavallium/strangedb/java/objects/EnhancedObjectUpgrader.java +++ b/src/main/java/it/cavallium/strangedb/java/objects/EnhancedObjectUpgrader.java @@ -41,15 +41,7 @@ public interface EnhancedObjectUpgrader { return getPrimitiveField(id, DbPrimitiveType.DOUBLE); } - Object getField(int id, DbDataType type, Supplier> enhancedClassType) throws IOException; + Object getField(int id, DbDataType type) throws IOException; - default Object getField(int id, DbDataType type) throws IOException { - return getField(id, type, null); - } - - Object getMethod(int id, DbDataType type, Supplier> enhancedClassType) throws IOException; - - default Object getMethod(int id, DbDataType type) throws IOException { - return getField(id, type, null); - } + Object getMethod(int id, DbDataType type) throws IOException; } diff --git a/src/main/java/it/cavallium/strangedb/java/objects/lists/ElementsArrayList.java b/src/main/java/it/cavallium/strangedb/java/objects/lists/ElementsArrayList.java new file mode 100644 index 0000000..afd22c7 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/java/objects/lists/ElementsArrayList.java @@ -0,0 +1,70 @@ +package it.cavallium.strangedb.java.objects.lists; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class ElementsArrayList implements ElementsList { + + private final ArrayList list; + + public ElementsArrayList() { + this.list = new ArrayList<>(); + } + + public ElementsArrayList(Collection collection) { + this.list = new ArrayList<>(collection); + } + + public ElementsArrayList(int initialCapacity) { + this.list = new ArrayList<>(initialCapacity); + } + + @Override + public T get(int index) { + return list.get(index); + } + + @Override + public void add(T value) { + list.add(value); + } + + @Override + public void update(int index, T value) { + set(index, value); + } + + @Override + public void set(int index, T value) { + list.set(index, value); + } + + @Override + public void add(int index, T value) { + list.add(index, value); + } + + @Override + public T getLast() { + return list.get(list.size() - 1); + } + + @Override + public boolean isEmpty() { + return list.isEmpty(); + } + + @Override + public int size() { + return list.size(); + } + + public boolean contains(Object o) { + return list.contains(o); + } + + public ArrayList asList() { + return list; + } +} diff --git a/src/main/java/it/cavallium/strangedb/java/objects/lists/ElementsList.java b/src/main/java/it/cavallium/strangedb/java/objects/lists/ElementsList.java new file mode 100644 index 0000000..1ffcd41 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/java/objects/lists/ElementsList.java @@ -0,0 +1,14 @@ +package it.cavallium.strangedb.java.objects.lists; + +import java.io.IOException; + +interface ElementsList { + T get(int index) throws IOException; + void add(T value) throws IOException; + void update(int index, T value) throws IOException; + void set(int index, T value) throws IOException; + void add(int index, T value) throws IOException; + T getLast() throws IOException; + boolean isEmpty(); + int size(); +} diff --git a/src/main/java/it/cavallium/strangedb/java/objects/lists/EnhancedObjectStrangeDbList.java b/src/main/java/it/cavallium/strangedb/java/objects/lists/EnhancedObjectStrangeDbList.java index e1bb0ce..a43f875 100644 --- a/src/main/java/it/cavallium/strangedb/java/objects/lists/EnhancedObjectStrangeDbList.java +++ b/src/main/java/it/cavallium/strangedb/java/objects/lists/EnhancedObjectStrangeDbList.java @@ -1,5 +1,6 @@ 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; @@ -33,11 +34,156 @@ public class EnhancedObjectStrangeDbList extends Stran @Override protected T loadItem(long uid) throws IOException { - return databaseTools.getObjectsIO().loadEnhancedObject(uid, type); + return databaseTools.getObjectsIO().loadEnhancedObject(uid); } @Override protected void writeItemToDisk(long uid, T item) throws IOException { databaseTools.getObjectsIO().setEnhancedObject(uid, item); } + + public ElementsArrayList queryUids(ListQuery query) throws IOException { + ElementsArrayList uids = executeQuery(query, this, databaseTools.getObjectsIO()); + return uids; + } + + public ElementsArrayList query(ListQuery query) throws IOException { + ElementsArrayList uids = queryUids(query); + ElementsArrayList 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 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 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 results = new ElementsArrayList<>(); + for (ListQuery childQuery : children) { + ElementsArrayList 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 main, ElementsList 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 toElementsArrayList(ElementsList elementsList) { + if (elementsList instanceof EnhancedObjectStrangeDbList) { + return new ElementsArrayList<>(((EnhancedObjectStrangeDbList) elementsList).getIndices()); + } else if (elementsList instanceof ElementsArrayList) { + return (ElementsArrayList) elementsList; + } else { + throw new UnsupportedOperationException(); + } + } + + @SuppressWarnings("unchecked") + private static ElementsArrayList executeQueryElement(ListQuery.ListQueryElement query, ElementsList inputList, IObjectsIO dbio) throws IOException { + ElementsArrayList 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 elementsUids = ((ElementsArrayList) 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"); + } + } diff --git a/src/main/java/it/cavallium/strangedb/java/objects/lists/KMP.java b/src/main/java/it/cavallium/strangedb/java/objects/lists/KMP.java new file mode 100644 index 0000000..3c41d71 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/java/objects/lists/KMP.java @@ -0,0 +1,58 @@ +package it.cavallium.strangedb.java.objects.lists; + +public class KMP { + public static int KMP(CharSequence content, CharSequence stringToFind) { + int[] failureTable = failureTable(stringToFind); + + int targetPointer = 0; // current char in target string + int searchPointer = 0; // current char in search string + + while (searchPointer < content.length()) { // while there is more to search with, keep searching + if (content.charAt(searchPointer) == stringToFind.charAt(targetPointer)) { // case 1 + // found current char in targetPointer in search string + targetPointer++; + if (targetPointer == stringToFind.length()) { // found all characters + int x = stringToFind.length() + 1; + return searchPointer - x; // return starting index of found target inside searched string + } + searchPointer++; // move forward if not found target string + } else if (targetPointer > 0) { // case 2 + // use failureTable to use pointer pointed at nearest location of usable string prefix + targetPointer = failureTable[targetPointer]; + } else { // case 3 + // targetPointer is pointing at state 0, so restart search with current searchPointer index + searchPointer++; + } + } + return -1; + } + + /** + * Returns an int[] that points to last valid string prefix, given target string + */ + public static int[] failureTable(CharSequence target) { + int[] table = new int[target.length() + 1]; + // state 0 and 1 are guarenteed be the prior + table[0] = -1; + table[1] = 0; + + // the pointers pointing at last failure and current satte + int left = 0; + int right = 2; + + while (right < table.length) { // RIGHT NEVER MOVES RIGHT UNTIL ASSIGNED A VALID POINTER + if (target.charAt(right - 1) == target.charAt(left)) { // when both chars before left and right are equal, link both and move both forward + left++; + table[right] = left; + right++; + } else if (left > 0) { // if left isn't at the very beginning, then send left backward + // by following the already set pointer to where it is pointing to + left = table[left]; + } else { // left has fallen all the way back to the beginning + table[right] = left; + right++; + } + } + return table; + } +} diff --git a/src/main/java/it/cavallium/strangedb/java/objects/lists/ListQuery.java b/src/main/java/it/cavallium/strangedb/java/objects/lists/ListQuery.java new file mode 100644 index 0000000..e19343d --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/java/objects/lists/ListQuery.java @@ -0,0 +1,105 @@ +package it.cavallium.strangedb.java.objects.lists; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public abstract class ListQuery { + + public static ListQuery create(ValuePointer valuePointer, ValueOperation valueOperation) { + return new ListQueryElement(valuePointer, valueOperation); + } + + public ListQuery and(ValuePointer valuePointer, ValueOperation operation) { + return new ListQueryAnd(this, create(valuePointer, operation)); + } + + public ListQuery and(ListQuery query) { + return new ListQueryAnd(this, query); + } + + public ListQuery or(ValuePointer valuePointer, ValueOperation operation) { + return new ListQueryOr(this, create(valuePointer, operation)); + } + + public ListQuery or(ListQuery query) { + return new ListQueryOr(this, query); + } + + abstract List getQueryElementsRecursively(); + + static class ListQueryElement extends ListQuery { + public final ValuePointer valuePointer; + public final ValueOperation valueOperation; + + private ListQueryElement(ValuePointer valuePointer, ValueOperation valueOperation) { + this.valuePointer = valuePointer; + this.valueOperation = valueOperation; + } + + @Override + List getQueryElementsRecursively() { + return Collections.singletonList(this); + } + } + + static class ListQueryCollection extends ListQuery { + protected ListQuery[] queries; + + private ListQueryCollection(ListQuery... queries) { + this.queries = queries; + } + + @Override + List getQueryElementsRecursively() { + List elements = new ArrayList<>(); + for (ListQuery query : queries) { + elements.addAll(query.getQueryElementsRecursively()); + } + return elements; + } + + ListQuery[] getQueryChildren() { + return queries.clone(); + } + } + + static class ListQueryAnd extends ListQueryCollection { + private ListQueryAnd(ListQuery... queries) { + super(queries); + } + + @Override + public ListQuery and(ListQuery query) { + return new ListQueryAnd(append(this.queries, query)); + } + + @Override + public ListQuery and(ValuePointer valuePointer, ValueOperation operation) { + return and(create(valuePointer, operation)); + } + } + + static class ListQueryOr extends ListQueryCollection { + private ListQueryOr(ListQuery... queries) { + super(queries); + } + + @Override + public ListQuery or(ListQuery query) { + return new ListQueryOr(append(this.queries, query)); + } + + @Override + public ListQuery or(ValuePointer valuePointer, ValueOperation operation) { + return or(create(valuePointer, operation)); + } + } + + private static T[] append(T[] array, T value) { + T[] newArray = Arrays.copyOf(array, array.length + 1); + newArray[array.length] = value; + return newArray; + } +} diff --git a/src/main/java/it/cavallium/strangedb/java/objects/lists/ObjectStrangeDbList.java b/src/main/java/it/cavallium/strangedb/java/objects/lists/ObjectStrangeDbList.java index 0bd76c8..fc3f489 100644 --- a/src/main/java/it/cavallium/strangedb/java/objects/lists/ObjectStrangeDbList.java +++ b/src/main/java/it/cavallium/strangedb/java/objects/lists/ObjectStrangeDbList.java @@ -17,7 +17,7 @@ public class ObjectStrangeDbList extends StrangeDbList { return indices; } - protected ObjectStrangeDbList() { + public ObjectStrangeDbList() { super(); } diff --git a/src/main/java/it/cavallium/strangedb/java/objects/lists/StrangeDbList.java b/src/main/java/it/cavallium/strangedb/java/objects/lists/StrangeDbList.java index 05696aa..f42010b 100644 --- a/src/main/java/it/cavallium/strangedb/java/objects/lists/StrangeDbList.java +++ b/src/main/java/it/cavallium/strangedb/java/objects/lists/StrangeDbList.java @@ -5,10 +5,9 @@ import it.cavallium.strangedb.java.objects.EnhancedObject; import it.cavallium.strangedb.java.database.IDatabaseTools; import java.io.IOException; -import java.util.Collection; import java.util.StringJoiner; -public abstract class StrangeDbList extends EnhancedObject { +public abstract class StrangeDbList extends EnhancedObject implements ElementsList { private final Object indicesAccessLock = new Object(); @@ -22,6 +21,7 @@ public abstract class StrangeDbList extends EnhancedObject { super(databaseTools); } + @Override public T get(int index) throws IOException { synchronized (indicesAccessLock) { long uid = getIndices().getLong(index); @@ -29,6 +29,7 @@ public abstract class StrangeDbList extends EnhancedObject { } } + @Override public void add(T value) throws IOException { long uid = databaseTools.getObjectsIO().newNullObject(); synchronized (indicesAccessLock) { @@ -37,13 +38,16 @@ public abstract class StrangeDbList extends EnhancedObject { } } + @Override public void update(int index, T value) throws IOException { - synchronized (indicesAccessLock) { - long uid = getIndices().getLong(index); - writeItemToDisk(uid, value); + lock.writeLock().lock(); + try { + set(index, value); + } finally { } } + @Override public void set(int index, T value) throws IOException { long uid = databaseTools.getObjectsIO().newNullObject(); synchronized (indicesAccessLock) { @@ -52,6 +56,7 @@ public abstract class StrangeDbList extends EnhancedObject { } } + @Override public void add(int index, T value) throws IOException { long uid = databaseTools.getObjectsIO().newNullObject(); synchronized (indicesAccessLock) { @@ -88,7 +93,7 @@ public abstract class StrangeDbList extends EnhancedObject { @Override public String toString() { - return new StringJoiner(", ", StrangeDbList.class.getSimpleName() + "[", "]") + return new StringJoiner(", ", StrangeDbList.class.getSimpleName() + "[", "]") .add(getIndices().size() + " items") .toString(); } diff --git a/src/main/java/it/cavallium/strangedb/java/objects/lists/ValueOperation.java b/src/main/java/it/cavallium/strangedb/java/objects/lists/ValueOperation.java new file mode 100644 index 0000000..9675c3a --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/java/objects/lists/ValueOperation.java @@ -0,0 +1,5 @@ +package it.cavallium.strangedb.java.objects.lists; + +public interface ValueOperation { + public boolean evaluate(Object value); +} diff --git a/src/main/java/it/cavallium/strangedb/java/objects/lists/ValuePointer.java b/src/main/java/it/cavallium/strangedb/java/objects/lists/ValuePointer.java new file mode 100644 index 0000000..03cf8f4 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/java/objects/lists/ValuePointer.java @@ -0,0 +1,139 @@ +package it.cavallium.strangedb.java.objects.lists; + +import it.cavallium.strangedb.java.annotations.DbField; +import it.cavallium.strangedb.java.annotations.DbPrimitiveField; +import it.cavallium.strangedb.java.annotations.DbProperty; +import it.cavallium.strangedb.java.objects.EnhancedObject; +import org.apache.commons.lang3.reflect.FieldUtils; +import org.apache.commons.lang3.reflect.MethodUtils; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Arrays; + +public class ValuePointer { + + private static ValuePointer base = new ValuePointer(new int[0], new ValueType[0]); + + private final int[] pathNumbers; + private final ValueType[] pathTypes; + + private ValuePointer(int[] pathNumbers, ValueType[] pathTypes) { + this.pathNumbers = pathNumbers; + this.pathTypes = pathTypes; + } + + public static ValuePointer ofField(Class parentType, String field) { + return base.field(parentType, field); + } + + public static ValuePointer ofProp(Class parentType, String property) { + return base.prop(parentType, property); + } + public static ValuePointer ofPrimitiveField(Class parentType, String primitiveFieldName) { + return base.primitiveField(parentType, primitiveFieldName); + } + + public ValuePointer prop(Class parentType, String propertyName) { + + ValueType[] newPathTypes = append(this.pathTypes, ValueType.FIELD); + + Method[] methods = MethodUtils.getMethodsWithAnnotation(parentType, DbProperty.class); + DbProperty dbProperty = null; + for (Method method : methods) { + DbProperty annotation = method.getAnnotation(DbProperty.class); + if (annotation.name().equals(propertyName)) { + dbProperty = annotation; + break; + } + } + if (dbProperty == null) { + throw new IllegalArgumentException("Property '" + propertyName + "' not found in class " + parentType.getSimpleName()); + } + + int[] newPathNumbers = append(this.pathNumbers, dbProperty.id()); + return new ValuePointer(newPathNumbers, newPathTypes); + } + + public ValuePointer field(Class parentType, String fieldName) { + ValueType[] newPathTypes = append(this.pathTypes, ValueType.FIELD); + + Field[] fields = FieldUtils.getFieldsWithAnnotation(parentType, DbField.class); + DbField dbField = null; + for (Field field : fields) { + DbField annotation = field.getAnnotation(DbField.class); + if (annotation.name().equals(fieldName)) { + dbField = annotation; + break; + } + } + if (dbField == null) { + throw new IllegalArgumentException("Field '" + fieldName + "' not found in class " + parentType.getSimpleName()); + } + + int[] newPathNumbers = append(this.pathNumbers, dbField.id()); + return new ValuePointer(newPathNumbers, newPathTypes); + } + + public ValuePointer primitiveField(Class parentType, String primitiveFieldName) { + ValueType[] newPathTypes = append(this.pathTypes, ValueType.PRIMITIVE_FIELD); + + Field[] fields = FieldUtils.getFieldsWithAnnotation(parentType, DbPrimitiveField.class); + DbPrimitiveField dbField = null; + for (Field field : fields) { + DbPrimitiveField annotation = field.getAnnotation(DbPrimitiveField.class); + if (annotation.name().equals(primitiveFieldName)) { + dbField = annotation; + break; + } + } + if (dbField == null) { + throw new IllegalArgumentException("Field '" + primitiveFieldName + "' not found in class " + parentType.getSimpleName()); + } + + int[] newPathNumbers = append(this.pathNumbers, dbField.id()); + return new ValuePointer(newPathNumbers, newPathTypes); + } + + public ValuePointer at(int index) { + if (index >= pathNumbers.length) { + throw new ArrayIndexOutOfBoundsException(); + } + if (index == pathNumbers.length - 1) { + return this; + } + return new ValuePointer(Arrays.copyOf(this.pathNumbers, index + 1), Arrays.copyOf(this.pathTypes, index + 1)); + } + + public int size() { + return this.pathNumbers.length; + } + + public boolean hasPrevious() { + return pathNumbers.length > 0; + } + + public ValuePointer previous() { + return at(pathNumbers.length - 2); + } + + private static int[] append(int[] array, int value) { + int[] newArray = Arrays.copyOf(array, array.length + 1); + newArray[array.length] = value; + return newArray; + } + + private static T[] append(T[] array, T value) { + T[] newArray = Arrays.copyOf(array, array.length + 1); + newArray[array.length] = value; + return newArray; + } + + public int getPathNumber() { + return pathNumbers[pathNumbers.length - 1]; + } + + public ValueType getPathType() { + return pathTypes[pathTypes.length - 1]; + } +} diff --git a/src/main/java/it/cavallium/strangedb/java/objects/lists/ValueType.java b/src/main/java/it/cavallium/strangedb/java/objects/lists/ValueType.java new file mode 100644 index 0000000..e09c799 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/java/objects/lists/ValueType.java @@ -0,0 +1,7 @@ +package it.cavallium.strangedb.java.objects.lists; + +public enum ValueType { + PROPERTY, + FIELD, + PRIMITIVE_FIELD +} diff --git a/src/main/java/it/cavallium/strangedb/java/objects/lists/operations/Contains.java b/src/main/java/it/cavallium/strangedb/java/objects/lists/operations/Contains.java new file mode 100644 index 0000000..b40f556 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/java/objects/lists/operations/Contains.java @@ -0,0 +1,25 @@ +package it.cavallium.strangedb.java.objects.lists.operations; + +import it.cavallium.strangedb.java.objects.lists.KMP; +import it.cavallium.strangedb.java.objects.lists.ValueOperation; + +public class Contains implements ValueOperation { + + private final T containsValue; + + private Contains(T containsValue) { + this.containsValue = containsValue; + } + + public static Contains containsValue(T value) { + return new Contains(value); + } + + @Override + public boolean evaluate(Object value) { + if (value instanceof CharSequence) { + return KMP.KMP((CharSequence) value, containsValue) != -1; + } + return false; + } +} diff --git a/src/main/java/it/cavallium/strangedb/java/objects/lists/operations/ContainsIgnoreCase.java b/src/main/java/it/cavallium/strangedb/java/objects/lists/operations/ContainsIgnoreCase.java new file mode 100644 index 0000000..8594775 --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/java/objects/lists/operations/ContainsIgnoreCase.java @@ -0,0 +1,25 @@ +package it.cavallium.strangedb.java.objects.lists.operations; + +import it.cavallium.strangedb.java.objects.lists.KMP; +import it.cavallium.strangedb.java.objects.lists.ValueOperation; + +public class ContainsIgnoreCase implements ValueOperation { + + private final String containsValue; + + private ContainsIgnoreCase(String containsValue) { + this.containsValue = containsValue.toLowerCase(); + } + + public static ContainsIgnoreCase containsValue(String value) { + return new ContainsIgnoreCase(value); + } + + @Override + public boolean evaluate(Object value) { + if (value instanceof String) { + return KMP.KMP(((String) value).toLowerCase(), containsValue) != -1; + } + return false; + } +} diff --git a/src/main/java/it/cavallium/strangedb/java/objects/lists/operations/Equals.java b/src/main/java/it/cavallium/strangedb/java/objects/lists/operations/Equals.java new file mode 100644 index 0000000..a8e5c1b --- /dev/null +++ b/src/main/java/it/cavallium/strangedb/java/objects/lists/operations/Equals.java @@ -0,0 +1,21 @@ +package it.cavallium.strangedb.java.objects.lists.operations; + +import it.cavallium.strangedb.java.objects.lists.ValueOperation; + +public class Equals implements ValueOperation { + + private final T equalToValue; + + private Equals(T equalToValue) { + this.equalToValue = equalToValue; + } + + public static Equals to(T value) { + return new Equals(value); + } + + @Override + public boolean evaluate(Object value) { + return equalToValue.equals(value); + } +} diff --git a/src/test/java/it/cavallium/strangedb/tests/Clean.java b/src/test/java/it/cavallium/strangedb/tests/Clean.java index fc32e0d..bd0a977 100644 --- a/src/test/java/it/cavallium/strangedb/tests/Clean.java +++ b/src/test/java/it/cavallium/strangedb/tests/Clean.java @@ -1,14 +1,11 @@ package it.cavallium.strangedb.tests; +import it.cavallium.strangedb.java.annotations.*; import org.junit.After; import org.junit.Before; import org.junit.Test; 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 it.cavallium.strangedb.java.annotations.DbPropertyGetter; -import it.cavallium.strangedb.java.annotations.DbPropertySetter; import it.cavallium.strangedb.utils.NTestUtils; import java.io.IOException; @@ -20,7 +17,7 @@ public class Clean { @Before public void setUp() throws Exception { db = NTestUtils.wrapDb().create((db) -> { - root = db.get().loadRoot(RootTwoClasses.class, RootTwoClasses::new); + root = db.get().loadRoot(RootTwoClasses::new); }); root.class1 = new NTestUtils.RootClass(db.get()); db.setRootClassValues(root.class1); @@ -40,7 +37,7 @@ public class Clean { db.testRootClassValues(root.getClass4()); db.get().closeAndClean(); db = NTestUtils.wrapDb().create((db) -> { - root = db.get().loadRoot(RootTwoClasses.class, RootTwoClasses::new); + root = db.get().loadRoot(RootTwoClasses::new); }); } @@ -65,22 +62,26 @@ public class Clean { super(databaseTools); } - @DbPropertyGetter(id = 0, type = DbDataType.ENHANCED_OBJECT) + @DbProperty(id = 0, type = DbDataType.ENHANCED_OBJECT) + @DbPropertyGetter public NTestUtils.RootClass getClass3() { return getProperty(); } - @DbPropertySetter(id = 0, type = DbDataType.ENHANCED_OBJECT) + @DbProperty(id = 0, type = DbDataType.ENHANCED_OBJECT) + @DbPropertySetter public void setClass3(NTestUtils.RootClass value) { setProperty(value); } - @DbPropertyGetter(id = 1, type = DbDataType.ENHANCED_OBJECT) + @DbProperty(id = 1, type = DbDataType.ENHANCED_OBJECT) + @DbPropertyGetter public NTestUtils.RootClass getClass4() { return getProperty(); } - @DbPropertySetter(id = 1, type = DbDataType.ENHANCED_OBJECT) + @DbProperty(id = 1, type = DbDataType.ENHANCED_OBJECT) + @DbPropertySetter public void setClass4(NTestUtils.RootClass value) { setProperty(value); } diff --git a/src/test/java/it/cavallium/strangedb/tests/EnhancedClassUpdate.java b/src/test/java/it/cavallium/strangedb/tests/EnhancedClassUpdate.java index 2416e48..bb6b272 100644 --- a/src/test/java/it/cavallium/strangedb/tests/EnhancedClassUpdate.java +++ b/src/test/java/it/cavallium/strangedb/tests/EnhancedClassUpdate.java @@ -25,7 +25,7 @@ public class EnhancedClassUpdate { path2 = Files.createTempFile("db-tests-blocks-", ".db"); path3 = Files.createTempFile("db-tests-references-", ".db"); db = new DatabaseJava(path1, path2, path3); - OldClass root = db.loadRoot(OldClass.class, OldClass::new); + OldClass root = db.loadRoot(OldClass::new); root.field1 = "Abc"; root.field2 = 12; root.field4 = 13; @@ -35,7 +35,7 @@ public class EnhancedClassUpdate { @Test public void shouldUpdateClass() throws IOException { db = new DatabaseJava(path1, path2, path3); - V2Class root = db.loadRoot(V2Class.class, V2Class::new); + V2Class root = db.loadRoot(V2Class::new); assertEquals(root.field4, "Abc"); assertEquals(root.field2, 12); assertEquals(root.field1, 13L); diff --git a/src/test/java/it/cavallium/strangedb/tests/ListContainer.java b/src/test/java/it/cavallium/strangedb/tests/ListContainer.java new file mode 100644 index 0000000..ad27ca7 --- /dev/null +++ b/src/test/java/it/cavallium/strangedb/tests/ListContainer.java @@ -0,0 +1,44 @@ +package it.cavallium.strangedb.tests; + +import it.cavallium.strangedb.java.annotations.DbDataType; +import it.cavallium.strangedb.java.annotations.DbField; +import it.cavallium.strangedb.java.database.IDatabaseTools; +import it.cavallium.strangedb.java.objects.EnhancedObject; +import it.cavallium.strangedb.java.objects.lists.EnhancedObjectStrangeDbList; + +import java.io.IOException; +import java.util.Random; + +public class ListContainer extends EnhancedObject { + + @DbField(id = 0, type = DbDataType.ENHANCED_OBJECT) + public EnhancedObjectStrangeDbList usersList; + + public ListContainer() { + } + + public ListContainer(IDatabaseTools databaseTools, int count) throws IOException { + super(databaseTools); + this.usersList = new EnhancedObjectStrangeDbList<>(databaseTools, User.class); + Random random = new Random(); + for (int i = 0; i < count; i++) { + User usr; + int randomInt = random.nextInt(2); + switch (randomInt) { + case 0: + usr = new User(databaseTools, "Rossi" + count + "Mario"+count, "the" + count + "_mariorossi99", "Long long big " + count + " giant bio mario rossi 99 abcdefghijklmnopqrstuvwxyz"); + break; + case 1: + usr = new User(databaseTools, QueryTests.constantFirstName, QueryTests.constantUsername, QueryTests.constantBio); + break; + case 2: + usr = new User(databaseTools, QueryTests.constantFirstName, "b" + count + "a", QueryTests.constantBio); + break; + default: + throw new ArrayIndexOutOfBoundsException(); + } + this.usersList.add(usr); + } + } + +} diff --git a/src/test/java/it/cavallium/strangedb/tests/MultipleEnhancedObjects.java b/src/test/java/it/cavallium/strangedb/tests/MultipleEnhancedObjects.java index 23cd1db..d6177d7 100644 --- a/src/test/java/it/cavallium/strangedb/tests/MultipleEnhancedObjects.java +++ b/src/test/java/it/cavallium/strangedb/tests/MultipleEnhancedObjects.java @@ -1,10 +1,7 @@ package it.cavallium.strangedb.tests; +import it.cavallium.strangedb.java.annotations.*; import it.cavallium.strangedb.java.objects.EnhancedObject; -import it.cavallium.strangedb.java.annotations.DbDataType; -import it.cavallium.strangedb.java.annotations.DbField; -import it.cavallium.strangedb.java.annotations.DbPropertyGetter; -import it.cavallium.strangedb.java.annotations.DbPropertySetter; import it.cavallium.strangedb.java.database.IDatabaseTools; import it.cavallium.strangedb.utils.NTestUtils; import org.junit.After; @@ -20,7 +17,7 @@ public class MultipleEnhancedObjects { @Before public void setUp() throws Exception { db = NTestUtils.wrapDb().create((db) -> { - root = db.get().loadRoot(RootTwoClasses.class, RootTwoClasses::new); + root = db.get().loadRoot(RootTwoClasses::new); }); root.class1 = new NTestUtils.RootClass(db.get()); db.setRootClassValues(root.class1); @@ -62,22 +59,26 @@ public class MultipleEnhancedObjects { super(databaseTools); } - @DbPropertyGetter(id = 0, type = DbDataType.ENHANCED_OBJECT) + @DbProperty(id = 0, type = DbDataType.ENHANCED_OBJECT) + @DbPropertyGetter public NTestUtils.RootClass getClass3() { return getProperty(); } - @DbPropertySetter(id = 0, type = DbDataType.ENHANCED_OBJECT) + @DbProperty(id = 0, type = DbDataType.ENHANCED_OBJECT) + @DbPropertySetter public void setClass3(NTestUtils.RootClass value) { setProperty(value); } - @DbPropertyGetter(id = 1, type = DbDataType.ENHANCED_OBJECT) + @DbProperty(id = 1, type = DbDataType.ENHANCED_OBJECT) + @DbPropertyGetter public NTestUtils.RootClass getClass4() { return getProperty(); } - @DbPropertySetter(id = 1, type = DbDataType.ENHANCED_OBJECT) + @DbProperty(id = 1, type = DbDataType.ENHANCED_OBJECT) + @DbPropertySetter public void setClass4(NTestUtils.RootClass value) { setProperty(value); } diff --git a/src/test/java/it/cavallium/strangedb/tests/ObjectListTests.java b/src/test/java/it/cavallium/strangedb/tests/ObjectListTests.java new file mode 100644 index 0000000..784337e --- /dev/null +++ b/src/test/java/it/cavallium/strangedb/tests/ObjectListTests.java @@ -0,0 +1,139 @@ +package it.cavallium.strangedb.tests; + +import it.cavallium.strangedb.java.annotations.DbDataType; +import it.cavallium.strangedb.java.annotations.DbField; +import it.cavallium.strangedb.java.database.DatabaseJava; +import it.cavallium.strangedb.java.database.IDatabaseTools; +import it.cavallium.strangedb.java.objects.EnhancedObject; +import it.cavallium.strangedb.java.objects.lists.EnhancedObjectStrangeDbList; +import it.cavallium.strangedb.java.objects.lists.ObjectStrangeDbList; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.junit.Assert.assertEquals; + +public class ObjectListTests { + + private Path path1; + private Path path2; + private Path path3; + private DatabaseJava db; + + @Before + public void setUp() throws Exception { + path1 = Files.createTempFile("db-tests-data-", ".db"); + path2 = Files.createTempFile("db-tests-blocks-", ".db"); + path3 = Files.createTempFile("db-tests-references-", ".db"); + db = new DatabaseJava(path1, path2, path3); + ListsRoot root = db.loadRoot(ListsRoot::new); + for (int i = 0; i < 5000; i++) { + root.objectList.add(new ObjectItem(i)); + root.enhancedObjectList.add(new EnhancedObjectItem(db, i)); + } + for (int i = 0; i < 5000; i++) { + if (i % 10 == 0) { + root.objectList.update(i, new ObjectItem(i)); + root.enhancedObjectList.update(i, new EnhancedObjectItem(db, i)); + } + } + for (int i = 0; i < 5000; i++) { + if (i % 11 == 0) { + root.objectList.set(i, new ObjectItem(i)); + root.enhancedObjectList.set(i, new EnhancedObjectItem(db, i)); + } + } + for (int i = 5000; i < 6000; i++) { + root.objectList.add(new ObjectItem(0)); + root.enhancedObjectList.add(i, new EnhancedObjectItem(db, 0)); + } + db.close(); + } + + @Test + public void shouldUpdateClass() throws IOException { + db = new DatabaseJava(path1, path2, path3); + ListsRoot root = db.loadRoot(ListsRoot::new); + + new Thread(() -> { + try { + for (int i = 0; i < 5000; i++) { + String val = root.objectList.get(i).value; + assertEquals(val, "test_" + i); + val = root.enhancedObjectList.get(i).value; + assertEquals(val, "test_" + i); + } + for (int i = 5000; i < 6000; i++) { + assertEquals(root.objectList.get(i).value, "test_" + 0); + assertEquals(root.enhancedObjectList.get(i).value, "test_" + 0); + } + } catch (IOException e) { + e.printStackTrace(); + } + }).start(); + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + db.close(); + } + + @After + public void tearDown() throws Exception { + Files.deleteIfExists(path1); + Files.deleteIfExists(path2); + Files.deleteIfExists(path3); + } + + public static class ListsRoot extends EnhancedObject { + + @DbField(id = 0,name = "objectList", type = DbDataType.ENHANCED_OBJECT) + public ObjectStrangeDbList objectList; + @DbField(id = 1,name = "enhancedObjectList", type = DbDataType.ENHANCED_OBJECT) + public EnhancedObjectStrangeDbList enhancedObjectList; + + @Deprecated + public ListsRoot() { + + } + + + public ListsRoot(IDatabaseTools tools) throws IOException { + super(tools); + objectList = new ObjectStrangeDbList<>(tools); + enhancedObjectList = new EnhancedObjectStrangeDbList<>(tools, EnhancedObjectItem.class); + } + } + + public static class ObjectItem { + private String value; + + public ObjectItem() { + + } + + private ObjectItem(int i) { + this.value = "test_" + i; + } + } + + public static class EnhancedObjectItem extends EnhancedObject { + @DbField(id = 0, type = DbDataType.OBJECT, name = "value") + private String value; + + @Deprecated + public EnhancedObjectItem() { + + } + + public EnhancedObjectItem(IDatabaseTools tools, int i) throws IOException { + super(tools); + this.value = "test_" + i; + } + } +} diff --git a/src/test/java/it/cavallium/strangedb/tests/Performance.java b/src/test/java/it/cavallium/strangedb/tests/Performance.java index 2fa5bab..1f82833 100644 --- a/src/test/java/it/cavallium/strangedb/tests/Performance.java +++ b/src/test/java/it/cavallium/strangedb/tests/Performance.java @@ -49,16 +49,16 @@ public class Performance { System.out.println("Test name Total Time | Time at 1 Time at 10 Time at 100 Time at 1K Time at 10K"); System.out.println("-------------------------------------------------------+-----------------------------------------------------------------"); testS("DatabaseCore creation", 3000, Performance::deleteDb, Performance::generateDb, () -> {}); - testS("DatabaseCore root creation", 3000, Performance::regenDb, () -> db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new), () -> {}); + testS("DatabaseCore root creation", 3000, Performance::regenDb, () -> db.loadRoot(PreloadedListContainer::new), () -> {}); final VariableWrapper preloadedListContainer = new VariableWrapper<>(null); final VariableWrapper simpleEnhancedObjectContainer = new VariableWrapper<>(null); testS("ObjectStrangeDbList creation", 3000, () -> { regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); + preloadedListContainer.var = db.loadRoot(PreloadedListContainer::new); }, () -> preloadedListContainer.var.list = new ObjectStrangeDbList<>(db), () -> {}); testS("ObjectStrangeDbList: Filling with 1000 items", 100, () -> { regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); + preloadedListContainer.var = db.loadRoot(PreloadedListContainer::new); preloadedListContainer.var.list = new ObjectStrangeDbList<>(db); }, () -> { for (int i = 0; i < 1000; i++) { @@ -67,7 +67,7 @@ public class Performance { }, () -> {}); testS("ObjectStrangeDbList: Filling with 1000 items", 100, () -> { regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); + preloadedListContainer.var = db.loadRoot(PreloadedListContainer::new); preloadedListContainer.var.listOfEnhancedObj = new EnhancedObjectStrangeDbList<>(db, SimpleEnhancedObject.class); simpleEnhancedObjectContainer.var = new SimpleEnhancedObject(db); simpleEnhancedObjectContainer.var.integerNumber = 10; @@ -83,7 +83,7 @@ public class Performance { }, () -> {}); testS("ObjectStrangeDbList: Filling with 10000 items", 10, () -> { regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); + preloadedListContainer.var = db.loadRoot(PreloadedListContainer::new); preloadedListContainer.var.list = new ObjectStrangeDbList<>(db); }, () -> { for (int i = 0; i < 10000; i++) { @@ -92,7 +92,7 @@ public class Performance { }, () -> {}); testS("ObjectStrangeDbList: Filling with 100000 items", 1, () -> { regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); + preloadedListContainer.var = db.loadRoot(PreloadedListContainer::new); preloadedListContainer.var.list = new ObjectStrangeDbList<>(db); }, () -> { for (int i = 0; i < 100000; i++) { @@ -101,7 +101,7 @@ public class Performance { }, () -> {}); testS("ObjectStrangeDbList: Loading 1000 items", 100, () -> { regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); + preloadedListContainer.var = db.loadRoot(PreloadedListContainer::new); preloadedListContainer.var.list = new ObjectStrangeDbList<>(db); for (int i = 0; i < 1000; i++) { preloadedListContainer.var.list.add(1000); @@ -113,7 +113,7 @@ public class Performance { }, () -> {}); testS("ObjectStrangeDbList: Loading with 1000 items", 100, () -> { regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); + preloadedListContainer.var = db.loadRoot(PreloadedListContainer::new); preloadedListContainer.var.listOfEnhancedObj = new EnhancedObjectStrangeDbList<>(db, SimpleEnhancedObject.class); simpleEnhancedObjectContainer.var = new SimpleEnhancedObject(db); simpleEnhancedObjectContainer.var.integerNumber = 10; @@ -132,7 +132,7 @@ public class Performance { }, () -> {}); testS("ObjectStrangeDbList: Loading 10000 items", 10, () -> { regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); + preloadedListContainer.var = db.loadRoot(PreloadedListContainer::new); preloadedListContainer.var.list = new ObjectStrangeDbList<>(db); for (int i = 0; i < 10000; i++) { preloadedListContainer.var.list.add(1000); @@ -144,7 +144,7 @@ public class Performance { }, () -> {}); testS("ObjectStrangeDbList: getLast() with 1000 items", 100, () -> { regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); + preloadedListContainer.var = db.loadRoot(PreloadedListContainer::new); preloadedListContainer.var.list = new ObjectStrangeDbList<>(db); for (int i = 0; i < 1000; i++) { preloadedListContainer.var.list.add(1000); @@ -154,7 +154,7 @@ public class Performance { }, () -> {}); testS("ObjectStrangeDbList: getLast() with 1000 items", 100, () -> { regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); + preloadedListContainer.var = db.loadRoot(PreloadedListContainer::new); preloadedListContainer.var.listOfEnhancedObj = new EnhancedObjectStrangeDbList<>(db, SimpleEnhancedObject.class); simpleEnhancedObjectContainer.var = new SimpleEnhancedObject(db); simpleEnhancedObjectContainer.var.integerNumber = 10; @@ -171,7 +171,7 @@ public class Performance { }, () -> {}); testS("ObjectStrangeDbList: size() with 1000 items", 100, () -> { regenDb(); - preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new); + preloadedListContainer.var = db.loadRoot(PreloadedListContainer::new); preloadedListContainer.var.list = new ObjectStrangeDbList<>(db); for (int i = 0; i < 1000; i++) { preloadedListContainer.var.list.add(1000); @@ -318,12 +318,14 @@ public class Performance { } - @DbPropertyGetter(id = 0, type = DbDataType.ENHANCED_OBJECT) + @DbProperty(id = 0, type = DbDataType.ENHANCED_OBJECT) + @DbPropertyGetter() public ObjectStrangeDbList getList() { return getProperty(); } - @DbPropertySetter(id = 1, type = DbDataType.ENHANCED_OBJECT) + @DbProperty(id = 1, type = DbDataType.ENHANCED_OBJECT) + @DbPropertySetter() public void setList(ObjectStrangeDbList list) { setProperty(list); } diff --git a/src/test/java/it/cavallium/strangedb/tests/QueryTests.java b/src/test/java/it/cavallium/strangedb/tests/QueryTests.java new file mode 100644 index 0000000..9d4aaad --- /dev/null +++ b/src/test/java/it/cavallium/strangedb/tests/QueryTests.java @@ -0,0 +1,59 @@ +package it.cavallium.strangedb.tests; + +import it.cavallium.strangedb.java.database.DatabaseJava; +import it.cavallium.strangedb.java.objects.lists.ListQuery; +import it.cavallium.strangedb.java.objects.lists.ValuePointer; +import it.cavallium.strangedb.java.objects.lists.operations.Equals; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; + +import static org.junit.Assert.assertNotEquals; + +public class QueryTests { + + public static final String constantFirstName = "Jesus christ this is a very strange first name"; + public static final String constantUsername = "is this an username?"; + public static final String constantBio = "and is this a bio??? Are you mad?"; + private Path path1; + private Path path2; + private Path path3; + private DatabaseJava db; + + @Before + public void setUp() throws Exception { + path1 = Files.createTempFile("db-tests-data-", ".db"); + path2 = Files.createTempFile("db-tests-blocks-", ".db"); + path3 = Files.createTempFile("db-tests-references-", ".db"); + db = new DatabaseJava(path1, path2, path3); + } + + @Test + public void shouldCreateListAndQuery() throws IOException { + ListContainer root = db.loadRoot((db) -> new ListContainer(db, 1000)); + ListQuery query = ListQuery.create(ValuePointer.ofField(User.class, "firstName"), Equals.to(constantFirstName)) + .and(ValuePointer.ofField(User.class, "username"), Equals.to(constantUsername)) + .and(ValuePointer.ofField(User.class, "fullInfo").field(UserFullInfo.class, "bio"), Equals.to(constantBio)); + long time1 = System.currentTimeMillis(); + ArrayList elements = root.usersList.query(query).asList(); + System.out.println("Time elapsed: " + (System.currentTimeMillis() - time1)); + System.out.println("Found " + elements.size() + " elements. First 5 items:"); + assertNotEquals(elements.size(), 0); + for (int i = 0; i < (elements.size() > 10 ? 10 : elements.size()); i++) { + System.out.println(elements.get(i)); + } + db.close(); + } + + @After + public void tearDown() throws Exception { + Files.deleteIfExists(path1); + Files.deleteIfExists(path2); + Files.deleteIfExists(path3); + } +} diff --git a/src/test/java/it/cavallium/strangedb/tests/User.java b/src/test/java/it/cavallium/strangedb/tests/User.java new file mode 100644 index 0000000..202001a --- /dev/null +++ b/src/test/java/it/cavallium/strangedb/tests/User.java @@ -0,0 +1,40 @@ +package it.cavallium.strangedb.tests; + +import it.cavallium.strangedb.java.annotations.DbDataType; +import it.cavallium.strangedb.java.annotations.DbField; +import it.cavallium.strangedb.java.database.IDatabaseTools; +import it.cavallium.strangedb.java.objects.EnhancedObject; + +import java.io.IOException; +import java.util.StringJoiner; + +public class User extends EnhancedObject { + + @DbField(id = 0, name = "firstName") + public String firstName; + + @DbField(id = 1, name = "username") + public String username; + + @DbField(id = 2, type = DbDataType.ENHANCED_OBJECT, name = "fullInfo") + public UserFullInfo fullInfo; + + public User() { + } + + public User(IDatabaseTools databaseTools, String firstName, String username, String bio) throws IOException { + super(databaseTools); + this.firstName = firstName; + this.username = username; + this.fullInfo = new UserFullInfo(databaseTools, bio); + } + + @Override + public String toString() { + return new StringJoiner(", ", User.class.getSimpleName() + "[", "]") + .add("firstName='" + firstName + "'") + .add("username='" + username + "'") + .add("fullInfo=" + fullInfo) + .toString(); + } +} diff --git a/src/test/java/it/cavallium/strangedb/tests/UserFullInfo.java b/src/test/java/it/cavallium/strangedb/tests/UserFullInfo.java new file mode 100644 index 0000000..d9fd2bf --- /dev/null +++ b/src/test/java/it/cavallium/strangedb/tests/UserFullInfo.java @@ -0,0 +1,31 @@ +package it.cavallium.strangedb.tests; + +import it.cavallium.strangedb.java.annotations.DbDataType; +import it.cavallium.strangedb.java.annotations.DbField; +import it.cavallium.strangedb.java.database.IDatabaseTools; +import it.cavallium.strangedb.java.objects.EnhancedObject; + +import java.io.IOException; +import java.util.StringJoiner; + +public class UserFullInfo extends EnhancedObject { + + @DbField(id = 0, name = "bio") + public String bio; + + public UserFullInfo() { + + } + + public UserFullInfo(IDatabaseTools databaseTools, String bio) throws IOException { + super(databaseTools); + this.bio = bio; + } + + @Override + public String toString() { + return new StringJoiner(", ", UserFullInfo.class.getSimpleName() + "[", "]") + .add("bio='" + bio + "'") + .toString(); + } +} diff --git a/src/test/java/it/cavallium/strangedb/utils/NTestUtils.java b/src/test/java/it/cavallium/strangedb/utils/NTestUtils.java index e79be44..f34246b 100644 --- a/src/test/java/it/cavallium/strangedb/utils/NTestUtils.java +++ b/src/test/java/it/cavallium/strangedb/utils/NTestUtils.java @@ -247,32 +247,38 @@ public class NTestUtils { super(databaseTools); } - @DbPropertyGetter(id = 0, type = DbDataType.OBJECT) + @DbProperty(id = 0, type = DbDataType.OBJECT) + @DbPropertyGetter public String get7() { return getProperty(); } - @DbPropertyGetter(id = 1, type = DbDataType.REFERENCES_LIST) + @DbProperty(id = 1, type = DbDataType.REFERENCES_LIST) + @DbPropertyGetter public LongArrayList get8() { return getProperty(); } - @DbPropertyGetter(id = 2, type = DbDataType.ENHANCED_OBJECT) + @DbProperty(id = 2, type = DbDataType.ENHANCED_OBJECT) + @DbPropertyGetter public NSimplestClass get9() { return getProperty(); } - @DbPropertySetter(id = 0, type = DbDataType.OBJECT) + @DbProperty(id = 0, type = DbDataType.OBJECT) + @DbPropertySetter public void set7(String val) { setProperty(val); } - @DbPropertySetter(id = 1, type = DbDataType.REFERENCES_LIST) + @DbProperty(id = 1, type = DbDataType.REFERENCES_LIST) + @DbPropertySetter public void set8(LongArrayList val) { setProperty(val); } - @DbPropertySetter(id = 2, type = DbDataType.ENHANCED_OBJECT) + @DbProperty(id = 2, type = DbDataType.ENHANCED_OBJECT) + @DbPropertySetter public void set9(NSimplestClass val) { setProperty(val); }