As soon as you claim that the Item identifier is locally unique for the menu you are creating, and when children are added to each item update, a link to the parent?
This will allow you to expand the subtree of what is focused in the URL, the interface (assuming html) will dynamically navigate through the menu representing various categories to the user.
The local uniqueness of the elements can be confirmed using the factory template by adding a new class called "Menu" and making children in the Menu mutable.
class Menu { final HashMap<String, Item> items = new HashMap<String, Item>(); final List<Item> root = new ArrayList<Item>(); public Item createItem(String title, String id, Item parent) { if (items.containsKey(id)) { raise SomeRuntimeException(); } final Item item = new Item(title, id, parent, this); if (parent == null) { root.add(item); } else { parent.addChild(item); } items.put(id, item); } public Item createItem(String title, String id, Item parent) { return addItem(title, id, null); } }
Some changes to the Item class.
class Item { private final Menu menu; private final Item parent; private final List<Item> children = new ArrayList<Item>(); public Item(String name, String resourceId, Menu menu, Item parent) { ... this.menu = menu; this.parent = parent; } public Item addChild(String name, String resourceId) { final Item item = this.menu.createItem(name, resourceId, this); this.children.add(item); return item; } }
Now I have sacrificed some immutability, because I believe that this template is much more expressive in error handling than providing a set of nested lists.
Creating an immutable menu
If immutability is a big problem, you can always change the menu and item to interfaces and implement immutable options that copy the original menu and item, and then add the copyImmutable method to the Menu class, which will create the requested structure.
class MenuBuilder { Menu copyImmutable() { ImmutableList<Item> root = ... ImmutableMap<String, Item> items = ... return new ImmutableMenu(root, items) } }
This means that you recursively do the same for all elements.
Menu Creation Algorithm
- Search for an item from a menu class (eliminating potential errors)
- Each parent iterates into this menu and pathTaken entry.
- When the root node user is reached, save it as activeRoot .
- Iterate all the root nodes according to the menu and visualize them. When you hit activeRoot, recurse all the children recursively, but enter only those that are registered in pathTaken .
I hope this describes a solution that can inspire you to solve your problem!