Class AccessorRegistry

java.lang.Object
org.klojang.templates.AccessorRegistry

public final class AccessorRegistry extends Object

A registry of accessors. Accessors are used by the insert() and populate() methods of the RenderSession class to extract values from data provided by the data access layer. This is how an AccessorRegistry decides which accessor to use for a particular type of object:

  1. If you have registered your own Accessor for that particular type of object, then that is the Accessor that is going to be used.
  2. Otherwise an internally defined, non-exposed Accessor implementation will be used. This Accessor implementation is very versatile and can read almost any type of object. It is internally backed by a PathWalker.

Note that the internally defined Accessor mentioned above does not use reflection to read bean properties, but it does use reflection to figure out what those properties are in the first place. Thus, if the JavaBeans are inside a Java 9+ module, you must open the module to Klojang Templates. Irrespective of whether the JavaBeans are inside a Java 9+ module, both the bean class and the bean properties must be public.

Alternatively, you could write your own Accessor:


 Accessor<Person> personAccessor =
   (person, property) -> switch(property) {
       case "id" : return person.getId();
       case "firstName" : return person.getFirstName();
       case "lastName" : return person.getLastName();
       case "birthDate" : return person.getBirthDate();
       default : return Accessor.UNDEFINED;
   };
 AccessorRegistry accessors = AccessorRegistry
   .configure()
   .register(Person.class, new PersonAccessor())
   .freeze();
 RenderSession session = template.newRenderSession(accessors);
 

A slightly less verbose, but still fully reflection-free alternative is to use a BeanReaderBuilder:


 // forClass returns a BeanReaderBuilder
 BeanReader beanReader = BeanReader.forClass(Person.class)
    .withInt("id")
    .withString("firstName", "lastName")
    .with(LocalDate.class, "birthDate"))
    .build();
 AccessorRegistry accessors = AccessorRegistry
   .configure()
   .register(beanReader)
   .freeze();
 RenderSession session = template.newRenderSession(accessors);
 

In practice, you would likely create just a single AccessorRegistry instance for your entire application, when it starts up, and pass that instance to all calls to Template.newRenderSession().

Author:
Ayco Holleman
See Also:
  • Field Details

    • STANDARD_ACCESSORS

      public static final AccessorRegistry STANDARD_ACCESSORS
      The default AccessorRegistry. It assumes that template variables map as-is to names used in source data objects.
  • Method Details

    • standard

      public static AccessorRegistry standard(NameMapper nameMapper)
      Returns an AccessorRegistry that should be sufficient for most use cases. It allows you to specify one global NameMapper for mapping the template variables to the names used in source data objects.
      Parameters:
      nameMapper - the NameMapper to be used to map template variables to bean properties and/or map keys.
      Returns:
      an AccessorRegistry the should sufficient for most use cases
    • standard

      public static AccessorRegistry standard(boolean nullEqualsUndefined)
      Returns an AccessorRegistry that should be sufficient for most use cases.
      Parameters:
      nullEqualsUndefined - whether null values should be treated the same way as Accessor.UNDEFINED
      Returns:
      an AccessorRegistry the should sufficient for most use cases
    • standard

      public static AccessorRegistry standard(NameMapper nameMapper, boolean nullEqualsUndefined)
      Returns an AccessorRegistry that should be sufficient for most use cases. It allows you to specify one global NameMapper for mapping the template variables to the names used in source data objects.
      Parameters:
      nameMapper - the NameMapper to be used to map template variables to bean properties and/or map keys.
      nullEqualsUndefined - whether null values should be treated the same way as Accessor.UNDEFINED
      Returns:
      an AccessorRegistry the should sufficient for most use cases
    • configure

      public static AccessorRegistry.Builder configure()
      Returns a Builder object that lets you configure an AccessorRegistry.
      Returns:
      a Builder object that lets you configure an AccessorRegistry