Comprehensive Java annotation processing framework for generating immutable value objects, marshalers, repositories, and custom code generators with extensive integration support.
—
Advanced annotation processing framework for creating custom code generators and template-based processors. The Generator framework provides the foundation for building sophisticated annotation processors beyond the basic immutable value generation.
Mark classes as template definitions for code generation.
/**
* Generates "generator" subclass of annotated template definition.
* It is recommended that annotated class also extend AbstractTemplate
* so default templating language capabilities will be accessible.
*/
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
@interface Generator.Template {}Usage Example:
@Generator.Template
public abstract class PersonTemplate extends AbstractTemplate {
@Generator.Typedef
java.util.List<String> StringList;
public void generate() {
for (TypeElement type : annotations()) {
generateForType(type);
}
}
private void generateForType(TypeElement type) {
// Template generation logic here
out("// Generated code for: " + type.getSimpleName());
}
}Import classes as simple name aliases for template language.
/**
* Imports classes as simple name aliases to be available to template language.
* Special kind of annotation inheritance works. All imports combined together
* from @Generator.Import annotations of template classes and enclosing packages,
* as well as from superclasses and their respective packages.
*/
@Inherited
@Target({ ElementType.TYPE, ElementType.PACKAGE })
@Retention(RetentionPolicy.SOURCE)
@interface Generator.Import {
Class<?>[] value();
}Usage Example:
@Generator.Template
@Generator.Import({
java.util.List.class,
java.util.Map.class,
com.example.CustomType.class
})
public abstract class MyTemplate extends AbstractTemplate {
// Can now use List, Map, CustomType as simple names in templates
}Define complex types as simple type names for template language.
/**
* Used to introduce complex types as simple type names available to template language.
* Annotate fields with this annotation to introduce such typedef. Fields should be
* named starting with uppercase, so template will recognize it as type identifier.
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
@interface Generator.Typedef {}Usage Example:
@Generator.Template
public abstract class CollectionTemplate extends AbstractTemplate {
@Generator.Typedef
java.util.Map.Entry<String, String> StringPair;
@Generator.Typedef
java.util.List<java.util.Map<String, Object>> DataList;
// Can now use StringPair and DataList as simple type names
}Cache method results for improved performance during template processing.
/**
* This annotation is used for memoization of methods or types (caching results).
* Applied to methods to avoid repeated computation of expensive operations.
*/
@Documented
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.SOURCE)
@interface Generator.Memoised {}Usage Example:
@Generator.Template
public abstract class OptimizedTemplate extends AbstractTemplate {
@Generator.Memoised
protected String computeExpensiveValue(TypeElement type) {
// Expensive computation that gets cached
return performComplexAnalysis(type);
}
}Declare which annotations the processor handles.
/**
* Applies to the annotation processor extending AbstractGenerator to supply
* annotation names that processor will handle. Could be used instead of
* @SupportedAnnotationTypes, which is also supported.
*/
@Target({ ElementType.TYPE, ElementType.PACKAGE })
@Retention(RetentionPolicy.RUNTIME)
@interface Generator.SupportedAnnotations {
Class<? extends Annotation>[] value();
}Usage Example:
@Generator.SupportedAnnotations({
MyCustomAnnotation.class,
AnotherAnnotation.class
})
public class MyAnnotationProcessor extends AbstractGenerator {
@Override
protected void process() {
// Process the supported annotations
}
}Core class for template invocation, handling output generation and parameter management.
/**
* Template invocation context providing output methods and parameter access.
* Used within template methods to generate code and handle parameters.
*/
public final static class Templates.Invokation {
/** Get the number of parameters passed to this invocation */
public int arity();
/** Get parameter at specified index */
public Object param(int ordinal);
/** Enable delimiter handling for cleaner output formatting */
public Invokation delimit();
/** Output a newline character */
public Invokation ln();
/** Output a string */
public Invokation out(String string);
/** Output an object (converted to string) */
public Invokation out(@Nullable Object content);
/** Output multiple objects */
public Invokation out(Object... objects);
/** Set current position for indentation management */
public Invokation pos(int pos);
}Abstract base class for reusable template fragments.
/**
* Abstract base class for template fragments that can be invoked with parameters.
* Provides captured indentation and parameter management for reusable code blocks.
*/
public static abstract class Templates.Fragment implements Invokable {
/** Create fragment with specified arity and captured invocation context */
protected Fragment(int arity, @Nullable Invokation capturedInvokation);
/** Create fragment with specified arity */
protected Fragment(int arity);
/** Get the number of parameters this fragment expects */
public int arity();
/** Run the fragment with given invocation context */
public abstract void run(Invokation invokation);
/** Invoke fragment with parameters, returning null or nested invokable */
@Nullable
public Invokable invoke(Invokation invokation, Object... params);
/** Convert fragment to character sequence */
CharSequence toCharSequence();
/** Convert fragment to string representation */
public String toString();
}Core interface for objects that can be invoked in template context.
/**
* Interface for objects that can be invoked within template processing.
* Enables composition and chaining of template operations.
*/
public interface Templates.Invokable {
/**
* Invoke with parent invocation context and parameters
* @return null or nested invokable for chained operations
*/
@Nullable
Invokable invoke(Invokation parentInvokation, Object... parameters);
/** Get the number of parameters this invokable expects */
int arity();
}Base class for template definitions with built-in templating capabilities.
/**
* Abstract base class for template definitions, extending built-in template
* language capabilities and providing access to processing environment.
*/
public abstract class AbstractTemplate extends Builtins {
/** Get the annotation processing environment */
protected final ProcessingEnvironment processing();
/** Get the current round environment */
protected final RoundEnvironment round();
/** Get the set of annotation types being processed */
protected final Set<TypeElement> annotations();
}Base class for annotation processors using the Generator framework.
/**
* Abstract base class for annotation processors using the Generator framework.
* Extends AbstractProcessor with template invocation capabilities.
*/
public abstract class AbstractGenerator extends AbstractProcessor {
/** Main processing method to be implemented by subclasses */
protected abstract void process();
/** Get the annotation processing environment */
protected final ProcessingEnvironment processing();
/** Get the current round environment */
protected final RoundEnvironment round();
/** Get the set of annotation types being processed */
protected final Set<TypeElement> annotations();
/** Invoke a template or fragment */
protected final void invoke(Templates.Invokable invokable);
}@Generator.SupportedAnnotations(MyAnnotation.class)
public class MyProcessor extends AbstractGenerator {
@Override
protected void process() {
for (TypeElement type : annotations()) {
processAnnotatedType(type);
}
}
private void processAnnotatedType(TypeElement type) {
MyTemplate template = new MyTemplateGenerator();
template.setProcessingEnvironment(processing());
template.setRoundEnvironment(round());
template.generateForType(type);
}
}@Generator.Template
public abstract class ComponentTemplate extends AbstractTemplate {
protected final Fragment methodFragment = new Fragment(2) {
@Override
public void run(Invokation invokation) {
String methodName = (String) invokation.param(0);
String returnType = (String) invokation.param(1);
invokation
.out("public ").out(returnType).out(" ").out(methodName).out("() {").ln()
.out(" // Generated method implementation").ln()
.out("}").ln();
}
};
public void generateClass(String className) {
out("public class ").out(className).out(" {").ln();
methodFragment.invoke(null, "getName", "String");
methodFragment.invoke(null, "getId", "Long");
out("}").ln();
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-immutables--immutables