-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add feature to get maven module dependency graph (#151)
* feat: add feature to get maven module dependency graph * Add maven model dependency * Please spotless * Rectify IntelliJ warnings * Make names clearer * Detect if there are submodule as dependency * Please spotless
- Loading branch information
1 parent
5d90c92
commit e917911
Showing
16 changed files
with
428 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
96 changes: 96 additions & 0 deletions
96
...or-commons/src/main/java/io/github/algomaster99/terminator/commons/maven/MavenModule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package io.github.algomaster99.terminator.commons.maven; | ||
|
||
import java.nio.file.Path; | ||
import java.util.ArrayDeque; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Queue; | ||
import org.apache.maven.model.Dependency; | ||
import org.apache.maven.model.Model; | ||
|
||
public class MavenModule { | ||
private final MavenModule parent; | ||
|
||
private final Model self; | ||
|
||
private final Path fileSystemPath; | ||
|
||
private final List<MavenModule> submodules = new ArrayList<>(); | ||
|
||
MavenModule(Model self, Path fileSystemPath, MavenModule parent) { | ||
this.self = self; | ||
this.fileSystemPath = fileSystemPath; | ||
this.parent = parent; | ||
} | ||
|
||
public void addSubmodule(MavenModule child) { | ||
submodules.add(child); | ||
} | ||
|
||
public Model getSelf() { | ||
return self; | ||
} | ||
|
||
public List<MavenModule> getSubmodules() { | ||
return submodules; | ||
} | ||
|
||
public Path getFileSystemPath() { | ||
return fileSystemPath; | ||
} | ||
|
||
public MavenModule findSubmodule(String artifactIdOfModule) { | ||
Queue<MavenModule> queue = new ArrayDeque<>(); | ||
queue.add(topLevelParent()); | ||
while (!queue.isEmpty()) { | ||
MavenModule module = queue.poll(); | ||
if (module.getSelf().getArtifactId().equals(artifactIdOfModule)) { | ||
return module; | ||
} | ||
queue.addAll(module.getSubmodules()); | ||
} | ||
return null; | ||
} | ||
|
||
public MavenModule topLevelParent() { | ||
if (parent == null) { | ||
return this; | ||
} | ||
return parent.topLevelParent(); | ||
} | ||
|
||
public List<Model> getSubmodulesThatAreDependencies() { | ||
List<Model> subModulesThatAreDependencies = new ArrayList<>(); | ||
List<Dependency> dependencies = self.getDependencies(); | ||
for (Dependency dependency : dependencies) { | ||
String artifactId = dependency.getArtifactId(); | ||
MavenModule submodule = findSubmodule(artifactId); | ||
if (submodule == null) { | ||
continue; | ||
} | ||
subModulesThatAreDependencies.add(submodule.getSelf()); | ||
submodule.getSubmodulesThatAreDependencies(); | ||
} | ||
return subModulesThatAreDependencies; | ||
} | ||
|
||
/** | ||
* This is delegated to {@link Model#equals(Object)}. | ||
*/ | ||
@Override | ||
public boolean equals(Object obj) { | ||
if (this == obj) { | ||
return true; | ||
} | ||
if (obj == null || getClass() != obj.getClass()) { | ||
return false; | ||
} | ||
MavenModule that = (MavenModule) obj; | ||
return self.equals(that.self); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return self.hashCode(); | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
...main/java/io/github/algomaster99/terminator/commons/maven/MavenModuleDependencyGraph.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package io.github.algomaster99.terminator.commons.maven; | ||
|
||
import java.io.FileReader; | ||
import java.io.IOException; | ||
import java.nio.file.Path; | ||
import java.util.List; | ||
import org.apache.maven.model.Model; | ||
import org.apache.maven.model.io.xpp3.MavenXpp3Reader; | ||
import org.codehaus.plexus.util.xml.pull.XmlPullParserException; | ||
|
||
public class MavenModuleDependencyGraph { | ||
// create dependency graph of maven modules | ||
|
||
public static MavenModule createMavenModuleGraph(Path projectRoot) throws IOException, XmlPullParserException { | ||
Path rootPom = projectRoot.resolve("pom.xml"); | ||
MavenXpp3Reader reader = new MavenXpp3Reader(); | ||
Model rootModel = reader.read(new FileReader(rootPom.toFile())); | ||
|
||
MavenModule root = new MavenModule(rootModel, projectRoot.toAbsolutePath(), null); | ||
|
||
List<String> submodules = rootModel.getModules(); | ||
|
||
for (String module : submodules) { | ||
Path modulePath = projectRoot.resolve(module); | ||
MavenXpp3Reader moduleReader = new MavenXpp3Reader(); | ||
Model moduleModel = moduleReader.read( | ||
new FileReader(modulePath.resolve("pom.xml").toFile())); | ||
MavenModule mavenModule = new MavenModule(moduleModel, modulePath, root); | ||
if (moduleModel.getModules() != null) { | ||
List<String> childModules = moduleModel.getModules(); | ||
List<MavenModule> children = childModules.stream() | ||
.map(childModule -> { | ||
try { | ||
return createMavenModuleGraph(modulePath.resolve(childModule)); | ||
} catch (IOException | XmlPullParserException e) { | ||
throw new RuntimeException(e); | ||
} | ||
}) | ||
.toList(); | ||
children.forEach(mavenModule::addSubmodule); | ||
} | ||
root.addSubmodule(mavenModule); | ||
} | ||
return root; | ||
} | ||
} |
114 changes: 114 additions & 0 deletions
114
.../java/io/github/algomaster99/terminator/commons/maven/MavenModuleDependencyGraphTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package io.github.algomaster99.terminator.commons.maven; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Path; | ||
import java.util.List; | ||
import java.util.Set; | ||
import org.codehaus.plexus.util.xml.pull.XmlPullParserException; | ||
import org.junit.jupiter.api.Test; | ||
|
||
public class MavenModuleDependencyGraphTest { | ||
@Test | ||
void createMavenModuleGraph_singleModule() throws XmlPullParserException, IOException { | ||
// arrange | ||
Path projectRoot = | ||
Path.of("src/test/resources/maven-modules/single-module").toAbsolutePath(); | ||
|
||
// act | ||
MavenModule root = MavenModuleDependencyGraph.createMavenModuleGraph(projectRoot); | ||
|
||
// assert | ||
assertThat(root).isNotNull(); | ||
|
||
assertThat(root.getSelf().getArtifactId()).isEqualTo("single-module"); | ||
assertThat(root.getFileSystemPath()).isEqualTo(projectRoot); | ||
assertThat(root.getSubmodules()).hasSize(0); | ||
} | ||
|
||
@Test | ||
void createMavenModuleGraph_multiModule_singleDepth() throws XmlPullParserException, IOException { | ||
// arrange | ||
Path projectRoot = Path.of("src/test/resources/maven-modules/multi-module-single-depth") | ||
.toAbsolutePath(); | ||
|
||
// act | ||
MavenModule root = MavenModuleDependencyGraph.createMavenModuleGraph(projectRoot); | ||
|
||
// assert | ||
assertThat(root).isNotNull(); | ||
|
||
assertThat(root.getSelf().getArtifactId()).isEqualTo("multi-module-single-depth"); | ||
assertThat(root.getFileSystemPath()).isEqualTo(projectRoot); | ||
assertThat(root.getSubmodules()).hasSize(2); | ||
|
||
MavenModule module1 = root.getSubmodules().get(0); | ||
MavenModule module2 = root.getSubmodules().get(1); | ||
|
||
assertThat(Set.of(module1.getSelf().getArtifactId(), module2.getSelf().getArtifactId())) | ||
.contains("m1", "m2"); | ||
assertThat(Set.of(module1.getFileSystemPath(), module2.getFileSystemPath())) | ||
.contains(projectRoot.resolve("m1"), projectRoot.resolve("m2")); | ||
|
||
assertThat(module1.getSubmodules()).hasSize(0); | ||
assertThat(module2.getSubmodules()).hasSize(0); | ||
} | ||
|
||
@Test | ||
void createMavenModuleGraph_multiModule_multipleDepth() throws XmlPullParserException, IOException { | ||
// arrange | ||
Path projectRoot = Path.of("src/test/resources/maven-modules/multi-module-multiple-depth") | ||
.toAbsolutePath(); | ||
|
||
// act | ||
MavenModule root = MavenModuleDependencyGraph.createMavenModuleGraph(projectRoot); | ||
|
||
// assert | ||
assertThat(root).isNotNull(); | ||
|
||
assertThat(root.getSelf().getArtifactId()).isEqualTo("multi-module-multiple-depth"); | ||
assertThat(root.getFileSystemPath()).isEqualTo(projectRoot); | ||
assertThat(root.getSubmodules()).hasSize(2); | ||
|
||
MavenModule module1 = root.getSubmodules().get(0); | ||
MavenModule module2 = root.getSubmodules().get(1); | ||
|
||
assertThat(Set.of(module1.getSelf().getArtifactId(), module2.getSelf().getArtifactId())) | ||
.contains("m1", "m2"); | ||
assertThat(Set.of(module1.getFileSystemPath(), module2.getFileSystemPath())) | ||
.contains(projectRoot.resolve("m1"), projectRoot.resolve("m2")); | ||
|
||
assertThat(module1.getSubmodules()).hasSize(0); | ||
assertThat(module2.getSubmodules()).hasSize(1); | ||
|
||
MavenModule module21 = module2.getSubmodules().get(0); | ||
|
||
assertThat(module21.getSelf().getArtifactId()).isEqualTo("m21"); | ||
assertThat(module21.getFileSystemPath()) | ||
.isEqualTo(projectRoot.resolve("m2").resolve("m21")); | ||
assertThat(module21.getSubmodules()).hasSize(0); | ||
} | ||
|
||
@Test | ||
void createMavenModuleGraph_submoduleAsDependency() throws XmlPullParserException, IOException { | ||
// arrange | ||
Path projectRoot = Path.of("src/test/resources/maven-modules/submodule-as-dependency") | ||
.toAbsolutePath(); | ||
|
||
// act | ||
MavenModule root = MavenModuleDependencyGraph.createMavenModuleGraph(projectRoot); | ||
|
||
// assert | ||
assertThat(root).isNotNull(); | ||
|
||
assertThat(root.getSelf().getArtifactId()).isEqualTo("submodule-as-dependency"); | ||
assertThat(root.getFileSystemPath()).isEqualTo(projectRoot); | ||
assertThat(root.getSubmodules()).hasSize(2); | ||
|
||
MavenModule module1 = root.getSubmodules().get(0); | ||
MavenModule module2 = root.getSubmodules().get(1); | ||
|
||
assertThat(module1.getSubmodulesThatAreDependencies()).isEqualTo(List.of(module2.getSelf())); | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
terminator-commons/src/test/resources/maven-modules/multi-module-multiple-depth/m1/pom.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>org.example</groupId> | ||
<artifactId>multi-module-multiple-depth</artifactId> | ||
<version>10.4.2</version> | ||
</parent> | ||
|
||
<artifactId>m1</artifactId> | ||
<packaging>jar</packaging> | ||
<version>10.4.2</version> | ||
</project> |
14 changes: 14 additions & 0 deletions
14
...nator-commons/src/test/resources/maven-modules/multi-module-multiple-depth/m2/m21/pom.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>org.example</groupId> | ||
<artifactId>m2</artifactId> | ||
<version>10.4.2</version> | ||
</parent> | ||
|
||
<artifactId>m21</artifactId> | ||
<packaging>jar</packaging> | ||
<version>10.4.2</version> | ||
</project> |
18 changes: 18 additions & 0 deletions
18
terminator-commons/src/test/resources/maven-modules/multi-module-multiple-depth/m2/pom.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>org.example</groupId> | ||
<artifactId>multi-module-multiple-depth</artifactId> | ||
<version>10.4.2</version> | ||
</parent> | ||
|
||
<artifactId>m2</artifactId> | ||
<packaging>pom</packaging> | ||
<version>10.4.2</version> | ||
|
||
<modules> | ||
<module>m21</module> | ||
</modules> | ||
</project> |
14 changes: 14 additions & 0 deletions
14
terminator-commons/src/test/resources/maven-modules/multi-module-multiple-depth/pom.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>org.example</groupId> | ||
<artifactId>multi-module-multiple-depth</artifactId> | ||
<packaging>pom</packaging> | ||
<version>10.4.2</version> | ||
|
||
<modules> | ||
<module>m1</module> | ||
<module>m2</module> | ||
</modules> | ||
</project> |
14 changes: 14 additions & 0 deletions
14
terminator-commons/src/test/resources/maven-modules/multi-module-single-depth/m1/pom.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>org.example</groupId> | ||
<artifactId>multi-module-single-depth</artifactId> | ||
<version>10.4.2</version> | ||
</parent> | ||
|
||
<artifactId>m1</artifactId> | ||
<packaging>jar</packaging> | ||
<version>10.4.2</version> | ||
</project> |
14 changes: 14 additions & 0 deletions
14
terminator-commons/src/test/resources/maven-modules/multi-module-single-depth/m2/pom.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>org.example</groupId> | ||
<artifactId>multi-module-single-depth</artifactId> | ||
<version>10.4.2</version> | ||
</parent> | ||
|
||
<artifactId>m2</artifactId> | ||
<packaging>jar</packaging> | ||
<version>10.4.2</version> | ||
</project> |
14 changes: 14 additions & 0 deletions
14
terminator-commons/src/test/resources/maven-modules/multi-module-single-depth/pom.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>org.example</groupId> | ||
<artifactId>multi-module-single-depth</artifactId> | ||
<packaging>pom</packaging> | ||
<version>10.4.2</version> | ||
|
||
<modules> | ||
<module>m1</module> | ||
<module>m2</module> | ||
</modules> | ||
</project> |
Oops, something went wrong.