Search code examples
code-generationsun-codemodel

Using com.sun.codemodel; how to write class as String instead of to a File


I am investigating com.sun.codemodel to generate Java classes.

// https://mvnrepository.com/artifact/com.sun.codemodel/codemodel
compile group: 'com.sun.codemodel', name: 'codemodel', version: '2.6'

The JCodeModel class has multiple build methods that support generating the required Java classes to files, however I would like to obtain theses generated classes as Strings.

Looking at the Javadoc and source code of JCodeModel I cannot see anyway to achieve this.

How can I obtain my generated classes as a String instead of/as well as having them written to a file?

Is it possible to extend com.sun.codemodel.CodeWriter to produce a String?


Solution

  • Sure! Producing just a String is a little tricky though since JCodeModel produces multiple classes. You can look up those classes and output them as Strings using a custom CodeWriter as follows:

    JCodeModel codeModel = new JCodeModel();
    
    JDefinedClass testClass = codeModel._class("test.Test");
    testClass.method(JMod.PUBLIC, codeModel.VOID, "helloWorld");
    
    final Map<String, ByteArrayOutputStream> streams = new HashMap<String, ByteArrayOutputStream>();
    
    CodeWriter codeWriter = new CodeWriter() {
        @Override
        public OutputStream openBinary(JPackage jPackage, String name) {
            String fullyQualifiedName = jPackage.name().length() == 0 ? name : jPackage.name().replace(".", "/") + "/" + name;
    
            if(!streams.containsKey(fullyQualifiedName)) {
                streams.put(fullyQualifiedName, new ByteArrayOutputStream());
            }
            return streams.get(fullyQualifiedName);
        }
    
        @Override
        public void close() throws IOException {
            for (OutputStream outputStream : streams.values()) {
                outputStream.flush();
                outputStream.close();
            }
        }
    };
    
    codeModel.build(codeWriter);
    
    System.out.println(streams.get("test/Test.java"));
    

    Outputs:

    public class Test {
    
    
        public void helloWorld() {
        }
    
    }