User Defined Transformer

[create]Create the class/method

In order to create a user defined transformer, you need to create a class with transform methods and annotate it with @org.rythmengine.extension.Transformer annotation. When a class is annotated with @Transformer, all public static method with return type are treated as transform methods. For example, in the TransformerTest.java we defined three transform methods which provides dbl semantic to Integer, String and general Object type:

@Transformer
public class TransformerTest extends TestBase {
    public static Integer dbl(Integer i) {
        return i * 2;
    }
    public static String dbl(String s) {
        if (null == s) return "";
        return s + s;
    }
    public static String dbl(Object o) {
        if (null == o) return "";
        return dbl(o.toString());
    }
    ...
}

The Transformer annotation could also be used on a single method instead of the entire class, which makes it really easy to add specific transformer to your domain model classes. For example, in the Order.java class we defined a transform method asCurrency

    @Transformer(requireTemplate = true)
    public static String asCurrency(int amount) {
        return asCurrency(null, amount);
    }
    public static String asCurrency(ITemplate template, int amount) {
        Double d = (float)amount / 100.00;
        return S.formatCurrency(template, d, null, null);
    }
Note in this transformer annotation we have specified requireTemplate parameter to true because we need the localization context of the template to format currency.

[register]Register transformer

After you defined the transformer classes/methods you need to register them to the RythmEngine. You can find relevant code in the TransformerTest.java file:

@Test
public void testUserDefinedTransformer() {
    Rythm.engine().registerTransformer(TransformerTest.class);
    String t = "@args String s, int i\n" +
            "double of \"@s\" is \"@s.app_dbl()\",\n " +
            "double of [@i] is [@i.app_dbl().format(\"0000.00\")]";
    String s = Rythm.render(t, "Java", 99);
    assertContains(s, "double of \"Java\" is \"JavaJava\"");
    assertContains(s, "double of [99] is [0198.00]");
}
@Test
public void testUserDefinedTransformerWithNamespace() {
    // test register with namespace specified
    Rythm.engine().registerTransformer("foo", "", TransformerTest.class);
    String t = "@args String s, int i\n" +
            "double of \"@s\" is \"@s.foo_dbl()\",\n " +
            "double of [@i] is [@i.foo_dbl().format(\"0000.00\")]";
    String s = Rythm.render(t, "Java", 99);
    assertContains(s, "double of \"Java\" is \"JavaJava\"");
    assertContains(s, "double of [99] is [0198.00]");
}

So as it shows above, there are two RythmEngine methods you can use to register your transformers:

The first method accept an array of classes, and the second method has one additional parameter to define the namespace. Once an namespace is specified, then you need to invoke transformer with namespace_<transformer> notation. As shown in the above code, when you register the transformer without namespace specified, the namespace is the default “app”, so you invoke the transformer in your template code using app_:

double of "@s" is "@s.app_dbl()"

And when you registered the transformer with namespace foo, your template code should be:

double of "@s" is "@s.foo_dbl()"

You can also specify the namespace in the @Transformer annotation when you define the transformer class or methods:

@Transformer("foo")
public static String transformXX(...)

[see]See also

Loading fiddles ...