Skip to content

Commit 8a81250

Browse files
committed
Revamp
1 parent 24dd092 commit 8a81250

File tree

3 files changed

+185
-149
lines changed

3 files changed

+185
-149
lines changed

shared/src/main/java/eu/maveniverse/maven/toolbox/shared/Atoms.java

+60-85
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,19 @@
77
*/
88
package eu.maveniverse.maven.toolbox.shared;
99

10-
import static java.util.Objects.requireNonNull;
11-
1210
import java.util.Arrays;
1311
import java.util.Collection;
1412
import java.util.Collections;
1513
import java.util.HashSet;
1614
import java.util.Objects;
1715
import java.util.Set;
16+
import java.util.stream.Collectors;
1817

1918
/**
2019
* The "atoms" of the Toolbox that are used to assemble language specific dependency scopes and resolution scopes.
2120
* <p>
22-
* Essentially, we deal with 3-dimensional space: project scope, resolution scope, resolution mode. The lagnauges where languages
23-
* place their scopes.
21+
* Essentially, we deal with 3-dimensional space: project scope, resolution scope, resolution mode. The languages
22+
* place their scopes into this space (and name them and select the transitive ones).
2423
*/
2524
public final class Atoms {
2625
/**
@@ -58,113 +57,82 @@ public String toString() {
5857
}
5958

6059
/**
61-
* Dependency scope: all the variations for all resolution scopes.
60+
* Project scope: like "main", "test", etc...
6261
*/
63-
public static final class DependencyScope extends Atom {
64-
//
65-
// compile | runtime
66-
// none no | no
67-
// both yes | yes
68-
// onlyRuntime no | yes
69-
// onlyCompile yes | no
70-
public static final DependencyScope NONE = new DependencyScope("none");
71-
public static final DependencyScope BOTH = new DependencyScope("both");
72-
public static final DependencyScope ONLY_RUNTIME = new DependencyScope("onlyRuntime");
73-
public static final DependencyScope ONLY_COMPILE = new DependencyScope("onlyCompile");
62+
public static final class ProjectScope extends Atom {
63+
public static final ProjectScope MAIN = new ProjectScope("main");
64+
public static final ProjectScope TEST = new ProjectScope("test");
7465

75-
public static final Set<DependencyScope> ALL =
76-
Collections.unmodifiableSet(new HashSet<>(Arrays.asList(NONE, BOTH, ONLY_RUNTIME, ONLY_COMPILE)));
66+
public static final Set<ProjectScope> ALL =
67+
Collections.unmodifiableSet(new HashSet<>(Arrays.asList(MAIN, TEST)));
7768

78-
public DependencyScope(String id) {
69+
private ProjectScope(String id) {
7970
super(id);
8071
}
8172
}
8273

8374
/**
84-
* Project scope: like "main", "test", etc...
75+
* Resolution scope: "compile" and "runtime".
8576
*/
86-
public static final class ProjectScope extends Atom {
87-
public static final ProjectScope NONE = new ProjectScope("none");
88-
public static final ProjectScope MAIN = new ProjectScope("main");
89-
public static final ProjectScope TEST = new ProjectScope("test");
90-
public static final Set<ProjectScope> ALL =
91-
Collections.unmodifiableSet(new HashSet<>(Arrays.asList(NONE, MAIN, TEST)));
92-
93-
// TODO: this could be even extended? IT, etc
77+
public static final class ResolutionScope extends Atom {
78+
public static final ResolutionScope COMPILE = new ResolutionScope("compile");
79+
public static final ResolutionScope RUNTIME = new ResolutionScope("runtime");
9480

95-
public ProjectScope(String id) {
81+
public ResolutionScope(String id) {
9682
super(id);
9783
}
9884
}
9985

10086
/**
101-
* Resolution mode: eliminate or just remove.
87+
* Resolution mode: "eliminate" or (just) "remove".
10288
*/
103-
public enum ResolutionMode {
89+
public static final class ResolutionMode extends Atom {
10490
/**
105-
* Mode where non-wanted scopes are eliminated. In other words, this mode ensures that if a dependency was
106-
* removed, as it was in unwanted scope, it will guarantee that no such dependency will appear anywhere else in
107-
* the resulting graph.
91+
* Mode where artifacts in non-wanted scopes are eliminated. In other words, this mode ensures that if a
92+
* dependency was removed as it was in unwanted scope, it will guarantee that no such dependency will appear
93+
* anywhere else in the resulting graph.
10894
*/
109-
ELIMINATE,
95+
public static final ResolutionMode ELIMINATE = new ResolutionMode("eliminate");
11096

11197
/**
112-
* Mode where non-wanted scopes are removed only. In other words, they will NOT prevent (as in they will not
113-
* "dominate") perhaps appearing other occurrences of same artifact under some other scope in the graph.
98+
* Mode where artifacts in non-wanted scopes are removed only. In other words, this mode will NOT prevent
99+
* (as in, removed will not "dominate") perhaps appearing other occurrences of same artifact under some other
100+
* scope in the graph.
114101
*/
115-
REMOVE
102+
public static final ResolutionMode REMOVE = new ResolutionMode("remove");
103+
104+
private ResolutionMode(String id) {
105+
super(id);
106+
}
116107
}
117108

118109
/**
119-
* Resolution scope: essentially "compile" and "runtime".
110+
* Dependency scope: all the variations for all resolution scopes.
120111
*/
121-
public static final class ResolutionScope extends Atom {
122-
public static final ResolutionScope NONE =
123-
new ResolutionScope("none", Collections.emptySet(), DependencyScope.ALL);
124-
public static final ResolutionScope EMPTY =
125-
new ResolutionScope("empty", Collections.emptySet(), Collections.emptySet());
126-
public static final ResolutionScope COMPILE = new ResolutionScope(
127-
"compile",
128-
Arrays.asList(DependencyScope.BOTH, DependencyScope.ONLY_COMPILE),
129-
Arrays.asList(DependencyScope.NONE, DependencyScope.ONLY_RUNTIME));
130-
public static final ResolutionScope RUNTIME = new ResolutionScope(
131-
"runtime",
132-
Arrays.asList(DependencyScope.BOTH, DependencyScope.ONLY_RUNTIME),
133-
Arrays.asList(DependencyScope.NONE, DependencyScope.ONLY_COMPILE));
134-
135-
private final Set<DependencyScope> contains;
136-
private final Set<DependencyScope> excludesTransitively;
137-
138-
public ResolutionScope(
139-
String id, Collection<DependencyScope> contains, Collection<DependencyScope> excludesTransitively) {
140-
super(id);
141-
this.contains = Collections.unmodifiableSet(new HashSet<>(contains));
142-
this.excludesTransitively = Collections.unmodifiableSet(new HashSet<>(excludesTransitively));
143-
}
112+
public static final class DependencyScope extends Atom {
113+
//
114+
// compile | runtime
115+
// none no | no
116+
// both yes | yes
117+
// onlyRuntime no | yes
118+
// onlyCompile yes | no
119+
public static final DependencyScope NONE = new DependencyScope("none", Collections.emptySet());
120+
public static final DependencyScope BOTH =
121+
new DependencyScope("both", Arrays.asList(ResolutionScope.COMPILE, ResolutionScope.RUNTIME));
122+
public static final DependencyScope ONLY_RUNTIME =
123+
new DependencyScope("onlyRuntime", Collections.singleton(ResolutionScope.RUNTIME));
124+
public static final DependencyScope ONLY_COMPILE =
125+
new DependencyScope("onlyCompile", Collections.singleton(ResolutionScope.COMPILE));
144126

145-
public Set<DependencyScope> getContains() {
146-
return contains;
147-
}
127+
private final Set<ResolutionScope> memberOf;
148128

149-
public Set<DependencyScope> getExcludesTransitively() {
150-
return excludesTransitively;
129+
private DependencyScope(String id, Collection<ResolutionScope> resolutionScopes) {
130+
super(id);
131+
this.memberOf = Collections.unmodifiableSet(new HashSet<>(resolutionScopes));
151132
}
152133

153-
public ResolutionScope plus(DependencyScope dependencyScope) {
154-
requireNonNull(dependencyScope);
155-
if (this == NONE) {
156-
throw new IllegalStateException("NONE is not extensible resolution scope");
157-
}
158-
if (getContains().contains(dependencyScope)) {
159-
return this;
160-
}
161-
if (this == EMPTY) {
162-
return new ResolutionScope(
163-
dependencyScope.getId(), Collections.singleton(dependencyScope), Collections.emptySet());
164-
}
165-
HashSet<DependencyScope> dependencyScopes = new HashSet<>(getContains());
166-
dependencyScopes.add(dependencyScope);
167-
return new ResolutionScope(getId() + "+" + dependencyScope.getId(), dependencyScopes, excludesTransitively);
134+
public Set<ResolutionScope> getMemberOf() {
135+
return memberOf;
168136
}
169137
}
170138

@@ -189,9 +157,16 @@ public interface LanguageDependencyScope {
189157

190158
boolean isTransitive();
191159

192-
DependencyScope getDependencyScope();
160+
Set<DependencyScope> getDependencyScopes();
193161

194162
Set<ProjectScope> getProjectScopes();
163+
164+
default Set<ResolutionScope> getMemberOf() {
165+
return getDependencyScopes().stream()
166+
.map(DependencyScope::getMemberOf)
167+
.flatMap(Collection::stream)
168+
.collect(Collectors.toSet());
169+
}
195170
}
196171

197172
/**
@@ -202,9 +177,9 @@ public interface LanguageResolutionScope {
202177

203178
Language getLanguage();
204179

205-
ProjectScope getProjectScope();
180+
Set<ProjectScope> getProjectScopes();
206181

207-
ResolutionScope getResolutionScope();
182+
Set<ResolutionScope> getResolutionScopes();
208183

209184
ResolutionMode getResolutionMode();
210185
}

shared/src/main/java/eu/maveniverse/maven/toolbox/shared/internal/ToolboxImpl.java

+27-14
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.util.HashSet;
1717
import java.util.List;
1818
import java.util.Set;
19+
import java.util.stream.Collectors;
1920
import org.eclipse.aether.DefaultRepositorySystemSession;
2021
import org.eclipse.aether.RequestTrace;
2122
import org.eclipse.aether.artifact.Artifact;
@@ -65,10 +66,14 @@ public CollectResult collect(
6566
Set<String> transitiveExcludes = calculateTransitiveExcludes(resolutionScope);
6667
logger.info(
6768
"Collecting project scope: {}",
68-
resolutionScope.getProjectScope().getId());
69+
resolutionScope.getProjectScopes().stream()
70+
.map(Atoms.Atom::getId)
71+
.collect(Collectors.joining(",")));
6972
logger.info(
7073
" resolution scope: {}",
71-
resolutionScope.getResolutionScope().getId());
74+
resolutionScope.getResolutionScopes().stream()
75+
.map(Atoms.Atom::getId)
76+
.collect(Collectors.joining(",")));
7277
logger.info(
7378
" language: {}", resolutionScope.getLanguage().getId());
7479
logger.info(" includes: {}", includes);
@@ -121,10 +126,14 @@ public CollectResult collect(
121126
Set<String> transitiveExcludes = calculateTransitiveExcludes(resolutionScope);
122127
logger.info(
123128
"Collecting project scope: {}",
124-
resolutionScope.getProjectScope().getId());
129+
resolutionScope.getProjectScopes().stream()
130+
.map(Atoms.Atom::getId)
131+
.collect(Collectors.joining(",")));
125132
logger.info(
126133
" resolution scope: {}",
127-
resolutionScope.getResolutionScope().getId());
134+
resolutionScope.getResolutionScopes().stream()
135+
.map(Atoms.Atom::getId)
136+
.collect(Collectors.joining(",")));
128137
logger.info(
129138
" language: {}", resolutionScope.getLanguage().getId());
130139
logger.info(" includes: {}", includes);
@@ -160,13 +169,13 @@ public CollectResult collect(
160169
* This method basically translates "scope" to {@link Atoms.LanguageDependencyScope} specific string IDs.
161170
*/
162171
private Set<String> calculateIncludes(Atoms.LanguageResolutionScope scope) {
163-
Atoms.ProjectScope projectScope = scope.getProjectScope();
164-
Atoms.ResolutionScope resolutionScope = scope.getResolutionScope();
172+
Set<Atoms.ProjectScope> projectScopes = scope.getProjectScopes();
173+
Set<Atoms.ResolutionScope> resolutionScopes = scope.getResolutionScopes();
165174
HashSet<String> includes = new HashSet<>();
166175
for (Atoms.LanguageDependencyScope languageDependencyScope :
167176
scope.getLanguage().getLanguageDependencyScopeUniverse()) {
168-
if (languageDependencyScope.getProjectScopes().contains(projectScope)
169-
&& resolutionScope.getContains().contains(languageDependencyScope.getDependencyScope())) {
177+
if (hasIntersection(projectScopes, languageDependencyScope.getProjectScopes())
178+
&& hasIntersection(resolutionScopes, languageDependencyScope.getMemberOf())) {
170179
// IF: project scope is contained in given language project scopes
171180
// AND if resolution scope contains given language scope dependency scope
172181
// the languageScope should be included, add it
@@ -180,13 +189,13 @@ private Set<String> calculateIncludes(Atoms.LanguageResolutionScope scope) {
180189
* This method basically translates "scope" to {@link Atoms.LanguageDependencyScope} specific string IDs.
181190
*/
182191
private Set<String> calculateTransitiveExcludes(Atoms.LanguageResolutionScope scope) {
183-
Atoms.ProjectScope projectScope = scope.getProjectScope();
184-
Atoms.ResolutionScope resolutionScope = scope.getResolutionScope();
192+
Set<Atoms.ProjectScope> projectScopes = scope.getProjectScopes();
193+
Set<Atoms.ResolutionScope> resolutionScopes = scope.getResolutionScopes();
185194
HashSet<String> excludes = new HashSet<>();
186195
for (Atoms.LanguageDependencyScope languageDependencyScope :
187196
scope.getLanguage().getLanguageDependencyScopeUniverse()) {
188-
// if the language scope is not meant to be here (is not present in this project scope)
189-
if (!languageDependencyScope.getProjectScopes().contains(projectScope)) {
197+
// if the language scope is not meant to be here (is not present in wanted project scopes)
198+
if (!hasIntersection(projectScopes, languageDependencyScope.getProjectScopes())) {
190199
excludes.add(languageDependencyScope.getId());
191200
continue;
192201
}
@@ -195,14 +204,18 @@ private Set<String> calculateTransitiveExcludes(Atoms.LanguageResolutionScope sc
195204
excludes.add(languageDependencyScope.getId());
196205
continue;
197206
}
198-
// if the resolution scope explicitly excludes language scope's dependency scope
199-
if (resolutionScope.getExcludesTransitively().contains(languageDependencyScope.getDependencyScope())) {
207+
// if the resolution scopes has no language scope's dependency scope
208+
if (!hasIntersection(resolutionScopes, languageDependencyScope.getMemberOf())) {
200209
excludes.add(languageDependencyScope.getId());
201210
}
202211
}
203212
return excludes;
204213
}
205214

215+
private <T> boolean hasIntersection(Set<T> one, Set<T> two) {
216+
return one.stream().anyMatch(two::contains);
217+
}
218+
206219
@Override
207220
public List<ArtifactResult> resolveArtifacts(List<Artifact> artifacts, List<RemoteRepository> remoteRepositories)
208221
throws ArtifactResolutionException {

0 commit comments

Comments
 (0)