Skip to content

Commit 18f10b0

Browse files
committed
GH-1038 - Expose ApplicationModuleInformation.
ApplicationModuleInformation is now public as it's referenced from the ApplicationModuleDetectionStrategy SPI. Extracted ApplicationModuleInformationFactory to avoid the internal instance creation logic from leaking.
1 parent 133ad57 commit 18f10b0

File tree

2 files changed

+196
-157
lines changed

2 files changed

+196
-157
lines changed

spring-modulith-core/src/main/java/org/springframework/modulith/core/ApplicationModuleInformation.java

Lines changed: 3 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,17 @@
1515
*/
1616
package org.springframework.modulith.core;
1717

18-
import java.lang.annotation.Annotation;
19-
import java.util.Arrays;
2018
import java.util.List;
2119
import java.util.Optional;
22-
import java.util.function.Predicate;
23-
import java.util.function.Supplier;
24-
import java.util.stream.Stream;
25-
26-
import org.jmolecules.ddd.annotation.Module;
27-
import org.springframework.modulith.ApplicationModule;
28-
import org.springframework.modulith.ApplicationModule.Type;
29-
import org.springframework.modulith.core.Types.JMoleculesTypes;
30-
import org.springframework.util.Assert;
31-
import org.springframework.util.StringUtils;
32-
33-
import com.tngtech.archunit.core.domain.JavaClass;
3420

