/**
* Copyright (C) 2009 eXo Platform SAS.
*
* 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.exoplatform.portal.webui.navigation;
import org.exoplatform.container.ExoContainer;
import org.exoplatform.portal.config.UserACL;
import org.exoplatform.portal.config.UserPortalConfigService;
import org.exoplatform.portal.config.model.PageNavigation;
import org.exoplatform.portal.config.model.PageNode;
import org.exoplatform.portal.config.model.PortalConfig;
import org.exoplatform.portal.mop.Visibility;
import org.exoplatform.services.resources.ResourceBundleManager;
import org.exoplatform.webui.application.WebuiRequestContext;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
/**
* Created by The eXo Platform SARL
* Author : Nhu Dinh Thuan
* nhudinhthuan@exoplatform.com
* Jun 27, 2007
*/
public class PageNavigationUtils
{
public static void removeNode(List<PageNode> list, String uri)
{
if (list == null)
return;
for (PageNode pageNode : list)
{
if (pageNode.getUri().equalsIgnoreCase(uri))
{
list.remove(pageNode);
return;
}
}
}
/**
* This method returns a pair of PageNode, one is the PageNode specified by the uri,
* another is its parent. Value return is 2-element array
*
* 1. The element indexed 1 is the page node specified by the uri
*
* 2. The element indexed 0 is its parent
*
* @deprecated Returning 2-element array would makes it difficult to understand, handle the code.
* Method searchParentChildPairByUri should be used instead.
*
* @param node
* @param uri
* @return
*/
@Deprecated
public static PageNode[] searchPageNodesByUri(PageNode node, String uri)
{
if (node.getUri().equals(uri))
return new PageNode[]{null, node};
if (node.getChildren() == null)
return null;
List<PageNode> children = node.getChildren();
for (PageNode ele : children)
{
PageNode[] returnNodes = searchPageNodesByUri(ele, uri);
if (returnNodes != null)
{
if (returnNodes[0] == null)
returnNodes[0] = node;
return returnNodes;
}
}
return null;
}
@Deprecated
public static PageNode[] searchPageNodesByUri(PageNavigation nav, String uri)
{
if (nav.getNodes() == null)
return null;
List<PageNode> nodes = nav.getNodes();
for (PageNode ele : nodes)
{
PageNode[] returnNodes = searchPageNodesByUri(ele, uri);
if (returnNodes != null)
return returnNodes;
}
return null;
}
/**
* This method returns a pair of a node matching the parsed uri and the parent of this node.
*
* @param nav
* @param uri
* @return
*/
public static ParentChildPair searchParentChildPairByUri(PageNavigation nav, String uri)
{
List<PageNode> nodes = nav.getNodes();
if(nodes == null)
{
return null;
}
for(PageNode ele : nodes)
{
ParentChildPair parentChildPair = searchParentChildPairUnderNode(ele, uri);
if(parentChildPair != null)
{
return parentChildPair;
}
}
return null;
}
//TODO: Split the uri and use optimzed method <code>searchParentChildPairByPath</code>
public static ParentChildPair searchParentChildPairUnderNode(PageNode rootNode, String uri)
{
if(uri.equals(rootNode.getUri()))
{
return new ParentChildPair(null, rootNode);
}
List<PageNode> nodes = rootNode.getNodes();
if(nodes == null)
{
return null;
}
for(PageNode node : nodes)
{
ParentChildPair parentChildPair = searchParentChildPairUnderNode(node, uri);
if(parentChildPair != null)
{
if(parentChildPair.getParentNode() == null)
{
parentChildPair.setParentNode(rootNode);
}
return parentChildPair;
}
}
return null;
}
/**
* Search a pair of page node (specified by the path) and its parent
*
* @param rootNode
* @param path
* @return
*/
public static ParentChildPair searchParentChildPairByPath(PageNode rootNode, String[] path)
{
if(path.length == 0)
{
throw new IllegalArgumentException("The input path must have unzero length");
}
if(!rootNode.getName().equals(path[0]))
{
return null;
}
else
{
if(path.length == 1)
{
return new ParentChildPair(null, rootNode);
}
PageNode tempNode = rootNode;
PageNode parentNode = null;
PageNode childNode = null;
for(int i = 1; i< path.length; i++)
{
childNode = tempNode.getChild(path[i]);
if(childNode == null)
{
return null;
}
else
{
parentNode = tempNode;
}
}
return new ParentChildPair(parentNode, childNode);
}
}
public static PageNode searchPageNodeByUri(PageNode node, String uri)
{
if (node.getUri().equals(uri))
return node;
if (node.getChildren() == null)
return null;
List<PageNode> children = node.getChildren();
for (PageNode ele : children)
{
PageNode returnNode = searchPageNodeByUri(ele, uri);
if (returnNode != null)
return returnNode;
}
return null;
}
public static PageNode searchPageNodeByUri(PageNavigation nav, String uri)
{
if (nav.getNodes() == null)
return null;
List<PageNode> nodes = nav.getNodes();
for (PageNode ele : nodes)
{
PageNode returnNode = searchPageNodeByUri(ele, uri);
if (returnNode != null)
return returnNode;
}
return null;
}
public static Object searchParentNode(PageNavigation nav, String uri)
{
if (nav.getNodes() == null)
return null;
int last = uri.lastIndexOf("/");
String parentUri = "";
if (last > -1)
parentUri = uri.substring(0, uri.lastIndexOf("/"));
for (PageNode ele : nav.getNodes())
{
if (ele.getUri().equals(uri))
return nav;
}
if (parentUri.equals(""))
return null;
return searchPageNodeByUri(nav, parentUri);
}
// Still keep this method to have compatibility with legacy code
public static PageNavigation filter(PageNavigation nav, String userName) throws Exception
{
return filterNavigation(nav, userName, false, false);
}
/**
*
* @param nav
* @param userName
* @param acceptNonDisplayedNode
* @param acceptNodeWithoutPage
* @return
* @throws Exception
*/
public static PageNavigation filterNavigation(PageNavigation nav, String userName, boolean acceptNonDisplayedNode, boolean acceptNodeWithoutPage) throws Exception
{
PageNavigation filter = nav.clone();
filter.setNodes(new ArrayList<PageNode>());
WebuiRequestContext context = WebuiRequestContext.getCurrentInstance();
ExoContainer container = context.getApplication().getApplicationServiceContainer();
UserPortalConfigService userService =
(UserPortalConfigService)container.getComponentInstanceOfType(UserPortalConfigService.class);
UserACL userACL = (UserACL)container.getComponentInstanceOfType(UserACL.class);
for (PageNode node : nav.getNodes())
{
PageNode newNode = filterNodeNavigation(node, userName, acceptNonDisplayedNode, acceptNodeWithoutPage, userService, userACL);
if (newNode != null)
filter.addNode(newNode);
}
return filter;
}
/**
* use {@link #filterNavigation(PageNavigation, String, boolean, boolean)}
*
* @param nav
* @param userName
* @param acceptNonDisplayedNode
* @return
* @throws Exception
*/
@Deprecated
public static PageNavigation filterNavigation(PageNavigation nav, String userName, boolean acceptNonDisplayedNode) throws Exception
{
return filterNavigation(nav, userName, acceptNonDisplayedNode, true);
}
/**
* Use {@link #filterNodeNavigation(PageNode, String, boolean, boolean, UserPortalConfigService, UserACL)}
* @param startNode
* @param userName
* @param acceptNonDisplayedNode
* @param userService
* @param userACL
* @return
* @throws Exception
*/
@Deprecated
private static PageNode filterNodeNavigation(PageNode startNode, String userName, boolean acceptNonDisplayedNode,
UserPortalConfigService userService, UserACL userACL) throws Exception {
PageNode cloneStartNode = filterNodeNavigation(startNode, userName, acceptNonDisplayedNode, false, userService, userACL);
return cloneStartNode;
}
/**
* PageNode won't be processed in following cases:
*
* Case 1: Node 's visibility is SYSTEM and the user is not superuser or he is superuser but acceptNonDisplayNode = false
*
* Case 2: Node 's visibility is not SYSTEM but the node is not display and the acceptNonDisplayedNode = false
*
* Case 3: Node has non null pageReference but the associated Page does not exist and not accept this node is without page
*
*
* @param startNode
* @param userName
* @param acceptNonDisplayedNode
* @param acceptNodeWithoutPage
* @param userService
* @param userACL
* @return
* @throws Exception
*/
private static PageNode filterNodeNavigation(PageNode startNode, String userName, boolean acceptNonDisplayedNode, boolean acceptNodeWithoutPage,
UserPortalConfigService userService, UserACL userACL) throws Exception
{
Visibility nodeVisibility = startNode.getVisibility();
String pageReference = startNode.getPageReference();
boolean doNothingCase_1 = nodeVisibility == Visibility.SYSTEM && (!userACL.getSuperUser().equals(userName) || !acceptNonDisplayedNode);
boolean doNothingCase_2 = nodeVisibility != Visibility.SYSTEM && !startNode.isDisplay() && !acceptNonDisplayedNode;
boolean doNothingCase_3 = (pageReference != null) && (userService.getPage(pageReference, userName) == null) && !acceptNodeWithoutPage;
if (doNothingCase_1 || doNothingCase_2 || doNothingCase_3)
{
return null;
}
PageNode cloneStartNode = startNode.clone();
ArrayList<PageNode> filteredChildren = new ArrayList<PageNode>();
List<PageNode> children = startNode.getChildren();
if (children != null)
{
for (PageNode child : children)
{
PageNode filteredChildNode = filterNodeNavigation(child, userName, acceptNonDisplayedNode, acceptNodeWithoutPage, userService, userACL);
if (filteredChildNode != null)
{
filteredChildren.add(filteredChildNode);
}
}
}
//If are only accepting displayed nodes and If the node has no child and it does not point to any Page, then null is return
if (!acceptNonDisplayedNode && filteredChildren.size() == 0 && cloneStartNode.getPageReference() == null)
{
return null;
}
cloneStartNode.setChildren(filteredChildren);
return cloneStartNode;
}
public static PageNode filter(PageNode node, String userName, boolean acceptNonDisplayedNode) throws Exception
{
WebuiRequestContext context = WebuiRequestContext.getCurrentInstance();
ExoContainer container = context.getApplication().getApplicationServiceContainer();
UserPortalConfigService userService =
(UserPortalConfigService)container.getComponentInstanceOfType(UserPortalConfigService.class);
UserACL userACL = (UserACL)container.getComponentInstanceOfType(UserACL.class);
return filterNodeNavigation(node, userName, acceptNonDisplayedNode, userService, userACL);
}
public static void localizePageNavigation(PageNavigation nav, Locale locale, ResourceBundleManager i18nManager)
{
if (nav.getOwnerType().equals(PortalConfig.USER_TYPE))
return;
ResourceBundle res =
i18nManager.getNavigationResourceBundle(locale.getLanguage(), nav.getOwnerType(), nav.getOwnerId());
for (PageNode node : nav.getNodes())
{
resolveLabel(res, node);
}
}
private static void resolveLabel(ResourceBundle res, PageNode node)
{
node.setResolvedLabel(res);
if (node.getChildren() == null)
return;
for (PageNode childNode : node.getChildren())
{
resolveLabel(res, childNode);
}
}
public static PageNavigation findNavigationByID(List<PageNavigation> all_Navigations, int id)
{
for (PageNavigation nav : all_Navigations)
{
if (nav.getId() == id)
{
return nav;
}
}
return null;
}
public static void sortPageNavigation(List<PageNavigation> navigations)
{
Collections.sort(navigations, new PageNavigationComparator());
}
/**
*
* @author <a href="mailto:hoang281283@gmail.com">Minh Hoang TO</a>
* @version $Id$
*
*/
public static class PageNavigationComparator implements Comparator<PageNavigation>
{
public int compare(PageNavigation firstNav, PageNavigation secondNav)
{
int firstNavPriority = firstNav.getPriority();
int secondNavPriority = secondNav.getPriority();
if (firstNavPriority == secondNavPriority)
{
String firstNavId = firstNav.getOwnerId();
String secondNavId = secondNav.getOwnerId();
return firstNavId.compareTo(secondNavId);
}
else
{
if (firstNavPriority < secondNavPriority)
{
return -1;
}
else
{
return 1;
}
}
}
}
}