Skip to content

Commit

Permalink
Add Configuration for Kotlin's All-Open Plugin for JPA Entities
Browse files Browse the repository at this point in the history
  • Loading branch information
YangSiJun528 authored and mhalbritter committed Oct 11, 2024
1 parent 8666c5a commit 413a7f2
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
*
* @author Stephane Nicoll
* @author Moritz Halbritter
* @author Sijun Yang
*/
public class BuildMetadataResolver {

Expand Down Expand Up @@ -65,4 +66,16 @@ public boolean hasFacet(Build build, String facet) {
return dependencies(build).anyMatch((dependency) -> dependency.getFacets().contains(facet));
}

/**
* Checks if the given {@link Build} contains dependencies with the given
* {@code groupId}.
* @param build the build to query
* @param groupId the groupId to query
* @return {@code true} if this build defines at least a dependency with that groupId,
* {@code false} otherwise
*/
public boolean hasGroupId(Build build, String groupId) {
return dependencies(build).anyMatch((dependency) -> dependency.getGroupId().equals(groupId));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,38 @@
* related dependency is present.
*
* @author Madhura Bhave
* @author Sijun Yang
*/
public class KotlinJpaGradleBuildCustomizer implements BuildCustomizer<GradleBuild> {

private final BuildMetadataResolver buildMetadataResolver;

private final KotlinProjectSettings settings;

private final char quote;

public KotlinJpaGradleBuildCustomizer(InitializrMetadata metadata, KotlinProjectSettings settings,
ProjectDescription projectDescription) {
ProjectDescription projectDescription, char quote) {
this.buildMetadataResolver = new BuildMetadataResolver(metadata, projectDescription.getPlatformVersion());
this.settings = settings;
this.quote = quote;
}

@Override
public void customize(GradleBuild build) {
if (this.buildMetadataResolver.hasFacet(build, "jpa")) {
build.plugins()
.add("org.jetbrains.kotlin.plugin.jpa", (plugin) -> plugin.setVersion(this.settings.getVersion()));
build.extensions().customize("allOpen", (allOpen) -> {
allOpen.invoke("annotation", quote("jakarta.persistence.Entity"));
allOpen.invoke("annotation", quote("jakarta.persistence.MappedSuperclass"));
allOpen.invoke("annotation", quote("jakarta.persistence.Embeddable"));
});
}
}

private String quote(String element) {
return this.quote + element + this.quote;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
*
* @author Madhura Bhave
* @author Sebastien Deleuze
* @author Sijun Yang
*/
public class KotlinJpaMavenBuildCustomizer implements BuildCustomizer<MavenBuild> {

Expand All @@ -41,8 +42,15 @@ public KotlinJpaMavenBuildCustomizer(InitializrMetadata metadata, ProjectDescrip
public void customize(MavenBuild build) {
if (this.buildMetadataResolver.hasFacet(build, "jpa")) {
build.plugins().add("org.jetbrains.kotlin", "kotlin-maven-plugin", (kotlinPlugin) -> {
kotlinPlugin.configuration((configuration) -> configuration.configure("compilerPlugins",
(compilerPlugins) -> compilerPlugins.add("plugin", "jpa")));
kotlinPlugin.configuration((configuration) -> {
configuration.configure("compilerPlugins",
(compilerPlugins) -> compilerPlugins.add("plugin", "jpa"));
configuration.configure("pluginOptions", (option) -> {
option.add("option", "all-open:annotation=jakarta.persistence.Entity");
option.add("option", "all-open:annotation=jakarta.persistence.MappedSuperclass");
option.add("option", "all-open:annotation=jakarta.persistence.Embeddable");
});
});
kotlinPlugin.dependency("org.jetbrains.kotlin", "kotlin-maven-noarg", "${kotlin.version}");
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
* @author Stephane Nicoll
* @author Jean-Baptiste Nizet
* @author Moritz Halbritter
* @author Sijun Yang
*/
@Configuration
class KotlinProjectGenerationDefaultContributorsConfiguration {
Expand All @@ -67,10 +68,17 @@ BuildCustomizer<Build> kotlinDependenciesConfigurer() {
}

@Bean
@ConditionalOnBuildSystem(GradleBuildSystem.ID)
KotlinJpaGradleBuildCustomizer kotlinJpaGradleBuildCustomizer(InitializrMetadata metadata,
@ConditionalOnBuildSystem(value = GradleBuildSystem.ID, dialect = GradleBuildSystem.DIALECT_KOTLIN)
KotlinJpaGradleBuildCustomizer kotlinJpaGradleBuildCustomizerKotlinDsl(InitializrMetadata metadata,
KotlinProjectSettings settings, ProjectDescription projectDescription) {
return new KotlinJpaGradleBuildCustomizer(metadata, settings, projectDescription, '\"');
}

@Bean
@ConditionalOnBuildSystem(value = GradleBuildSystem.ID, dialect = GradleBuildSystem.DIALECT_GROOVY)
KotlinJpaGradleBuildCustomizer kotlinJpaGradleBuildCustomizerGroovyDsl(InitializrMetadata metadata,
KotlinProjectSettings settings, ProjectDescription projectDescription) {
return new KotlinJpaGradleBuildCustomizer(metadata, settings, projectDescription);
return new KotlinJpaGradleBuildCustomizer(metadata, settings, projectDescription, '\'');
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package io.spring.initializr.generator.spring.code.kotlin;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

import io.spring.initializr.generator.buildsystem.gradle.GradleBuild;
import io.spring.initializr.generator.buildsystem.gradle.GradlePlugin;
Expand All @@ -35,6 +37,7 @@
* Tests for {@link KotlinJpaGradleBuildCustomizer}.
*
* @author Madhura Bhave
* @author Sijun Yang
*/
class KotlinJpaGradleBuildCustomizerTests {

Expand All @@ -58,6 +61,32 @@ void customizeWhenJpaFacetAbsentShouldNotAddKotlinJpaPlugin() {
assertThat(build.plugins().values()).isEmpty();
}

@Test
void customizeWhenJpaFacetPresentShouldCustomizeAllOpen() {
Dependency dependency = Dependency.withId("foo");
dependency.setFacets(Collections.singletonList("jpa"));
GradleBuild build = getCustomizedBuild(dependency);
assertThat(build.extensions().values()).singleElement().satisfies((extension) -> {
assertThat(extension.getName()).isEqualTo("allOpen");
assertThat(extension.getInvocations())
.filteredOn((invocation) -> Objects.equals(invocation.getTarget(), "annotation"))
.extracting("arguments")
.containsExactlyInAnyOrder(List.of("\"jakarta.persistence.Entity\""),
List.of("\"jakarta.persistence.MappedSuperclass\""),
List.of("\"jakarta.persistence.Embeddable\""));
});
}

@Test
void customizeWhenJpaFacetAbsentShouldNotCustomizeAllOpen() {
Dependency dependency = Dependency.withId("foo");
GradleBuild build = getCustomizedBuild(dependency);
assertThat(build.extensions().values())
.filteredOn((extension) -> Objects.equals(extension.getName(), "allOpen"))
.isEmpty();
assertThat(build.extensions().values()).isEmpty();
}

private GradleBuild getCustomizedBuild(Dependency dependency) {
InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults()
.addDependencyGroup("test", dependency)
Expand All @@ -66,7 +95,7 @@ private GradleBuild getCustomizedBuild(Dependency dependency) {
MutableProjectDescription projectDescription = new MutableProjectDescription();
projectDescription.setPlatformVersion(Version.parse("1.0.0"));
KotlinJpaGradleBuildCustomizer customizer = new KotlinJpaGradleBuildCustomizer(metadata, settings,
projectDescription);
projectDescription, '\"');
GradleBuild build = new GradleBuild(new MetadataBuildItemResolver(metadata, Version.parse("2.0.0.RELEASE")));
build.dependencies().add("foo");
customizer.customize(build);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package io.spring.initializr.generator.spring.code.kotlin;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

import io.spring.initializr.generator.buildsystem.maven.MavenBuild;
import io.spring.initializr.generator.buildsystem.maven.MavenPlugin;
Expand All @@ -36,6 +38,7 @@
*
* @author Madhura Bhave
* @author Sebastien Deleuze
* @author Sijun Yang
*/
class KotlinJpaMavenBuildCustomizerTests {

Expand Down Expand Up @@ -67,6 +70,34 @@ void customizeWhenJpaFacetAbsentShouldNotAddKotlinJpaPlugin() {
assertThat(build.plugins().isEmpty()).isTrue();
}

@Test
void customizeWhenJpaFacetPresentShouldCustomizeAllOpen() {
Dependency dependency = Dependency.withId("foo");
dependency.setFacets(Collections.singletonList("jpa"));
MavenBuild build = getCustomizedBuild(dependency);

assertThat(build.plugins().values()).singleElement().satisfies((plugin) -> {
MavenPlugin.Configuration configuration = plugin.getConfiguration();

assertThat(configuration.getSettings()).filteredOn((setting) -> setting.getName().equals("pluginOptions"))
.isNotEmpty()
.first()
.satisfies((pluginOptions) -> assertThat(((List<MavenPlugin.Setting>) pluginOptions.getValue()))
.filteredOn((option) -> Objects.equals(option.getName(), "option"))
.map(MavenPlugin.Setting::getValue)
.containsExactlyInAnyOrder("all-open:annotation=jakarta.persistence.Entity",
"all-open:annotation=jakarta.persistence.MappedSuperclass",
"all-open:annotation=jakarta.persistence.Embeddable"));
});
}

@Test
void customizeWhenJpaFacetAbsentShouldNotCustomizeAllOpen() {
Dependency dependency = Dependency.withId("foo");
MavenBuild build = getCustomizedBuild(dependency);
assertThat(build.plugins().values()).isEmpty();
}

private MavenBuild getCustomizedBuild(Dependency dependency) {
InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults()
.addDependencyGroup("test", dependency)
Expand Down

0 comments on commit 413a7f2

Please sign in to comment.