package it.cavallium.strangedb.database; import it.cavallium.strangedb.annotations.*; import org.apache.commons.lang3.reflect.FieldUtils; import it.cavallium.strangedb.EnhancedObject; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.LinkedHashMap; import java.util.Map; public class DatabaseDataInitializer implements IDataInitializer { private final DatabaseObjectsIO objectsIO; public DatabaseDataInitializer(DatabaseObjectsIO objectsIO) { this.objectsIO = objectsIO; } @Override public void initializeDbObject(EnhancedObject obj) throws IOException { initializeDbObjectFields(obj); initializeDbObjectPrimitiveFields(obj); initializeDbObjectProperties(obj); } private void initializeDbObjectFields(EnhancedObject obj) throws IOException { // Declare the variables needed to get the biggest field Id Field[] unorderedFields = objectsIO.getFields(obj); // Find the biggest field Id int biggestFieldId = objectsIO.getBiggestFieldId(unorderedFields); // Allocate new UIDs long[] fieldUIDs = objectsIO.allocateNewUIDs(biggestFieldId + 1); // Declare the other variables Field[] fields = new Field[biggestFieldId + 1]; DbDataType[] orderedFieldTypes = new DbDataType[biggestFieldId + 1]; // Load all fields metadata and load them for (Field field : unorderedFields) { DbField fieldAnnotation = field.getAnnotation(DbField.class); int fieldId = fieldAnnotation.id(); DbDataType fieldType = fieldAnnotation.type(); objectsIO.loadField(obj, field, fieldType, fieldUIDs[fieldId]); fields[fieldId] = field; orderedFieldTypes[fieldId] = fieldType; } // Set fields metadata obj.setFields(fields, orderedFieldTypes, fieldUIDs); } private void initializeDbObjectPrimitiveFields(EnhancedObject obj) throws IOException { // Declare the variables needed to get the biggest field Id Field[] unorderedFields = objectsIO.getPrimitiveFields(obj); // Find the biggest field Id int biggestFieldId = objectsIO.getBiggestPrimitiveFieldId(unorderedFields); // Allocate new UID long fieldDataUID = objectsIO.newNullObject(); // Declare the other variables Field[] fields = new Field[biggestFieldId + 1]; DbPrimitiveType[] orderedFieldTypes = new DbPrimitiveType[biggestFieldId + 1]; // Load all fields metadata and load them try { for (Field field : unorderedFields) { DbPrimitiveField fieldAnnotation = field.getAnnotation(DbPrimitiveField.class); int fieldId = fieldAnnotation.id(); DbPrimitiveType fieldType = fieldAnnotation.type(); switch (fieldType) { case BOOLEAN: FieldUtils.writeField(field, obj, false, true); break; case BYTE: FieldUtils.writeField(field, obj, (byte) 0, true); break; case CHAR: FieldUtils.writeField(field, obj, (char) 0, true); break; case SHORT: FieldUtils.writeField(field, obj, (short) 0, true); break; case INTEGER: FieldUtils.writeField(field, obj, 0, true); break; case LONG: FieldUtils.writeField(field, obj, (long) 0, true); break; case FLOAT: FieldUtils.writeField(field, obj, (float) 0, true); break; case DOUBLE: FieldUtils.writeField(field, obj, (double) 0, true); break; } fields[fieldId] = field; orderedFieldTypes[fieldId] = fieldType; } } catch (IllegalArgumentException | IllegalAccessException e) { throw new IOException(e); } // Set fields metadata obj.setPrimitiveFields(fields, orderedFieldTypes, fieldDataUID); } private void initializeDbObjectProperties(EnhancedObject obj) throws IOException { // Declare the variables needed to get the biggest property Id Method[] unorderedPropertyGetters = obj.getPropertyGetters(); Method[] unorderedPropertySetters = obj.getPropertySetters(); // Find the biggest property Id int biggestGetter = objectsIO.getBiggestPropertyGetterId(unorderedPropertyGetters); int biggestSetter = objectsIO.getBiggestPropertySetterId(unorderedPropertySetters); int biggestPropertyId = biggestGetter > biggestSetter ? biggestGetter : biggestSetter; // Allocate new UIDs long[] propertyUIDs = objectsIO.allocateNewUIDs(biggestPropertyId + 1); for (Method property : unorderedPropertySetters) { DbPropertySetter fieldAnnotation = property.getAnnotation(DbPropertySetter.class); int propertyId = fieldAnnotation.id(); if (propertyId > biggestPropertyId) { biggestPropertyId = propertyId; } } // Declare the other variables 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<>(); // Load the properties metadata for (Method property : unorderedPropertyGetters) { DbPropertyGetter propertyAnnotation = property.getAnnotation(DbPropertyGetter.class); int propertyId = propertyAnnotation.id(); DbDataType propertyType = propertyAnnotation.type(); propertyTypes[propertyId] = propertyType; propertyGetters[propertyId] = property; getterMethods.put(property.getName(), propertyAnnotation); } for (Method property : unorderedPropertySetters) { DbPropertySetter propertyAnnotation = property.getAnnotation(DbPropertySetter.class); int propertyId = propertyAnnotation.id(); DbDataType propertyType = propertyAnnotation.type(); propertyTypes[propertyId] = propertyType; propertySetters[propertyId] = property; setterMethods.put(property.getName(), propertyAnnotation); } // Set properties metadata obj.setProperties(propertyGetters, propertySetters, propertyTypes, propertyUIDs, setterMethods, getterMethods); } }