Fork me on GitHub

Code of InterfaceRenderer

package org.jproggy.examples.intfgen.snippetory;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

import org.jproggy.snippetory.Template;
import org.jproggy.snippetory.TemplateContext;

public class InterfaceRenderer {
    private Set<String> types = new TreeSet<String>();
    private Collection<String> availablePackages = new HashSet<String>();

    public static void main(String[] args) throws Exception {
        Class<?> intf = Class.forName(args[1]);
        Template intfTpl = new TemplateContext().parseResource(args[0]);

        new InterfaceRenderer().render(intf, intfTpl);

        intfTpl.render(System.out);
    }

    public void render(Class<?> intf, Template intfTpl) throws Exception {
        availablePackages.add("java.lang");
        availablePackages.add(intf.getPackage().getName());

        intfTpl.set("name", intf.getSimpleName());
        intfTpl.set("package", intf.getPackage().getName());

        for (Class<?> parent : intf.getInterfaces()) {
            registerType(parent);
            intfTpl.append("parents", parent.getSimpleName());
        }

        for (Field field : intf.getDeclaredFields()) {
            renderField(intfTpl, field);
        }

        for (Method method : intf.getDeclaredMethods()) {
            renderMethod(intfTpl.get("method"), method);
        }

        renderImports(intfTpl, types);

        // allow rendering multiple classes
        availablePackages.clear();
        types.clear();
    }

    private void renderField(Template intfTpl, Field field) throws Exception {
        Class<?> type = field.getType();
        registerType(type);

        String fieldTplName = fieldTplName(type);
        if (fieldTplName != null) {
            Template fieldTpl = intfTpl.get(fieldTplName);
            fieldTpl.set("name", field.getName());
            fieldTpl.set("type", type.getSimpleName());
            fieldTpl.set("value", field.get(null));
            fieldTpl.render();
        }
    }

    private String fieldTplName(Class<?> type) {
        if (String.class.equals(type)) {
            return "string_field";
        }
        if (Number.class.isAssignableFrom(type) || type.isPrimitive())
            return "num_field";
        return null;
    }

    private void renderMethod(Template methodTpl, Method method) {
        Class<?> returnType = method.getReturnType();
        registerType(returnType);
        methodTpl.set("name", method.getName());
        methodTpl.set("return_type", returnType.getSimpleName());

        for (int i = 0; i < method.getParameterTypes().length; i++) {
            Class<?> type = method.getParameterTypes()[i];
            registerType(type);

            Template parameter = methodTpl.get("parameters");
            parameter.set("type", type.getSimpleName());
            parameter.set("i", i);
            parameter.render();
        }

        for (Class<?> ex : method.getExceptionTypes()) {
            registerType(ex);
            methodTpl.append("exceptions", ex.getSimpleName());
        }
        methodTpl.render();
    }

    private static void renderImports(Template intfTpl, Set<String> types) {
        String oldPrefix = "";
        for (String type : types) {
            String prefix = type.split("\\.")[0];
            if (!oldPrefix.equals(prefix)) {
                if (!"".equals(oldPrefix)) intfTpl.append("imports", "\n");
                oldPrefix = prefix;
            }
            intfTpl.get("imports").set("import", type).render();
        }
    }

    private void registerType(Class<?> type) {
        if (!type.isPrimitive() && !Void.TYPE.equals(type) && 
                !availablePackages.contains(type.getPackage().getName())) {
            types.add(type.getName());
        }
    }
}

Java, and all Java-based marks are trademarks or registered trademarks of Oracle.
This site is not affiliated in any way with Oracle.