0
# Style and Configuration
1
2
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.
3
4
## Capabilities
5
6
### Value.Style Annotation
7
8
Central configuration annotation for customizing all aspects of code generation.
9
10
```java { .api }
11
/**
12
* Naming and structural style configuration for generated immutable
13
* implementations and companion classes. Can be placed on class, package,
14
* or used as meta-annotation.
15
*/
16
@interface Value.Style {
17
// Naming templates for method recognition and generation
18
String[] get() default "get*";
19
String init() default "*";
20
String with() default "with*";
21
String withUnaryOperator() default "";
22
String add() default "add*";
23
String addAll() default "addAll*";
24
String put() default "put*";
25
String putAll() default "putAll*";
26
String copyOf() default "copyOf";
27
String of() default "of";
28
String instance() default "of";
29
String builder() default "builder";
30
String newBuilder() default "new";
31
String from() default "from";
32
String build() default "build";
33
String buildOrThrow() default "";
34
String canBuild() default "";
35
String toBuilder() default "";
36
String set() default "set*";
37
String unset() default "unset*";
38
String clear() default "clear";
39
String create() default "create";
40
String toImmutable() default "toImmutable";
41
String isInitialized() default "isInitialized";
42
String isSet() default "*IsSet";
43
44
// Type naming templates
45
String typeImmutable() default "Immutable*";
46
String typeBuilder() default "Builder";
47
String typeInnerBuilder() default "Builder";
48
String[] typeAbstract() default "Abstract*";
49
String typeImmutableEnclosing() default "Immutable*";
50
String typeImmutableNested() default "*";
51
String typeModifiable() default "Modifiable*";
52
String typeInnerModifiable() default "Modifiable";
53
String typeWith() default "With*";
54
String packageGenerated() default "*";
55
56
// Behavioral configuration flags
57
boolean strictBuilder() default false;
58
boolean strictModifiable() default true;
59
boolean allParameters() default false;
60
boolean jdkOnly() default false;
61
boolean jdk9Collections() default false;
62
ValidationMethod validationMethod() default ValidationMethod.SIMPLE;
63
ImplementationVisibility visibility() default ImplementationVisibility.SAME;
64
BuilderVisibility builderVisibility() default BuilderVisibility.PUBLIC;
65
String visibilityString() default "";
66
String builderVisibilityString() default "";
67
68
// Advanced configuration options
69
boolean depluralize() default false;
70
String[] depluralizeDictionary() default {};
71
boolean deepImmutablesDetection() default false;
72
boolean stagedBuilder() default false;
73
boolean optionalAcceptNullable() default false;
74
boolean generateSuppressAllWarnings() default true;
75
boolean privateNoargConstructor() default false;
76
boolean protectedNoargConstructor() default false;
77
boolean attributelessSingleton() default false;
78
boolean unsafeDefaultAndDerived() default false;
79
boolean clearBuilder() default false;
80
boolean deferCollectionAllocation() default false;
81
boolean overshadowImplementation() default false;
82
boolean implementationNestedInBuilder() default false;
83
boolean forceJacksonPropertyNames() default true;
84
boolean forceJacksonIgnoreFields() default false;
85
boolean forceEqualsInWithers() default false;
86
boolean jacksonIntegration() default true;
87
boolean weakInterning() default false;
88
boolean alwaysPublicInitializers() default true;
89
boolean builtinContainerAttributes() default true;
90
boolean beanFriendlyModifiables() default false;
91
boolean allMandatoryParameters() default false;
92
boolean transientDerivedFields() default true;
93
boolean finalInstanceFields() default true;
94
boolean attributeBuilderDetection() default false;
95
String redactedMask() default "";
96
String nullableAnnotation() default "Nullable";
97
String[] attributeBuilder() default {"Builder", "*Builder", "builder", "from", "build", "*Build", "new"};
98
String getBuilder() default "*Builder";
99
String setBuilder() default "*Builder";
100
String addBuilder() default "add*Builder";
101
String addAllBuilder() default "addAll*Builders";
102
String getBuilders() default "*Builders";
103
Class<? extends RuntimeException> throwForInvalidImmutableState() default IllegalStateException.class;
104
Class<? extends RuntimeException> throwForNullPointer() default NullPointerException.class;
105
Class<? extends Annotation>[] passAnnotations() default {};
106
Class<? extends Annotation>[] additionalJsonAnnotations() default {};
107
Class<?>[] immutableCopyOfRoutines() default {};
108
Class<? extends Annotation>[] allowedClasspathAnnotations() default {};
109
Class<? extends Annotation> fallbackNullableAnnotation() default Inherited.class;
110
int limitStringLengthInToString() default 0;
111
boolean headerComments() default false;
112
boolean defaultAsDefault() default false;
113
boolean jakarta() default false;
114
}
115
```
116
117
### Naming Template Customization
118
119
Control method and type naming conventions throughout generated code.
120
121
**Usage Examples:**
122
123
```java
124
// Custom naming style
125
@Value.Style(
126
typeImmutable = "*Impl", // Generate PersonImpl instead of ImmutablePerson
127
typeBuilder = "*Builder", // Generate PersonBuilder
128
get = {"get*", "is*"}, // Recognize both get* and is* prefixes
129
with = "set*", // Use set* instead of with* for copy methods
130
init = "set*" // Use set* for builder methods
131
)
132
@Value.Immutable
133
public interface Person {
134
String getName();
135
boolean isActive();
136
}
137
138
// Generated class: PersonImpl with PersonBuilder
139
PersonImpl person = PersonImpl.builder()
140
.setName("John")
141
.setActive(true)
142
.build();
143
144
PersonImpl updated = person.setName("Jane"); // Copy method
145
146
// Bean-style naming
147
@Value.Style(
148
get = {"get*", "is*"},
149
init = "set*",
150
with = "set*",
151
typeImmutable = "*Bean"
152
)
153
@Value.Immutable
154
public interface UserBean {
155
String getName();
156
boolean isEnabled();
157
}
158
159
// Usage follows JavaBean conventions
160
UserBeanBean user = UserBeanBean.builder()
161
.setName("Alice")
162
.setEnabled(true)
163
.build();
164
```
165
166
### Builder Behavior Configuration
167
168
Control builder generation and behavior patterns.
169
170
```java { .api }
171
/**
172
* Builder behavior configuration options
173
*/
174
boolean strictBuilder() default false; // Forward-only builders
175
boolean stagedBuilder() default false; // Telescopic/staged builders
176
boolean clearBuilder() default false; // Generate clear() method
177
String canBuild() default ""; // Generate canBuild() method
178
String buildOrThrow() default ""; // Generate buildOrThrow() method
179
```
180
181
**Usage Examples:**
182
183
```java
184
// Strict builders - forward-only, no reset
185
@Value.Style(strictBuilder = true)
186
@Value.Immutable
187
public interface Config {
188
String name();
189
int value();
190
List<String> tags();
191
}
192
193
// Strict builder prevents re-initialization
194
ImmutableConfig.Builder builder = ImmutableConfig.builder();
195
builder.name("test");
196
// builder.name("other"); // Would throw exception
197
builder.addTags("tag1", "tag2");
198
// builder.tags(List.of("different")); // No reset method generated
199
200
// Staged/telescopic builders - compile-time safety
201
@Value.Style(stagedBuilder = true)
202
@Value.Immutable
203
public interface Connection {
204
String host();
205
int port();
206
@Value.Default
207
default int timeout() { return 30; }
208
}
209
210
// Staged builder enforces mandatory attributes first
211
ImmutableConnection connection = ImmutableConnection.builder()
212
.host("localhost") // Must set host first
213
.port(8080) // Then port
214
.timeout(60) // Optional attributes can be set in any order
215
.build();
216
217
// Enhanced builder methods
218
@Value.Style(
219
canBuild = "isReady",
220
buildOrThrow = "buildOrThrow"
221
)
222
@Value.Immutable
223
public interface Request {
224
String method();
225
String url();
226
}
227
228
ImmutableRequest.Builder builder = ImmutableRequest.builder();
229
builder.method("GET");
230
231
if (builder.isReady()) { // Check if can build
232
Request req = builder.build();
233
} else {
234
Request req = builder.buildOrThrow(() ->
235
new IllegalStateException("Missing required fields"));
236
}
237
```
238
239
### Validation Method Configuration
240
241
Configure validation behavior for generated objects.
242
243
```java { .api }
244
/**
245
* Validation method options for generated immutable objects
246
*/
247
enum ValidationMethod {
248
NONE, // No validation, allow nulls and missing required fields
249
MANDATORY_ONLY, // Check required fields provided (even if null)
250
SIMPLE, // Standard null-hostile validation (default)
251
VALIDATION_API // Use JSR 303 Bean Validation API
252
}
253
```
254
255
**Usage Examples:**
256
257
```java
258
// Disable validation completely
259
@Value.Style(validationMethod = ValidationMethod.NONE)
260
@Value.Immutable
261
public interface Lenient {
262
String name(); // Can be null
263
int count(); // Will be 0 if not provided
264
}
265
266
// Lenient validation allows nulls and missing fields
267
Lenient lenient = ImmutableLenient.builder().build(); // No errors
268
269
// Mandatory-only validation
270
@Value.Style(validationMethod = ValidationMethod.MANDATORY_ONLY)
271
@Value.Immutable
272
public interface MandatoryCheck {
273
String name();
274
@Value.Default
275
default int count() { return 0; }
276
}
277
278
// Must provide name (even if null), count is optional
279
MandatoryCheck obj1 = ImmutableMandatoryCheck.builder()
280
.name(null) // Allowed - null is provided
281
.build();
282
283
// MandatoryCheck obj2 = ImmutableMandatoryCheck.builder().build(); // Error - name not provided
284
285
// JSR 303 Bean Validation
286
@Value.Style(validationMethod = ValidationMethod.VALIDATION_API)
287
@Value.Immutable
288
public interface ValidatedUser {
289
@NotNull @Size(min = 2)
290
String name();
291
292
@NotNull @Email
293
String email();
294
295
@Min(0) @Max(120)
296
int age();
297
}
298
299
// Uses Bean Validation annotations for validation
300
ValidatedUser user = ImmutableValidatedUser.builder()
301
.name("John")
302
.email("john@example.com")
303
.age(25)
304
.build(); // Validates constraints
305
```
306
307
### Visibility and Access Control
308
309
Control the visibility of generated classes and methods.
310
311
```java { .api }
312
/**
313
* Implementation visibility options
314
*/
315
enum ImplementationVisibility {
316
PUBLIC, // Generated class forced to be public
317
SAME, // Same visibility as abstract type
318
SAME_NON_RETURNED, // Same visibility, abstract type returned from factories
319
PACKAGE, // Package visibility
320
PRIVATE // Private visibility (requires builder or enclosing)
321
}
322
323
enum BuilderVisibility {
324
PUBLIC, // Builder forced to be public
325
SAME, // Same visibility as abstract type
326
PACKAGE // Package visibility
327
}
328
```
329
330
**Usage Examples:**
331
332
```java
333
// Private implementation with public builder
334
@Value.Style(
335
visibility = ImplementationVisibility.PRIVATE,
336
builderVisibility = BuilderVisibility.PUBLIC
337
)
338
@Value.Immutable
339
public interface PrivateImpl {
340
String value();
341
}
342
343
// Implementation class is private, only accessible via builder
344
// PrivateImpl obj = ImmutablePrivateImpl.of("test"); // Not accessible
345
PrivateImpl obj = ImmutablePrivateImpl.builder().value("test").build(); // OK
346
347
// Package-private implementation
348
@Value.Style(visibility = ImplementationVisibility.PACKAGE)
349
@Value.Immutable
350
public interface PackagePrivate {
351
String data();
352
}
353
354
// Generated ImmutablePackagePrivate has package visibility
355
```
356
357
### Advanced Configuration Options
358
359
Specialized configuration for complex scenarios and performance optimization.
360
361
```java { .api }
362
/**
363
* Advanced configuration options
364
*/
365
boolean allParameters() default false; // All attributes become parameters
366
boolean deepImmutablesDetection() default false; // Enhanced type analysis
367
boolean jdkOnly() default false; // Use only JDK collections
368
boolean jdk9Collections() default false; // Use JDK 9+ immutable collections
369
boolean depluralize() default false; // Depluralize collection method names
370
boolean weakInterning() default false; // Use weak references for interning
371
boolean forceJacksonPropertyNames() default true; // Force Jackson property names
372
```
373
374
**Usage Examples:**
375
376
```java
377
// All parameters style for tuple-like objects
378
@Value.Style(
379
allParameters = true,
380
typeImmutable = "*Tuple",
381
defaults = @Value.Immutable(builder = false)
382
)
383
@Value.Immutable
384
public interface Point {
385
double x();
386
double y();
387
388
@Value.Parameter(false) // Exclude from parameters
389
@Value.Derived
390
default double magnitude() {
391
return Math.sqrt(x() * x() + y() * y());
392
}
393
}
394
395
// Only constructor available: ImmutablePointTuple.of(x, y)
396
Point point = ImmutablePointTuple.of(3.0, 4.0);
397
398
// Deep immutables detection for enhanced builder methods
399
@Value.Style(deepImmutablesDetection = true)
400
@Value.Immutable
401
public interface Container {
402
Point location();
403
List<Point> waypoints();
404
}
405
406
// Enhanced builder with shortcut methods
407
Container container = ImmutableContainer.builder()
408
.location(3.0, 4.0) // Shortcut for ImmutablePoint.of(3.0, 4.0)
409
.addWaypoints(1.0, 1.0) // Shortcut for waypoints list
410
.addWaypoints(2.0, 2.0)
411
.build();
412
413
// Collection method depluralization
414
@Value.Style(
415
depluralize = true,
416
depluralizeDictionary = {"person:people", "child:children"}
417
)
418
@Value.Immutable
419
public interface Family {
420
List<String> people(); // addPerson(), addAllPeople()
421
List<String> children(); // addChild(), addAllChildren()
422
List<String> items(); // addItem(), addAllItems()
423
}
424
425
ImmutableFamily family = ImmutableFamily.builder()
426
.addPerson("Alice") // Singular form
427
.addChild("Bob") // Custom depluralization
428
.addItem("laptop") // Standard depluralization
429
.build();
430
```