Kotlin | Create tree structure from a list of metadata
A few weeks ago, I had a project where I wanted to display a menu with different entries and hierarchies on a web-app. The picture above is the end result of this tree structure. To do this, first of all, I needed to create the menu structure itself. The only input that I got at this point was a list of metadata, that had these attributes:
Most of you will already recognize, that we have a hierarchy in it, which will be quite important for the future steps. This hierarchy is just a string, divided with forward-slashes.
Defining a class diagram
First of all, we need to create a node class, which is responsible for the structure itself, since it links to instances of itself in the children map. This way we can go through the whole hierarchy and add as many hierarchy levels as there are needed.
If the current node is really just a node and not a leaf-node, hence it is not the last one in the hierarchy, then, it does not need to contain metadata. Only the leaf nodes do require the metadata.
Every node needs to have a title. The leaf nodes take the title from the metadata title and the hierarchy nodes take the title from the hierarchy step they are currently on.
The root class inherits from the node class. It can be created without any constructor parameters and can create a complete hierarchy tree with just one function call. There is also a possibility to add only one child to an existing tree.
Implementing the Node class
getItemOrAddChild function just creates a new leaf or hierarchy node based on the hierarchyList’s size.
createLeafNode function just adds a new node to the current nodes children.
createHierarchyNode function takes the current hierarchy and adds the underlying hierarchy as a new node to the current one. If the children of it already contain the currentHierarchy, it will just take it and go through the same process again, until there is no hierarchy anymore.
All these functions will return a Node, but the most important one of them is the
getItemOrAddChild function, since it is the one that will be called from the root Class.
Implementing the Root class
As you can see, the Root class is implementing the Node class and therefore has access to all the attributes and functions that the Nodes have.
createHierarchyList function will just split up the hierarchy string into a mutable list. This list gets used on the
addChildToTree function. It simply calls the
getItemOrAddChild function that we defined in the Node class earlier and returns the root object.
createWholeTree function just calls the
addChildToTree function for every item in its list and sorts it alphabetically based on its title. In the end, it will also return the root object itself.
If we run this function with a list of metadata, it will create the whole tree for us and return the root object to us. In this root object, we can see all the leaf nodes on first level and also the hierarchy nodes with deeper hierarchies.
To display our generated data structure, check out my follow-up article about displaying tree structures with Thymeleaf.
What went good?
I guess the thing that went best, was when I already had the Node class defined and only needed to access its functions with the root class. The root class was pretty easy to implement and since it was not referencing itself the whole time, it was also pretty easy to debug and test.
What needs improvement?
At the beginning I had some problems with the understanding of this whole principle of self referencing classes. I did not know this compound pattern and first needed to read into it to fully understand it. Next time a have such a problem, I will first search for a fitting build pattern and implement it directly this way. It would have saved me lots of time trying to come up with my own custom solutions.