Converting List to Enumeration in Kotlin
August 15th, 2018
There’s a bunch of helper extension methods that the Kotlin standard library provides for working with collections. However, it would seem that at the present moment <a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/java.util.-enumeration/index.html">java.util.Enumeration</a>
has been left a bit behind. Here is a simple extension method to convert any List
to a matching Enumeration
:
/**
* Extension function for converting a {@link List} to an {@link Enumeration}
*/
fun <T> List<T>.toEnumeration(): Enumeration<T> {
return object : Enumeration<T> {
var count = 0
override fun hasMoreElements(): Boolean {
return this.count < size
}
override fun nextElement(): T {
if (this.count < size) {
return get(this.count++)
}
throw NoSuchElementException("List enumeration asked for more elements than present")
}
}
}
And here is how you can use it to expose the local file system to the JTree
component. First, we create a custom implementation of the TreeNode
interface:
data class FileTreeNode(val file: File?, val children: Array<File>, val nodeParent: TreeNode?) : TreeNode {
constructor(file: File, parent: TreeNode) : this(file, file.listFiles() ?: arrayOf(), parent)
constructor(children: Array<File>) : this(null, children, null)
init {
children.sortWith(compareBy { it.name.toLowerCase() })
}
override fun children(): Enumeration<FileTreeNode> {
return children.map { FileTreeNode(it, this) }.toEnumeration()
}
override fun getAllowsChildren(): Boolean {
return true
}
override fun getChildAt(childIndex: Int): TreeNode {
return FileTreeNode(children[childIndex], this)
}
override fun getChildCount(): Int {
return children.size
}
override fun getIndex(node: TreeNode): Int {
val ftn = node as FileTreeNode
return children.indexOfFirst { it == ftn.file }
}
override fun getParent(): TreeNode? {
return this.nodeParent
}
override fun isLeaf(): Boolean {
val isNotFolder = (this.file != null) && (this.file.isFile)
return this.childCount == 0 && isNotFolder
}
}
Note a few language shortcuts that make the code more concise than its Java counterparts:
- Since
File.listFiles()
can returnnull
, we wrap that call with a simple Elvis operator:file.listFiles() ?: arrayOf()
. - The initializer block sorts the
File
children in place by name. - To return tree node enumeration in
children()
, we first map eachFile
child to the correspondingFileTreeNode
and then use our extension function to convert the resultingList
toEnumeration
. - Looking up the index of the specific node is done with the existing extension
indexOfFirst
function from the standard library.
Now all is left to do is to create our JTree
:
val tree = JTree(FileTreeNode(File.listRoots()))
tree.rootVisible = false