resolve getters

This commit is contained in:
wea_ondara
2022-09-08 19:24:55 +02:00
parent 2f0fa26c6d
commit 284bf647b4
3 changed files with 56 additions and 9 deletions

View File

@@ -9,29 +9,43 @@ import org.objectweb.asm.Opcodes;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
import java.util.stream.IntStream;
@Getter
public class AsmParser {
private final Serializable lambda;
private final Method method;
public AsmParser(SerializablePredicate<?> predicate) {
this.lambda = predicate;
this.method = null;
}
public AsmParser(SerializableFunction<?, ?> function) {
this.lambda = function;
this.method = null;
}
public AsmParser(Method method) {
this.lambda = null;
this.method = method;
}
public AsmParseResult parse() throws AsmParseException {
try {
return parseExpression();
if (this.lambda != null) {
return parseLambdaExpression();
} else if (this.method != null) {
return parseMethodExpression();
}
throw new IllegalStateException();
} catch (Exception e) {
throw new AsmParseException("PredicateParser: failed to parse expression: " + e.getLocalizedMessage(), e);
}
}
private AsmParseResult parseExpression() throws Exception {
private AsmParseResult parseLambdaExpression() throws Exception {
var cls = lambda.getClass();
var loader = cls.getClassLoader();
InputStream is;
@@ -53,4 +67,21 @@ public class AsmParser {
return visiter.getResult();
}
private AsmParseResult parseMethodExpression() throws Exception {
var cls = method.getClass();
var loader = cls.getClassLoader();
InputStream is = loader.getResourceAsStream(cls.getName().replace(".", "/") + ".class");
Object[] args = new Object[0];//TODO capturing args here? or maybe not supported since this will only be user by getter evaluation
return parseCommon(is, method.getName(), args);
}
private AsmParseResult parseCommon(InputStream classIs, String methodname, Object[] args) throws Exception {
var cr = new ClassReader(classIs);
var visiter = new FilterClassVisitor(Opcodes.ASM9, methodname, args);
cr.accept(visiter, 0);
return visiter.getResult();
}
}

View File

@@ -7,6 +7,8 @@ import jef.serializable.SerializableFunction;
import jef.serializable.SerializablePredicate;
import lombok.Getter;
import java.lang.reflect.Method;
@Getter
public class OptimizedAsmParser extends AsmParser {
@@ -18,6 +20,10 @@ public class OptimizedAsmParser extends AsmParser {
super(function);
}
public OptimizedAsmParser(Method method) {
super(method);
}
public AsmParseResult parse() throws AsmParseException {
var result = super.parse();
var expr = result.getExpression();

View File

@@ -1,7 +1,9 @@
package jef.model;
import jef.asm.OptimizedAsmParser;
import jef.model.annotations.ForeignKey;
import jef.serializable.SerializableObject;
import jef.util.Util;
import java.util.Locale;
@@ -31,26 +33,34 @@ class ForeignKeyExposeInitializer {//TODO testcases for this class
if (anno.entity() != SerializableObject.class) { // not a foreign key exposure
return false;
}
return f.getField().getName().equals(anno.getterOrField());//TODO support getters
var fieldname = anno.getterOrField(); //TODO test
//if getter, extract getter field
var method = Util.tryGet(() -> entityBuilder.type().orElseThrow().getMethod(anno.getterOrField())); //TODO test
if (method.isPresent()) {
var res = new OptimizedAsmParser(method.get()).parse();
fieldname = res.getAccessedFields().stream().findFirst().orElseThrow().getName();
}
return f.getField().getName().equals(fieldname);
}
//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")) {
if (e.getField().getName().equals(f.getField().getName() + "Id") //TODO test
|| e.getField().getName().equals(f.getField().getName() + "ID") //TODO test
|| e.getField().getName().equals(f.getField().getName() + "Fk") //TODO test
|| e.getField().getName().equals(f.getField().getName() + "FK")) { //TODO test
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());
var other = mb.getEntity(f.getField().getTypeName()); //TODO test
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();
var x = other.getPrimaryKey().getFields().get(0).getName(); //TODO test
x = x.substring(0, 1).toUpperCase(Locale.ROOT) + x.substring(1);
return e.getField().getName().equals(f.getField().getName() + x);
}).toList();