/*
* Copyright (C) 2010 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.mop.user;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import org.exoplatform.portal.config.UserPortalConfigService;
import org.exoplatform.portal.config.model.PortalConfig;
import org.exoplatform.portal.mop.SiteKey;
import org.exoplatform.portal.mop.SiteType;
import org.exoplatform.portal.mop.navigation.GenericScope;
import org.exoplatform.portal.mop.navigation.NavigationContext;
import org.exoplatform.portal.mop.navigation.NavigationServiceException;
import org.exoplatform.portal.mop.navigation.NodeChangeListener;
import org.exoplatform.portal.mop.navigation.NodeContext;
import org.exoplatform.portal.mop.navigation.NodeState;
import org.exoplatform.portal.mop.navigation.Scope;
import org.exoplatform.portal.mop.navigation.VisitMode;
import org.exoplatform.services.organization.Group;
/**
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
* @version $Revision$
*/
public class UserPortalImpl implements UserPortal
{
/** . */
final UserPortalConfigService service;
/** . */
private final PortalConfig portal;
/** . */
final UserPortalContext context;
/** . */
final String userName;
/** . */
private List<UserNavigation> navigations;
/** . */
private final String portalName;
/** . */
private final Locale portalLocale;
public UserPortalImpl(
UserPortalConfigService service,
String portalName,
PortalConfig portal,
String userName,
UserPortalContext context)
{
if (context == null)
{
throw new NullPointerException("No null context argument allowed");
}
//
String locale = portal.getLocale();
//
this.portalLocale = locale != null ? new Locale(locale) : null;
this.service = service;
this.portalName = portalName;
this.portal = portal;
this.userName = userName;
this.context = context;
this.navigations = null;
}
public Locale getLocale()
{
return portalLocale;
}
/**
* Returns an immutable sorted list of the valid navigations related to the user.
*
* @return the navigations
* @throws UserPortalException any user portal exception
*/
public List<UserNavigation> getNavigations() throws UserPortalException, NavigationServiceException
{
if (navigations == null)
{
List<UserNavigation> navigations = new ArrayList<UserNavigation>(userName == null ? 1 : 10);
NavigationContext portalNav = service.getNavigationService().loadNavigation(new SiteKey(SiteType.PORTAL, portalName));
if (portalNav != null && portalNav.getState() != null)
{
navigations.add(new UserNavigation(this, portalNav, service.getUserACL().hasEditPermission(portal)));
}
//
if (userName != null)
{
// Add user nav if any
NavigationContext userNavigation = service.getNavigationService().loadNavigation(SiteKey.user(userName));
if (userNavigation != null && userNavigation.getState() != null)
{
navigations.add(new UserNavigation(this, userNavigation, true));
}
//
Collection<?> groups;
try
{
if (service.getUserACL().getSuperUser().equals(userName))
{
groups = service.getOrganizationService().getGroupHandler().getAllGroups();
}
else
{
groups = service.getOrganizationService().getGroupHandler().findGroupsOfUser(userName);
}
}
catch (Exception e)
{
throw new UserPortalException("Could not retrieve groups", e);
}
//
for (Object group : groups)
{
Group m = (Group)group;
String groupId = m.getId().trim();
if (!groupId.equals(service.getUserACL().getGuestsGroup()))
{
NavigationContext groupNavigation = service.getNavigationService().loadNavigation(SiteKey.group(groupId));
if (groupNavigation != null && groupNavigation.getState() != null)
{
navigations.add(new UserNavigation(
this,
groupNavigation,
service.getUserACL().hasEditPermissionOnNavigation(groupNavigation.getKey())));
}
}
}
// Sort the list finally
Collections.sort(navigations, new Comparator<UserNavigation>()
{
public int compare(UserNavigation nav1, UserNavigation nav2)
{
return nav1.getPriority() - nav2.getPriority();
}
});
}
//
this.navigations = Collections.unmodifiableList(navigations);
}
return navigations;
}
public UserNavigation getNavigation(SiteKey key) throws NullPointerException, UserPortalException, NavigationServiceException
{
if (key == null)
{
throw new NullPointerException("No null key accepted");
}
for (UserNavigation navigation : getNavigations())
{
if (navigation.getKey().equals(key))
{
return navigation;
}
}
//
return null;
}
public void refresh()
{
navigations = null;
}
public UserNode getNode(
UserNavigation userNavigation,
Scope scope,
UserNodeFilterConfig filterConfig,
NodeChangeListener<UserNode> listener) throws NullPointerException, UserPortalException, NavigationServiceException
{
UserNodeContext context = new UserNodeContext(userNavigation, filterConfig);
NodeContext<UserNode> nodeContext = service.getNavigationService().loadNode(context, userNavigation.navigation, scope, new UserNodeListener(listener));
if (nodeContext != null)
{
return nodeContext.getNode().filter();
}
else
{
return null;
}
}
public void updateNode(UserNode node, Scope scope, NodeChangeListener<UserNode> listener)
throws NullPointerException, IllegalArgumentException, UserPortalException, NavigationServiceException
{
if (node == null)
{
throw new NullPointerException("No null node accepted");
}
service.getNavigationService().updateNode(node.context, scope, new UserNodeListener(listener));
node.filter();
}
public void rebaseNode(UserNode node, Scope scope, NodeChangeListener<UserNode> listener)
throws NullPointerException, IllegalArgumentException, UserPortalException, NavigationServiceException
{
if (node == null)
{
throw new NullPointerException("No null node accepted");
}
service.getNavigationService().rebaseNode(node.context, scope, new UserNodeListener(listener));
node.filter();
}
public void saveNode(UserNode node, NodeChangeListener<UserNode> listener) throws NullPointerException, UserPortalException, NavigationServiceException
{
if (node == null)
{
throw new NullPointerException("No null node accepted");
}
service.getNavigationService().saveNode(node.context, new UserNodeListener(listener));
node.filter();
}
/**
* Note : the scope implementation is not stateless but we don't care in this case.
*/
private class MatchingScope extends GenericScope.Branch.Visitor implements Scope
{
final UserNavigation userNavigation;
final UserNodeFilterConfig filterConfig;
final String[] match;
int score;
String id;
UserNode userNode;
MatchingScope(UserNavigation userNavigation, UserNodeFilterConfig filterConfig, String[] match)
{
this.userNavigation = userNavigation;
this.filterConfig = filterConfig;
this.match = match;
}
public Visitor get()
{
return this;
}
@Override
protected int getSize()
{
return match.length;
}
@Override
protected String getName(int index)
{
return match[index];
}
@Override
protected Visitor getFederated()
{
return Scope.CHILDREN.get();
}
void resolve() throws NavigationServiceException
{
UserNodeContext context = new UserNodeContext(userNavigation, filterConfig);
NodeContext<UserNode> nodeContext = service.getNavigationService().loadNode(context, userNavigation.navigation, this, null);
if (context != null)
{
if (score > 0)
{
userNode = nodeContext.getNode().filter().find(id);
}
}
}
public VisitMode enter(int depth, String id, String name, NodeState state)
{
VisitMode vm = super.enter(depth, id, name, state);
if (depth == 0)
{
score = 0;
MatchingScope.this.id = null;
}
else
{
if (vm == VisitMode.ALL_CHILDREN)
{
MatchingScope.this.id = id;
score++;
}
}
return vm;
}
}
public UserNode getDefaultPath(UserNodeFilterConfig filterConfig) throws UserPortalException, NavigationServiceException
{
for (UserNavigation userNavigation : getNavigations())
{
UserNode node = getDefaultPath(userNavigation, filterConfig);
if (node != null)
{
return node;
}
}
//
return null;
}
public UserNode getDefaultPath(UserNavigation userNavigation, UserNodeFilterConfig filterConfig) throws UserPortalException, NavigationServiceException
{
NavigationContext navigation = userNavigation.navigation;
if (navigation.getState() != null)
{
UserNodeContext context = new UserNodeContext(userNavigation, filterConfig);
NodeContext<UserNode> nodeContext = service.getNavigationService().loadNode(context, navigation, Scope.CHILDREN, null);
if (nodeContext != null)
{
UserNode root = nodeContext.getNode().filter();
for (UserNode node : root.getChildren())
{
return node;
}
}
}
return null;
}
public UserNode resolvePath(UserNodeFilterConfig filterConfig, String path)
throws NullPointerException, UserPortalException, NavigationServiceException
{
if (path == null)
{
throw new NullPointerException("No null path accepted");
}
// Parse path
String[] segments = Utils.parsePath(path);
// Find the first navigation available or return null
if (segments == null)
{
return getDefaultPath(filterConfig);
}
// Get navigations
List<UserNavigation> navigations = getNavigations();
//
MatchingScope best = null;
for (UserNavigation navigation : navigations)
{
MatchingScope scope = new MatchingScope(navigation, filterConfig, segments);
scope.resolve();
if (scope.score == segments.length)
{
best = scope;
break;
}
else
{
if (best == null)
{
best = scope;
}
else
{
if (scope.score > best.score)
{
best = scope;
}
}
}
}
//
if (best != null && best.score > 0)
{
return best.userNode;
}
else
{
return getDefaultPath(null);
}
}
public UserNode resolvePath(UserNavigation navigation, UserNodeFilterConfig filterConfig, String path)
throws NullPointerException, UserPortalException, NavigationServiceException
{
if (navigation == null)
{
throw new NullPointerException("No null navigation accepted");
}
if (path == null)
{
throw new NullPointerException("No null path accepted");
}
//
String[] segments = Utils.parsePath(path);
//
if (segments == null)
{
return null;
}
//
MatchingScope scope = new MatchingScope(navigation, filterConfig, segments);
scope.resolve();
//
if (scope.score > 0)
{
return scope.userNode;
}
else
{
return null;
}
}
}