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.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();
}
} }

View File

@@ -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();

View File

@@ -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();