Is there a Java library that generates Java source code to create objects?

I am looking for an API that will generate me source code that will generate objects equal to those that I passed to the library.

public static void main(String[] args) {
  int[] arr = new int[3];
  arr[0] = 3;
  arr[1] = 4;
  arr[2] = 5;

  // looking for this one
  MagicCode.generateCode(arr);
}

Gotta generate

  int[] arr = new int[3];
  arr[0] = 3;
  arr[1] = 4;
  arr[2] = 5;

or

  int[] arr = new int[] { 3, 4, 5 };

So, I want to pass an object and get the Java Source Code , which will create an object equal to my original object.

This should work not only for primitive types, but also for my own objects:

public static void main(String[] args) {
  Condition condition = new Condition();
  condition.setNumber(2);

  // looking for this one
  MagicCode.generateCode(condition);
}

Gotta generate

  Condition c1 = new Condition();
  c1.setNumber(2);

as a string that can then be inserted into the Java source file.

EDIT

I do not want to get around the compiler.

, . , 1000 . - /. 1000 , .

, #toString(), Java . 1000 , .

+4
3

- ! , , , , MagicCode.

, , .

Eclipse JDT API .

- IPackageFragment.createCompilationUnit. . , ICompilationUnit.

docs .

, , , , . API, AST. .

public class CodeGenerator {

    public static void main(String[] args) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        Foo foobar = new Foo();

        Bar bar = new Bar();
        bar.setSomeValue(555d);
        foobar.setBar(bar);
        foobar.setPrimitiveDouble(23);
        foobar.setValue("Hello World!");

        CodeGenerator codeGenerator = new CodeGenerator();

        String generatedCode = codeGenerator.generateCode(foobar);

        System.out.println(generatedCode);

    }

    int counter = 0;

    private String createVariableName(String clazzName) {
        return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, clazzName + getCurrentCounter());
    }

    public String generateCode(AST ast, List statements, Object object) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        String clazzName = object.getClass().getSimpleName();
        String variableName = createVariableName(clazzName);

        VariableDeclarationFragment newVariable = ast.newVariableDeclarationFragment();
        newVariable.setName(ast.newSimpleName(variableName)); // Or clazzName.toCamelCase()

        ClassInstanceCreation newInstance = ast.newClassInstanceCreation();
        newInstance.setType(ast.newSimpleType(ast.newSimpleName(clazzName)));
        newVariable.setInitializer(newInstance);

        VariableDeclarationStatement newObjectStatement = ast.newVariableDeclarationStatement(newVariable);
        newObjectStatement.setType(ast.newSimpleType(ast.newSimpleName(clazzName)));

        statements.add(newObjectStatement);

        BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());
        for (PropertyDescriptor propertyDesc : beanInfo.getPropertyDescriptors()) {
            String propertyName = propertyDesc.getName();

            if (!shouldIgnore(propertyName)) {

                MethodInvocation setterInvocation = ast.newMethodInvocation();

                SimpleName setterName = ast.newSimpleName(propertyDesc.getWriteMethod().getName());
                setterInvocation.setName(setterName);

                Object invoked = propertyDesc.getReadMethod().invoke(object);

                if (invoked == null) {
                    continue;
                }

                if (Primitives.isWrapperType(invoked.getClass())) {
                    if (Number.class.isAssignableFrom(invoked.getClass())) {
                        setterInvocation.arguments().add(ast.newNumberLiteral(invoked.toString()));
                    }

                    // TODO: Booleans
                } else {

                    if (invoked instanceof String) {
                        StringLiteral newStringLiteral = ast.newStringLiteral();
                        newStringLiteral.setLiteralValue(invoked.toString());
                        setterInvocation.arguments().add(newStringLiteral);
                    } else {

                        String newObjectVariable = generateCode(ast, statements, invoked);
                        SimpleName newSimpleName = ast.newSimpleName(newObjectVariable);
                        setterInvocation.arguments().add(newSimpleName);
                    }

                }

                SimpleName newSimpleName = ast.newSimpleName(variableName);
                setterInvocation.setExpression(newSimpleName);

                ExpressionStatement setterStatement = ast.newExpressionStatement(setterInvocation);

                statements.add(setterStatement);

            }

        }

        return variableName;
    }

    public String generateCode(Object object) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        resetCounter();

        AST ast = AST.newAST(AST.JLS3);
        Block block = ast.newBlock();

        generateCode(ast, block.statements(), object);

        return block.toString();

    }

    private int getCurrentCounter() {
        return counter++;
    }

    private void resetCounter() {
        counter = 0;
    }

    private boolean shouldIgnore(String propertyName) {
        return "class".equals(propertyName);
    }
}

, :

    <dependency>
        <groupId>org.eclipse.tycho</groupId>
        <artifactId>org.eclipse.jdt.core</artifactId>
        <version>3.9.1.v20130905-0837</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.core</groupId>
        <artifactId>runtime</artifactId>
        <version>3.9.100-v20131218-1515</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.birt.runtime</groupId>
        <artifactId>org.eclipse.core.resources</artifactId>
        <version>3.8.101.v20130717-0806</version>
    </dependency>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>18.0</version>
    </dependency>

:

  Foo foo0=new Foo();
  Bar bar1=new Bar();
  bar1.setSomeValue(555.0);
  foo0.setBar(bar1);
  foo0.setPrimitiveDouble(23.0);
  foo0.setValue("Hello World!");

Foo Bar:

public class Bar {

private double someValue;

public double getSomeValue() {
    return someValue;
}

public void setSomeValue(double someValue) {
    this.someValue = someValue;
}

}

public class Foo {

private String value;
private double primitiveDouble;
private Bar bar;

public Bar getBar() {
    return bar;
}

public double getPrimitiveDouble() {
    return primitiveDouble;
}

public String getValue() {
    return value;
}

public void setBar(Bar bar) {
    this.bar = bar;
}

public void setPrimitiveDouble(double primitiveDouble) {
    this.primitiveDouble = primitiveDouble;
}

public void setValue(String value) {
        this.value = value;
    }
}

github .

+3

. toString, , : .

toString, Intellij Idea 9 .

+1

If you have a String that contains source code and wants to compile it at runtime, there is a Java Compiler API for this purpose

-2
source

Source: https://habr.com/ru/post/1598882/


All Articles