diff --git a/src/main/java/jef/expressions/selectable/DatabaseFunctionExpression.java b/src/main/java/jef/expressions/selectable/DatabaseFunctionExpression.java index b38cc38..64f5fc4 100644 --- a/src/main/java/jef/expressions/selectable/DatabaseFunctionExpression.java +++ b/src/main/java/jef/expressions/selectable/DatabaseFunctionExpression.java @@ -4,6 +4,7 @@ import jef.expressions.Expression; public class DatabaseFunctionExpression implements Expression, SelectableExpression { private final String function; + public DatabaseFunctionExpression(String function) { this.function = function; } diff --git a/src/main/java/jef/model/DbEntity.java b/src/main/java/jef/model/DbEntity.java index ae041a1..56b442c 100644 --- a/src/main/java/jef/model/DbEntity.java +++ b/src/main/java/jef/model/DbEntity.java @@ -31,11 +31,11 @@ public class DbEntity { private final List keys = new ArrayList<>(); private final List indexes = new ArrayList<>(); - public DbEntity(Class type) { + DbEntity(Class type) { this(type, new ArrayList<>()); } - public DbEntity(Class type, List> fields) { + DbEntity(Class type, List> fields) { this.type = type; this.fields = fields; this.name = type.getSimpleName(); @@ -93,7 +93,7 @@ public class DbEntity { } } - public DbField getOrAddField(DbField field) { + public DbField addIfAbsent(DbField field) { try { var prop = (DbField) fields.stream().filter(e -> e.getName().equals(field.getName())).findFirst().orElse(null); if (prop == null) { @@ -120,18 +120,34 @@ public class DbEntity { } public void addForeignKey(ForeignKeyConstraint foreignKey) { - foreignKeys.add(foreignKey); + if (!foreignKeys.contains(foreignKey)) { + foreignKeys.add(foreignKey); + } } public void addUniqueContstraint(UniqueConstraint uniqueConstraint) { - uniqueKeys.add(uniqueConstraint); + if (!uniqueKeys.contains(uniqueConstraint)) { + uniqueKeys.add(uniqueConstraint); + } } public void addIndex(IndexConstraint index) { - indexes.add(index); + if (!indexes.contains(index)) { + indexes.add(index); + } } public void addKey(KeyConstraint key) { - keys.add(key); + if (!keys.contains(key)) { + keys.add(key); + } + } + + @Override + public String toString() { + return "DbEntity{" + + "type=" + type + + ", name='" + name + '\'' + + '}'; } } diff --git a/src/main/java/jef/model/DbField.java b/src/main/java/jef/model/DbField.java index 3e59f88..4b58eac 100644 --- a/src/main/java/jef/model/DbField.java +++ b/src/main/java/jef/model/DbField.java @@ -9,6 +9,7 @@ import lombok.Setter; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Collection; import java.util.List; @Getter @@ -17,21 +18,27 @@ public class DbField { private final DbEntity entity; private final Class type; private final Field field; + private boolean isModelField; + private boolean isDatabaseField; + private DbField foreignKeyModelLink; private String name; private boolean notNull = false; - public DbField(DbEntity entity, Class type, Field field) { - this.entity = entity; - this.type = type; - this.field = field; - this.name = field.getName(); + DbField(DbEntity entity, Class type, Field field) { + this(entity, type, field, field.getName()); } - public DbField(DbEntity entity, Class type, Field field, String name) { + DbField(DbEntity entity, Class type, Field field, String name) { this.entity = entity; this.type = type; this.field = field; this.name = name; + this.isModelField = field != null; + this.isDatabaseField = !Collection.class.isAssignableFrom(type) && !SerializableObject.class.isAssignableFrom(type); + } + + public boolean isForeignKey() { + return entity.getForeignKeys().stream().anyMatch(u -> u.getFields().size() == 1 && u.getFields().get(0) == this); } public boolean isUnique() { @@ -72,4 +79,13 @@ public class DbField { entity.getKeys().remove(constr.get()); } //else do nothing } + + @Override + public String toString() { + return "DbField{" + + "name=" + name + + ", type=" + type.getSimpleName() + (notNull ? "" : "?") + + ", entity=" + entity + + '}'; + } } diff --git a/src/main/java/jef/model/EntityInitializer.java b/src/main/java/jef/model/EntityInitializer.java new file mode 100644 index 0000000..97c471e --- /dev/null +++ b/src/main/java/jef/model/EntityInitializer.java @@ -0,0 +1,62 @@ +package jef.model; + +import jef.DbSet; +import jef.model.annotations.Clazz; +import jef.model.annotations.Transient; +import jef.serializable.SerializableObject; + +import java.lang.reflect.Field; +import java.util.Collection; + +class EntityInitializer { + static void initEntities(ModelBuilder mb, Class context) { + for (Field ctxfield : context.getDeclaredFields()) { + if (!DbSet.class.isAssignableFrom(ctxfield.getType())) { + continue; + } + Clazz clazzAnnotation = ctxfield.getAnnotation(Clazz.class); + if (clazzAnnotation == null) { + throw new ModelException("DbSet " + ctxfield.getName() + " is missing the " + Clazz.class.getSimpleName() + " annotation"); + } + var dbsetClazz = (Class) clazzAnnotation.clazz(); + initEntity(mb, dbsetClazz); + } + } + + static void initEntity(ModelBuilder mb, Class clazz) { + var entity = mb.getOrCreateEntity(clazz); + + var fields = ReflectionUtil.getFieldsRecursive(clazz); + for (var f : fields) { + if (f.getAnnotationsByType(Transient.class).length > 0) { + continue; + } + if (Collection.class.isAssignableFrom(f.getType())) { + //find a Collection field with the same Model + //e.g. class Entity { @Clazz(Entity2.class) List ent; @Clazz(Entity2.class) Set ent2; } + var clazzAnnotation = f.getAnnotationsByType(Clazz.class); + if (clazzAnnotation.length == 0) { + throw new ModelException("Field " + f.getClass().getSimpleName() + "::" + f.getName() + " is missing the " + Clazz.class.getSimpleName() + " annotation"); + } + var fClazz = clazzAnnotation[0].clazz(); + var foundCollection = entity.getFields().stream() + .filter(e -> Collection.class.isAssignableFrom(e.getType()) + && e.isModelField() + && e.getField().getAnnotationsByType(Clazz.class).length > 0 + && e.getField().getAnnotationsByType(Clazz.class)[0].clazz() == fClazz) + .findFirst(); + if (foundCollection.isPresent()) { + throw new ModelException("Model " + entity.getType().getSimpleName() + " multiple contains a 1 to N relation with type " + fClazz.getSimpleName()); + } + entity.getOrCreateField(f); + } else if (SerializableObject.class.isAssignableFrom(f.getType())) { + entity.getOrCreateField(f); + } else { + var dbField = entity.getOrCreateField(f); + if (f.getType().isPrimitive()) { + dbField.setNotNull(true); + } + } + } + } +} diff --git a/src/main/java/jef/model/ForeignKeyInitializer.java b/src/main/java/jef/model/ForeignKeyInitializer.java new file mode 100644 index 0000000..00a4376 --- /dev/null +++ b/src/main/java/jef/model/ForeignKeyInitializer.java @@ -0,0 +1,153 @@ +package jef.model; + +import jef.model.annotations.Clazz; +import jef.model.annotations.ForeignKey; +import jef.model.annotations.Transient; +import jef.model.constraints.ForeignKeyConstraint; +import jef.serializable.SerializableObject; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Collection; +import java.util.List; +import java.util.Locale; + +class ForeignKeyInitializer { + static void initForeignKeys(ModelBuilder mb) { + for (int i = 0; i < mb.getEntities().size(); i++) { + var entity = mb.getEntities().get(i); + initForeignKeys(mb, entity); + } + } + + static void initForeignKeys(ModelBuilder mb, DbEntity entity) { + var fields = ReflectionUtil.getFieldsRecursive(entity.getType()); + for (var f : fields) { + if (f.getAnnotationsByType(Transient.class).length > 0) { + continue; + } + if (Collection.class.isAssignableFrom(f.getType())) { + Clazz clazzAnnotation = f.getAnnotation(Clazz.class); + if (clazzAnnotation == null) { + throw new ModelException("Collection " + entity.getType().getSimpleName() + "." + f.getName() + " is missing the " + Clazz.class.getSimpleName() + " annotation"); + } + var otherEntity = mb.getEntity((Class) clazzAnnotation.clazz()); + if (otherEntity == null) { + EntityInitializer.initEntity(mb, (Class) clazzAnnotation.clazz()); + otherEntity = mb.getEntity((Class) clazzAnnotation.clazz()); + PrimaryKeyInitializer.initPrimaryKeys(mb, otherEntity); + } + var primary = entity.getPrimaryKey(); + if (primary == null) { + throw new ModelException("Entity " + entity.getType().getSimpleName() + " is missing a primary key and therefore cannot be referenced by " + otherEntity.getType().getSimpleName()); + } + var otherEntityF = otherEntity; + var otherFields = primary.getFields().stream() + .map(e -> { + //find list in other entity (N to N relation) + if (otherEntityF != entity) { //ignore on recursive models + var otherEntityListField = otherEntityF.getFields().stream() + .filter(oef -> Collection.class.isAssignableFrom(oef.getType()) + && oef.getField().getAnnotationsByType(Clazz.class).length > 0 + && oef.getField().getAnnotationsByType(Clazz.class)[0].clazz() == entity.getType()).findFirst(); + if (otherEntityListField.isPresent()) { + throw new ModelException("N to N relations need to explicitly defined via a mapping model (" + + otherEntityF.getType().getSimpleName() + "::" + otherEntityListField.get().getType().getName() + " and " + + entity.getType().getSimpleName() + "::" + f.getType().getName() + ")"); + } + } + + //find object in other entity (1 to N relation) + var otherEntityObjectField = otherEntityF.getFields().stream().filter(oef -> oef.getType() == entity.getType()).findFirst(); + if (otherEntityObjectField.isPresent()) { + return new FieldSearchResult(otherEntityObjectField.get(), false); + } + + //find objectId in other entity (1 to N relation) +// var idFieldName = entity.getType().getSimpleName().substring(0, 1).toLowerCase(Locale.ROOT) +// + entity.getType().getSimpleName().substring(1) +// + e.getName().substring(0, 1).toUpperCase(Locale.ROOT) +// + e.getName().substring(1); + var idFieldName = f.getName() + + e.getName().substring(0, 1).toUpperCase(Locale.ROOT) + + e.getName().substring(1); + var otherEntityIdField = otherEntityF.getFields().stream().filter(oef -> oef.getName().equals(idFieldName)).findFirst(); + if (otherEntityIdField.isPresent()) { + return new FieldSearchResult(otherEntityIdField.get(), otherEntityIdField.get().getField().getAnnotationsByType(ForeignKey.class).length == 0); + } + + var field = new DbField<>(otherEntityF, e.getType(), null, idFieldName); + field = otherEntityF.addIfAbsent(field); + return new FieldSearchResult(field, true); + }) + .toList(); + if (otherFields.stream().anyMatch(FieldSearchResult::isCreateForeignKey)) { + otherEntity.addForeignKey(new ForeignKeyConstraint(otherEntity, (List) otherFields.stream().map(FieldSearchResult::getField).toList(), + entity, primary.getFields(), ForeignKeyConstraint.Action.RESTRICT, ForeignKeyConstraint.Action.CASCADE)); + } + } else if (SerializableObject.class.isAssignableFrom(f.getType())) { + var otherEntity = mb.getEntity((Class) f.getType()); + if (otherEntity == null) { + EntityInitializer.initEntity(mb, (Class) f.getType()); + otherEntity = mb.getEntity((Class) f.getType()); + PrimaryKeyInitializer.initPrimaryKeys(mb, otherEntity); + } + var primary = otherEntity.getPrimaryKey(); + if (primary == null) { + throw new ModelException("Entity " + otherEntity.getType().getSimpleName() + " is missing a primary key and therefore cannot be referenced by " + entity.getType().getSimpleName()); + } + var otherEntityF = otherEntity; + var otherFields = primary.getFields().stream() + .map(otherPrimaryField -> { + //find list in other entity (N to 1 relation) + var entityListField = entity.getFields().stream() + .filter(oef -> Collection.class.isAssignableFrom(oef.getType()) + && oef.getField().getAnnotationsByType(Clazz.class).length > 0 + && oef.getField().getAnnotationsByType(Clazz.class)[0].clazz() == otherEntityF.getType()).toList(); +// if (entityListField.size() == 1) { +// return new FieldSearchResult(entityListField.get(0), true); +// } + + //find object in other entity (1 to 1 relation) + var entityObjectFields = entity.getFields().stream().filter(oef -> oef.getType() == otherEntityF.getType()).toList(); +// if (entityObjectField.isPresent()) { +// return new FieldSearchResult(entityObjectField.get(), false); +// } + + //find objectId in other entity (1 to 1 relation) + var idFieldName = f.getName() + + otherPrimaryField.getName().substring(0, 1).toUpperCase(Locale.ROOT) + + otherPrimaryField.getName().substring(1); + var entityIdField = entity.getFields().stream().filter(oef -> oef.getName().equals(idFieldName)).findFirst(); + if (entityIdField.isPresent()) { + return new FieldSearchResult(entityIdField.get(), entityIdField.get().getField().getAnnotationsByType(ForeignKey.class).length == 0); + } + + var field = new DbField<>(entity, otherPrimaryField.getType(), null, idFieldName); + field = entity.addIfAbsent(field); + if (entityListField.size() == 1) { + field.setForeignKeyModelLink(entityListField.get(0)); + entityListField.get(0).setForeignKeyModelLink(field); + } else if (entityObjectFields.size() == 1) { + field.setForeignKeyModelLink(entityObjectFields.get(0)); + entityObjectFields.get(0).setForeignKeyModelLink(field); + } + return new FieldSearchResult(field, true); +// return new DbField<>(entity, e.getType(), null, f.getName() + e.getName().substring(0, 1).toUpperCase(Locale.ROOT) + e.getName().substring(1)) + }) + .toList(); + if (otherFields.stream().anyMatch(FieldSearchResult::isCreateForeignKey)) { + entity.addForeignKey(new ForeignKeyConstraint(entity, (List) otherFields.stream().map(FieldSearchResult::getField).toList(), + otherEntity, primary.getFields(), ForeignKeyConstraint.Action.RESTRICT, ForeignKeyConstraint.Action.CASCADE)); + } + } + } + } + + @AllArgsConstructor + @Getter + private static class FieldSearchResult { + private final DbField field; + private final boolean createForeignKey; + } +} diff --git a/src/main/java/jef/model/ModelBuilder.java b/src/main/java/jef/model/ModelBuilder.java index 6c24415..98d77f5 100644 --- a/src/main/java/jef/model/ModelBuilder.java +++ b/src/main/java/jef/model/ModelBuilder.java @@ -1,24 +1,16 @@ package jef.model; -import jef.DbSet; -import jef.model.annotations.Clazz; -import jef.model.annotations.Id; -import jef.model.annotations.Transient; import jef.model.annotations.processors.AnnotationProcessor; +import jef.model.annotations.processors.ForeignKeyProcessor; import jef.model.annotations.processors.IndexProcessor; import jef.model.annotations.processors.KeyProcessor; import jef.model.annotations.processors.NotNullProcessor; import jef.model.annotations.processors.UniqueProcessor; -import jef.model.constraints.ForeignKeyConstraint; -import jef.model.constraints.PrimaryKeyConstraint; import jef.serializable.SerializableObject; -import java.lang.reflect.Field; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Locale; public class ModelBuilder { private static final List annotationProcessors = new ArrayList<>(); @@ -28,6 +20,7 @@ public class ModelBuilder { annotationProcessors.add(UniqueProcessor.INSTANCE); annotationProcessors.add(IndexProcessor.INSTANCE); annotationProcessors.add(KeyProcessor.INSTANCE); + annotationProcessors.add(ForeignKeyProcessor.INSTANCE); } public static ModelBuilder from(Class context) { @@ -40,9 +33,9 @@ public class ModelBuilder { private static ModelBuilder from0(Class context) throws Exception { var mb = new ModelBuilder(new ArrayList<>()); - initEntities(mb, context); - addPrimaryKeys(mb); - addForeignKeys(mb); + EntityInitializer.initEntities(mb, context); + PrimaryKeyInitializer.initPrimaryKeys(mb); + ForeignKeyInitializer.initForeignKeys(mb); for (AnnotationProcessor processor : annotationProcessors) { processor.apply(mb); @@ -50,128 +43,6 @@ public class ModelBuilder { return mb; } - private static void initEntities(ModelBuilder mb, Class context) { - for (Field ctxfield : context.getDeclaredFields()) { - if (!DbSet.class.isAssignableFrom(ctxfield.getType())) { - continue; - } - Clazz clazzAnnotation = ctxfield.getAnnotation(Clazz.class); - if (clazzAnnotation == null) { - throw new ModelException("DbSet " + ctxfield.getName() + " is missing the " + Clazz.class.getSimpleName() + " annotation"); - } - var dbsetClazz = (Class) clazzAnnotation.clazz(); - initEntity(mb, dbsetClazz); - } - } - - private static void initEntity(ModelBuilder mb, Class clazz) { - var entity = mb.getOrCreateEntity(clazz); - - var fields = ReflectionUtil.getFieldsRecursive(clazz); - for (var f : fields) { - if (f.getAnnotationsByType(Transient.class).length > 0) { - continue; - } - if (Collection.class.isAssignableFrom(f.getType())) { - } else { - var dbField = entity.getOrCreateField(f); - if (f.getType().isPrimitive()) { - dbField.setNotNull(true); - } - } - } - } - - private static void addPrimaryKeys(ModelBuilder mb) { - for (int i = 0; i < mb.getEntities().size(); i++) { - var entity = mb.getEntities().get(i); - addPrimaryKeys(mb, entity); - } - } - - private static void addPrimaryKeys(ModelBuilder mb, DbEntity entity) { - var fields = ReflectionUtil.getFieldsRecursive(entity.getType()); - var idFields = new ArrayList(); - - //search for fields wuth @Id annotation - for (var f : fields) { - if (f.getAnnotationsByType(Transient.class).length > 0) { - continue; - } - if (!f.getType().isPrimitive()) { - continue; - } - if (f.getAnnotationsByType(Id.class).length == 0) { - continue; - } - - //fields in same class check - if (idFields.size() == 0 || idFields.get(0).getDeclaringClass() == f.getDeclaringClass()) { - idFields.add(f); - } else { - break; - } - } - - if (idFields.isEmpty()) { - for (var f : fields) { - if (f.getAnnotationsByType(Transient.class).length > 0) { - continue; - } - if (!f.getType().isPrimitive()) { - continue; - } - if (f.getName().equals("id")) { - idFields.add(f); - break; - } - } - } - - if (!idFields.isEmpty()) { - var dbfields = idFields.stream().map(entity::getField).toList(); - entity.setPrimaryKey(new PrimaryKeyConstraint(entity, (List) dbfields)); - } - } - - private static void addForeignKeys(ModelBuilder mb) { - for (int i = 0; i < mb.getEntities().size(); i++) { - var entity = mb.getEntities().get(i); - addForeignKeys(mb, entity); - } - } - - private static void addForeignKeys(ModelBuilder mb, DbEntity entity) { - var fields = ReflectionUtil.getFieldsRecursive(entity.getType()); - for (var f : fields) { - if (f.getAnnotationsByType(Transient.class).length > 0) { - continue; - } - if (Collection.class.isAssignableFrom(f.getType())) { - Clazz clazzAnnotation = f.getAnnotation(Clazz.class); - if (clazzAnnotation == null) { - throw new ModelException("Collection " + entity.getType().getSimpleName() + "." + f.getName() + " is missing the " + Clazz.class.getSimpleName() + " annotation"); - } - var refEntity = mb.getEntity((Class) clazzAnnotation.clazz()); - if (refEntity == null) { - initEntity(mb, (Class) clazzAnnotation.clazz()); - refEntity = mb.getEntity((Class) clazzAnnotation.clazz()); - addPrimaryKeys(mb, refEntity); - } - var primary = refEntity.getPrimaryKey(); - if (primary == null) { - throw new ModelException("Entity " + refEntity.getType().getSimpleName() + " is missing a primary key and therefore cannot be referenced by " + entity.getType().getSimpleName()); - } - var refFields = primary.getFields().stream() - .map(e -> new DbField<>(entity, e.getType(), null, f.getName() + e.getName().substring(0, 1).toUpperCase(Locale.ROOT) + e.getName().substring(1))) - .map(entity::getOrAddField) - .toList(); - entity.addForeignKey(new ForeignKeyConstraint(entity, (List) refFields, refEntity, primary.getFields())); - } - } - } - - private final List> entities; public ModelBuilder(List> entities) { diff --git a/src/main/java/jef/model/PrimaryKeyInitializer.java b/src/main/java/jef/model/PrimaryKeyInitializer.java new file mode 100644 index 0000000..ad2c391 --- /dev/null +++ b/src/main/java/jef/model/PrimaryKeyInitializer.java @@ -0,0 +1,63 @@ +package jef.model; + +import jef.model.annotations.Id; +import jef.model.annotations.Transient; +import jef.model.constraints.PrimaryKeyConstraint; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +class PrimaryKeyInitializer { + static void initPrimaryKeys(ModelBuilder mb) { + for (int i = 0; i < mb.getEntities().size(); i++) { + var entity = mb.getEntities().get(i); + initPrimaryKeys(mb, entity); + } + } + + static void initPrimaryKeys(ModelBuilder mb, DbEntity entity) { + var fields = ReflectionUtil.getFieldsRecursive(entity.getType()); + var idFields = new ArrayList(); + + //search for fields with @Id annotation + for (var f : fields) { + if (f.getAnnotationsByType(Transient.class).length > 0) { + continue; + } + if (!f.getType().isPrimitive()) { + continue; + } + if (f.getAnnotationsByType(Id.class).length == 0) { + continue; + } + + //fields in same class check + if (idFields.size() == 0 || idFields.get(0).getDeclaringClass() == f.getDeclaringClass()) { + idFields.add(f); + } else { + break; + } + } + + if (idFields.isEmpty()) { + for (var f : fields) { + if (f.getAnnotationsByType(Transient.class).length > 0) { + continue; + } + if (!f.getType().isPrimitive()) { + continue; + } + if (f.getName().equals("id")) { + idFields.add(f); + break; + } + } + } + + if (!idFields.isEmpty()) { + var dbfields = idFields.stream().map(entity::getField).toList(); + entity.setPrimaryKey(new PrimaryKeyConstraint(entity, (List) dbfields)); + } + } +} diff --git a/src/main/java/jef/model/annotations/ForeignKey.java b/src/main/java/jef/model/annotations/ForeignKey.java new file mode 100644 index 0000000..4378955 --- /dev/null +++ b/src/main/java/jef/model/annotations/ForeignKey.java @@ -0,0 +1,23 @@ +package jef.model.annotations; + +import jef.model.constraints.ForeignKeyConstraint; +import jef.serializable.SerializableObject; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Documented +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ForeignKey { + String getterOrField(); + + Class entity() default SerializableObject.class; + + ForeignKeyConstraint.Action onUpdate() default ForeignKeyConstraint.Action.RESTRICT; + + ForeignKeyConstraint.Action onDelete() default ForeignKeyConstraint.Action.CASCADE; +} diff --git a/src/main/java/jef/model/annotations/processors/ForeignKeyProcessor.java b/src/main/java/jef/model/annotations/processors/ForeignKeyProcessor.java new file mode 100644 index 0000000..ea2a67c --- /dev/null +++ b/src/main/java/jef/model/annotations/processors/ForeignKeyProcessor.java @@ -0,0 +1,99 @@ +package jef.model.annotations.processors; + +import jef.model.DbEntity; +import jef.model.DbField; +import jef.model.ModelBuilder; +import jef.model.ModelException; +import jef.model.annotations.ForeignKey; +import jef.model.constraints.ForeignKeyConstraint; +import jef.serializable.SerializableObject; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class ForeignKeyProcessor implements AnnotationProcessor { + public static final ForeignKeyProcessor INSTANCE = new ForeignKeyProcessor(); + + @Override + public void apply(ModelBuilder mb) { + for (DbEntity entity : mb.getEntities()) { + //annotation on fields + for (DbField field : entity.getFields()) { + if (field.isModelField() && field.getField().getAnnotationsByType(ForeignKey.class).length > 0) { + var anno = field.getField().getAnnotationsByType(ForeignKey.class)[0]; +// var dbfield = entity.getField(field.getField()); +// if (dbfield == null) { +// throw new ModelException("DbField with field " + field.getName() + " not found in " + entity.getType().getSimpleName()); +// } + var exposeForeignKey = anno.entity() == SerializableObject.class; + var refEntity = exposeForeignKey ? entity : mb.getEntity(anno.entity()); + if (!exposeForeignKey && refEntity == null) { + throw new ModelException("Could not find referenced entity " + anno.entity().getSimpleName() + " (via @" + ForeignKey.class.getSimpleName() + + " in " + entity.getType().getSimpleName() + "::" + field.getField().getName() + ")"); + } + Field refClassField; + try { + refClassField = getField(refEntity, anno.getterOrField()); + } catch (ModelException e) { + throw new ModelException(e.getMessage() + " (via @" + ForeignKey.class.getSimpleName() + + " in " + entity.getType().getSimpleName() + "::" + field.getField().getName() + ")"); + } + var refField = refEntity.getField(refClassField); + + if (exposeForeignKey) { + field.setForeignKeyModelLink(refField); + refField.setForeignKeyModelLink(field); + continue; + } + + //check for primary key + if (refEntity.getPrimaryKey() == null) { + throw new ModelException("Entity " + refEntity.getType().getSimpleName() + " does not have a primary key and can " + + "therefore not be referenced (via @" + ForeignKey.class.getSimpleName() + + " in " + entity.getType().getSimpleName() + "::" + field.getField().getName() + ")"); + } + + //check if references field is the primary key of the refeneced entity + if (!refEntity.getPrimaryKey().getFields().equals(List.of(refField))) { + throw new ModelException(refEntity.getType().getSimpleName() + "::" + refField.getField().getName() + + " is not equal to the primary key of entity " + refEntity.getType().getSimpleName() + + " (" + refEntity.getPrimaryKey().getFields().stream().map(e -> e.getField().getName()).collect(Collectors.joining(", ")) + ")" + + " and can therefore not be referenced (via @" + ForeignKey.class.getSimpleName() + + " in " + entity.getType().getSimpleName() + "::" + field.getField().getName() + ")"); + } + entity.addForeignKey(new ForeignKeyConstraint(entity, List.of(field), refEntity, List.of(refField), anno.onUpdate(), anno.onDelete())); + } + } + } + } + + private Field getField(DbEntity entity, String fieldOrGetter) { + Method getter = null; + try { + getter = entity.getType().getDeclaredMethod(fieldOrGetter); + } catch (NoSuchMethodException e) { + } + + Field field = null; + try { + if (getter != null && getter.getName().length() > 3 && getter.getName().startsWith("get")) { + var name = getter.getName().substring(3, 4).toLowerCase(Locale.ROOT) + getter.getName().substring(4); //HACK + field = entity.getType().getDeclaredField(name); + } else { + field = entity.getType().getDeclaredField(fieldOrGetter); + } + } catch (NoSuchFieldException e) { + } + + if (field == null) { + throw new ModelException("Cannot find getter/field " + entity.getType().getSimpleName() + "::" + fieldOrGetter); + } + return field; + } +} diff --git a/src/main/java/jef/model/annotations/processors/KeyProcessorBase.java b/src/main/java/jef/model/annotations/processors/KeyProcessorBase.java index 34195af..1d26114 100644 --- a/src/main/java/jef/model/annotations/processors/KeyProcessorBase.java +++ b/src/main/java/jef/model/annotations/processors/KeyProcessorBase.java @@ -14,7 +14,7 @@ import java.util.Arrays; import java.util.List; import java.util.Locale; -public abstract class KeyProcessorBase implements AnnotationProcessor { +abstract class KeyProcessorBase implements AnnotationProcessor { private final Class annotationClass; protected KeyProcessorBase(Class annotationClass) { diff --git a/src/main/java/jef/model/constraints/ForeignKeyConstraint.java b/src/main/java/jef/model/constraints/ForeignKeyConstraint.java index 761b970..384b2c3 100644 --- a/src/main/java/jef/model/constraints/ForeignKeyConstraint.java +++ b/src/main/java/jef/model/constraints/ForeignKeyConstraint.java @@ -3,6 +3,7 @@ package jef.model.constraints; import jef.model.DbEntity; import jef.model.DbField; import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; import lombok.Getter; import java.util.List; @@ -10,14 +11,30 @@ import java.util.stream.Collectors; @Getter @AllArgsConstructor +@EqualsAndHashCode public class ForeignKeyConstraint implements Constraint { private final DbEntity entity; private final List> fields; private final DbEntity referencedEntity; private final List> referencedFields; + private final Action onUpdate; + private final Action onDelete; @Override public String getName() { return "FK_" + entity.getName() + "_" + referencedEntity.getName() + "_" + fields.stream().map(DbField::getName).collect(Collectors.joining("_")); } + + @Override + public String toString() { + return "CONSTRAINT " + getName() + " FOREIGN KEY (" + fields.stream().map(DbField::getName).collect(Collectors.joining(", ")) + ") " + + "REFERENCES " + referencedEntity.getName() + "(" + referencedFields.stream().map(DbField::getName).collect(Collectors.joining(", ")) + ")"; + } + + public enum Action { + CASCADE, + RESTRICT, + SET_NULL, + NO_ACTION, + } } diff --git a/src/main/java/jef/model/constraints/IndexConstraint.java b/src/main/java/jef/model/constraints/IndexConstraint.java index e9f7803..8c9c25f 100644 --- a/src/main/java/jef/model/constraints/IndexConstraint.java +++ b/src/main/java/jef/model/constraints/IndexConstraint.java @@ -3,6 +3,7 @@ package jef.model.constraints; import jef.model.DbEntity; import jef.model.DbField; import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; import lombok.Getter; import java.util.List; @@ -10,6 +11,7 @@ import java.util.stream.Collectors; @Getter @AllArgsConstructor +@EqualsAndHashCode public class IndexConstraint implements Constraint { private final DbEntity entity; private final List> fields; @@ -18,4 +20,9 @@ public class IndexConstraint implements Constraint { public String getName() { return "I_" + entity.getName() + "_" + fields.stream().map(DbField::getName).collect(Collectors.joining("_")); } + + @Override + public String toString() { + return "CONSTRAINT " + getName() + " INDEX (" + fields.stream().map(DbField::getName).collect(Collectors.joining(", ")) + ")"; + } } diff --git a/src/main/java/jef/model/constraints/KeyConstraint.java b/src/main/java/jef/model/constraints/KeyConstraint.java index fc173a2..5be25c9 100644 --- a/src/main/java/jef/model/constraints/KeyConstraint.java +++ b/src/main/java/jef/model/constraints/KeyConstraint.java @@ -3,6 +3,7 @@ package jef.model.constraints; import jef.model.DbEntity; import jef.model.DbField; import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; import lombok.Getter; import java.util.List; @@ -10,6 +11,7 @@ import java.util.stream.Collectors; @Getter @AllArgsConstructor +@EqualsAndHashCode public class KeyConstraint implements Constraint { private final DbEntity entity; private final List> fields; @@ -18,4 +20,9 @@ public class KeyConstraint implements Constraint { public String getName() { return "K_" + entity.getName() + "_" + fields.stream().map(DbField::getName).collect(Collectors.joining("_")); } + + @Override + public String toString() { + return "CONSTRAINT " + getName() + " KEY (" + fields.stream().map(DbField::getName).collect(Collectors.joining(", ")) + ")"; + } } diff --git a/src/main/java/jef/model/constraints/PrimaryKeyConstraint.java b/src/main/java/jef/model/constraints/PrimaryKeyConstraint.java index 81e7fb6..a17f42a 100644 --- a/src/main/java/jef/model/constraints/PrimaryKeyConstraint.java +++ b/src/main/java/jef/model/constraints/PrimaryKeyConstraint.java @@ -3,12 +3,15 @@ package jef.model.constraints; import jef.model.DbEntity; import jef.model.DbField; import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; import lombok.Getter; import java.util.List; +import java.util.stream.Collectors; @Getter @AllArgsConstructor +@EqualsAndHashCode public class PrimaryKeyConstraint implements Constraint { private final DbEntity entity; private final List> fields; @@ -17,4 +20,9 @@ public class PrimaryKeyConstraint implements Constraint { public String getName() { return "PRIMARY"; } + + @Override + public String toString() { + return getName() + " KEY (" + fields.stream().map(DbField::getName).collect(Collectors.joining(", ")) + ")"; + } } diff --git a/src/main/java/jef/model/constraints/UniqueConstraint.java b/src/main/java/jef/model/constraints/UniqueConstraint.java index 40c0e88..ce5f133 100644 --- a/src/main/java/jef/model/constraints/UniqueConstraint.java +++ b/src/main/java/jef/model/constraints/UniqueConstraint.java @@ -3,6 +3,7 @@ package jef.model.constraints; import jef.model.DbEntity; import jef.model.DbField; import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; import lombok.Getter; import java.util.List; @@ -10,6 +11,7 @@ import java.util.stream.Collectors; @Getter @AllArgsConstructor +@EqualsAndHashCode public class UniqueConstraint implements Constraint { private final DbEntity entity; private final List> fields; @@ -18,4 +20,9 @@ public class UniqueConstraint implements Constraint { public String getName() { return "U_" + entity.getName() + "_" + fields.stream().map(DbField::getName).collect(Collectors.joining("_")); } + + @Override + public String toString() { + return "CONSTRAINT " + getName() + " UNIQUE KEY (" + fields.stream().map(DbField::getName).collect(Collectors.joining(", ")) + ")"; + } } diff --git a/src/test/java/jef/model/DbContextMissingAnnotationTest.java b/src/test/java/jef/model/DbContextMissingAnnotationTest.java new file mode 100644 index 0000000..06a4d44 --- /dev/null +++ b/src/test/java/jef/model/DbContextMissingAnnotationTest.java @@ -0,0 +1,33 @@ +package jef.model; + +import jef.DbSet; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; + +class DbContextMissingAnnotationTest { + @Test + public void test() { + assertEquals("DbSet objects1 is missing the Clazz annotation", + assertThrowsExactly(ModelException.class, () -> ModelBuilder.from(Ctx.class)).getMessage()); + } + + public static class Ctx extends DbContext { + // @Clazz(clazz = TestClass.class) + private DbSet objects1; + } + + @Getter + public static class TestClass extends SerializableObject { + @Id + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/DbContextSimpleTest.java b/src/test/java/jef/model/DbContextSimpleTest.java new file mode 100644 index 0000000..c701f22 --- /dev/null +++ b/src/test/java/jef/model/DbContextSimpleTest.java @@ -0,0 +1,52 @@ +package jef.model; + +import jef.DbSet; +import jef.model.annotations.Clazz; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class DbContextSimpleTest { + @Test + public void test() { + var mb = ModelBuilder.from(Ctx.class); + assertEquals(1, mb.getEntities().size()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + + assertEquals(5, mb.getEntity(TestClass.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i")).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d")).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f")).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l")).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o")).count()); + + //intrinsic non null + assertEquals(5, mb.getEntity(TestClass.class).getFields().size()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i")).findFirst().get().isNotNull()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d")).findFirst().get().isNotNull()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f")).findFirst().get().isNotNull()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l")).findFirst().get().isNotNull()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o")).findFirst().get().isNotNull()); + } + + public static class Ctx extends DbContext { + + @Clazz(clazz = TestClass.class) + private DbSet objects1; + } + + @Getter + public static class TestClass extends SerializableObject { + @Id + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/DbContextTest.java b/src/test/java/jef/model/DbContextTest.java deleted file mode 100644 index 4c9c742..0000000 --- a/src/test/java/jef/model/DbContextTest.java +++ /dev/null @@ -1,143 +0,0 @@ -package jef.model; - -import jef.DbSet; -import jef.model.annotations.Clazz; -import jef.model.annotations.Id; -import jef.serializable.SerializableObject; -import lombok.Getter; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class DbContextTest { - - @Test - public void testSimple() { - var mb = ModelBuilder.from(Ctx.class); - assertEquals(1, mb.getEntities().size()); - assertEquals(TestClass.class.getSimpleName(), mb.getEntities().get(0).getName()); - - assertEquals(5, mb.getEntities().get(0).getFields().size()); - assertEquals(1, mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("i")).count()); - assertEquals(1, mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("d")).count()); - assertEquals(1, mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("f")).count()); - assertEquals(1, mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("l")).count()); - assertEquals(1, mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("o")).count()); - - //intrinsic non null - assertEquals(5, mb.getEntities().get(0).getFields().size()); - assertTrue(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("i")).findFirst().get().isNotNull()); - assertTrue(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("d")).findFirst().get().isNotNull()); - assertTrue(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("f")).findFirst().get().isNotNull()); - assertTrue(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("l")).findFirst().get().isNotNull()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("o")).findFirst().get().isNotNull()); - } - - public static class Ctx extends DbContext { - - @Clazz(clazz = TestClass.class) - private DbSet objects1; - } - - @Test - public void testMissingAnnotation() { - assertThrows(ModelException.class, () -> ModelBuilder.from(CtxMissingAnnotation.class)); - } - - public static class CtxMissingAnnotation extends DbContext { - - private DbSet objects1; - } - - @Getter - public static class TestClass extends SerializableObject { - @Id - public int i = 1; - public Object o = new Object(); - public double d; - public float f; - public long l; - } - - //test nested - @Test - public void testNestedObjectsSimple() { - var mb = ModelBuilder.from(CtxNestedSimple.class); - - assertEquals(2, mb.getEntities().size()); - assertEquals(TestClass2.class.getSimpleName(), mb.getEntities().get(0).getName()); - assertEquals(TestClass.class.getSimpleName(), mb.getEntities().get(1).getName()); - - //TestClass2 - assertEquals(2, mb.getEntities().get(0).getFields().size()); - assertEquals(1, mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("i")).count()); - assertEquals(1, mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("nestedI")).count()); - - //TestClass - assertEquals(5, mb.getEntities().get(1).getFields().size()); - assertEquals(1, mb.getEntities().get(1).getFields().stream().filter(e -> e.getName().equals("i")).count()); - assertEquals(1, mb.getEntities().get(1).getFields().stream().filter(e -> e.getName().equals("d")).count()); - assertEquals(1, mb.getEntities().get(1).getFields().stream().filter(e -> e.getName().equals("f")).count()); - assertEquals(1, mb.getEntities().get(1).getFields().stream().filter(e -> e.getName().equals("l")).count()); - assertEquals(1, mb.getEntities().get(1).getFields().stream().filter(e -> e.getName().equals("o")).count()); - } - - public static class CtxNestedSimple extends DbContext { - @Clazz(clazz = TestClass2.class) - private DbSet objects1; - } - - @Getter - public static class TestClass2 extends SerializableObject { - @Id - public int i = 1; - @Clazz(clazz = TestClass.class) - public List nested; - } - - //test nested - @Test - public void testNestedObjects2Layer() { - var mb = ModelBuilder.from(CtxNested2Layer.class); - - assertEquals(3, mb.getEntities().size()); - assertEquals(TestClass3.class.getSimpleName(), mb.getEntities().get(0).getName()); - assertEquals(TestClass2.class.getSimpleName(), mb.getEntities().get(1).getName()); - assertEquals(TestClass.class.getSimpleName(), mb.getEntities().get(2).getName()); - - //TestClass2 - assertEquals(2, mb.getEntities().get(0).getFields().size()); - assertEquals(1, mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("id")).count()); - assertEquals(1, mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("nested2I")).count()); - - //TestClass2 - assertEquals(2, mb.getEntities().get(1).getFields().size()); - assertEquals(1, mb.getEntities().get(1).getFields().stream().filter(e -> e.getName().equals("i")).count()); - assertEquals(1, mb.getEntities().get(1).getFields().stream().filter(e -> e.getName().equals("nestedI")).count()); - - //TestClass - assertEquals(5, mb.getEntities().get(2).getFields().size()); - assertEquals(1, mb.getEntities().get(2).getFields().stream().filter(e -> e.getName().equals("i")).count()); - assertEquals(1, mb.getEntities().get(2).getFields().stream().filter(e -> e.getName().equals("d")).count()); - assertEquals(1, mb.getEntities().get(2).getFields().stream().filter(e -> e.getName().equals("f")).count()); - assertEquals(1, mb.getEntities().get(2).getFields().stream().filter(e -> e.getName().equals("l")).count()); - assertEquals(1, mb.getEntities().get(2).getFields().stream().filter(e -> e.getName().equals("o")).count()); - } - - public static class CtxNested2Layer extends DbContext { - @Clazz(clazz = TestClass3.class) - private DbSet objects1; - } - - @Getter - public static class TestClass3 extends SerializableObject { - public int id = 1; - @Clazz(clazz = TestClass2.class) - public List nested2; - } -} \ No newline at end of file diff --git a/src/test/java/jef/model/EntityInitializerMultiple1To1RelationTest.java b/src/test/java/jef/model/EntityInitializerMultiple1To1RelationTest.java new file mode 100644 index 0000000..effca3e --- /dev/null +++ b/src/test/java/jef/model/EntityInitializerMultiple1To1RelationTest.java @@ -0,0 +1,84 @@ +package jef.model; + +import jef.DbSet; +import jef.model.annotations.Clazz; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class EntityInitializerMultiple1To1RelationTest { + @Test + public void test() { + var mb = ModelBuilder.from(Ctx.class); + + assertEquals(2, mb.getEntities().size()); + assertEquals(TestClass2.class.getSimpleName(), mb.getEntity(TestClass2.class).getName()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + assertTrue(mb.getEntity(TestClass2.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass2.class))); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + assertTrue(mb.getEntity(TestClass2.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass2.class))); + assertTrue(mb.getEntity(TestClass.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + + //fields ------------------------ + //TestClass2 + assertEquals(5, mb.getEntity(TestClass2.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("i2") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("nested1") && e.isModelField() && !e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("nested1I") && !e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("nested2") && e.isModelField() && !e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("nested2I") && !e.isModelField() && e.isDatabaseField()).count()); + + //TestClass + assertEquals(5, mb.getEntity(TestClass.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o") && e.isModelField() && e.isDatabaseField()).count()); + // /fields ------------------------ + + //keys ------------------------ + assertEquals(2, mb.getEntity(TestClass2.class).getForeignKeys().size()); + assertEquals(0, mb.getEntity(TestClass.class).getForeignKeys().size()); + assertEquals(mb.getEntity(TestClass2.class), mb.getEntity(TestClass2.class).getForeignKeys().get(0).getEntity()); + assertEquals(mb.getEntity(TestClass2.class), mb.getEntity(TestClass2.class).getForeignKeys().get(1).getEntity()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass2.class).getForeignKeys().get(0).getReferencedEntity()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass2.class).getForeignKeys().get(1).getReferencedEntity()); + assertEquals(mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("nested2I")).toList(), + mb.getEntity(TestClass2.class).getForeignKeys().get(0).getFields()); + assertEquals(mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("nested1I")).toList(), + mb.getEntity(TestClass2.class).getForeignKeys().get(1).getFields()); + assertEquals(mb.getEntity(TestClass.class).getPrimaryKey().getFields(), mb.getEntity(TestClass2.class).getForeignKeys().get(0).getReferencedFields()); + assertEquals(mb.getEntity(TestClass.class).getPrimaryKey().getFields(), mb.getEntity(TestClass2.class).getForeignKeys().get(1).getReferencedFields()); + // /keys ------------------------ + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects1; + @Clazz(clazz = TestClass2.class) + private DbSet objects2; + } + + @Getter + public static class TestClass2 extends SerializableObject { + @Id + public int i2 = 1; + private TestClass nested1; + private TestClass nested2; + } + + @Getter + public static class TestClass extends SerializableObject { + @Id + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/EntityInitializerMultiple1ToNRelationTest.java b/src/test/java/jef/model/EntityInitializerMultiple1ToNRelationTest.java new file mode 100644 index 0000000..26c2492 --- /dev/null +++ b/src/test/java/jef/model/EntityInitializerMultiple1ToNRelationTest.java @@ -0,0 +1,49 @@ +package jef.model; + +import jef.DbSet; +import jef.model.annotations.Clazz; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; + +class EntityInitializerMultiple1ToNRelationTest { + @Test + public void test() { + assertEquals("Model TestClass2 multiple contains a 1 to N relation with type TestClass", + assertThrowsExactly(ModelException.class, () -> ModelBuilder.from(Ctx.class)).getMessage()); + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects1; + @Clazz(clazz = TestClass2.class) + private DbSet objects2; + } + + @Getter + public static class TestClass2 extends SerializableObject { + @Id + public int i2 = 1; + @Clazz(clazz = TestClass.class) + private List mapping; + @Clazz(clazz = TestClass.class) + private Set mapping2; + } + + @Getter + public static class TestClass extends SerializableObject { + @Id + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/ForeignKeyInitializerNToNRelationTest.java b/src/test/java/jef/model/ForeignKeyInitializerNToNRelationTest.java new file mode 100644 index 0000000..f2c843e --- /dev/null +++ b/src/test/java/jef/model/ForeignKeyInitializerNToNRelationTest.java @@ -0,0 +1,107 @@ +package jef.model; + +import jef.DbSet; +import jef.model.annotations.Clazz; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ForeignKeyInitializerNToNRelationTest { + @Test + public void test() { + var mb = ModelBuilder.from(Ctx.class); + + assertEquals(3, mb.getEntities().size()); + assertEquals(TestClass2.class.getSimpleName(), mb.getEntity(TestClass2.class).getName()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + assertEquals(Mapping.class.getSimpleName(), mb.getEntity(Mapping.class).getName()); + assertTrue(mb.getEntity(TestClass2.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass2.class))); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + assertTrue(mb.getEntity(Mapping.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(Mapping.class))); + assertTrue(mb.getEntity(TestClass2.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass2.class))); + assertTrue(mb.getEntity(TestClass.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + assertTrue(mb.getEntity(Mapping.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(Mapping.class))); + + //fields ------------------------ + //TestClass2 + assertEquals(2, mb.getEntity(TestClass2.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("i2") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("mapping") && e.isModelField() && !e.isDatabaseField()).count()); + + //TestClass + assertEquals(6, mb.getEntity(TestClass.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("mapping") && e.isModelField() && !e.isDatabaseField()).count()); + + //Mapping + assertEquals(4, mb.getEntity(Mapping.class).getFields().size()); + assertEquals(1, mb.getEntity(Mapping.class).getFields().stream().filter(e -> e.getName().equals("object") && e.isModelField() && !e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(Mapping.class).getFields().stream().filter(e -> e.getName().equals("objectI") && !e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(Mapping.class).getFields().stream().filter(e -> e.getName().equals("object2") && e.isModelField() && !e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(Mapping.class).getFields().stream().filter(e -> e.getName().equals("object2I2") && !e.isModelField() && e.isDatabaseField()).count()); + // /fields ------------------------ + + //keys ------------------------ + assertEquals(0, mb.getEntity(TestClass2.class).getForeignKeys().size()); + assertEquals(0, mb.getEntity(TestClass.class).getForeignKeys().size()); + assertEquals(2, mb.getEntity(Mapping.class).getForeignKeys().size()); + assertEquals(mb.getEntity(Mapping.class), mb.getEntity(Mapping.class).getForeignKeys().get(0).getEntity()); + assertEquals(mb.getEntity(Mapping.class), mb.getEntity(Mapping.class).getForeignKeys().get(1).getEntity()); + assertEquals(mb.getEntity(TestClass2.class), mb.getEntity(Mapping.class).getForeignKeys().get(0).getReferencedEntity()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(Mapping.class).getForeignKeys().get(1).getReferencedEntity()); + assertEquals(mb.getEntity(Mapping.class).getFields().stream().filter(e -> e.getName().equals("object2I2")).toList(), + mb.getEntity(Mapping.class).getForeignKeys().get(0).getFields()); + assertEquals(mb.getEntity(Mapping.class).getFields().stream().filter(e -> e.getName().equals("objectI")).toList(), + mb.getEntity(Mapping.class).getForeignKeys().get(1).getFields()); + assertEquals(mb.getEntity(TestClass2.class).getPrimaryKey().getFields(), mb.getEntity(Mapping.class).getForeignKeys().get(0).getReferencedFields()); + assertEquals(mb.getEntity(TestClass.class).getPrimaryKey().getFields(), mb.getEntity(Mapping.class).getForeignKeys().get(1).getReferencedFields()); + // /keys ------------------------ + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects1; + @Clazz(clazz = TestClass2.class) + private DbSet objects2; + @Clazz(clazz = Mapping.class) + private DbSet rels; + } + + @Getter + public static class TestClass2 extends SerializableObject { + @Id + public int i2 = 1; + @Clazz(clazz = Mapping.class) + private List mapping; + } + + @Getter + public static class TestClass extends SerializableObject { + @Id + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + @Clazz(clazz = Mapping.class) + private List mapping; + } + + @Getter + public static class Mapping extends SerializableObject { + @Clazz(clazz = TestClass2.class) + private TestClass2 object2; + @Clazz(clazz = TestClass.class) + private TestClass object; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/ForeignKeyInitializerNestedList2LayerTest.java b/src/test/java/jef/model/ForeignKeyInitializerNestedList2LayerTest.java new file mode 100644 index 0000000..11e6ccc --- /dev/null +++ b/src/test/java/jef/model/ForeignKeyInitializerNestedList2LayerTest.java @@ -0,0 +1,104 @@ +package jef.model; + +import jef.DbSet; +import jef.model.annotations.Clazz; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ForeignKeyInitializerNestedList2LayerTest { + @Test + public void test() { + var mb = ModelBuilder.from(Ctx.class); + + assertEquals(3, mb.getEntities().size()); + assertEquals(TestClass3.class.getSimpleName(), mb.getEntity(TestClass3.class).getName()); + assertEquals(TestClass2.class.getSimpleName(), mb.getEntity(TestClass2.class).getName()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + assertTrue(mb.getEntity(TestClass3.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass3.class))); + assertTrue(mb.getEntity(TestClass2.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass2.class))); + assertTrue(mb.getEntity(TestClass.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + + assertTrue(mb.getEntity(TestClass3.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass3.class))); + assertTrue(mb.getEntity(TestClass2.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass2.class))); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + + //fields ------------------------ + //TestClass3 + assertEquals(2, mb.getEntity(TestClass3.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass3.class).getFields().stream().filter(e -> e.getName().equals("id") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass3.class).getFields().stream().filter(e -> e.getName().equals("nested2") && e.isModelField() && !e.isDatabaseField()).count()); + + //TestClass2 + assertEquals(3, mb.getEntity(TestClass2.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("i") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("nested") && e.isModelField() && !e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("nested2Id") && !e.isModelField() && e.isDatabaseField()).count()); + + //TestClass + assertEquals(6, mb.getEntity(TestClass.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("nestedI") && !e.isModelField() && e.isDatabaseField()).count()); + // /fields ------------------------ + + //keys ------------------------ + assertEquals(0, mb.getEntity(TestClass3.class).getForeignKeys().size()); + assertEquals(1, mb.getEntity(TestClass2.class).getForeignKeys().size()); + assertEquals(1, mb.getEntity(TestClass.class).getForeignKeys().size()); + + //refs TestClass3, TestClass2 + assertEquals(mb.getEntity(TestClass2.class), mb.getEntity(TestClass2.class).getForeignKeys().get(0).getEntity()); + assertEquals(mb.getEntity(TestClass3.class), mb.getEntity(TestClass2.class).getForeignKeys().get(0).getReferencedEntity()); + assertEquals(mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("nested2Id")).toList(), + mb.getEntity(TestClass2.class).getForeignKeys().get(0).getFields()); + assertEquals(mb.getEntity(TestClass3.class).getPrimaryKey().getFields(), mb.getEntity(TestClass2.class).getForeignKeys().get(0).getReferencedFields()); + + //refs TestClass2, TestClass + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass.class).getForeignKeys().get(0).getEntity()); + assertEquals(mb.getEntity(TestClass2.class), mb.getEntity(TestClass.class).getForeignKeys().get(0).getReferencedEntity()); + assertEquals(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("nestedI")).toList(), + mb.getEntity(TestClass.class).getForeignKeys().get(0).getFields()); + assertEquals(mb.getEntity(TestClass2.class).getPrimaryKey().getFields(), mb.getEntity(TestClass.class).getForeignKeys().get(0).getReferencedFields()); + // /keys ------------------------ + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass3.class) + private DbSet objects1; + } + + @Getter + public static class TestClass3 extends SerializableObject { + public int id = 1; + @Clazz(clazz = TestClass2.class) + public List nested2; + } + + @Getter + public static class TestClass2 extends SerializableObject { + @Id + public int i = 1; + @Clazz(clazz = TestClass.class) + public List nested; + } + + @Getter + public static class TestClass extends SerializableObject { + @Id + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/ForeignKeyInitializerNestedListMissingPrimaryKeyTest.java b/src/test/java/jef/model/ForeignKeyInitializerNestedListMissingPrimaryKeyTest.java new file mode 100644 index 0000000..99f29da --- /dev/null +++ b/src/test/java/jef/model/ForeignKeyInitializerNestedListMissingPrimaryKeyTest.java @@ -0,0 +1,44 @@ +package jef.model; + +import jef.DbSet; +import jef.model.annotations.Clazz; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; + +class ForeignKeyInitializerNestedListMissingPrimaryKeyTest { + @Test + public void test() { + assertEquals("Entity TestClass2 is missing a primary key and therefore cannot be referenced by TestClass", + assertThrowsExactly(ModelException.class, () -> ModelBuilder.from(Ctx.class)).getMessage()); + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass2.class) + private DbSet objects1; + } + + @Getter + public static class TestClass2 extends SerializableObject { + // @Id + public int i = 1; + @Clazz(clazz = TestClass.class) + public List nested; + } + + @Getter + public static class TestClass extends SerializableObject { + @Id + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/ForeignKeyInitializerNestedListSimpleTest.java b/src/test/java/jef/model/ForeignKeyInitializerNestedListSimpleTest.java new file mode 100644 index 0000000..62f0070 --- /dev/null +++ b/src/test/java/jef/model/ForeignKeyInitializerNestedListSimpleTest.java @@ -0,0 +1,77 @@ +package jef.model; + +import jef.DbSet; +import jef.model.annotations.Clazz; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ForeignKeyInitializerNestedListSimpleTest { + @Test + public void test() { + var mb = ModelBuilder.from(Ctx.class); + + assertEquals(2, mb.getEntities().size()); + assertEquals(TestClass2.class.getSimpleName(), mb.getEntity(TestClass2.class).getName()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + assertTrue(mb.getEntity(TestClass2.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass2.class))); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + assertTrue(mb.getEntity(TestClass2.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass2.class))); + assertTrue(mb.getEntity(TestClass.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + + //fields ------------------------ + //TestClass2 + assertEquals(2, mb.getEntity(TestClass2.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("i") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("nested") && e.isModelField() && !e.isDatabaseField()).count()); + + //TestClass + assertEquals(6, mb.getEntity(TestClass.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("nestedI") && !e.isModelField() && e.isDatabaseField()).count()); + // /fields ------------------------ + + //keys ------------------------ + assertEquals(0, mb.getEntity(TestClass2.class).getForeignKeys().size()); + assertEquals(1, mb.getEntity(TestClass.class).getForeignKeys().size()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass.class).getForeignKeys().get(0).getEntity()); + assertEquals(mb.getEntity(TestClass2.class), mb.getEntity(TestClass.class).getForeignKeys().get(0).getReferencedEntity()); + assertEquals(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("nestedI")).toList(), + mb.getEntity(TestClass.class).getForeignKeys().get(0).getFields()); + assertEquals(mb.getEntity(TestClass2.class).getPrimaryKey().getFields(), mb.getEntity(TestClass.class).getForeignKeys().get(0).getReferencedFields()); + // /keys ------------------------ + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass2.class) + private DbSet objects1; + } + + @Getter + public static class TestClass2 extends SerializableObject { + @Id + public int i = 1; + @Clazz(clazz = TestClass.class) + public List nested; + } + + @Getter + public static class TestClass extends SerializableObject { + @Id + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/ForeignKeyInitializerNestedObject2LayerTest.java b/src/test/java/jef/model/ForeignKeyInitializerNestedObject2LayerTest.java new file mode 100644 index 0000000..13ddaae --- /dev/null +++ b/src/test/java/jef/model/ForeignKeyInitializerNestedObject2LayerTest.java @@ -0,0 +1,99 @@ +package jef.model; + +import jef.DbSet; +import jef.model.annotations.Clazz; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ForeignKeyInitializerNestedObject2LayerTest { + @Test + public void test() { + var mb = ModelBuilder.from(Ctx.class); + + assertEquals(3, mb.getEntities().size()); + assertEquals(TestClass3.class.getSimpleName(), mb.getEntity(TestClass3.class).getName()); + assertEquals(TestClass2.class.getSimpleName(), mb.getEntity(TestClass2.class).getName()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + assertTrue(mb.getEntity(TestClass3.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass3.class))); + assertTrue(mb.getEntity(TestClass2.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass2.class))); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + assertTrue(mb.getEntity(TestClass3.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass3.class))); + assertTrue(mb.getEntity(TestClass2.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass2.class))); + assertTrue(mb.getEntity(TestClass.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + + //fields ------------------------ + //TestClass3 + assertEquals(3, mb.getEntity(TestClass3.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass3.class).getFields().stream().filter(e -> e.getName().equals("id") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass3.class).getFields().stream().filter(e -> e.getName().equals("nested2") && e.isModelField() && !e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass3.class).getFields().stream().filter(e -> e.getName().equals("nested2I") && !e.isModelField() && e.isDatabaseField()).count()); + + //TestClass2 + assertEquals(3, mb.getEntity(TestClass2.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("i") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("nested") && e.isModelField() && !e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("nestedI") && !e.isModelField() && e.isDatabaseField()).count()); + + //TestClass + assertEquals(5, mb.getEntity(TestClass.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i")).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d")).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f")).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l")).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o")).count()); + // /fields ------------------------ + + //keys ------------------------ + assertEquals(1, mb.getEntity(TestClass3.class).getForeignKeys().size()); + assertEquals(1, mb.getEntity(TestClass2.class).getForeignKeys().size()); + assertEquals(0, mb.getEntity(TestClass.class).getForeignKeys().size()); + + //refs TestClass3, TestClass2 + assertEquals(mb.getEntity(TestClass3.class), mb.getEntity(TestClass3.class).getForeignKeys().get(0).getEntity()); + assertEquals(mb.getEntity(TestClass2.class), mb.getEntity(TestClass3.class).getForeignKeys().get(0).getReferencedEntity()); + assertEquals(mb.getEntity(TestClass3.class).getFields().stream().filter(e -> e.getName().equals("nested2I")).toList(), + mb.getEntity(TestClass3.class).getForeignKeys().get(0).getFields()); + assertEquals(mb.getEntity(TestClass2.class).getPrimaryKey().getFields(), mb.getEntity(TestClass3.class).getForeignKeys().get(0).getReferencedFields()); + + //refs TestClass2, TestClass + assertEquals(mb.getEntity(TestClass2.class), mb.getEntity(TestClass2.class).getForeignKeys().get(0).getEntity()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass2.class).getForeignKeys().get(0).getReferencedEntity()); + assertEquals(mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("nestedI")).toList(), + mb.getEntity(TestClass2.class).getForeignKeys().get(0).getFields()); + assertEquals(mb.getEntity(TestClass.class).getPrimaryKey().getFields(), mb.getEntity(TestClass2.class).getForeignKeys().get(0).getReferencedFields()); + // /keys ------------------------ + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass3.class) + private DbSet objects1; + } + + @Getter + public static class TestClass3 extends SerializableObject { + public int id = 1; + public TestClass2 nested2; + } + + @Getter + public static class TestClass2 extends SerializableObject { + @Id + public int i = 1; + public TestClass nested; + } + + @Getter + public static class TestClass extends SerializableObject { + @Id + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/ForeignKeyInitializerNestedObjectMissingPrimaryKeyTest.java b/src/test/java/jef/model/ForeignKeyInitializerNestedObjectMissingPrimaryKeyTest.java new file mode 100644 index 0000000..4db0310 --- /dev/null +++ b/src/test/java/jef/model/ForeignKeyInitializerNestedObjectMissingPrimaryKeyTest.java @@ -0,0 +1,41 @@ +package jef.model; + +import jef.DbSet; +import jef.model.annotations.Clazz; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; + +class ForeignKeyInitializerNestedObjectMissingPrimaryKeyTest { + @Test + public void test() { + assertEquals("Entity TestClass is missing a primary key and therefore cannot be referenced by TestClass2", + assertThrowsExactly(ModelException.class, () -> ModelBuilder.from(Ctx.class)).getMessage()); + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass2.class) + private DbSet objects1; + } + + @Getter + public static class TestClass2 extends SerializableObject { + @Id + public int i = 1; + public TestClass nested; + } + + @Getter + public static class TestClass extends SerializableObject { + // @Id + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/ForeignKeyInitializerNestedObjectSimpleTest.java b/src/test/java/jef/model/ForeignKeyInitializerNestedObjectSimpleTest.java new file mode 100644 index 0000000..942ec76 --- /dev/null +++ b/src/test/java/jef/model/ForeignKeyInitializerNestedObjectSimpleTest.java @@ -0,0 +1,74 @@ +package jef.model; + +import jef.DbSet; +import jef.model.annotations.Clazz; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ForeignKeyInitializerNestedObjectSimpleTest { + @Test + public void test() { + var mb = ModelBuilder.from(Ctx.class); + + assertEquals(2, mb.getEntities().size()); + assertEquals(TestClass2.class.getSimpleName(), mb.getEntity(TestClass2.class).getName()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + assertTrue(mb.getEntity(TestClass2.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass2.class))); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + assertTrue(mb.getEntity(TestClass2.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass2.class))); + assertTrue(mb.getEntity(TestClass.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + + //fields ------------------------ + //TestClass2 + assertEquals(3, mb.getEntity(TestClass2.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("i") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("nested") && e.isModelField() && !e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("nestedI") && !e.isModelField() && e.isDatabaseField()).count()); + + //TestClass + assertEquals(5, mb.getEntity(TestClass.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o") && e.isModelField() && e.isDatabaseField()).count()); + // /fields ------------------------ + + //keys ------------------------ + assertEquals(1, mb.getEntity(TestClass2.class).getForeignKeys().size()); + assertEquals(0, mb.getEntity(TestClass.class).getForeignKeys().size()); + assertEquals(mb.getEntity(TestClass2.class), mb.getEntity(TestClass2.class).getForeignKeys().get(0).getEntity()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass2.class).getForeignKeys().get(0).getReferencedEntity()); + assertEquals(mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("nestedI")).toList(), + mb.getEntity(TestClass2.class).getForeignKeys().get(0).getFields()); + assertEquals(mb.getEntity(TestClass.class).getPrimaryKey().getFields(), mb.getEntity(TestClass2.class).getForeignKeys().get(0).getReferencedFields()); + // /keys ------------------------ + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass2.class) + private DbSet objects1; + } + + @Getter + public static class TestClass2 extends SerializableObject { + @Id + public int i = 1; + public TestClass nested; + } + + @Getter + public static class TestClass extends SerializableObject { + @Id + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/ForeignKeyInitializerRecursive1To1RelationTest.java b/src/test/java/jef/model/ForeignKeyInitializerRecursive1To1RelationTest.java new file mode 100644 index 0000000..61dc097 --- /dev/null +++ b/src/test/java/jef/model/ForeignKeyInitializerRecursive1To1RelationTest.java @@ -0,0 +1,68 @@ +package jef.model; + +import jef.DbSet; +import jef.model.annotations.Clazz; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ForeignKeyInitializerRecursive1To1RelationTest { + @Test + public void test() { + var mb = ModelBuilder.from(Ctx.class); + + assertEquals(1, mb.getEntities().size()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + assertTrue(mb.getEntity(TestClass.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + + //fields ------------------------ + //TestClass + assertEquals(9, mb.getEntity(TestClass.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("previous") && e.isModelField() && !e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("previousI") && !e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("next") && e.isModelField() && !e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("nextI") && !e.isModelField() && e.isDatabaseField()).count()); + // /fields ------------------------ + + //keys ------------------------ + assertEquals(2, mb.getEntity(TestClass.class).getForeignKeys().size()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass.class).getForeignKeys().get(0).getEntity()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass.class).getForeignKeys().get(1).getEntity()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass.class).getForeignKeys().get(0).getReferencedEntity()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass.class).getForeignKeys().get(1).getReferencedEntity()); + assertEquals(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("nextI")).toList(), + mb.getEntity(TestClass.class).getForeignKeys().get(0).getFields()); + assertEquals(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("previousI")).toList(), + mb.getEntity(TestClass.class).getForeignKeys().get(1).getFields()); + assertEquals(mb.getEntity(TestClass.class).getPrimaryKey().getFields(), mb.getEntity(TestClass.class).getForeignKeys().get(0).getReferencedFields()); + assertEquals(mb.getEntity(TestClass.class).getPrimaryKey().getFields(), mb.getEntity(TestClass.class).getForeignKeys().get(1).getReferencedFields()); + // /keys ------------------------ + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects2; + } + + @Getter + public static class TestClass extends SerializableObject { + @Id + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + private TestClass previous; + private TestClass next; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/ForeignKeyInitializerRecursive1ToNRelationTest.java b/src/test/java/jef/model/ForeignKeyInitializerRecursive1ToNRelationTest.java new file mode 100644 index 0000000..9ff027b --- /dev/null +++ b/src/test/java/jef/model/ForeignKeyInitializerRecursive1ToNRelationTest.java @@ -0,0 +1,63 @@ +package jef.model; + +import jef.DbSet; +import jef.model.annotations.Clazz; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ForeignKeyInitializerRecursive1ToNRelationTest { + @Test + public void test() { + var mb = ModelBuilder.from(Ctx.class); + + assertEquals(1, mb.getEntities().size()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + assertTrue(mb.getEntity(TestClass.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + + //fields ------------------------ + //TestClass + assertEquals(7, mb.getEntity(TestClass.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("recursive") && e.isModelField() && !e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("recursiveI") && !e.isModelField() && e.isDatabaseField()).count()); + // /fields ------------------------ + + //keys ------------------------ + assertEquals(1, mb.getEntity(TestClass.class).getForeignKeys().size()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass.class).getForeignKeys().get(0).getEntity()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass.class).getForeignKeys().get(0).getReferencedEntity()); + assertEquals(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("recursiveI")).toList(), + mb.getEntity(TestClass.class).getForeignKeys().get(0).getFields()); + assertEquals(mb.getEntity(TestClass.class).getPrimaryKey().getFields(), mb.getEntity(TestClass.class).getForeignKeys().get(0).getReferencedFields()); + // /keys ------------------------ + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects2; + } + + @Getter + public static class TestClass extends SerializableObject { + @Id + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + @Clazz(clazz = TestClass.class) + private List recursive; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/ForeignKeyInitializerRecursiveWithParent1ToNRelationTest.java b/src/test/java/jef/model/ForeignKeyInitializerRecursiveWithParent1ToNRelationTest.java new file mode 100644 index 0000000..c89df11 --- /dev/null +++ b/src/test/java/jef/model/ForeignKeyInitializerRecursiveWithParent1ToNRelationTest.java @@ -0,0 +1,65 @@ +package jef.model; + +import jef.DbSet; +import jef.model.annotations.Clazz; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ForeignKeyInitializerRecursiveWithParent1ToNRelationTest { + @Test + public void test() { + var mb = ModelBuilder.from(Ctx.class); + + assertEquals(1, mb.getEntities().size()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + assertTrue(mb.getEntity(TestClass.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + + //fields ------------------------ + //TestClass + assertEquals(8, mb.getEntity(TestClass.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("recursive") && e.isModelField() && !e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("parent") && e.isModelField() && !e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("parentI") && !e.isModelField() && e.isDatabaseField()).count()); + // /fields ------------------------ + + //keys ------------------------ + assertEquals(1, mb.getEntity(TestClass.class).getForeignKeys().size()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass.class).getForeignKeys().get(0).getEntity()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass.class).getForeignKeys().get(0).getReferencedEntity()); + assertEquals(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("parentI")).toList(), + mb.getEntity(TestClass.class).getForeignKeys().get(0).getFields()); + assertEquals(mb.getEntity(TestClass.class).getPrimaryKey().getFields(), mb.getEntity(TestClass.class).getForeignKeys().get(0).getReferencedFields()); + // /keys ------------------------ + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects2; + } + + @Getter + public static class TestClass extends SerializableObject { + @Id + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + @Clazz(clazz = TestClass.class) + private List recursive; + private TestClass parent; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorExposeTest.java b/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorExposeTest.java new file mode 100644 index 0000000..c8664f2 --- /dev/null +++ b/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorExposeTest.java @@ -0,0 +1,80 @@ +package jef.model.annotations.processors; + +import jef.DbSet; +import jef.model.DbContext; +import jef.model.ModelBuilder; +import jef.model.annotations.Clazz; +import jef.model.annotations.ForeignKey; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ForeignKeyProcessorExposeTest { + @Test + public void test() { + var mb = ModelBuilder.from(Ctx.class); + + assertEquals(2, mb.getEntities().size()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + assertEquals(TestClass2.class.getSimpleName(), mb.getEntity(TestClass2.class).getName()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + assertTrue(mb.getEntity(TestClass2.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass2.class))); + assertTrue(mb.getEntity(TestClass.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + assertTrue(mb.getEntity(TestClass2.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass2.class))); + + //fields ------------------------ + //TestClass + assertEquals(8, mb.getEntity(TestClass.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("test") && e.isModelField() && !e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("testFk") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("testI") && !e.isModelField() && e.isDatabaseField()).count()); + + //TestClass2 + assertEquals(1, mb.getEntity(TestClass2.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("i") && e.isModelField() && e.isDatabaseField()).count()); + // /fields ------------------------ + + //keys ------------------------ + assertEquals(1, mb.getEntity(TestClass.class).getForeignKeys().size()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass.class).getForeignKeys().get(0).getEntity()); + assertEquals(mb.getEntity(TestClass2.class), mb.getEntity(TestClass.class).getForeignKeys().get(0).getReferencedEntity()); + assertEquals(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("testI")).toList(), + mb.getEntity(TestClass.class).getForeignKeys().get(0).getFields()); + assertEquals(mb.getEntity(TestClass2.class).getPrimaryKey().getFields(), mb.getEntity(TestClass.class).getForeignKeys().get(0).getReferencedFields()); + // /keys ------------------------ + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects1; + @Clazz(clazz = TestClass2.class) + private DbSet objects2; + } + + @Getter + public static class TestClass extends SerializableObject { + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + private TestClass2 test; + @ForeignKey(getterOrField = "test") + public int testFk; + } + + @Getter + public static class TestClass2 extends SerializableObject { + @Id + public int i = 1; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorInvalidEntityTest.java b/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorInvalidEntityTest.java new file mode 100644 index 0000000..740b108 --- /dev/null +++ b/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorInvalidEntityTest.java @@ -0,0 +1,46 @@ +package jef.model.annotations.processors; + +import jef.DbSet; +import jef.model.DbContext; +import jef.model.ModelBuilder; +import jef.model.ModelException; +import jef.model.annotations.Clazz; +import jef.model.annotations.ForeignKey; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ForeignKeyProcessorInvalidEntityTest { + @Test + public void test() { + assertEquals("Could not find referenced entity TestClass2 (via @ForeignKey in TestClass::ref)", + assertThrowsExactly(ModelException.class, () -> ModelBuilder.from(Ctx.class)).getMessage()); + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects1; + } + + @Getter + public static class TestClass extends SerializableObject { + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + @ForeignKey(getterOrField = "i", entity = TestClass2.class) + public int ref; + } + + public static class TestClass2 extends SerializableObject { + @Id + public int i = 1; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorInvalidFieldOrGetterTest.java b/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorInvalidFieldOrGetterTest.java new file mode 100644 index 0000000..0692faf --- /dev/null +++ b/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorInvalidFieldOrGetterTest.java @@ -0,0 +1,40 @@ +package jef.model.annotations.processors; + +import jef.DbSet; +import jef.model.DbContext; +import jef.model.ModelBuilder; +import jef.model.ModelException; +import jef.model.annotations.Clazz; +import jef.model.annotations.ForeignKey; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ForeignKeyProcessorInvalidFieldOrGetterTest { + @Test + public void test() { + assertEquals("Cannot find getter/field TestClass::x (via @ForeignKey in TestClass::ref)", + assertThrowsExactly(ModelException.class, () -> ModelBuilder.from(Ctx.class)).getMessage()); + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects1; + } + + @Getter + public static class TestClass extends SerializableObject { + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + @ForeignKey(getterOrField = "x", entity = TestClass.class) + public int ref; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorMissingPrimaryKeyTest.java b/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorMissingPrimaryKeyTest.java new file mode 100644 index 0000000..3faf3db --- /dev/null +++ b/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorMissingPrimaryKeyTest.java @@ -0,0 +1,40 @@ +package jef.model.annotations.processors; + +import jef.DbSet; +import jef.model.DbContext; +import jef.model.ModelBuilder; +import jef.model.ModelException; +import jef.model.annotations.Clazz; +import jef.model.annotations.ForeignKey; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ForeignKeyProcessorMissingPrimaryKeyTest { + @Test + public void test() { + assertEquals("Entity TestClass does not have a primary key and can therefore not be referenced (via @ForeignKey in TestClass::ref)", + assertThrowsExactly(ModelException.class, () -> ModelBuilder.from(Ctx.class)).getMessage()); + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects1; + } + + @Getter + public static class TestClass extends SerializableObject { + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + @ForeignKey(getterOrField = "i", entity = TestClass.class) + public int ref; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorNotPrimaryKeyTest.java b/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorNotPrimaryKeyTest.java new file mode 100644 index 0000000..a0f27e8 --- /dev/null +++ b/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorNotPrimaryKeyTest.java @@ -0,0 +1,40 @@ +package jef.model.annotations.processors; + +import jef.DbSet; +import jef.model.DbContext; +import jef.model.ModelBuilder; +import jef.model.ModelException; +import jef.model.annotations.Clazz; +import jef.model.annotations.ForeignKey; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; + +class ForeignKeyProcessorNotPrimaryKeyTest { + @Test + public void test() { + assertEquals("TestClass::l is not equal to the primary key of entity TestClass (i) and can therefore not be referenced (via @ForeignKey in TestClass::ref)", + assertThrowsExactly(ModelException.class, () -> ModelBuilder.from(Ctx.class)).getMessage()); + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects1; + } + + @Getter + public static class TestClass extends SerializableObject { + @Id + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + @ForeignKey(getterOrField = "l", entity = TestClass.class) + public int ref; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorSelfReferenceTest.java b/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorSelfReferenceTest.java new file mode 100644 index 0000000..ff6e8cd --- /dev/null +++ b/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorSelfReferenceTest.java @@ -0,0 +1,63 @@ +package jef.model.annotations.processors; + +import jef.DbSet; +import jef.model.DbContext; +import jef.model.ModelBuilder; +import jef.model.annotations.Clazz; +import jef.model.annotations.ForeignKey; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ForeignKeyProcessorSelfReferenceTest { + @Test + public void test() { + var mb = ModelBuilder.from(Ctx.class); + + assertEquals(1, mb.getEntities().size()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + assertTrue(mb.getEntity(TestClass.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + + //fields ------------------------ + //TestClass + assertEquals(6, mb.getEntity(TestClass.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("ref") && e.isModelField() && e.isDatabaseField()).count()); + // /fields ------------------------ + + //keys ------------------------ + assertEquals(1, mb.getEntity(TestClass.class).getForeignKeys().size()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass.class).getForeignKeys().get(0).getEntity()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass.class).getForeignKeys().get(0).getReferencedEntity()); + assertEquals(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("ref")).toList(), + mb.getEntity(TestClass.class).getForeignKeys().get(0).getFields()); + assertEquals(mb.getEntity(TestClass.class).getPrimaryKey().getFields(), mb.getEntity(TestClass.class).getForeignKeys().get(0).getReferencedFields()); + // /keys ------------------------ + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects1; + } + + @Getter + public static class TestClass extends SerializableObject { + @Id + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + @ForeignKey(getterOrField = "i", entity = TestClass.class) + public int ref; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorSimpleTest.java b/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorSimpleTest.java new file mode 100644 index 0000000..44ae7a2 --- /dev/null +++ b/src/test/java/jef/model/annotations/processors/ForeignKeyProcessorSimpleTest.java @@ -0,0 +1,77 @@ +package jef.model.annotations.processors; + +import jef.DbSet; +import jef.model.DbContext; +import jef.model.ModelBuilder; +import jef.model.annotations.Clazz; +import jef.model.annotations.ForeignKey; +import jef.model.annotations.Id; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ForeignKeyProcessorSimpleTest { + @Test + public void test() { + var mb = ModelBuilder.from(Ctx.class); + + assertEquals(2, mb.getEntities().size()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + assertEquals(TestClass2.class.getSimpleName(), mb.getEntity(TestClass2.class).getName()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + assertTrue(mb.getEntity(TestClass2.class).getFields().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass2.class))); + assertTrue(mb.getEntity(TestClass.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass.class))); + assertTrue(mb.getEntity(TestClass2.class).getForeignKeys().stream().allMatch(e -> e.getEntity() == mb.getEntity(TestClass2.class))); + + //fields ------------------------ + //TestClass + assertEquals(6, mb.getEntity(TestClass.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o") && e.isModelField() && e.isDatabaseField()).count()); + assertEquals(1, mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("ref") && e.isModelField() && e.isDatabaseField()).count()); + + //TestClass2 + assertEquals(1, mb.getEntity(TestClass2.class).getFields().size()); + assertEquals(1, mb.getEntity(TestClass2.class).getFields().stream().filter(e -> e.getName().equals("ix") && e.isModelField() && e.isDatabaseField()).count()); + // /fields ------------------------ + + //keys ------------------------ + assertEquals(1, mb.getEntity(TestClass.class).getForeignKeys().size()); + assertEquals(mb.getEntity(TestClass.class), mb.getEntity(TestClass.class).getForeignKeys().get(0).getEntity()); + assertEquals(mb.getEntity(TestClass2.class), mb.getEntity(TestClass.class).getForeignKeys().get(0).getReferencedEntity()); + assertEquals(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("ref")).toList(), + mb.getEntity(TestClass.class).getForeignKeys().get(0).getFields()); + assertEquals(mb.getEntity(TestClass2.class).getPrimaryKey().getFields(), mb.getEntity(TestClass.class).getForeignKeys().get(0).getReferencedFields()); + // /keys ------------------------ + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects1; + @Clazz(clazz = TestClass2.class) + private DbSet objects2; + } + + @Getter + public static class TestClass extends SerializableObject { + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + @ForeignKey(getterOrField = "ix", entity = TestClass2.class) + public int ref; + } + + @Getter + public static class TestClass2 extends SerializableObject { + @Id + public int ix = 1; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/annotations/processors/IndexProcessorClassTest.java b/src/test/java/jef/model/annotations/processors/IndexProcessorClassTest.java new file mode 100644 index 0000000..e8a30bf --- /dev/null +++ b/src/test/java/jef/model/annotations/processors/IndexProcessorClassTest.java @@ -0,0 +1,51 @@ +package jef.model.annotations.processors; + +import jef.DbSet; +import jef.model.DbContext; +import jef.model.ModelBuilder; +import jef.model.annotations.Clazz; +import jef.model.annotations.Index; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class IndexProcessorClassTest { + @Test + public void test() { + var mb = ModelBuilder.from(CtxIndexOnClass.class); + + assertEquals(1, mb.getEntities().size()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i")).findFirst().get().isIndex()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d")).findFirst().get().isIndex()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f")).findFirst().get().isIndex()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l")).findFirst().get().isIndex()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o")).findFirst().get().isIndex()); + + assertTrue(mb.getEntity(TestClass.class).getIndexes().stream() + .anyMatch(e -> e.getFields().size() == 2 + && e.getFields().stream().anyMatch(f -> f.getField().getName().equals("i")) + && e.getFields().stream().anyMatch(f -> f.getField().getName().equals("l")))); + } + + public static class CtxIndexOnClass extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects1; + } + + @Getter + @Index(gettersOrFields = {"l", "getI"}) + public static class TestClass extends SerializableObject { + public int i = 1; + public Object o = new Object(); + @Index + public double d; + public float f; + public long l; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/annotations/processors/IndexProcessorFieldTest.java b/src/test/java/jef/model/annotations/processors/IndexProcessorFieldTest.java new file mode 100644 index 0000000..a1ec81c --- /dev/null +++ b/src/test/java/jef/model/annotations/processors/IndexProcessorFieldTest.java @@ -0,0 +1,45 @@ +package jef.model.annotations.processors; + +import jef.DbSet; +import jef.model.DbContext; +import jef.model.ModelBuilder; +import jef.model.annotations.Clazz; +import jef.model.annotations.Index; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class IndexProcessorFieldTest { + @Test + public void test() { + var mb = ModelBuilder.from(Ctx.class); + + assertEquals(1, mb.getEntities().size()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i")).findFirst().get().isIndex()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d")).findFirst().get().isIndex()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f")).findFirst().get().isIndex()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l")).findFirst().get().isIndex()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o")).findFirst().get().isIndex()); + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects1; + } + + @Getter + public static class TestClass extends SerializableObject { + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + @Index + public long l; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/annotations/processors/IndexProcessorTest.java b/src/test/java/jef/model/annotations/processors/IndexProcessorTest.java deleted file mode 100644 index 05ec609..0000000 --- a/src/test/java/jef/model/annotations/processors/IndexProcessorTest.java +++ /dev/null @@ -1,82 +0,0 @@ -package jef.model.annotations.processors; - -import jef.DbSet; -import jef.model.DbContext; -import jef.model.ModelBuilder; -import jef.model.annotations.Clazz; -import jef.model.annotations.Index; -import jef.serializable.SerializableObject; -import lombok.Getter; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class IndexProcessorTest { - @Test - public void testSimple() { - var mb = ModelBuilder.from(Ctx.class); - - assertEquals(1, mb.getEntities().size()); - assertEquals(TestClass.class.getSimpleName(), mb.getEntities().get(0).getName()); - - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("i")).findFirst().get().isIndex()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("d")).findFirst().get().isIndex()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("f")).findFirst().get().isIndex()); - assertTrue(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("l")).findFirst().get().isIndex()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("o")).findFirst().get().isIndex()); - } - - @Test - public void testIndexOnClass() { - var mb = ModelBuilder.from(CtxIndexOnClass.class); - - assertEquals(1, mb.getEntities().size()); - assertEquals(TestClassIndexOnClass.class.getSimpleName(), mb.getEntities().get(0).getName()); - - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("i")).findFirst().get().isIndex()); - assertTrue(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("d")).findFirst().get().isIndex()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("f")).findFirst().get().isIndex()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("l")).findFirst().get().isIndex()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("o")).findFirst().get().isIndex()); - - assertTrue(mb.getEntities().get(0).getIndexes().stream() - .anyMatch(e -> e.getFields().size() == 2 - && e.getFields().stream().anyMatch(f -> f.getField().getName().equals("i")) - && e.getFields().stream().anyMatch(f -> f.getField().getName().equals("l")))); - } - - public static class Ctx extends DbContext { - - @Clazz(clazz = TestClass.class) - private DbSet objects1; - } - - @Getter - public static class TestClass extends SerializableObject { - public int i = 1; - public Object o = new Object(); - public double d; - public float f; - @Index - public long l; - } - - public static class CtxIndexOnClass extends DbContext { - - @Clazz(clazz = TestClassIndexOnClass.class) - private DbSet objects1; - } - - @Getter - @Index(gettersOrFields = {"l", "getI"}) - public static class TestClassIndexOnClass extends SerializableObject { - public int i = 1; - public Object o = new Object(); - @Index - public double d; - public float f; - public long l; - } -} \ No newline at end of file diff --git a/src/test/java/jef/model/annotations/processors/KeyProcessorClassTest.java b/src/test/java/jef/model/annotations/processors/KeyProcessorClassTest.java new file mode 100644 index 0000000..e965604 --- /dev/null +++ b/src/test/java/jef/model/annotations/processors/KeyProcessorClassTest.java @@ -0,0 +1,51 @@ +package jef.model.annotations.processors; + +import jef.DbSet; +import jef.model.DbContext; +import jef.model.ModelBuilder; +import jef.model.annotations.Clazz; +import jef.model.annotations.Key; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class KeyProcessorClassTest { + @Test + public void test() { + var mb = ModelBuilder.from(CtxKeyOnClass.class); + + assertEquals(1, mb.getEntities().size()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i")).findFirst().get().isKey()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d")).findFirst().get().isKey()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f")).findFirst().get().isKey()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l")).findFirst().get().isKey()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o")).findFirst().get().isKey()); + + assertTrue(mb.getEntity(TestClass.class).getKeys().stream() + .anyMatch(e -> e.getFields().size() == 2 + && e.getFields().stream().anyMatch(f -> f.getField().getName().equals("i")) + && e.getFields().stream().anyMatch(f -> f.getField().getName().equals("l")))); + } + + public static class CtxKeyOnClass extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects1; + } + + @Getter + @Key(gettersOrFields = {"l", "getI"}) + public static class TestClass extends SerializableObject { + public int i = 1; + public Object o = new Object(); + @Key + public double d; + public float f; + public long l; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/annotations/processors/KeyProcessorFieldTest.java b/src/test/java/jef/model/annotations/processors/KeyProcessorFieldTest.java new file mode 100644 index 0000000..287433b --- /dev/null +++ b/src/test/java/jef/model/annotations/processors/KeyProcessorFieldTest.java @@ -0,0 +1,45 @@ +package jef.model.annotations.processors; + +import jef.DbSet; +import jef.model.DbContext; +import jef.model.ModelBuilder; +import jef.model.annotations.Clazz; +import jef.model.annotations.Key; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class KeyProcessorFieldTest { + @Test + public void test() { + var mb = ModelBuilder.from(Ctx.class); + + assertEquals(1, mb.getEntities().size()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i")).findFirst().get().isKey()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d")).findFirst().get().isKey()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f")).findFirst().get().isKey()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l")).findFirst().get().isKey()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o")).findFirst().get().isKey()); + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects1; + } + + @Getter + public static class TestClass extends SerializableObject { + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + @Key + public long l; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/annotations/processors/KeyProcessorTest.java b/src/test/java/jef/model/annotations/processors/KeyProcessorTest.java deleted file mode 100644 index 58828c8..0000000 --- a/src/test/java/jef/model/annotations/processors/KeyProcessorTest.java +++ /dev/null @@ -1,82 +0,0 @@ -package jef.model.annotations.processors; - -import jef.DbSet; -import jef.model.DbContext; -import jef.model.ModelBuilder; -import jef.model.annotations.Clazz; -import jef.model.annotations.Key; -import jef.serializable.SerializableObject; -import lombok.Getter; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class KeyProcessorTest { - @Test - public void testSimple() { - var mb = ModelBuilder.from(Ctx.class); - - assertEquals(1, mb.getEntities().size()); - assertEquals(TestClass.class.getSimpleName(), mb.getEntities().get(0).getName()); - - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("i")).findFirst().get().isKey()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("d")).findFirst().get().isKey()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("f")).findFirst().get().isKey()); - assertTrue(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("l")).findFirst().get().isKey()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("o")).findFirst().get().isKey()); - } - - @Test - public void testKeyOnClass() { - var mb = ModelBuilder.from(CtxKeyOnClass.class); - - assertEquals(1, mb.getEntities().size()); - assertEquals(TestClassKeyOnClass.class.getSimpleName(), mb.getEntities().get(0).getName()); - - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("i")).findFirst().get().isKey()); - assertTrue(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("d")).findFirst().get().isKey()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("f")).findFirst().get().isKey()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("l")).findFirst().get().isKey()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("o")).findFirst().get().isKey()); - - assertTrue(mb.getEntities().get(0).getKeys().stream() - .anyMatch(e -> e.getFields().size() == 2 - && e.getFields().stream().anyMatch(f -> f.getField().getName().equals("i")) - && e.getFields().stream().anyMatch(f -> f.getField().getName().equals("l")))); - } - - public static class Ctx extends DbContext { - - @Clazz(clazz = TestClass.class) - private DbSet objects1; - } - - @Getter - public static class TestClass extends SerializableObject { - public int i = 1; - public Object o = new Object(); - public double d; - public float f; - @Key - public long l; - } - - public static class CtxKeyOnClass extends DbContext { - - @Clazz(clazz = TestClassKeyOnClass.class) - private DbSet objects1; - } - - @Getter - @Key(gettersOrFields = {"l", "getI"}) - public static class TestClassKeyOnClass extends SerializableObject { - public int i = 1; - public Object o = new Object(); - @Key - public double d; - public float f; - public long l; - } -} \ No newline at end of file diff --git a/src/test/java/jef/model/annotations/processors/NotNullProcessorTest.java b/src/test/java/jef/model/annotations/processors/NotNullProcessorTest.java index b911c21..d1cf32f 100644 --- a/src/test/java/jef/model/annotations/processors/NotNullProcessorTest.java +++ b/src/test/java/jef/model/annotations/processors/NotNullProcessorTest.java @@ -5,7 +5,6 @@ import jef.model.DbContext; import jef.model.ModelBuilder; import jef.model.annotations.Clazz; import jef.model.annotations.NotNull; -import jef.model.annotations.Unique; import jef.serializable.SerializableObject; import lombok.Getter; import org.junit.jupiter.api.Test; @@ -15,25 +14,22 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; class NotNullProcessorTest { - @Test public void test() { var mb = ModelBuilder.from(Ctx.class); assertEquals(1, mb.getEntities().size()); - assertEquals(TestClass.class.getSimpleName(), mb.getEntities().get(0).getName()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); - assertTrue(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("i")).findFirst().get().isNotNull()); - assertTrue(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("d")).findFirst().get().isNotNull()); - assertTrue(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("f")).findFirst().get().isNotNull()); - assertTrue(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("l")).findFirst().get().isNotNull()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("o")).findFirst().get().isNotNull()); - assertTrue(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("s")).findFirst().get().isNotNull()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i")).findFirst().get().isNotNull()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d")).findFirst().get().isNotNull()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f")).findFirst().get().isNotNull()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l")).findFirst().get().isNotNull()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o")).findFirst().get().isNotNull()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("s")).findFirst().get().isNotNull()); } - public static class Ctx extends DbContext { - @Clazz(clazz = TestClass.class) private DbSet objects1; } diff --git a/src/test/java/jef/model/annotations/processors/UniqueProcessorClassTest.java b/src/test/java/jef/model/annotations/processors/UniqueProcessorClassTest.java new file mode 100644 index 0000000..9df0dde --- /dev/null +++ b/src/test/java/jef/model/annotations/processors/UniqueProcessorClassTest.java @@ -0,0 +1,51 @@ +package jef.model.annotations.processors; + +import jef.DbSet; +import jef.model.DbContext; +import jef.model.ModelBuilder; +import jef.model.annotations.Clazz; +import jef.model.annotations.Unique; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class UniqueProcessorClassTest { + @Test + public void test() { + var mb = ModelBuilder.from(Ctx.class); + + assertEquals(1, mb.getEntities().size()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i")).findFirst().get().isUnique()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d")).findFirst().get().isUnique()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f")).findFirst().get().isUnique()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l")).findFirst().get().isUnique()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o")).findFirst().get().isUnique()); + + assertTrue(mb.getEntity(TestClass.class).getUniqueKeys().stream() + .anyMatch(e -> e.getFields().size() == 2 + && e.getFields().stream().anyMatch(f -> f.getField().getName().equals("i")) + && e.getFields().stream().anyMatch(f -> f.getField().getName().equals("l")))); + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects1; + } + + @Getter + @Unique(gettersOrFields = {"l", "getI"}) + public static class TestClass extends SerializableObject { + public int i = 1; + public Object o = new Object(); + @Unique + public double d; + public float f; + public long l; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/annotations/processors/UniqueProcessorFieldTest.java b/src/test/java/jef/model/annotations/processors/UniqueProcessorFieldTest.java new file mode 100644 index 0000000..ee663ce --- /dev/null +++ b/src/test/java/jef/model/annotations/processors/UniqueProcessorFieldTest.java @@ -0,0 +1,45 @@ +package jef.model.annotations.processors; + +import jef.DbSet; +import jef.model.DbContext; +import jef.model.ModelBuilder; +import jef.model.annotations.Clazz; +import jef.model.annotations.Unique; +import jef.serializable.SerializableObject; +import lombok.Getter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class UniqueProcessorFieldTest { + @Test + public void test() { + var mb = ModelBuilder.from(Ctx.class); + + assertEquals(1, mb.getEntities().size()); + assertEquals(TestClass.class.getSimpleName(), mb.getEntity(TestClass.class).getName()); + + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("i")).findFirst().get().isUnique()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("d")).findFirst().get().isUnique()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("f")).findFirst().get().isUnique()); + assertTrue(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("l")).findFirst().get().isUnique()); + assertFalse(mb.getEntity(TestClass.class).getFields().stream().filter(e -> e.getName().equals("o")).findFirst().get().isUnique()); + } + + public static class Ctx extends DbContext { + @Clazz(clazz = TestClass.class) + private DbSet objects1; + } + + @Getter + public static class TestClass extends SerializableObject { + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + @Unique + public long l; + } +} \ No newline at end of file diff --git a/src/test/java/jef/model/annotations/processors/UniqueProcessorTest.java b/src/test/java/jef/model/annotations/processors/UniqueProcessorTest.java deleted file mode 100644 index 9ee017e..0000000 --- a/src/test/java/jef/model/annotations/processors/UniqueProcessorTest.java +++ /dev/null @@ -1,82 +0,0 @@ -package jef.model.annotations.processors; - -import jef.DbSet; -import jef.model.DbContext; -import jef.model.ModelBuilder; -import jef.model.annotations.Clazz; -import jef.model.annotations.Unique; -import jef.serializable.SerializableObject; -import lombok.Getter; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class UniqueProcessorTest { - @Test - public void testSimple() { - var mb = ModelBuilder.from(Ctx.class); - - assertEquals(1, mb.getEntities().size()); - assertEquals(TestClass.class.getSimpleName(), mb.getEntities().get(0).getName()); - - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("i")).findFirst().get().isUnique()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("d")).findFirst().get().isUnique()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("f")).findFirst().get().isUnique()); - assertTrue(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("l")).findFirst().get().isUnique()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("o")).findFirst().get().isUnique()); - } - - @Test - public void testUniqueOnClass() { - var mb = ModelBuilder.from(CtxUniqueOnClass.class); - - assertEquals(1, mb.getEntities().size()); - assertEquals(TestClassUniqueOnClass.class.getSimpleName(), mb.getEntities().get(0).getName()); - - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("i")).findFirst().get().isUnique()); - assertTrue(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("d")).findFirst().get().isUnique()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("f")).findFirst().get().isUnique()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("l")).findFirst().get().isUnique()); - assertFalse(mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("o")).findFirst().get().isUnique()); - - assertTrue(mb.getEntities().get(0).getUniqueKeys().stream() - .anyMatch(e -> e.getFields().size() == 2 - && e.getFields().stream().anyMatch(f -> f.getField().getName().equals("i")) - && e.getFields().stream().anyMatch(f -> f.getField().getName().equals("l")))); - } - - public static class Ctx extends DbContext { - - @Clazz(clazz = TestClass.class) - private DbSet objects1; - } - - @Getter - public static class TestClass extends SerializableObject { - public int i = 1; - public Object o = new Object(); - public double d; - public float f; - @Unique - public long l; - } - - public static class CtxUniqueOnClass extends DbContext { - - @Clazz(clazz = TestClassUniqueOnClass.class) - private DbSet objects1; - } - - @Getter - @Unique(gettersOrFields = {"l", "getI"}) - public static class TestClassUniqueOnClass extends SerializableObject { - public int i = 1; - public Object o = new Object(); - @Unique - public double d; - public float f; - public long l; - } -} \ No newline at end of file diff --git a/src/test/java/jef/operations/FilterOpTest.java b/src/test/java/jef/operations/FilterOpTest.java index dda869e..e1ce559 100644 --- a/src/test/java/jef/operations/FilterOpTest.java +++ b/src/test/java/jef/operations/FilterOpTest.java @@ -6,7 +6,6 @@ import lombok.Getter; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import java.io.Serializable; import java.util.Arrays; import java.util.List;