Skip to content

Introduce Pico ConfigBean Builder Extensions #5482

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 37 commits into from
Dec 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
f2d6748
config integration into builder
trentjeff Nov 19, 2022
22d198c
checkstyle suppression, and javadoc fixups
trentjeff Nov 21, 2022
743b779
Promote ConfigMapper and ConfigMapperProvider to common level SPI. Th…
trentjeff Nov 22, 2022
50f4ed4
A few tweaks over the last push.
trentjeff Nov 22, 2022
c5f0339
A few tweaks over the last push.
trentjeff Nov 22, 2022
1cd03c9
Suppress false positives (#5450)
barchetta Nov 17, 2022
dfee561
Fix handling of optional whitespace at the beginning of headers. (#5441)
tomas-langer Nov 17, 2022
f77e47a
NullPointerException when there is an illegal character in the reques…
klustria Nov 18, 2022
b5747c8
Error handling support in HTTP for Nima WebServer. (#5436)
tomas-langer Nov 20, 2022
8256e47
move bean utils from builder spi to processor module. (#5448)
trentjeff Nov 21, 2022
453da59
remove -Ddocker.build=true (#5485)
aserkes Nov 21, 2022
f5f6d24
Fix Guava version to match that required by the grpc-java libraries (…
thegridman Nov 22, 2022
10038f1
5379 TempDir support for tests (#5508)
aserkes Nov 24, 2022
74de234
Kafka producer nacking fix 5510 (#5531)
danielkec Nov 24, 2022
ba35447
4836 graalvm 22 4.x (#5378)
tomas-langer Nov 24, 2022
22f67b0
Tyrus integration into Nima (#5464)
spericas Nov 28, 2022
2a83a85
Bump-up reactive messaging/ops to 3.0 (#5526)
danielkec Nov 28, 2022
3cfb5c9
5469 - forEachCS (#5532)
danielkec Nov 28, 2022
1e6a678
Fixed OpentraceableClientE2ETest to be more deterministic (#5536)
tomas-langer Nov 28, 2022
13707ea
[4.x] - Fix Intermittent TestJBatchEndpoint.runJob (#5542)
dalexandrov Nov 28, 2022
b01279d
5377 custom exception for CharBuffer (#5505)
aserkes Nov 28, 2022
9977d1e
Fix incorrect tags comparison when trying to match metric IDs (#5550)
tjquinno Nov 29, 2022
03a01eb
config integration into builder
trentjeff Nov 19, 2022
127c6e5
checkstyle suppression, and javadoc fixups
trentjeff Nov 21, 2022
f7e72e0
Promote ConfigMapper and ConfigMapperProvider to common level SPI. Th…
trentjeff Nov 22, 2022
925da74
A few tweaks over the last push.
trentjeff Nov 22, 2022
e010a87
A few tweaks over the last push.
trentjeff Nov 22, 2022
15a8ff2
Merge branch 'pico4' of github.com:trentjeff/helidon into pico4
trentjeff Nov 29, 2022
67de03d
relocating /pico/builder to /builder
trentjeff Nov 29, 2022
2299910
checkstyles, formats, and import ordering
trentjeff Nov 29, 2022
728e14c
some review comments addressed
trentjeff Nov 29, 2022
3bd66fa
checkstyles
trentjeff Nov 29, 2022
2dda9ec
more checkstyles
trentjeff Nov 29, 2022
c355b7a
Changes to builder modules
tomas-langer Dec 1, 2022
b0f7758
Changes to config beans and build fixes.
tomas-langer Dec 1, 2022
2d95c5b
1. allowNulls support added.
trentjeff Dec 1, 2022
85fdb09
fix failing test
trentjeff Dec 1, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 27 additions & 14 deletions bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1391,40 +1391,53 @@
<version>${helidon.version}</version>
</dependency>

<!-- Pico -->
<!-- Builder -->
<dependency>
<groupId>io.helidon.pico</groupId>
<artifactId>helidon-pico</artifactId>
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.pico</groupId>
<artifactId>helidon-pico-types</artifactId>
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder-processor-spi</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder-processor-tools</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder-processor</artifactId>
<version>${helidon.version}</version>
</dependency>

<!-- Pico Builder -->
<!-- Pico Core -->
<dependency>
<groupId>io.helidon.pico.builder</groupId>
<artifactId>helidon-pico-builder</artifactId>
<groupId>io.helidon.pico</groupId>
<artifactId>helidon-pico</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.pico.builder</groupId>
<artifactId>helidon-pico-builder-processor-spi</artifactId>
<groupId>io.helidon.pico</groupId>
<artifactId>helidon-pico-types</artifactId>
<version>${helidon.version}</version>
</dependency>

<!-- Pico Config Builder -->
<dependency>
<groupId>io.helidon.pico.builder</groupId>
<artifactId>helidon-pico-builder-processor-tools</artifactId>
<groupId>io.helidon.pico.builder.config</groupId>
<artifactId>helidon-pico-builder-config</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.pico.builder</groupId>
<artifactId>helidon-pico-builder-processor</artifactId>
<groupId>io.helidon.pico.builder.config</groupId>
<artifactId>helidon-pico-builder-config-processor</artifactId>
<version>${helidon.version}</version>
</dependency>


</dependencies>
</dependencyManagement>
</project>
20 changes: 10 additions & 10 deletions pico/builder/README.md → builder/README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
# pico-builder
# builder

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:
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:
<ol>
<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>
<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>
<li>Generated classes always behave like a <i>SuperBuilder</i> from Lombok. Basically this means that builders can form
a hierarchy on the types they target (e.g., Level2 derives from Level1 derives from Level0, etc.).</li>
<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>
<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>
<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>
<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>
</ol>

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

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

The Helidon Pico Builder is completely independent of other parts of Pico. It can therefore be used in a standalone manner. The
The Helidon Builder is independent of other parts of Helidon. It can therefore be used in a standalone manner. The
generated implementation class will not require any special module to support those classes - just the types from your interface
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.

Expand All @@ -32,15 +32,15 @@ public interface MyConfigBean {
}
```
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.
3. Compile (using the <i>pico-builder-processor</i> in your annotation classpath).
3. Compile (using the <i>builder-processor</i> in your annotation classpath).

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

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

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# pico-builder
# builder

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

Expand Down
8 changes: 4 additions & 4 deletions pico/builder/builder/pom.xml → builder/builder/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<parent>
<groupId>io.helidon.pico.builder</groupId>
<artifactId>helidon-pico-builder-project</artifactId>
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder-project</artifactId>
<version>4.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>helidon-pico-builder</artifactId>
<name>Helidon Pico Builder</name>
<artifactId>helidon-builder</artifactId>
<name>Helidon Builder</name>

<dependencies>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package io.helidon.pico.builder;
package io.helidon.builder;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,20 @@
* limitations under the License.
*/

package io.helidon.pico.builder;
package io.helidon.builder;

import java.util.Map;
import java.util.function.Supplier;

/**
* A functional interface that can be used to visit all attributes of this type.
* <p>
* This type is used when {@link io.helidon.pico.builder.Builder#requireLibraryDependencies()} is used.
* This type is used when {@link Builder#requireLibraryDependencies()} is used.
*
* @param <T> type of the user defined context this attribute visitor supports
*/
@FunctionalInterface
public interface AttributeVisitor {
public interface AttributeVisitor<T> {

/**
* Visits the attribute named 'attrName'.
Expand All @@ -40,7 +42,7 @@ public interface AttributeVisitor {
void visit(String attrName,
Supplier<Object> valueSupplier,
Map<String, Object> meta,
Object userDefinedCtx,
T userDefinedCtx,
Class<?> type,
Class<?>... typeArgument);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package io.helidon.pico.builder;
package io.helidon.builder;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
Expand Down Expand Up @@ -62,6 +62,11 @@
*/
String DEFAULT_SUFFIX = "";

/**
* The default value for {@link #allowNulls()}.
*/
boolean DEFAULT_ALLOW_NULLS = false;

/**
* The default list type used for the generated class implementation for any references to {@link java.util.List} is found
* on the methods of the {@link Builder}-annotation interface.
Expand Down Expand Up @@ -167,6 +172,14 @@
*/
boolean requireBeanStyle() default false;

/**
* Should the bean and the builder allow for the possibility of nullable non-{@link java.util.Optional} values to be present.
* Default is {@code false}.
*
* @return true to allow for the possibility of nullable non-Optional values to be present
*/
boolean allowNulls() default DEFAULT_ALLOW_NULLS;

/**
* The list implementation type to apply, defaulting to {@link #DEFAULT_LIST_TYPE}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package io.helidon.pico.builder;
package io.helidon.builder;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,49 +14,66 @@
* limitations under the License.
*/

package io.helidon.pico.builder.spi;
package io.helidon.builder;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;

import io.helidon.pico.builder.AttributeVisitor;

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

/**
* Default constructor.
*/
// note: this needs to remain public since it will be new'ed from code-generated builder processing ...
// important note: this needs to remain public since it will be new'ed from code-generated builder processing ...
public RequiredAttributeVisitor() {
this(Builder.DEFAULT_ALLOW_NULLS);
}

/**
* Constructor.
*
* @param allowNullsByDefault true if nulls should be allowed
*/
// important note: this needs to remain public since it will be new'ed from code-generated builder processing ...
public RequiredAttributeVisitor(boolean allowNullsByDefault) {
this.allowNullsByDefault = allowNullsByDefault;
}

@Override
// important note: this needs to remain public since it will be new'ed from code-generated builder processing ...
public void visit(String attrName,
Supplier<Object> valueSupplier,
Map<String, Object> meta,
Object userDefinedCtx,
Class<?> type,
Class<?>... typeArgument) {
boolean required = Boolean.parseBoolean((String) meta.get("required"));
if (!required) {
String requiredStr = (String) meta.get("required");
boolean requiredPresent = Objects.nonNull(requiredStr);
boolean required = Boolean.parseBoolean(requiredStr);
if (!required && requiredPresent) {
return;
}

if (allowNullsByDefault && !requiredPresent) {
return;
}

Expand All @@ -73,6 +90,7 @@ public void visit(String attrName,
*
* @throws java.lang.IllegalStateException when any attributes are in violation with the validation policy
*/
// important note: this needs to remain public since it will be new'ed from code-generated builder processing ...
public void validate() {
if (!errors.isEmpty()) {
throw new IllegalStateException(String.join(", ", errors));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package io.helidon.pico.builder;
package io.helidon.builder;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@

/**
* The Builder API consists of a few annotations that can be used to create fluent builders for the types that use
* {@link io.helidon.pico.builder.Builder}, or otherwise one of its kind. The meta annotation
* {@link io.helidon.pico.builder.BuilderTrigger} is used to annotate the annotations that trigger custom-style builders.
* {@link io.helidon.builder.Builder}, or otherwise one of its kind. The meta annotation
* {@link io.helidon.builder.BuilderTrigger} is used to annotate the annotations that trigger custom-style builders.
* <p>
* The {@link io.helidon.pico.builder.Builder} annotation typically is applied to the an interface type, but it can also
* The {@link io.helidon.builder.Builder} annotation typically is applied to the an interface type, but it can also
* be used directly on annotation types as well. When applied, and if the annotation processor is applied for the builder-type
* annotation then an implementation class is generated that supports the fluent-builder pattern for that type.
* <p>
Expand All @@ -29,4 +29,4 @@
* <li>Any static or default method will be ignored during APT processing.</li>
* </ul>
*/
package io.helidon.pico.builder;
package io.helidon.builder;
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@
*/

/**
* The Pico Builder API / SPI module.
* The Builder API module.
*/
module io.helidon.pico.builder {
exports io.helidon.pico.builder;
exports io.helidon.pico.builder.spi;
module io.helidon.builder {
exports io.helidon.builder;
}
Loading