Render to different views - Pyknic/CodeGen GitHub Wiki

One of the advantages of the modular approach is that multiple views can be attached to the same generator. By using different "installers", the rendering can go through the same pipeline and still be divided into different contexts.

Example: XML-installer

In this example, we will render the same "concat-method" model using two different installers. One is the standard java-installer and one is an example XML-installer.

The XMLInstaller will have two additional views, MethodXMLView and FieldXMLView. Those views will use some of the Java-views (like TypeView) since a type looks the same in both contexts.

Main.java

public class Main {
    private final static Installer 
        XML = new DefaultInstaller("XMLInstaller")
            .install(Method.class, MethodXMLView.class)
            .install(Field.class, FieldXMLView.class),
        
        JAVA = new JavaInstaller();

    public static void main(String[] args) {
        final MultiGenerator gen = new MultiGenerator(JAVA, XML);
        Formatting.tab("    ");
        
        gen.codeOn(
            Method.of("concat", DefaultType.STRING).public_()
                    .add(Field.of("str1", DefaultType.STRING))
                    .add(Field.of("str2", DefaultType.STRING))
                    .add("return str1 + str2;")
        ).forEach(code -> {
            System.out.println("-------------------------------------");
            System.out.println("  " + code.getInstaller().getName() + ":");
            System.out.println("-------------------------------------");
            System.out.println(code.getText());
        });
    }
}

MethodXMLView.java

public static class MethodXMLView implements CodeView<Method> {
    @Override
    public Optional<String> render(CodeGenerator cg, Method model) {
        return Optional.of(
            "<method name=\"" + model.getName() + "\" type=\"" + 
            cg.on(model.getType()).get() + "\">" + nl() + indent(
                "<params>" + nl() + indent(
                    cg.codeOn(model.getFields())
                        .filter(c -> XML.equals(c.getInstaller()))
                        .map(c -> c.getText())
                        .collect(Collectors.joining(nl()))
                ) + nl() + "</params>" + nl() +
                "<code>" + nl() + indent(
                    model.getCode().stream().collect(Collectors.joining(nl()))
                ) + nl() + "</code>"
            ) + nl() + "</methods>"
        );
    }
}

MethodXMLView.java

public static class FieldXMLView implements CodeView<Field> {
    @Override
    public Optional<String> render(CodeGenerator cg, Field model) {
        return Optional.of("<field name=\"" + model.getName() + "\" />");
    }
}

Results

When the application above is executed, the following will be outputed:

-------------------------------------
  JavaInstaller:
-------------------------------------
public java.lang.String concat(java.lang.String str1, <field name="str1" />, java.lang.String str2, <field name="str2" />) {
    return str1 + str2;
}
-------------------------------------
  XMLInstaller:
-------------------------------------
<method name="concat" type="java.lang.String">
    <params>
        <field name="str1" />
        <field name="str2" />
    </params>
    <code>
        return str1 + str2;
    </code>
</methods>

The same model is rendered in two different languages using the same rendering pipeline.

⚠️ **GitHub.com Fallback** ⚠️