Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 52 additions & 27 deletions src/main/java/org/javawebstack/orm/TableInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class TableInfo {
private final Class<? extends Model> modelClass;
private String primaryKey;
private final List<String> uniqueKeys = new ArrayList<>();
private final Constructor<?> constructor;
private Constructor<?> constructor;
private String relationField;
private final Map<String, String> filterable = new HashMap<>();
private final List<String> searchable = new ArrayList<>();
Expand All @@ -42,6 +42,36 @@ public class TableInfo {
public TableInfo(Class<? extends Model> model, ORMConfig config) throws ORMConfigurationException {
this.config = config;
this.modelClass = model;

Stack<Class<?>> superClasses = Helper.getSuperClassesTill(model, Model.class);
while (!superClasses.isEmpty()) {
Class<? extends Model> superClass = (Class<? extends Model>) superClasses.pop();
if (Modifier.isAbstract(superClass.getModifiers())) {
analyzeColumns(superClass);
} else {
throw new ORMConfigurationException("The parent model has to be abstract!");
}
}

constructInfo(model);
}

private void constructInfo (Class<? extends Model> model) throws ORMConfigurationException {
Comment thread
x7airworker marked this conversation as resolved.
analyzeTable(model);
analyzeColumns(model);

if (!fields.containsKey(idField))
idField = "uuid";
if (!fields.containsKey(idField))
throw new ORMConfigurationException("No id field found!");

if (config.isIdPrimaryKey()) {
if (primaryKey == null)
primaryKey = idField;
}
}

private void analyzeTable(Class<? extends Model> model) throws ORMConfigurationException {
if (model.isAnnotationPresent(Table.class)) {
Table table = model.getDeclaredAnnotationsByType(Table.class)[0];
tableName = table.value();
Expand All @@ -59,6 +89,26 @@ public TableInfo(Class<? extends Model> model, ORMConfig config) throws ORMConfi
} catch (NoSuchMethodException e) {
throw new ORMConfigurationException("The model class has no empty constructor!");
}
if (model.isAnnotationPresent(RelationField.class)) {
relationField = model.getDeclaredAnnotationsByType(RelationField.class)[0].value();
} else {
relationField = Helper.pascalToCamelCase(model.getSimpleName()) + ((getIdType().equals(UUID.class) && !idField.equalsIgnoreCase("id")) ? "UUID" : "Id");
}
if (model.isAnnotationPresent(SoftDelete.class)) {
softDelete = model.getDeclaredAnnotationsByType(SoftDelete.class)[0];
if (!fields.containsKey(softDelete.value()))
throw new ORMConfigurationException("Missing soft-delete field '" + softDelete.value() + "'");
}
if (model.isAnnotationPresent(Dates.class)) {
dates = model.getDeclaredAnnotationsByType(Dates.class)[0];
if (!fields.containsKey(dates.create()))
throw new ORMConfigurationException("Missing dates field '" + dates.create() + "'");
if (!fields.containsKey(dates.update()))
throw new ORMConfigurationException("Missing dates field '" + dates.update() + "'");
}
}

private void analyzeColumns(Class<? extends Model> model) throws ORMConfigurationException {
for (Field field : model.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers()))
continue;
Expand All @@ -82,7 +132,7 @@ public TableInfo(Class<? extends Model> model, ORMConfig config) throws ORMConfi
else
fieldSize = fieldConfig.size();

SQLType sqlType = config.getType(field.getType(), fieldSize);
SQLType sqlType = config.getType(field.getType(), fieldSize);
if (sqlType != null) {
sqlTypes.put(fieldName, sqlType);
sqlTypeParameters.put(fieldName, config.getTypeParameters(field.getType(), fieldSize));
Expand All @@ -106,31 +156,6 @@ public TableInfo(Class<? extends Model> model, ORMConfig config) throws ORMConfi
if (field.isAnnotationPresent(Searchable.class))
this.searchable.add(fieldName);
}
if (!fields.containsKey(idField))
idField = "uuid";
if (!fields.containsKey(idField))
throw new ORMConfigurationException("No id field found!");
if (model.isAnnotationPresent(RelationField.class)) {
relationField = model.getDeclaredAnnotationsByType(RelationField.class)[0].value();
} else {
relationField = Helper.pascalToCamelCase(model.getSimpleName()) + ((getIdType().equals(UUID.class) && !idField.equalsIgnoreCase("id")) ? "UUID" : "Id");
}
if (config.isIdPrimaryKey()) {
if (primaryKey == null)
primaryKey = idField;
}
if (model.isAnnotationPresent(SoftDelete.class)) {
softDelete = model.getDeclaredAnnotationsByType(SoftDelete.class)[0];
if (!fields.containsKey(softDelete.value()))
throw new ORMConfigurationException("Missing soft-delete field '" + softDelete.value() + "'");
}
if (model.isAnnotationPresent(Dates.class)) {
dates = model.getDeclaredAnnotationsByType(Dates.class)[0];
if (!fields.containsKey(dates.create()))
throw new ORMConfigurationException("Missing dates field '" + dates.create() + "'");
if (!fields.containsKey(dates.update()))
throw new ORMConfigurationException("Missing dates field '" + dates.update() + "'");
}
}

public boolean isSoftDelete() {
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/org/javawebstack/orm/util/Helper.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.javawebstack.orm.util;

import java.util.Stack;

public class Helper {

public static String toSnakeCase(String source) {
Expand Down Expand Up @@ -41,4 +43,15 @@ public static String toCamelCase(String source) {
return sb.toString();
}

public static Stack<Class<?>> getSuperClassesTill(Class<?> clazz, Class<?> target) {
Stack<Class<?>> stack = new Stack<>();
Class<?> superClass = clazz.getSuperclass();

while (superClass != null && superClass != target) {
stack.push(superClass);
superClass = superClass.getSuperclass();
}

return stack;
}
}
68 changes: 68 additions & 0 deletions src/test/java/org/javawebstack/orm/test/TableInfoTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package org.javawebstack.orm.test;

import org.javawebstack.orm.Model;
import org.javawebstack.orm.ORM;
import org.javawebstack.orm.ORMConfig;
import org.javawebstack.orm.Repo;
import org.javawebstack.orm.annotation.Column;
import org.javawebstack.orm.exception.ORMConfigurationException;
import org.javawebstack.orm.util.KeyType;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

public class TableInfoTest extends ORMTestCase {
@Test
public void testParentTableInfo () throws ORMConfigurationException {
ORMConfig config = new ORMConfig()
.setDefaultSize(255);
ORM.register(Child.class, sql(), config);

assertEquals(Repo.get(Child.class).getInfo().getFields().size(), 2);
}

@Test
public void testParentTableMigration () throws ORMConfigurationException {
ORMConfig config = new ORMConfig()
.setDefaultSize(255);
ORM.register(Child.class, sql(), config);
ORM.autoMigrate(true);

Child child = new Child();
child.id = 1337;
child.content = "Hello World!";
child.save();

Child fetchedChild = Repo.get(Child.class).get(1337);
assertEquals(fetchedChild.id, child.id);
assertEquals(fetchedChild.content, child.content);
}

@Test
public void testNonAbstractParent () throws ORMConfigurationException {
ORMConfig config = new ORMConfig()
.setDefaultSize(255);

assertThrows(ORMConfigurationException.class, () -> ORM.register(SecondChild.class, sql(), config), "The parent model has to be abstract!");
}

public static abstract class Parent extends Model {
@Column(ai = true, key = KeyType.PRIMARY)
public int id;
}

public static class Child extends Parent {
@Column
public String content;
}

public static class NonAbstractParent extends Model {
@Column(ai = true, key = KeyType.PRIMARY)
public int id;
}

public static class SecondChild extends NonAbstractParent {
@Column
public String content;
}
}