diff --git a/pom.xml b/pom.xml
index 1f88371..cb50222 100644
--- a/pom.xml
+++ b/pom.xml
@@ -57,6 +57,19 @@
slf4j-simple
1.7.30
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.7.0
+ test
+
+
+ org.assertj
+ assertj-core
+ 3.17.2
+ test
+
diff --git a/src/main/kotlin/starter/Models.kt b/src/main/kotlin/starter/Models.kt
index ae9e410..b554376 100644
--- a/src/main/kotlin/starter/Models.kt
+++ b/src/main/kotlin/starter/Models.kt
@@ -12,13 +12,12 @@ data class Dependency(
val name: String,
val groupId: String,
val artifactId: String,
- val version: String,
+ val version: Version,
val default: Boolean,
val category: Category,
val scope: Scope,
val logger: String?,
- val repository: String?,
- val versionKey: String,
+ val repository: Repository?,
)
data class Repository(val name: String, val url: String)
@@ -30,7 +29,7 @@ data class Project(
val basePackage: String,
val inputs: List,
val dependencies: List,
- val repositories: List,
+ val repositories: Collection,
)
data class Version(val name: String, val value: String)
diff --git a/src/main/kotlin/starter/config/Config.kt b/src/main/kotlin/starter/config/Config.kt
index a5f96e6..e7aa557 100644
--- a/src/main/kotlin/starter/config/Config.kt
+++ b/src/main/kotlin/starter/config/Config.kt
@@ -8,7 +8,6 @@ import com.electronwill.nightconfig.core.Config as NightConfig
data class StarterConfig(
val dependencies: List,
val inputs: List,
- val repositories: List,
)
class Config {
@@ -23,22 +22,29 @@ class Config {
@Suppress("UNCHECKED_CAST")
val versions = cfg.get("versions").valueMap() as Map
+ val repositories = cfg.configMap("repositories")
+ .map { (name, values) ->
+ Repository(name, values["url"])
+ }
+
val dependencies = cfg.configMap("dependencies")
.map { (name, values) ->
val versionKey: String = values["version"] ?: name
val version = versions[versionKey] ?: error("Missing version for $name")
+ val repositoryName: String? = values["repository"]
+ val repo = repositoryName?.let { repoName -> repositories.find { it.name == repoName } }
+
Dependency(
- name,
- values["groupId"],
- values["artifactId"],
- version,
- values.getOrElse("default", false),
- values.getEnumOrElse("category", Category.Other),
- values.getEnumOrElse("scope", Scope.Compile),
- values["logger"],
- values["repository"],
- versionKey
+ name = name,
+ groupId = values["groupId"],
+ artifactId = values["artifactId"],
+ version = Version(versionKey, version),
+ default = values.getOrElse("default", false),
+ category = values.getEnumOrElse("category", Category.Other),
+ scope = values.getEnumOrElse("scope", Scope.Compile),
+ logger = values["logger"],
+ repository = repo,
)
}
@@ -47,11 +53,6 @@ class Config {
Input(name, values["display"], values["default"])
}
- val repositories = cfg.configMap("repositories")
- .map { (name, values) ->
- Repository(name, values["url"])
- }
-
- return StarterConfig(dependencies, inputs, repositories)
+ return StarterConfig(dependencies, inputs)
}
}
diff --git a/src/main/kotlin/starter/modules/PebbleModule.kt b/src/main/kotlin/starter/modules/PebbleModule.kt
index c8cc9f4..aa2950d 100644
--- a/src/main/kotlin/starter/modules/PebbleModule.kt
+++ b/src/main/kotlin/starter/modules/PebbleModule.kt
@@ -37,7 +37,7 @@ class DepAsXmlPebbleFunction : PebbleFunction {
|${startTag("dependency")}
| ${tag("groupId", dep.groupId)}
| ${tag("artifactId", dep.artifactId)}
- | ${tag("version", dep.version)}
+ | ${tag("version", dep.version.value)}
|${endTag("dependency")}
""".trimMargin()
diff --git a/src/main/kotlin/starter/routes/ZipRouteSupplier.kt b/src/main/kotlin/starter/routes/ZipRouteSupplier.kt
index 2d5f35e..5978b54 100644
--- a/src/main/kotlin/starter/routes/ZipRouteSupplier.kt
+++ b/src/main/kotlin/starter/routes/ZipRouteSupplier.kt
@@ -38,9 +38,7 @@ class ZipRouteSupplier(
if (basePackage.contains("/") || basePackage.contains("..")) {
Response.badRequest()
} else {
- val repositories = conf.repositories
- .filter { repo -> repo.name in deps.mapNotNull { it.repository } }
-
+ val repositories = deps.mapNotNull { it.repository }.toSet()
val project = Project(projectName, basePackage, inputs, deps, repositories)
val outputStream = projectZip.createZip(project)
diff --git a/src/main/kotlin/starter/templates/PomTemplate.kt b/src/main/kotlin/starter/templates/PomTemplate.kt
index a0f56ca..b33a444 100644
--- a/src/main/kotlin/starter/templates/PomTemplate.kt
+++ b/src/main/kotlin/starter/templates/PomTemplate.kt
@@ -14,7 +14,7 @@ class PomTemplate(private val engine: PebbleEngine) : Template {
"dependencies" to project.dependencies.sortedBy { it.scope },
"repositories" to project.repositories,
"kotlinxSerialization" to project.dependencies.any { it.name == "kotlinx-serialization" },
- "versions" to project.dependencies.map { Version(name = it.versionKey, value = it.version) }.toSet()
+ "versions" to project.dependencies.map { it.version }.toSet()
)
project.inputs.forEach {
diff --git a/src/main/resources/starter/pom/@dependencies.twig b/src/main/resources/starter/pom/@dependencies.twig
index cbc8ebe..12478ef 100644
--- a/src/main/resources/starter/pom/@dependencies.twig
+++ b/src/main/resources/starter/pom/@dependencies.twig
@@ -8,7 +8,7 @@
{{ dep.groupId }}
{{ dep.artifactId }}
- {{ "${" }}{{ dep.versionKey }}{{ ".version}" }}
+ {{ "${" }}{{ dep.version.name }}{{ ".version}" }}
{% if dep.scope == "Test" %}
test
{% endif %}
diff --git a/src/test/kotlin/starter/templates/PomTemplateTest.kt b/src/test/kotlin/starter/templates/PomTemplateTest.kt
new file mode 100644
index 0000000..88fbd8b
--- /dev/null
+++ b/src/test/kotlin/starter/templates/PomTemplateTest.kt
@@ -0,0 +1,121 @@
+package starter.templates
+
+import org.assertj.core.api.Assertions.assertThat
+import org.intellij.lang.annotations.Language
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.TestInstance
+import org.koin.dsl.koinApplication
+import org.w3c.dom.Node
+import org.w3c.dom.NodeList
+import starter.Project
+import starter.config.StarterConfig
+import starter.modules.mainModule
+import starter.modules.pebbleModule
+import starter.modules.templateModule
+import javax.xml.parsers.DocumentBuilderFactory
+import javax.xml.xpath.XPathConstants
+import javax.xml.xpath.XPathFactory
+
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+internal class PomTemplateTest {
+
+ private val koin = koinApplication {
+ modules(mainModule, pebbleModule, templateModule)
+ }.koin
+
+ private val pomTemplate = koin.get()
+ private val conf = koin.get()
+
+ private val project = Project(
+ name = "Test",
+ basePackage = "org.test",
+ inputs = conf.inputs,
+ dependencies = conf.dependencies,
+ repositories = conf.dependencies.mapNotNull { it.repository }.toSet()
+ )
+
+ private val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
+ private val xPath = XPathFactory.newInstance().newXPath()
+
+ // region xml utils
+ private fun String.extract(expression: String): String {
+ val doc = docBuilder.parse(this.byteInputStream())
+ xPath.compile(expression).evaluate(doc, XPathConstants.NODESET)
+ return xPath.compile(expression).evaluate(doc)
+ }
+
+ private fun String.extractAll(expression: String, mapper: (Node) -> T): List {
+ val doc = docBuilder.parse(this.byteInputStream())
+ val res = xPath.compile(expression).evaluate(doc, XPathConstants.NODESET) as NodeList
+ return res.asList().map(mapper)
+ }
+
+ private fun NodeList.asList(): List = (0 until length).map { item(it) }
+ // endregion
+
+ @Test
+ fun javaVersion() {
+ val xml = pomTemplate.render(project)
+ assertThat(xml.extract("/project/properties/java.version"))
+ .isEqualTo(project.inputs.find { it.name == "javaVersion" }?.value)
+
+ println(xml)
+ }
+
+ @Test
+ fun dependencies() {
+ val xml = pomTemplate.render(project)
+
+ val deps = xml.extractAll("/project/dependencies/dependency") {
+ val map = it.childNodes.asList()
+ .filter { it.nodeType == Node.ELEMENT_NODE }
+ .associate { it.nodeName to it.firstChild.nodeValue }
+
+ Triple(map["groupId"]!!, map["artifactId"]!!, map["version"]!!)
+
+ }.filterNot { it.second == "kotlin-stdlib-jdk8" }
+
+ println(deps.joinToString("\n"))
+
+ val expectedDependencies = project.dependencies
+ .map { Triple(it.groupId, it.artifactId, "\${" + it.version.name + ".version}") }
+
+ assertThat(expectedDependencies).containsExactlyInAnyOrderElementsOf(deps)
+ }
+
+ @Test
+ fun versions() {
+ val xml = pomTemplate.render(project)
+
+ val versions = xml.extractAll("/project/properties") {
+ it.childNodes.asList()
+ .filter { it.nodeType == Node.ELEMENT_NODE }
+ .filter { it.nodeName.endsWith(".version") }
+ .filterNot { it.nodeName in listOf("java.version", "kotlin.version") }
+ .associate { it.nodeName.substringBefore(".version") to it.firstChild.nodeValue }
+ }.first()
+
+ val expected = project.dependencies.associate { it.version.name to it.version.value }
+
+ assertThat(versions).containsExactlyInAnyOrderEntriesOf(expected)
+
+ println(versions)
+ }
+
+ @Test
+ fun kotlinxSerialization() {
+ val xml = pomTemplate.render(project)
+
+ @Language("XPath")
+ val kotlinMavenPlugin = "/project/build/plugins/plugin[artifactId='kotlin-maven-plugin']"
+
+ val kotlinxPlugin = "$kotlinMavenPlugin/configuration/compilerPlugins/plugin"
+ assertThat(xml.extract(kotlinxPlugin))
+ .isEqualTo("kotlinx-serialization")
+
+ val kotlinxPluginDep = "$kotlinMavenPlugin/dependencies/dependency/artifactId"
+ assertThat(xml.extract(kotlinxPluginDep))
+ .isEqualTo("kotlin-maven-serialization")
+
+ }
+}