Chapter 5. Navigation

5.1. Retrieving Navigation Nodes

When retrieving navigation nodes it is possible to either retrieve the root node, or a specific node in the hierarchy. It is also possible to control which if any of the children are loaded.

Example 5.1. Basic Navigation Portlet

This example shows a very simple navigation portlet that displays the top level of entries in the navigation menu.

public void doView(RenderRequest request, RenderResponse response) throws IOException {
    PrintWriter pw = response.getWriter();
    Navigation navigation = PortalRequest.getInstance().getNavigation();

    pw.print("<ul>");
    for (Node n : navigation.getRootNode(Nodes.visitChildren())) {
        pw.printf("<li><a href='%s'>%s</a></li>", n.getURI(), n.getDisplayName());
    }
    pw.print("</ul>");
}

Example 5.2. Retrieve a Specific Node

This example demonstrates how to retrieve a specific node in the tree by specifying the NodePath to the node.

Node node = navigation.getNode(NodePath.path("home"));

Note

When a node is retrieved, it actually represents a tree of nodes and all operations (for example, save and refresh) act on that entire tree. For example, if a root node with two child nodes is retrieved, and changes are made to the both child nodes but only one node is saved, the other child will be saved automatically because the save operation acts on the entire node tree.

5.1.1. NodeVisitor

It is important to limit how many levels of navigation nodes are retrieved, especially where there is a large number of nodes. This is controlled by using either one of the built in NodeVisitor from the Nodes class, or by implementing your own NodeVisitor . The Nodes class contains the following visitors:
  • visitAll - loads all nodes
  • visitChildren - loads the immediate children
  • visitNone - loads only the node
  • visitNodes(int) - loads a specified depth of descendants

Example 5.3. Retrieve a Node Using visitNodes

This example retrieves the root node and two levels of nodes.

Node rootNode = navigation.getRootNode(Nodes.visitNodes(2));

Example 5.4. isChildrenLoaded versus visitChildren Method

To correctly confirm whether the child nodes are loaded, use the isChildrenLoaded method instead of visitChildren.
This would return true:
Node rootNode = navigation.getRootNode(Nodes.visitChildren()).isChildrenLoaded()
This would return false:
Node rootNode = navigation.getRootNode(Nodes.visitNone()).isChildrenLoaded()

5.1.2. Filtering Navigation Nodes

Nodes support a filtering mechanism which simplifies displaying nodes that have specific properties.

Example 5.5. Display User-visible Nodes When Creating a Navigation Portlet

This example displays visible nodes where the user has access to view the page.

Node filtered = node.filter().showDefault();
There are a number of methods available to control what nodes are displayed, and they all start with show . For example, showDefault is an abbreviation for showVisible().showHasAccess(PortalRequest.getInstance().getUser())

Example 5.6. Custom Filter

This example uses a custom filter to only display nodes with a display name that starts with "A".

Node filtered = root.filter().show(new Filter<Node>() {
    public boolean accept(Node node) {
        return node.getDisplayName().startsWith("A");
    }
});

5.2. Creating a Navigation Node

Creating a node uses the following workflow:
  1. Retrieve the parent node you want to add the node to.
  2. Invoke the addChild method on the parent node.
  3. Set the configuration for the node (such as the display name and the page it should link to).
  4. Save it using saveNode on Navigation.

Example 5.7. Creating a Navigation Node

This example creates a node as a child of the home node.
The node is not visible (or persisted) until saveNode is invoked.

Node home = navigation.getNode(NodePath.path("home"));
Node child = home.addChild("mynode");
child.setDisplayName("My Node");
child.setPageId(new PageId("classic", "mypage"));
navigation.saveNode(home);

5.2.1. Navigation Node Visibility

Nodes can be visible, hidden or only visible at a specified publication date. By default a new node is visible.
A node can be hidden with node.setVisibility(false), or only shown until a specific date with node.setVisibility(PublicationDate.endingOn(date)). It is also possible to set a starting date, or set both a starting date and a finishing date.
Changes to node visibility are not shown until saveNode is invoked on the Portal.

5.2.2. Localization

The display name for a node supports localization.

Example 5.8. Setting and English and French Node

This example sets the display name for a node in English and French.

LocalizedString localizedString = node.getDisplayNames();
localizedString.setLocalizedValue(Locale.ENGLISH, "My node");
localizedString.setLocalizedValue(Locale.FRENCH, "Mon noeud");
node.setDisplayNames(localizedString);

navigation.saveNode(node);

5.3. Deleting a Navigation Node

A node is deleted by removing it from the parent node.

Example 5.9. Deleting a Node

This example removes the child with the name mynode.
The node is not removed until saveNode is invoked.

node.removeChild("mynode");
navigation.saveNode(node);

5.4. Moving a Navigation Node

A node can be moved to a different parent, or it can be moved to a different index in the same parent. When moving to a different parent the new parent is required to be in the same tree.

Example 5.10. Move Child Nodes Between Parent and Index Nodes

Move a node from one parent to another.

root.getNode("parent1", "child").moveTo(root.getNode("parent2"));
navigation.saveNode(root);
Move a node to a different index in the same parent.

root.getNode("parent", "child").moveTo(0);
navigation.saveNode(root);
The changes are not visible (or persisted) until saveNode is invoked.
A more convenient way to sort children for a parent is to use the sort method on the parent.

Example 5.11. Sorting by Display Name

This example demonstrates how to sort the children of the root node by their display names.
The changes are not visible (or persisted) until saveNode is invoked.

root.sort(new Comparator<Node>() {
    public int compare(Node o1, Node o2) {
        return o1.getDisplayName().compareTo(o2.getDisplayName());
    }
});
navigation.saveNode(root);