3521
/**
3622
* Abstraction for low-level module information. Used to support different annotations to configure metadata about a
3723
* module.
3824
*
3925
* @author Oliver Drotbohm
26+
* @since 1.4, previously package private.
4027
*/
41-
interface ApplicationModuleInformation {
28+
public interface ApplicationModuleInformation {
4229

4330
/**
4431
* Creates a new {@link ApplicationModuleInformation} for the given {@link JavaPackage}.
@@ -47,12 +34,7 @@ interface ApplicationModuleInformation {
4734
* @return will never be {@literal null}.
4835
*/
4936
public static ApplicationModuleInformation of(JavaPackage javaPackage) {
50-
51-
var lookup = AnnotationLookup.of(javaPackage.toSingle(), __ -> true);
52-
53-
return JMoleculesTypes.isModulePresent() && JMoleculesModule.supports(lookup)
54-
? new JMoleculesModule(lookup)
55-
: new SpringModulithModule(lookup);
37+
return ApplicationModuleInformationFactory.of(javaPackage);
5638
}
5739

5840
/**
@@ -78,140 +60,4 @@ default Optional<String> getDisplayName() {
7860
* @since 1.2
7961
*/
8062
boolean isOpen();
81-
82-
/**
83-
* An {@link ApplicationModuleInformation} for the jMolecules {@link Module} annotation.
84-
*
85-
* @author Oliver Drotbohm
86-
* @see <a href="https://jmolecules.org">https://jMolecules.org</a>
87-
*/
88-
static class JMoleculesModule implements ApplicationModuleInformation {
89-
90-
private final Optional<Module> annotation;
91-
92-
public static boolean supports(AnnotationLookup lookup) {
93-
return lookup.lookup(Module.class).isPresent();
94-
}
95-
96-
public <A extends Annotation> JMoleculesModule(AnnotationLookup lookup) {
97-
this.annotation = lookup.lookup(Module.class);
98-
}
99-
100-
/*
101-
* (non-Javadoc)
102-
* @see org.springframework.modulith.model.ApplicationModuleInformation#getDisplayName()
103-
*/
104-
@Override
105-
public Optional<String> getDisplayName() {
106-
107-
Supplier<Optional<String>> fallback = () -> annotation //
108-
.map(Module::value) //
109-
.filter(StringUtils::hasText);
110-
111-
return annotation //
112-
.map(Module::name) //
113-
.filter(StringUtils::hasText)
114-
.or(fallback);
115-
}
116-
117-
/*
118-
* (non-Javadoc)
119-
* @see org.springframework.modulith.core.ApplicationModuleInformation#getDeclaredDependencies()
120-
*/
121-
@Override
122-
public List<String> getDeclaredDependencies() {
123-
return List.of(ApplicationModule.OPEN_TOKEN);
124-
}
125-
126-
/*
127-
* (non-Javadoc)
128-
* @see org.springframework.modulith.core.ApplicationModuleInformation#isOpenModule()
129-
*/
130-
@Override
131-
public boolean isOpen() {
132-
return false;
133-
}
134-
}
135-
136-
/**
137-
* An {@link ApplicationModuleInformation} that inspects the {@link ApplicationModule} annotation.
138-
*
139-
* @author Oliver Drotbohm
140-
*/
141-
static class SpringModulithModule implements ApplicationModuleInformation {
142-
143-
private final Optional<ApplicationModule> annotation;
144-
145-
/**
146-
* Whether the given {@link AnnotationLookup} supports this {@link ApplicationModuleInformation}.
147-
*
148-
* @param lookup must not be {@literal null}.
149-
*/
150-
public static boolean supports(AnnotationLookup lookup) {
151-
152-
Assert.notNull(lookup, "Annotation lookup must not be null!");
153-
154-
return lookup.lookup(ApplicationModule.class).isPresent();
155-
}
156-
157-
/**
158-
* Creates a new {@link SpringModulithModule} for the given {@link AnnotationLookup}.
159-
*
160-
* @param lookup must not be {@literal null}.
161-
*/
162-
public SpringModulithModule(AnnotationLookup lookup) {
163-
this.annotation = lookup.lookup(ApplicationModule.class);
164-
}
165-
166-
/*
167-
* (non-Javadoc)
168-
* @see org.springframework.modulith.model.ApplicationModuleInformation#getDisplayName()
169-
*/
170-
@Override
171-
public Optional<String> getDisplayName() {
172-
173-
return annotation //
174-
.map(ApplicationModule::displayName) //
175-
.filter(StringUtils::hasText);
176-
}
177-
178-
/*
179-
* (non-Javadoc)
180-
* @see org.springframework.modulith.core.ApplicationModuleInformation#getDeclaredDependencies()
181-
*/
182-
@Override
183-
public List<String> getDeclaredDependencies() {
184-
185-
return annotation //
186-
.map(it -> Arrays.stream(it.allowedDependencies())) //
187-
.orElse(Stream.of(ApplicationModule.OPEN_TOKEN)) //
188-
.toList();
189-
}
190-
191-
/*
192-
* (non-Javadoc)
193-
* @see org.springframework.modulith.core.ApplicationModuleInformation#isOpenModule()
194-
*/
195-
@Override
196-
public boolean isOpen() {
197-
return annotation.map(it -> it.type().equals(Type.OPEN)).orElse(false);
198-
}
199-
}
200-
201-
interface AnnotationLookup {
202-
203-
static AnnotationLookup of(JavaPackage javaPackage,
204-
Predicate<JavaClass> typeSelector) {
205-
206-
return new AnnotationLookup() {
207-
208-
@Override
209-
public <A extends Annotation> Optional<A> lookup(Class<A> annotation) {
210-
return javaPackage.findAnnotation(annotation);
211-
}
212-
};
213-
}
214-
215-
<A extends Annotation> Optional<A> lookup(Class<A> annotation);
216-
}
21763
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
/*
2+
* Copyright 2025 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+
package org.springframework.modulith.core;
17+
18+
import java.lang.annotation.Annotation;
19+
import java.util.Arrays;
20+
import java.util.List;
21+
import java.util.Optional;
22+
import java.util.function.Predicate;
23+
import java.util.function.Supplier;
24+
import java.util.stream.Stream;
25+
26+
import org.jmolecules.ddd.annotation.Module;
27+
import org.springframework.modulith.ApplicationModule;
28+
import org.springframework.modulith.ApplicationModule.Type;
29+
import org.springframework.modulith.core.Types.JMoleculesTypes;
30+
import org.springframework.util.Assert;
31+
import org.springframework.util.StringUtils;
32+
33+
import com.tngtech.archunit.core.domain.JavaClass;
34+
35+
/**
36+
* Encapsulate creation logic for {@link ApplicationModuleInformation} instances.
37+
*
38+
* @author Oliver Drotbohm
39+
* @since 1.4
40+
*/
41+
class ApplicationModuleInformationFactory {
42+
43+
/**
44+
* Creates a new {@link ApplicationModuleInformation} for the given {@link JavaPackage}.
45+
*
46+
* @param javaPackage must not be {@literal null}.
47+
* @return will never be {@literal null}.
48+
*/
49+
public static ApplicationModuleInformation of(JavaPackage javaPackage) {
50+
51+
var lookup = AnnotationLookup.of(javaPackage.toSingle(), __ -> true);
52+
53+
return JMoleculesTypes.isModulePresent() && JMoleculesModule.supports(lookup)
54+
? new JMoleculesModule(lookup)
55+
: new SpringModulithModule(lookup);
56+
}
57+
58+
/**
59+
* An {@link ApplicationModuleInformation} for the jMolecules {@link Module} annotation.
60+
*
61+
* @author Oliver Drotbohm
62+
* @see <a href="https://jmolecules.org">https://jMolecules.org</a>
63+
*/
64+
static class JMoleculesModule implements ApplicationModuleInformation {
65+
66+
private final Optional<Module> annotation;
67+
68+
public static boolean supports(AnnotationLookup lookup) {
69+
return lookup.lookup(Module.class).isPresent();
70+
}
71+
72+
public <A extends Annotation> JMoleculesModule(AnnotationLookup lookup) {
73+
this.annotation = lookup.lookup(Module.class);
74+
}
75+
76+
/*
77+
* (non-Javadoc)
78+
* @see org.springframework.modulith.model.ApplicationModuleInformation#getDisplayName()
79+
*/
80+
@Override
81+
public Optional<String> getDisplayName() {
82+
83+
Supplier<Optional<String>> fallback = () -> annotation //
84+
.map(Module::value) //
85+
.filter(StringUtils::hasText);
86+
87+
return annotation //
88+
.map(Module::name) //
89+
.filter(StringUtils::hasText)
90+
.or(fallback);
91+
}
92+
93+
/*
94+
* (non-Javadoc)
95+
* @see org.springframework.modulith.core.ApplicationModuleInformation#getDeclaredDependencies()
96+
*/
97+
@Override
98+
public List<String> getDeclaredDependencies() {
99+
return List.of(ApplicationModule.OPEN_TOKEN);
100+
}
101+
102+
/*
103+
* (non-Javadoc)
104+
* @see org.springframework.modulith.core.ApplicationModuleInformation#isOpenModule()
105+
*/
106+
@Override
107+
public boolean isOpen() {
108+
return false;
109+
}
110+
}
111+
112+
/**
113+
* An {@link ApplicationModuleInformation} that inspects the {@link ApplicationModule} annotation.
114+
*
115+
* @author Oliver Drotbohm
116+
*/
117+
static class SpringModulithModule implements ApplicationModuleInformation {
118+
119+
private final Optional<ApplicationModule> annotation;
120+
121+
/**
122+
* Whether the given {@link AnnotationLookup} supports this {@link ApplicationModuleInformation}.
123+
*
124+
* @param lookup must not be {@literal null}.
125+
*/
126+
public static boolean supports(AnnotationLookup lookup) {
127+
128+
Assert.notNull(lookup, "Annotation lookup must not be null!");
129+
130+
return lookup.lookup(ApplicationModule.class).isPresent();
131+
}
132+
133+
/**
134+
* Creates a new {@link SpringModulithModule} for the given {@link AnnotationLookup}.
135+
*
136+
* @param lookup must not be {@literal null}.
137+
*/
138+
public SpringModulithModule(AnnotationLookup lookup) {
139+
this.annotation = lookup.lookup(ApplicationModule.class);
140+
}
141+
142+
/*
143+
* (non-Javadoc)
144+
* @see org.springframework.modulith.model.ApplicationModuleInformation#getDisplayName()
145+
*/
146+
@Override
147+
public Optional<String> getDisplayName() {
148+
149+
return annotation //
150+
.map(ApplicationModule::displayName) //
151+
.filter(StringUtils::hasText);
152+
}
153+
154+
/*
155+
* (non-Javadoc)
156+
* @see org.springframework.modulith.core.ApplicationModuleInformation#getDeclaredDependencies()
157+
*/
158+
@Override
159+
public List<String> getDeclaredDependencies() {
160+
161+
return annotation //
162+
.map(it -> Arrays.stream(it.allowedDependencies())) //
163+
.orElse(Stream.of(ApplicationModule.OPEN_TOKEN)) //
164+
.toList();
165+
}
166+
167+
/*
168+
* (non-Javadoc)
169+
* @see org.springframework.modulith.core.ApplicationModuleInformation#isOpenModule()
170+
*/
171+
@Override
172+
public boolean isOpen() {
173+
return annotation.map(it -> it.type().equals(Type.OPEN)).orElse(false);
174+
}
175+
}
176+
177+
interface AnnotationLookup {
178+
179+
static AnnotationLookup of(JavaPackage javaPackage,
180+
Predicate<JavaClass> typeSelector) {
181+
182+
return new AnnotationLookup() {
183+
184+
@Override
185+
public <A extends Annotation> Optional<A> lookup(Class<A> annotation) {
186+
return javaPackage.findAnnotation(annotation);
187+
}
188+
};
189+
}
190+
191+
<A extends Annotation> Optional<A> lookup(Class<A> annotation);
192+
}
193+
}

0 commit comments

Comments
 (0)