added constraints and constraint annotations, except foreign key annotation
This commit is contained in:
10
pom.xml
10
pom.xml
@@ -133,10 +133,10 @@
|
|||||||
<version>${lombok.version}</version>
|
<version>${lombok.version}</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<!-- <dependency>-->
|
||||||
<groupId>javax.persistence</groupId>
|
<!-- <groupId>javax.persistence</groupId>-->
|
||||||
<artifactId>javax.persistence-api</artifactId>
|
<!-- <artifactId>javax.persistence-api</artifactId>-->
|
||||||
<version>2.2</version>
|
<!-- <version>2.2</version>-->
|
||||||
</dependency>
|
<!-- </dependency>-->
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
@@ -4,6 +4,11 @@ import jef.asm.AsmParseException;
|
|||||||
import jef.asm.AsmParser;
|
import jef.asm.AsmParser;
|
||||||
import jef.expressions.Expression;
|
import jef.expressions.Expression;
|
||||||
import jef.expressions.IntermediateFieldExpression;
|
import jef.expressions.IntermediateFieldExpression;
|
||||||
|
import jef.model.constraints.ForeignKeyConstraint;
|
||||||
|
import jef.model.constraints.IndexConstraint;
|
||||||
|
import jef.model.constraints.KeyConstraint;
|
||||||
|
import jef.model.constraints.PrimaryKeyConstraint;
|
||||||
|
import jef.model.constraints.UniqueConstraint;
|
||||||
import jef.serializable.SerializableFunction;
|
import jef.serializable.SerializableFunction;
|
||||||
import jef.serializable.SerializableObject;
|
import jef.serializable.SerializableObject;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@@ -17,18 +22,23 @@ import java.util.List;
|
|||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class DbEntity<T extends SerializableObject> {
|
public class DbEntity<T extends SerializableObject> {
|
||||||
private final Class<T> entityClazz;
|
private final Class<T> type;
|
||||||
private final List<DbField<?>> fields;
|
private final List<DbField<?>> fields;
|
||||||
private String name;
|
private String name;
|
||||||
|
private PrimaryKeyConstraint primaryKey;
|
||||||
|
private final List<ForeignKeyConstraint> foreignKeys = new ArrayList<>();
|
||||||
|
private final List<UniqueConstraint> uniqueKeys = new ArrayList<>();
|
||||||
|
private final List<KeyConstraint> keys = new ArrayList<>();
|
||||||
|
private final List<IndexConstraint> indexes = new ArrayList<>();
|
||||||
|
|
||||||
public DbEntity(Class<T> entityClazz) {
|
public DbEntity(Class<T> type) {
|
||||||
this(entityClazz, new ArrayList<>());
|
this(type, new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public DbEntity(Class<T> entityClazz, List<DbField<?>> fields) {
|
public DbEntity(Class<T> type, List<DbField<?>> fields) {
|
||||||
this.entityClazz = entityClazz;
|
this.type = type;
|
||||||
this.fields = fields;
|
this.fields = fields;
|
||||||
this.name = entityClazz.getSimpleName();
|
this.name = type.getSimpleName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DbField<?>> getFields() {
|
public List<DbField<?>> getFields() {
|
||||||
@@ -48,16 +58,20 @@ public class DbEntity<T extends SerializableObject> {
|
|||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <R> DbField<R> getField(Field field) {
|
||||||
|
return (DbField<R>) fields.stream().filter(e -> e.getField().equals(field)).findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
public <R> DbField<R> getOrCreateField(SerializableFunction<T, R> getter) {
|
public <R> DbField<R> getOrCreateField(SerializableFunction<T, R> getter) {
|
||||||
try {
|
try {
|
||||||
var prop = getField(getter);
|
var prop = getField(getter);
|
||||||
if (prop == null) {
|
if (prop == null) {
|
||||||
var name = extractFieldName(getter);
|
var name = extractFieldName(getter);
|
||||||
var field = ReflectionUtil.getFieldsRecursive(entityClazz).stream().filter(f -> f.getName().equals(name)).findFirst().orElse(null);
|
var field = ReflectionUtil.getFieldsRecursive(type).stream().filter(f -> f.getName().equals(name)).findFirst().orElse(null);
|
||||||
if (field == null) {
|
if (field == null) {
|
||||||
throw new RuntimeException("Field not found: " + name);
|
throw new RuntimeException("Field not found: " + name);
|
||||||
}
|
}
|
||||||
prop = new DbField<>((Class<R>) field.getType(), field);
|
prop = new DbField<>(this, (Class<R>) field.getType(), field);
|
||||||
fields.add(prop);
|
fields.add(prop);
|
||||||
}
|
}
|
||||||
return prop;
|
return prop;
|
||||||
@@ -66,11 +80,24 @@ public class DbEntity<T extends SerializableObject> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <R> DbField<R> getOrCreateField(Field f) {
|
public <R> DbField<R> getOrCreateField(Field field) {
|
||||||
try {
|
try {
|
||||||
var prop = (DbField<R>) fields.stream().filter(e -> e.getField() == f).findFirst().orElse(null);
|
var prop = (DbField<R>) fields.stream().filter(e -> e.getField() == field).findFirst().orElse(null);
|
||||||
if (prop == null) {
|
if (prop == null) {
|
||||||
prop = new DbField<>((Class<R>) f.getType(), f);
|
prop = new DbField<>(this, (Class<R>) field.getType(), field);
|
||||||
|
fields.add(prop);
|
||||||
|
}
|
||||||
|
return prop;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Invalid expression", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <R> DbField<R> getOrAddField(DbField<R> field) {
|
||||||
|
try {
|
||||||
|
var prop = (DbField<R>) fields.stream().filter(e -> e.getName().equals(field.getName())).findFirst().orElse(null);
|
||||||
|
if (prop == null) {
|
||||||
|
prop = field;
|
||||||
fields.add(prop);
|
fields.add(prop);
|
||||||
}
|
}
|
||||||
return prop;
|
return prop;
|
||||||
@@ -91,4 +118,20 @@ public class DbEntity<T extends SerializableObject> {
|
|||||||
throw new RuntimeException("Invalid expression", e);
|
throw new RuntimeException("Invalid expression", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addForeignKey(ForeignKeyConstraint foreignKey) {
|
||||||
|
foreignKeys.add(foreignKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addUniqueContstraint(UniqueConstraint uniqueConstraint) {
|
||||||
|
uniqueKeys.add(uniqueConstraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addIndex(IndexConstraint index) {
|
||||||
|
indexes.add(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addKey(KeyConstraint key) {
|
||||||
|
keys.add(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,75 @@
|
|||||||
package jef.model;
|
package jef.model;
|
||||||
|
|
||||||
|
import jef.model.constraints.IndexConstraint;
|
||||||
|
import jef.model.constraints.KeyConstraint;
|
||||||
|
import jef.model.constraints.UniqueConstraint;
|
||||||
|
import jef.serializable.SerializableObject;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class DbField<T> {
|
public class DbField<T> {
|
||||||
private final Class<T> propertyClazz;
|
private final DbEntity<? extends SerializableObject> entity;
|
||||||
|
private final Class<T> type;
|
||||||
private final Field field;
|
private final Field field;
|
||||||
private String name;
|
private String name;
|
||||||
private boolean notNull = false;
|
private boolean notNull = false;
|
||||||
|
|
||||||
public DbField(Class<T> propertyClazz, Field field) {
|
public DbField(DbEntity<? extends SerializableObject> entity, Class<T> type, Field field) {
|
||||||
this.propertyClazz = propertyClazz;
|
this.entity = entity;
|
||||||
|
this.type = type;
|
||||||
this.field = field;
|
this.field = field;
|
||||||
this.name = field.getName();
|
this.name = field.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DbField(DbEntity<? extends SerializableObject> entity, Class<T> type, Field field, String name) {
|
||||||
|
this.entity = entity;
|
||||||
|
this.type = type;
|
||||||
|
this.field = field;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUnique() {
|
||||||
|
return entity.getUniqueKeys().stream().anyMatch(u -> u.getFields().size() == 1 && u.getFields().get(0) == this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUnique(boolean unique) {
|
||||||
|
var constr = entity.getUniqueKeys().stream().filter(u -> u.getFields().size() == 1 && u.getFields().get(0) == this).findFirst();
|
||||||
|
if (!constr.isPresent() && unique) {
|
||||||
|
entity.getUniqueKeys().add(new UniqueConstraint(entity, new ArrayList<>(List.of(this))));
|
||||||
|
} else if (constr.isPresent() && !unique) {
|
||||||
|
entity.getUniqueKeys().remove(constr.get());
|
||||||
|
} //else do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIndex() {
|
||||||
|
return entity.getIndexes().stream().anyMatch(u -> u.getFields().size() == 1 && u.getFields().get(0) == this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndex(boolean indexed) {
|
||||||
|
var constr = entity.getIndexes().stream().filter(u -> u.getFields().size() == 1 && u.getFields().get(0) == this).findFirst();
|
||||||
|
if (!constr.isPresent() && indexed) {
|
||||||
|
entity.getIndexes().add(new IndexConstraint(entity, new ArrayList<>(List.of(this))));
|
||||||
|
} else if (constr.isPresent() && !indexed) {
|
||||||
|
entity.getIndexes().remove(constr.get());
|
||||||
|
} //else do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isKey() {
|
||||||
|
return entity.getKeys().stream().anyMatch(u -> u.getFields().size() == 1 && u.getFields().get(0) == this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(boolean keyed) {
|
||||||
|
var constr = entity.getKeys().stream().filter(u -> u.getFields().size() == 1 && u.getFields().get(0) == this).findFirst();
|
||||||
|
if (!constr.isPresent() && keyed) {
|
||||||
|
entity.getKeys().add(new KeyConstraint(entity, new ArrayList<>(List.of(this))));
|
||||||
|
} else if (constr.isPresent() && !keyed) {
|
||||||
|
entity.getKeys().remove(constr.get());
|
||||||
|
} //else do nothing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,26 +2,35 @@ package jef.model;
|
|||||||
|
|
||||||
import jef.DbSet;
|
import jef.DbSet;
|
||||||
import jef.model.annotations.Clazz;
|
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.AnnotationProcessor;
|
||||||
|
import jef.model.annotations.processors.IndexProcessor;
|
||||||
|
import jef.model.annotations.processors.KeyProcessor;
|
||||||
import jef.model.annotations.processors.NotNullProcessor;
|
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 jef.serializable.SerializableObject;
|
||||||
|
|
||||||
import javax.persistence.Transient;
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
public class ModelBuilder {
|
public class ModelBuilder {
|
||||||
private static final List<AnnotationProcessor> annotationProcessors = new ArrayList<>();
|
private static final List<AnnotationProcessor> annotationProcessors = new ArrayList<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
annotationProcessors.add(NotNullProcessor.INSTANCE);
|
annotationProcessors.add(NotNullProcessor.INSTANCE);
|
||||||
|
annotationProcessors.add(UniqueProcessor.INSTANCE);
|
||||||
|
annotationProcessors.add(IndexProcessor.INSTANCE);
|
||||||
|
annotationProcessors.add(KeyProcessor.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ModelBuilder from(Class<? extends DbContext> context) {
|
||||||
public static ModelBuilder from(DbContext context) {
|
|
||||||
try {
|
try {
|
||||||
return from0(context);
|
return from0(context);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -29,54 +38,140 @@ public class ModelBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ModelBuilder from0(DbContext context) throws Exception {
|
private static ModelBuilder from0(Class<? extends DbContext> context) throws Exception {
|
||||||
var mb = new ModelBuilder(new ArrayList<>());
|
var mb = new ModelBuilder(new ArrayList<>());
|
||||||
for (Field ctxfield : context.getClass().getDeclaredFields()) {
|
initEntities(mb, context);
|
||||||
System.out.println(ctxfield);
|
addPrimaryKeys(mb);
|
||||||
if (!DbSet.class.isAssignableFrom(ctxfield.getType())) {
|
addForeignKeys(mb);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Clazz clazzAnnontation = ctxfield.getAnnotation(Clazz.class);
|
|
||||||
if (clazzAnnontation == null) {
|
|
||||||
throw new ModelException("DbSet " + ctxfield.getName() + " is missing the Clazz annotation");
|
|
||||||
}
|
|
||||||
var dbsetClazz = (Class<? extends SerializableObject>)clazzAnnontation.clazz();
|
|
||||||
var entity = mb.getOrCreateEntity(dbsetClazz);
|
|
||||||
|
|
||||||
var fields = ReflectionUtil.getFieldsRecursive(dbsetClazz);
|
|
||||||
for (var f : fields) {
|
|
||||||
if (f.getAnnotationsByType(Transient.class).length > 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (Collection.class.isAssignableFrom(f.getType())) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
} else {
|
|
||||||
var dbField = entity.getOrCreateField(f);
|
|
||||||
if (f.getType().isPrimitive()) {
|
|
||||||
dbField.setNotNull(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (AnnotationProcessor processor : annotationProcessors) {
|
for (AnnotationProcessor processor : annotationProcessors) {
|
||||||
processor.apply(mb);
|
processor.apply(mb);
|
||||||
}
|
}
|
||||||
return mb;
|
return mb;
|
||||||
// var entities = new HashMap<Class<? extends SerializableObject>, DbEntity<? extends SerializableObject>>();
|
|
||||||
// for (Field ctxfield : context.getClass().getDeclaredFields()) {
|
|
||||||
// if (!DbSet.class.isAssignableFrom(ctxfield.getClass())) {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// ctxfield.setAccessible(true);
|
|
||||||
// var dbset = (DbSet<? extends SerializableObject>) ctxfield.get(context);
|
|
||||||
// var dbsetClazz = dbset.getClazz();
|
|
||||||
// var fields = getFieldsRecursive(dbsetClazz);
|
|
||||||
// entities.put(dbsetClazz, createEntity(dbsetClazz, fields));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return new ModelBuilder(new ArrayList<>(entities.values()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void initEntities(ModelBuilder mb, Class<? extends DbContext> 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<? extends SerializableObject>) clazzAnnotation.clazz();
|
||||||
|
initEntity(mb, dbsetClazz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initEntity(ModelBuilder mb, Class<? extends SerializableObject> 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<Field>();
|
||||||
|
|
||||||
|
//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<? extends SerializableObject>) clazzAnnotation.clazz());
|
||||||
|
if (refEntity == null) {
|
||||||
|
initEntity(mb, (Class<? extends SerializableObject>) clazzAnnotation.clazz());
|
||||||
|
refEntity = mb.getEntity((Class<? extends SerializableObject>) 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<DbEntity<? extends SerializableObject>> entities;
|
private final List<DbEntity<? extends SerializableObject>> entities;
|
||||||
|
|
||||||
public ModelBuilder(List<DbEntity<? extends SerializableObject>> entities) {
|
public ModelBuilder(List<DbEntity<? extends SerializableObject>> entities) {
|
||||||
@@ -95,7 +190,7 @@ public class ModelBuilder {
|
|||||||
* @return the database model for the requested class or null if not present.
|
* @return the database model for the requested class or null if not present.
|
||||||
*/
|
*/
|
||||||
public <T extends SerializableObject> DbEntity<T> getEntity(Class<T> clazz) {
|
public <T extends SerializableObject> DbEntity<T> getEntity(Class<T> clazz) {
|
||||||
return (DbEntity<T>) entities.stream().filter(e -> e.getEntityClazz() == clazz).findFirst().orElse(null);
|
return (DbEntity<T>) entities.stream().filter(e -> e.getType() == clazz).findFirst().orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -7,6 +7,15 @@ import java.util.Collection;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
class ReflectionUtil {
|
class ReflectionUtil {
|
||||||
|
/**
|
||||||
|
* Returns a list of all declared fields of the given class.
|
||||||
|
* This also includes fields from super classes up until SerializableObject (exclusive).
|
||||||
|
* The fields within the same are not ordered in any particular way.
|
||||||
|
* The overall ordering is super class fields last, i.e., [...fields of the passed class, ...super class fields, ...super-super class fields, ...]
|
||||||
|
*
|
||||||
|
* @param clazz the class the go the declared fields from
|
||||||
|
* @return a list of all declared fields of the given class, including super class fields
|
||||||
|
*/
|
||||||
static Collection<Field> getFieldsRecursive(Class<? extends SerializableObject> clazz) {
|
static Collection<Field> getFieldsRecursive(Class<? extends SerializableObject> clazz) {
|
||||||
var fields = new HashMap<String, Field>();
|
var fields = new HashMap<String, Field>();
|
||||||
do {
|
do {
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package jef.model.annotations;
|
package jef.model.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Documented
|
||||||
@Target(ElementType.FIELD)
|
@Target(ElementType.FIELD)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Clazz {
|
public @interface Clazz {
|
||||||
|
|||||||
13
src/main/java/jef/model/annotations/Id.java
Normal file
13
src/main/java/jef/model/annotations/Id.java
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package jef.model.annotations;
|
||||||
|
|
||||||
|
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 Id {
|
||||||
|
}
|
||||||
14
src/main/java/jef/model/annotations/Index.java
Normal file
14
src/main/java/jef/model/annotations/Index.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package jef.model.annotations;
|
||||||
|
|
||||||
|
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, ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Index {
|
||||||
|
String[] gettersOrFields() default {};
|
||||||
|
}
|
||||||
14
src/main/java/jef/model/annotations/Key.java
Normal file
14
src/main/java/jef/model/annotations/Key.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package jef.model.annotations;
|
||||||
|
|
||||||
|
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, ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Key {
|
||||||
|
String[] gettersOrFields() default {};
|
||||||
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
package jef.model.annotations;
|
package jef.model.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Documented
|
||||||
@Target(ElementType.FIELD)
|
@Target(ElementType.FIELD)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface NotNull {
|
public @interface NotNull {
|
||||||
|
|||||||
13
src/main/java/jef/model/annotations/Transient.java
Normal file
13
src/main/java/jef/model/annotations/Transient.java
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package jef.model.annotations;
|
||||||
|
|
||||||
|
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 Transient {
|
||||||
|
}
|
||||||
14
src/main/java/jef/model/annotations/Unique.java
Normal file
14
src/main/java/jef/model/annotations/Unique.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package jef.model.annotations;
|
||||||
|
|
||||||
|
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, ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Unique {
|
||||||
|
String[] gettersOrFields() default {};
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package jef.model.annotations.processors;
|
||||||
|
|
||||||
|
import jef.model.DbEntity;
|
||||||
|
import jef.model.DbField;
|
||||||
|
import jef.model.annotations.Index;
|
||||||
|
import jef.model.constraints.IndexConstraint;
|
||||||
|
import jef.serializable.SerializableObject;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class IndexProcessor extends KeyProcessorBase<IndexConstraint, Index> {
|
||||||
|
public static final IndexProcessor INSTANCE = new IndexProcessor();
|
||||||
|
|
||||||
|
private IndexProcessor() {
|
||||||
|
super(Index.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IndexConstraint initConstraint(DbEntity<? extends SerializableObject> entity, List<DbField<?>> fields) {
|
||||||
|
return new IndexConstraint(entity, fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addConstraint(IndexConstraint constr) {
|
||||||
|
constr.getEntity().addIndex(constr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getGettersOrFields(Annotation annotation) {
|
||||||
|
return ((Index) annotation).gettersOrFields();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package jef.model.annotations.processors;
|
||||||
|
|
||||||
|
import jef.model.DbEntity;
|
||||||
|
import jef.model.DbField;
|
||||||
|
import jef.model.annotations.Key;
|
||||||
|
import jef.model.constraints.KeyConstraint;
|
||||||
|
import jef.serializable.SerializableObject;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class KeyProcessor extends KeyProcessorBase<KeyConstraint, Key> {
|
||||||
|
public static final KeyProcessor INSTANCE = new KeyProcessor();
|
||||||
|
|
||||||
|
private KeyProcessor() {
|
||||||
|
super(Key.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected KeyConstraint initConstraint(DbEntity<? extends SerializableObject> entity, List<DbField<?>> fields) {
|
||||||
|
return new KeyConstraint(entity, fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addConstraint(KeyConstraint constr) {
|
||||||
|
constr.getEntity().addKey(constr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getGettersOrFields(Annotation annotation) {
|
||||||
|
return ((Key) annotation).gettersOrFields();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package jef.model.annotations.processors;
|
||||||
|
|
||||||
|
import jef.model.DbEntity;
|
||||||
|
import jef.model.DbField;
|
||||||
|
import jef.model.ModelBuilder;
|
||||||
|
import jef.model.ModelException;
|
||||||
|
import jef.serializable.SerializableObject;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public abstract class KeyProcessorBase<K, T extends Annotation> implements AnnotationProcessor {
|
||||||
|
private final Class<T> annotationClass;
|
||||||
|
|
||||||
|
protected KeyProcessorBase(Class<T> annotationClass) {
|
||||||
|
this.annotationClass = annotationClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract K initConstraint(DbEntity<? extends SerializableObject> entity, List<DbField<?>> fields);
|
||||||
|
|
||||||
|
protected abstract void addConstraint(K constr);
|
||||||
|
|
||||||
|
protected abstract String[] getGettersOrFields(Annotation annotation);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(ModelBuilder mb) {
|
||||||
|
for (DbEntity<? extends SerializableObject> entity : mb.getEntities()) {
|
||||||
|
//class annotation
|
||||||
|
var classAnno = entity.getType().getAnnotationsByType(annotationClass);
|
||||||
|
for (T t : classAnno) {
|
||||||
|
var classFields = Arrays.stream(getGettersOrFields(t))
|
||||||
|
.map(name -> getField(entity, name))
|
||||||
|
.map(field -> {
|
||||||
|
var dbfield = (DbField<?>) entity.getField(field);
|
||||||
|
if (dbfield == null) {
|
||||||
|
throw new ModelException("DbField with field " + field.getName() + " not found in " + entity.getType().getSimpleName());
|
||||||
|
}
|
||||||
|
return dbfield;
|
||||||
|
}).toList();
|
||||||
|
addConstraint(initConstraint(entity, new ArrayList<>(classFields)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//annotation on fields
|
||||||
|
for (DbField<?> field : entity.getFields()) {
|
||||||
|
if (field.getField() != null && field.getField().getAnnotationsByType(annotationClass).length > 0) {
|
||||||
|
var dbfield = entity.getField(field.getField());
|
||||||
|
if (dbfield == null) {
|
||||||
|
throw new ModelException("DbField with field " + field.getName() + " not found in " + entity.getType().getSimpleName());
|
||||||
|
}
|
||||||
|
addConstraint(initConstraint(entity, List.of(dbfield)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Field getField(DbEntity<? extends SerializableObject> 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 '" + fieldOrGetter + "' in " + entity.getType().getSimpleName());
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@ public class NotNullProcessor implements AnnotationProcessor {
|
|||||||
public void apply(ModelBuilder mb) {
|
public void apply(ModelBuilder mb) {
|
||||||
for (DbEntity<? extends SerializableObject> entity : mb.getEntities()) {
|
for (DbEntity<? extends SerializableObject> entity : mb.getEntities()) {
|
||||||
for (DbField<?> field : entity.getFields()) {
|
for (DbField<?> field : entity.getFields()) {
|
||||||
if (field.getField().getAnnotationsByType(NotNull.class).length > 0) {
|
if (field.getField() != null && field.getField().getAnnotationsByType(NotNull.class).length > 0) {
|
||||||
field.setNotNull(true);
|
field.setNotNull(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package jef.model.annotations.processors;
|
||||||
|
|
||||||
|
import jef.model.DbEntity;
|
||||||
|
import jef.model.DbField;
|
||||||
|
import jef.model.annotations.Unique;
|
||||||
|
import jef.model.constraints.UniqueConstraint;
|
||||||
|
import jef.serializable.SerializableObject;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class UniqueProcessor extends KeyProcessorBase<UniqueConstraint, Unique> {
|
||||||
|
public static final UniqueProcessor INSTANCE = new UniqueProcessor();
|
||||||
|
|
||||||
|
private UniqueProcessor() {
|
||||||
|
super(Unique.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected UniqueConstraint initConstraint(DbEntity<? extends SerializableObject> entity, List<DbField<?>> fields) {
|
||||||
|
return new UniqueConstraint(entity, fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addConstraint(UniqueConstraint constr) {
|
||||||
|
constr.getEntity().addUniqueContstraint(constr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getGettersOrFields(Annotation annotation) {
|
||||||
|
return ((Unique) annotation).gettersOrFields();
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/main/java/jef/model/constraints/Constraint.java
Normal file
29
src/main/java/jef/model/constraints/Constraint.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package jef.model.constraints;
|
||||||
|
|
||||||
|
import jef.model.DbEntity;
|
||||||
|
import jef.model.DbField;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface Constraint {
|
||||||
|
/**
|
||||||
|
* Returns the DbEntity containing the constraint.
|
||||||
|
*
|
||||||
|
* @return he DbEntity containing the constraint
|
||||||
|
*/
|
||||||
|
DbEntity<?> getEntity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the constraint.
|
||||||
|
*
|
||||||
|
* @return the name of the constraint
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the fields of {@code getEntity()} involved in this constraint.
|
||||||
|
*
|
||||||
|
* @return the fields of {@code getEntity()} involved in this constraint
|
||||||
|
*/
|
||||||
|
List<DbField<?>> getFields();
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package jef.model.constraints;
|
||||||
|
|
||||||
|
import jef.model.DbEntity;
|
||||||
|
import jef.model.DbField;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ForeignKeyConstraint implements Constraint {
|
||||||
|
private final DbEntity<?> entity;
|
||||||
|
private final List<DbField<?>> fields;
|
||||||
|
private final DbEntity<?> referencedEntity;
|
||||||
|
private final List<DbField<?>> referencedFields;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "FK_" + entity.getName() + "_" + referencedEntity.getName() + "_" + fields.stream().map(DbField::getName).collect(Collectors.joining("_"));
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/main/java/jef/model/constraints/IndexConstraint.java
Normal file
21
src/main/java/jef/model/constraints/IndexConstraint.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package jef.model.constraints;
|
||||||
|
|
||||||
|
import jef.model.DbEntity;
|
||||||
|
import jef.model.DbField;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class IndexConstraint implements Constraint {
|
||||||
|
private final DbEntity<?> entity;
|
||||||
|
private final List<DbField<?>> fields;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "I_" + entity.getName() + "_" + fields.stream().map(DbField::getName).collect(Collectors.joining("_"));
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/main/java/jef/model/constraints/KeyConstraint.java
Normal file
21
src/main/java/jef/model/constraints/KeyConstraint.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package jef.model.constraints;
|
||||||
|
|
||||||
|
import jef.model.DbEntity;
|
||||||
|
import jef.model.DbField;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class KeyConstraint implements Constraint {
|
||||||
|
private final DbEntity<?> entity;
|
||||||
|
private final List<DbField<?>> fields;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "K_" + entity.getName() + "_" + fields.stream().map(DbField::getName).collect(Collectors.joining("_"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package jef.model.constraints;
|
||||||
|
|
||||||
|
import jef.model.DbEntity;
|
||||||
|
import jef.model.DbField;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class PrimaryKeyConstraint implements Constraint {
|
||||||
|
private final DbEntity<?> entity;
|
||||||
|
private final List<DbField<?>> fields;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "PRIMARY";
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/main/java/jef/model/constraints/UniqueConstraint.java
Normal file
21
src/main/java/jef/model/constraints/UniqueConstraint.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package jef.model.constraints;
|
||||||
|
|
||||||
|
import jef.model.DbEntity;
|
||||||
|
import jef.model.DbField;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class UniqueConstraint implements Constraint {
|
||||||
|
private final DbEntity<?> entity;
|
||||||
|
private final List<DbField<?>> fields;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "U_" + entity.getName() + "_" + fields.stream().map(DbField::getName).collect(Collectors.joining("_"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,10 +2,13 @@ package jef.model;
|
|||||||
|
|
||||||
import jef.DbSet;
|
import jef.DbSet;
|
||||||
import jef.model.annotations.Clazz;
|
import jef.model.annotations.Clazz;
|
||||||
|
import jef.model.annotations.Id;
|
||||||
import jef.serializable.SerializableObject;
|
import jef.serializable.SerializableObject;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.junit.jupiter.api.Test;
|
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.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
@@ -14,30 +17,25 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||||||
class DbContextTest {
|
class DbContextTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void testSimple() {
|
||||||
var mb = ModelBuilder.from(new Ctx());
|
var mb = ModelBuilder.from(Ctx.class);
|
||||||
for (DbEntity<? extends SerializableObject> entity : mb.getEntities()) {
|
assertEquals(1, mb.getEntities().size());
|
||||||
assertEquals("TestClass", entity.getName());
|
assertEquals(TestClass.class.getSimpleName(), mb.getEntities().get(0).getName());
|
||||||
assertEquals(5, entity.getFields().size());
|
|
||||||
assertEquals(1, entity.getFields().stream().filter(e -> e.getName().equals("i")).count());
|
|
||||||
assertEquals(1, entity.getFields().stream().filter(e -> e.getName().equals("d")).count());
|
|
||||||
assertEquals(1, entity.getFields().stream().filter(e -> e.getName().equals("f")).count());
|
|
||||||
assertEquals(1, entity.getFields().stream().filter(e -> e.getName().equals("l")).count());
|
|
||||||
assertEquals(1, entity.getFields().stream().filter(e -> e.getName().equals("o")).count());
|
|
||||||
|
|
||||||
//intrinsic non null
|
assertEquals(5, mb.getEntities().get(0).getFields().size());
|
||||||
assertEquals(5, entity.getFields().size());
|
assertEquals(1, mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("i")).count());
|
||||||
assertTrue(entity.getFields().stream().filter(e -> e.getName().equals("i")).findFirst().get().isNotNull());
|
assertEquals(1, mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("d")).count());
|
||||||
assertTrue(entity.getFields().stream().filter(e -> e.getName().equals("d")).findFirst().get().isNotNull());
|
assertEquals(1, mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("f")).count());
|
||||||
assertTrue(entity.getFields().stream().filter(e -> e.getName().equals("f")).findFirst().get().isNotNull());
|
assertEquals(1, mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("l")).count());
|
||||||
assertTrue(entity.getFields().stream().filter(e -> e.getName().equals("l")).findFirst().get().isNotNull());
|
assertEquals(1, mb.getEntities().get(0).getFields().stream().filter(e -> e.getName().equals("o")).count());
|
||||||
assertFalse(entity.getFields().stream().filter(e -> e.getName().equals("o")).findFirst().get().isNotNull());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
//intrinsic non null
|
||||||
public void testMissingAnnotation() {
|
assertEquals(5, mb.getEntities().get(0).getFields().size());
|
||||||
assertThrows(ModelException.class, () -> ModelBuilder.from(new CtxMissingAnnotation()));
|
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 {
|
public static class Ctx extends DbContext {
|
||||||
@@ -46,6 +44,11 @@ class DbContextTest {
|
|||||||
private DbSet<TestClass> objects1;
|
private DbSet<TestClass> objects1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMissingAnnotation() {
|
||||||
|
assertThrows(ModelException.class, () -> ModelBuilder.from(CtxMissingAnnotation.class));
|
||||||
|
}
|
||||||
|
|
||||||
public static class CtxMissingAnnotation extends DbContext {
|
public static class CtxMissingAnnotation extends DbContext {
|
||||||
|
|
||||||
private DbSet<TestClass> objects1;
|
private DbSet<TestClass> objects1;
|
||||||
@@ -53,10 +56,88 @@ class DbContextTest {
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public static class TestClass extends SerializableObject {
|
public static class TestClass extends SerializableObject {
|
||||||
|
@Id
|
||||||
public int i = 1;
|
public int i = 1;
|
||||||
public Object o = new Object();
|
public Object o = new Object();
|
||||||
public double d;
|
public double d;
|
||||||
public float f;
|
public float f;
|
||||||
public long l;
|
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<TestClass2> objects1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public static class TestClass2 extends SerializableObject {
|
||||||
|
@Id
|
||||||
|
public int i = 1;
|
||||||
|
@Clazz(clazz = TestClass.class)
|
||||||
|
public List<TestClass> 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<TestClass3> objects1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public static class TestClass3 extends SerializableObject {
|
||||||
|
public int id = 1;
|
||||||
|
@Clazz(clazz = TestClass2.class)
|
||||||
|
public List<TestClass2> nested2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
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<TestClass> 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<TestClassIndexOnClass> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
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<TestClass> 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<TestClassKeyOnClass> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.NotNull;
|
||||||
|
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 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());
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Ctx extends DbContext {
|
||||||
|
|
||||||
|
@Clazz(clazz = TestClass.class)
|
||||||
|
private DbSet<TestClass> 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;
|
||||||
|
@NotNull
|
||||||
|
public String s;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
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<TestClass> 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<TestClassUniqueOnClass> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user