CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-immutables--value

Compile-time annotation processor for generating immutable value objects with builder patterns and compile-time validation.

Pending
Overview
Eval results
Files

style-configuration.mddocs/

Style and Configuration

Comprehensive styling system for customizing naming conventions, generation behavior, validation methods, and code structure. The @Value.Style annotation provides extensive configuration options for tailoring generated code to specific project requirements.

Capabilities

Value.Style Annotation

Central configuration annotation for customizing all aspects of code generation.

/**
 * Naming and structural style configuration for generated immutable 
 * implementations and companion classes. Can be placed on class, package,
 * or used as meta-annotation.
 */
@interface Value.Style {
    // Naming templates for method recognition and generation
    String[] get() default "get*";
    String init() default "*";
    String with() default "with*";
    String withUnaryOperator() default "";
    String add() default "add*";
    String addAll() default "addAll*";
    String put() default "put*";
    String putAll() default "putAll*";
    String copyOf() default "copyOf";
    String of() default "of";
    String instance() default "of";
    String builder() default "builder";
    String newBuilder() default "new";
    String from() default "from";
    String build() default "build";
    String buildOrThrow() default "";
    String canBuild() default "";
    String toBuilder() default "";
    String set() default "set*";
    String unset() default "unset*";
    String clear() default "clear";
    String create() default "create";
    String toImmutable() default "toImmutable";
    String isInitialized() default "isInitialized";
    String isSet() default "*IsSet";
    
    // Type naming templates
    String typeImmutable() default "Immutable*";
    String typeBuilder() default "Builder";
    String typeInnerBuilder() default "Builder";
    String[] typeAbstract() default "Abstract*";
    String typeImmutableEnclosing() default "Immutable*";
    String typeImmutableNested() default "*";
    String typeModifiable() default "Modifiable*";
    String typeInnerModifiable() default "Modifiable";
    String typeWith() default "With*";
    String packageGenerated() default "*";
    
    // Behavioral configuration flags
    boolean strictBuilder() default false;
    boolean strictModifiable() default true;
    boolean allParameters() default false;
    boolean jdkOnly() default false;
    boolean jdk9Collections() default false;
    ValidationMethod validationMethod() default ValidationMethod.SIMPLE;
    ImplementationVisibility visibility() default ImplementationVisibility.SAME;
    BuilderVisibility builderVisibility() default BuilderVisibility.PUBLIC;
    String visibilityString() default "";
    String builderVisibilityString() default "";
    
    // Advanced configuration options
    boolean depluralize() default false;
    String[] depluralizeDictionary() default {};
    boolean deepImmutablesDetection() default false;
    boolean stagedBuilder() default false;
    boolean optionalAcceptNullable() default false;
    boolean generateSuppressAllWarnings() default true;
    boolean privateNoargConstructor() default false;
    boolean protectedNoargConstructor() default false;
    boolean attributelessSingleton() default false;
    boolean unsafeDefaultAndDerived() default false;
    boolean clearBuilder() default false;
    boolean deferCollectionAllocation() default false;
    boolean overshadowImplementation() default false;
    boolean implementationNestedInBuilder() default false;
    boolean forceJacksonPropertyNames() default true;
    boolean forceJacksonIgnoreFields() default false;
    boolean forceEqualsInWithers() default false;
    boolean jacksonIntegration() default true;
    boolean weakInterning() default false;
    boolean alwaysPublicInitializers() default true;
    boolean builtinContainerAttributes() default true;
    boolean beanFriendlyModifiables() default false;
    boolean allMandatoryParameters() default false;
    boolean transientDerivedFields() default true;
    boolean finalInstanceFields() default true;
    boolean attributeBuilderDetection() default false;
    String redactedMask() default "";
    String nullableAnnotation() default "Nullable";
    String[] attributeBuilder() default {"Builder", "*Builder", "builder", "from", "build", "*Build", "new"};
    String getBuilder() default "*Builder";
    String setBuilder() default "*Builder";  
    String addBuilder() default "add*Builder";
    String addAllBuilder() default "addAll*Builders";
    String getBuilders() default "*Builders";
    Class<? extends RuntimeException> throwForInvalidImmutableState() default IllegalStateException.class;
    Class<? extends RuntimeException> throwForNullPointer() default NullPointerException.class;
    Class<? extends Annotation>[] passAnnotations() default {};
    Class<? extends Annotation>[] additionalJsonAnnotations() default {};
    Class<?>[] immutableCopyOfRoutines() default {};
    Class<? extends Annotation>[] allowedClasspathAnnotations() default {};
    Class<? extends Annotation> fallbackNullableAnnotation() default Inherited.class;
    int limitStringLengthInToString() default 0;
    boolean headerComments() default false;
    boolean defaultAsDefault() default false;
    boolean jakarta() default false;
}

