Navigation in its simplest form can be seen visually by visiting jquery navigation page. You have a NavItem that contains a list of NavItems to represent fly out 1:M relationship.
When you add requirements such as filter nodes based on a business rule, apply custom parameters to the link and maintain a flexible structure to add nodes it takes us beyond just having a static JSON or HTML hosted on a CDN that applications consume. There are various options such as pulling items from a database but since these items rarely change it isn't necessary to make another database read. Another approach as described above would to store items in a properties file but since it is complex structure it lead to a static JSON and an associated java structure.
Thinking through this decision. Storing navigation as JSON should allow flexibility when adding a node with no code change, no database request, migration, etc. If went with an approach where we tied all navigation together with an Enum, code would change and the flexibility of adding subnodes (fan out) might be more difficult. In addition, taking advantage of some jackson magic which we will show below, all nodes should get populated recursively down the tree. From a maintenance perspective JSON is a natural readable format so most folks should pick this up fairly quickly. If there is concern with format, ie. missing a comma or curly brace, you could add a unit test to validate and use json online formatters to help.
The associated java object:
Base navigation can be considered navigation shown to all users. There are several ways to read a properties file and two primary ways to convert json to a java object. Reading in the base we will use jackson to convert a json array to a java arraylist. By default jackson will walk JSON tree recursively setting the java object based on the JSON structure. In combination with the
NavItems above we can transform the json to java object.
One requirement is to apply a custom rules to the navigation element. For instance, lets say a client wants the link text changes from 'Exercises' to 'My Exercises'. Again, we could throw all these into a DB, do some out joins and bam! - we would have what we need. Since there is a limited number of these rules to save a network hop we threw these into a JSON structure as well. Interesting thing is that for a particular key, you could have multiple nodes you want updated. A very natural data structure is guava multimap where we can transform json to a multimap. By adding jackson-datatype-guava module and the java code snippet below we were able to perform that mapping.
Other design decisions considered:
- Instead of starting with a base of navigation elements, why not build up instead of filtering away.
- If you are working with JSON, why not use JSONpath and filter custom elements that way
- Instead of working with a java object, why not just work with JSON nodes and walk the tree
This might be easier using another language but with the constraint of java and environment this was chosen - we will see how it goes! Next time before you settle on using a properties file consider using JSON to store your complex data structures.