Skip to content

Commit 2945eb1

Browse files
committed
Polish "Add ability to exclude ProjectGenerationConfiguration"
See gh-1584
1 parent 2b83654 commit 2945eb1

File tree

6 files changed

+144
-26
lines changed

6 files changed

+144
-26
lines changed

initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectGenerationConfigurationTypeFilter.java

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,65 @@
1616

1717
package io.spring.initializr.generator.project;
1818

19+
import java.util.Arrays;
20+
import java.util.Set;
21+
import java.util.function.Predicate;
22+
1923
/**
2024
* Allows to filter {@link ProjectGenerationConfiguration}.
2125
*
2226
* @author Simon Zambrovski
27+
* @author Moritz Halbritter
2328
*/
24-
public interface ProjectGenerationConfigurationTypeFilter {
29+
public interface ProjectGenerationConfigurationTypeFilter extends Predicate<Class<?>> {
30+
31+
/**
32+
* Creates a {@link ProjectGenerationConfigurationTypeFilter} which includes the given
33+
* types.
34+
* @param types the types to include
35+
* @return a {@link ProjectGenerationConfigurationTypeFilter}
36+
*/
37+
static ProjectGenerationConfigurationTypeFilter include(Class<?>... types) {
38+
Set<Class<?>> classes = Set.of(types);
39+
return classes::contains;
40+
}
41+
42+
/**
43+
* Creates a {@link ProjectGenerationConfigurationTypeFilter} which excludes the given
44+
* types.
45+
* @param types the types to exclude
46+
* @return a {@link ProjectGenerationConfigurationTypeFilter}
47+
*/
48+
static ProjectGenerationConfigurationTypeFilter exclude(Class<?>... types) {
49+
Set<Class<?>> classes = Set.of(types);
50+
return (clazz) -> !classes.contains(clazz);
51+
}
52+
53+
/**
54+
* Creates a {@link ProjectGenerationConfigurationTypeFilter} from multiple filters
55+
* which must all match.
56+
* @param filters the filters
57+
* @return a combined {@link ProjectGenerationConfigurationTypeFilter}
58+
*/
59+
static ProjectGenerationConfigurationTypeFilter allMatch(ProjectGenerationConfigurationTypeFilter... filters) {
60+
return allMatch(Arrays.asList(filters));
61+
}
2562

2663
/**
27-
* Determines if the provided class matches the filter.
28-
* @param type type to match.
29-
* @return true, if the type matches.
64+
* Creates a {@link ProjectGenerationConfigurationTypeFilter} from multiple filters
65+
* which must all match.
66+
* @param filters the filters
67+
* @return a combined {@link ProjectGenerationConfigurationTypeFilter}
3068
*/
31-
boolean match(Class<?> type);
69+
static ProjectGenerationConfigurationTypeFilter allMatch(
70+
Iterable<? extends ProjectGenerationConfigurationTypeFilter> filters) {
71+
return (clazz) -> {
72+
boolean match = true;
73+
for (ProjectGenerationConfigurationTypeFilter filter : filters) {
74+
match &= filter.test(clazz);
75+
}
76+
return match;
77+
};
78+
}
3279

3380
}

initializr-generator/src/main/java/io/spring/initializr/generator/project/ProjectGenerator.java

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
*
3636
* @author Andy Wilkinson
3737
* @author Stephane Nicoll
38+
* @author Simon Zambrovski
39+
* @author Moritz Halbritter
3840
*/
3941
public class ProjectGenerator {
4042

@@ -119,8 +121,9 @@ public <T> T generate(ProjectDescription description, ProjectAssetGenerator<T> p
119121
* Return the {@link ProjectGenerationConfiguration} class names that should be
120122
* considered. By default, this method will load candidates using
121123
* {@link SpringFactoriesLoader} with {@link ProjectGenerationConfiguration} and
122-
* exclude those which are matched by the
123-
* {@link ProjectGenerationConfigurationTypeFilter}
124+
* exclude those which are not matched by the
125+
* {@link ProjectGenerationConfigurationTypeFilter}, also loaded by
126+
* {@link SpringFactoriesLoader}.
124127
* @param description the description of the project to generate
125128
* @return a list of candidate configurations
126129
*/
@@ -129,8 +132,8 @@ protected List<String> getCandidateProjectGenerationConfigurations(ProjectDescri
129132
List<String> candidates = getProjectGenerationConfigurationFactoryNames();
130133
ProjectGenerationConfigurationTypeFilter filter = getProjectGenerationConfigurationExclusionFilter();
131134
return candidates.stream().filter((candidate) -> {
132-
Class<?> type = this.resolveClass(candidate);
133-
return type != null && !filter.match(type);
135+
Class<?> type = resolveClass(candidate);
136+
return type != null && filter.test(type);
134137
}).toList();
135138
}
136139

@@ -152,14 +155,7 @@ List<String> getProjectGenerationConfigurationFactoryNames() {
152155
ProjectGenerationConfigurationTypeFilter getProjectGenerationConfigurationExclusionFilter() {
153156
List<ProjectGenerationConfigurationTypeFilter> filters = SpringFactoriesLoader
154157
.loadFactories(ProjectGenerationConfigurationTypeFilter.class, getClass().getClassLoader());
155-
// Build a composite filter, combining results with a logical OR
156-
return (configurationClass) -> {
157-
boolean excluded = false;
158-
for (ProjectGenerationConfigurationTypeFilter filter : filters) {
159-
excluded = excluded || filter.match(configurationClass);
160-
}
161-
return excluded;
162-
};
158+
return ProjectGenerationConfigurationTypeFilter.allMatch(filters);
163159
}
164160

165161
private void registerProjectDescription(ProjectGenerationContext context, ProjectDescription description) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.spring.initializr.generator.project;
18+
19+
import org.junit.jupiter.api.Test;
20+
21+
import static org.assertj.core.api.Assertions.assertThat;
22+
23+
/**
24+
* Tests for {@link ProjectGenerationConfigurationTypeFilter}.
25+
*
26+
* @author Moritz Halbritter
27+
*/
28+
class ProjectGenerationConfigurationTypeFilterTests {
29+
30+
@Test
31+
void include() {
32+
ProjectGenerationConfigurationTypeFilter filter = ProjectGenerationConfigurationTypeFilter.include(A.class,
33+
B.class);
34+
assertThat(filter).accepts(A.class, B.class);
35+
assertThat(filter).rejects(C.class);
36+
}
37+
38+
@Test
39+
void exclude() {
40+
ProjectGenerationConfigurationTypeFilter filter = ProjectGenerationConfigurationTypeFilter.exclude(A.class,
41+
B.class);
42+
assertThat(filter).rejects(A.class, B.class);
43+
assertThat(filter).accepts(C.class);
44+
}
45+
46+
@Test
47+
void allMatch() {
48+
ProjectGenerationConfigurationTypeFilter filterA = (clazz) -> clazz.equals(A.class);
49+
ProjectGenerationConfigurationTypeFilter filterAorB = (clazz) -> clazz.equals(A.class) || clazz.equals(B.class);
50+
ProjectGenerationConfigurationTypeFilter filterNotC = (clazz) -> !clazz.equals(C.class);
51+
ProjectGenerationConfigurationTypeFilter combined = ProjectGenerationConfigurationTypeFilter.allMatch(filterA,
52+
filterAorB, filterNotC);
53+
assertThat(combined).accepts(A.class);
54+
assertThat(combined).rejects(B.class, C.class);
55+
}
56+
57+
private static final class A {
58+
59+
}
60+
61+
private static final class B {
62+
63+
}
64+
65+
private static final class C {
66+
67+
}
68+
69+
}

initializr-generator/src/test/java/io/spring/initializr/generator/project/ProjectGeneratorTests.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -203,13 +203,13 @@ void loadAndConstructProjectGenerationTypeExclusionFilter() {
203203
ProjectGenerator generator = new ProjectGenerator(mockContextInitializr());
204204
ProjectGenerationConfigurationTypeFilter filter = generator.getProjectGenerationConfigurationExclusionFilter();
205205
assertThat(filter).isNotNull();
206-
assertThat(filter.match(TestProjectGenerationConfiguration.class)).isTrue();
207-
assertThat(filter.match(TestProjectGenerationConfiguration2.class)).isTrue();
208-
assertThat(filter.match(Integer.class)).isFalse();
206+
assertThat(filter.test(TestProjectGenerationConfiguration.class)).isFalse();
207+
assertThat(filter.test(TestProjectGenerationConfiguration2.class)).isFalse();
208+
assertThat(filter.test(Integer.class)).isTrue();
209209
}
210210

211211
@Test
212-
void filterProjectContributorsCorrectly(@TempDir Path projectDir) {
212+
void filterProjectContributorsCorrectly() {
213213
ProjectDescription description = mock(ProjectDescription.class);
214214
given(description.getArtifactId()).willReturn("test-custom-contributor");
215215
given(description.getBuildSystem()).willReturn(new MavenBuildSystem());
@@ -222,7 +222,7 @@ List<String> getProjectGenerationConfigurationFactoryNames() {
222222

223223
@Override
224224
ProjectGenerationConfigurationTypeFilter getProjectGenerationConfigurationExclusionFilter() {
225-
return TestProjectGenerationConfiguration2.class::equals;
225+
return (clazz) -> !TestProjectGenerationConfiguration2.class.equals(clazz);
226226
}
227227
};
228228
List<String> candidates = generator.getCandidateProjectGenerationConfigurations(description);

initializr-generator/src/test/java/io/spring/initializr/generator/project/contributor/TestProjectGenerationConfiguration2ExcludingTypeFilter.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@
2121
public class TestProjectGenerationConfiguration2ExcludingTypeFilter
2222
implements ProjectGenerationConfigurationTypeFilter {
2323

24+
private final ProjectGenerationConfigurationTypeFilter delegate = ProjectGenerationConfigurationTypeFilter
25+
.exclude(TestProjectGenerationConfiguration2.class);
26+
2427
@Override
25-
public boolean match(Class<?> type) {
26-
return TestProjectGenerationConfiguration2.class.equals(type);
28+
public boolean test(Class<?> type) {
29+
return this.delegate.test(type);
2730
}
2831

2932
}

initializr-generator/src/test/java/io/spring/initializr/generator/project/contributor/TestProjectGenerationConfigurationExcludingTypeFilter.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@
2020

2121
public class TestProjectGenerationConfigurationExcludingTypeFilter implements ProjectGenerationConfigurationTypeFilter {
2222

23+
private final ProjectGenerationConfigurationTypeFilter delegate = ProjectGenerationConfigurationTypeFilter
24+
.exclude(TestProjectGenerationConfiguration.class);
25+
2326
@Override
24-
public boolean match(Class<?> type) {
25-
return TestProjectGenerationConfiguration.class.equals(type);
27+
public boolean test(Class<?> type) {
28+
return this.delegate.test(type);
2629
}
2730

2831
}

0 commit comments

Comments
 (0)