Naming Template Customization

Control method and type naming conventions throughout generated code.

Usage Examples:

// Custom naming style
@Value.Style(
    typeImmutable = "*Impl",           // Generate PersonImpl instead of ImmutablePerson
    typeBuilder = "*Builder",          // Generate PersonBuilder 
    get = {"get*", "is*"},            // Recognize both get* and is* prefixes
    with = "set*",                    // Use set* instead of with* for copy methods
    init = "set*"                     // Use set* for builder methods
)
@Value.Immutable
public interface Person {
    String getName();
    boolean isActive();
}

// Generated class: PersonImpl with PersonBuilder
PersonImpl person = PersonImpl.builder()
    .setName("John")
    .setActive(true)
    .build();

PersonImpl updated = person.setName("Jane"); // Copy method

// Bean-style naming
@Value.Style(
    get = {"get*", "is*"},
    init = "set*",
    with = "set*", 
    typeImmutable = "*Bean"
)
@Value.Immutable
public interface UserBean {
    String getName();
    boolean isEnabled();
}

// Usage follows JavaBean conventions
UserBeanBean user = UserBeanBean.builder()
    .setName("Alice")
    .setEnabled(true)
    .build();

Builder Behavior Configuration

Control builder generation and behavior patterns.

/**
 * Builder behavior configuration options
 */
boolean strictBuilder() default false;     // Forward-only builders
boolean stagedBuilder() default false;     // Telescopic/staged builders  
boolean clearBuilder() default false;      // Generate clear() method
String canBuild() default "";             // Generate canBuild() method
String buildOrThrow() default "";         // Generate buildOrThrow() method

Usage Examples:

// Strict builders - forward-only, no reset
@Value.Style(strictBuilder = true)
@Value.Immutable
public interface Config {
    String name();
    int value();
    List<String> tags();
}

// Strict builder prevents re-initialization
ImmutableConfig.Builder builder = ImmutableConfig.builder();
builder.name("test");
// builder.name("other"); // Would throw exception
builder.addTags("tag1", "tag2");
// builder.tags(List.of("different")); // No reset method generated

// Staged/telescopic builders - compile-time safety
@Value.Style(stagedBuilder = true)
@Value.Immutable  
public interface Connection {
    String host();
    int port();
    @Value.Default
    default int timeout() { return 30; }
}

// Staged builder enforces mandatory attributes first
ImmutableConnection connection = ImmutableConnection.builder()
    .host("localhost")    // Must set host first
    .port(8080)          // Then port
    .timeout(60)         // Optional attributes can be set in any order
    .build();

// Enhanced builder methods
@Value.Style(
    canBuild = "isReady",
    buildOrThrow = "buildOrThrow"
)
@Value.Immutable
public interface Request {
    String method();
    String url();
}

ImmutableRequest.Builder builder = ImmutableRequest.builder();
builder.method("GET");

if (builder.isReady()) {           // Check if can build
    Request req = builder.build();
} else {
    Request req = builder.buildOrThrow(() -> 
        new IllegalStateException("Missing required fields"));
}

Validation Method Configuration

Configure validation behavior for generated objects.

/**
 * Validation method options for generated immutable objects
 */
enum ValidationMethod {
    NONE,           // No validation, allow nulls and missing required fields
    MANDATORY_ONLY, // Check required fields provided (even if null)
    SIMPLE,         // Standard null-hostile validation (default)
    VALIDATION_API  // Use JSR 303 Bean Validation API
}

Usage Examples:

// Disable validation completely
@Value.Style(validationMethod = ValidationMethod.NONE)
@Value.Immutable
public interface Lenient {
    String name();      // Can be null
    int count();        // Will be 0 if not provided
}

// Lenient validation allows nulls and missing fields
Lenient lenient = ImmutableLenient.builder().build(); // No errors

// Mandatory-only validation
@Value.Style(validationMethod = ValidationMethod.MANDATORY_ONLY)
@Value.Immutable
public interface MandatoryCheck {
    String name();
    @Value.Default
    default int count() { return 0; }
}

