-
Notifications
You must be signed in to change notification settings - Fork 23
/
style.html
377 lines (307 loc) · 30.1 KB
/
style.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"-->
<link rel="stylesheet" href="/gfx/bootstrap.min.css">
<link rel="stylesheet" href="/gfx/main.css">
<link rel="stylesheet" href="/gfx/code.css">
<title>Style customization</title>
</head>
<body class="page">
<!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-PMJSKV"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-PMJSKV');</script>
<!-- End Google Tag Manager -->
<header>
<div class="container">
<a href="/">Immutables</a> ←
<h1>Style customization <iframe src="https://ghbtns.com/github-btn.html?user=immutables&repo=immutables&type=star&count=true&size=large" frameborder="0" scrolling="0" width="160px" height="30px"></iframe>
</h1>
</div>
</header>
<aside id="toc"></aside>
<section class="documentation">
<h2 id="overview">Overview</h2>
<p>In addition to feature annotations (which are used for specific features), you can customize what
and how code will be generated for immutable values. The “what” is defined by using attributes
of the <code class="language-plaintext highlighter-rouge">@org.immutables.value.Value.Immutable</code> annotation. The “how” is defined by using styles
defined by the <code class="language-plaintext highlighter-rouge">@org.immutables.value.Value.Style</code> annotation. Custom styles are definitely
more advanced functionality and the annotation processor cannot guarantee that all possible
combinations of customizations will work correctly.</p>
<h2 id="define-style">Define style</h2>
<p><code class="language-plaintext highlighter-rouge">@Value.Style</code> annotation has a number of attributes to
customize generated the APIs and implementations. See the JavaDoc for
<a href="https://github.com/immutables/immutables/blob/master/value-annotations/src/org/immutables/value/Value.java#L416">Value.Style</a></p>
<p>In nutshell, using styles you can:</p>
<ul>
<li>Customize prefixes or suffixes of how names of types and attributes are detected.</li>
<li>Customize prefixes or suffixes of generated types and methods.</li>
<li>Force builders to be constructed using a constructor rather than a factory method (by setting the naming template to “new”).</li>
<li>Make an implementation hidden or visible: public, package private or the same as the abstract value type.</li>
<li>Make construction methods return abstract value types instead of the implementation class.</li>
<li>Make immutable implementations hidden as private inside a top-level builder.</li>
<li>Make immutable implementations hidden as private inside a top-level <a href="#nesting">enclosing</a> class.</li>
<li>Generate <a href="/immutable.html#strict-builder">strict builders</a>.</li>
<li>Force the generation of JDK-only implementation code, even if Guava is available in classpath.</li>
<li>Set template “defaults” setting for <code class="language-plaintext highlighter-rouge">@Value.Immutable</code> which will then be used for every immutable class.</li>
</ul>
<p><a name="apply"></a></p>
<h2 id="apply-style">Apply style</h2>
<p>A <code class="language-plaintext highlighter-rouge">Style</code> can be attached to:</p>
<ul>
<li>A package, where it will affect all classes in the package
<ul>
<li>It will also affect nested packages unless overridden</li>
</ul>
</li>
<li>A top-level type, where it will affect this and nested value types</li>
<li>A nested value type, if this does not contradict top-level style in case of <a href="#nesting">enclosing</a> class.</li>
<li>Annotation, which in turn will serve as style meta-annotation to annotate types and packages.</li>
</ul>
<p>A <code class="language-plaintext highlighter-rouge">@Value.Style</code> as inline style will win over meta-annotation style.</p>
<p>It is recommended to create one or more style meta-annotations for your projects. Doing this will result in a lot less clutter, and easier maintenance and upgrades.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">org.immutables.value.Value</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.lang.annotation.RetentionPolicy</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.lang.annotation.Retention</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.lang.annotation.ElementType</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.lang.annotation.Target</span><span class="o">;</span>
<span class="nd">@Target</span><span class="o">({</span><span class="nc">ElementType</span><span class="o">.</span><span class="na">PACKAGE</span><span class="o">,</span> <span class="nc">ElementType</span><span class="o">.</span><span class="na">TYPE</span><span class="o">})</span>
<span class="nd">@Retention</span><span class="o">(</span><span class="nc">RetentionPolicy</span><span class="o">.</span><span class="na">CLASS</span><span class="o">)</span> <span class="c1">// Make it class retention for incremental compilation</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Style</span><span class="o">(</span>
<span class="n">get</span> <span class="o">=</span> <span class="o">{</span><span class="s">"is*"</span><span class="o">,</span> <span class="s">"get*"</span><span class="o">},</span> <span class="c1">// Detect 'get' and 'is' prefixes in accessor methods</span>
<span class="n">init</span> <span class="o">=</span> <span class="s">"set*"</span><span class="o">,</span> <span class="c1">// Builder initialization methods will have 'set' prefix</span>
<span class="n">typeAbstract</span> <span class="o">=</span> <span class="o">{</span><span class="s">"Abstract*"</span><span class="o">},</span> <span class="c1">// 'Abstract' prefix will be detected and trimmed</span>
<span class="n">typeImmutable</span> <span class="o">=</span> <span class="s">"*"</span><span class="o">,</span> <span class="c1">// No prefix or suffix for generated immutable type</span>
<span class="n">builder</span> <span class="o">=</span> <span class="s">"new"</span><span class="o">,</span> <span class="c1">// construct builder using 'new' instead of factory method</span>
<span class="n">build</span> <span class="o">=</span> <span class="s">"create"</span><span class="o">,</span> <span class="c1">// rename 'build' method on builder to 'create'</span>
<span class="n">visibility</span> <span class="o">=</span> <span class="nc">ImplementationVisibility</span><span class="o">.</span><span class="na">PUBLIC</span><span class="o">,</span> <span class="c1">// Generated class will be always public</span>
<span class="n">defaults</span> <span class="o">=</span> <span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span><span class="o">(</span><span class="n">copy</span> <span class="o">=</span> <span class="kc">false</span><span class="o">))</span> <span class="c1">// Disable copy methods by default</span>
<span class="kd">public</span> <span class="nd">@interface</span> <span class="nc">MyStyle</span> <span class="o">{}</span>
<span class="o">...</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span> <span class="c1">// if no attributes are specified, then defaults will be used</span>
<span class="nd">@MyStyle</span> <span class="c1">// This annotation could be also placed on package</span>
<span class="kd">interface</span> <span class="nc">AbstractItem</span> <span class="o">{</span>
<span class="kt">int</span> <span class="nf">getId</span><span class="o">();</span>
<span class="kt">boolean</span> <span class="nf">isEnabled</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">...</span>
<span class="nc">Item</span> <span class="n">item</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Item</span><span class="o">.</span><span class="na">Builder</span><span class="o">()</span>
<span class="o">.</span><span class="na">setId</span><span class="o">(</span><span class="mi">1</span><span class="o">)</span>
<span class="o">.</span><span class="na">setEnabled</span><span class="o">(</span><span class="kc">true</span><span class="o">)</span>
<span class="o">.</span><span class="na">create</span><span class="o">();</span>
</code></pre></div></div>
<p>This way you can match the generated code style to your conventions and preferences!</p>
<p>The simplest way to apply styles in manner as close to globally as possible is to annotate the top-level package of your project or module.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// com/mycompany/project/package-info.java</span>
<span class="nd">@MyStyle</span>
<span class="kn">package</span> <span class="nn">com.mycompany.project</span><span class="o">;</span>
</code></pre></div></div>
<p><strong>Things to be aware of</strong></p>
<ul>
<li>When there are couple of conflicting styles mixed on the same level using meta annotations, then either may be selected arbitrarily. You should not rely on any particular selection order here.</li>
<li>Styles are not merged in any way.</li>
<li>Styles are applied at package level, top-level class level, or on a value type itself if it’s nested. Styles will not work if applied at attribute level or declared on intermediate nested types.</li>
<li>Styles are a sharp tool, expect compilation errors in generated code if style definitions are inaccurate and names overlap, contain inappropriate symbols or Java keywords etc.</li>
<li>Styles are aggressively cached. If you change some meta-style or parent-package style sometimes you may not see thing correctly compiling until a full clean rebuild or even IDE restart.</li>
</ul>
<p><a name="depluralization"></a></p>
<h3 id="depluralization">Depluralization</h3>
<p><code class="language-plaintext highlighter-rouge">Style.depluralize</code> style attribute enables automatic depluralization of attribute names for collection and map attributes used for generating derived method names, such as <code class="language-plaintext highlighter-rouge">add*</code> and <code class="language-plaintext highlighter-rouge">put*</code>. In order to enable depluralization specify depluralize = true: this will trim trailing “s” suffixes if present to create singular form (“ies” to “y” suffix conversion is also supported).</p>
<p>Exceptions are provided using <code class="language-plaintext highlighter-rouge">Style.depluralizeDictionary</code> array of <code class="language-plaintext highlighter-rouge">"singular:plural"</code> pairs as alternative to mechanical <code class="language-plaintext highlighter-rouge">"*s"</code> depluralization.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Value</span><span class="o">.</span><span class="na">Style</span><span class="o">(</span>
<span class="n">depluralize</span> <span class="o">=</span> <span class="kc">true</span><span class="o">,</span> <span class="c1">// enable feature</span>
<span class="n">depluralizeDictionary</span> <span class="o">=</span> <span class="o">{</span><span class="s">"person:people"</span><span class="o">,</span> <span class="s">"foot:feet"</span><span class="o">})</span> <span class="c1">// specifying dictionary of exceptions</span>
</code></pre></div></div>
<p>When given the dictionary defined as <code class="language-plaintext highlighter-rouge">{"person:people", "foot:feet"}</code> then examples for <code class="language-plaintext highlighter-rouge">add*</code> method in builder would be:</p>
<ul>
<li>boats → addBoat</li>
<li>people → addPerson</li>
<li>feet → addFoot</li>
<li>feetPeople → addFeetPerson</li>
<li>peopleRepublics → addPeopleRepublic</li>
</ul>
<p>Dictionary-based depluralization is based on the assumption that simple <code class="language-plaintext highlighter-rouge">s</code> trimming will cover most cases, while exceptions, if provided, are likely to be ubiquitous in a problem domain being modelled by value objects. As a reminder, you don’t have to annotate every single value class with bulky style definitions, rather annotate some top-level package or use style as meta annotation (See <a href="#apply">Apply style</a>)</p>
<h2 id="other-customizations">Other customizations</h2>
<h3 id="simpler-imports">Simpler imports</h3>
<p>This example can barely be called a customization. Let it just be a reminder that you can use
annotations with simple names rather than qualified with umbrella annotations like <code class="language-plaintext highlighter-rouge">@Value</code>:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">org.immutables.value.Value.Immutable</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.immutables.value.Value.Parameter</span><span class="o">;</span>
<span class="nd">@Immutable</span> <span class="kd">interface</span> <span class="nc">Value</span> <span class="o">{</span>
<span class="nd">@Parameter</span> <span class="kt">int</span> <span class="nf">getFirst</span><span class="o">();</span>
<span class="nd">@Parameter</span> <span class="nc">String</span> <span class="nf">getSecond</span><span class="o">();</span>
<span class="o">}</span>
</code></pre></div></div>
<h3 id="is-prefix-and-custom-getters">“is” prefix and custom getters</h3>
<p>As “strange” as it sounds, but out-of-the-box only <code class="language-plaintext highlighter-rouge">get</code>-prefixed or no-prefix accessors are supported. The <code class="language-plaintext highlighter-rouge">isEmpty()</code> accessor will be considered as <code class="language-plaintext highlighter-rouge">isEmpty</code> attribute, not as one called <code class="language-plaintext highlighter-rouge">empty</code>. Yep, Immutables is not a JavaBean-compliant toolkit and don’t expect it to be. However, styles allows you to specify arbitrary prefixes (or even suffixes) to be recognized as part of attribute accessors. Most folks that want to use familiar <code class="language-plaintext highlighter-rouge">get</code> and <code class="language-plaintext highlighter-rouge">is</code> prefixes simply use <code class="language-plaintext highlighter-rouge">@Value.Style(get = {"get*", "is*"})</code> configured for a parent-package or as a meta-annotation.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Style</span><span class="o">(</span><span class="n">get</span> <span class="o">=</span> <span class="o">{</span><span class="s">"get*"</span><span class="o">,</span> <span class="s">"is*"</span><span class="o">,</span> <span class="s">"*Whatever"</span><span class="o">},</span> <span class="n">init</span> <span class="o">=</span> <span class="s">"set*"</span><span class="o">)</span>
<span class="kd">interface</span> <span class="nc">Val</span> <span class="o">{</span>
<span class="kt">int</span> <span class="nf">getProp</span><span class="o">();</span>
<span class="kt">boolean</span> <span class="nf">isEmpty</span><span class="o">();</span>
<span class="nc">String</span> <span class="nf">fooWhatever</span><span class="o">();</span>
<span class="kd">static</span> <span class="kt">void</span> <span class="nf">demo</span><span class="o">()</span> <span class="o">{</span>
<span class="nc">Val</span> <span class="n">v</span> <span class="o">=</span> <span class="nc">ImmutableVal</span><span class="o">.</span><span class="na">builder</span><span class="o">()</span>
<span class="o">.</span><span class="na">setProp</span><span class="o">(</span><span class="mi">1</span><span class="o">)</span>
<span class="o">.</span><span class="na">setEmpty</span><span class="o">(</span><span class="kc">true</span><span class="o">)</span>
<span class="o">.</span><span class="na">setFoo</span><span class="o">(</span><span class="s">"whatever"</span><span class="o">)</span>
<span class="o">.</span><span class="na">build</span><span class="o">();</span>
<span class="n">v</span><span class="o">.</span><span class="na">toString</span><span class="o">();</span><span class="c1">// Val{prop=1, empty=true, foo=whatever}</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p><a name="nesting"></a></p>
<h3 id="enclosing-type">Enclosing type</h3>
<p>When modelling messages and documents, we usually want to have a lot of small value classes in one
file. In Java this naturally accomplished by nesting those classes under an umbrella top-level
class. Of course, it is possible to generate immutable subclasses for nested static inner
classes or interfaces.</p>
<p><code class="language-plaintext highlighter-rouge">@Value.Enclosing</code> annotation can be used on a top-level class to provide namespacing for implementation
classes generated out of nested abstract value types. This can be used as a matter of
preference or to avoid name clashes of immutable implementation classes which would otherwise
be generated as top-level classes in the same package.</p>
<p>By default, namespaced implementation classes have simple names without prefixes, an can be
star-imported for clutter-free usage.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Value</span><span class="o">.</span><span class="na">Enclosing</span>
<span class="kd">class</span> <span class="nc">GraphPrimitives</span> <span class="o">{</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="kd">interface</span> <span class="nc">Vertex</span> <span class="o">{}</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="kd">static</span> <span class="kd">class</span> <span class="nc">Edge</span> <span class="o">{}</span>
<span class="o">}</span>
<span class="o">...</span>
<span class="kn">import</span> <span class="nn">...ImmutableGraphPrimitives.*</span><span class="o">;</span>
<span class="o">...</span>
<span class="nc">Edge</span><span class="o">.</span><span class="na">builder</span><span class="o">().</span><span class="na">build</span><span class="o">();</span>
<span class="nc">Vertex</span><span class="o">.</span><span class="na">builder</span><span class="o">().</span><span class="na">build</span><span class="o">();</span>
</code></pre></div></div>
<p>There are number of styling options available to customize naming of generated top-level and nested classes.
It worth to note that style annotation should be placed on a top-level enclosing class or on a package,
because style of the enclosing class and nested value objects should be the same.</p>
<p><em>Note: prior to 2.0, <code class="language-plaintext highlighter-rouge">@Value.Enclosing</code> was named <code class="language-plaintext highlighter-rouge">@Value.Nested</code></em></p>
<p><em>Note: as of 2.1 we would not advertise the use of <code class="language-plaintext highlighter-rouge">@Value.Enclosing</code>. It is not deprecated and may be useful as namespacing tool, but still this should be considered as a niche solution, not the one that you should use “by default”. Just nesting value types and generating top-level immutable classes in the same package works fine in many cases.</em></p>
<h3 id="custom-immutable-annotation">Custom immutable annotation</h3>
<p>What if you want nice single annotation to express immutable object along with certain style? Or better set of annotation with predefined styles? Let’s define two such annotations as a contrived example.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">org.example.annotation</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.immutables.value.Value</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.lang.annotation.ElementType</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.lang.annotation.Target</span><span class="o">;</span>
<span class="cm">/**
* Tupled annotation will be used to generate simple tuples in reverse-style,
* having construction methods of all annotations.
*/</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Style</span><span class="o">(</span> <span class="c1">// Tupled annotation will serve as both immutable and meta-annotated style annotation</span>
<span class="n">typeAbstract</span> <span class="o">=</span> <span class="s">"*Def"</span><span class="o">,</span>
<span class="n">typeImmutable</span> <span class="o">=</span> <span class="s">"*"</span><span class="o">,</span>
<span class="n">allParameters</span> <span class="o">=</span> <span class="kc">true</span><span class="o">,</span> <span class="c1">// all attributes will become constructor parameters</span>
<span class="c1">// as if they are annotated with @Value.Parameter</span>
<span class="n">visibility</span> <span class="o">=</span> <span class="nc">Value</span><span class="o">.</span><span class="na">Style</span><span class="o">.</span><span class="na">ImplementationVisibility</span><span class="o">.</span><span class="na">PUBLIC</span><span class="o">,</span> <span class="c1">// Generated class will be always public</span>
<span class="n">defaults</span> <span class="o">=</span> <span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span><span class="o">(</span><span class="n">builder</span> <span class="o">=</span> <span class="kc">false</span><span class="o">))</span> <span class="c1">// Disable copy methods and builder</span>
<span class="kd">public</span> <span class="nd">@interface</span> <span class="nc">Tupled</span> <span class="o">{}</span>
<span class="o">...</span>
<span class="cm">/**
* Builded annotation will generate builder which produces private implementations
* of abstract value type.
*/</span>
<span class="nd">@Target</span><span class="o">(</span><span class="nc">ElementType</span><span class="o">.</span><span class="na">TYPE</span><span class="o">)</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Style</span><span class="o">(</span>
<span class="n">typeBuilder</span> <span class="o">=</span> <span class="s">"BuilderFor_*"</span><span class="o">,</span>
<span class="n">defaultAsDefault</span> <span class="o">=</span> <span class="kc">true</span><span class="o">,</span> <span class="c1">// java 8 default methods will be automatically turned into @Value.Default</span>
<span class="n">visibility</span> <span class="o">=</span> <span class="nc">Value</span><span class="o">.</span><span class="na">Style</span><span class="o">.</span><span class="na">ImplementationVisibility</span><span class="o">.</span><span class="na">PRIVATE</span><span class="o">,</span>
<span class="n">builderVisibility</span> <span class="o">=</span> <span class="nc">Value</span><span class="o">.</span><span class="na">Style</span><span class="o">.</span><span class="na">BuilderVisibility</span><span class="o">.</span><span class="na">PACKAGE</span><span class="o">)</span> <span class="c1">// We will extend builder to make it public</span>
<span class="kd">public</span> <span class="nd">@interface</span> <span class="nc">Builded</span> <span class="o">{}</span>
</code></pre></div></div>
<p>But those definitions along is not enough. Create text file as classpath resource having path
<code class="language-plaintext highlighter-rouge">/META-INF/annotations/org.immutables.value.immutable</code> and put one or more lines with fully qualified names
of extension annotations:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>org.example.annotation.Tupled
org.example.annotation.Builded
</code></pre></div></div>
<p>Ok, now compile annotations and put the above file as a separate jar and then put it on the same classpath/scope as the annotation processor during build along with regular compilation(only) classpath. The annotation jar is not needed at runtime.</p>
<p>Then we can use this annotation module as compile/annotation-processing dependency. Using Maven just put it in <code class="language-plaintext highlighter-rouge">provided</code> scope.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">org.example.models</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.example.annotation.Tupled</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.example.annotation.Builded</span><span class="o">;</span>
<span class="c1">// Look, custom annotation instead of @Value.Immutable</span>
<span class="c1">// and the style is also attached!</span>
<span class="nd">@Tupled</span> <span class="kd">interface</span> <span class="nc">RgbDef</span> <span class="o">{</span>
<span class="kt">double</span> <span class="nf">red</span><span class="o">();</span>
<span class="kt">double</span> <span class="nf">green</span><span class="o">();</span>
<span class="kt">double</span> <span class="nf">blue</span><span class="o">();</span>
<span class="o">}</span>
<span class="c1">// ...</span>
<span class="nc">Rgb</span> <span class="n">color</span> <span class="o">=</span> <span class="nc">Rgb</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="mf">0.4</span><span class="o">,</span> <span class="mf">0.3</span><span class="o">,</span> <span class="mf">1.0</span><span class="o">);</span>
<span class="c1">// Custom annotation for builder with private immutable implementation.</span>
<span class="nd">@Builded</span> <span class="kd">public</span> <span class="kd">interface</span> <span class="nc">Record</span> <span class="o">{</span>
<span class="kt">long</span> <span class="nf">id</span><span class="o">();</span>
<span class="nc">String</span> <span class="nf">name</span><span class="o">();</span>
<span class="k">default</span> <span class="nc">String</span> <span class="nf">notes</span><span class="o">()</span> <span class="o">{</span> <span class="c1">// Works as default attribute!</span>
<span class="k">return</span> <span class="s">""</span><span class="o">;</span>
<span class="o">}</span>
<span class="c1">// Then we extend package-private builder with public nested builder and expose all</span>
<span class="c1">// public methods as methods of Record.Builder.</span>
<span class="kd">class</span> <span class="nc">Builder</span> <span class="kd">extends</span> <span class="n">BuilderFor_Record</span> <span class="o">{}</span>
<span class="o">}</span>
<span class="c1">// ...</span>
<span class="nc">Record</span> <span class="n">record</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Record</span><span class="o">.</span><span class="na">Builder</span><span class="o">()</span>
<span class="o">.</span><span class="na">id</span><span class="o">(</span><span class="mi">123L</span><span class="o">)</span>
<span class="o">.</span><span class="na">name</span><span class="o">(</span><span class="s">"Named Record"</span><span class="o">)</span>
<span class="o">.</span><span class="na">notes</span><span class="o">(</span><span class="s">"Oh, nothing interesting, surely!"</span><span class="o">)</span>
<span class="o">.</span><span class="na">build</span><span class="o">();</span>
</code></pre></div></div>
</section>
<footer class="jumbotron">
<div class="container">
<h2 id="guides">Guides</h2>
<ul>
<li><a href="/getstarted.html">Get started!</a></li>
<li><a href="/intro.html">Inception</a></li>
<li><a href="/immutable.html">Immutable objects</a></li>
<li><a href="/factory.html">Factory builders</a></li>
<li><a href="/functional.html">Functions and Predicates (for Java 7)</a></li>
<li><a href="/style.html">Style customization</a></li>
<li><a href="/json.html">JSON serialization</a></li>
<li><a href="/criteria.html">Criteria</a></li>
<li><a href="/mongo.html">MongoDB repositories</a></li>
<li><a href="/dynamodb.html">DynamoDB integration</a></li>
<li><a href="/encoding.html">Encoding: Customizing attributes and builders (experimental)</a></li>
<li><a href="/apt.html">Using annotation processor in IDE</a></li>
</ul>
<h2 id="get-involved">Get involved</h2>
<ul>
<li>Clone source repository, contribute bug reports and fixes on <a href="https://github.com/immutables/immutables">GitHub immutables/immutables</a></li>
<li>Issue reports, questions and feedback is welcome on issue tracker <a href="https://github.com/immutables/immutables/issues">GitHub immutables/immutables/issues</a></li>
<li>News and announcements on twitter <a href="https://twitter.com/ImmutablesOrg">@ImmutablesOrg</a></li>
</ul>
<p><a href="/license.html">Apache License 2.0</a></p>
<!--<div><h2>Posts</h2>
<ul>
</ul>
</div>-->
</div>
</footer>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script defer src="/gfx/jquery.toc.min.js"></script>
<script>
$(function() {
$('#toc').toc({
container: '.documentation',
selectors: 'h1,h2,h3,h4',
anchorName: function(i, heading, prefix) {
heading = $(heading).text();
if (heading.trim) heading = heading.trim();
return heading.toLowerCase().replace(/ /g, '-').replace(/[^a-z^\-]+/g, '');
},
})
})
</script>
</body>
</html>