All Articles

a simple pattern processor

Sometimes you don’t want to use a full-blown third party library to process templates in your app or you need some custom functionality and therefore you decide to roll your own.

A template usually has some variable placeholders, like ${variableName} or {{variable-name}}. Such a template can then be processed with a specific context providing assignments for these variables. You could go further by allowing arbitrary variables nesting, like ${variableName${suffixName}}, sections, lists, delimiter switching etc. We’ll stick with the simplest case here.

We define a simple TemplateProcessor whose context can be reset (setContext) or augmented by setting the contained variables (putContext), and then write the processed template to some writer:

TemplateProcessor p = new TemplateProcessor();
Writer writer = ...

p.putContext(context);
p.process(template1, writer);

p.putContext(addictionContext);
p.process(template2, writer);

or return the result directly as a string:

String result = p.process(template);

The context at its simplest form is just a wrapper on top of a map:

TemplateContext context = TemplateContext.from(of("varA", objA, "varB", objB));
context.putAll(moreVarsMap);
context.putAllFrom(yetAnotherCtx);

Variable values are serialized using their natural toString() but we could extend it to use custom serialization. We can further specify how we’d like to treat unassigned variables, for example leave-as-is (leaveMissing()), omit completely (omitMissing) or replace with some set value (replaceMissing()).

The only other thing that might help is create some sort of context sources pertaining to your application like device information:

public final class TemplateContexts {
  private TemplateContexts() {}

  public static TemplateContext fromDeviceInfo(DeviceInfo info) {
    return new TemplateContext()
        .put("device-brand", info.getBrand())
        .put("device-device", info.getDevice())
        .put("device-fingerprint", info.getFingerprint())
        .put("device-manufacturer", info.getManufacturer())
        .put("device-model", info.getModel())
        .put("device-product", info.getProduct());
  }

  ...

or some other means suitable to your app.

An implementation of such a simple parser can be found in this github gist.