// Must provide name (even if null), count is optional
MandatoryCheck obj1 = ImmutableMandatoryCheck.builder()
    .name(null)    // Allowed - null is provided
    .build();

// MandatoryCheck obj2 = ImmutableMandatoryCheck.builder().build(); // Error - name not provided

// JSR 303 Bean Validation
@Value.Style(validationMethod = ValidationMethod.VALIDATION_API)
@Value.Immutable
public interface ValidatedUser {
    @NotNull @Size(min = 2)
    String name();
    
    @NotNull @Email
    String email();
    
    @Min(0) @Max(120)
    int age();
}

// Uses Bean Validation annotations for validation
ValidatedUser user = ImmutableValidatedUser.builder()
    .name("John")
    .email("john@example.com")
    .age(25)
    .build(); // Validates constraints

Visibility and Access Control

Control the visibility of generated classes and methods.

/**
 * Implementation visibility options
 */
enum ImplementationVisibility {
    PUBLIC,           // Generated class forced to be public
    SAME,            // Same visibility as abstract type
    SAME_NON_RETURNED, // Same visibility, abstract type returned from factories
    PACKAGE,         // Package visibility
    PRIVATE          // Private visibility (requires builder or enclosing)
}

enum BuilderVisibility {
    PUBLIC,  // Builder forced to be public
    SAME,    // Same visibility as abstract type  
    PACKAGE  // Package visibility
}

Usage Examples:

// Private implementation with public builder
@Value.Style(
    visibility = ImplementationVisibility.PRIVATE,
    builderVisibility = BuilderVisibility.PUBLIC
)
@Value.Immutable
public interface PrivateImpl {
    String value();
}

// Implementation class is private, only accessible via builder
// PrivateImpl obj = ImmutablePrivateImpl.of("test"); // Not accessible
PrivateImpl obj = ImmutablePrivateImpl.builder().value("test").build(); // OK

// Package-private implementation
@Value.Style(visibility = ImplementationVisibility.PACKAGE)
@Value.Immutable
public interface PackagePrivate {
    String data();
}

// Generated ImmutablePackagePrivate has package visibility

Advanced Configuration Options

Specialized configuration for complex scenarios and performance optimization.

/**
 * Advanced configuration options
 */
boolean allParameters() default false;              // All attributes become parameters
boolean deepImmutablesDetection() default false;   // Enhanced type analysis
boolean jdkOnly() default false;                   // Use only JDK collections
boolean jdk9Collections() default false;           // Use JDK 9+ immutable collections
boolean depluralize() default false;               // Depluralize collection method names
boolean weakInterning() default false;             // Use weak references for interning
boolean forceJacksonPropertyNames() default true;  // Force Jackson property names

Usage Examples:

// All parameters style for tuple-like objects
@Value.Style(
    allParameters = true,
    typeImmutable = "*Tuple",
    defaults = @Value.Immutable(builder = false)
)
@Value.Immutable
public interface Point {
    double x();
    double y();
    
    @Value.Parameter(false) // Exclude from parameters
    @Value.Derived
    default double magnitude() {
        return Math.sqrt(x() * x() + y() * y());
    }
}

// Only constructor available: ImmutablePointTuple.of(x, y)
Point point = ImmutablePointTuple.of(3.0, 4.0);

// Deep immutables detection for enhanced builder methods
@Value.Style(deepImmutablesDetection = true)
@Value.Immutable
public interface Container {
    Point location();
    List<Point> waypoints();
}

// Enhanced builder with shortcut methods
Container container = ImmutableContainer.builder()
    .location(3.0, 4.0)           // Shortcut for ImmutablePoint.of(3.0, 4.0)
    .addWaypoints(1.0, 1.0)       // Shortcut for waypoints list
    .addWaypoints(2.0, 2.0)
    .build();

// Collection method depluralization
@Value.Style(
    depluralize = true,
    depluralizeDictionary = {"person:people", "child:children"}
)
@Value.Immutable
public interface Family {
    List<String> people();    // addPerson(), addAllPeople()
    List<String> children();  // addChild(), addAllChildren() 
    List<String> items();     // addItem(), addAllItems()
}

ImmutableFamily family = ImmutableFamily.builder()
    .addPerson("Alice")      // Singular form
    .addChild("Bob")         // Custom depluralization
    .addItem("laptop")       // Standard depluralization
    .build();

Install with Tessl CLI

npx tessl i tessl/maven-org-immutables--value

docs

advanced-features.md

attributes.md

core-immutable.md

index.md

style-configuration.md

validation.md

tile.json