/** * Copyright (C) 2011 JTalks.org Team * This library 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 library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package org.jtalks.jcommune.model.dto; import org.jtalks.common.model.entity.Group; import org.jtalks.common.model.permissions.JtalksPermission; import org.jtalks.common.model.permissions.ProfilePermission; import java.util.*; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentSkipListMap; /** * Container for permissions and related to it access lists. Contains several methods to simple management of access * lists. * * @author Vyacheslav Zhivaev */ public class GroupsPermissions { private final ConcurrentMap<JtalksPermission, GroupAccessList> accessListMap = new ConcurrentSkipListMap<>(new PermissionComparator()); /** * Constructs {@link GroupsPermissions} with empty internal state. Use add* methods to fill this map. */ public GroupsPermissions() { // NOOP } /** * Constructs {@link GroupsPermissions} with given list of permissions and empty restrict\allow data. * * @param permissions to be added to the access lists */ public <T extends JtalksPermission> GroupsPermissions(List<T> permissions) { for (JtalksPermission permission : permissions) { accessListMap.put(permission, new GroupAccessList()); } } /** * Constructs {@link GroupsPermissions} with predefined values to be added to the access lists. * * @param accessLists values to initialize this container */ public GroupsPermissions(Map<JtalksPermission, GroupAccessList> accessLists) { accessListMap.putAll(accessLists); } /** * Adds new permission to the access list. * * @param permission to be added * @param toAllow group to allow * @param toRestrict group to restrict * @return {@code this} instance for providing fluent interface */ public GroupsPermissions add(JtalksPermission permission, Group toAllow, Group toRestrict) { accessListMap.putIfAbsent(permission, new GroupAccessList()); accessListMap.get(permission).addAllowed(toAllow).addRestricted(toRestrict); return this; } /** * Adds new 'allowed' permission. * * @param permission the permission to add * @param group the group for which permission added * @return {@code this} instance for providing fluent interface */ public GroupsPermissions addAllowed(JtalksPermission permission, Group group) { return add(permission, group, null); } /** * Adds new 'restricted' permission. * * @param permission the permission to add * @param group the group for which permission added * @return {@code this} instance for providing fluent interface */ public GroupsPermissions addRestricted(JtalksPermission permission, Group group) { return add(permission, null, group); } /** * Based on 'allow' flag, add 'allow' permission (if it's {@code true}), or 'restrict' permission on it * (otherwise). * * @param permission the permission to add * @param group the group for which permission added * @param allow {@code true} if allowance is needed, {@code false} otherwise * @return {@code this} instance for providing fluent interface */ public GroupsPermissions add(JtalksPermission permission, Group group, boolean allow) { return (allow) ? addAllowed(permission, group) : addRestricted(permission, group); } /** * For given permission, retrieves list of {@link org.jtalks.common.model.entity.Group} that are allowed. * * @param permission the permission to get for * @return list of {@link org.jtalks.common.model.entity.Group}, list instance is UNMODIFIABLE */ public List<Group> getAllowed(JtalksPermission permission) { GroupAccessList groupAccessList = accessListMap.get(permission); if (groupAccessList == null) { return Collections.unmodifiableList(new ArrayList<Group>()); } else { return Collections.unmodifiableList(groupAccessList.getAllowed()); } } /** * For given permission, retrieves list of {@link org.jtalks.common.model.entity.Group} that are restricted. * * @param permission the permission to get for * @return list of {@link org.jtalks.common.model.entity.Group}, list instance is UNMODIFIABLE */ public List<Group> getRestricted(JtalksPermission permission) { GroupAccessList groupAccessList = accessListMap.get(permission); if (groupAccessList == null) { return Collections.unmodifiableList(new ArrayList<Group>()); } else { return Collections.unmodifiableList(groupAccessList.getRestricted()); } } /** * For given permission, retrieves list of {@link org.jtalks.common.model.entity.Group} that are allowed or restricted relative to parameter {@code * allowed}. * * @param permission the permission to get for * @param allowed the flag indicating which type of groups needed: allowed (if {@code true}) or restricted * @return list of {@link org.jtalks.common.model.entity.Group}, list instance is UNMODIFIABLE */ public List<Group> get(JtalksPermission permission, boolean allowed) { return (allowed) ? getAllowed(permission) : getRestricted(permission); } /** * Gets all permissions defined in this map. * * @return set of all permissions defined in this map, set instance is UNMODIFIABLE */ public Set<JtalksPermission> getPermissions() { return Collections.unmodifiableSet(accessListMap.keySet()); } /** * Access List Map is a internal object - map where key is the permission of type <T extends JtalksPermission> and * the value is GroupAccessList object containing groups which have this permission ("allowed") * or do not have ("restricted"). * This method returns copy of the Access List Map where keys are the same like in the original map. * Values (GroupAccessList) are newly created objects based on data from the values in the original map * but they were created with unmodified list with data from the original allowed and restricted group lists. * @return copy of the Access List Map */ public Map<JtalksPermission, GroupAccessList> getAccessListMap() { Map<JtalksPermission, GroupAccessList > accessListMapCopy = new HashMap <>(); Set<JtalksPermission> permissions = getPermissions(); for (JtalksPermission permission : permissions) { GroupAccessList groupAccessList = new GroupAccessList(); groupAccessList.setAllowed(getAllowed(permission)); groupAccessList.setRestricted(getRestricted(permission)); accessListMapCopy.put(permission, groupAccessList); } return accessListMapCopy; } /** * Gets groups permissions with all the profile permissions but no groups restricted or allowed. * * @return groups permissions with all the profile permissions but no groups restricted or allowed */ public static GroupsPermissions profilePermissions() { return new GroupsPermissions(ProfilePermission.getAllAsList()); } public static class PermissionComparator implements Comparator<JtalksPermission> { @Override public int compare(JtalksPermission o1, JtalksPermission o2) { return o1.getMask() - o2.getMask(); } } }