Class GenerateVisitorAnnotationProcessor

java.lang.Object
javax.annotation.processing.AbstractProcessor
com.apple.foundationdb.annotation.GenerateVisitorAnnotationProcessor
All Implemented Interfaces:
Processor

@AutoService(javax.annotation.processing.Processor.class) public class GenerateVisitorAnnotationProcessor extends AbstractProcessor

Annotation processor to automatically generate a visitor class for the entire class hierarchy underneath the annotated root class or all implementors of an annotated interface within the unit of compilation. In that sense the annotation views the class/interface hierarchy as a sealed trait.

Please see GenerateVisitor for a more conceptual overview. First, the annotation processor discovers all extending/implementing (non-abstract) classes of the annotated interface or class. Due to the way java compiles a module/sub-project/compilation unit, subclasses/implementors in downstream projects are naturally not discoverable.

Once a set of classes has been discovered, we generate a visitor interface (for convenient mix-ins rather than a superclass) that has a visitation method for each discovered class CLAZZ:

... T visitCLAZZ(@Nonnull final CLAZZ element); ...

In addition to a specific visitation method for each such CLAZZ, there are two other methods defined:

default T visit(@Nonnull final ANNOTATED_ROOT_CLASS element) ...

The default implementation of this method is to dispatch over the dynamic type of the argument element to the specific visitation methods. If element's dynamic type is unknown to the visitor, the method:

default T visitDefault(@Nonnull final ANNOTATED_ROOT_CLASS element);

is called. All methods except visit() itself must be implemented by the user. Using the annotation processor makes sure every subclass known to the compiler is represented by its own visitation method and is adequately dispatched to. Due to the encoded dispatching, the original class hierarchy does not need to implement an accept() method.

In cases where generic code takes care of the bulk of the logic but there may be some specialization for a few subclasses, a second interface called ...WithDefaults is created with default implementations of all visitation methods which just call visitDefault(). You can implement the generic logic in visitDefault(), implement the specific overrides by overriding the specific visitation method.