Skip to content

Commit

Permalink
4.x: Inject update - collateral (helidon-io#8281)
Browse files Browse the repository at this point in the history
* Introduction of codegen modules
* Refactoring of modules to use new builder codegen (remove use of config metadata for builders)
* Deprecated old processor modules (such as builder processor)

Co-authored-by: Daniel Kec <daniel.kec@oracle.com>
Co-authored-by: Jeff Trent <jeff.trent@oracle.com>
Co-authored-by: David Kral <david.kral@oracle.com>
Signed-off-by: Tomas Langer <tomas.langer@oracle.com>
  • Loading branch information
4 people authored and hrstoyanov committed Feb 23, 2024
1 parent 601fbad commit 2553fdb
Show file tree
Hide file tree
Showing 294 changed files with 22,724 additions and 902 deletions.
28 changes: 28 additions & 0 deletions all/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,30 @@
<groupId>io.helidon.common</groupId>
<artifactId>helidon-common-tls</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.codegen</groupId>
<artifactId>helidon-codegen</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.codegen</groupId>
<artifactId>helidon-codegen-apt</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.codegen</groupId>
<artifactId>helidon-codegen-scan</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.codegen</groupId>
<artifactId>helidon-codegen-compiler</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.codegen</groupId>
<artifactId>helidon-codegen-class-model</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.codegen</groupId>
<artifactId>helidon-codegen-helidon-copyright</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.common.processor</groupId>
<artifactId>helidon-common-processor</artifactId>
Expand Down Expand Up @@ -1008,6 +1032,10 @@
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder-processor</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder-codegen</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.inject</groupId>
<artifactId>helidon-inject-api</artifactId>
Expand Down
43 changes: 38 additions & 5 deletions bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -237,11 +237,6 @@
<artifactId>helidon-security-integration-common</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.security.integration</groupId>
<artifactId>helidon-security-integration-webserver</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.security</groupId>
<artifactId>helidon-security-annotations</artifactId>
Expand Down Expand Up @@ -507,16 +502,49 @@
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.codegen</groupId>
<artifactId>helidon-codegen</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.codegen</groupId>
<artifactId>helidon-codegen-apt</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.codegen</groupId>
<artifactId>helidon-codegen-scan</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.codegen</groupId>
<artifactId>helidon-codegen-compiler</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.codegen</groupId>
<artifactId>helidon-codegen-class-model</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.codegen</groupId>
<artifactId>helidon-codegen-helidon-copyright</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<!-- deprecated module -->
<groupId>io.helidon.common.processor</groupId>
<artifactId>helidon-common-processor</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<!-- deprecated module -->
<groupId>io.helidon.common.processor</groupId>
<artifactId>helidon-common-processor-helidon-copyright</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<!-- deprecated module -->
<groupId>io.helidon.common.processor</groupId>
<artifactId>helidon-common-processor-class-model</artifactId>
<version>${helidon.version}</version>
Expand Down Expand Up @@ -1321,6 +1349,11 @@
<artifactId>helidon-builder-processor</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder-codegen</artifactId>
<version>${helidon.version}</version>
</dependency>

<!-- Injection Core -->
<dependency>
Expand Down
21 changes: 20 additions & 1 deletion builder/api/src/main/java/io/helidon/builder/api/Option.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Oracle and/or its affiliates.
* Copyright (c) 2023, 2024 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -426,4 +426,23 @@ private Option() {
*/
String value();
}

/**
* Define an option decorator.
* This is useful for example when setting a compound option, where we need to set additional options on this builder.
* <p>
* Decorator on collection based options will be ignored.
* Decorator on optional values must accept an option (as it would be called both from the setter and unset methods).
*/
@Target(ElementType.METHOD)
// note: class retention needed for cases when derived builders are inherited across modules
@Retention(RetentionPolicy.CLASS)
public @interface Decorator {
/**
* Type declaration including generic types (must match the declared generic type on the blueprint).
*
* @return type name with generic declaration
*/
Class<? extends Prototype.OptionDecorator<?, ?>> value();
}
}
43 changes: 37 additions & 6 deletions builder/api/src/main/java/io/helidon/builder/api/Prototype.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Oracle and/or its affiliates.
* Copyright (c) 2023, 2024 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -209,7 +209,7 @@ public interface Factory<T> {
public @interface Blueprint {
/**
* The generated interface is public by default. We can switch it to package local
* by setting this property to {@code false}-
* by setting this property to {@code false}.
*
* @return whether the generated interface should be public
*/
Expand All @@ -231,9 +231,10 @@ public interface Factory<T> {
boolean createFromConfigPublic() default true;

/**
* Method create() is public by default.
* Method create() is created whenever there are no fields required (or all have default values).
* This property can disable generation of the method.
*
* @return whether factory method create() should be public on prototype
* @return whether factory method create() should be created on prototype
*/
boolean createEmptyPublic() default true;

Expand Down Expand Up @@ -309,7 +310,7 @@ public interface Factory<T> {
* The builder provides accessors to all types, using {@link java.util.Optional} for any field that is optional,
* or any other field unless it has a default value. Primitive types are an exception (unless declared as required).
*
* @param <T> the type of the bean builder to intercept
* @param <T> the type of the builder to decorate
* @see io.helidon.builder.api.Prototype.Blueprint#decorator()
*/
@FunctionalInterface
Expand All @@ -322,6 +323,28 @@ public interface BuilderDecorator<T> {
void decorate(T target);
}

/**
* Provides a way to decorate a single option when it is applied to the builder.
* The decorator must have an accessible no argument constructor (at least package local).
*
* @param <B> the type of the builder to decorate
* @param <T> the type of the option to decorate
* @see io.helidon.builder.api.Prototype.Blueprint#decorator()
*/
@FunctionalInterface
public interface OptionDecorator<B, T> {
/**
* Provides the ability to decorate option as it is being set on the target builder.
* This method is invoked from within the setter of the value before the value is set on the builder (i.e. the
* builder still contains previous value).
* Do not call the same setter again from within this method, as it would end in a stack overflow.
*
* @param builder the target builder being decorated
* @param optionValue option value set by the caller of the setter method
*/
void decorate(B builder, T optionValue);
}

/**
* Adding this annotation in conjunction with the {@link Prototype.Blueprint} on a target interface
* type or method causes the {@link #value()} be added to the generated implementation class and methods respectfully.
Expand Down Expand Up @@ -407,6 +430,15 @@ public interface BuilderDecorator<T> {
public @interface PrototypeMethod {
}

/**
* Annotated constant of a custom methods type to be added to prototype interface.
* The constant will be generated as a reference to the annotated constant (so it must be package local).
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.CLASS)
public @interface Constant {
}

/**
* Add additional interfaces to implement by the prototype. Provide correct types (fully qualified) for generics.
*/
Expand All @@ -418,6 +450,5 @@ public interface BuilderDecorator<T> {
*/
String[] value();
}

}

58 changes: 58 additions & 0 deletions builder/codegen/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2022, 2024 Oracle and/or its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<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-builder-codegen</artifactId>
<name>Helidon Builder Code Generator</name>

<dependencies>
<dependency>
<groupId>io.helidon.common</groupId>
<artifactId>helidon-common-types</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.codegen</groupId>
<artifactId>helidon-codegen</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.codegen</groupId>
<artifactId>helidon-codegen-class-model</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2023, 2024 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.helidon.builder.codegen;

import java.util.List;
import java.util.Set;

import io.helidon.common.types.TypeName;

record AnnotationDataBlueprint(
boolean prototypePublic,
boolean builderPublic,
boolean createFromConfigPublic,
boolean createEmptyPublic,
boolean isFactory,
Set<TypeName> extendsList,
String javadoc,
List<TypeName> typeArguments) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2023, 2024 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.helidon.builder.codegen;

import io.helidon.common.types.Annotation;
import io.helidon.common.types.TypeInfo;

record AnnotationDataConfigured(boolean configured, String rootPrefix, boolean isRoot) {
static AnnotationDataConfigured create(TypeInfo typeInfo) {
boolean configured = false;
boolean isRoot = false;
String prefix = null;

if (typeInfo.hasAnnotation(Types.PROTOTYPE_CONFIGURED)) {
configured = true;

Annotation annotation = typeInfo.annotation(Types.PROTOTYPE_CONFIGURED);
// if the annotation is present, the value has to be defined (may be empty string)
prefix = annotation.stringValue().orElse(null);
if (prefix != null) {
isRoot = annotation.booleanValue("root").orElse(true);
}
}

return new AnnotationDataConfigured(configured, prefix, isRoot);
}
}
Loading

0 comments on commit 2553fdb

Please sign in to comment.