/******************************************************************************
* JBoss, a division of Red Hat *
* Copyright 2011, Red Hat Middleware, LLC, and individual *
* contributors as indicated by the @authors tag. See the *
* copyright.txt in the distribution for a full listing of *
* individual contributors. *
* *
* This is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2.1 of *
* the License, or (at your option) any later version. *
* *
* This software is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this software; if not, write to the Free *
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
* 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
******************************************************************************/
package org.gatein.portlet.responsive.navigation;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletPreferences;
import javax.portlet.PortletRequest;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import javax.portlet.PortletRequestDispatcher;
import org.gatein.api.PortalRequest;
import org.gatein.api.navigation.Navigation;
import org.gatein.api.navigation.Node;
import org.gatein.api.navigation.NodePath;
import org.gatein.api.navigation.Nodes;
/**
* Responsive version of the navigation portlet implemented using the GateIn navigation API.
*
* @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
* @version $Revision$
*/
public class NavigationPortlet extends GenericPortlet {
private String EMPTY_CATEGORY_PROPERTY_NAME = "ShowEmptyCategories";
/**
* Method responsible for the VIEW mode of the navigation portlet.
* This method passes the navigationRootNodeBean as an attribute to the JSP page.
* The navigationRootNodeBean is the root node of the navigation and contains main menu (top-menu) elements (Home and Sitemap
* by default) as children nodes.
*
* @see javax.portlet.GenericPortlet#doView(javax.portlet.RenderRequest, javax.portlet.RenderResponse)
* @param request the portlet request
* @param response the render response
* @throws PortletException if the portlet cannot fulfilling the request
* @throws IOException if the streaming causes an I/O problem
*/
@Override
protected void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
PortalRequest portalRequest = PortalRequest.getInstance();
Navigation navigation = PortalRequest.getInstance().getNavigation();
// Diving two levels so the information about children count of children nodes is available
Node rootNode = navigation.getRootNode(Nodes.visitNodes(2)).filter().showDefault();
// The root navigation bean contains the top-menu elements (Home and Sitemap by default) as its direct children nodes.
NavigationNodeBean navigationRootNodeBean = new NavigationNodeBean(rootNode);
boolean showEmptyCategory = getShowEmptyCategory(request);
if (!showEmptyCategory) {
navigationRootNodeBean.setEmptyCategory(isEmptyCategory(rootNode));
}
/* Setting the 1st node to be active when accesing the root node "/" */
boolean isRootNode = portalRequest.getNodePath().equals(NodePath.root());
List<NavigationNodeBean> rootNodeChildrenList = getChildren(rootNode, isRootNode, showEmptyCategory);
navigationRootNodeBean.setChildren(rootNodeChildrenList);
request.setAttribute("showEmptyCategory", showEmptyCategory);
request.setAttribute("navigationRootNode", navigationRootNodeBean);
PortletRequestDispatcher prd = getPortletContext().getRequestDispatcher("/jsp/navigation.jsp");
prd.include(request, response);
}
/**
* The serveResource method is used for handling AJAX requests. It's used for the rendering of sub-menus. Anytime
* users clicks on the menu item, the URI parameter is passed to the serveResource method. This parameter contains the URI
* of the node which sub-menu is about to be rendered.
*
* @see javax.portlet.GenericPortlet#serveResource(javax.portlet.ResourceRequest, javax.portlet.ResourceResponse)
*
* @param request the resource request
* @param response the resource response
* @throws PortletException if the portlet has problems fulfilling the rendering request
* @throws IOException if the streaming causes an I/O problem
*/
@Override
public void serveResource(ResourceRequest request, ResourceResponse response) throws PortletException, IOException {
Navigation navigation = PortalRequest.getInstance().getNavigation();
String chosenNodeURI = request.getParameter("uri");
Node chosenNode = navigation.getNode(NodePath.fromString(chosenNodeURI), Nodes.visitNodes(2)).filter().showDefault();
NavigationNodeBean chosenNodeBean = new NavigationNodeBean(chosenNode);
boolean showEmptyCategory = getShowEmptyCategory(request);
List<NavigationNodeBean> nodeChildrenList = getChildren(chosenNode, false, showEmptyCategory);
if (!showEmptyCategory) {
chosenNodeBean.setEmptyCategory(isEmptyCategory(chosenNode));
}
chosenNodeBean.setChildren(nodeChildrenList);
request.setAttribute("showEmptyCategory", showEmptyCategory);
request.setAttribute("parentNode", chosenNodeBean);
PortletRequestDispatcher prd = getPortletContext().getRequestDispatcher("/jsp/node.jsp");
prd.include(request, response);
}
private boolean isEmptyCategory(Node n){
if (n.getPageId() != null) {
return false;
} else {
Navigation navigation = PortalRequest.getInstance().getNavigation();
Iterator<Node> iterator = n.iterator();
while (iterator.hasNext()){
Node child = navigation.getNode(iterator.next().getNodePath(), Nodes.visitNodes(1)).filter().showDefault();
if (!isEmptyCategory(child)){
return false;
}
}
}
return true;
}
private List<NavigationNodeBean> getChildren(Node node, boolean firstActive, boolean showEmptyCategory) {
List<NavigationNodeBean> nodes = new ArrayList<NavigationNodeBean>();
boolean firstActiveSet = false;
Iterator<Node> nodeIterator = node.iterator();
while (nodeIterator.hasNext()) {
Node childNode = nodeIterator.next();
NavigationNodeBean childNodeBean = new NavigationNodeBean(childNode);
if (firstActive && !firstActiveSet){
childNodeBean.setActive(true);
firstActiveSet = true;
}
if (!showEmptyCategory) {
childNodeBean.setEmptyCategory(isEmptyCategory(childNode));
}
nodes.add(childNodeBean);
}
return nodes;
}
private boolean getShowEmptyCategory(PortletRequest request){
PortletPreferences portletPreferences = request.getPreferences();
String showEmptyCategoryStringValue = portletPreferences.getValue(EMPTY_CATEGORY_PROPERTY_NAME, "false");
return Boolean.valueOf(showEmptyCategoryStringValue);
}
}