added migrations

This commit is contained in:
wea_ondara
2022-09-08 15:58:20 +02:00
parent d532d92c0f
commit 6a1585f438
61 changed files with 1130 additions and 581 deletions

View File

@@ -15,6 +15,9 @@
- actually parse getter
- resolve Predicate functions (not, and, or)
- don't bind external vars in lambdas, instead make information (parameter and intercepted values) available in a context object
- expose more stuff as result (e.g. accessed members/functions, ...)
- cleanup exception handling
- cleanup if else trees
## ModelBuilder
- add registrable conversion types e.g. UUID, Date, Timestamp, Calendar, LocalTime, Instant,...
@@ -22,6 +25,9 @@
- field length
- field precision
- sql type
- ignore() entity/field for db
- object inlining
- entity() with callback
## Annotations
- db type

View File

@@ -1,6 +1,6 @@
package jef.asm;
public class AsmParseException extends Exception {
public class AsmParseException extends RuntimeException {
public AsmParseException() {
}

View File

@@ -0,0 +1,16 @@
package jef.asm;
import jef.expressions.Expression;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Set;
@AllArgsConstructor
@Getter
public class AsmParseResult {
private final Expression expression;
private final Set<Field> accessedFields;
}

View File

@@ -1,6 +1,5 @@
package jef.asm;
import jef.expressions.Expression;
import jef.serializable.SerializableFunction;
import jef.serializable.SerializablePredicate;
import lombok.Getter;
@@ -24,7 +23,7 @@ public class AsmParser {
this.lambda = function;
}
public Expression parse() throws AsmParseException {
public AsmParseResult parse() throws AsmParseException {
try {
return parseExpression();
} catch (Exception e) {
@@ -32,35 +31,26 @@ public class AsmParser {
}
}
private Expression parseExpression() throws Exception {
private AsmParseResult parseExpression() throws Exception {
var cls = lambda.getClass();
var loader = cls.getClassLoader();
InputStream is;
// System.out.println(cls);
// System.out.println(cls.getName());
if (cls.getName().contains("$$Lambda$")) {
// System.out.println(cls.getName().split("\\$\\$")[0].replace(".", "/") + ".class");
is = loader.getResourceAsStream(cls.getName().split("\\$\\$")[0].replace(".", "/") + ".class");
} else {
// System.out.println(cls.getName().replace(".", "/") + ".class");
is = loader.getResourceAsStream(cls.getName().replace(".", "/") + ".class");
}
var x = cls.getDeclaredMethod("writeReplace");
// System.out.println(x);
x.setAccessible(true);
var serlambda = (SerializedLambda) x.invoke(lambda);
var writeReplace = cls.getDeclaredMethod("writeReplace");
writeReplace.setAccessible(true);
var serlambda = (SerializedLambda) writeReplace.invoke(lambda);
Object[] args = IntStream.range(0, serlambda.getCapturedArgCount()).mapToObj(serlambda::getCapturedArg).toArray();
// System.out.println(serlambda);
var lambdaname = serlambda.getImplMethodName();
// System.out.println(lambdaname);
var expr = new Expression[1];
var cr = new ClassReader(is);
var visiter = new FilterClassVisitor(Opcodes.ASM9, lambdaname, args, e -> expr[0] = e);
var visiter = new FilterClassVisitor(Opcodes.ASM9, lambdaname, args);
cr.accept(visiter, 0);
return expr[0];
return visiter.getResult();
}
}

View File

@@ -1,23 +1,22 @@
package jef.asm;
import jef.expressions.Expression;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import java.util.function.Consumer;
import java.util.Optional;
class FilterClassVisitor extends ClassVisitor {
private final int api;
private final String lambdaname;
private final Consumer<Expression> queryConsumer;
private final Object[] args;
protected FilterClassVisitor(int api, String lambdaname, Object[] args, Consumer<Expression> queryConsumer) {
private FilterMethodVisitor mv;
protected FilterClassVisitor(int api, String lambdaname, Object[] args) {
super(api);
this.api = api;
this.lambdaname = lambdaname;
this.args = args;
this.queryConsumer = queryConsumer;
}
@Override
@@ -26,7 +25,23 @@ class FilterClassVisitor extends ClassVisitor {
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
System.out.println("found method name: " + name);
return new FilterMethodVisitor(api, descriptor, args, queryConsumer);
if (mv != null) {
throw new IllegalStateException("multiple lambda with same name found: " + lambdaname);
}
return mv = new FilterMethodVisitor(api, descriptor, args);
}
@Override
public void visitEnd() {
super.visitEnd();
//finish
if (mv == null) {
throw new IllegalStateException("lambda not found: " + lambdaname);
}
}
public AsmParseResult getResult() {
return Optional.ofNullable(mv).map(e -> e.getResult()).orElse(null);
}
}

View File

@@ -22,6 +22,7 @@ import org.objectweb.asm.Type;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
@@ -37,13 +38,12 @@ class FilterMethodVisitor extends MethodVisitor {
private Stack<Expression> varStack = new Stack<>();
private final String[] parameterClasses;
private final Object[] args;
private final Consumer<Expression> exprConsumer;
private Expression lambdaExpr;
private final Set<Field> accessedMembers = new HashSet<>();
protected FilterMethodVisitor(int api, String descriptor, Object[] args, Consumer<Expression> exprConsumer) {
protected FilterMethodVisitor(int api, String descriptor, Object[] args) {
super(api);
this.args = args;
this.exprConsumer = exprConsumer;
//parameters
var types = Type.getMethodType(descriptor).getArgumentTypes();
@@ -53,6 +53,10 @@ class FilterMethodVisitor extends MethodVisitor {
}
}
public AsmParseResult getResult() {
return new AsmParseResult(lambdaExpr, accessedMembers);
}
@Override
public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) {
System.out.println("local var: " + name);
@@ -67,6 +71,11 @@ class FilterMethodVisitor extends MethodVisitor {
var v = varStack.pop();
if (v instanceof ParameterExpression p) {
if (p.isInput()) {
try {
accessedMembers.add(Class.forName(owner.replace("/", ".")).getDeclaredField(name));
} catch (NoSuchFieldException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
varStack.push(new IntermediateFieldExpression(name, descriptor));
} else {
throw new RuntimeException("field insn: unsupported GETFIELD expression");
@@ -386,7 +395,6 @@ class FilterMethodVisitor extends MethodVisitor {
System.out.println("end");
super.visitEnd();
exprConsumer.accept(lambdaExpr);
}
@Override

View File

@@ -27,8 +27,9 @@ public class OptimizedAsmParser extends AsmParser{
super(function);
}
public Expression parse() throws AsmParseException {
var expr = super.parse();
public AsmParseResult parse() throws AsmParseException {
var result = super.parse();
var expr = result.getExpression();
System.out.println(expr);
expr = new TernaryRewriter().modify(expr);
@@ -37,6 +38,6 @@ public class OptimizedAsmParser extends AsmParser{
System.out.println(expr);
expr = new ExpressionOptimizerBottomUp().modify(expr);
return expr;
return new AsmParseResult(expr, result.getAccessedFields());
}
}

View File

@@ -10,7 +10,7 @@ import java.util.Optional;
import java.util.stream.Collectors;
public abstract class DbContext {
private static final String ILLEGAL_CHARACTERS = "\"'`,.";//TODO also validate this in modelbuilder/dbentity/dbfield
private static final String ILLEGAL_CHARACTERS = "\"'`,.";
public void onModelCreate(ModelBuilder mb) {
}
@@ -44,13 +44,13 @@ public abstract class DbContext {
//check for duplicate field names
for (DbEntity<? extends SerializableObject> entity : mb.getEntities()) {
var fieldNameMap = new HashMap<String, DbEntity<?>>();
var fieldNameMap = new HashMap<String, DbField<?>>();
for (DbField<?> field : entity.getFields()) {
var name = field.getName().toLowerCase();
if (fieldNameMap.containsKey(name)) {
errors.add("Duplicate DbField in entity " + entity.getTypeName() + " with name " + field.getName() + ": " + field.getName() + " and " + fieldNameMap.get(name).getName());
} else {
fieldNameMap.put(name, entity);
fieldNameMap.put(name, field);
}
}
}

View File

@@ -12,7 +12,6 @@ import jef.model.constraints.UniqueKeyConstraint;
import jef.serializable.SerializableFunction;
import jef.serializable.SerializableObject;
import jef.util.Check;
import jef.util.Util;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
@@ -24,11 +23,11 @@ import java.util.List;
import java.util.Objects;
@Getter
@Setter
@Setter(value = AccessLevel.PACKAGE)
public class DbEntity<T extends SerializableObject> {
private final String typeName;
@Setter(value = AccessLevel.PACKAGE)
private Class<T> type;
private String typeName;
// @Setter
// private Class<T> type;
private final List<DbField<?>> fields;
private String name;
private PrimaryKeyConstraint primaryKey;
@@ -39,7 +38,6 @@ public class DbEntity<T extends SerializableObject> {
//only used for migrations
DbEntity(String typeName) {
this.type = (Class) Util.tryGet(() -> Class.forName(typeName)).orElse(null);
this.typeName = typeName;
this.fields = new ArrayList<>();
var split = typeName.split("\\.");
@@ -55,7 +53,7 @@ public class DbEntity<T extends SerializableObject> {
}
DbEntity(Class<T> type, String name, List<DbField<?>> fields) {
this.type = Check.notNull(type, "type");
// this.type = Check.notNull(type, "type");
this.typeName = type.getName();
this.fields = Check.notNull(fields, "fields");
this.name = Check.notNull(name, "name");
@@ -107,7 +105,7 @@ public class DbEntity<T extends SerializableObject> {
var prop = getField(getter);
if (prop == null) {
var name = extractFieldName(getter);
var field = ReflectionUtil.getFieldsRecursive(type).stream().filter(f -> f.getName().equals(name)).findFirst().orElse(null);
var field = ReflectionUtil.getFieldsRecursive((Class<SerializableObject>) Class.forName(typeName)).stream().filter(f -> f.getName().equals(name)).findFirst().orElse(null);
if (field == null) {
throw new RuntimeException("Field not found: " + name);
}
@@ -181,6 +179,7 @@ public class DbEntity<T extends SerializableObject> {
/**
* Does not validate foreign key integrity
*
* @param primaryKey
*/
public void setPrimaryKey(PrimaryKeyConstraint primaryKey) {
@@ -211,9 +210,18 @@ public class DbEntity<T extends SerializableObject> {
}
}
private <R> String extractFieldName(SerializableFunction<T, R> getter) {
void addField(DbField<?> field) {
this.fields.add(field);
}
DbEntityBuilder<T> builder(ModelBuilder mb) {
return new DbEntityBuilder<>(mb, this);
}
<R> String extractFieldName(SerializableFunction<T, R> getter) {
try {
var expr = new AsmParser(getter).parse();
var expr = new AsmParser(getter).parse().getExpression();
if (expr.getType() != Expression.Type.INTERMEDIATE_FIELD) {
throw new RuntimeException(expr.getClass().getSimpleName() + " is not a field expression");
}
@@ -241,13 +249,13 @@ public class DbEntity<T extends SerializableObject> {
@Override
public int hashCode() {
return Objects.hash(typeName, type, fields, name, primaryKey, foreignKeys, uniqueKeys, keys, indexes);
return Objects.hash(typeName, fields, name, primaryKey, foreignKeys, uniqueKeys, keys, indexes);
}
@Override
public String toString() {
return "DbEntity{" +
"type=" + type +
"typeName=" + typeName +
", name='" + name + '\'' +
'}';
}

View File

@@ -0,0 +1,121 @@
package jef.model;
import jef.asm.AsmParser;
import jef.serializable.SerializableFunction;
import jef.serializable.SerializableObject;
import jef.util.Check;
import jef.util.Util;
import lombok.AllArgsConstructor;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
@AllArgsConstructor
public class DbEntityBuilder<T extends SerializableObject> {
private final ModelBuilder modelBuilder;
private final DbEntity<T> entity;
public DbEntityBuilder<T> name(String name) {
entity.setName(name);
return this;
}
public <R> DbFieldBuilder<R> field(SerializableFunction<T, R> getter) {
try {
var prop = entity.getField(getter);
if (prop == null) {
var name = entity.extractFieldName(getter);
var field = ReflectionUtil.getFieldsRecursive(type().get()).stream().filter(f -> f.getName().equals(name)).findFirst().orElse(null);
if (field == null) {
throw new RuntimeException("Field not found: " + name);
}
prop = new DbField<>(entity, (Class<R>) field.getType(), field);
entity.addField(prop);
}
return new DbFieldBuilder<>(prop);
} catch (Exception e) {
throw new RuntimeException("Invalid expression", e);
}
}
public <R> DbFieldBuilder<R> field(Field field) {
var prop = (DbField<R>) entity.getFields().stream().filter(e -> e.getField().equals(field)).findFirst().orElse(null);
if (prop == null) {
prop = new DbField<>(entity, (Class<R>) field.getType(), field);
entity.addField(prop);
}
return new DbFieldBuilder<>(prop);
}
public <R> DbFieldBuilder<R> field(String name, String typeName) {
var prop = (DbField<R>) entity.getFields().stream().filter(e -> e.getName().equals(name)).findFirst().orElse(null);
if (prop == null) {
prop = new DbField<>(entity, name, typeName);
entity.addField(prop);
}
return new DbFieldBuilder<>(prop);
}
//keys
public KeyBuilder<T> hasOne(SerializableFunction<T, ?> getter) {
Check.notNull(getter, "getter");
var set = new AsmParser(getter).parse().getAccessedFields();
var fields = entity.getFields().stream().filter(e -> set.contains(e.getField())).toList();
return new KeyBuilder<>(modelBuilder, entity, fields);
}
public KeyBuilder<T> hasOne(String... getterOrFieldNames) {
Check.notNull(getterOrFieldNames, "getterOrFieldNames");
var set = new HashSet<>(Arrays.asList(getterOrFieldNames));
var fields = entity.getFields().stream().filter(e -> set.contains(e.getName())).toList();
return new KeyBuilder<>(modelBuilder, entity, fields);
}
public KeyBuilder<T> hasMany(SerializableFunction<T, ?> getter) {
Check.notNull(getter, "getter");
var set = new AsmParser(getter).parse().getAccessedFields();
var fields = entity.getFields().stream().filter(e -> set.contains(e.getField())).toList();
return new KeyBuilder<>(modelBuilder, entity, fields);
}
public KeyBuilder<T> hasMany(String... getterOrFieldNames) {
Check.notNull(getterOrFieldNames, "getterOrFieldNames");
var set = new HashSet<>(Arrays.asList(getterOrFieldNames));
var fields = entity.getFields().stream().filter(e -> set.contains(e.getName())).toList();
return new KeyBuilder<>(modelBuilder, entity, fields);
}
//getters
public String name() {
return entity.getName();
}
public List<DbFieldBuilder<?>> fields() {
return (List) entity.getFields().stream().map(e -> new DbFieldBuilder(e)).toList();
}
public Optional<Class<T>> type() {
return Util.tryGet(() -> (Class<T>) Class.forName(typeName()));
}
public String typeName() {
return entity.getTypeName();
}
public String className() {
var s = entity.getTypeName().replace("$", ".").split("\\.");
return s[s.length - 1];
}
public DbEntity<T> getEntity() { //TODO make this libaray private somehow
return entity;
}
@Override
public String toString() {
return entity.toString();
}
}

View File

@@ -1,8 +1,5 @@
package jef.model;
import jef.model.constraints.IndexConstraint;
import jef.model.constraints.KeyConstraint;
import jef.model.constraints.UniqueKeyConstraint;
import jef.serializable.SerializableObject;
import jef.util.Check;
import lombok.AccessLevel;
@@ -10,9 +7,7 @@ import lombok.Getter;
import lombok.Setter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
@Getter
@@ -26,7 +21,7 @@ public class DbField<T> {
private Field field;
private boolean isModelField;
private boolean isDatabaseField;
private DbField<?> foreignKeyModelLink;
private DbField<?> exposingForeignKeyOf;
private String name;
private boolean notNull = false;
@@ -62,41 +57,14 @@ public class DbField<T> {
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.addUniqueKey(new UniqueKeyConstraint(entity, new ArrayList<>(List.of(this))));
} else if (constr.isPresent() && !unique) {
entity.dropUniqueKey(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.addIndex(new IndexConstraint(entity, new ArrayList<>(List.of(this))));
} else if (constr.isPresent() && !indexed) {
entity.dropIndex(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.addKey(new KeyConstraint(entity, new ArrayList<>(List.of(this))));
} else if (constr.isPresent() && !keyed) {
entity.dropKey(constr.get());
} //else do nothing
}
public DbField<T> setModelField(boolean modelField) {
isModelField = modelField;
return this;
@@ -136,14 +104,14 @@ public class DbField<T> {
&& entity.getName().equals(dbField.entity.getName())
&& typeName.equals(dbField.typeName)
// && Objects.equals(type, dbField.type)
&& Objects.equals(foreignKeyModelLink == null ? null : foreignKeyModelLink.getName(),
dbField.foreignKeyModelLink == null ? null : dbField.foreignKeyModelLink.getName());
&& Objects.equals(exposingForeignKeyOf == null ? null : exposingForeignKeyOf.getName(),
dbField.exposingForeignKeyOf == null ? null : dbField.exposingForeignKeyOf.getName());
}
@Override
public int hashCode() {
return Objects.hash(entity.getName(), typeName, type, field == null ? null : field.getName(), isModelField, isDatabaseField,
foreignKeyModelLink == null ? null : foreignKeyModelLink.getName(),
exposingForeignKeyOf == null ? null : exposingForeignKeyOf.getName(),
name, notNull);
}

View File

@@ -0,0 +1,85 @@
package jef.model;
import jef.model.constraints.IndexConstraint;
import jef.model.constraints.KeyConstraint;
import jef.model.constraints.UniqueKeyConstraint;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Accessors;
import java.util.ArrayList;
import java.util.List;
@RequiredArgsConstructor
public class DbFieldBuilder<T> {
private final DbField<T> field;
public DbFieldBuilder<T> name(String name) {
field.setName(name);
return this;
}
public DbFieldBuilder<T> isDatabaseField(boolean isDatabase) {
field.setDatabaseField(isDatabase);
return this;
}
public DbFieldBuilder<T> isModelField(boolean isModel) {
field.setModelField(isModel);
return this;
}
public DbFieldBuilder<T> isNotNull() {
return isNotNull(true);
}
public DbFieldBuilder<T> isNotNull(boolean notnull) {
field.setNotNull(notnull);
return this;
}
public void isUnique() {
isUnique(true);
}
public void isUnique(boolean unique) {
var entity = field.getEntity();
var constr = entity.getUniqueKeys().stream().filter(u -> u.getFields().size() == 1 && u.getFields().get(0) == field).findFirst();
if (!constr.isPresent() && unique) {
entity.addUniqueKey(new UniqueKeyConstraint(entity, new ArrayList<>(List.of(field))));
} else if (constr.isPresent() && !unique) {
entity.dropUniqueKey(constr.get());
} //else do nothing
}
public void isKey() {
isKey(true);
}
public void isKey(boolean key) {
var entity = field.getEntity();
var constr = entity.getKeys().stream().filter(u -> u.getFields().size() == 1 && u.getFields().get(0) == field).findFirst();
if (!constr.isPresent() && key) {
entity.addKey(new KeyConstraint(entity, new ArrayList<>(List.of(field))));
} else if (constr.isPresent() && !key) {
entity.dropKey(constr.get());
} //else do nothing
}
public void isIndex() {
isIndex(true);
}
public void isIndex(boolean index) {
var entity = field.getEntity();
var constr = entity.getIndexes().stream().filter(u -> u.getFields().size() == 1 && u.getFields().get(0) == field).findFirst();
if (!constr.isPresent() && index) {
entity.addIndex(new IndexConstraint(entity, new ArrayList<>(List.of(field))));
} else if (constr.isPresent() && !index) {
entity.dropIndex(constr.get());
} //else do nothing
}
public DbField<T> getField() {//TODO make this library private
return field;
}
}

View File

@@ -4,58 +4,78 @@ import jef.DbSet;
import jef.model.annotations.Clazz;
import jef.model.annotations.Transient;
import jef.serializable.SerializableObject;
import jef.util.Log;
import java.lang.reflect.Field;
import java.util.Collection;
class EntityInitializer {
static void initEntities(ModelBuilder mb, Class<? extends DbContext> context) {
for (Field ctxfield : context.getDeclaredFields()) {
if (!DbSet.class.isAssignableFrom(ctxfield.getType())) {
for (Field ctxField : context.getDeclaredFields()) {
if (!DbSet.class.isAssignableFrom(ctxField.getType())) {
continue;
}
Clazz clazzAnnotation = ctxfield.getAnnotation(Clazz.class);
Clazz clazzAnnotation = ctxField.getAnnotation(Clazz.class);
if (clazzAnnotation == null) {
throw new ModelException("DbSet " + ctxfield.getName() + " is missing the " + Clazz.class.getSimpleName() + " annotation");
throw new ModelException("DbSet " + ctxField.getName() + " is missing the " + Clazz.class.getSimpleName() + " annotation");
}
if (!SerializableObject.class.isAssignableFrom(clazzAnnotation.value())) {
throw new ModelException("DbSet " + ctxField.getName() + " has a class in its " + Clazz.class.getSimpleName() + " annotation that does not inherit from " + SerializableObject.class.getSimpleName() + ": " + clazzAnnotation.value().getSimpleName()); //TODO testcase for this
}
var dbSetClazz = (Class<? extends SerializableObject>) clazzAnnotation.value();
initEntity(mb, dbsetClazz, ctxfield.getName());
initEntity(mb, dbSetClazz, ctxField.getName(), true);
}
}
static void initEntity(ModelBuilder mb, Class<? extends SerializableObject> clazz, String name) {
var entity = mb.getOrCreateEntity(clazz);
entity.setName(name);
static void initEntity(ModelBuilder mb, Class<? extends SerializableObject> clazz, String name, boolean overrideName) {
var existingEntity = mb.getEntity(clazz);
if (existingEntity != null) {
//allow DbSets to override the name
if (overrideName) {
existingEntity.setName(name);
}
return;
}
Log.debug("Initializing entity '" + name + "' of type " + clazz.getName());
var entity = mb.entity(clazz);
entity.name(name);
var fields = ReflectionUtil.getFieldsRecursive(clazz);
for (var f : fields) {
if (f.getAnnotationsByType(Transient.class).length > 0) {
continue;
}
Log.debug("Initializing field '" + f.getName() + "' with type " + f.getType().getName());
if (Collection.class.isAssignableFrom(f.getType())) {
//find a Collection field with the same Model
//e.g. class Entity { @Clazz(Entity2.class) List<Entity2> ent; @Clazz(Entity2.class) Set<Entity2> ent2; }
var clazzAnnotation = f.getAnnotationsByType(Clazz.class);
if (clazzAnnotation.length == 0) {
var clazzAnnotation = f.getAnnotation(Clazz.class);
if (clazzAnnotation == null) {
throw new ModelException("Field " + f.getClass().getSimpleName() + "::" + f.getName() + " is missing the " + Clazz.class.getSimpleName() + " annotation");
}
var fClazz = clazzAnnotation[0].value();
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)
var fClazz = clazzAnnotation.value();
if (!SerializableObject.class.isAssignableFrom(fClazz)) {
throw new ModelException("Field " + f.getClass().getSimpleName() + "::" + f.getName() + " has a class in its " + Clazz.class.getSimpleName() + " annotation that does not inherit from " + SerializableObject.class.getSimpleName() + ": " + fClazz.getSimpleName()); //TODO testcase for this
}
var foundCollection = entity.fields().stream()
.filter(e -> Collection.class.isAssignableFrom(e.getField().getType())
&& e.getField().isModelField()
&& e.getField().getField().getAnnotationsByType(Clazz.class).length > 0
&& e.getField().getField().getAnnotationsByType(Clazz.class)[0].value() == fClazz)
.findFirst();
if (foundCollection.isPresent()) {
throw new ModelException("Model " + entity.getType().getSimpleName() + " multiple contains a 1 to N relation with type " + fClazz.getSimpleName());
throw new ModelException("Model " + entity.className() + " contains multiple 1 to N relations with type " + fClazz.getSimpleName());
}
entity.getOrCreateField(f);
entity.field(f);
initEntity(mb, (Class<? extends SerializableObject>) fClazz, fClazz.getSimpleName(), false);
} else if (SerializableObject.class.isAssignableFrom(f.getType())) {
entity.getOrCreateField(f);
entity.field(f);
initEntity(mb, (Class<? extends SerializableObject>) f.getType(), f.getType().getSimpleName(), false);
} else {
var dbField = entity.getOrCreateField(f);
var dbField = entity.field(f);
if (f.getType().isPrimitive()) {
dbField.setNotNull(true);
dbField.isNotNull();
}
}
}

View File

@@ -0,0 +1,22 @@
package jef.model;
import jef.model.constraints.ForeignKeyConstraint;
import jef.serializable.SerializableObject;
import lombok.RequiredArgsConstructor;
import java.util.List;
@RequiredArgsConstructor
public class ForeignKeyBuilder<T extends SerializableObject, R extends SerializableObject> {
private final ForeignKeyConstraint foreignKey;
public ForeignKeyBuilder<T, R> onUpdate(ForeignKeyConstraint.Action onUpdate) {
foreignKey.setOnUpdate(onUpdate);
return this;
}
public ForeignKeyBuilder<T, R> onDelete(ForeignKeyConstraint.Action onDelete) {
foreignKey.setOnDelete(onDelete);
return this;
}
}

View File

@@ -0,0 +1,63 @@
package jef.model;
import jef.model.annotations.ForeignKey;
import jef.serializable.SerializableObject;
import java.util.Locale;
class ForeignKeyExposeInitializer {//TODO testcases for this class
static void initForeignKeyExposures(ModelBuilder mb) {
var entities = mb.entities();
for (int i = 0; i < entities.size(); i++) {
var entity = entities.get(i);
initForeignKeyExposures(mb, entity);
}
}
static void initForeignKeyExposures(ModelBuilder mb, DbEntityBuilder<?> entityBuilder) {
var fields = entityBuilder.fields();
for (var f : fields) {
if (SerializableObject.class.isAssignableFrom(f.getField().getType())) {
var idFields = fields.stream()
.filter(e -> {
//ignore self
if (e.getField().getName().equals(f.getField().getName())) {
return false;
}
//match with name in annotation
var anno = e.getField().getField().getAnnotation(ForeignKey.class);
if (anno != null) {
if (anno.entity() != SerializableObject.class) { // not a foreign key exposure
return false;
}
return f.getField().getName().equals(anno.getterOrField());//TODO support getters
}
//only allow fields with same prefix
if (!e.getField().getName().startsWith(f.getField().getName())) {
return false;
}
//match id field which ends in Id or Fk
if (e.getField().getName().equals(f.getField().getName() + "Id")
|| e.getField().getName().equals(f.getField().getName() + "ID")
|| e.getField().getName().equals(f.getField().getName() + "Fk")
|| e.getField().getName().equals(f.getField().getName() + "FK")) {
return true;
}
//match id field which ends in the name of the primary key field of the referenced entity
var other = mb.getEntity(f.getField().getTypeName());
if (other == null || other.getPrimaryKey() == null) {
return false;
}
//assumption: initializing from models only has primary keys with 1 field (no composite keys)
var x = other.getPrimaryKey().getFields().get(0).getName();
x = x.substring(0, 1).toUpperCase(Locale.ROOT) + x.substring(1);
return e.getField().getName().equals(f.getField().getName() + x);
}).toList();
idFields.forEach(e -> {
e.getField().setExposingForeignKeyOf(f.getField());
});
}
}
}
}

View File

@@ -3,144 +3,179 @@ 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 jef.util.Log;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.lang.reflect.Field;
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);
var entities = mb.entities();
for (int i = 0; i < entities.size(); i++) {
var entity = entities.get(i);
initForeignKeys(mb, entity);
}
}
static void initForeignKeys(ModelBuilder mb, DbEntity<?> entity) {
var fields = ReflectionUtil.getFieldsRecursive(entity.getType());
static void initForeignKeys(ModelBuilder mb, DbEntityBuilder<?> entityBuilder) {
var entity = entityBuilder.getEntity();
var fields = ReflectionUtil.getFieldsRecursive(entityBuilder.type().orElseThrow(() -> new IllegalStateException("Class not found: " + entityBuilder.typeName())));
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<? extends SerializableObject>) clazzAnnotation.value());
if (otherEntity == null) {
EntityInitializer.initEntity(mb, (Class<? extends SerializableObject>) clazzAnnotation.value(), f.getName());
otherEntity = mb.getEntity((Class<? extends SerializableObject>) clazzAnnotation.value());
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<object> 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].value() == 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() + ")");
}
}
do1toN(mb, entityBuilder, entity, f);
} else if (SerializableObject.class.isAssignableFrom(f.getType())) {//1 to 1 relation
do1to1(mb, entityBuilder, entity, f);
}
}
}
//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);
}
private static void do1toN(ModelBuilder mb, DbEntityBuilder<?> entityBuilder, DbEntity<?> entity, Field f) {
Clazz clazzAnnotation = f.getAnnotation(Clazz.class);
if (clazzAnnotation == null) {
throw new ModelException("Collection " + entityBuilder.className() + "." + f.getName() + " is missing the " + Clazz.class.getSimpleName() + " annotation");
}
var otherEntity = mb.getEntity((Class<? extends SerializableObject>) clazzAnnotation.value());
if (otherEntity == null) {
//all types must be initialized by EntityInitializer
throw new IllegalStateException(ForeignKeyInitializer.class.getSimpleName() + ": Entity of type " + clazzAnnotation.value() + " does not exist");
// EntityInitializer.initEntity(mb, (Class<? extends SerializableObject>) clazzAnnotation.value(), f.getName());
// otherEntity = mb.getEntity((Class<? extends SerializableObject>) clazzAnnotation.value());
// PrimaryKeyInitializer.initPrimaryKeys(mb, otherEntity.builder(mb));
}
var primary = entityBuilder.getEntity().getPrimaryKey();
if (primary == null) {
throw new ModelException("Entity " + entityBuilder.className() + " is missing a primary key and therefore cannot be referenced by " + otherEntity.builder(mb).className());
}
var otherEntityF = otherEntity;
var otherFields = primary.getFields().stream()
.map(e -> {
//find list<object> 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].value().getName().equals(entity.getTypeName())).findFirst();
if (otherEntityListField.isPresent()) {
throw new ModelException("N to N relations need to explicitly defined via a mapping model ("
+ otherEntityF.builder(mb).className() + "::" + otherEntityListField.get().getTypeName() + " and "
+ entityBuilder.className() + "::" + f.getType().getName() + ")");
}
}
//find objectId in other entity (1 to N relation)
//find object in other entity (1 to N relation)
var otherEntityObjectField = otherEntityF.getFields().stream().filter(oef -> oef.getTypeName().equals(entity.getTypeName())).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 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<? extends SerializableObject>) f.getType());
if (otherEntity == null) {
EntityInitializer.initEntity(mb, (Class<? extends SerializableObject>) f.getType(), f.getName());
otherEntity = mb.getEntity((Class<? extends SerializableObject>) 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<object> 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].value() == otherEntityF.getType()).toList();
// if (entityListField.size() == 1) {
// return new FieldSearchResult(entityListField.get(0), true);
// }
// //add shadow field
// var entityField = new DbField<>(otherEntityF, f.getDeclaringClass(), null, f.getName());
// entityField.setNotNull(true);
// entityField = otherEntityF.addIfAbsent(entityField);
//find object in other entity (1 to 1 relation)
var entityObjectFields = entity.getFields().stream().filter(oef -> oef.getType() == otherEntityF.getType()).toList();
//add shadow id field
var entityIdField = new DbField<>(otherEntityF, entityBuilder.type().orElseThrow(), null, idFieldName);
entityIdField.setNotNull(true);
entityIdField.setDatabaseField(true);
entityIdField = otherEntityF.addIfAbsent(entityIdField);
// if (entityIdField.getExposingForeignKeyOf() == null) {
// entityIdField.setExposingForeignKeyOf(entityField);
// }
return new FieldSearchResult(entityIdField, true);
})
.toList();
if (otherFields.stream().anyMatch(FieldSearchResult::isCreateForeignKey)) {
otherEntity.builder(mb)
.hasOne(otherFields.stream().map(e -> e.getField().getName()).toArray(String[]::new))
.withMany(entity.getTypeName(), primary.getFields().stream().map(DbField::getName).toArray(String[]::new));
// otherEntity.addForeignKey(new ForeignKeyConstraint(otherEntity, (List) otherFields.stream().map(FieldSearchResult::getField).toList(),
// entity, primary.getFields(), ForeignKeyConstraint.Action.RESTRICT, ForeignKeyConstraint.Action.CASCADE));
}
}
private static void do1to1(ModelBuilder mb, DbEntityBuilder<?> entityBuilder, DbEntity<?> entity, Field f) {
Log.debug("Initializing foreign key for " + entityBuilder.className() + "::" + f.getName());
var otherEntity = mb.getEntity((Class<? extends SerializableObject>) f.getType());
if (otherEntity == null) {
//all types must be initialized by EntityInitializer
throw new IllegalStateException(ForeignKeyInitializer.class.getSimpleName() + ": Entity of type " + f.getType().getName() + " does not exist");
// EntityInitializer.initEntity(mb, (Class<? extends SerializableObject>) f.getType(), f.getName());
// otherEntity = mb.getEntity((Class<? extends SerializableObject>) f.getType());
// PrimaryKeyInitializer.initPrimaryKeys(mb, otherEntity.builder(mb));
}
var primary = otherEntity.getPrimaryKey();
if (primary == null) {
throw new ModelException("Entity " + otherEntity.builder(mb).className() + " is missing a primary key and therefore cannot be referenced by " + entityBuilder.className());
}
var otherEntityF = otherEntity;
var otherFields = primary.getFields().stream()
.map(otherPrimaryField -> {
// //find list<object> 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].value().getName().equals(otherEntityF.getTypeName())).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.getTypeName().equals(otherEntityF.getTypeName())).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);
}
//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);
var field = new DbField<>(entity, otherPrimaryField.getType(), null, idFieldName);
field.setExposingForeignKeyOf(entity.getField(f.getName()));
field = entity.addIfAbsent(field);
// if (entityListField.size() == 1) {
//// field.setForeignKeyObjectField(entityListField.get(0));
//// entityListField.get(0).setForeignKeyObjectField(field);
// } else
// if (entityObjectFields.size() == 1) {
// field.setExposingForeignKeyOf(entityObjectFields.get(0));
// entityObjectFields.get(0).setForeignKeyObjectField(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));
}
}
})
.toList();
if (otherFields.stream().anyMatch(FieldSearchResult::isCreateForeignKey)) {
entityBuilder
.hasOne(otherFields.stream().map(e -> e.getField().getName()).toArray(String[]::new))
.withOne(otherEntity.getTypeName(), primary.getFields().stream().map(DbField::getName).toArray(String[]::new));
// entity.addForeignKey(new ForeignKeyConstraint(entity, (List) otherFields.stream().map(FieldSearchResult::getField).toList(),
// otherEntity, primary.getFields(), ForeignKeyConstraint.Action.RESTRICT, ForeignKeyConstraint.Action.CASCADE));
}
}

View File

@@ -0,0 +1,180 @@
package jef.model;
import jef.asm.AsmParser;
import jef.model.constraints.ForeignKeyConstraint;
import jef.model.constraints.IndexConstraint;
import jef.model.constraints.KeyConstraint;
import jef.model.constraints.PrimaryKeyConstraint;
import jef.model.constraints.UniqueKeyConstraint;
import jef.serializable.SerializableFunction;
import jef.serializable.SerializableObject;
import jef.util.Check;
import lombok.RequiredArgsConstructor;
import java.lang.reflect.Field;
import java.util.List;
import java.util.stream.IntStream;
@RequiredArgsConstructor
public class KeyBuilder<T extends SerializableObject> {
private final ModelBuilder modelBuilder;
private final DbEntity<T> entity;
private final List<DbField<?>> fields;
public <R extends SerializableObject> ForeignKeyBuilder<T, R> withOne(SerializableFunction<T, R> getter) {
Check.notNull(getter, "getter");
var set = new AsmParser(getter).parse().getAccessedFields();
// if (set.isEmpty()) throw new IllegalArgumentException("no fields found");
// else if (set.size() > 1) throw new IllegalArgumentException("more than 1 field found");
// var refFields = entity.getFields().stream().filter(e -> set.contains(e.getField())).toList();
// var refEntities = refFields.stream().map(e -> modelBuilder.getEntity(e.getTypeName())).toList();
// var existingFk = entity.getForeignKeys().stream().filter(fk -> fk.getEntity() == this.entity
// && fk.getFields().equals(this.fields)
// && fk.getReferencedEntity() == refEntities.get(0)
// && fk.getReferencedFields().equals(refFields))
// .findFirst().orElse(null);
// if (existingFk == null) {
// existingFk = new ForeignKeyConstraint(this.entity, this.fields, refEntities.get(0), refFields, ForeignKeyConstraint.Action.RESTRICT, ForeignKeyConstraint.Action.CASCADE);
// this.entity.addForeignKey(existingFk);
// }
// return new ForeignKeyBuilder<>(existingFk);
// var rClassName = getter.getClass().
return withOne("", set.stream().map(Field::getName).toArray(String[]::new));
}
public <R extends SerializableObject> ForeignKeyBuilder<T, R> withOne(String referencedClass, String... getterOrFieldNames) {
Check.notNull(getterOrFieldNames, "getterOrFieldNames");
// var set = new HashSet<>(Arrays.asList(getterOrFieldNames));
// if (set.isEmpty()) throw new IllegalArgumentException("no fields found");
// else if (set.size() > 1) throw new IllegalArgumentException("more than 1 field found");
// var refFields = entity.getFields().stream().filter(e -> set.contains(e.getName())).toList();
// var refEntities = refFields.stream().map(e -> modelBuilder.getEntity(e.getTypeName())).toList();
var refEntities = List.of(modelBuilder.getEntity(referencedClass));
var refFields = IntStream.range(0, getterOrFieldNames.length)
.mapToObj(i -> {
// var field = fields.get(i);
// if (field.getExposingForeignKeyOf() != null) {
// field = field.getExposingForeignKeyOf();
// }
return refEntities.get(0).getField(getterOrFieldNames[i]);
})
.toList();
// var refEntities = refFields.stream().map(e -> e.getEntity()).toList();
var existingFk = entity.getForeignKeys().stream().filter(fk -> fk.getEntity() == this.entity
&& fk.getFields().equals(this.fields)
&& fk.getReferencedEntity() == refEntities.get(0)
&& fk.getReferencedFields().equals(refFields))
.findFirst().orElse(null);
if (existingFk == null) {
existingFk = new ForeignKeyConstraint(this.entity, this.fields, refEntities.get(0), (List) refFields, ForeignKeyConstraint.Action.RESTRICT, ForeignKeyConstraint.Action.CASCADE);
this.entity.addForeignKey(existingFk);
}
return new ForeignKeyBuilder<>(existingFk);
}
public <R extends SerializableObject> ForeignKeyBuilder<T, R> withMany(SerializableFunction<T, R> getter) {
Check.notNull(getter, "getter");
var set = new AsmParser(getter).parse().getAccessedFields();
// if (set.isEmpty()) throw new IllegalArgumentException("no fields found");
// else if (set.size() > 1) throw new IllegalArgumentException("more than 1 field found");
// var refFields = entity.getFields().stream().filter(e -> set.contains(e.getField())).toList();
// var refEntities = refFields.stream().map(e -> modelBuilder.getEntity(e.getTypeName())).toList();
// var existingFk = entity.getForeignKeys().stream().filter(fk -> fk.getEntity() == this.entity
// && fk.getFields().equals(this.fields)
// && fk.getReferencedEntity() == refEntities.get(0)
// && fk.getReferencedFields().equals(refFields))
// .findFirst().orElse(null);
// if (existingFk == null) {
// existingFk = new ForeignKeyConstraint(this.entity, this.fields, refEntities.get(0), refFields, ForeignKeyConstraint.Action.RESTRICT, ForeignKeyConstraint.Action.CASCADE);
// this.entity.addForeignKey(existingFk);
// }
// return new ForeignKeyBuilder<>(existingFk);
return withMany("", set.stream().map(Field::getName).toArray(String[]::new));
}
public <R extends SerializableObject> ForeignKeyBuilder<T, R> withMany(String referencedClass, String... getterOrFieldNames) {
Check.notNull(getterOrFieldNames, "getterOrFieldNames");
// var set = new HashSet<>(Arrays.asList(getterOrFieldNames));
// var refFields = entity.getFields().stream().filter(e -> set.contains(e.getName())).toList();
// var refEntities = refFields.stream().map(e -> modelBuilder.getEntity(e.getTypeName())).toList();
var refEntities = List.of(modelBuilder.getEntity(referencedClass));
var refFields = IntStream.range(0, getterOrFieldNames.length)
.mapToObj(i -> {
// var field = fields.get(i);
// if (field.getExposingForeignKeyOf() != null) {
// field = field.getExposingForeignKeyOf();
// }
// var type = (Class<? extends SerializableObject>) field.getType();
// return modelBuilder.getEntity(type).getField(getterOrFieldNames[i]);
return refEntities.get(0).getField(getterOrFieldNames[i]);
})
.toList();
// var refEntities = refFields.stream().map(e -> e.getEntity()).toList();
var existingFk = entity.getForeignKeys().stream().filter(fk -> fk.getEntity() == this.entity
&& fk.getFields().equals(this.fields)
&& fk.getReferencedEntity() == refEntities.get(0)
&& fk.getReferencedFields().equals(refFields))
.findFirst().orElse(null);
if (existingFk == null) {
existingFk = new ForeignKeyConstraint(this.entity, this.fields, refEntities.get(0), (List) refFields, ForeignKeyConstraint.Action.RESTRICT, ForeignKeyConstraint.Action.CASCADE);
this.entity.addForeignKey(existingFk);
}
return new ForeignKeyBuilder<>(existingFk);
}
public KeyBuilder<T> notNull(boolean notNull) {
//TODO
return this;
}
public void isUnique() {
isUnique(true);
}
public void isUnique(boolean unique) {
var key = new UniqueKeyConstraint(entity, fields);
if (unique) {
entity.addUniqueKey(key);
} else {
entity.dropUniqueKey(key);
}
}
public void isPrimaryKey() {
isPrimaryKey(true);
}
public void isPrimaryKey(boolean primary) {//TODO foreign key integrity
if (primary) {
entity.setPrimaryKey(new PrimaryKeyConstraint(entity, fields));
} else {
entity.setPrimaryKey(null);
}
}
public void isKey() {
isKey(true);
}
public void isKey(boolean key) {
var k = new KeyConstraint(entity, fields);
if (key) {
entity.addKey(k);
} else {
entity.dropKey(k);
}
}
public void isIndex() {
isIndex(true);
}
public void isIndex(boolean index) {
var i = new IndexConstraint(entity, fields);
if (index) {
entity.addIndex(i);
} else {
entity.dropIndex(i);
}
}
}

View File

@@ -18,6 +18,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public class ModelBuilder {
private static final List<AnnotationProcessor> annotationProcessors = new ArrayList<>();
@@ -48,6 +49,7 @@ public class ModelBuilder {
var mb = new ModelBuilder(new ArrayList<>());
EntityInitializer.initEntities(mb, context);
PrimaryKeyInitializer.initPrimaryKeys(mb);
ForeignKeyExposeInitializer.initForeignKeyExposures(mb);
ForeignKeyInitializer.initForeignKeys(mb);
for (AnnotationProcessor processor : annotationProcessors) {
@@ -86,6 +88,10 @@ public class ModelBuilder {
return Collections.unmodifiableList(entities);
}
public List<DbEntityBuilder<? extends SerializableObject>> entities() {
return entities.stream().map(e -> new DbEntityBuilder<>(this, e)).collect(Collectors.toUnmodifiableList());
}
/**
* Returns the database model for the requested class or null if not present.
*
@@ -117,9 +123,9 @@ public class ModelBuilder {
* @param <T> the type of model class
* @return the DbEntity for the requested class or the newly created empty DbEntity if none existed.
*/
public <T extends SerializableObject> DbEntity<T> getOrCreateEntity(Class<T> clazz) {
public <T extends SerializableObject> DbEntityBuilder<T> entity(Class<T> clazz) {
Check.notNull(clazz, "clazz");
return getOrCreateEntity(clazz.getName());
return entity(clazz.getName());
}
/**
@@ -129,14 +135,14 @@ public class ModelBuilder {
* @param <T> the type of model class
* @return the DbEntity for the requested class or the newly created empty DbEntity if none existed.
*/
public <T extends SerializableObject> DbEntity<T> getOrCreateEntity(String typeName) {
public <T extends SerializableObject> DbEntityBuilder<T> entity(String typeName) {
Check.notNull(typeName, "typeName");
var entity = (DbEntity<T>) getEntity(typeName);
if (entity == null) {
entity = new DbEntity<>(typeName);
entities.add(entity);
}
return entity;
return new DbEntityBuilder<>(this, entity);
}
/**
@@ -168,7 +174,7 @@ public class ModelBuilder {
var old = this.entities.get(i);
var entity = (DbEntity<?>) new DbEntity(old.getTypeName());
entity.setName(old.getName());
entity.setType((Class) old.getType());
entity.setTypeName(old.getTypeName());
//add fields
old.getFields().stream().map(e -> {
@@ -183,9 +189,9 @@ public class ModelBuilder {
.forEach(entity::addIfAbsent);
//apply exposed foreign keys
old.getFields().stream().filter(e -> e.getForeignKeyModelLink() != null).forEach(e -> {
old.getFields().stream().filter(e -> e.getExposingForeignKeyOf() != null).forEach(e -> {
var nf = entity.getFields().stream().filter(f -> f.getName().equals(e.getName())).findFirst().get(); //get(): should always be there
nf.setForeignKeyModelLink(old.getFields().stream().filter(f -> f.getName().equals(e.getForeignKeyModelLink().getName())).findFirst().get()); //get(): should always be there
nf.setExposingForeignKeyOf(old.getFields().stream().filter(f -> f.getName().equals(e.getExposingForeignKeyOf().getName())).findFirst().get()); //get(): should always be there
});
entity.setName(old.getName());

View File

@@ -2,22 +2,21 @@ 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);
var entities = mb.entities();
for (int i = 0; i < entities.size(); i++) {
var entity = entities.get(i);
initPrimaryKeys(mb, entity);
}
}
static void initPrimaryKeys(ModelBuilder mb, DbEntity<?> entity) {
var fields = ReflectionUtil.getFieldsRecursive(entity.getType());
static void initPrimaryKeys(ModelBuilder mb, DbEntityBuilder<?> entity) {
var fields = ReflectionUtil.getFieldsRecursive(entity.type().get());
var idFields = new ArrayList<Field>();
//search for fields with @Id annotation
@@ -56,8 +55,8 @@ class PrimaryKeyInitializer {
}
if (!idFields.isEmpty()) {
var dbfields = idFields.stream().map(entity::getField).toList();
entity.setPrimaryKey(new PrimaryKeyConstraint(entity, (List) dbfields));
var dbfields = idFields.stream().map(e -> entity.field(e).getField().getName()).toList();
entity.hasOne(dbfields.toArray(String[]::new)).isPrimaryKey(true);
}
}
}

View File

@@ -1,7 +1,6 @@
package jef.model.annotations.processors;
import jef.model.DbEntity;
import jef.model.DbField;
import jef.model.DbEntityBuilder;
import jef.model.ModelBuilder;
import jef.model.ModelException;
import jef.model.annotations.ForeignKey;
@@ -22,61 +21,62 @@ public class ForeignKeyProcessor implements AnnotationProcessor {
@Override
public void apply(ModelBuilder mb) {
for (DbEntity<? extends SerializableObject> entity : mb.getEntities()) {
for (var entity : mb.entities()) {
//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];
for (var field : entity.fields()) {
if (field.getField().isModelField() && field.getField().getField().getAnnotationsByType(ForeignKey.class).length > 0) {
var anno = field.getField().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());
var refEntity = exposeForeignKey ? entity.getEntity() : 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() + ")");
+ " in " + entity.className() + "::" + field.getField().getName() + ")");
}
var refEntityBuilder = mb.entity(refEntity.getTypeName());
Field refClassField;
try {
refClassField = getField(refEntity, anno.getterOrField());
refClassField = getField(refEntityBuilder, anno.getterOrField());
} catch (ModelException e) {
throw new ModelException(e.getMessage() + " (via @" + ForeignKey.class.getSimpleName()
+ " in " + entity.getType().getSimpleName() + "::" + field.getField().getName() + ")");
+ " in " + entity.className() + "::" + field.getField().getName() + ")");
}
var refField = refEntity.getField(refClassField);
if (exposeForeignKey) {
field.setForeignKeyModelLink(refField);
refField.setForeignKeyModelLink(field);
// field.getField().setExposingForeignKeyOf(refField);
refField.setExposingForeignKeyOf(field.getField());
continue;
}
//check for primary key
if (refEntity.getPrimaryKey() == null) {
throw new ModelException("Entity " + refEntity.getType().getSimpleName() + " does not have a primary key and can "
throw new ModelException("Entity " + refEntityBuilder.className() + " does not have a primary key and can "
+ "therefore not be referenced (via @" + ForeignKey.class.getSimpleName()
+ " in " + entity.getType().getSimpleName() + "::" + field.getField().getName() + ")");
+ " in " + entity.className() + "::" + 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()
throw new ModelException(refEntityBuilder.className() + "::" + refField.getField().getName()
+ " is not equal to the primary key of entity " + refEntityBuilder.className()
+ " (" + 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() + ")");
+ " in " + entity.className() + "::" + field.getField().getName() + ")");
}
entity.addForeignKey(new ForeignKeyConstraint(entity, List.of(field), refEntity, List.of(refField), anno.onUpdate(), anno.onDelete()));
entity.getEntity().addForeignKey(new ForeignKeyConstraint(entity.getEntity(), List.of(field.getField()), refEntity, List.of(refField), anno.onUpdate(), anno.onDelete()));
}
}
}
}
private Field getField(DbEntity<? extends SerializableObject> entity, String fieldOrGetter) {
private Field getField(DbEntityBuilder<? extends SerializableObject> entity, String fieldOrGetter) {
Method getter = null;
try {
getter = entity.getType().getDeclaredMethod(fieldOrGetter);
getter = entity.type().get().getDeclaredMethod(fieldOrGetter);
} catch (NoSuchMethodException e) {
}
@@ -84,15 +84,15 @@ public class ForeignKeyProcessor implements AnnotationProcessor {
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);
field = entity.type().get().getDeclaredField(name);
} else {
field = entity.getType().getDeclaredField(fieldOrGetter);
field = entity.type().get().getDeclaredField(fieldOrGetter);
}
} catch (NoSuchFieldException e) {
}
if (field == null) {
throw new ModelException("Cannot find getter/field " + entity.getType().getSimpleName() + "::" + fieldOrGetter);
throw new ModelException("Cannot find getter/field " + entity.className() + "::" + fieldOrGetter);
}
return field;
}

View File

@@ -1,7 +1,9 @@
package jef.model.annotations.processors;
import jef.model.DbEntity;
import jef.model.DbEntityBuilder;
import jef.model.DbField;
import jef.model.DbFieldBuilder;
import jef.model.annotations.Index;
import jef.model.constraints.IndexConstraint;
import jef.serializable.SerializableObject;
@@ -17,8 +19,8 @@ public class IndexProcessor extends KeyProcessorBase<IndexConstraint, Index> {
}
@Override
protected IndexConstraint initConstraint(DbEntity<? extends SerializableObject> entity, List<DbField<?>> fields) {
return new IndexConstraint(entity, fields);
protected IndexConstraint initConstraint(DbEntityBuilder<? extends SerializableObject> entity, List<DbFieldBuilder<?>> fields) {
return new IndexConstraint(entity.getEntity(), (List)fields.stream().map(DbFieldBuilder::getField).toList());
}
@Override

View File

@@ -1,7 +1,9 @@
package jef.model.annotations.processors;
import jef.model.DbEntity;
import jef.model.DbEntityBuilder;
import jef.model.DbField;
import jef.model.DbFieldBuilder;
import jef.model.annotations.Key;
import jef.model.constraints.KeyConstraint;
import jef.serializable.SerializableObject;
@@ -17,8 +19,8 @@ public class KeyProcessor extends KeyProcessorBase<KeyConstraint, Key> {
}
@Override
protected KeyConstraint initConstraint(DbEntity<? extends SerializableObject> entity, List<DbField<?>> fields) {
return new KeyConstraint(entity, fields);
protected KeyConstraint initConstraint(DbEntityBuilder<? extends SerializableObject> entity, List<DbFieldBuilder<?>> fields) {
return new KeyConstraint(entity.getEntity(), (List)fields.stream().map(DbFieldBuilder::getField).toList());
}
@Override

View File

@@ -1,7 +1,8 @@
package jef.model.annotations.processors;
import jef.model.DbEntity;
import jef.model.DbEntityBuilder;
import jef.model.DbField;
import jef.model.DbFieldBuilder;
import jef.model.ModelBuilder;
import jef.model.ModelException;
import jef.serializable.SerializableObject;
@@ -21,7 +22,7 @@ abstract class KeyProcessorBase<K, T extends Annotation> implements AnnotationPr
this.annotationClass = annotationClass;
}
protected abstract K initConstraint(DbEntity<? extends SerializableObject> entity, List<DbField<?>> fields);
protected abstract K initConstraint(DbEntityBuilder<? extends SerializableObject> entity, List<DbFieldBuilder<?>> fields);
protected abstract void addConstraint(K constr);
@@ -29,16 +30,16 @@ abstract class KeyProcessorBase<K, T extends Annotation> implements AnnotationPr
@Override
public void apply(ModelBuilder mb) {
for (DbEntity<? extends SerializableObject> entity : mb.getEntities()) {
for (DbEntityBuilder<? extends SerializableObject> entity : mb.entities()) {
//class annotation
var classAnno = entity.getType().getAnnotationsByType(annotationClass);
var classAnno = entity.type().get().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);
var dbfield = (DbFieldBuilder<?>) entity.field(field);
if (dbfield == null) {
throw new ModelException("DbField with field " + field.getName() + " not found in " + entity.getType().getSimpleName());
throw new ModelException("DbField with field " + field.getName() + " not found in " + entity.className());
}
return dbfield;
}).toList();
@@ -46,11 +47,11 @@ abstract class KeyProcessorBase<K, T extends Annotation> implements AnnotationPr
}
//annotation on fields
for (DbField<?> field : entity.getFields()) {
if (field.getField() != null && field.getField().getAnnotationsByType(annotationClass).length > 0) {
var dbfield = entity.getField(field.getField());
for (DbFieldBuilder<?> field : entity.fields()) {
if (field.getField().getField() != null && field.getField().getField().getAnnotationsByType(annotationClass).length > 0) {
var dbfield = entity.field(field.getField().getField());
if (dbfield == null) {
throw new ModelException("DbField with field " + field.getName() + " not found in " + entity.getType().getSimpleName());
throw new ModelException("DbField with field " + field.getField().getName() + " not found in " + entity.className());
}
addConstraint(initConstraint(entity, List.of(dbfield)));
}
@@ -58,26 +59,26 @@ abstract class KeyProcessorBase<K, T extends Annotation> implements AnnotationPr
}
}
private Field getField(DbEntity<? extends SerializableObject> entity, String fieldOrGetter) {
private Field getField(DbEntityBuilder<? extends SerializableObject> entity, String fieldOrGetter) {
Method getter = null;
try {
getter = entity.getType().getDeclaredMethod(fieldOrGetter);
getter = entity.type().get().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);
var name = getter.getName().substring(3, 4).toLowerCase(Locale.ROOT) + getter.getName().substring(4); //TODO HACK
field = entity.type().get().getDeclaredField(name);
} else {
field = entity.getType().getDeclaredField(fieldOrGetter);
field = entity.type().get().getDeclaredField(fieldOrGetter);
}
} catch (NoSuchFieldException e) {
}
if (field == null) {
throw new ModelException("Cannot find getter/field '" + fieldOrGetter + "' in " + entity.getType().getSimpleName());
throw new ModelException("Cannot find getter/field '" + fieldOrGetter + "' in " + entity.className());
}
return field;
}

View File

@@ -1,13 +1,14 @@
package jef.model.annotations.processors;
import jef.model.DbEntity;
import jef.model.DbField;
import jef.model.DbEntityBuilder;
import jef.model.DbFieldBuilder;
import jef.model.annotations.Unique;
import jef.model.constraints.UniqueKeyConstraint;
import jef.serializable.SerializableObject;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.stream.Collectors;
public class UniqueProcessor extends KeyProcessorBase<UniqueKeyConstraint, Unique> {
public static final UniqueProcessor INSTANCE = new UniqueProcessor();
@@ -17,8 +18,8 @@ public class UniqueProcessor extends KeyProcessorBase<UniqueKeyConstraint, Uniqu
}
@Override
protected UniqueKeyConstraint initConstraint(DbEntity<? extends SerializableObject> entity, List<DbField<?>> fields) {
return new UniqueKeyConstraint(entity, fields);
protected UniqueKeyConstraint initConstraint(DbEntityBuilder<? extends SerializableObject> entity, List<DbFieldBuilder<?>> fields) {
return new UniqueKeyConstraint(entity.getEntity(), (List)fields.stream().map(DbFieldBuilder::getField).toList());
}
@Override

View File

@@ -2,25 +2,28 @@ package jef.model.constraints;
import jef.model.DbEntity;
import jef.model.DbField;
import jef.util.Check;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Getter
@Setter
public class ForeignKeyConstraint extends ConstraintBase {
private final DbEntity<?> referencedEntity;
private final List<DbField<?>> referencedFields;
private final Action onUpdate;
private final Action onDelete;
private Action onUpdate;
private Action onDelete;
public ForeignKeyConstraint(DbEntity<?> entity, List<DbField<?>> fields, DbEntity<?> referencedEntity, List<DbField<?>> referencedFields, Action onUpdate, Action onDelete) {
super(entity, fields);
this.referencedEntity = referencedEntity;
this.referencedFields = referencedFields;
this.onUpdate = onUpdate;
this.onDelete = onDelete;
this.referencedEntity = Check.notNull(referencedEntity, "referencedEntity");
this.referencedFields = Check.notNull(referencedFields, "referencedFields");
this.onUpdate = Check.notNull(onUpdate, "onUpdate");
this.onDelete = Check.notNull(onDelete, "onDelete");
}
@Override

View File

@@ -2,6 +2,7 @@ package jef.model.migration.creator;
import jef.model.DbContext;
import jef.model.DbEntity;
import jef.model.DbEntityBuilder;
import jef.model.DbField;
import jef.model.ModelBuilder;
import jef.model.constraints.ForeignKeyConstraint;
@@ -40,29 +41,29 @@ public class ModelBuilderGenerator {
var indent = " ";
imports.add(DbContext.class);
imports.add(ModelBuilder.class);
imports.add(DbEntity.class);
imports.add(DbEntityBuilder.class);
var java = ""
+ "public class " + name + "Snapshot extends DbContext {\n"
+ " @Override\n"
+ " public void onModelCreate(ModelBuilder mb) {\n"
+ indent + "DbEntity entity;\n"
+ indent + "DbEntity referencedEntity;\n";
+ indent + "DbEntityBuilder entity;\n"
+ indent + "DbEntityBuilder referencedEntity;\n";
for (DbEntity<? extends SerializableObject> entity : mb.getEntities()) {
java += indent + "entity = mb.getOrCreateEntity(\"" + entity.getTypeName() + "\");\n"
+ indent + "entity.setName(\"" + entity.getName() + "\");\n";
java += indent + "mb.entity(\"" + entity.getTypeName() + "\")\n"
+ indent + " .name(\"" + entity.getName() + "\");\n";
for (DbField<?> field : entity.getFields()) {
java += indent + "entity.getOrCreateField(\"" + field.getName() + "\", \"" + field.getTypeName() + "\")"
+ (field.isNotNull() ? "\n" + indent + " .setNotNull(true)" : "")
+ "\n" + indent + " .setDatabaseField(" + field.isDatabaseField() + ")"
+ "\n" + indent + " .setModelField(" + field.isModelField() + ")"
+ ";\n";
java += indent + "mb.entity(\"" + entity.getTypeName() + "\")\n"
+ indent + " .field(\"" + field.getName() + "\", \"" + field.getTypeName() + "\")"
+ (field.isNotNull() ? "\n" + indent + " .isNotNull()" : "")
+ "\n" + indent + " .isDatabaseField(" + field.isDatabaseField() + ")"
+ "\n" + indent + " .isModelField(" + field.isModelField() + ");";
}
if (entity.getPrimaryKey() != null) {
imports.add(List.class);
imports.add(PrimaryKeyConstraint.class);
java += indent + "entity.setPrimaryKey(new PrimaryKeyConstraint(entity, List.of(\n"
+ indent + " " + entity.getPrimaryKey().getFields().stream().map(f -> "entity.getField(\"" + f.getName() + "\")").collect(Collectors.joining(",\n ")) + "\n"
+ indent + " )));\n";
java += indent + "mb.entity(\"" + entity.getTypeName() + "\")\n"
+ indent + " .hasOne(" + entity.getPrimaryKey().getFields().stream().map(f -> "\"" + f.getName() + "\"").collect(Collectors.joining(", ")) + ")\n"
+ indent + " .isPrimaryKey();\n";
}
java += "\n";
}
@@ -71,40 +72,29 @@ public class ModelBuilderGenerator {
continue;
}
java += indent + "entity = mb.getOrCreateEntity(\"" + entity.getTypeName() + "\");\n";
for (ForeignKeyConstraint foreignKey : entity.getForeignKeys()) {
imports.add(List.class);
imports.add(ForeignKeyConstraint.class);
imports.add(ForeignKeyConstraint.Action.class);
java += indent + "referencedEntity = mb.getEntity(\"" + foreignKey.getReferencedEntity().getTypeName() + "\");\n"
+ indent + "entity.addForeignKey(new ForeignKeyConstraint(entity, List.of(\n"
+ indent + " " + foreignKey.getFields().stream().map(f -> "entity.getField(\"" + f.getName() + "\")").collect(Collectors.joining(",\n " + indent)) + "\n"
+ indent + " ),\n"
+ indent + " referencedEntity, List.of(\n"
+ indent + " " + foreignKey.getReferencedFields().stream().map(f -> "referencedEntity.getField(\"" + f.getName() + "\")").collect(Collectors.joining(",\n " + indent)) + "\n"
+ indent + " ),\n"
+ indent + " ForeignKeyConstraint.Action." + foreignKey.getOnUpdate().name() + ", ForeignKeyConstraint.Action." + foreignKey.getOnDelete().name() + "));\n";
//TODO hasOne/hasMany/withOne/WithMany
java += indent + "mb.entity(\"" + entity.getTypeName() + "\")\n"
+ indent + " .hasOne(" + foreignKey.getFields().stream().map(f -> "\"" + f.getName() + "\"").collect(Collectors.joining(", " + indent)) + ")\n"
+ indent + " .withOne(\"" + foreignKey.getReferencedEntity().getTypeName() + "\", " + foreignKey.getReferencedFields().stream().map(f -> "\"" + f.getName() + "\"").collect(Collectors.joining(", ")) + ")\n"
+ indent + " .onUpdate(ForeignKeyConstraint.Action." + foreignKey.getOnUpdate().name() + ")\n"
+ indent + " .onDelete(ForeignKeyConstraint.Action." + foreignKey.getOnDelete().name() + ");\n";
}
for (UniqueKeyConstraint uniqueKey : entity.getUniqueKeys()) {
imports.add(List.class);
imports.add(UniqueKeyConstraint.class);
java += indent + "entity.addUniqueKey(new UniqueKeyConstraint(entity, List.of(\n"
+ indent + " " + uniqueKey.getFields().stream().map(f -> "entity.getField(\"" + f.getName() + "\")").collect(Collectors.joining(",\n " + indent)) + "\n"
+ indent + " )));\n";
java += indent + "mb.entity(\"" + entity.getTypeName() + "\")\n"
+ indent + " .hasOne(" + uniqueKey.getFields().stream().map(f -> "\"" + f.getName() + "\"").collect(Collectors.joining(", ")) + ")\n"
+ indent + " .isUnique();\n";
}
for (KeyConstraint key : entity.getKeys()) {
imports.add(List.class);
imports.add(KeyConstraint.class);
java += indent + "entity.addKey(new KeyConstraint(entity, List.of(\n"
+ indent + " " + key.getFields().stream().map(f -> "entity.getField(\"" + f.getName() + "\")").collect(Collectors.joining(",\n " + indent)) + "\n"
+ indent + " )));\n";
java += indent + "mb.entity(\"" + entity.getTypeName() + "\")\n"
+ indent + " .hasOne(" + key.getFields().stream().map(f -> "\"" + f.getName() + "\"").collect(Collectors.joining(", ")) + ")\n"
+ indent + " .isKey();\n";
}
for (IndexConstraint index : entity.getIndexes()) {
imports.add(List.class);
imports.add(IndexConstraint.class);
java += indent + "entity.addIndex(new IndexConstraint(entity, List.of(\n"
+ indent + " " + index.getFields().stream().map(f -> "entity.getField(\"" + f.getName() + "\")").collect(Collectors.joining(",\n " + indent)) + "\n"
+ indent + " )));\n";
java += indent + "mb.entity(\"" + entity.getTypeName() + "\")\n"
+ indent + " .hasOne(" + index.getFields().stream().map(f -> "\"" + f.getName() + "\"").collect(Collectors.joining(", ")) + ")\n"
+ indent + " .isIndex();\n";
}
}
java += " }\n"

View File

@@ -2,15 +2,11 @@ package jef.operations;
import jef.Queryable;
import jef.asm.AsmParseException;
import jef.asm.AsmParser;
import jef.asm.OptimizedAsmParser;
import jef.expressions.Expression;
import jef.expressions.SelectExpression;
import jef.expressions.WhereExpression;
import jef.expressions.modifier.ExpressionOptimizerBottomUp;
import jef.expressions.modifier.IConst0Fixer;
import jef.expressions.modifier.TableAliasInjector;
import jef.expressions.modifier.TernaryRewriter;
import jef.expressions.selectable.DatabaseSelectAllExpression;
import jef.serializable.SerializablePredicate;
@@ -31,18 +27,13 @@ public class FilterOp<T extends Serializable> implements Queryable<T>, Operation
var parser = new OptimizedAsmParser(predicate);
Expression expr;
try {
expr = parser.parse();
expr = parser.parse().getExpression();
} catch (AsmParseException e) {
throw new RuntimeException(e);
}
expr = new TableAliasInjector(getTableAlias()).modify(expr);//TODO this does not work together with expression optimization
this.predicateExpr = expr;
//TODO optimize whole expression
// this.finalExpr = new ExpressionOptimizerBottomUp().modify(
// new WhereExpression(
// new SelectExpression(List.of(DatabaseSelectAllExpression.INSTANCE), queryable.getExpression(), getTableAlias()),
// predicateExpr));
}
@Override

View File

@@ -61,7 +61,7 @@ public class SortOp<T extends Serializable> implements Queryable<T> {
var parser = new AsmParser(fieldSelector);
Expression expr;
try {
expr = parser.parse();
expr = parser.parse().getExpression();
} catch (AsmParseException e) {
throw new RuntimeException(e);
}

View File

@@ -0,0 +1,13 @@
package jef.util;
public class Log {
// private static Log INSTANCE = new Log();
public static void debug(String s) {
System.out.println(s);
}
private Log() {
}
}

View File

@@ -15,38 +15,38 @@ public class OptimizedAsmParserTest {
public void testTrue() throws AsmParseException {
String act;
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> true).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> true).parse().getExpression().toString();
Assertions.assertEquals("1", act);
}
@Test
public void testCompareWithEntityMember() throws AsmParseException {
String act;
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 1).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 1).parse().getExpression().toString();
Assertions.assertEquals("`i` = 1", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i != 1).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i != 1).parse().getExpression().toString();
Assertions.assertEquals("`i` <> 1", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i < 1).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i < 1).parse().getExpression().toString();
Assertions.assertEquals("`i` < 1", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i > 1).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i > 1).parse().getExpression().toString();
Assertions.assertEquals("`i` > 1", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i <= 1).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i <= 1).parse().getExpression().toString();
Assertions.assertEquals("`i` <= 1", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i >= 1).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i >= 1).parse().getExpression().toString();
Assertions.assertEquals("`i` >= 1", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 1337).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 1337).parse().getExpression().toString();
Assertions.assertEquals("`i` = 1337", act);
}
@@ -54,12 +54,12 @@ public class OptimizedAsmParserTest {
public void testContainsWithEntityMember() throws AsmParseException {
var s = List.of(1, 3);
String act;
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> s.contains(e.i)).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> s.contains(e.i)).parse().getExpression().toString();
Assertions.assertEquals("`i` IN (1, 3)", act);
//TODO
// act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> List.of(1, 3).contains(e.i)).parse().toString();
// act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> List.of(1, 3).contains(e.i)).parse().getExpression().toString();
// Assertions.assertEquals("`i` IN (1, 3)", act);
}
@@ -67,23 +67,23 @@ public class OptimizedAsmParserTest {
public void testComplexExpression() throws AsmParseException {
String act;
var s = List.of(1, 3);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> s.contains(e.i) && e.i == 1337).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> s.contains(e.i) && e.i == 1337).parse().getExpression().toString();
Assertions.assertEquals("`i` IN (1, 3) AND `i` = 1337", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> s.contains(e.i) && e.i == 1337 && e.i == 420).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> s.contains(e.i) && e.i == 1337 && e.i == 420).parse().getExpression().toString();
Assertions.assertEquals("`i` IN (1, 3) AND `i` = 1337 AND `i` = 420", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 1337 || e.i != 420 || s.contains(e.i)).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 1337 || e.i != 420 || s.contains(e.i)).parse().getExpression().toString();
Assertions.assertEquals("`i` = 1337 OR `i` <> 420 OR `i` IN (1, 3)", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 1337 || e.i == 420 || s.contains(e.i)).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 1337 || e.i == 420 || s.contains(e.i)).parse().getExpression().toString();
Assertions.assertEquals("`i` = 1337 OR `i` = 420 OR `i` IN (1, 3)", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 1337 || s.contains(e.i) || e.i == 420).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 1337 || s.contains(e.i) || e.i == 420).parse().getExpression().toString();
Assertions.assertEquals("`i` = 1337 OR `i` IN (1, 3) OR `i` = 420", act);
}
@@ -91,7 +91,7 @@ public class OptimizedAsmParserTest {
public void testComplexExpressionMixedAndOr() throws AsmParseException {
String act;
var s = List.of(1, 3);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> s.contains(e.i) && (e.i == 1337 || e.i == 420)).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> s.contains(e.i) && (e.i == 1337 || e.i == 420)).parse().getExpression().toString();
Assertions.assertEquals("`i` IN (1, 3) AND (`i` = 1337 OR `i` = 420)", act);
@@ -105,15 +105,15 @@ public class OptimizedAsmParserTest {
public void testObject() throws AsmParseException {
String act;
var s = Arrays.asList(null, 4);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.o == null).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.o == null).parse().getExpression().toString();
Assertions.assertEquals("`o` IS NULL", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.o != null).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.o != null).parse().getExpression().toString();
Assertions.assertEquals("`o` IS NOT NULL", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.o != null || s.contains(e.o)).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.o != null || s.contains(e.o)).parse().getExpression().toString();
Assertions.assertEquals("`o` IS NOT NULL OR `o` IN (NULL, 4)", act);
}
@@ -121,41 +121,41 @@ public class OptimizedAsmParserTest {
public void testFloatingPoint() throws AsmParseException {
String act;
var s = Arrays.asList(null, 2);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.d == 3.14d).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.d == 3.14d).parse().getExpression().toString();
Assertions.assertEquals("`d` = 3.14", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.f == 3.14f).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.f == 3.14f).parse().getExpression().toString();
Assertions.assertEquals("`f` = 3.14", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.d != 1d || e.f != 1 || s.contains(e.d)).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.d != 1d || e.f != 1 || s.contains(e.d)).parse().getExpression().toString();
Assertions.assertEquals("`d` <> 1 OR `f` <> 1 OR `d` IN (NULL, 2)", act);
}
@Test
public void testIDFLConst() throws AsmParseException {
String act;
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 0 || e.i == 1 || e.i == 2 || e.i == 3 || e.i == 4 || e.i == 5).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 0 || e.i == 1 || e.i == 2 || e.i == 3 || e.i == 4 || e.i == 5).parse().getExpression().toString();
Assertions.assertEquals("`i` = 0 OR `i` = 1 OR `i` = 2 OR `i` = 3 OR `i` = 4 OR `i` = 5", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.d == 0D || e.d == 1D).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.d == 0D || e.d == 1D).parse().getExpression().toString();
Assertions.assertEquals("`d` = 0 OR `d` = 1", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.f == 0F || e.f == 1F || e.f == 2F).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.f == 0F || e.f == 1F || e.f == 2F).parse().getExpression().toString();
Assertions.assertEquals("`f` = 0 OR `f` = 1 OR `f` = 2", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.l == 0L || e.l == 1L).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.l == 0L || e.l == 1L).parse().getExpression().toString();
Assertions.assertEquals("`l` = 0 OR `l` = 1", act);
}
@Test
public void testMemberViaGetter() throws AsmParseException {
String act;
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.getI() == 1337).parse().toString();
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.getI() == 1337).parse().getExpression().toString();
Assertions.assertEquals("`i` = 1337", act);
}

View File

@@ -38,6 +38,14 @@ class DbContextSimpleTest {
@Clazz(TestClass.class)
private DbSet<TestClass> objects1;
@Override
public void onModelCreate(ModelBuilder mb) {
super.onModelCreate(mb);
mb.entity(TestClass.class)
.hasOne(e -> e.i)
.isUnique(true);
}
}
@Getter

View File

@@ -16,7 +16,7 @@ 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",
assertEquals("Model TestClass2 contains multiple 1 to N relations with type TestClass",
assertThrowsExactly(ModelException.class, () -> ModelBuilder.from(Ctx.class)).getMessage());
}

View File

@@ -19,8 +19,8 @@ class ForeignKeyInitializerNestedList2LayerTest {
assertEquals(3, mb.getEntities().size());
assertEquals("objects1", mb.getEntity(TestClass3.class).getName());
assertEquals("nested2", mb.getEntity(TestClass2.class).getName());
assertEquals("nested", mb.getEntity(TestClass.class).getName());
assertEquals("TestClass2", mb.getEntity(TestClass2.class).getName());
assertEquals("TestClass", 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)));

View File

@@ -19,7 +19,7 @@ class ForeignKeyInitializerNestedListSimpleTest {
assertEquals(2, mb.getEntities().size());
assertEquals("objects1", mb.getEntity(TestClass2.class).getName());
assertEquals("nested", mb.getEntity(TestClass.class).getName());
assertEquals("TestClass", 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)));

View File

@@ -17,8 +17,8 @@ class ForeignKeyInitializerNestedObject2LayerTest {
assertEquals(3, mb.getEntities().size());
assertEquals("objects1", mb.getEntity(TestClass3.class).getName());
assertEquals("nested2", mb.getEntity(TestClass2.class).getName());
assertEquals("nested", mb.getEntity(TestClass.class).getName());
assertEquals("TestClass2", mb.getEntity(TestClass2.class).getName());
assertEquals("TestClass", 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)));

View File

@@ -17,7 +17,7 @@ class ForeignKeyInitializerNestedObjectSimpleTest {
assertEquals(2, mb.getEntities().size());
assertEquals("objects1", mb.getEntity(TestClass2.class).getName());
assertEquals("nested", mb.getEntity(TestClass.class).getName());
assertEquals("TestClass", 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)));

View File

@@ -102,11 +102,6 @@ public class ModelBuilderCloneTest {
System.out.println("ex: " + o.getTypeName());
System.out.println("ac: " + c.getTypeName());
}
if (!Objects.equals(o.getType(), c.getType())) {
System.out.println("types differ: entity " + o.getName());
System.out.println("ex: " + o.getType());
System.out.println("ac: " + c.getType());
}
if (!o.getName().equals(c.getName())) {
System.out.println("names differ: entity " + o.getName());
System.out.println("ex: " + o.getName());
@@ -202,11 +197,11 @@ public class ModelBuilderCloneTest {
System.out.println("ex: " + of.getField());
System.out.println("ac: " + cf.getField());
}
if (!Objects.equals(of.getForeignKeyModelLink() == null ? null : of.getForeignKeyModelLink().getName(),
cf.getForeignKeyModelLink() == null ? null : cf.getForeignKeyModelLink().getName())) {
if (!Objects.equals(of.getExposingForeignKeyOf() == null ? null : of.getExposingForeignKeyOf().getName(),
cf.getExposingForeignKeyOf() == null ? null : cf.getExposingForeignKeyOf().getName())) {
System.out.println("fk model links differ: entity " + o.getName() + ", field " + of.getName());
System.out.println("ex: " + (of.getForeignKeyModelLink() == null ? null : of.getForeignKeyModelLink().getName()));
System.out.println("ac: " + (cf.getForeignKeyModelLink() == null ? null : cf.getForeignKeyModelLink().getName()));
System.out.println("ex: " + (of.getExposingForeignKeyOf() == null ? null : of.getExposingForeignKeyOf().getName()));
System.out.println("ac: " + (cf.getExposingForeignKeyOf() == null ? null : cf.getExposingForeignKeyOf().getName()));
}
if (!of.getName().equals(cf.getName())) {
System.out.println("names differ: entity " + o.getName() + ", field " + of.getName());

View File

@@ -26,10 +26,10 @@ public class MigrationCreatorAddEntityTest extends MigrationCreatorTestBase {
var from = ModelBuilder.from(Ctx.class);
var to = ModelBuilder.from(Ctx.class);
var ent = to.entity("AddedEntity");
ent.getOrCreateField("id", int.class.getName());
ent.getOrCreateField("addedField", int.class.getName());
ent.setPrimaryKey(new PrimaryKeyConstraint(ent, List.of(ent.getField("id"))));
ent.addForeignKey(new ForeignKeyConstraint(ent, List.of(ent.getField("addedField")), ent, List.of(ent.getField("id")), ForeignKeyConstraint.Action.CASCADE, ForeignKeyConstraint.Action.CASCADE));
ent.field("id", int.class.getName());
ent.field("addedField", int.class.getName());
to.getEntity("AddedEntity").setPrimaryKey(new PrimaryKeyConstraint(to.getEntity("AddedEntity"), List.of(to.getEntity("AddedEntity").getField("id"))));
to.getEntity("AddedEntity").addForeignKey(new ForeignKeyConstraint(to.getEntity("AddedEntity"), List.of(to.getEntity("AddedEntity").getField("addedField")), to.getEntity("AddedEntity"), List.of(to.getEntity("AddedEntity").getField("id")), ForeignKeyConstraint.Action.CASCADE, ForeignKeyConstraint.Action.CASCADE));
var mc = new MigrationCreator();
var res = mc.createMigration(from, to, "SomeMigration", "test", new ModelBuilderGenerator(from, "Current", "test").generate().getJava());
try {

View File

@@ -16,7 +16,7 @@ import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class MigrationCreatorAddForeignKeyTest extends MigrationCreatorTestBase{
public class MigrationCreatorAddForeignKeyTest extends MigrationCreatorTestBase {
@Test
public void test() {
var from = ModelBuilder.from(Ctx.class);
@@ -39,8 +39,8 @@ public class MigrationCreatorAddForeignKeyTest extends MigrationCreatorTestBase
assertEquals(1, res.getStepsUp().size());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof AddForeignKeyOperation o
&& o.getTable().equals("nested")
&& o.getReferencedTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getReferencedTable().equals("TestClass")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("i2")
&& o.getReferencedFields().size() == 1
@@ -52,8 +52,8 @@ public class MigrationCreatorAddForeignKeyTest extends MigrationCreatorTestBase
assertEquals(1, res.getStepsDown().size());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getName().equals("FK_nested_nested_i2"))
&& o.getTable().equals("TestClass")
&& o.getName().equals("FK_TestClass_TestClass_i2"))
.count());
}

View File

@@ -20,8 +20,8 @@ public class MigrationCreatorAddIndexTest extends MigrationCreatorTestBase{
public void test() {
var from = ModelBuilder.from(Ctx.class);
var to = ModelBuilder.from(Ctx.class);
var ent = to.getEntity(TestClass.class);
ent.getField("d").setIndex(true);
var ent = to.entity(TestClass.class);
ent.field("d", double.class.getName()).isIndex(true);
var mc = new MigrationCreator();
var res = mc.createMigration(from, to, "SomeMigration", "test", new ModelBuilderGenerator(from, "Current", "test").generate().getJava());
try {
@@ -38,7 +38,7 @@ public class MigrationCreatorAddIndexTest extends MigrationCreatorTestBase{
assertEquals(1, res.getStepsUp().size());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof AddIndexOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("d"))
.count());
@@ -48,8 +48,8 @@ public class MigrationCreatorAddIndexTest extends MigrationCreatorTestBase{
assertEquals(1, res.getStepsDown().size());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getName().equals("I_nested_d"))
&& o.getTable().equals("TestClass")
&& o.getName().equals("I_TestClass_d"))
.count());
}

View File

@@ -20,8 +20,8 @@ public class MigrationCreatorAddKeyTest extends MigrationCreatorTestBase{
public void test() {
var from = ModelBuilder.from(Ctx.class);
var to = ModelBuilder.from(Ctx.class);
var ent = to.getEntity(TestClass.class);
ent.getField("d").setKey(true);
var ent = to.entity(TestClass.class);
ent.field("d", double.class.getName()).isKey(true);
var mc = new MigrationCreator();
var res = mc.createMigration(from, to, "SomeMigration", "test", new ModelBuilderGenerator(from, "Current", "test").generate().getJava());
try {
@@ -38,7 +38,7 @@ public class MigrationCreatorAddKeyTest extends MigrationCreatorTestBase{
assertEquals(1, res.getStepsUp().size());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof AddKeyOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("d"))
.count());
@@ -48,8 +48,8 @@ public class MigrationCreatorAddKeyTest extends MigrationCreatorTestBase{
assertEquals(1, res.getStepsDown().size());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getName().equals("K_nested_d"))
&& o.getTable().equals("TestClass")
&& o.getName().equals("K_TestClass_d"))
.count());
}

View File

@@ -20,8 +20,8 @@ public class MigrationCreatorAddUniqueTest extends MigrationCreatorTestBase{
public void test() {
var from = ModelBuilder.from(Ctx.class);
var to = ModelBuilder.from(Ctx.class);
var ent = to.getEntity(TestClass.class);
ent.getField("d").setUnique(true);
var ent = to.entity(TestClass.class);
ent.field("d", double.class.getName()).isUnique(true);
var mc = new MigrationCreator();
var res = mc.createMigration(from, to, "SomeMigration", "test", new ModelBuilderGenerator(from, "Current", "test").generate().getJava());
try {
@@ -38,7 +38,7 @@ public class MigrationCreatorAddUniqueTest extends MigrationCreatorTestBase{
assertEquals(1, res.getStepsUp().size());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof AddUniqueKeyOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("d"))
.count());
@@ -48,8 +48,8 @@ public class MigrationCreatorAddUniqueTest extends MigrationCreatorTestBase{
assertEquals(1, res.getStepsDown().size());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getName().equals("U_nested_d"))
&& o.getTable().equals("TestClass")
&& o.getName().equals("U_TestClass_d"))
.count());
}

View File

@@ -45,7 +45,7 @@ public class MigrationCreatorInitialMigrationTest extends MigrationCreatorTestBa
.count());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof AddTableOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getFields().size() == 6
&& o.getFields().stream().filter(f -> f.build().getField().equals("d")).count() == 1
&& o.getFields().stream().filter(f -> f.build().getField().equals("f")).count() == 1
@@ -62,13 +62,13 @@ public class MigrationCreatorInitialMigrationTest extends MigrationCreatorTestBa
.count());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof AddPrimaryKeyOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("i"))
.count());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof AddForeignKeyOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getReferencedTable().equals("objects1")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("nestedI")
@@ -81,12 +81,12 @@ public class MigrationCreatorInitialMigrationTest extends MigrationCreatorTestBa
assertEquals(5, res.getStepsDown().size());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getName().equals("FK_nested_objects1_nestedI"))
&& o.getTable().equals("TestClass")
&& o.getName().equals("FK_TestClass_objects1_nestedI"))
.count());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getName().equals("PRIMARY"))
.count());
assertEquals(1, res.getStepsDown().stream()
@@ -97,7 +97,7 @@ public class MigrationCreatorInitialMigrationTest extends MigrationCreatorTestBa
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof DropTableOperation o
&& o.getTable().equals("nested"))
&& o.getTable().equals("TestClass"))
.count());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof DropTableOperation o

View File

@@ -22,8 +22,8 @@ public class MigrationCreatorRenameEntityTest extends MigrationCreatorTestBase {
public void test() {
var from = ModelBuilder.from(Ctx.class);
var to = ModelBuilder.from(Ctx.class);
var ent = to.getEntity(TestClass.class);
ent.setName("d2");
var ent = to.entity(TestClass.class);
ent.name("d2");
var mc = new MigrationCreator();
var res = mc.createMigration(from, to, "SomeMigration", "test", new ModelBuilderGenerator(from, "Current", "test").generate().getJava());
try {
@@ -40,17 +40,17 @@ public class MigrationCreatorRenameEntityTest extends MigrationCreatorTestBase {
assertEquals(5, res.getStepsUp().size());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getName().equals("FK_nested_objects1_nestedI"))
&& o.getTable().equals("TestClass")
&& o.getName().equals("FK_TestClass_objects1_nestedI"))
.count());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getName().equals("PRIMARY"))
.count());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof RenameTableOperation o
&& o.getOldName().equals("nested")
&& o.getOldName().equals("TestClass")
&& o.getNewName().equals("d2"))
.count());
assertEquals(1, res.getStepsUp().stream()
@@ -85,17 +85,17 @@ public class MigrationCreatorRenameEntityTest extends MigrationCreatorTestBase {
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof RenameTableOperation o
&& o.getOldName().equals("d2")
&& o.getNewName().equals("nested"))
&& o.getNewName().equals("TestClass"))
.count());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof AddPrimaryKeyOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("i"))
.count());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof AddForeignKeyOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getReferencedTable().equals("objects1")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("nestedI")

View File

@@ -46,45 +46,45 @@ public class MigrationCreatorRenameFieldConstraintsTest extends MigrationCreator
assertEquals(11, res.getStepsUp().size());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getName().equals("FK_nested_nested_iFk"))
&& o.getTable().equals("TestClass")
&& o.getName().equals("FK_TestClass_TestClass_iFk"))
.count());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getName().equals("PRIMARY"))
.count());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getName().equals("U_nested_i"))
&& o.getTable().equals("TestClass")
&& o.getName().equals("U_TestClass_i"))
.count());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getName().equals("K_nested_i"))
&& o.getTable().equals("TestClass")
&& o.getName().equals("K_TestClass_i"))
.count());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getName().equals("I_nested_i"))
&& o.getTable().equals("TestClass")
&& o.getName().equals("I_TestClass_i"))
.count());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof RenameFieldOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getOldName().equals("i")
&& o.getNewName().equals("i2"))
.count());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof AddPrimaryKeyOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("i2"))
.count());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof AddForeignKeyOperation o
&& o.getTable().equals("nested")
&& o.getReferencedTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getReferencedTable().equals("TestClass")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("iFk")
&& o.getReferencedFields().size() == 1
@@ -92,19 +92,19 @@ public class MigrationCreatorRenameFieldConstraintsTest extends MigrationCreator
.count());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof AddUniqueKeyOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("i2"))
.count());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof AddKeyOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("i2"))
.count());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof AddIndexOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("i2"))
.count());
@@ -114,45 +114,45 @@ public class MigrationCreatorRenameFieldConstraintsTest extends MigrationCreator
assertEquals(11, res.getStepsDown().size());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getName().equals("FK_nested_nested_iFk"))
&& o.getTable().equals("TestClass")
&& o.getName().equals("FK_TestClass_TestClass_iFk"))
.count());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getName().equals("PRIMARY"))
.count());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getName().equals("U_nested_i2"))
&& o.getTable().equals("TestClass")
&& o.getName().equals("U_TestClass_i2"))
.count());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getName().equals("K_nested_i2"))
&& o.getTable().equals("TestClass")
&& o.getName().equals("K_TestClass_i2"))
.count());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof DropConstraintOperation o
&& o.getTable().equals("nested")
&& o.getName().equals("I_nested_i2"))
&& o.getTable().equals("TestClass")
&& o.getName().equals("I_TestClass_i2"))
.count());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof RenameFieldOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getOldName().equals("i2")
&& o.getNewName().equals("i"))
.count());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof AddPrimaryKeyOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("i"))
.count());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof AddForeignKeyOperation o
&& o.getTable().equals("nested")
&& o.getReferencedTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getReferencedTable().equals("TestClass")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("iFk")
&& o.getReferencedFields().size() == 1
@@ -160,19 +160,19 @@ public class MigrationCreatorRenameFieldConstraintsTest extends MigrationCreator
.count());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof AddUniqueKeyOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("i"))
.count());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof AddKeyOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("i"))
.count());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof AddIndexOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getFields().size() == 1
&& o.getFields().get(0).equals("i"))
.count());

View File

@@ -19,8 +19,8 @@ public class MigrationCreatorRenameFieldTest extends MigrationCreatorTestBase {
public void test() {
var from = ModelBuilder.from(Ctx.class);
var to = ModelBuilder.from(Ctx.class);
var ent = to.getEntity(TestClass.class);
ent.getField("d").setName("d2");
var ent = to.entity(TestClass.class);
ent.field("d", double.class.getName()).name("d2");
var mc = new MigrationCreator();
var res = mc.createMigration(from, to, "SomeMigration", "test", new ModelBuilderGenerator(from, "Current", "test").generate().getJava());
try {
@@ -37,7 +37,7 @@ public class MigrationCreatorRenameFieldTest extends MigrationCreatorTestBase {
assertEquals(1, res.getStepsUp().size());
assertEquals(1, res.getStepsUp().stream()
.filter(e -> e instanceof RenameFieldOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getOldName().equals("d")
&& o.getNewName().equals("d2"))
.count());
@@ -47,7 +47,7 @@ public class MigrationCreatorRenameFieldTest extends MigrationCreatorTestBase {
assertEquals(1, res.getStepsDown().size());
assertEquals(1, res.getStepsDown().stream()
.filter(e -> e instanceof RenameFieldOperation o
&& o.getTable().equals("nested")
&& o.getTable().equals("TestClass")
&& o.getOldName().equals("d2")
&& o.getNewName().equals("d"))
.count());

View File

@@ -24,22 +24,22 @@ class ModelChangeDetectorAddEntityTest {
private ModelBuilder createFrom() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
return mb;
}
private ModelBuilder createTo() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass2");
mb.entity("TestClass2").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass2").field("i2", int.class.getName())
.isNotNull(true);
mb.entity("TestClass3");
mb.entity("TestClass3").getOrCreateField("i3", int.class.getName())
.setNotNull(true);
mb.entity("TestClass3").field("i3", int.class.getName())
.isNotNull(true);
return mb;
}
}

View File

@@ -24,20 +24,20 @@ class ModelChangeDetectorAddFieldTest {
private ModelBuilder createFrom() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
return mb;
}
private ModelBuilder createTo() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i3", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i3", int.class.getName())
.isNotNull(true);
return mb;
}
}

View File

@@ -26,23 +26,23 @@ class ModelChangeDetectorAddForeignKeyTest {
private ModelBuilder createFrom() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
return mb;
}
private ModelBuilder createTo() {
var mb = new ModelBuilder();
var ent = mb.entity("TestClass");
ent.getOrCreateField("i", int.class.getName())
.setNotNull(true);
ent.getOrCreateField("i2", int.class.getName())
.setNotNull(true);
ent.addForeignKey(new ForeignKeyConstraint(ent, List.of(ent.getField("i2")),
ent, List.of(ent.getField("i")),
ForeignKeyConstraint.Action.CASCADE, ForeignKeyConstraint.Action.CASCADE));
ent.field("i", int.class.getName())
.isNotNull(true);
ent.field("i2", int.class.getName())
.isNotNull(true);
mb.getEntity("TestClass").addForeignKey(new ForeignKeyConstraint(mb.getEntity("TestClass"), List.of(mb.getEntity("TestClass").getField("i2")),
mb.getEntity("TestClass"), List.of(mb.getEntity("TestClass").getField("i")),
ForeignKeyConstraint.Action.CASCADE, ForeignKeyConstraint.Action.CASCADE));
return mb;
}
}

View File

@@ -23,21 +23,21 @@ class ModelChangeDetectorAddIndexTest {
private ModelBuilder createFrom() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
return mb;
}
private ModelBuilder createTo() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i", int.class.getName()).setIndex(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i", int.class.getName()).isIndex(true);
return mb;
}
}

View File

@@ -23,21 +23,21 @@ class ModelChangeDetectorAddKeyTest {
private ModelBuilder createFrom() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
return mb;
}
private ModelBuilder createTo() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i", int.class.getName()).setKey(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i", int.class.getName()).isKey(true);
return mb;
}
}

View File

@@ -27,22 +27,22 @@ class ModelChangeDetectorAddPrimaryKeyTest {
private ModelBuilder createFrom() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
return mb;
}
private ModelBuilder createTo() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").setPrimaryKey(new PrimaryKeyConstraint(mb.entity("TestClass"),
List.of(mb.entity("TestClass").getField("i"))));
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
mb.getEntity("TestClass").setPrimaryKey(new PrimaryKeyConstraint(mb.getEntity("TestClass"),
List.of(mb.getEntity("TestClass").getField("i"))));
return mb;
}
}

View File

@@ -23,21 +23,21 @@ class ModelChangeDetectorAddUniqueTest {
private ModelBuilder createFrom() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
return mb;
}
private ModelBuilder createTo() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i", int.class.getName()).setUnique(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i", int.class.getName()).isUnique(true);
return mb;
}
}

View File

@@ -24,22 +24,22 @@ class ModelChangeDetectorDropEntityTest {
private ModelBuilder createFrom() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass2");
mb.entity("TestClass2").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass2").field("i2", int.class.getName())
.isNotNull(true);
mb.entity("TestClass3");
mb.entity("TestClass3").getOrCreateField("i3", int.class.getName())
.setNotNull(true);
mb.entity("TestClass3").field("i3", int.class.getName())
.isNotNull(true);
return mb;
}
private ModelBuilder createTo() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
return mb;
}
}

View File

@@ -24,20 +24,20 @@ class ModelChangeDetectorDropFieldTest {
private ModelBuilder createFrom() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i3", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i3", int.class.getName())
.isNotNull(true);
return mb;
}
private ModelBuilder createTo() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
return mb;
}
}

View File

@@ -26,23 +26,23 @@ class ModelChangeDetectorDropForeignKeyTest {
private ModelBuilder createFrom() {
var mb = new ModelBuilder();
var ent = mb.entity("TestClass");
ent.getOrCreateField("i", int.class.getName())
.setNotNull(true);
ent.getOrCreateField("i2", int.class.getName())
.setNotNull(true);
ent.addForeignKey(new ForeignKeyConstraint(ent, List.of(ent.getField("i2")),
ent, List.of(ent.getField("i")),
ForeignKeyConstraint.Action.CASCADE, ForeignKeyConstraint.Action.CASCADE));
ent.field("i", int.class.getName())
.isNotNull(true);
ent.field("i2", int.class.getName())
.isNotNull(true);
mb.getEntity("TestClass").addForeignKey(new ForeignKeyConstraint(mb.getEntity("TestClass"), List.of(mb.getEntity("TestClass").getField("i2")),
mb.getEntity("TestClass"), List.of(mb.getEntity("TestClass").getField("i")),
ForeignKeyConstraint.Action.CASCADE, ForeignKeyConstraint.Action.CASCADE));
return mb;
}
private ModelBuilder createTo() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
return mb;
}
}

View File

@@ -23,21 +23,21 @@ class ModelChangeDetectorDropIndexTest {
private ModelBuilder createFrom() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i", int.class.getName()).setIndex(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i", int.class.getName()).isIndex(true);
return mb;
}
private ModelBuilder createTo() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
return mb;
}
}

View File

@@ -23,21 +23,21 @@ class ModelChangeDetectorDropKeyTest {
private ModelBuilder createFrom() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i", int.class.getName()).setKey(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i", int.class.getName()).isKey(true);
return mb;
}
private ModelBuilder createTo() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
return mb;
}
}

View File

@@ -27,22 +27,22 @@ class ModelChangeDetectorDropPrimaryKeyTest {
private ModelBuilder createFrom() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").setPrimaryKey(new PrimaryKeyConstraint(mb.entity("TestClass"),
List.of(mb.entity("TestClass").getField("i"))));
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
mb.getEntity("TestClass").setPrimaryKey(new PrimaryKeyConstraint(mb.getEntity("TestClass"),
List.of(mb.getEntity("TestClass").getField("i"))));
return mb;
}
private ModelBuilder createTo() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
return mb;
}
}

View File

@@ -23,21 +23,21 @@ class ModelChangeDetectorDropUniqueTest {
private ModelBuilder createFrom() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i", int.class.getName()).setUnique(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i", int.class.getName()).isUnique(true);
return mb;
}
private ModelBuilder createTo() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass").field("i2", int.class.getName())
.isNotNull(true);
return mb;
}
}

View File

@@ -18,13 +18,13 @@ class ModelChangeDetectorNoChangeTest {
private ModelBuilder createFrom() {
var mb = new ModelBuilder();
mb.entity("TestClass");
mb.entity("TestClass").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass2");
mb.entity("TestClass2").getOrCreateField("i", int.class.getName())
.setNotNull(true);
mb.entity("TestClass2").getOrCreateField("i2", int.class.getName())
.setNotNull(true);
mb.entity("TestClass2").field("i", int.class.getName())
.isNotNull(true);
mb.entity("TestClass2").field("i2", int.class.getName())
.isNotNull(true);
return mb;
}