Skip to content

Commit 4c90786

Browse files
authored
Introduce Pico ConfigBean Builder Extensions (helidon-io#5482)
1 parent 7972752 commit 4c90786

175 files changed

Lines changed: 10209 additions & 625 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

bom/pom.xml

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,40 +1391,53 @@
13911391
<version>${helidon.version}</version>
13921392
</dependency>
13931393

1394-
<!-- Pico -->
1394+
<!-- Builder -->
13951395
<dependency>
1396-
<groupId>io.helidon.pico</groupId>
1397-
<artifactId>helidon-pico</artifactId>
1396+
<groupId>io.helidon.builder</groupId>
1397+
<artifactId>helidon-builder</artifactId>
13981398
<version>${helidon.version}</version>
13991399
</dependency>
14001400
<dependency>
1401-
<groupId>io.helidon.pico</groupId>
1402-
<artifactId>helidon-pico-types</artifactId>
1401+
<groupId>io.helidon.builder</groupId>
1402+
<artifactId>helidon-builder-processor-spi</artifactId>
1403+
<version>${helidon.version}</version>
1404+
</dependency>
1405+
<dependency>
1406+
<groupId>io.helidon.builder</groupId>
1407+
<artifactId>helidon-builder-processor-tools</artifactId>
1408+
<version>${helidon.version}</version>
1409+
</dependency>
1410+
<dependency>
1411+
<groupId>io.helidon.builder</groupId>
1412+
<artifactId>helidon-builder-processor</artifactId>
14031413
<version>${helidon.version}</version>
14041414
</dependency>
14051415

1406-
<!-- Pico Builder -->
1416+
<!-- Pico Core -->
14071417
<dependency>
1408-
<groupId>io.helidon.pico.builder</groupId>
1409-
<artifactId>helidon-pico-builder</artifactId>
1418+
<groupId>io.helidon.pico</groupId>
1419+
<artifactId>helidon-pico</artifactId>
14101420
<version>${helidon.version}</version>
14111421
</dependency>
14121422
<dependency>
1413-
<groupId>io.helidon.pico.builder</groupId>
1414-
<artifactId>helidon-pico-builder-processor-spi</artifactId>
1423+
<groupId>io.helidon.pico</groupId>
1424+
<artifactId>helidon-pico-types</artifactId>
14151425
<version>${helidon.version}</version>
14161426
</dependency>
1427+
1428+
<!-- Pico Config Builder -->
14171429
<dependency>
1418-
<groupId>io.helidon.pico.builder</groupId>
1419-
<artifactId>helidon-pico-builder-processor-tools</artifactId>
1430+
<groupId>io.helidon.pico.builder.config</groupId>
1431+
<artifactId>helidon-pico-builder-config</artifactId>
14201432
<version>${helidon.version}</version>
14211433
</dependency>
14221434
<dependency>
1423-
<groupId>io.helidon.pico.builder</groupId>
1424-
<artifactId>helidon-pico-builder-processor</artifactId>
1435+
<groupId>io.helidon.pico.builder.config</groupId>
1436+
<artifactId>helidon-pico-builder-config-processor</artifactId>
14251437
<version>${helidon.version}</version>
14261438
</dependency>
14271439

1440+
14281441
</dependencies>
14291442
</dependencyManagement>
14301443
</project>
Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1-
# pico-builder
1+
# builder
22

3-
The <b>Helidon Pico Builder</b> provides compile-time code generation for fluent builders. It was inspired by [Lombok]([https://projectlombok.org/), but the implementation here in Helidon is different in a few ways:
3+
The <b>Helidon Builder</b> provides compile-time code generation for fluent builders. It was inspired by [Lombok]([https://projectlombok.org/), but the implementation here in Helidon is different in a few ways:
44
<ol>
55
<li>The <i>Builder</i> annotation targets interface or annotation types only. Your interface effectively contains the attributes of your getter as well as serving as the contract for your getter methods.</li>
66
<li>Generated classes implement your target interface (or annotation) and provide a fluent builder that will always have an implementation of <i>toString(), hashCode(), and equals().</i> implemented</li>
77
<li>Generated classes always behave like a <i>SuperBuilder</i> from Lombok. Basically this means that builders can form
88
a hierarchy on the types they target (e.g., Level2 derives from Level1 derives from Level0, etc.).</li>
9-
<li>Lombok uses AOP while the Pico Builder generates source code. You can use the <i>Builder</i> annotation (as well as other annotations in the package and <i>ConfiguredOption</i>) to control the naming and other features of what and how the implementation classes are generated and behave.</li>
10-
<li>Pico Builders are extensible - you can provide your own implementation of the <b>Builder Processor SPI</b> to customize the generated classes for your situation.</li>
9+
<li>Lombok uses AOP while the Helidon Builder generates source code. You can use the <i>Builder</i> annotation (as well as other annotations in the package and <i>ConfiguredOption</i>) to control the naming and other features of what and how the implementation classes are generated and behave.</li>
10+
<li>Builders are extensible - you can provide your own implementation of the <b>Builder Processor SPI</b> to customize the generated classes for your situation.</li>
1111
</ol>
1212

13-
Supported annotation types (see [builder](./builder/src/main/java/io/helidon/pico/builder) for further details):
13+
Supported annotation types (see [builder](./builder/src/main/java/io/helidon/builder) for further details):
1414
* Builder - similar to Lombok's SuperBuilder.
1515
* Singular - similar to Lombok's Singular.
1616

1717
Any and all types are supported by the Builder, with special handling for List, Map, Set, and Optional types. The target interface,
1818
however, should only contain getter like methods (i.e., has a non-void return and takes no arguments). All static and default methods
1919
are ignored on the target being processed.
2020

21-
The Helidon Pico Builder is completely independent of other parts of Pico. It can therefore be used in a standalone manner. The
21+
The Helidon Builder is independent of other parts of Helidon. It can therefore be used in a standalone manner. The
2222
generated implementation class will not require any special module to support those classes - just the types from your interface
2323
and standard JRE types are used. This is made possible when your <i>Builder</i> has the <i>requireBuilderLibrary=false</i>. See the javadoc for details.
2424

@@ -32,15 +32,15 @@ public interface MyConfigBean {
3232
}
3333
```
3434
2. Annotate your interface definition with <i>Builder</i>, and optionally use <i>ConfiguredOption</i>, <i>Singular</i>, etc. Remember to review the annotation attributes javadoc for any customizations.
35-
3. Compile (using the <i>pico-builder-processor</i> in your annotation classpath).
35+
3. Compile (using the <i>builder-processor</i> in your annotation classpath).
3636

3737
The result of this will create (under ./target/generated-sources/annotations):
3838
* MyConfigBeanImpl (in the same package as MyConfigBean) that will support multi-inheritance builders named MyConfigBeanImpl.Builder.
3939
* Support for toString(), hashCode(), and equals() are always included.
4040
* Support for toBuilder().
41-
* Support for streams (see javadoc for [Builder](./builder/src/main/java/io/helidon/pico/builder/Builder.java)).
42-
* Support for attribute visitors (see [test-builder](./tests/builder/src/main/java/io/helidon/pico/builder/test/testsubjects/package-info.java)).
43-
* Support for attribute validation (see ConfiguredOption#required() and [builder](./tests/builder/src/main/java/io/helidon/pico/builder/test/testsubjects/package-info.java)).
41+
* Support for streams (see javadoc for [Builder](./builder/src/main/java/io/helidon/builder/Builder.java)).
42+
* Support for attribute visitors (see [test-builder](./tests/builder/src/main/java/io/helidon/builder/test/testsubjects/package-info.java)).
43+
* Support for attribute validation (see ConfiguredOption#required() and [builder](./tests/builder/src/main/java/io/helidon/builder/test/testsubjects/package-info.java)).
4444

4545
The implementation of the processor also allows for a provider-based extensibility mechanism.
4646

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# pico-builder
1+
# builder
22

33
This module can either be used compile-time only or at runtime as well depending upon your usage.
44

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@
2222
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2323

2424
<parent>
25-
<groupId>io.helidon.pico.builder</groupId>
26-
<artifactId>helidon-pico-builder-project</artifactId>
25+
<groupId>io.helidon.builder</groupId>
26+
<artifactId>helidon-builder-project</artifactId>
2727
<version>4.0.0-SNAPSHOT</version>
2828
<relativePath>../pom.xml</relativePath>
2929
</parent>
3030
<modelVersion>4.0.0</modelVersion>
3131

32-
<artifactId>helidon-pico-builder</artifactId>
33-
<name>Helidon Pico Builder</name>
32+
<artifactId>helidon-builder</artifactId>
33+
<name>Helidon Builder</name>
3434

3535
<dependencies>
3636
<dependency>

pico/builder/builder/src/main/java/io/helidon/pico/builder/Annotated.java renamed to builder/builder/src/main/java/io/helidon/builder/Annotated.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package io.helidon.pico.builder;
17+
package io.helidon.builder;
1818

1919
import java.lang.annotation.ElementType;
2020
import java.lang.annotation.Retention;

pico/builder/builder/src/main/java/io/helidon/pico/builder/AttributeVisitor.java renamed to builder/builder/src/main/java/io/helidon/builder/AttributeVisitor.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,20 @@
1414
* limitations under the License.
1515
*/
1616

17-
package io.helidon.pico.builder;
17+
package io.helidon.builder;
1818

1919
import java.util.Map;
2020
import java.util.function.Supplier;
2121

2222
/**
2323
* A functional interface that can be used to visit all attributes of this type.
2424
* <p>
25-
* This type is used when {@link io.helidon.pico.builder.Builder#requireLibraryDependencies()} is used.
25+
* This type is used when {@link Builder#requireLibraryDependencies()} is used.
26+
*
27+
* @param <T> type of the user defined context this attribute visitor supports
2628
*/
2729
@FunctionalInterface
28-
public interface AttributeVisitor {
30+
public interface AttributeVisitor<T> {
2931

3032
/**
3133
* Visits the attribute named 'attrName'.
@@ -40,7 +42,7 @@ public interface AttributeVisitor {
4042
void visit(String attrName,
4143
Supplier<Object> valueSupplier,
4244
Map<String, Object> meta,
43-
Object userDefinedCtx,
45+
T userDefinedCtx,
4446
Class<?> type,
4547
Class<?>... typeArgument);
4648

pico/builder/builder/src/main/java/io/helidon/pico/builder/Builder.java renamed to builder/builder/src/main/java/io/helidon/builder/Builder.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package io.helidon.pico.builder;
17+
package io.helidon.builder;
1818

1919
import java.lang.annotation.ElementType;
2020
import java.lang.annotation.Retention;
@@ -62,6 +62,11 @@
6262
*/
6363
String DEFAULT_SUFFIX = "";
6464

65+
/**
66+
* The default value for {@link #allowNulls()}.
67+
*/
68+
boolean DEFAULT_ALLOW_NULLS = false;
69+
6570
/**
6671
* The default list type used for the generated class implementation for any references to {@link java.util.List} is found
6772
* on the methods of the {@link Builder}-annotation interface.
@@ -167,6 +172,14 @@
167172
*/
168173
boolean requireBeanStyle() default false;
169174

175+
/**
176+
* Should the bean and the builder allow for the possibility of nullable non-{@link java.util.Optional} values to be present.
177+
* Default is {@code false}.
178+
*
179+
* @return true to allow for the possibility of nullable non-Optional values to be present
180+
*/
181+
boolean allowNulls() default DEFAULT_ALLOW_NULLS;
182+
170183
/**
171184
* The list implementation type to apply, defaulting to {@link #DEFAULT_LIST_TYPE}.
172185
*

pico/builder/builder/src/main/java/io/helidon/pico/builder/BuilderTrigger.java renamed to builder/builder/src/main/java/io/helidon/builder/BuilderTrigger.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package io.helidon.pico.builder;
17+
package io.helidon.builder;
1818

1919
import java.lang.annotation.Documented;
2020
import java.lang.annotation.ElementType;

pico/builder/builder/src/main/java/io/helidon/pico/builder/spi/RequiredAttributeVisitor.java renamed to builder/builder/src/main/java/io/helidon/builder/RequiredAttributeVisitor.java

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,49 +14,66 @@
1414
* limitations under the License.
1515
*/
1616

17-
package io.helidon.pico.builder.spi;
17+
package io.helidon.builder;
1818

1919
import java.util.ArrayList;
2020
import java.util.List;
2121
import java.util.Map;
2222
import java.util.Objects;
2323
import java.util.function.Supplier;
2424

25-
import io.helidon.pico.builder.AttributeVisitor;
26-
2725
/**
2826
* An implementation of {@link AttributeVisitor} that will validate each attribute to enforce not-null in accordance with
2927
* {@link io.helidon.config.metadata.ConfiguredOption#required()}.
3028
* <p>
31-
* Note that the source type having the {@link io.helidon.pico.builder.Builder} must be annotated with
29+
* Note that the source type having the {@link io.helidon.builder.Builder} must be annotated with
3230
* {@code ConfiguredOption(required=true)} for this to be enforced.
3331
* Also note that this implementation will be used only when
34-
* {@link io.helidon.pico.builder.Builder#requireLibraryDependencies()} is enabled. If not enabled then an implementation
32+
* {@link io.helidon.builder.Builder#requireLibraryDependencies()} is enabled. If not enabled then an implementation
3533
* similar to this type will be inlined directly into the code-generated builder type.
3634
*
3735
* @deprecated This class is subject to change at any time - Helidon users should not use this directly. It will be referenced in
3836
* code generated sources that Helidon generates.
3937
*/
4038
@Deprecated
41-
public class RequiredAttributeVisitor implements AttributeVisitor {
39+
public class RequiredAttributeVisitor implements AttributeVisitor<Object> {
4240
private final List<String> errors = new ArrayList<>();
41+
private final boolean allowNullsByDefault;
4342

4443
/**
4544
* Default constructor.
4645
*/
47-
// note: this needs to remain public since it will be new'ed from code-generated builder processing ...
46+
// important note: this needs to remain public since it will be new'ed from code-generated builder processing ...
4847
public RequiredAttributeVisitor() {
48+
this(Builder.DEFAULT_ALLOW_NULLS);
49+
}
50+
51+
/**
52+
* Constructor.
53+
*
54+
* @param allowNullsByDefault true if nulls should be allowed
55+
*/
56+
// important note: this needs to remain public since it will be new'ed from code-generated builder processing ...
57+
public RequiredAttributeVisitor(boolean allowNullsByDefault) {
58+
this.allowNullsByDefault = allowNullsByDefault;
4959
}
5060

5161
@Override
62+
// important note: this needs to remain public since it will be new'ed from code-generated builder processing ...
5263
public void visit(String attrName,
5364
Supplier<Object> valueSupplier,
5465
Map<String, Object> meta,
5566
Object userDefinedCtx,
5667
Class<?> type,
5768
Class<?>... typeArgument) {
58-
boolean required = Boolean.parseBoolean((String) meta.get("required"));
59-
if (!required) {
69+
String requiredStr = (String) meta.get("required");
70+
boolean requiredPresent = Objects.nonNull(requiredStr);
71+
boolean required = Boolean.parseBoolean(requiredStr);
72+
if (!required && requiredPresent) {
73+
return;
74+
}
75+
76+
if (allowNullsByDefault && !requiredPresent) {
6077
return;
6178
}
6279

@@ -73,6 +90,7 @@ public void visit(String attrName,
7390
*
7491
* @throws java.lang.IllegalStateException when any attributes are in violation with the validation policy
7592
*/
93+
// important note: this needs to remain public since it will be new'ed from code-generated builder processing ...
7694
public void validate() {
7795
if (!errors.isEmpty()) {
7896
throw new IllegalStateException(String.join(", ", errors));

pico/builder/builder/src/main/java/io/helidon/pico/builder/Singular.java renamed to builder/builder/src/main/java/io/helidon/builder/Singular.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package io.helidon.pico.builder;
17+
package io.helidon.builder;
1818

1919
import java.lang.annotation.ElementType;
2020
import java.lang.annotation.Retention;

0 commit comments

Comments
 (0)