Kotlin offers significant improvements to Java. But coming from a Java background, it can sometimes get tricky. I was looking at browsing folders and I found Kotlin’s method walkTopDown:
fun File.walkTopDown(): FileTreeWalk
I used it recursively to find pom.xml files.
fun findPomFiles(
folder: File,
pomTrees: MutableList,
includeDependencyManagement: Boolean,
searchSubFolders: Boolean
): MutableList {
// find pom file in the current folder
val pomFile = folder.listFiles().find { it.name == "pom.xml" }
pomFile?.let {
println("Found pom file in $folder")
pomTrees.add(PomNode(pomParser.deserialize(it), includeDependencyManagement))
}
if (searchSubFolders) {
folder.walkTopDown() // HERE IS THE METHOD
.filter { it.isDirectory && it != folder && it.name != "target" && it.name != "src"} // ignore src and target folders for performance
.forEach {
findPomFiles(it, pomTrees, includeDependencyManagement, searchSubFolders)
}
}
return pomTrees
}
I also found the function onEnter of FileTreeWalk that can be used to avoid exploring useless branches.
fun onEnter(function: (File) -> Boolean): FileTreeWalk
folder.walkTopDown() // HERE IS THE METHOD
.onEnter { it.name != "target" && it.name != "src"}
However, the result was not what I expected. The program was looking at the folders multiple times. I realize walkTopDown is not made for exploring folders recursively.
What it actually does is to browse folders and for each folder, we can do whatever we need to.
So two possibilities:
A. keeping the code recursive and using listFiles() from File – like we used to do it in Java
if (searchSubFolders) {
folder.listFiles()
.filter { it.isDirectory && it != folder && it.name != "target" && it.name != "src"} // ignore src and target folders for performance
.forEach {
findPomFiles(it, pomTrees, includeDependencyManagement, searchSubFolders)
}
}
B. using walkTopDown
fun findPomFiles(
folder: File,
pomTrees: MutableList,
includeDependencyManagement: Boolean,
searchSubFolders: Boolean
): MutableList {
// find pom file in the current folder
addPomNode(folder, includeDependencyManagement)?.let { pomTrees.add(it) }
if (searchSubFolders) {
folder.walkTopDown()
.onEnter { it.name != "target" && it.name != "src" }
.forEach {
addPomNode(it, includeDependencyManagement)?.let { pomNode -> pomTrees.add(pomNode) }
}
}
return pomTrees
}
fun addPomNode(folder: File, includeDependencyManagement: Boolean): PomNode? {
val pomFile = folder.listFiles()?.find { it.name == "pom.xml" }
pomFile?.let {
println("Found pom file in $folder")
return PomNode(pomParser.deserialize(it), includeDependencyManagement)
}
return null
}