-1

I am new to bytebuddy, I would like to dynamically create a class and execute code like below using byte buddy.

public class Formulas{
    public double formula1234(FormulaAPI apiReference) {
                                if(apiReference.getId() > 0){
                                      return apiReference.evaluate("A") * 2;
                                }else if(apiReference.getId() == 1){
                                       return apiReference.evaluate("B");
                                }else{
                                     return apiReference.getSum(x1, x2);
                                }
                                return null;
 }
}

I have the class FormulaAPI already defined, which has the methods -> evaluate(..) and getSum(..) defined in it.

I would like to use byte buddy to dynamically create the class called Formulas and dynamically construct the method formula1234(..) and the code inside the method.

Is it even possible to construct the if else statements using byte buddy?

Please could you give an example of how this code can be dynamically generated using byte buddy. Any help is appreciated.

BeUndead
  • 3,463
  • 2
  • 17
  • 21
javaseeker
  • 73
  • 1
  • 9

1 Answers1

1

Code generation in java is not that easy, so it is not used often. Especially compared to languages that have something like an eval() function.

One common approach you would use in java would be to use a list/map of strategies. In your case the strategy(*) would consist of two method. A condition that checks if the strategy should be applied, and the actual execution.

Here a self contained example:

public static void main(String[] args) {

    Formulas formulas = new Formulas();

    formulas.addFormula(api -> api.getApi() == 0, api -> api.getVal1() + api.getVal2());
    formulas.addFormula(api -> api.getApi() == 1, api -> api.getVal1() + 25d);
    formulas.addFormula(api -> api.getApi() == 2, api -> api.getVal2() - api.getVal1());

    System.out.println(formulas.formula123(new Api(0, 1, 2)));
    System.out.println(formulas.formula123(new Api(1, 2, -5)));
    System.out.println(formulas.formula123(new Api(2, 5, -5)));

}

public static class Api {
    private final int api;

    private final double val1;
    private final double val2;

    public Api(int api, double val1, double val2) {
        this.api = api;
        this.val1 = val1;
        this.val2 = val2;
    }

    public int getApi() {
        return api;
    }

    public double getVal1() {
        return val1;
    }

    public double getVal2() {
        return val2;
    }

}

public static class Formula {

    private final Predicate<Api> condition;
    private final Function<Api, Double> execute;

    public Formula(Predicate<Api> condition, Function<Api, Double> execute) {
        this.condition = condition;
        this.execute = execute;
    }

    public Predicate<Api> getCondition() {
        return condition;
    }

    public Function<Api, Double> getExecute() {
        return execute;
    }

}

public static class Formulas {
    private final List<Formula> formulas = new ArrayList<>();

    public void addFormula(Predicate<Api> condition, Function<Api, Double> execute) {
        formulas.add(new Formula(condition, execute));
    }

    public Double formula123(Api api) {
        for (Formula formula : formulas) {
            if (formula.getCondition().test(api)) {
                return formula.getExecute().apply(api);
            }
        }
        return null;
    }
}

(*) no idea if that still counts as strategy with two methods.

k5_
  • 5,450
  • 2
  • 19
  • 27