resolve getters
This commit is contained in:
@@ -9,29 +9,43 @@ import org.objectweb.asm.Opcodes;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.invoke.SerializedLambda;
|
import java.lang.invoke.SerializedLambda;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class AsmParser {
|
public class AsmParser {
|
||||||
private final Serializable lambda;
|
private final Serializable lambda;
|
||||||
|
private final Method method;
|
||||||
|
|
||||||
public AsmParser(SerializablePredicate<?> predicate) {
|
public AsmParser(SerializablePredicate<?> predicate) {
|
||||||
this.lambda = predicate;
|
this.lambda = predicate;
|
||||||
|
this.method = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsmParser(SerializableFunction<?, ?> function) {
|
public AsmParser(SerializableFunction<?, ?> function) {
|
||||||
this.lambda = function;
|
this.lambda = function;
|
||||||
|
this.method = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsmParser(Method method) {
|
||||||
|
this.lambda = null;
|
||||||
|
this.method = method;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsmParseResult parse() throws AsmParseException {
|
public AsmParseResult parse() throws AsmParseException {
|
||||||
try {
|
try {
|
||||||
return parseExpression();
|
if (this.lambda != null) {
|
||||||
|
return parseLambdaExpression();
|
||||||
|
} else if (this.method != null) {
|
||||||
|
return parseMethodExpression();
|
||||||
|
}
|
||||||
|
throw new IllegalStateException();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new AsmParseException("PredicateParser: failed to parse expression: " + e.getLocalizedMessage(), 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 cls = lambda.getClass();
|
||||||
var loader = cls.getClassLoader();
|
var loader = cls.getClassLoader();
|
||||||
InputStream is;
|
InputStream is;
|
||||||
@@ -53,4 +67,21 @@ public class AsmParser {
|
|||||||
|
|
||||||
return visiter.getResult();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import jef.serializable.SerializableFunction;
|
|||||||
import jef.serializable.SerializablePredicate;
|
import jef.serializable.SerializablePredicate;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class OptimizedAsmParser extends AsmParser {
|
public class OptimizedAsmParser extends AsmParser {
|
||||||
|
|
||||||
@@ -18,6 +20,10 @@ public class OptimizedAsmParser extends AsmParser {
|
|||||||
super(function);
|
super(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public OptimizedAsmParser(Method method) {
|
||||||
|
super(method);
|
||||||
|
}
|
||||||
|
|
||||||
public AsmParseResult parse() throws AsmParseException {
|
public AsmParseResult parse() throws AsmParseException {
|
||||||
var result = super.parse();
|
var result = super.parse();
|
||||||
var expr = result.getExpression();
|
var expr = result.getExpression();
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package jef.model;
|
package jef.model;
|
||||||
|
|
||||||
|
import jef.asm.OptimizedAsmParser;
|
||||||
import jef.model.annotations.ForeignKey;
|
import jef.model.annotations.ForeignKey;
|
||||||
import jef.serializable.SerializableObject;
|
import jef.serializable.SerializableObject;
|
||||||
|
import jef.util.Util;
|
||||||
|
|
||||||
import java.util.Locale;
|
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
|
if (anno.entity() != SerializableObject.class) { // not a foreign key exposure
|
||||||
return false;
|
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
|
//only allow fields with same prefix
|
||||||
if (!e.getField().getName().startsWith(f.getField().getName())) {
|
if (!e.getField().getName().startsWith(f.getField().getName())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//match id field which ends in Id or Fk
|
//match id field which ends in Id or Fk
|
||||||
if (e.getField().getName().equals(f.getField().getName() + "Id")
|
if (e.getField().getName().equals(f.getField().getName() + "Id") //TODO test
|
||||||
|| e.getField().getName().equals(f.getField().getName() + "ID")
|
|| e.getField().getName().equals(f.getField().getName() + "ID") //TODO test
|
||||||
|| e.getField().getName().equals(f.getField().getName() + "Fk")
|
|| e.getField().getName().equals(f.getField().getName() + "Fk") //TODO test
|
||||||
|| e.getField().getName().equals(f.getField().getName() + "FK")) {
|
|| e.getField().getName().equals(f.getField().getName() + "FK")) { //TODO test
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//match id field which ends in the name of the primary key field of the referenced entity
|
//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) {
|
if (other == null || other.getPrimaryKey() == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//assumption: initializing from models only has primary keys with 1 field (no composite keys)
|
//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);
|
x = x.substring(0, 1).toUpperCase(Locale.ROOT) + x.substring(1);
|
||||||
return e.getField().getName().equals(f.getField().getName() + x);
|
return e.getField().getName().equals(f.getField().getName() + x);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|||||||
Reference in New Issue
Block a user