140 lines
4.5 KiB
Java
140 lines
4.5 KiB
Java
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 <T extends EnhancedObject> ValuePointer ofField(Class<T> parentType, String field) {
|
|
return base.field(parentType, field);
|
|
}
|
|
|
|
public static <T extends EnhancedObject> ValuePointer ofProp(Class<T> parentType, String property) {
|
|
return base.prop(parentType, property);
|
|
}
|
|
public static <T extends EnhancedObject> ValuePointer ofPrimitiveField(Class<T> parentType, String primitiveFieldName) {
|
|
return base.primitiveField(parentType, primitiveFieldName);
|
|
}
|
|
|
|
public <T extends EnhancedObject> ValuePointer prop(Class<T> 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 <T extends EnhancedObject> ValuePointer field(Class<T> 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 <T extends EnhancedObject> ValuePointer primitiveField(Class<T> 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> 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];
|
|
}
|
|
}
|