From 1dbed8cdf8be97e8f22bb2cdcf7c7dc296f87105 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 7 Feb 2019 15:17:18 +0100 Subject: [PATCH] Add build abstraction This commit adds a build abstraction with a base model that concrete build systems can reuse. See gh-814 Co-authored-by: Stephane Nicoll --- .../buildsystem/BillOfMaterials.java | 64 +++++++++ .../generator/buildsystem/BomContainer.java | 62 ++++++++ .../generator/buildsystem/Build.java | 132 ++++++++++++++++++ .../buildsystem/BuildItemContainer.java | 114 +++++++++++++++ .../buildsystem/BuildItemResolver.java | 47 +++++++ .../generator/buildsystem/BuildSystem.java | 57 ++++++++ .../buildsystem/BuildSystemFactory.java | 34 +++++ .../generator/buildsystem/Dependency.java | 102 ++++++++++++++ .../buildsystem/DependencyComparator.java | 56 ++++++++ .../buildsystem/DependencyContainer.java | 75 ++++++++++ .../buildsystem/DependencyScope.java | 61 ++++++++ .../buildsystem/MavenRepository.java | 67 +++++++++ .../buildsystem/MavenRepositoryContainer.java | 64 +++++++++ .../buildsystem/SimpleBuildItemResolver.java | 57 ++++++++ .../generator/buildsystem/package-info.java | 20 +++ .../generator/version/VersionReference.java | 98 +++++++++++++ .../buildsystem/BomContainerTests.java | 70 ++++++++++ .../buildsystem/BuildItemContainerTests.java | 115 +++++++++++++++ .../buildsystem/BuildSystemTests.java | 36 +++++ .../generator/buildsystem/BuildTests.java | 88 ++++++++++++ .../DependencyComparatorTests.java | 69 +++++++++ .../buildsystem/DependencyContainerTests.java | 69 +++++++++ .../MavenRepositoryContainerTests.java | 82 +++++++++++ .../version/VersionReferenceTests.java | 89 ++++++++++++ 24 files changed, 1728 insertions(+) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BillOfMaterials.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BomContainer.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/Build.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BuildItemContainer.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BuildItemResolver.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BuildSystem.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BuildSystemFactory.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/Dependency.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/DependencyComparator.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/DependencyContainer.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/DependencyScope.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/MavenRepository.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/MavenRepositoryContainer.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/SimpleBuildItemResolver.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/package-info.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/version/VersionReference.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/BomContainerTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/BuildItemContainerTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/BuildSystemTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/BuildTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/DependencyComparatorTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/DependencyContainerTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/MavenRepositoryContainerTests.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/version/VersionReferenceTests.java diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BillOfMaterials.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BillOfMaterials.java new file mode 100644 index 00000000..d9dbeb32 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BillOfMaterials.java @@ -0,0 +1,64 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +import io.spring.initializr.generator.version.VersionReference; + +/** + * A Bill of Materials (BOM) definition to be declared in a project's build configuration. + * + * @author Stephane Nicoll + */ +public class BillOfMaterials { + + private final String groupId; + + private final String artifactId; + + private final VersionReference version; + + private final int order; + + public BillOfMaterials(String groupId, String artifactId, VersionReference version) { + this(groupId, artifactId, version, Integer.MAX_VALUE); + } + + public BillOfMaterials(String groupId, String artifactId, VersionReference version, + int order) { + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + this.order = order; + } + + public String getGroupId() { + return this.groupId; + } + + public String getArtifactId() { + return this.artifactId; + } + + public VersionReference getVersion() { + return this.version; + } + + public int getOrder() { + return this.order; + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BomContainer.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BomContainer.java new file mode 100644 index 00000000..bafdad17 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BomContainer.java @@ -0,0 +1,62 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +import java.util.LinkedHashMap; +import java.util.function.Function; + +import io.spring.initializr.generator.version.VersionReference; + +/** + * A {@link BuildItemContainer} implementation for boms. + * + * @author Stephane Nicoll + */ +public class BomContainer extends BuildItemContainer { + + BomContainer(Function itemResolver) { + super(new LinkedHashMap<>(), itemResolver); + } + + /** + * Register a {@link BillOfMaterials} with the specified {@code id} and a + * {@link Integer#MAX_VALUE} order. + * @param id the id of the bom + * @param groupId the groupId + * @param artifactId the artifactId + * @param version the {@link VersionReference} + */ + public void add(String id, String groupId, String artifactId, + VersionReference version) { + add(id, new BillOfMaterials(groupId, artifactId, version)); + } + + /** + * Register a {@link BillOfMaterials} with the specified {@code id} and a custom + * order. + * @param id the id of the bom + * @param groupId the groupId + * @param artifactId the artifactId + * @param version the {@link VersionReference} + * @param order the order of the bom + */ + public void add(String id, String groupId, String artifactId, + VersionReference version, int order) { + add(id, new BillOfMaterials(groupId, artifactId, version, order)); + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/Build.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/Build.java new file mode 100644 index 00000000..fbc0c591 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/Build.java @@ -0,0 +1,132 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; + +import io.spring.initializr.generator.version.VersionProperty; + +/** + * Build configuration for a project. + * + * @author Andy Wilkinson + * @author Stephane Nicoll + */ +public abstract class Build { + + private String group; + + private String artifact; + + private String version = "0.0.1-SNAPSHOT"; + + private final Map versionProperties = new TreeMap<>(); + + private final DependencyContainer dependencies; + + private final BomContainer boms; + + private final MavenRepositoryContainer repositories; + + private final MavenRepositoryContainer pluginRepositories; + + protected Build(BuildItemResolver buildItemResolver) { + BuildItemResolver resolver = determineBuildItemResolver(buildItemResolver); + this.dependencies = new DependencyContainer(resolver::resolveDependency); + this.boms = new BomContainer(resolver::resolveBom); + this.repositories = new MavenRepositoryContainer(resolver::resolveRepository); + this.pluginRepositories = new MavenRepositoryContainer( + resolver::resolveRepository); + } + + private static BuildItemResolver determineBuildItemResolver( + BuildItemResolver buildItemResolver) { + if (buildItemResolver != null) { + return buildItemResolver; + } + return new SimpleBuildItemResolver((id) -> null, (id) -> null, + (id) -> id.equals("maven-central") ? MavenRepository.MAVEN_CENTRAL + : null); + } + + /** + * Return the identifier of the group for the project. + * @return the groupId + */ + public String getGroup() { + return this.group; + } + + public void setGroup(String group) { + this.group = group; + } + + /** + * Return the identifier of the project. + * @return the artifactId + */ + public String getArtifact() { + return this.artifact; + } + + public void setArtifact(String artifact) { + this.artifact = artifact; + } + + public String getVersion() { + return this.version; + } + + public void setVersion(String version) { + this.version = version; + } + + public void addVersionProperty(VersionProperty versionProperty, String version) { + this.versionProperties.put(versionProperty, version); + } + + public void addExternalVersionProperty(String propertyName, String version) { + addVersionProperty(VersionProperty.of(propertyName, false), version); + } + + public void addInternalVersionProperty(String propertyName, String version) { + addVersionProperty(VersionProperty.of(propertyName, true), version); + } + + public Map getVersionProperties() { + return Collections.unmodifiableMap(this.versionProperties); + } + + public DependencyContainer dependencies() { + return this.dependencies; + } + + public BomContainer boms() { + return this.boms; + } + + public MavenRepositoryContainer repositories() { + return this.repositories; + } + + public MavenRepositoryContainer pluginRepositories() { + return this.pluginRepositories; + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BuildItemContainer.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BuildItemContainer.java new file mode 100644 index 00000000..af584dad --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BuildItemContainer.java @@ -0,0 +1,114 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Stream; + +/** + * A container for items. + * + * @param the type of the identifier + * @param the type of the item + * @author Stephane Nicoll + */ +public class BuildItemContainer { + + private final Map items; + + private final Function itemResolver; + + protected BuildItemContainer(Map items, Function itemResolver) { + this.items = items; + this.itemResolver = itemResolver; + } + + /** + * Specify if this container is empty. + * @return {@code true} if no item is registered + */ + public boolean isEmpty() { + return this.items.isEmpty(); + } + + /** + * Specify if this container has an item with the specified id. + * @param id the id of an item + * @return {@code true} if an item with the specified {@code id} is registered + */ + public boolean has(I id) { + return this.items.containsKey(id); + } + + /** + * Return a {@link Stream} of registered identifiers. + * @return a stream of ids + */ + public Stream ids() { + return this.items.keySet().stream(); + } + + /** + * Return a {@link Stream} of registered items. + * @return a stream of items + */ + public Stream items() { + return this.items.values().stream(); + } + + /** + * Return the item with the specified {@code id} or {@code null} if no such item + * exists. + * @param id the id of an item + * @return the item or {@code null} + */ + public V get(I id) { + return this.items.get(id); + } + + /** + * Lookup the item with the specified {@code id} and register it to this container. + * @param id the id of an item + */ + public void add(I id) { + V item = this.itemResolver.apply(id); + if (item == null) { + throw new IllegalArgumentException("No such value with id '" + id + "'"); + } + add(id, item); + } + + /** + * Register the specified {@code item} with the specified {@code id}. + * @param id the id of the item + * @param item the item to register + */ + public void add(I id, V item) { + this.items.put(id, item); + } + + /** + * Remove the item with the specified {@code id}. + * @param id the id of the item to remove + * @return {@code true} if such an item was registered, {@code false} otherwise + */ + public boolean remove(I id) { + return this.items.remove(id) != null; + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BuildItemResolver.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BuildItemResolver.java new file mode 100644 index 00000000..6550a29d --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BuildItemResolver.java @@ -0,0 +1,47 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +/** + * Resolve an item of the {@link Build} against an identifer. + * + * @author Stephane Nicoll + */ +public interface BuildItemResolver { + + /** + * Resolve the {@link Dependency} with the specified {@code id}. + * @param id the id of the dependency + * @return the matching {@link Dependency} or {@code null} if none is found + */ + Dependency resolveDependency(String id); + + /** + * Resolve the {@link BillOfMaterials} with the specified {@code id}. + * @param id the id of the bom + * @return the matching {@link BillOfMaterials} or {@code null} if none is found + */ + BillOfMaterials resolveBom(String id); + + /** + * Resolve the {@link MavenRepository repository} with the specified {@code id}. + * @param id the id of the bom + * @return the matching {@link MavenRepository} or {@code null} if none is found + */ + MavenRepository resolveRepository(String id); + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BuildSystem.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BuildSystem.java new file mode 100644 index 00000000..c243443b --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BuildSystem.java @@ -0,0 +1,57 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +import java.nio.file.Path; +import java.util.Objects; + +import io.spring.initializr.generator.language.Language; + +import org.springframework.core.io.support.SpringFactoriesLoader; + +/** + * A build system that can be used by a generated project. + * + * @author Andy Wilkinson + */ +public interface BuildSystem { + + /** + * The id of the build system. + * @return the id + */ + String id(); + + default Path getMainDirectory(Path projectRoot, Language language) { + return projectRoot.resolve("src/main/" + language.id()); + } + + default Path getTestDirectory(Path projectRoot, Language language) { + return projectRoot.resolve("src/test/" + language.id()); + } + + static BuildSystem forId(String id) { + return SpringFactoriesLoader + .loadFactories(BuildSystemFactory.class, + BuildSystem.class.getClassLoader()) + .stream().map((factory) -> factory.createBuildSystem(id)) + .filter(Objects::nonNull).findFirst() + .orElseThrow(() -> new IllegalStateException( + "Unrecognized build system id '" + id + "'")); + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BuildSystemFactory.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BuildSystemFactory.java new file mode 100644 index 00000000..cbdb19dd --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/BuildSystemFactory.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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +/** + * A factory for creating a {@link BuildSystem}. + * + * @author Andy Wilkinson + */ +public interface BuildSystemFactory { + + /** + * Creates and returns a {@link BuildSystem} for the given id. If the factory does not + * recognise the given {@code id}, {@code null} should be returned. + * @param id the id of the build system + * @return the build system or {@code null} + */ + BuildSystem createBuildSystem(String id); + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/Dependency.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/Dependency.java new file mode 100644 index 00000000..35208331 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/Dependency.java @@ -0,0 +1,102 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +import io.spring.initializr.generator.version.VersionReference; + +/** + * A dependency to be declared in a project's build configuration. + * + * @author Andy Wilkinson + */ +public class Dependency { + + private final String groupId; + + private final String artifactId; + + private final VersionReference version; + + private final DependencyScope scope; + + private final String type; + + public Dependency(String groupId, String artifactId) { + this(groupId, artifactId, DependencyScope.COMPILE); + } + + public Dependency(String groupId, String artifactId, DependencyScope scope) { + this(groupId, artifactId, null, scope); + } + + public Dependency(String groupId, String artifactId, VersionReference version, + DependencyScope scope) { + this(groupId, artifactId, version, scope, null); + } + + public Dependency(String groupId, String artifactId, VersionReference version, + DependencyScope scope, String type) { + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + this.scope = scope; + this.type = type; + } + + /** + * The group ID of the dependency. + * @return the group ID + */ + public String getGroupId() { + return this.groupId; + } + + /** + * The artifact ID of the dependency. + * @return the artifact ID + */ + public String getArtifactId() { + return this.artifactId; + } + + /** + * The {@link VersionReference} of the dependency. May be {@code null} for a + * dependency whose version is expected to be provided by dependency management. + * @return the version reference or {@code null} + */ + public VersionReference getVersion() { + return this.version; + } + + /** + * The {@link DependencyScope scope} of the dependency. + * @return the scope + */ + public DependencyScope getScope() { + return this.scope; + } + + /** + * The type of the dependency. Can be {@code null} to indicate that the default type + * should be used (i.e. {@code jar}). + * @return the type or {@code null} + */ + public String getType() { + return this.type; + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/DependencyComparator.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/DependencyComparator.java new file mode 100644 index 00000000..3fb36f78 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/DependencyComparator.java @@ -0,0 +1,56 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +import java.util.Comparator; + +/** + * A {@link Comparator} that orders {@link Dependency dependencies} in a suitable form for + * being referenced in the build. + * + * @author Stephane Nicoll + */ +public class DependencyComparator implements Comparator { + + /** + * A default stateless instance. + */ + public static final DependencyComparator INSTANCE = new DependencyComparator(); + + @Override + public int compare(Dependency o1, Dependency o2) { + if (isSpringBootDependency(o1) && isSpringBootDependency(o2)) { + return o1.getArtifactId().compareTo(o2.getArtifactId()); + } + if (isSpringBootDependency(o1)) { + return -1; + } + if (isSpringBootDependency(o2)) { + return 1; + } + int group = o1.getGroupId().compareTo(o2.getGroupId()); + if (group != 0) { + return group; + } + return o1.getArtifactId().compareTo(o2.getArtifactId()); + } + + private boolean isSpringBootDependency(Dependency dependency) { + return dependency.getGroupId().startsWith("org.springframework.boot"); + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/DependencyContainer.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/DependencyContainer.java new file mode 100644 index 00000000..542dad28 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/DependencyContainer.java @@ -0,0 +1,75 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +import java.util.LinkedHashMap; +import java.util.function.Function; + +import io.spring.initializr.generator.version.VersionReference; + +/** + * A {@link BuildItemContainer} implementation for dependencies. + * + * @author Stephane Nicoll + */ +public class DependencyContainer extends BuildItemContainer { + + DependencyContainer(Function itemResolver) { + super(new LinkedHashMap<>(), itemResolver); + } + + /** + * Register a {@link Dependency} with the specified {@code id} and a managed version. + * @param id the id of the dependency + * @param groupId the groupId + * @param artifactId the artifactId + * @param scope the {@link DependencyScope} + */ + public void add(String id, String groupId, String artifactId, DependencyScope scope) { + add(id, new Dependency(groupId, artifactId, scope)); + } + + /** + * Register a {@link Dependency} with the specified {@code id}, version and + * {@link DependencyScope scope}. + * @param id the id of the dependency + * @param groupId the groupId + * @param artifactId the artifactId + * @param version the {@link VersionReference} + * @param scope the {@link DependencyScope} + */ + public void add(String id, String groupId, String artifactId, + VersionReference version, DependencyScope scope) { + add(id, new Dependency(groupId, artifactId, version, scope)); + } + + /** + * Register a {@link Dependency} with the specified {@code id}, version, + * {@link DependencyScope scope} and type. + * @param id the id of the dependency + * @param groupId the groupId + * @param artifactId the artifactId + * @param version the {@link VersionReference} + * @param scope the {@link DependencyScope} + * @param type the artifact type + */ + public void add(String id, String groupId, String artifactId, + VersionReference version, DependencyScope scope, String type) { + add(id, new Dependency(groupId, artifactId, version, scope, type)); + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/DependencyScope.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/DependencyScope.java new file mode 100644 index 00000000..56f0bbb4 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/DependencyScope.java @@ -0,0 +1,61 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +/** + * The scopes of dependencies supported by project generation. + * + * @author Andy Wilkinson + */ +public enum DependencyScope { + + /** + * A dependency that is used as an annotation processor when compiling a project. + */ + ANNOTATION_PROCESSOR, + + /** + * A dependency that is used to compile a project. + */ + COMPILE, + + /** + * A dependency that is a compile time only dependency and not used at runtime. + */ + COMPILE_ONLY, + + /** + * A dependency this is used to run a project. + */ + RUNTIME, + + /** + * A dependency that is provided and is used to run the project. + */ + PROVIDED_RUNTIME, + + /** + * A dependency that is used to compile a project's tests. + */ + TEST_COMPILE, + + /** + * A dependency this is used to run a project's tests. + */ + TEST_RUNTIME + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/MavenRepository.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/MavenRepository.java new file mode 100644 index 00000000..37300822 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/MavenRepository.java @@ -0,0 +1,67 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +/** + * A Maven repository. + * + * @author Andy Wilkinson + */ +public class MavenRepository { + + /** + * Maven Central. + */ + public static final MavenRepository MAVEN_CENTRAL = new MavenRepository( + "maven-central", "Maven Central", "https://repo.maven.apache.org/maven2"); + + private final String id; + + private final String name; + + private final String url; + + private final boolean snapshotsEnabled; + + public MavenRepository(String id, String name, String url) { + this(id, name, url, false); + } + + public MavenRepository(String id, String name, String url, boolean snapshotsEnabled) { + this.id = id; + this.name = name; + this.url = url; + this.snapshotsEnabled = snapshotsEnabled; + } + + public String getId() { + return this.id; + } + + public String getName() { + return this.name; + } + + public String getUrl() { + return this.url; + } + + public boolean isSnapshotsEnabled() { + return this.snapshotsEnabled; + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/MavenRepositoryContainer.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/MavenRepositoryContainer.java new file mode 100644 index 00000000..04905bac --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/MavenRepositoryContainer.java @@ -0,0 +1,64 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +import java.util.LinkedHashMap; +import java.util.function.Function; + +/** + * A {@link BuildItemContainer} implementation for repositories. + * + * @author Stephane Nicoll + */ +public class MavenRepositoryContainer + extends BuildItemContainer { + + MavenRepositoryContainer(Function itemResolver) { + super(new LinkedHashMap<>(), itemResolver); + } + + /** + * Register the specified {@link MavenRepository repository}. + * @param repository the repository to register + */ + public void add(MavenRepository repository) { + add(repository.getId(), repository); + } + + /** + * Register a {@link MavenRepository repository} with snapshots disabled. + * @param id the id of the repository + * @param name the repository name + * @param url the repository url + */ + public void add(String id, String name, String url) { + add(id, name, url, false); + } + + /** + * Register a {@link MavenRepository repository} and specify whether snapshots are + * enabled. + * @param id the id of the repository + * @param name the repository name + * @param url the repository url + * @param snapshotsEnabled whether snapshots are enabled + */ + public void add(String id, String name, String url, boolean snapshotsEnabled) { + add(id, new MavenRepository(id, name, url, snapshotsEnabled)); + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/SimpleBuildItemResolver.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/SimpleBuildItemResolver.java new file mode 100644 index 00000000..3bcf70a1 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/SimpleBuildItemResolver.java @@ -0,0 +1,57 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +import java.util.function.Function; + +/** + * A simple {@link BuildItemResolver} implementation. + * + * @author Stephane Nicoll + */ +public class SimpleBuildItemResolver implements BuildItemResolver { + + private final Function dependencyResolver; + + private final Function bomResolver; + + private final Function repositoryResolver; + + public SimpleBuildItemResolver(Function dependencyResolver, + Function bomResolver, + Function repositoryResolver) { + this.dependencyResolver = dependencyResolver; + this.bomResolver = bomResolver; + this.repositoryResolver = repositoryResolver; + } + + @Override + public Dependency resolveDependency(String id) { + return this.dependencyResolver.apply(id); + } + + @Override + public BillOfMaterials resolveBom(String id) { + return this.bomResolver.apply(id); + } + + @Override + public MavenRepository resolveRepository(String id) { + return this.repositoryResolver.apply(id); + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/package-info.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/package-info.java new file mode 100644 index 00000000..ded91d6b --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/package-info.java @@ -0,0 +1,20 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Build systems abstraction. + */ +package io.spring.initializr.generator.buildsystem; diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/version/VersionReference.java b/initializr-generator/src/main/java/io/spring/initializr/generator/version/VersionReference.java new file mode 100644 index 00000000..780f9bce --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/version/VersionReference.java @@ -0,0 +1,98 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.version; + +import java.util.Objects; + +/** + * A version reference to either a property or an actual version. + * + * @author Stephane Nicoll + */ +public final class VersionReference { + + private final VersionProperty property; + + private final String value; + + private VersionReference(VersionProperty property, String value) { + this.property = property; + this.value = value; + } + + public static VersionReference ofProperty(VersionProperty property) { + return new VersionReference(property, null); + } + + public static VersionReference ofProperty(String internalProperty) { + return ofProperty(VersionProperty.of(internalProperty)); + } + + public static VersionReference ofValue(String value) { + return new VersionReference(null, value); + } + + /** + * Specify if this reference defines a property. + * @return {@code true} if this version is backed by a property + */ + public boolean isProperty() { + return this.property != null; + } + + /** + * Return the {@link VersionProperty} or {@code null} if this reference is not a + * property. + * @return the version property or {@code null} + */ + public VersionProperty getProperty() { + return this.property; + } + + /** + * Return the version of {@code null} if this reference is backed by a property. + * @return the version or {@code null} + */ + public String getValue() { + return this.value; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + VersionReference that = (VersionReference) o; + return Objects.equals(this.property, that.property) + && Objects.equals(this.value, that.value); + } + + @Override + public int hashCode() { + return Objects.hash(this.property, this.value); + } + + @Override + public String toString() { + return (this.property != null) ? "${" + this.property.toStandardFormat() + "}" + : this.value; + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/BomContainerTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/BomContainerTests.java new file mode 100644 index 00000000..87a00506 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/BomContainerTests.java @@ -0,0 +1,70 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +import io.spring.initializr.generator.version.VersionReference; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link BomContainer}. + * + * @author Stephane Nicoll + */ +class BomContainerTests { + + @Test + void addBom() { + BomContainer container = createTestContainer(); + container.add("root", "org.springframework.boot", "spring-boot-dependencies", + VersionReference.ofProperty("spring-boot.version")); + assertThat(container.ids()).containsOnly("root"); + assertThat(container.items()).hasSize(1); + assertThat(container.isEmpty()).isFalse(); + assertThat(container.has("root")).isTrue(); + BillOfMaterials bom = container.get("root"); + assertThat(bom).isNotNull(); + assertThat(bom.getGroupId()).isEqualTo("org.springframework.boot"); + assertThat(bom.getArtifactId()).isEqualTo("spring-boot-dependencies"); + assertThat(bom.getVersion()) + .isEqualTo(VersionReference.ofProperty("spring-boot.version")); + assertThat(bom.getOrder()).isEqualTo(Integer.MAX_VALUE); + } + + @Test + void addBomWithOrder() { + BomContainer container = createTestContainer(); + container.add("custom", "com.example", "acme", VersionReference.ofValue("1.0.0"), + 42); + assertThat(container.ids()).containsOnly("custom"); + assertThat(container.items()).hasSize(1); + assertThat(container.isEmpty()).isFalse(); + assertThat(container.has("custom")).isTrue(); + BillOfMaterials bom = container.get("custom"); + assertThat(bom).isNotNull(); + assertThat(bom.getGroupId()).isEqualTo("com.example"); + assertThat(bom.getArtifactId()).isEqualTo("acme"); + assertThat(bom.getVersion()).isEqualTo(VersionReference.ofValue("1.0.0")); + assertThat(bom.getOrder()).isEqualTo(42); + } + + private BomContainer createTestContainer() { + return new BomContainer((id) -> null); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/BuildItemContainerTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/BuildItemContainerTests.java new file mode 100644 index 00000000..44519dab --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/BuildItemContainerTests.java @@ -0,0 +1,115 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Function; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; + +/** + * Tests for {@link BuildItemContainer}. + * + * @author Stephane Nicoll + */ +class BuildItemContainerTests { + + @Test + void emptyContainer() { + BuildItemContainer container = createTestContainer( + new LinkedHashMap<>()); + assertThat(container.isEmpty()).isTrue(); + assertThat(container.ids()).isEmpty(); + assertThat(container.items()).isEmpty(); + assertThat(container.get("any")).isNull(); + assertThat(container.has("any")).isFalse(); + } + + @Test + void addElement() { + BuildItemContainer container = createTestContainer( + new LinkedHashMap<>()); + container.add("test", "value"); + assertThat(container.ids()).containsOnly("test"); + assertThat(container.items()).containsOnly("value"); + assertThat(container.isEmpty()).isFalse(); + assertThat(container.get("test")).isEqualTo("value"); + assertThat(container.has("test")).isTrue(); + } + + @Test + void addElementWithSameIdOverrideItem() { + BuildItemContainer container = createTestContainer( + new LinkedHashMap<>()); + container.add("test", "value"); + container.add("test", "another"); + assertThat(container.get("test")).isEqualTo("another"); + } + + @Test + void addByIdWithResolution() { + BuildItemContainer container = createTestContainer( + new LinkedHashMap<>(), (id) -> id.equals("test") ? "value" : null); + container.add("test"); + assertThat(container.get("test")).isEqualTo("value"); + } + + @Test + void addByIdWithNoResolution() { + BuildItemContainer container = createTestContainer( + new LinkedHashMap<>(), (id) -> id.equals("test") ? "value" : null); + assertThatIllegalArgumentException().isThrownBy(() -> container.add("unknown")) + .withMessageContaining("unknown"); + } + + @Test + void removeExistingElement() { + BuildItemContainer container = createTestContainer( + new LinkedHashMap<>()); + container.add("test", "value"); + assertThat(container.remove("test")).isTrue(); + assertThat(container.ids()).isEmpty(); + assertThat(container.items()).isEmpty(); + assertThat(container.isEmpty()).isTrue(); + } + + @Test + void removeUnknownElement() { + BuildItemContainer container = createTestContainer( + new LinkedHashMap<>()); + container.add("test", "value"); + assertThat(container.remove("unknown")).isFalse(); + assertThat(container.ids()).containsOnly("test"); + assertThat(container.items()).containsOnly("value"); + assertThat(container.isEmpty()).isFalse(); + } + + private BuildItemContainer createTestContainer( + Map content) { + return createTestContainer(content, (id) -> null); + } + + private BuildItemContainer createTestContainer( + Map content, Function itemResolver) { + return new BuildItemContainer<>(content, itemResolver); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/BuildSystemTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/BuildSystemTests.java new file mode 100644 index 00000000..ecafa119 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/BuildSystemTests.java @@ -0,0 +1,36 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; + +/** + * Tests for {@link BuildSystem}. + * + * @author Stephane Nicoll + */ +class BuildSystemTests { + + @Test + void unknownBuildSystem() { + assertThatIllegalStateException().isThrownBy(() -> BuildSystem.forId("unknown")) + .withMessageContaining("Unrecognized build system id 'unknown'"); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/BuildTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/BuildTests.java new file mode 100644 index 00000000..d5e2e45c --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/BuildTests.java @@ -0,0 +1,88 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link Build}. + * + * @author Stephane Nicoll + */ +class BuildTests { + + @Test + void buildWithDefaultBuildItemResolver() { + TestBuild build = new TestBuild(null); + Assertions.assertThatIllegalArgumentException() + .isThrownBy(() -> build.dependencies().add("test")) + .withMessageContaining("No such value with id 'test'"); + Assertions.assertThatIllegalArgumentException() + .isThrownBy(() -> build.boms().add("another")) + .withMessageContaining("No such value with id 'another'"); + Assertions.assertThatIllegalArgumentException() + .isThrownBy(() -> build.repositories().add("repo")) + .withMessageContaining("No such value with id 'repo'"); + } + + @Test + void buildWithCustomBuildItemResolverResolveDependency() { + BuildItemResolver resolver = mock(BuildItemResolver.class); + Dependency dependency = mock(Dependency.class); + given(resolver.resolveDependency("test")).willReturn(dependency); + TestBuild build = new TestBuild(resolver); + assertThat(build.dependencies().ids()).hasSize(0); + build.dependencies().add("test"); + assertThat(build.dependencies().items()).containsExactly(dependency); + } + + @Test + void buildWithCustomBuildItemResolverResolveBom() { + BuildItemResolver resolver = mock(BuildItemResolver.class); + BillOfMaterials bom = mock(BillOfMaterials.class); + given(resolver.resolveBom("another")).willReturn(bom); + TestBuild build = new TestBuild(resolver); + assertThat(build.boms().ids()).hasSize(0); + build.boms().add("another"); + assertThat(build.boms().items()).containsExactly(bom); + } + + @Test + void buildWithCustomBuildItemResolverResolveRepository() { + BuildItemResolver resolver = mock(BuildItemResolver.class); + MavenRepository repository = mock(MavenRepository.class); + given(resolver.resolveRepository("repo")).willReturn(repository); + TestBuild build = new TestBuild(resolver); + assertThat(build.repositories().ids()).hasSize(0); + build.repositories().add("repo"); + assertThat(build.repositories().items()).containsExactly(repository); + } + + private static class TestBuild extends Build { + + TestBuild(BuildItemResolver buildItemResolver) { + super(buildItemResolver); + } + + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/DependencyComparatorTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/DependencyComparatorTests.java new file mode 100644 index 00000000..5043064d --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/DependencyComparatorTests.java @@ -0,0 +1,69 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link DependencyComparator}. + * + * @author Stephane Nicoll + */ +class DependencyComparatorTests { + + private static final Dependency SPRING_BOOT_A = new Dependency( + "org.springframework.boot", "spring-boot-a"); + + private static final Dependency SPRING_BOOT_B = new Dependency( + "org.springframework.boot", "spring-boot-b"); + + private static final Dependency LIB_ALPHA = new Dependency("com.example.alpha", + "test"); + + private static final Dependency LIB_BETA = new Dependency("com.example.beta", "test"); + + private final DependencyComparator comparator = new DependencyComparator(); + + @Test + void compareWithStarters() { + assertThat(this.comparator.compare(SPRING_BOOT_A, SPRING_BOOT_B)).isNegative(); + } + + @Test + void compareStarterToLib() { + assertThat(this.comparator.compare(SPRING_BOOT_A, LIB_BETA)).isNegative(); + } + + @Test + void compareLibToStarter() { + assertThat(this.comparator.compare(LIB_ALPHA, SPRING_BOOT_A)).isPositive(); + } + + @Test + void compareLibDifferentGroupId() { + assertThat(this.comparator.compare(LIB_ALPHA, LIB_BETA)).isNegative(); + } + + @Test + void compareLibSameGroupId() { + assertThat(this.comparator.compare(LIB_BETA, + new Dependency("com.example.beta", "a"))).isPositive(); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/DependencyContainerTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/DependencyContainerTests.java new file mode 100644 index 00000000..98c16022 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/DependencyContainerTests.java @@ -0,0 +1,69 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +import io.spring.initializr.generator.version.VersionReference; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link DependencyContainer}. + * + * @author Stephane Nicoll + */ +class DependencyContainerTests { + + @Test + void addDependency() { + DependencyContainer container = createTestContainer(); + container.add("web", "org.springframework.boot", "spring-boot-starter-web", + DependencyScope.COMPILE); + assertThat(container.ids()).containsOnly("web"); + assertThat(container.items()).hasSize(1); + assertThat(container.isEmpty()).isFalse(); + assertThat(container.has("web")).isTrue(); + Dependency web = container.get("web"); + assertThat(web).isNotNull(); + assertThat(web.getGroupId()).isEqualTo("org.springframework.boot"); + assertThat(web.getArtifactId()).isEqualTo("spring-boot-starter-web"); + assertThat(web.getVersion()).isNull(); + assertThat(web.getScope()).isEqualTo(DependencyScope.COMPILE); + } + + @Test + void addDependencyWithVersion() { + DependencyContainer container = createTestContainer(); + container.add("custom", "com.example", "acme", VersionReference.ofValue("1.0.0"), + DependencyScope.COMPILE); + assertThat(container.ids()).containsOnly("custom"); + assertThat(container.items()).hasSize(1); + assertThat(container.isEmpty()).isFalse(); + assertThat(container.has("custom")).isTrue(); + Dependency custom = container.get("custom"); + assertThat(custom).isNotNull(); + assertThat(custom.getGroupId()).isEqualTo("com.example"); + assertThat(custom.getArtifactId()).isEqualTo("acme"); + assertThat(custom.getVersion()).isEqualTo(VersionReference.ofValue("1.0.0")); + assertThat(custom.getScope()).isEqualTo(DependencyScope.COMPILE); + } + + private DependencyContainer createTestContainer() { + return new DependencyContainer((id) -> null); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/MavenRepositoryContainerTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/MavenRepositoryContainerTests.java new file mode 100644 index 00000000..dcb421bd --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/MavenRepositoryContainerTests.java @@ -0,0 +1,82 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.buildsystem; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link MavenRepositoryContainer}. + * + * @author Stephane Nicoll + */ +class MavenRepositoryContainerTests { + + @Test + void addMavenRepository() { + MavenRepositoryContainer container = createTestContainer(); + container.add("test", "my repo", "https://example.com/releases"); + assertThat(container.ids()).containsOnly("test"); + assertThat(container.items()).hasSize(1); + assertThat(container.isEmpty()).isFalse(); + assertThat(container.has("test")).isTrue(); + MavenRepository repository = container.get("test"); + assertThat(repository).isNotNull(); + assertThat(repository.getName()).isEqualTo("my repo"); + assertThat(repository.getUrl()).isEqualTo("https://example.com/releases"); + assertThat(repository.isSnapshotsEnabled()).isFalse(); + } + + @Test + void addMavenRepositoryInstance() { + MavenRepositoryContainer container = createTestContainer(); + MavenRepository instance = new MavenRepository("test", "my repo", + "https://example.com/releases"); + container.add(instance); + assertThat(container.ids()).containsOnly("test"); + assertThat(container.items()).hasSize(1); + assertThat(container.isEmpty()).isFalse(); + assertThat(container.has("test")).isTrue(); + MavenRepository repository = container.get("test"); + assertThat(repository).isNotNull(); + assertThat(repository.getName()).isEqualTo("my repo"); + assertThat(repository.getUrl()).isEqualTo("https://example.com/releases"); + assertThat(repository.isSnapshotsEnabled()).isFalse(); + } + + @Test + void addMavenRepositoryWithSnapshotsEnabled() { + MavenRepositoryContainer container = createTestContainer(); + container.add("custom", "custom-snapshots", "https://example.com/snapshots", + true); + assertThat(container.ids()).containsOnly("custom"); + assertThat(container.items()).hasSize(1); + assertThat(container.isEmpty()).isFalse(); + assertThat(container.has("custom")).isTrue(); + MavenRepository repository = container.get("custom"); + assertThat(repository).isNotNull(); + assertThat(repository.getName()).isEqualTo("custom-snapshots"); + assertThat(repository.getUrl()).isEqualTo("https://example.com/snapshots"); + assertThat(repository.isSnapshotsEnabled()).isTrue(); + } + + private MavenRepositoryContainer createTestContainer() { + return new MavenRepositoryContainer((id) -> null); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/version/VersionReferenceTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/version/VersionReferenceTests.java new file mode 100644 index 00000000..ec1a6802 --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/version/VersionReferenceTests.java @@ -0,0 +1,89 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.initializr.generator.version; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link VersionReference}. + * + * @author Stephane Nicoll + */ +class VersionReferenceTests { + + @Test + void ofPropertyWithVersionProperty() { + VersionProperty property = VersionProperty.of("test.version", true); + VersionReference reference = VersionReference.ofProperty(property); + assertThat(reference.isProperty()).isTrue(); + assertThat(reference.getProperty()).isEqualTo(property); + assertThat(reference.getValue()).isNull(); + assertThat(reference).hasToString("${test.version}"); + } + + @Test + void ofPropertyWithInternalProperty() { + VersionReference reference = VersionReference.ofProperty("test.version"); + assertThat(reference.isProperty()).isTrue(); + assertThat(reference.getProperty().toStandardFormat()).isEqualTo("test.version"); + assertThat(reference.getValue()).isNull(); + assertThat(reference).hasToString("${test.version}"); + } + + @Test + void ofPropertyWithValue() { + VersionReference reference = VersionReference.ofValue("1.2.3.RELEASE"); + assertThat(reference.isProperty()).isFalse(); + assertThat(reference.getProperty()).isNull(); + assertThat(reference.getValue()).isEqualTo("1.2.3.RELEASE"); + assertThat(reference).hasToString("1.2.3.RELEASE"); + } + + @Test + void equalsWithSameValue() { + assertThat(VersionReference.ofValue("1")) + .isEqualTo(VersionReference.ofValue("1")); + } + + @Test + void equalsWithDifferentValue() { + assertThat(VersionReference.ofValue("1")) + .isNotEqualTo(VersionReference.ofValue("2")); + } + + @Test + void equalsWithSameProperty() { + assertThat(VersionReference.ofProperty("test.version")) + .isEqualTo(VersionReference.ofProperty("test.version")); + } + + @Test + void equalsWithDifferentProperty() { + assertThat(VersionReference.ofProperty("test.version")) + .isNotEqualTo(VersionReference.ofProperty("another.version")); + } + + @Test + void equalsWithDifferentPropertyScope() { + assertThat(VersionReference.ofProperty(VersionProperty.of("test.version", false))) + .isNotEqualTo(VersionReference + .ofProperty(VersionProperty.of("test.version", true))); + } + +}