Picking up a lambda expression for runtime translation is a virtually impossible task(so far), I will try to give you two suggestions:
1 - Think of a simpler solution that doesn’t involve a translation the way you described it;
2 - If you really need to do it that way, I believe lambda-from-string can help you with a slightly different solution(Function instead of Predicate).
I tried to simplify as much as I could, but still I think it is not a very interesting solution for production(mainly due to performance).
SOLUTION
Instead of trying to capture the lambda expression at runtime we can make a val of an expression(String) applying the translation and converting the String in a Function.
pom.xml
<dependency>
<groupId>pl.joegreen</groupId>
<artifactId>lambda-from-string</artifactId>
<version>1.6</version>
</dependency>
We start by defining a translation interface of the expressions:
public interface FunctionTranslator<T> {
void eval(String lambda, LambdaFactory factory) throws LambdaCreationException;
T getFunction();
}
Translator implementation of an expression that compares integers:
public class CompareIntegersFunctionTranslator implements FunctionTranslator<Function<Integer, Boolean>> {
private final String TRANSLATOR_PATTERN = "{$var%s} === %s";
private final TypeReference<Function<Integer, Boolean>> TYPE_REFERENCE = new TypeReference<Function<Integer,Boolean>>(){};
private String translatedLambda;
private Function<Integer, Boolean> function;
@Override
public void eval(String lambda, LambdaFactory factory) throws LambdaCreationException {
this.function = factory.createLambda(lambda, TYPE_REFERENCE);
this.translatedLambda = translate(lambda);
}
@Override
public Function<Integer, Boolean> getFunction() {
return function;
}
private String translate(String expression) {
String [] splited = expression.split("");
return String
.format(TRANSLATOR_PATTERN,
splited[0].toUpperCase(),
splited[splited.length - 1]);
}
@Override
public String toString() {
return translatedLambda;
}
}
Implementation of the translator of an expression summing integers:
public class SumIntegersFunctionTranslator implements FunctionTranslator<Function<Integer, Integer>> {
private final String TRANSLATOR_PATTERN = "{$var%s} += 1";
private final TypeReference<Function<Integer, Integer>> TYPE_REFERENCE = new TypeReference<Function<Integer, Integer>>(){};
private String translatedLambda;
private Function<Integer, Integer> function;
@Override
public void eval(String lambda, LambdaFactory factory) throws LambdaCreationException {
this.function = factory.createLambda(lambda, TYPE_REFERENCE);
this.translatedLambda = translate(lambda);
}
@Override
public Function<Integer, Integer> getFunction() {
return function;
}
private String translate(String expression) {
String [] splited = expression.split("");
return String
.format(TRANSLATOR_PATTERN,
splited[0].toUpperCase(),
splited[splited.length - 1]);
}
@Override
public String toString() {
return translatedLambda;
}
}
Implementation of translation strategy:
public enum FunctionTranslatorStrategy {
COMPARE_INTEGERS(new CompareIntegersFunctionTranslator()),
SUM_INTEGERS(new SumIntegersFunctionTranslator());
FunctionTranslator<?> translator;
FunctionTranslatorStrategy(FunctionTranslator<?> translator) {
this.translator = translator;
}
public FunctionTranslator<?> getFunctionTranslator() {
return translator;
}
}
Implementation of a Factory Translator:
public class FunctionFactory {
private static final LambdaFactory LAMBDA_FACTORY = LambdaFactory.get();
@SuppressWarnings("unchecked")
public static <T> FunctionTranslator<T> create(
String lambda,
FunctionTranslatorStrategy strategy) throws LambdaCreationException {
FunctionTranslator<T> translator = (FunctionTranslator<T>) strategy.getFunctionTranslator();
translator.eval(lambda, LAMBDA_FACTORY);
return translator;
}
}
Testing:
public static void main(String[] args) throws LambdaCreationException {
FunctionTranslator<Function<Integer, Boolean>> compare = FunctionFactory
.create("a -> a == 1",
FunctionTranslatorStrategy.COMPARE_INTEGERS);
System.out.println(compare.toString()); // {$varA} === 1
System.out.println(compare.getFunction().apply(1)); // true
System.out.println(compare.getFunction().apply(2)); // false
FunctionTranslator<Function<Integer, Integer>> sum = FunctionFactory
.create("b -> b + 1",
FunctionTranslatorStrategy.SUM_INTEGERS);
System.out.println(sum.toString()); // {$varB} += 1
System.out.println(sum.getFunction().apply(1)); // 2
System.out.println(sum.getFunction().apply(2)); // 3
}
Note that there is repeated code and the translation method is very basic (maybe regex to improve). It is possible to greatly improve this implementation and make things simpler, this is just an idea of where to go.