From 161fccbc7523bd675fef3229264b1d7120f129a5 Mon Sep 17 00:00:00 2001 From: bono007 Date: Mon, 21 Oct 2019 21:56:30 -0500 Subject: [PATCH 1/2] Keep track of original ProjectDescription See gh-1023 --- .../project/MutableProjectDescription.java | 39 +++ .../generator/project/ProjectDescription.java | 11 + .../generator/project/ProjectGenerator.java | 17 +- .../DefaultProjectDescriptionDiffFactory.java | 34 +++ .../project/diff/ProjectDescriptionDiff.java | 233 ++++++++++++++ .../diff/ProjectDescriptionDiffFactory.java | 38 +++ .../project/ProjectGeneratorTests.java | 14 + .../diff/ProjectDescriptionDiffTest.java | 283 ++++++++++++++++++ .../InitializrAutoConfiguration.java | 8 + .../InitializrAutoConfigurationTests.java | 6 + .../custom/CustomProjectContributor.java | 1 + .../custom/CustomProjectDescription.java | 14 + .../custom/CustomProjectDescriptionDiff.java | 48 +++ .../CustomProjectDescriptionDiffFactory.java | 35 +++ .../CustomProjectDescriptionDiffTest.java | 81 +++++ ...ntrollerCustomRequestIntegrationTests.java | 5 + 16 files changed, 866 insertions(+), 1 deletion(-) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/DefaultProjectDescriptionDiffFactory.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiff.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiffFactory.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiffTest.java create mode 100644 initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiff.java create mode 100644 initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiffFactory.java create mode 100644 initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiffTest.java diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/project/MutableProjectDescription.java b/initializr-generator/src/main/java/io/spring/initializr/generator/project/MutableProjectDescription.java index fa37ec95..dc435e70 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/project/MutableProjectDescription.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/project/MutableProjectDescription.java @@ -61,6 +61,33 @@ public class MutableProjectDescription implements ProjectDescription { private String baseDirectory; + public MutableProjectDescription() { + super(); + } + + protected MutableProjectDescription(final MutableProjectDescription source) { + super(); + setPlatformVersion(source.getPlatformVersion()); + setBuildSystem(source.getBuildSystem()); + setPackaging(source.getPackaging()); + setLanguage(source.getLanguage()); + source.getRequestedDependencies().forEach(this::addDependency); + setGroupId(source.getGroupId()); + setArtifactId(source.getArtifactId()); + setVersion(source.getVersion()); + setName(source.getName()); + setDescription(source.getDescription()); + setApplicationName(source.getApplicationName()); + setPackageName(source.getPackageName()); + setBaseDirectory(source.getBaseDirectory()); + } + + @Override + public MutableProjectDescription createCopy() { + return new MutableProjectDescription(this); + } + + @Override public Version getPlatformVersion() { return this.platformVersion; } @@ -69,6 +96,7 @@ public class MutableProjectDescription implements ProjectDescription { this.platformVersion = platformVersion; } + @Override public BuildSystem getBuildSystem() { return this.buildSystem; } @@ -77,6 +105,7 @@ public class MutableProjectDescription implements ProjectDescription { this.buildSystem = buildSystem; } + @Override public Packaging getPackaging() { return this.packaging; } @@ -85,6 +114,7 @@ public class MutableProjectDescription implements ProjectDescription { this.packaging = packaging; } + @Override public Language getLanguage() { return this.language; } @@ -101,10 +131,12 @@ public class MutableProjectDescription implements ProjectDescription { return addDependency(id, builder.build()); } + @Override public Map getRequestedDependencies() { return Collections.unmodifiableMap(this.requestedDependencies); } + @Override public String getGroupId() { return this.groupId; } @@ -113,6 +145,7 @@ public class MutableProjectDescription implements ProjectDescription { this.groupId = groupId; } + @Override public String getArtifactId() { return this.artifactId; } @@ -121,6 +154,7 @@ public class MutableProjectDescription implements ProjectDescription { this.artifactId = artifactId; } + @Override public String getVersion() { return this.version; } @@ -129,6 +163,7 @@ public class MutableProjectDescription implements ProjectDescription { this.version = version; } + @Override public String getName() { return this.name; } @@ -137,6 +172,7 @@ public class MutableProjectDescription implements ProjectDescription { this.name = name; } + @Override public String getDescription() { return this.description; } @@ -145,6 +181,7 @@ public class MutableProjectDescription implements ProjectDescription { this.description = description; } + @Override public String getApplicationName() { return this.applicationName; } @@ -153,6 +190,7 @@ public class MutableProjectDescription implements ProjectDescription { this.applicationName = applicationName; } + @Override public String getPackageName() { if (StringUtils.hasText(this.packageName)) { return this.packageName; @@ -167,6 +205,7 @@ public class MutableProjectDescription implements ProjectDescription { this.packageName = packageName; } + @Override public String getBaseDirectory() { return this.baseDirectory; } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectDescription.java b/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectDescription.java index fca2bdbe..28dcc5d7 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectDescription.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectDescription.java @@ -110,4 +110,15 @@ public interface ProjectDescription { */ String getBaseDirectory(); + /** + * ProjectDescription implementations should implement this to create a copy of + * themselves. However, the default implementation throws + * UnsupportedOperationException. + * @return never + * @throws UnsupportedOperationException always + */ + default ProjectDescription createCopy() { + throw new UnsupportedOperationException(); + } + } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectGenerator.java b/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectGenerator.java index 85d97c49..efaa8c83 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectGenerator.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectGenerator.java @@ -21,6 +21,10 @@ import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; +import io.spring.initializr.generator.project.diff.DefaultProjectDescriptionDiffFactory; +import io.spring.initializr.generator.project.diff.ProjectDescriptionDiff; +import io.spring.initializr.generator.project.diff.ProjectDescriptionDiffFactory; + import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.ImportSelector; @@ -119,9 +123,20 @@ public class ProjectGenerator { private Supplier resolve(ProjectDescription description, ProjectGenerationContext context) { return () -> { + if (description instanceof MutableProjectDescription) { + + final MutableProjectDescription mutableProjectDesc = (MutableProjectDescription) description; + + // Find the diff factory and use it to create and register a diff bean + final ProjectDescriptionDiffFactory diffFactory = context + .getBeanProvider(ProjectDescriptionDiffFactory.class) + .getIfAvailable(() -> new DefaultProjectDescriptionDiffFactory()); + final ProjectDescriptionDiff diff = diffFactory.create(mutableProjectDesc); + context.registerBean(ProjectDescriptionDiff.class, () -> diff); + context.getBeanProvider(ProjectDescriptionCustomizer.class).orderedStream() - .forEach((customizer) -> customizer.customize((MutableProjectDescription) description)); + .forEach((customizer) -> customizer.customize(mutableProjectDesc)); } return description; }; diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/DefaultProjectDescriptionDiffFactory.java b/initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/DefaultProjectDescriptionDiffFactory.java new file mode 100644 index 00000000..717ce260 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/DefaultProjectDescriptionDiffFactory.java @@ -0,0 +1,34 @@ +/* + * Copyright 2012-2019 the original author or authors. + * + * 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 + * + * https://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.spring.initializr.generator.project.diff; + +import io.spring.initializr.generator.project.ProjectDescription; + +/** + * A default {@link ProjectDescriptionDiffFactory} implementation that creates default + * {@link ProjectDescriptionDiff} instances. + * + * @author Chris Bono + */ +public class DefaultProjectDescriptionDiffFactory implements ProjectDescriptionDiffFactory { + + @Override + public ProjectDescriptionDiff create(final ProjectDescription description) { + return new ProjectDescriptionDiff(description); + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiff.java b/initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiff.java new file mode 100644 index 00000000..7ab832e5 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiff.java @@ -0,0 +1,233 @@ +/* + * Copyright 2012-2019 the original author or authors. + * + * 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 + * + * https://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.spring.initializr.generator.project.diff; + +import java.lang.reflect.Field; +import java.util.Objects; +import java.util.function.BiConsumer; + +import io.spring.initializr.generator.buildsystem.BuildSystem; +import io.spring.initializr.generator.language.Language; +import io.spring.initializr.generator.packaging.Packaging; +import io.spring.initializr.generator.project.ProjectDescription; +import io.spring.initializr.generator.version.Version; + +import org.springframework.util.ReflectionUtils; + +/** + * Provides a convenient API for determining if certain fields on a + * {@link ProjectDescription} were modified. + * + * @author Chris Bono + */ +public class ProjectDescriptionDiff { + + private final ProjectDescription original; + + /** + * Construct a {@link ProjectDescriptionDiff} that creates and uses a copy of the + * specified description as its source. + * @param original the description to copy as the source + */ + public ProjectDescriptionDiff(final ProjectDescription original) { + this.original = original.createCopy(); + } + + /** + * Gets the copy of the originally specified description that is being tracked. + * @return copy of the originally specified description + */ + public ProjectDescription getOriginal() { + return this.original; + } + + /** + * Calls the specified consumer if the {@code platformVersion} is different on the + * original source project description than the specified project description. + * @param current the project description to test against + * @param consumer to call if the property has changed + */ + public void ifPlatformVersionChanged(final ProjectDescription current, + final BiConsumer consumer) { + if (!Objects.equals(this.original.getPlatformVersion(), current.getPlatformVersion())) { + consumer.accept(this.original.getPlatformVersion(), current.getPlatformVersion()); + } + } + + /** + * Calls the specified consumer if the {@code buildSystem} is different on the + * original source project description than the specified project description. + * @param current the description to test against + * @param consumer to call if the property has changed + */ + public void ifBuildSystemChanged(final ProjectDescription current, + final BiConsumer consumer) { + if (!Objects.equals(this.original.getBuildSystem(), current.getBuildSystem())) { + consumer.accept(this.original.getBuildSystem(), current.getBuildSystem()); + } + } + + /** + * Calls the specified consumer if the {@code packaging} is different on the original + * source project description than the specified project description. + * @param current the description to test against + * @param consumer to call if the property has changed + */ + public void ifPackagingChanged(final ProjectDescription current, final BiConsumer consumer) { + if (!Objects.equals(this.original.getPackaging(), current.getPackaging())) { + consumer.accept(this.original.getPackaging(), current.getPackaging()); + } + } + + /** + * Calls the specified consumer if the {@code language} is different on the original + * source project description than the specified project description. + * @param current the description to test against + * @param consumer to call if the property has changed + */ + public void ifLanguageChanged(final ProjectDescription current, final BiConsumer consumer) { + if (!Objects.equals(this.original.getLanguage(), current.getLanguage())) { + consumer.accept(this.original.getLanguage(), current.getLanguage()); + } + } + + /** + * Calls the specified consumer if the {@code groupId} is different on the original + * source project description than the specified project description. + * @param current the description to test against + * @param consumer to call if the property has changed + */ + public void ifGroupIdChanged(final ProjectDescription current, final BiConsumer consumer) { + if (!Objects.equals(this.original.getGroupId(), current.getGroupId())) { + consumer.accept(this.original.getGroupId(), current.getGroupId()); + } + } + + /** + * Calls the specified consumer if the {@code artifactId} is different on the original + * source project description than the specified project description. + * @param current the description to test against + * @param consumer to call if the property has changed + */ + public void ifArtifactIdChanged(final ProjectDescription current, final BiConsumer consumer) { + if (!Objects.equals(this.original.getArtifactId(), current.getArtifactId())) { + consumer.accept(this.original.getArtifactId(), current.getArtifactId()); + } + } + + /** + * Calls the specified consumer if the {@code version} is different on the original + * source project description than the specified project description. + * @param current the description to test against + * @param consumer to call if the property has changed + */ + public void ifVersionChanged(final ProjectDescription current, final BiConsumer consumer) { + if (!Objects.equals(this.original.getVersion(), current.getVersion())) { + consumer.accept(this.original.getVersion(), current.getVersion()); + } + } + + /** + * Calls the specified consumer if the {@code name} is different on the original + * source project description than the specified project description. + * @param current the description to test against + * @param consumer to call if the property has changed + */ + public void ifNameChanged(final ProjectDescription current, final BiConsumer consumer) { + if (!Objects.equals(this.original.getName(), current.getName())) { + consumer.accept(this.original.getName(), current.getName()); + } + } + + /** + * Calls the specified consumer if the {@code description} is different on the + * original source project description than the specified project description. + * @param current the description to test against + * @param consumer to call if the property has changed + */ + public void ifDescriptionChanged(final ProjectDescription current, final BiConsumer consumer) { + if (!Objects.equals(this.original.getDescription(), current.getDescription())) { + consumer.accept(this.original.getDescription(), current.getDescription()); + } + } + + /** + * Calls the specified consumer if the {@code applicationName} is different on the + * original source project description than the specified project description. + * @param current the description to test against + * @param consumer to call if the property has changed + */ + public void ifApplicationNameChanged(final ProjectDescription current, final BiConsumer consumer) { + if (!Objects.equals(this.original.getApplicationName(), current.getApplicationName())) { + consumer.accept(this.original.getApplicationName(), current.getApplicationName()); + } + } + + /** + * Calls the specified consumer if the {@code packageName} is different on the + * original source project description than the specified project description. + * @param current the description to test against + * @param consumer to call if the property has changed + */ + public void ifPackageNameChanged(final ProjectDescription current, final BiConsumer consumer) { + if (!Objects.equals(this.original.getPackageName(), current.getPackageName())) { + consumer.accept(this.original.getPackageName(), current.getPackageName()); + } + } + + /** + * Calls the specified consumer if the {@code baseDirectory} is different on the + * original source project description than the specified project description. + * @param current the description to test against + * @param consumer to call if the property has changed + */ + public void ifBaseDirectoryChanged(final ProjectDescription current, final BiConsumer consumer) { + if (!Objects.equals(this.original.getBaseDirectory(), current.getBaseDirectory())) { + consumer.accept(this.original.getBaseDirectory(), current.getBaseDirectory()); + } + } + + /** + * Calls the specified consumer if the value of the specified property is different on + * the original source project description than the specified project description. + * @param current the description to test against + * @param property the name of the property to check + * @param propertyClass the class of the property to check + * @param consumer to call if the property has changed + * @param type of the property + */ + public void ifPropertyChanged(final ProjectDescription current, final String property, + final Class propertyClass, final BiConsumer consumer) { + final V originalValue = getPropertyValueReflectively(this.original, property); + final V currentValue = getPropertyValueReflectively(current, property); + if (!Objects.equals(originalValue, currentValue)) { + consumer.accept(originalValue, currentValue); + } + } + + private V getPropertyValueReflectively(final ProjectDescription description, final String property) { + final Class descriptionClass = description.getClass(); + final Field field = ReflectionUtils.findField(descriptionClass, property); + if (field == null) { + throw new IllegalArgumentException( + String.format("No property named '%s' in '%s'.", property, descriptionClass.getSimpleName())); + } + ReflectionUtils.makeAccessible(field); + return (V) ReflectionUtils.getField(field, description); + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiffFactory.java b/initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiffFactory.java new file mode 100644 index 00000000..eda62aa9 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiffFactory.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012-2019 the original author or authors. + * + * 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 + * + * https://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.spring.initializr.generator.project.diff; + +import io.spring.initializr.generator.project.ProjectDescription; + +/** + * A factory for {@link ProjectDescriptionDiff} objects. + * + * @param the type of {@link ProjectDescription} + * @author Chris Bono + */ +public interface ProjectDescriptionDiffFactory { + + /** + * Construct a diff for the specified {@link ProjectDescription}. + *

+ * @param description the project description to use as the source of the diff + * @return a diff instance using the current state of the specified description as its + * source + */ + ProjectDescriptionDiff create(T description); + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/project/ProjectGeneratorTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/project/ProjectGeneratorTests.java index 8b68ae32..4d837230 100644 --- a/initializr-generator/src/test/java/io/spring/initializr/generator/project/ProjectGeneratorTests.java +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/project/ProjectGeneratorTests.java @@ -20,6 +20,9 @@ import java.io.IOException; import java.util.Map; import java.util.function.Consumer; +import io.spring.initializr.generator.project.diff.DefaultProjectDescriptionDiffFactory; +import io.spring.initializr.generator.project.diff.ProjectDescriptionDiff; +import io.spring.initializr.generator.project.diff.ProjectDescriptionDiffFactory; import org.junit.jupiter.api.Test; import org.mockito.InOrder; @@ -53,6 +56,17 @@ public class ProjectGeneratorTests { assertThat(description).isSameAs(beanDescription); } + @Test + void generateRegisterProjectDescriptionDiff() { + ProjectGenerator generator = new ProjectGenerator((context) -> context + .registerBean(ProjectDescriptionDiffFactory.class, () -> new DefaultProjectDescriptionDiffFactory())); + MutableProjectDescription description = new MutableProjectDescription(); + generator.generate(description, (context) -> { + assertThat(context.getBeansOfType(ProjectDescriptionDiff.class)).hasSize(1); + return context.getBean(ProjectDescriptionDiff.class); + }); + } + @Test void generateInvokeContextInitializerBeforeContextIsRefreshed() { ProjectGenerator generator = new ProjectGenerator((context) -> { diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiffTest.java b/initializr-generator/src/test/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiffTest.java new file mode 100644 index 00000000..c611117c --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiffTest.java @@ -0,0 +1,283 @@ +/* + * Copyright 2012-2019 the original author or authors. + * + * 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 + * + * https://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.spring.initializr.generator.project.diff; + +import java.util.function.BiConsumer; + +import io.spring.initializr.generator.buildsystem.BuildSystem; +import io.spring.initializr.generator.buildsystem.gradle.GradleBuildSystem; +import io.spring.initializr.generator.buildsystem.maven.MavenBuildSystem; +import io.spring.initializr.generator.language.Language; +import io.spring.initializr.generator.language.java.JavaLanguage; +import io.spring.initializr.generator.packaging.Packaging; +import io.spring.initializr.generator.project.MutableProjectDescription; +import io.spring.initializr.generator.project.ProjectDescription; +import io.spring.initializr.generator.version.Version; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; + +class ProjectDescriptionDiffTest { + + @Test + void originalIsCopied() { + ProjectDescription original = createProjectDescription(); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(original); + assertThat(diff.getOriginal()).usingRecursiveComparison().isEqualTo(original); + assertThat(diff.getOriginal()).isNotSameAs(original); + } + + @Test + void noChanges() { + MutableProjectDescription description = createProjectDescription(); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + BiConsumer failIfCalled = (v1, v2) -> fail("Values should not have changed"); + diff.ifPlatformVersionChanged(description, failIfCalled); + diff.ifBuildSystemChanged(description, failIfCalled); + diff.ifPackagingChanged(description, failIfCalled); + diff.ifLanguageChanged(description, failIfCalled); + diff.ifGroupIdChanged(description, failIfCalled); + diff.ifArtifactIdChanged(description, failIfCalled); + diff.ifVersionChanged(description, failIfCalled); + diff.ifNameChanged(description, failIfCalled); + diff.ifDescriptionChanged(description, failIfCalled); + diff.ifApplicationNameChanged(description, failIfCalled); + diff.ifPackageNameChanged(description, failIfCalled); + diff.ifBaseDirectoryChanged(description, failIfCalled); + diff.ifPropertyChanged(description, "name", String.class, failIfCalled); + } + + @Test + void platformVersionChanged() { + MutableProjectDescription description = createProjectDescription(); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + Version original = description.getPlatformVersion(); + description.setPlatformVersion(Version.parse("2.0.0.RELEASE")); + CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { + assertThat(prev).isEqualTo(original); + assertThat(curr).isEqualTo(description.getPlatformVersion()); + }); + diff.ifPlatformVersionChanged(description, changeHandler); + diff.ifPropertyChanged(description, "platformVersion", Version.class, changeHandler); + assertThat(changeHandler.timesCalled()).isEqualTo(2); + } + + @Test + void buildSystemChanged() { + MutableProjectDescription description = createProjectDescription(); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + BuildSystem original = description.getBuildSystem(); + description.setBuildSystem(BuildSystem.forId(GradleBuildSystem.ID)); + CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { + assertThat(prev).isEqualTo(original); + assertThat(curr).isEqualTo(description.getBuildSystem()); + }); + diff.ifBuildSystemChanged(description, changeHandler); + diff.ifPropertyChanged(description, "buildSystem", BuildSystem.class, changeHandler); + assertThat(changeHandler.timesCalled()).isEqualTo(2); + } + + @Test + void packagingChanged() { + MutableProjectDescription description = createProjectDescription(); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + Packaging original = description.getPackaging(); + description.setPackaging(Packaging.forId("war")); + CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { + assertThat(prev).isEqualTo(original); + assertThat(curr).isEqualTo(description.getPackaging()); + }); + diff.ifPackagingChanged(description, changeHandler); + diff.ifPropertyChanged(description, "packaging", Packaging.class, changeHandler); + assertThat(changeHandler.timesCalled()).isEqualTo(2); + } + + @Test + void languageChanged() { + MutableProjectDescription description = createProjectDescription(); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + Language original = description.getLanguage(); + description.setLanguage(Language.forId(JavaLanguage.ID, "13")); + CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { + assertThat(prev).isEqualTo(original); + assertThat(curr).isEqualTo(description.getLanguage()); + }); + diff.ifLanguageChanged(description, changeHandler); + diff.ifPropertyChanged(description, "language", String.class, changeHandler); + assertThat(changeHandler.timesCalled()).isEqualTo(2); + } + + @Test + void groupIdChanged() { + MutableProjectDescription description = createProjectDescription(); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + String original = description.getGroupId(); + description.setGroupId("group5150"); + CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { + assertThat(prev).isEqualTo(original); + assertThat(curr).isEqualTo(description.getGroupId()); + }); + diff.ifGroupIdChanged(description, changeHandler); + diff.ifPropertyChanged(description, "groupId", String.class, changeHandler); + assertThat(changeHandler.timesCalled()).isEqualTo(2); + } + + @Test + void artifactIdChanged() { + MutableProjectDescription description = createProjectDescription(); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + String original = description.getArtifactId(); + description.setArtifactId("artifact5150"); + CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { + assertThat(prev).isEqualTo(original); + assertThat(curr).isEqualTo(description.getArtifactId()); + }); + diff.ifArtifactIdChanged(description, changeHandler); + diff.ifPropertyChanged(description, "artifactId", String.class, changeHandler); + assertThat(changeHandler.timesCalled()).isEqualTo(2); + } + + @Test + void versionChanged() { + MutableProjectDescription description = createProjectDescription(); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + String original = description.getVersion(); + description.setVersion("version5150"); + CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { + assertThat(prev).isEqualTo(original); + assertThat(curr).isEqualTo(description.getVersion()); + }); + diff.ifVersionChanged(description, changeHandler); + diff.ifPropertyChanged(description, "version", String.class, changeHandler); + assertThat(changeHandler.timesCalled()).isEqualTo(2); + } + + @Test + void nameChanged() { + MutableProjectDescription description = createProjectDescription(); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + String original = description.getName(); + description.setName("name5150"); + CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { + assertThat(prev).isEqualTo(original); + assertThat(curr).isEqualTo(description.getName()); + }); + diff.ifNameChanged(description, changeHandler); + diff.ifPropertyChanged(description, "name", String.class, changeHandler); + assertThat(changeHandler.timesCalled()).isEqualTo(2); + } + + @Test + void descriptionChanged() { + MutableProjectDescription description = createProjectDescription(); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + String original = description.getDescription(); + description.setDescription("desc5150"); + CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { + assertThat(prev).isEqualTo(original); + assertThat(curr).isEqualTo(description.getDescription()); + }); + diff.ifDescriptionChanged(description, changeHandler); + diff.ifPropertyChanged(description, "description", String.class, changeHandler); + assertThat(changeHandler.timesCalled()).isEqualTo(2); + } + + @Test + void applicationNameChanged() { + MutableProjectDescription description = createProjectDescription(); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + String original = description.getApplicationName(); + description.setApplicationName("appname5150"); + CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { + assertThat(prev).isEqualTo(original); + assertThat(curr).isEqualTo(description.getApplicationName()); + }); + diff.ifApplicationNameChanged(description, changeHandler); + diff.ifPropertyChanged(description, "applicationName", String.class, changeHandler); + assertThat(changeHandler.timesCalled()).isEqualTo(2); + } + + @Test + void packageNameChanged() { + MutableProjectDescription description = createProjectDescription(); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + String original = description.getPackageName(); + description.setPackageName("pkg5150"); + CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { + assertThat(prev).isEqualTo(original); + assertThat(curr).isEqualTo(description.getPackageName()); + }); + diff.ifPackageNameChanged(description, changeHandler); + diff.ifPropertyChanged(description, "packageName", String.class, changeHandler); + assertThat(changeHandler.timesCalled()).isEqualTo(2); + } + + @Test + void baseDirectoryChanged() { + MutableProjectDescription description = createProjectDescription(); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + String original = description.getBaseDirectory(); + description.setBaseDirectory("baseDir5150"); + CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { + assertThat(prev).isEqualTo(original); + assertThat(curr).isEqualTo(description.getBaseDirectory()); + }); + diff.ifBaseDirectoryChanged(description, changeHandler); + diff.ifPropertyChanged(description, "baseDirectory", String.class, changeHandler); + assertThat(changeHandler.timesCalled()).isEqualTo(2); + } + + private MutableProjectDescription createProjectDescription() { + MutableProjectDescription description = new MutableProjectDescription(); + description.setBuildSystem(BuildSystem.forId(MavenBuildSystem.ID)); + description.setLanguage(Language.forId(JavaLanguage.ID, "11")); + description.setPlatformVersion(Version.parse("2.2.0.RELEASE")); + description.setGroupId("com.example"); + description.setArtifactId("demo"); + description.setName("demo"); + description.setVersion("0.0.8"); + description.setApplicationName("DemoApplication"); + description.setPackageName("com.example.demo"); + description.setPackaging(Packaging.forId("jar")); + description.setBaseDirectory("."); + return description; + } + + static class CallTrackingBiConsumer implements BiConsumer { + + private final BiConsumer delegate; + + private int callCount; + + CallTrackingBiConsumer(BiConsumer delegate) { + this.delegate = delegate; + } + + @Override + public void accept(T t, U u) { + this.callCount++; + this.delegate.accept(t, u); + } + + int timesCalled() { + return this.callCount; + } + + } + +} diff --git a/initializr-web/src/main/java/io/spring/initializr/web/autoconfigure/InitializrAutoConfiguration.java b/initializr-web/src/main/java/io/spring/initializr/web/autoconfigure/InitializrAutoConfiguration.java index 079a6169..a08dcf4c 100644 --- a/initializr-web/src/main/java/io/spring/initializr/web/autoconfigure/InitializrAutoConfiguration.java +++ b/initializr-web/src/main/java/io/spring/initializr/web/autoconfigure/InitializrAutoConfiguration.java @@ -28,6 +28,8 @@ import io.spring.initializr.generator.io.SimpleIndentStrategy; import io.spring.initializr.generator.io.template.MustacheTemplateRenderer; import io.spring.initializr.generator.io.template.TemplateRenderer; import io.spring.initializr.generator.project.ProjectDirectoryFactory; +import io.spring.initializr.generator.project.diff.DefaultProjectDescriptionDiffFactory; +import io.spring.initializr.generator.project.diff.ProjectDescriptionDiffFactory; import io.spring.initializr.metadata.DependencyMetadataProvider; import io.spring.initializr.metadata.InitializrMetadata; import io.spring.initializr.metadata.InitializrMetadataBuilder; @@ -129,6 +131,12 @@ public class InitializrAutoConfiguration { return new DefaultDependencyMetadataProvider(); } + @Bean + @ConditionalOnMissingBean + ProjectDescriptionDiffFactory projectDescriptionDiffFactory() { + return new DefaultProjectDescriptionDiffFactory(); + } + /** * Initializr web configuration. */ diff --git a/initializr-web/src/test/java/io/spring/initializr/web/autoconfigure/InitializrAutoConfigurationTests.java b/initializr-web/src/test/java/io/spring/initializr/web/autoconfigure/InitializrAutoConfigurationTests.java index c5a36e81..3f39972f 100755 --- a/initializr-web/src/test/java/io/spring/initializr/web/autoconfigure/InitializrAutoConfigurationTests.java +++ b/initializr-web/src/test/java/io/spring/initializr/web/autoconfigure/InitializrAutoConfigurationTests.java @@ -17,6 +17,7 @@ package io.spring.initializr.web.autoconfigure; import io.spring.initializr.generator.io.template.TemplateRenderer; +import io.spring.initializr.generator.project.diff.ProjectDescriptionDiffFactory; import io.spring.initializr.metadata.DependencyMetadataProvider; import io.spring.initializr.metadata.InitializrMetadataProvider; import io.spring.initializr.web.controller.CommandLineMetadataController; @@ -63,6 +64,11 @@ class InitializrAutoConfigurationTests { this.contextRunner.run((context) -> assertThat(context).hasSingleBean(TemplateRenderer.class)); } + @Test + void autoConfigRegistersDiffFactory() { + this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ProjectDescriptionDiffFactory.class)); + } + @Test void autoConfigWhenTemplateRendererBeanPresentDoesNotRegisterTemplateRenderer() { this.contextRunner.withUserConfiguration(CustomTemplateRendererConfiguration.class).run((context) -> { diff --git a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectContributor.java b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectContributor.java index cc135c95..5e3cca91 100644 --- a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectContributor.java +++ b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectContributor.java @@ -44,6 +44,7 @@ class CustomProjectContributor implements ProjectContributor { && ((CustomProjectDescription) this.description).isCustomFlag()) { Files.createFile(projectRoot.resolve("custom.txt")); } + } } diff --git a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescription.java b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescription.java index dc7fbaa2..c4cb8eef 100644 --- a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescription.java +++ b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescription.java @@ -28,6 +28,20 @@ class CustomProjectDescription extends MutableProjectDescription { private boolean customFlag; + CustomProjectDescription() { + super(); + } + + CustomProjectDescription(final CustomProjectDescription source) { + super(source); + setCustomFlag(source.isCustomFlag()); + } + + @Override + public CustomProjectDescription createCopy() { + return new CustomProjectDescription(this); + } + boolean isCustomFlag() { return this.customFlag; } diff --git a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiff.java b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiff.java new file mode 100644 index 00000000..16742bde --- /dev/null +++ b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiff.java @@ -0,0 +1,48 @@ +/* + * Copyright 2012-2019 the original author or authors. + * + * 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 + * + * https://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.spring.initializr.web.controller.custom; + +import java.util.function.BiConsumer; + +import io.spring.initializr.generator.project.diff.ProjectDescriptionDiff; + +/** + * Extends the base {@link ProjectDescriptionDiff} to provide convenient diff methods on + * {@link CustomProjectDescription}. + * + * @author cbono + */ +class CustomProjectDescriptionDiff extends ProjectDescriptionDiff { + + CustomProjectDescriptionDiff(final CustomProjectDescription original) { + super(original); + } + + /** + * Optionally calls the specified consumer if the {@code customFlag} is different on + * the original source description and the specified current description. + * @param current the description to test against + * @param consumer to call if the property has changed + */ + void ifCUstomFlagChanged(final CustomProjectDescription current, final BiConsumer consumer) { + final CustomProjectDescription original = (CustomProjectDescription) super.getOriginal(); + if (original.isCustomFlag() != current.isCustomFlag()) { + consumer.accept(original.isCustomFlag(), current.isCustomFlag()); + } + } + +} diff --git a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiffFactory.java b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiffFactory.java new file mode 100644 index 00000000..bd56bdd6 --- /dev/null +++ b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiffFactory.java @@ -0,0 +1,35 @@ +/* + * Copyright 2012-2019 the original author or authors. + * + * 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 + * + * https://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.spring.initializr.web.controller.custom; + +import io.spring.initializr.generator.project.diff.ProjectDescriptionDiff; +import io.spring.initializr.generator.project.diff.ProjectDescriptionDiffFactory; + +/** + * A custom {@link ProjectDescriptionDiffFactory} implementation that creates custom + * {@link CustomProjectDescriptionDiff} instances. + * + * @author cbono + */ +public class CustomProjectDescriptionDiffFactory implements ProjectDescriptionDiffFactory { + + @Override + public ProjectDescriptionDiff create(final CustomProjectDescription description) { + return new CustomProjectDescriptionDiff(description); + } + +} diff --git a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiffTest.java b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiffTest.java new file mode 100644 index 00000000..0085fa67 --- /dev/null +++ b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiffTest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2012-2019 the original author or authors. + * + * 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 + * + * https://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.spring.initializr.web.controller.custom; + +import io.spring.initializr.generator.buildsystem.BuildSystem; +import io.spring.initializr.generator.buildsystem.maven.MavenBuildSystem; +import io.spring.initializr.generator.language.Language; +import io.spring.initializr.generator.language.java.JavaLanguage; +import io.spring.initializr.generator.packaging.Packaging; +import io.spring.initializr.generator.version.Version; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; + +/** + * Simple sanity test around the custom diff extension model. + */ +class CustomProjectDescriptionDiffTest { + + @Test + void sanityCheck() { + + CustomProjectDescription description = customProjectDescription(); + CustomProjectDescriptionDiffFactory diffFactory = new CustomProjectDescriptionDiffFactory(); + CustomProjectDescriptionDiff diff = (CustomProjectDescriptionDiff) diffFactory.create(description); + + // copied + assertThat(diff.getOriginal()).usingRecursiveComparison().isEqualTo(description); + assertThat(diff.getOriginal()).isNotSameAs(description); + + // no changes + diff.ifCUstomFlagChanged(description, (v1, v2) -> fail("Values should not have changed")); + + // changes + boolean originalValue = description.isCustomFlag(); + description.setCustomFlag(!originalValue); + + // TODO could use the CallTrackingBiConsumer that I used in initializr-generator + // tests but then where to put it? + final boolean[] called = { false }; + diff.ifCUstomFlagChanged(description, (prev, curr) -> { + assertThat(prev).isEqualTo(originalValue); + assertThat(curr).isEqualTo(description.isCustomFlag()); + called[0] = true; + }); + assertThat(called[0]).isTrue(); + } + + private CustomProjectDescription customProjectDescription() { + CustomProjectDescription description = new CustomProjectDescription(); + description.setBuildSystem(BuildSystem.forId(MavenBuildSystem.ID)); + description.setLanguage(Language.forId(JavaLanguage.ID, "11")); + description.setPlatformVersion(Version.parse("2.2.0.RELEASE")); + description.setGroupId("com.example"); + description.setArtifactId("demo"); + description.setName("demo"); + description.setVersion("0.0.8"); + description.setApplicationName("DemoApplication"); + description.setPackageName("com.example.demo"); + description.setPackaging(Packaging.forId("jar")); + description.setBaseDirectory("."); + description.setCustomFlag(true); + return description; + } + +} diff --git a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/ProjectGenerationControllerCustomRequestIntegrationTests.java b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/ProjectGenerationControllerCustomRequestIntegrationTests.java index 68c9b2c3..9144d89e 100644 --- a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/ProjectGenerationControllerCustomRequestIntegrationTests.java +++ b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/ProjectGenerationControllerCustomRequestIntegrationTests.java @@ -79,6 +79,11 @@ public class ProjectGenerationControllerCustomRequestIntegrationTests return new CustomProjectGenerationController(metadataProvider, projectGenerationInvoker); } + @Bean + CustomProjectDescriptionDiffFactory customProjectDescriptionDiffFactory() { + return new CustomProjectDescriptionDiffFactory(); + } + } static class CustomProjectRequestToDescriptionConverter From 5325e679e251c47be31f686017848a5c640de29a Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Fri, 27 Dec 2019 10:32:06 +0100 Subject: [PATCH 2/2] Polish "Keep track of original ProjectDescription" See gh-1023 --- .../main/asciidoc/configuration-guide.adoc | 4 +- .../DefaultProjectDescriptionDiffFactory.java | 8 +- .../project/MutableProjectDescription.java | 34 ++- .../generator/project/ProjectDescription.java | 20 +- .../{diff => }/ProjectDescriptionDiff.java | 72 ++--- .../ProjectDescriptionDiffFactory.java | 16 +- .../generator/project/ProjectGenerator.java | 21 +- .../project/ProjectDescriptionDiffTests.java | 226 ++++++++++++++ .../project/ProjectGeneratorTests.java | 28 +- .../diff/ProjectDescriptionDiffTest.java | 283 ------------------ .../InitializrAutoConfiguration.java | 8 - .../InitializrAutoConfigurationTests.java | 6 - .../custom/CustomProjectContributor.java | 1 - .../custom/CustomProjectDescription.java | 5 +- .../custom/CustomProjectDescriptionDiff.java | 24 +- .../CustomProjectDescriptionDiffFactory.java | 35 --- .../CustomProjectDescriptionDiffTest.java | 81 ----- ...ntrollerCustomRequestIntegrationTests.java | 32 +- 18 files changed, 356 insertions(+), 548 deletions(-) rename initializr-generator/src/main/java/io/spring/initializr/generator/project/{diff => }/DefaultProjectDescriptionDiffFactory.java (78%) rename initializr-generator/src/main/java/io/spring/initializr/generator/project/{diff => }/ProjectDescriptionDiff.java (66%) rename initializr-generator/src/main/java/io/spring/initializr/generator/project/{diff => }/ProjectDescriptionDiffFactory.java (66%) create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/project/ProjectDescriptionDiffTests.java delete mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiffTest.java delete mode 100644 initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiffFactory.java delete mode 100644 initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiffTest.java diff --git a/initializr-docs/src/main/asciidoc/configuration-guide.adoc b/initializr-docs/src/main/asciidoc/configuration-guide.adoc index 5fb3d235..57b46da5 100644 --- a/initializr-docs/src/main/asciidoc/configuration-guide.adoc +++ b/initializr-docs/src/main/asciidoc/configuration-guide.adoc @@ -129,7 +129,9 @@ include::{code-examples}/doc/generator/project/SampleContributor.java[tag=code] ==== Project Generation Lifecycle When a `ProjectGenerator` is instructed to generate a project, the specified `ProjectDescription` can be customized using available `ProjectDescriptionCustomizer` -beans and can be ordered using Spring's `Ordered` interface. +beans and can be ordered using Spring's `Ordered` interface. A `ProjectDescriptionDiff` +bean is available for extensions that wish to know if an attribute of the original +`ProjectDescription` was modified. Once the description has been customized based on the available ``ProjectDescriptionCustomizer``s, the generator uses a `ProjectAssetGenerator` to diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/DefaultProjectDescriptionDiffFactory.java b/initializr-generator/src/main/java/io/spring/initializr/generator/project/DefaultProjectDescriptionDiffFactory.java similarity index 78% rename from initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/DefaultProjectDescriptionDiffFactory.java rename to initializr-generator/src/main/java/io/spring/initializr/generator/project/DefaultProjectDescriptionDiffFactory.java index 717ce260..8a304b8a 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/DefaultProjectDescriptionDiffFactory.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/project/DefaultProjectDescriptionDiffFactory.java @@ -14,9 +14,7 @@ * limitations under the License. */ -package io.spring.initializr.generator.project.diff; - -import io.spring.initializr.generator.project.ProjectDescription; +package io.spring.initializr.generator.project; /** * A default {@link ProjectDescriptionDiffFactory} implementation that creates default @@ -24,10 +22,10 @@ import io.spring.initializr.generator.project.ProjectDescription; * * @author Chris Bono */ -public class DefaultProjectDescriptionDiffFactory implements ProjectDescriptionDiffFactory { +public class DefaultProjectDescriptionDiffFactory implements ProjectDescriptionDiffFactory { @Override - public ProjectDescriptionDiff create(final ProjectDescription description) { + public ProjectDescriptionDiff create(ProjectDescription description) { return new ProjectDescriptionDiff(description); } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/project/MutableProjectDescription.java b/initializr-generator/src/main/java/io/spring/initializr/generator/project/MutableProjectDescription.java index dc435e70..87b4399c 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/project/MutableProjectDescription.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/project/MutableProjectDescription.java @@ -62,24 +62,26 @@ public class MutableProjectDescription implements ProjectDescription { private String baseDirectory; public MutableProjectDescription() { - super(); } - protected MutableProjectDescription(final MutableProjectDescription source) { - super(); - setPlatformVersion(source.getPlatformVersion()); - setBuildSystem(source.getBuildSystem()); - setPackaging(source.getPackaging()); - setLanguage(source.getLanguage()); - source.getRequestedDependencies().forEach(this::addDependency); - setGroupId(source.getGroupId()); - setArtifactId(source.getArtifactId()); - setVersion(source.getVersion()); - setName(source.getName()); - setDescription(source.getDescription()); - setApplicationName(source.getApplicationName()); - setPackageName(source.getPackageName()); - setBaseDirectory(source.getBaseDirectory()); + /** + * Create a new instance with the state of the specified {@code source}. + * @param source the source description to initialize this instance with + */ + protected MutableProjectDescription(MutableProjectDescription source) { + this.platformVersion = source.getPlatformVersion(); + this.buildSystem = source.getBuildSystem(); + this.packaging = source.getPackaging(); + this.language = source.getLanguage(); + this.requestedDependencies.putAll(source.getRequestedDependencies()); + this.groupId = source.getGroupId(); + this.artifactId = source.getArtifactId(); + this.version = source.getVersion(); + this.name = source.getName(); + this.description = source.getDescription(); + this.applicationName = source.getApplicationName(); + this.packageName = source.getPackageName(); + this.baseDirectory = source.getBaseDirectory(); } @Override diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectDescription.java b/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectDescription.java index 28dcc5d7..be89723e 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectDescription.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectDescription.java @@ -32,6 +32,15 @@ import io.spring.initializr.generator.version.Version; */ public interface ProjectDescription { + /** + * Create a full copy of this description so that any additional changes made on this + * instance are not reflected on the returned copy. + * @return a clone of this instance + */ + default ProjectDescription createCopy() { + throw new UnsupportedOperationException(); + } + /** * Return a immutable mapping of requested {@link Dependency dependencies}. * @return the requested dependencies @@ -110,15 +119,4 @@ public interface ProjectDescription { */ String getBaseDirectory(); - /** - * ProjectDescription implementations should implement this to create a copy of - * themselves. However, the default implementation throws - * UnsupportedOperationException. - * @return never - * @throws UnsupportedOperationException always - */ - default ProjectDescription createCopy() { - throw new UnsupportedOperationException(); - } - } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiff.java b/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectDescriptionDiff.java similarity index 66% rename from initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiff.java rename to initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectDescriptionDiff.java index 7ab832e5..712e9b28 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiff.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectDescriptionDiff.java @@ -14,42 +14,39 @@ * limitations under the License. */ -package io.spring.initializr.generator.project.diff; +package io.spring.initializr.generator.project; -import java.lang.reflect.Field; import java.util.Objects; import java.util.function.BiConsumer; import io.spring.initializr.generator.buildsystem.BuildSystem; import io.spring.initializr.generator.language.Language; import io.spring.initializr.generator.packaging.Packaging; -import io.spring.initializr.generator.project.ProjectDescription; import io.spring.initializr.generator.version.Version; -import org.springframework.util.ReflectionUtils; - /** * Provides a convenient API for determining if certain fields on a * {@link ProjectDescription} were modified. * * @author Chris Bono + * @author Stephane Nicoll */ public class ProjectDescriptionDiff { private final ProjectDescription original; /** - * Construct a {@link ProjectDescriptionDiff} that creates and uses a copy of the - * specified description as its source. + * Create a {@link ProjectDescriptionDiff} that uses a copy of the specified + * description as its source. * @param original the description to copy as the source */ - public ProjectDescriptionDiff(final ProjectDescription original) { + public ProjectDescriptionDiff(ProjectDescription original) { this.original = original.createCopy(); } /** - * Gets the copy of the originally specified description that is being tracked. - * @return copy of the originally specified description + * Return the original {@link ProjectDescription} that is being tracked. + * @return the original description */ public ProjectDescription getOriginal() { return this.original; @@ -61,8 +58,7 @@ public class ProjectDescriptionDiff { * @param current the project description to test against * @param consumer to call if the property has changed */ - public void ifPlatformVersionChanged(final ProjectDescription current, - final BiConsumer consumer) { + public void ifPlatformVersionChanged(ProjectDescription current, BiConsumer consumer) { if (!Objects.equals(this.original.getPlatformVersion(), current.getPlatformVersion())) { consumer.accept(this.original.getPlatformVersion(), current.getPlatformVersion()); } @@ -74,8 +70,7 @@ public class ProjectDescriptionDiff { * @param current the description to test against * @param consumer to call if the property has changed */ - public void ifBuildSystemChanged(final ProjectDescription current, - final BiConsumer consumer) { + public void ifBuildSystemChanged(ProjectDescription current, BiConsumer consumer) { if (!Objects.equals(this.original.getBuildSystem(), current.getBuildSystem())) { consumer.accept(this.original.getBuildSystem(), current.getBuildSystem()); } @@ -87,7 +82,7 @@ public class ProjectDescriptionDiff { * @param current the description to test against * @param consumer to call if the property has changed */ - public void ifPackagingChanged(final ProjectDescription current, final BiConsumer consumer) { + public void ifPackagingChanged(ProjectDescription current, BiConsumer consumer) { if (!Objects.equals(this.original.getPackaging(), current.getPackaging())) { consumer.accept(this.original.getPackaging(), current.getPackaging()); } @@ -99,7 +94,7 @@ public class ProjectDescriptionDiff { * @param current the description to test against * @param consumer to call if the property has changed */ - public void ifLanguageChanged(final ProjectDescription current, final BiConsumer consumer) { + public void ifLanguageChanged(ProjectDescription current, BiConsumer consumer) { if (!Objects.equals(this.original.getLanguage(), current.getLanguage())) { consumer.accept(this.original.getLanguage(), current.getLanguage()); } @@ -111,7 +106,7 @@ public class ProjectDescriptionDiff { * @param current the description to test against * @param consumer to call if the property has changed */ - public void ifGroupIdChanged(final ProjectDescription current, final BiConsumer consumer) { + public void ifGroupIdChanged(ProjectDescription current, BiConsumer consumer) { if (!Objects.equals(this.original.getGroupId(), current.getGroupId())) { consumer.accept(this.original.getGroupId(), current.getGroupId()); } @@ -123,7 +118,7 @@ public class ProjectDescriptionDiff { * @param current the description to test against * @param consumer to call if the property has changed */ - public void ifArtifactIdChanged(final ProjectDescription current, final BiConsumer consumer) { + public void ifArtifactIdChanged(ProjectDescription current, BiConsumer consumer) { if (!Objects.equals(this.original.getArtifactId(), current.getArtifactId())) { consumer.accept(this.original.getArtifactId(), current.getArtifactId()); } @@ -135,7 +130,7 @@ public class ProjectDescriptionDiff { * @param current the description to test against * @param consumer to call if the property has changed */ - public void ifVersionChanged(final ProjectDescription current, final BiConsumer consumer) { + public void ifVersionChanged(ProjectDescription current, BiConsumer consumer) { if (!Objects.equals(this.original.getVersion(), current.getVersion())) { consumer.accept(this.original.getVersion(), current.getVersion()); } @@ -147,7 +142,7 @@ public class ProjectDescriptionDiff { * @param current the description to test against * @param consumer to call if the property has changed */ - public void ifNameChanged(final ProjectDescription current, final BiConsumer consumer) { + public void ifNameChanged(ProjectDescription current, BiConsumer consumer) { if (!Objects.equals(this.original.getName(), current.getName())) { consumer.accept(this.original.getName(), current.getName()); } @@ -159,7 +154,7 @@ public class ProjectDescriptionDiff { * @param current the description to test against * @param consumer to call if the property has changed */ - public void ifDescriptionChanged(final ProjectDescription current, final BiConsumer consumer) { + public void ifDescriptionChanged(ProjectDescription current, BiConsumer consumer) { if (!Objects.equals(this.original.getDescription(), current.getDescription())) { consumer.accept(this.original.getDescription(), current.getDescription()); } @@ -171,7 +166,7 @@ public class ProjectDescriptionDiff { * @param current the description to test against * @param consumer to call if the property has changed */ - public void ifApplicationNameChanged(final ProjectDescription current, final BiConsumer consumer) { + public void ifApplicationNameChanged(ProjectDescription current, BiConsumer consumer) { if (!Objects.equals(this.original.getApplicationName(), current.getApplicationName())) { consumer.accept(this.original.getApplicationName(), current.getApplicationName()); } @@ -183,7 +178,7 @@ public class ProjectDescriptionDiff { * @param current the description to test against * @param consumer to call if the property has changed */ - public void ifPackageNameChanged(final ProjectDescription current, final BiConsumer consumer) { + public void ifPackageNameChanged(ProjectDescription current, BiConsumer consumer) { if (!Objects.equals(this.original.getPackageName(), current.getPackageName())) { consumer.accept(this.original.getPackageName(), current.getPackageName()); } @@ -195,39 +190,10 @@ public class ProjectDescriptionDiff { * @param current the description to test against * @param consumer to call if the property has changed */ - public void ifBaseDirectoryChanged(final ProjectDescription current, final BiConsumer consumer) { + public void ifBaseDirectoryChanged(ProjectDescription current, BiConsumer consumer) { if (!Objects.equals(this.original.getBaseDirectory(), current.getBaseDirectory())) { consumer.accept(this.original.getBaseDirectory(), current.getBaseDirectory()); } } - /** - * Calls the specified consumer if the value of the specified property is different on - * the original source project description than the specified project description. - * @param current the description to test against - * @param property the name of the property to check - * @param propertyClass the class of the property to check - * @param consumer to call if the property has changed - * @param type of the property - */ - public void ifPropertyChanged(final ProjectDescription current, final String property, - final Class propertyClass, final BiConsumer consumer) { - final V originalValue = getPropertyValueReflectively(this.original, property); - final V currentValue = getPropertyValueReflectively(current, property); - if (!Objects.equals(originalValue, currentValue)) { - consumer.accept(originalValue, currentValue); - } - } - - private V getPropertyValueReflectively(final ProjectDescription description, final String property) { - final Class descriptionClass = description.getClass(); - final Field field = ReflectionUtils.findField(descriptionClass, property); - if (field == null) { - throw new IllegalArgumentException( - String.format("No property named '%s' in '%s'.", property, descriptionClass.getSimpleName())); - } - ReflectionUtils.makeAccessible(field); - return (V) ReflectionUtils.getField(field, description); - } - } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiffFactory.java b/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectDescriptionDiffFactory.java similarity index 66% rename from initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiffFactory.java rename to initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectDescriptionDiffFactory.java index eda62aa9..d1fecc6f 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiffFactory.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectDescriptionDiffFactory.java @@ -14,25 +14,23 @@ * limitations under the License. */ -package io.spring.initializr.generator.project.diff; - -import io.spring.initializr.generator.project.ProjectDescription; +package io.spring.initializr.generator.project; /** - * A factory for {@link ProjectDescriptionDiff} objects. + * A factory for {@link ProjectDescriptionDiff}. * - * @param the type of {@link ProjectDescription} * @author Chris Bono */ -public interface ProjectDescriptionDiffFactory { +public interface ProjectDescriptionDiffFactory { /** - * Construct a diff for the specified {@link ProjectDescription}. - *

+ * Create a {@link ProjectDescriptionDiff} for the specified + * {@link ProjectDescription}. Any change on the specified {@code description} is + * tracked by the returned instance. * @param description the project description to use as the source of the diff * @return a diff instance using the current state of the specified description as its * source */ - ProjectDescriptionDiff create(T description); + ProjectDescriptionDiff create(ProjectDescription description); } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectGenerator.java b/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectGenerator.java index efaa8c83..c4bce087 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectGenerator.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectGenerator.java @@ -21,10 +21,6 @@ import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; -import io.spring.initializr.generator.project.diff.DefaultProjectDescriptionDiffFactory; -import io.spring.initializr.generator.project.diff.ProjectDescriptionDiff; -import io.spring.initializr.generator.project.diff.ProjectDescriptionDiffFactory; - import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.ImportSelector; @@ -123,20 +119,13 @@ public class ProjectGenerator { private Supplier resolve(ProjectDescription description, ProjectGenerationContext context) { return () -> { - if (description instanceof MutableProjectDescription) { - - final MutableProjectDescription mutableProjectDesc = (MutableProjectDescription) description; - - // Find the diff factory and use it to create and register a diff bean - final ProjectDescriptionDiffFactory diffFactory = context - .getBeanProvider(ProjectDescriptionDiffFactory.class) - .getIfAvailable(() -> new DefaultProjectDescriptionDiffFactory()); - final ProjectDescriptionDiff diff = diffFactory.create(mutableProjectDesc); - context.registerBean(ProjectDescriptionDiff.class, () -> diff); - + MutableProjectDescription mutableDescription = (MutableProjectDescription) description; + ProjectDescriptionDiffFactory diffFactory = context.getBeanProvider(ProjectDescriptionDiffFactory.class) + .getIfAvailable(DefaultProjectDescriptionDiffFactory::new); + context.registerBean(ProjectDescriptionDiff.class, () -> diffFactory.create(mutableDescription)); context.getBeanProvider(ProjectDescriptionCustomizer.class).orderedStream() - .forEach((customizer) -> customizer.customize(mutableProjectDesc)); + .forEach((customizer) -> customizer.customize(mutableDescription)); } return description; }; diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/project/ProjectDescriptionDiffTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/project/ProjectDescriptionDiffTests.java new file mode 100644 index 00000000..27537691 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/project/ProjectDescriptionDiffTests.java @@ -0,0 +1,226 @@ +/* + * Copyright 2012-2019 the original author or authors. + * + * 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 + * + * https://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.spring.initializr.generator.project; + +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +import io.spring.initializr.generator.buildsystem.BuildSystem; +import io.spring.initializr.generator.buildsystem.gradle.GradleBuildSystem; +import io.spring.initializr.generator.buildsystem.maven.MavenBuildSystem; +import io.spring.initializr.generator.language.Language; +import io.spring.initializr.generator.language.java.JavaLanguage; +import io.spring.initializr.generator.packaging.Packaging; +import io.spring.initializr.generator.packaging.jar.JarPackaging; +import io.spring.initializr.generator.version.Version; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +/** + * Tests for {@link ProjectDescriptionDiff}. + * + * @author Chris Bono + * @author Stephane Nicoll + */ +class ProjectDescriptionDiffTests { + + @Test + void projectDescriptionDiffCopySource() { + ProjectDescription original = createFullProjectDescription(); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(original); + assertThat(diff.getOriginal()).usingRecursiveComparison().isEqualTo(original); + assertThat(diff.getOriginal()).isNotSameAs(original); + } + + @Test + void projectDescriptionDiffWithUnmodifiedDescriptionDoesNotInvokeConsumer() { + ProjectDescription description = createFullProjectDescription(); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + diff.ifPlatformVersionChanged(description, (original, actual) -> fail("Values should not have changed")); + diff.ifBuildSystemChanged(description, (original, actual) -> fail("Values should not have changed")); + diff.ifPackagingChanged(description, (original, actual) -> fail("Values should not have changed")); + diff.ifLanguageChanged(description, (original, actual) -> fail("Values should not have changed")); + diff.ifGroupIdChanged(description, (original, actual) -> fail("Values should not have changed")); + diff.ifArtifactIdChanged(description, (original, actual) -> fail("Values should not have changed")); + diff.ifVersionChanged(description, (original, actual) -> fail("Values should not have changed")); + diff.ifNameChanged(description, (original, actual) -> fail("Values should not have changed")); + diff.ifDescriptionChanged(description, (original, actual) -> fail("Values should not have changed")); + diff.ifApplicationNameChanged(description, (original, actual) -> fail("Values should not have changed")); + diff.ifPackageNameChanged(description, (original, actual) -> fail("Values should not have changed")); + diff.ifBaseDirectoryChanged(description, (original, actual) -> fail("Values should not have changed")); + } + + @Test + void projectDescriptionDiffWithModifiedPlatformVersionInvokesConsumer() { + Version original = Version.parse("2.1.0.RELEASE"); + Version actual = Version.parse("2.2.0.RELEASE"); + MutableProjectDescription description = new MutableProjectDescription(); + description.setPlatformVersion(original); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + description.setPlatformVersion(actual); + validateConsumer(original, actual, (consumer) -> diff.ifPlatformVersionChanged(description, consumer)); + } + + @Test + void projectDescriptionDiffWithModifiedBuildSystemInvokesConsumer() { + BuildSystem original = BuildSystem.forId(MavenBuildSystem.ID); + BuildSystem actual = BuildSystem.forId(GradleBuildSystem.ID); + MutableProjectDescription description = new MutableProjectDescription(); + description.setBuildSystem(original); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + description.setBuildSystem(actual); + validateConsumer(original, actual, (consumer) -> diff.ifBuildSystemChanged(description, consumer)); + } + + @Test + void projectDescriptionDiffWithModifiedPackagingInvokesConsumer() { + Packaging original = Packaging.forId(JarPackaging.ID); + Packaging actual = Packaging.forId("war"); + MutableProjectDescription description = new MutableProjectDescription(); + description.setPackaging(original); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + description.setPackaging(actual); + validateConsumer(original, actual, (consumer) -> diff.ifPackagingChanged(description, consumer)); + } + + @Test + void projectDescriptionDiffWithModifiedLanguageInvokesConsumer() { + Language original = Language.forId(JavaLanguage.ID, "11"); + Language actual = Language.forId(JavaLanguage.ID, "13"); + MutableProjectDescription description = new MutableProjectDescription(); + description.setLanguage(original); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + description.setLanguage(actual); + validateConsumer(original, actual, (consumer) -> diff.ifLanguageChanged(description, consumer)); + } + + @Test + void projectDescriptionDiffWithModifiedGroupIdInvokesConsumer() { + String original = "com.example"; + String actual = "com.example.app"; + MutableProjectDescription description = new MutableProjectDescription(); + description.setGroupId(original); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + description.setGroupId(actual); + validateConsumer(original, actual, (consumer) -> diff.ifGroupIdChanged(description, consumer)); + } + + @Test + void projectDescriptionDiffWithModifiedArtifactIdInvokesConsumer() { + String original = "demo"; + String actual = "app"; + MutableProjectDescription description = new MutableProjectDescription(); + description.setArtifactId(original); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + description.setArtifactId(actual); + validateConsumer(original, actual, (consumer) -> diff.ifArtifactIdChanged(description, consumer)); + } + + @Test + void projectDescriptionDiffWithModifiedVersionInvokesConsumer() { + String original = "1.0.0"; + String actual = "1.1.0"; + MutableProjectDescription description = new MutableProjectDescription(); + description.setVersion(original); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + description.setVersion(actual); + validateConsumer(original, actual, (consumer) -> diff.ifVersionChanged(description, consumer)); + } + + @Test + void projectDescriptionDiffWithModifiedNameInvokesConsumer() { + String original = "demo"; + String actual = "application"; + MutableProjectDescription description = new MutableProjectDescription(); + description.setName(original); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + description.setName(actual); + validateConsumer(original, actual, (consumer) -> diff.ifNameChanged(description, consumer)); + } + + @Test + void projectDescriptionDiffWithModifiedDescriptionInvokesConsumer() { + String original = "Demo Application"; + String actual = "Application"; + MutableProjectDescription description = new MutableProjectDescription(); + description.setDescription(original); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + description.setDescription(actual); + validateConsumer(original, actual, (consumer) -> diff.ifDescriptionChanged(description, consumer)); + } + + @Test + void projectDescriptionDiffWithModifiedApplicationNameInvokesConsumer() { + String original = "DemoApplication"; + String actual = "Application"; + MutableProjectDescription description = new MutableProjectDescription(); + description.setApplicationName(original); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + description.setApplicationName(actual); + validateConsumer(original, actual, (consumer) -> diff.ifApplicationNameChanged(description, consumer)); + } + + @Test + void projectDescriptionDiffWithModifiedPackageNameInvokesConsumer() { + String original = "com.example"; + String actual = "com.example.app"; + MutableProjectDescription description = new MutableProjectDescription(); + description.setPackageName(original); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + description.setPackageName(actual); + validateConsumer(original, actual, (consumer) -> diff.ifPackageNameChanged(description, consumer)); + } + + @Test + void projectDescriptionDiffWithModifiedBaseDirectoryInvokesConsumer() { + String original = null; + String actual = "demo-app"; + MutableProjectDescription description = new MutableProjectDescription(); + description.setBaseDirectory(original); + ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); + description.setBaseDirectory(actual); + validateConsumer(original, actual, (consumer) -> diff.ifBaseDirectoryChanged(description, consumer)); + } + + private MutableProjectDescription createFullProjectDescription() { + MutableProjectDescription description = new MutableProjectDescription(); + description.setBuildSystem(BuildSystem.forId(MavenBuildSystem.ID)); + description.setLanguage(Language.forId(JavaLanguage.ID, "11")); + description.setPlatformVersion(Version.parse("2.2.0.RELEASE")); + description.setGroupId("com.example"); + description.setArtifactId("demo"); + description.setName("demo"); + description.setVersion("0.0.8"); + description.setApplicationName("DemoApplication"); + description.setPackageName("com.example.demo"); + description.setPackaging(Packaging.forId("jar")); + description.setBaseDirectory("."); + return description; + } + + @SuppressWarnings("unchecked") + private void validateConsumer(T original, T actual, Consumer> test) { + BiConsumer consumer = mock(BiConsumer.class); + test.accept(consumer); + verify(consumer).accept(original, actual); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/project/ProjectGeneratorTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/project/ProjectGeneratorTests.java index 4d837230..d2cec6ec 100644 --- a/initializr-generator/src/test/java/io/spring/initializr/generator/project/ProjectGeneratorTests.java +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/project/ProjectGeneratorTests.java @@ -20,9 +20,6 @@ import java.io.IOException; import java.util.Map; import java.util.function.Consumer; -import io.spring.initializr.generator.project.diff.DefaultProjectDescriptionDiffFactory; -import io.spring.initializr.generator.project.diff.ProjectDescriptionDiff; -import io.spring.initializr.generator.project.diff.ProjectDescriptionDiffFactory; import org.junit.jupiter.api.Test; import org.mockito.InOrder; @@ -35,6 +32,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; /** @@ -57,14 +55,30 @@ public class ProjectGeneratorTests { } @Test - void generateRegisterProjectDescriptionDiff() { - ProjectGenerator generator = new ProjectGenerator((context) -> context - .registerBean(ProjectDescriptionDiffFactory.class, () -> new DefaultProjectDescriptionDiffFactory())); + void generateProvideDefaultProjectDescriptionDiff() { + ProjectGenerator generator = new ProjectGenerator(mockContextInitializr()); MutableProjectDescription description = new MutableProjectDescription(); - generator.generate(description, (context) -> { + ProjectDescriptionDiff diff = generator.generate(description, (context) -> { assertThat(context.getBeansOfType(ProjectDescriptionDiff.class)).hasSize(1); return context.getBean(ProjectDescriptionDiff.class); }); + assertThat(diff).isInstanceOf(ProjectDescriptionDiff.class); + } + + @Test + void generateUseAvailableProjectDescriptionDiffFactory() { + ProjectDescriptionDiff diff = mock(ProjectDescriptionDiff.class); + ProjectDescriptionDiffFactory diffFactory = mock(ProjectDescriptionDiffFactory.class); + MutableProjectDescription description = new MutableProjectDescription(); + given(diffFactory.create(description)).willReturn(diff); + ProjectGenerator generator = new ProjectGenerator( + (context) -> context.registerBean(ProjectDescriptionDiffFactory.class, () -> diffFactory)); + ProjectDescriptionDiff actualDiff = generator.generate(description, (context) -> { + assertThat(context.getBeansOfType(ProjectDescriptionDiff.class)).hasSize(1); + return context.getBean(ProjectDescriptionDiff.class); + }); + assertThat(actualDiff).isSameAs(diff); + verify(diffFactory).create(description); } @Test diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiffTest.java b/initializr-generator/src/test/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiffTest.java deleted file mode 100644 index c611117c..00000000 --- a/initializr-generator/src/test/java/io/spring/initializr/generator/project/diff/ProjectDescriptionDiffTest.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * 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 - * - * https://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.spring.initializr.generator.project.diff; - -import java.util.function.BiConsumer; - -import io.spring.initializr.generator.buildsystem.BuildSystem; -import io.spring.initializr.generator.buildsystem.gradle.GradleBuildSystem; -import io.spring.initializr.generator.buildsystem.maven.MavenBuildSystem; -import io.spring.initializr.generator.language.Language; -import io.spring.initializr.generator.language.java.JavaLanguage; -import io.spring.initializr.generator.packaging.Packaging; -import io.spring.initializr.generator.project.MutableProjectDescription; -import io.spring.initializr.generator.project.ProjectDescription; -import io.spring.initializr.generator.version.Version; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; - -class ProjectDescriptionDiffTest { - - @Test - void originalIsCopied() { - ProjectDescription original = createProjectDescription(); - ProjectDescriptionDiff diff = new ProjectDescriptionDiff(original); - assertThat(diff.getOriginal()).usingRecursiveComparison().isEqualTo(original); - assertThat(diff.getOriginal()).isNotSameAs(original); - } - - @Test - void noChanges() { - MutableProjectDescription description = createProjectDescription(); - ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); - BiConsumer failIfCalled = (v1, v2) -> fail("Values should not have changed"); - diff.ifPlatformVersionChanged(description, failIfCalled); - diff.ifBuildSystemChanged(description, failIfCalled); - diff.ifPackagingChanged(description, failIfCalled); - diff.ifLanguageChanged(description, failIfCalled); - diff.ifGroupIdChanged(description, failIfCalled); - diff.ifArtifactIdChanged(description, failIfCalled); - diff.ifVersionChanged(description, failIfCalled); - diff.ifNameChanged(description, failIfCalled); - diff.ifDescriptionChanged(description, failIfCalled); - diff.ifApplicationNameChanged(description, failIfCalled); - diff.ifPackageNameChanged(description, failIfCalled); - diff.ifBaseDirectoryChanged(description, failIfCalled); - diff.ifPropertyChanged(description, "name", String.class, failIfCalled); - } - - @Test - void platformVersionChanged() { - MutableProjectDescription description = createProjectDescription(); - ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); - Version original = description.getPlatformVersion(); - description.setPlatformVersion(Version.parse("2.0.0.RELEASE")); - CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { - assertThat(prev).isEqualTo(original); - assertThat(curr).isEqualTo(description.getPlatformVersion()); - }); - diff.ifPlatformVersionChanged(description, changeHandler); - diff.ifPropertyChanged(description, "platformVersion", Version.class, changeHandler); - assertThat(changeHandler.timesCalled()).isEqualTo(2); - } - - @Test - void buildSystemChanged() { - MutableProjectDescription description = createProjectDescription(); - ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); - BuildSystem original = description.getBuildSystem(); - description.setBuildSystem(BuildSystem.forId(GradleBuildSystem.ID)); - CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { - assertThat(prev).isEqualTo(original); - assertThat(curr).isEqualTo(description.getBuildSystem()); - }); - diff.ifBuildSystemChanged(description, changeHandler); - diff.ifPropertyChanged(description, "buildSystem", BuildSystem.class, changeHandler); - assertThat(changeHandler.timesCalled()).isEqualTo(2); - } - - @Test - void packagingChanged() { - MutableProjectDescription description = createProjectDescription(); - ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); - Packaging original = description.getPackaging(); - description.setPackaging(Packaging.forId("war")); - CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { - assertThat(prev).isEqualTo(original); - assertThat(curr).isEqualTo(description.getPackaging()); - }); - diff.ifPackagingChanged(description, changeHandler); - diff.ifPropertyChanged(description, "packaging", Packaging.class, changeHandler); - assertThat(changeHandler.timesCalled()).isEqualTo(2); - } - - @Test - void languageChanged() { - MutableProjectDescription description = createProjectDescription(); - ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); - Language original = description.getLanguage(); - description.setLanguage(Language.forId(JavaLanguage.ID, "13")); - CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { - assertThat(prev).isEqualTo(original); - assertThat(curr).isEqualTo(description.getLanguage()); - }); - diff.ifLanguageChanged(description, changeHandler); - diff.ifPropertyChanged(description, "language", String.class, changeHandler); - assertThat(changeHandler.timesCalled()).isEqualTo(2); - } - - @Test - void groupIdChanged() { - MutableProjectDescription description = createProjectDescription(); - ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); - String original = description.getGroupId(); - description.setGroupId("group5150"); - CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { - assertThat(prev).isEqualTo(original); - assertThat(curr).isEqualTo(description.getGroupId()); - }); - diff.ifGroupIdChanged(description, changeHandler); - diff.ifPropertyChanged(description, "groupId", String.class, changeHandler); - assertThat(changeHandler.timesCalled()).isEqualTo(2); - } - - @Test - void artifactIdChanged() { - MutableProjectDescription description = createProjectDescription(); - ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); - String original = description.getArtifactId(); - description.setArtifactId("artifact5150"); - CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { - assertThat(prev).isEqualTo(original); - assertThat(curr).isEqualTo(description.getArtifactId()); - }); - diff.ifArtifactIdChanged(description, changeHandler); - diff.ifPropertyChanged(description, "artifactId", String.class, changeHandler); - assertThat(changeHandler.timesCalled()).isEqualTo(2); - } - - @Test - void versionChanged() { - MutableProjectDescription description = createProjectDescription(); - ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); - String original = description.getVersion(); - description.setVersion("version5150"); - CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { - assertThat(prev).isEqualTo(original); - assertThat(curr).isEqualTo(description.getVersion()); - }); - diff.ifVersionChanged(description, changeHandler); - diff.ifPropertyChanged(description, "version", String.class, changeHandler); - assertThat(changeHandler.timesCalled()).isEqualTo(2); - } - - @Test - void nameChanged() { - MutableProjectDescription description = createProjectDescription(); - ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); - String original = description.getName(); - description.setName("name5150"); - CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { - assertThat(prev).isEqualTo(original); - assertThat(curr).isEqualTo(description.getName()); - }); - diff.ifNameChanged(description, changeHandler); - diff.ifPropertyChanged(description, "name", String.class, changeHandler); - assertThat(changeHandler.timesCalled()).isEqualTo(2); - } - - @Test - void descriptionChanged() { - MutableProjectDescription description = createProjectDescription(); - ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); - String original = description.getDescription(); - description.setDescription("desc5150"); - CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { - assertThat(prev).isEqualTo(original); - assertThat(curr).isEqualTo(description.getDescription()); - }); - diff.ifDescriptionChanged(description, changeHandler); - diff.ifPropertyChanged(description, "description", String.class, changeHandler); - assertThat(changeHandler.timesCalled()).isEqualTo(2); - } - - @Test - void applicationNameChanged() { - MutableProjectDescription description = createProjectDescription(); - ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); - String original = description.getApplicationName(); - description.setApplicationName("appname5150"); - CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { - assertThat(prev).isEqualTo(original); - assertThat(curr).isEqualTo(description.getApplicationName()); - }); - diff.ifApplicationNameChanged(description, changeHandler); - diff.ifPropertyChanged(description, "applicationName", String.class, changeHandler); - assertThat(changeHandler.timesCalled()).isEqualTo(2); - } - - @Test - void packageNameChanged() { - MutableProjectDescription description = createProjectDescription(); - ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); - String original = description.getPackageName(); - description.setPackageName("pkg5150"); - CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { - assertThat(prev).isEqualTo(original); - assertThat(curr).isEqualTo(description.getPackageName()); - }); - diff.ifPackageNameChanged(description, changeHandler); - diff.ifPropertyChanged(description, "packageName", String.class, changeHandler); - assertThat(changeHandler.timesCalled()).isEqualTo(2); - } - - @Test - void baseDirectoryChanged() { - MutableProjectDescription description = createProjectDescription(); - ProjectDescriptionDiff diff = new ProjectDescriptionDiff(description); - String original = description.getBaseDirectory(); - description.setBaseDirectory("baseDir5150"); - CallTrackingBiConsumer changeHandler = new CallTrackingBiConsumer<>((prev, curr) -> { - assertThat(prev).isEqualTo(original); - assertThat(curr).isEqualTo(description.getBaseDirectory()); - }); - diff.ifBaseDirectoryChanged(description, changeHandler); - diff.ifPropertyChanged(description, "baseDirectory", String.class, changeHandler); - assertThat(changeHandler.timesCalled()).isEqualTo(2); - } - - private MutableProjectDescription createProjectDescription() { - MutableProjectDescription description = new MutableProjectDescription(); - description.setBuildSystem(BuildSystem.forId(MavenBuildSystem.ID)); - description.setLanguage(Language.forId(JavaLanguage.ID, "11")); - description.setPlatformVersion(Version.parse("2.2.0.RELEASE")); - description.setGroupId("com.example"); - description.setArtifactId("demo"); - description.setName("demo"); - description.setVersion("0.0.8"); - description.setApplicationName("DemoApplication"); - description.setPackageName("com.example.demo"); - description.setPackaging(Packaging.forId("jar")); - description.setBaseDirectory("."); - return description; - } - - static class CallTrackingBiConsumer implements BiConsumer { - - private final BiConsumer delegate; - - private int callCount; - - CallTrackingBiConsumer(BiConsumer delegate) { - this.delegate = delegate; - } - - @Override - public void accept(T t, U u) { - this.callCount++; - this.delegate.accept(t, u); - } - - int timesCalled() { - return this.callCount; - } - - } - -} diff --git a/initializr-web/src/main/java/io/spring/initializr/web/autoconfigure/InitializrAutoConfiguration.java b/initializr-web/src/main/java/io/spring/initializr/web/autoconfigure/InitializrAutoConfiguration.java index a08dcf4c..079a6169 100644 --- a/initializr-web/src/main/java/io/spring/initializr/web/autoconfigure/InitializrAutoConfiguration.java +++ b/initializr-web/src/main/java/io/spring/initializr/web/autoconfigure/InitializrAutoConfiguration.java @@ -28,8 +28,6 @@ import io.spring.initializr.generator.io.SimpleIndentStrategy; import io.spring.initializr.generator.io.template.MustacheTemplateRenderer; import io.spring.initializr.generator.io.template.TemplateRenderer; import io.spring.initializr.generator.project.ProjectDirectoryFactory; -import io.spring.initializr.generator.project.diff.DefaultProjectDescriptionDiffFactory; -import io.spring.initializr.generator.project.diff.ProjectDescriptionDiffFactory; import io.spring.initializr.metadata.DependencyMetadataProvider; import io.spring.initializr.metadata.InitializrMetadata; import io.spring.initializr.metadata.InitializrMetadataBuilder; @@ -131,12 +129,6 @@ public class InitializrAutoConfiguration { return new DefaultDependencyMetadataProvider(); } - @Bean - @ConditionalOnMissingBean - ProjectDescriptionDiffFactory projectDescriptionDiffFactory() { - return new DefaultProjectDescriptionDiffFactory(); - } - /** * Initializr web configuration. */ diff --git a/initializr-web/src/test/java/io/spring/initializr/web/autoconfigure/InitializrAutoConfigurationTests.java b/initializr-web/src/test/java/io/spring/initializr/web/autoconfigure/InitializrAutoConfigurationTests.java index 3f39972f..c5a36e81 100755 --- a/initializr-web/src/test/java/io/spring/initializr/web/autoconfigure/InitializrAutoConfigurationTests.java +++ b/initializr-web/src/test/java/io/spring/initializr/web/autoconfigure/InitializrAutoConfigurationTests.java @@ -17,7 +17,6 @@ package io.spring.initializr.web.autoconfigure; import io.spring.initializr.generator.io.template.TemplateRenderer; -import io.spring.initializr.generator.project.diff.ProjectDescriptionDiffFactory; import io.spring.initializr.metadata.DependencyMetadataProvider; import io.spring.initializr.metadata.InitializrMetadataProvider; import io.spring.initializr.web.controller.CommandLineMetadataController; @@ -64,11 +63,6 @@ class InitializrAutoConfigurationTests { this.contextRunner.run((context) -> assertThat(context).hasSingleBean(TemplateRenderer.class)); } - @Test - void autoConfigRegistersDiffFactory() { - this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ProjectDescriptionDiffFactory.class)); - } - @Test void autoConfigWhenTemplateRendererBeanPresentDoesNotRegisterTemplateRenderer() { this.contextRunner.withUserConfiguration(CustomTemplateRendererConfiguration.class).run((context) -> { diff --git a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectContributor.java b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectContributor.java index 5e3cca91..cc135c95 100644 --- a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectContributor.java +++ b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectContributor.java @@ -44,7 +44,6 @@ class CustomProjectContributor implements ProjectContributor { && ((CustomProjectDescription) this.description).isCustomFlag()) { Files.createFile(projectRoot.resolve("custom.txt")); } - } } diff --git a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescription.java b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescription.java index c4cb8eef..668078f9 100644 --- a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescription.java +++ b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescription.java @@ -29,12 +29,11 @@ class CustomProjectDescription extends MutableProjectDescription { private boolean customFlag; CustomProjectDescription() { - super(); } - CustomProjectDescription(final CustomProjectDescription source) { + CustomProjectDescription(CustomProjectDescription source) { super(source); - setCustomFlag(source.isCustomFlag()); + this.customFlag = source.isCustomFlag(); } @Override diff --git a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiff.java b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiff.java index 16742bde..556d485c 100644 --- a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiff.java +++ b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiff.java @@ -16,32 +16,36 @@ package io.spring.initializr.web.controller.custom; +import java.util.Objects; import java.util.function.BiConsumer; -import io.spring.initializr.generator.project.diff.ProjectDescriptionDiff; +import io.spring.initializr.generator.project.ProjectDescriptionDiff; /** * Extends the base {@link ProjectDescriptionDiff} to provide convenient diff methods on * {@link CustomProjectDescription}. * - * @author cbono + * @author Chris Bono + * @author Stephane Nicoll */ class CustomProjectDescriptionDiff extends ProjectDescriptionDiff { - CustomProjectDescriptionDiff(final CustomProjectDescription original) { + private final CustomProjectDescription original; + + CustomProjectDescriptionDiff(CustomProjectDescription original) { super(original); + this.original = original; } /** - * Optionally calls the specified consumer if the {@code customFlag} is different on - * the original source description and the specified current description. - * @param current the description to test against + * Calls the specified consumer if the {@code customFlag} is different on the original + * source project description than the specified project description. + * @param current the project description to test against * @param consumer to call if the property has changed */ - void ifCUstomFlagChanged(final CustomProjectDescription current, final BiConsumer consumer) { - final CustomProjectDescription original = (CustomProjectDescription) super.getOriginal(); - if (original.isCustomFlag() != current.isCustomFlag()) { - consumer.accept(original.isCustomFlag(), current.isCustomFlag()); + void ifCustomFlagChanged(CustomProjectDescription current, BiConsumer consumer) { + if (!Objects.equals(this.original.isCustomFlag(), current.isCustomFlag())) { + consumer.accept(this.original.isCustomFlag(), current.isCustomFlag()); } } diff --git a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiffFactory.java b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiffFactory.java deleted file mode 100644 index bd56bdd6..00000000 --- a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiffFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * 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 - * - * https://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.spring.initializr.web.controller.custom; - -import io.spring.initializr.generator.project.diff.ProjectDescriptionDiff; -import io.spring.initializr.generator.project.diff.ProjectDescriptionDiffFactory; - -/** - * A custom {@link ProjectDescriptionDiffFactory} implementation that creates custom - * {@link CustomProjectDescriptionDiff} instances. - * - * @author cbono - */ -public class CustomProjectDescriptionDiffFactory implements ProjectDescriptionDiffFactory { - - @Override - public ProjectDescriptionDiff create(final CustomProjectDescription description) { - return new CustomProjectDescriptionDiff(description); - } - -} diff --git a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiffTest.java b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiffTest.java deleted file mode 100644 index 0085fa67..00000000 --- a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/CustomProjectDescriptionDiffTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * 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 - * - * https://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.spring.initializr.web.controller.custom; - -import io.spring.initializr.generator.buildsystem.BuildSystem; -import io.spring.initializr.generator.buildsystem.maven.MavenBuildSystem; -import io.spring.initializr.generator.language.Language; -import io.spring.initializr.generator.language.java.JavaLanguage; -import io.spring.initializr.generator.packaging.Packaging; -import io.spring.initializr.generator.version.Version; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; - -/** - * Simple sanity test around the custom diff extension model. - */ -class CustomProjectDescriptionDiffTest { - - @Test - void sanityCheck() { - - CustomProjectDescription description = customProjectDescription(); - CustomProjectDescriptionDiffFactory diffFactory = new CustomProjectDescriptionDiffFactory(); - CustomProjectDescriptionDiff diff = (CustomProjectDescriptionDiff) diffFactory.create(description); - - // copied - assertThat(diff.getOriginal()).usingRecursiveComparison().isEqualTo(description); - assertThat(diff.getOriginal()).isNotSameAs(description); - - // no changes - diff.ifCUstomFlagChanged(description, (v1, v2) -> fail("Values should not have changed")); - - // changes - boolean originalValue = description.isCustomFlag(); - description.setCustomFlag(!originalValue); - - // TODO could use the CallTrackingBiConsumer that I used in initializr-generator - // tests but then where to put it? - final boolean[] called = { false }; - diff.ifCUstomFlagChanged(description, (prev, curr) -> { - assertThat(prev).isEqualTo(originalValue); - assertThat(curr).isEqualTo(description.isCustomFlag()); - called[0] = true; - }); - assertThat(called[0]).isTrue(); - } - - private CustomProjectDescription customProjectDescription() { - CustomProjectDescription description = new CustomProjectDescription(); - description.setBuildSystem(BuildSystem.forId(MavenBuildSystem.ID)); - description.setLanguage(Language.forId(JavaLanguage.ID, "11")); - description.setPlatformVersion(Version.parse("2.2.0.RELEASE")); - description.setGroupId("com.example"); - description.setArtifactId("demo"); - description.setName("demo"); - description.setVersion("0.0.8"); - description.setApplicationName("DemoApplication"); - description.setPackageName("com.example.demo"); - description.setPackaging(Packaging.forId("jar")); - description.setBaseDirectory("."); - description.setCustomFlag(true); - return description; - } - -} diff --git a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/ProjectGenerationControllerCustomRequestIntegrationTests.java b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/ProjectGenerationControllerCustomRequestIntegrationTests.java index 9144d89e..1ea03f50 100644 --- a/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/ProjectGenerationControllerCustomRequestIntegrationTests.java +++ b/initializr-web/src/test/java/io/spring/initializr/web/controller/custom/ProjectGenerationControllerCustomRequestIntegrationTests.java @@ -16,7 +16,10 @@ package io.spring.initializr.web.controller.custom; +import io.spring.initializr.generator.project.MutableProjectDescription; import io.spring.initializr.generator.project.ProjectDescription; +import io.spring.initializr.generator.project.ProjectDescriptionCustomizer; +import io.spring.initializr.generator.project.ProjectDescriptionDiffFactory; import io.spring.initializr.generator.test.project.ProjectStructure; import io.spring.initializr.metadata.InitializrMetadata; import io.spring.initializr.metadata.InitializrMetadataProvider; @@ -33,6 +36,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.test.context.ActiveProfiles; +import org.springframework.util.Assert; import static org.assertj.core.api.Assertions.assertThat; @@ -44,8 +48,7 @@ import static org.assertj.core.api.Assertions.assertThat; */ @ActiveProfiles("test-default") @Import(CustomProjectGenerationConfiguration.class) -public class ProjectGenerationControllerCustomRequestIntegrationTests - extends AbstractInitializrControllerIntegrationTests { +class ProjectGenerationControllerCustomRequestIntegrationTests extends AbstractInitializrControllerIntegrationTests { @Test void createProjectWithCustomFlagEnabled() { @@ -79,6 +82,11 @@ public class ProjectGenerationControllerCustomRequestIntegrationTests return new CustomProjectGenerationController(metadataProvider, projectGenerationInvoker); } + @Bean + CustomProjectDescriptionCustomizer customProjectDescriptionCustomizer() { + return new CustomProjectDescriptionCustomizer(); + } + @Bean CustomProjectDescriptionDiffFactory customProjectDescriptionDiffFactory() { return new CustomProjectDescriptionDiffFactory(); @@ -96,10 +104,28 @@ public class ProjectGenerationControllerCustomRequestIntegrationTests description.setCustomFlag(request.isCustomFlag()); // Override attributes for test purposes description.setPackageName("org.example.custom"); - description.setApplicationName("CustomApp"); return description; } } + static class CustomProjectDescriptionCustomizer implements ProjectDescriptionCustomizer { + + @Override + public void customize(MutableProjectDescription description) { + description.setApplicationName("CustomApp"); + } + + } + + static class CustomProjectDescriptionDiffFactory implements ProjectDescriptionDiffFactory { + + @Override + public CustomProjectDescriptionDiff create(ProjectDescription description) { + Assert.isInstanceOf(CustomProjectDescription.class, description); + return new CustomProjectDescriptionDiff((CustomProjectDescription) description); + } + + } + }