org.hyperic.hq.authz.server.session.RoleManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.hyperic.hq.authz.server.session.RoleManagerImpl.java

Source

/*
 * NOTE: This copyright does *not* cover user programs that use HQ
 * program services by normal system calls through the application
 * program interfaces provided as part of the Hyperic Plug-in Development
 * Kit or the Hyperic Client Development Kit - this is merely considered
 * normal use of the program, and does *not* fall under the heading of
 * "derived work".
 *
 * Copyright (C) [2004-2008], Hyperic, Inc.
 * This file is part of HQ.
 *
 * HQ is free software; you can redistribute it and/or modify
 * it under the terms version 2 of the GNU General Public License as
 * published by the Free Software Foundation. This program 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 General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA.
 */

package org.hyperic.hq.authz.server.session;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;

import javax.annotation.PostConstruct;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.hq.authz.server.session.events.group.GroupAddedToRolesZevent;
import org.hyperic.hq.authz.server.session.events.group.GroupRemovedFromRolesZevent;
import org.hyperic.hq.authz.server.session.events.role.GroupsAddedToRoleZevent;
import org.hyperic.hq.authz.server.session.events.role.GroupsRemovedFromRoleZevent;
import org.hyperic.hq.authz.server.session.events.role.RoleDeletedZevent;
import org.hyperic.hq.authz.server.session.events.role.RolePermissionsChangedZevent;
import org.hyperic.hq.authz.server.session.events.role.SubjectsAddedToRoleZevent;
import org.hyperic.hq.authz.server.session.events.role.SubjectsRemovedFromRoleZevent;
import org.hyperic.hq.authz.server.session.events.subject.SubjectAddedToRolesZevent;
import org.hyperic.hq.authz.server.session.events.subject.SubjectRemovedFromRolesZevent;
import org.hyperic.hq.authz.shared.AuthzConstants;
import org.hyperic.hq.authz.shared.AuthzDuplicateNameException;
import org.hyperic.hq.authz.shared.AuthzSubjectValue;
import org.hyperic.hq.authz.shared.PermissionException;
import org.hyperic.hq.authz.shared.PermissionManager;
import org.hyperic.hq.authz.shared.ResourceGroupValue;
import org.hyperic.hq.authz.shared.ResourceValue;
import org.hyperic.hq.authz.shared.RoleManager;
import org.hyperic.hq.authz.shared.RoleValue;
import org.hyperic.hq.authz.values.OwnedRoleValue;
import org.hyperic.hq.common.ApplicationException;
import org.hyperic.hq.common.NotFoundException;
import org.hyperic.hq.common.server.session.Calendar;
import org.hyperic.hq.common.shared.CalendarManager;
import org.hyperic.hq.zevents.ZeventManager;
import org.hyperic.util.pager.PageControl;
import org.hyperic.util.pager.PageList;
import org.hyperic.util.pager.Pager;
import org.hyperic.util.pager.SortAttribute;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * Manipulates Roles and Subjects associated with them. All arguments and return
 * values are value-objects.
 * 
 */
@Service
@Transactional
public class RoleManagerImpl implements RoleManager, ApplicationContextAware {

    private final Log log = LogFactory.getLog(RoleManagerImpl.class);
    private Pager subjectPager;
    private Pager rolePager;
    private Pager groupPager;
    private Pager ownedRolePager;
    private static final String SUBJECT_PAGER = "org.hyperic.hq.authz.server.session.PagerProcessor_subject";
    private static final String ROLE_PAGER = "org.hyperic.hq.authz.server.session.PagerProcessor_role";
    private static final String OWNEDROLE_PAGER = "org.hyperic.hq.authz.server.session.PagerProcessor_ownedRole";
    private static final String GROUP_PAGER = "org.hyperic.hq.authz.server.session.PagerProcessor_resourceGroup";
    private RoleCalendarDAO roleCalendarDAO;
    private OperationDAO operationDAO;
    private ResourceGroupDAO resourceGroupDAO;
    private ResourceTypeDAO resourceTypeDAO;
    private RoleDAO roleDAO;
    private AuthzSubjectDAO authzSubjectDAO;
    private ResourceDAO resourceDAO;
    private CalendarManager calendarManager;
    private PermissionManager permissionManager;
    private ApplicationContext applicationContext;
    private ZeventManager zeventManager;

    @Autowired
    public RoleManagerImpl(RoleCalendarDAO roleCalendarDAO, OperationDAO operationDAO,
            ResourceGroupDAO resourceGroupDAO, ResourceTypeDAO resourceTypeDAO, RoleDAO roleDAO,
            AuthzSubjectDAO authzSubjectDAO, ResourceDAO resourceDAO, CalendarManager calendarManager,
            PermissionManager permissionManager, ZeventManager zeventManager) {
        this.roleCalendarDAO = roleCalendarDAO;
        this.operationDAO = operationDAO;
        this.resourceGroupDAO = resourceGroupDAO;
        this.resourceTypeDAO = resourceTypeDAO;
        this.roleDAO = roleDAO;
        this.authzSubjectDAO = authzSubjectDAO;
        this.resourceDAO = resourceDAO;
        this.calendarManager = calendarManager;
        this.permissionManager = permissionManager;
        this.zeventManager = zeventManager;
    }

    @PostConstruct
    public void afterPropertiesSet() throws Exception {
        subjectPager = Pager.getPager(SUBJECT_PAGER);
        rolePager = Pager.getPager(ROLE_PAGER);
        groupPager = Pager.getPager(GROUP_PAGER);
        ownedRolePager = Pager.getPager(OWNEDROLE_PAGER);
    }

    /**
     * Validate that a role is ok to be added or updated
     * 
     * @param aRole
     * @throws AuthzDuplicateNameException
     */
    private void validateRole(RoleValue aRole) throws AuthzDuplicateNameException {
        Role role = roleDAO.findByName(aRole.getName());
        if (role != null) {
            throw new AuthzDuplicateNameException("A role named: " + aRole.getName() + " already exists");
        }

    }

    private Role lookupRole(RoleValue role) {
        return lookupRole(role.getId());
    }

    private Role lookupRole(Integer id) {
        return roleDAO.findById(id);
    }

    private ResourceGroup lookupGroup(Integer id) {
        return resourceGroupDAO.findById(id);
    }

    /**
    * 
    */
    @Transactional(readOnly = true)
    public boolean isRootRoleMember(AuthzSubject subject) {
        return getRootRoleIfMember(subject) != null;
    }

    @Transactional(readOnly = true)
    private Role getRootRoleIfMember(AuthzSubject subject) {
        // Look up the root role
        Role rootRole = roleDAO.findById(AuthzConstants.rootRoleId);
        // Look up the calling subject
        if (rootRole.getSubjects().contains(subject)) {
            return rootRole;
        }

        return null;
    }

    /**
     * Filter a collection of roleLocal objects to only include those viewable
     * by the specified user
     * 
     *
     */
    private Collection<Role> filterViewableRoles(AuthzSubject who, Collection<Role> roles)
            throws PermissionException {
        return filterViewableRoles(who, roles, null);
    }

    /**
     * Filter a collection of roleLocal object to only include those viewable by
     * the specific user and not in the list of ids passed in as excluded
     * 
     * @param who - the user
     * @param roles - the list of role locals
     * @param excludeIds - role ids which should be excluded from the return
     *        list
     * 
     * 
     */
    private Collection<Role> filterViewableRoles(AuthzSubject who, Collection<Role> roles, Integer[] excludeIds)
            throws PermissionException {
        try {

            permissionManager.check(who.getId(), resourceTypeDAO.findByName(AuthzConstants.roleResourceTypeName),
                    AuthzConstants.rootResourceId, AuthzConstants.roleOpViewRole);
        } catch (PermissionException e) {
            return new ArrayList<Role>(0);
        }

        List<Integer> excludeList = null;
        boolean hasExclude = (excludeIds != null && excludeIds.length > 0);
        if (hasExclude) {
            excludeList = Arrays.asList(excludeIds);
        }

        // Throw out the excludes
        for (Iterator<Role> i = roles.iterator(); i.hasNext();) {
            Role role = i.next();
            Integer pk = role.getId();
            if (hasExclude && excludeList.contains(pk)) {
                i.remove();
            }
        }
        return roles;
    }

    /**
     * Create a role.
     * 
     * @param whoami The current running user.
     * @param role The to be created.
     * @param operations Operations to associate with the new role. Use null if
     *        you want to associate operations later.
     * @param subjectIds Ids of subjects to add to the new role. Use null to add
     *        subjects later.
     * @param groupIds Ids of resource groups to add to the new role. Use null
     *        to add subjects later.
     * @return OwnedRoleValue for the role.
     * 
     * 
     * @throws PermissionException whoami may not perform createResource on the
     *         covalentAuthzRole ResourceType.
     * 
     */
    public Integer createOwnedRole(AuthzSubject whoami, RoleValue role, Operation[] operations,
            Integer[] subjectIds, Integer[] groupIds) throws AuthzDuplicateNameException, PermissionException {

        validateRole(role);

        permissionManager.check(whoami.getId(), resourceTypeDAO.findTypeResourceType(),
                AuthzConstants.rootResourceId, AuthzConstants.roleOpCreateRole);

        Role roleLocal = roleDAO.create(whoami, role);

        // Associated operations
        roleLocal.setOperations(toPojos(operations));

        if (subjectIds != null) {
            HashSet<AuthzSubject> sLocals = new HashSet<AuthzSubject>(subjectIds.length);
            for (int si = 0; si < subjectIds.length; si++) {
                sLocals.add(authzSubjectDAO.findById(subjectIds[si]));
            }
            // Associated subjects
            roleLocal.setSubjects(sLocals);
            zeventManager.enqueueEventAfterCommit(new SubjectsAddedToRoleZevent(roleLocal, sLocals));

        }

        if (groupIds != null) {
            HashSet<ResourceGroup> gLocals = new HashSet<ResourceGroup>(groupIds.length);
            for (int gi = 0; gi < groupIds.length; gi++) {
                gLocals.add(lookupGroup(groupIds[gi]));
            }
            // Associated resource groups
            roleLocal.setResourceGroups(gLocals);
            zeventManager.enqueueEventAfterCommit(new GroupsAddedToRoleZevent(roleLocal, groupIds));
        }
        applicationContext.publishEvent(new RoleCreatedEvent(roleLocal));
        return roleLocal.getId();
    }

    /**
     * Delete the specified role.
     * 
     * @param whoami The current running user.
     * @param rolePk The role to delete.
     * @throws ApplicationException Unable to delete the specified entity.
     * 
     */
    public void removeRole(AuthzSubject whoami, Integer rolePk) throws PermissionException, ApplicationException {
        // Don't delete the super user role
        if (rolePk.equals(AuthzConstants.rootRoleId)) {
            throw new ApplicationException("Superuser role cannot be removed");
        }

        Role role = roleDAO.findById(rolePk);

        permissionManager.check(whoami.getId(), role.getResource().getResourceType(), role.getId(),
                AuthzConstants.roleOpRemoveRole);
        applicationContext.publishEvent(new RoleDeleteRequestedEvent(role));
        final Collection<AuthzSubject> subjects = new ArrayList<AuthzSubject>(role.getSubjects());
        Collection<ResourceGroup> assignedResourceGroups = new ArrayList<ResourceGroup>(role.getResourceGroups());

        for (RoleCalendar c : role.getCalendars()) {
            removeCalendar(c);
        }
        roleDAO.remove(role);
        zeventManager.enqueueEventAfterCommit(new RoleDeletedZevent(role, assignedResourceGroups, subjects));
    }

    /**
     * Write the specified entity out to permanent storage.
     * 
     * @param whoami The current running user.
     * @param role The role to save.
     * @throws PermissionException whoami may not perform modifyRole on this
     *         role.
     * 
     */
    public void saveRole(AuthzSubject whoami, RoleValue role)
            throws AuthzDuplicateNameException, PermissionException {
        Role roleLocal = lookupRole(role);
        if (!roleLocal.getName().equals(role.getName())) {
            // Name has changed... check it
            validateRole(role);
        }

        permissionManager.check(whoami.getId(), roleLocal.getResource().getResourceType(), roleLocal.getId(),
                AuthzConstants.roleOpModifyRole);
        roleLocal.setRoleValue(role);
    }

    /**
     * Change the owner of the role.
     * 
     * @param whoami The current running user.
     * @param id The ID of the role to change
     * @param ownerVal The new owner of the role..
     * @throws PermissionException whoami may not perform modifyRole on this
     *         role.
     * 
     */
    public void changeOwner(AuthzSubject whoami, Integer id, AuthzSubject owner) throws PermissionException {
        Role roleLocal = lookupRole(id);

        permissionManager.check(whoami.getId(), roleLocal.getResource().getResourceType(), roleLocal.getId(),
                AuthzConstants.roleOpModifyRole);

        roleLocal.getResource().setOwner(owner);
    }

    /**
     * Associate operations with this role.
     * 
     * @param whoami The current running user.
     * @param role The role.
     * @param operations The operations to associate with the role.
     * 
     * @throws PermissionException whoami may not perform addOperation on this
     *         role.
     * 
     */
    public void addOperations(AuthzSubject whoami, Role role, Operation[] operations) throws PermissionException {
        Set<Operation> opLocals = toPojos(operations);

        // roleLocal.setWhoami(lookupSubject(whoami));
        Collection<Operation> orgOperations = role.getOperations();
        role.getOperations().addAll(opLocals);
        zeventManager.enqueueEventAfterCommit(new RolePermissionsChangedZevent(role, orgOperations));
    }

    /**
     * Disassociate all operations from this role.
     * 
     * @param whoami The current running user.
     * @param role The role.
     *
     * @throws PermissionException whoami may not perform removeOperation on
     *         this role.
     * 
     */
    public void removeAllOperations(AuthzSubject whoami, Role role) throws PermissionException {
        // roleLocal.setWhoami(lookupSubject(whoami));
        role.getOperations().clear();
    }

    /**
     * Set the operations for this role. To get the operations call
     * getOperations() on the value-object.
     * 
     * @param whoami The current running user.
     * @param id The ID of the role.
     * @param operations Operations to associate with this role.
     * 
     * @throws PermissionException whoami is not allowed to perform
     *         setOperations on this role.
     * 
     */
    public void setOperations(AuthzSubject whoami, Integer id, Operation[] operations) throws PermissionException {
        if (operations != null) {
            Role roleLocal = lookupRole(id);

            permissionManager.check(whoami.getId(), roleLocal.getResource().getResourceType(), roleLocal.getId(),
                    AuthzConstants.roleOpModifyRole);

            Set<Operation> opLocals = toPojos(operations);
            Collection<Operation> orgOperations = roleLocal.getOperations();
            roleLocal.setOperations(opLocals);
            zeventManager.enqueueEventAfterCommit(new RolePermissionsChangedZevent(roleLocal, orgOperations));
        }
    }

    /**
     * Associate ResourceGroups with this role.
     * 
     * @param whoami The current running user.
     * @param role This role.
     * @param gids The ids of the groups to associate with this role.
     * 
     * @throws PermissionException whoami is not allowed to perform
     *         addResourceGroup on this role.
     * 
     */
    public void addResourceGroups(AuthzSubject whoami, Integer rid, Integer[] gids) throws PermissionException {
        Role roleLocal = roleDAO.findById(rid);
        if (gids != null && gids.length > 0) {
            for (int i = 0; i < gids.length; i++) {
                ResourceGroup group = lookupGroup(gids[i]);
                group.addRole(roleLocal);
            }
            zeventManager.enqueueEventAfterCommit(new GroupsAddedToRoleZevent(roleLocal, gids));
        }
    }

    /**
     * Associate ResourceGroup with list of roles.
     * 
     * @param whoami The current running user.
     * @param roles The roles.
     * @param ids The id of the group to associate with the roles.
     * @throws PermissionException whoami is not allowed to perform
     *         addResourceGroup on this role.
     * 
     * 
     */
    public void addResourceGroupRoles(AuthzSubject whoami, Integer gid, Integer[] ids) throws PermissionException {
        addResourceGroupRoles(whoami, gid, ids, false);
    }

    /**
     * Associate ResourceGroup with list of roles.
     * 
     * @param whoami The current running user.
     * @param roles The roles.
     * @param ids The id of the group to associate with the roles.
     * @throws PermissionException whoami is not allowed to perform
     *         addResourceGroup on this role.
     * 
     * 
     */
    public void addResourceGroupRoles(AuthzSubject whoami, Integer gid, Integer[] ids, boolean isDuringCalculation)
            throws PermissionException {
        ResourceGroup group = lookupGroup(gid);
        for (int i = 0; i < ids.length; i++) {
            Role roleLocal = lookupRole(ids[i]);
            group.addRole(roleLocal);
        }
        if (ids != null && ids.length > 0) {
            zeventManager.enqueueEventAfterCommit(new GroupAddedToRolesZevent(group, isDuringCalculation));
        }
    }

    /**
     * Disassociate ResourceGroups from this role.
     * 
     * @param whoami The current running user.
     * @param id This role.
     * @param gids The ids of the groups to disassociate.
     * 
     * @throws PermissionException whoami is not allowed to perform modifyRole
     *         on this role.
     * 
     */
    public void removeResourceGroups(AuthzSubject whoami, Integer id, Integer[] gids) throws PermissionException {
        Role roleLocal = lookupRole(id);
        Collection<ResourceGroup> groups = new HashSet<ResourceGroup>();
        permissionManager.check(whoami.getId(), roleLocal.getResource().getResourceType(), roleLocal.getId(),
                AuthzConstants.roleOpModifyRole);

        for (int i = 0; i < gids.length; i++) {
            ResourceGroup group = lookupGroup(gids[i]);
            roleLocal.removeResourceGroup(group);
            groups.add(group);

        }
        if (gids != null && gids.length > 0) {
            zeventManager.enqueueEventAfterCommit(new GroupsRemovedFromRoleZevent(roleLocal, groups));
        }
    }

    /**
     * Disassociate roles from this ResourceGroup.
     * 
     * @param whoami The current running user.
     * @param role This role.
     * @param ids The ids of the groups to disassociate.
     *
     * @throws PermissionException whoami is not allowed to perform modifyRole
     *         on this role.
     * 
     */
    public void removeResourceGroupRoles(AuthzSubject whoami, Integer gid, Integer[] ids)
            throws PermissionException {
        removeResourceGroupRoles(whoami, gid, ids, false);
    }

    /**
     * Disassociate roles from this ResourceGroup.
     * 
     * @param whoami The current running user.
     * @param role This role.
     * @param ids The ids of the groups to disassociate.
     * @param isDuringCalculation true/false if we are in the middle of group membership calculation 
     *
     * @throws PermissionException whoami is not allowed to perform modifyRole
     *         on this role.
     * 
     */
    public void removeResourceGroupRoles(AuthzSubject whoami, Integer gid, Integer[] ids,
            boolean isDuringCalculation) throws PermissionException {

        ResourceGroup group = lookupGroup(gid);
        Collection<Role> roles = new HashSet<Role>();
        for (int i = 0; i < ids.length; i++) {
            Role roleLocal = lookupRole(ids[i]);

            permissionManager.check(whoami.getId(), roleLocal.getResource().getResourceType(), roleLocal.getId(),
                    AuthzConstants.roleOpModifyRole);

            roles.add(roleLocal);
            roleLocal.removeResourceGroup(group);
        }
        if (ids != null && ids.length > 0) {
            zeventManager
                    .enqueueEventAfterCommit(new GroupRemovedFromRolesZevent(group, roles, isDuringCalculation));
        }
    }

    /**
     * Disassociate all ResourceGroups of this role from this role.
     * 
     * @param whoami The current running user.
     * @param role This role.
     * 
     *
     * @throws PermissionException whoami is not allowed to perform modifyRole
     *         on this role.
     * 
     */
    @SuppressWarnings("unchecked")
    public void removeAllResourceGroups(AuthzSubject whoami, Role role) throws PermissionException {

        permissionManager.check(whoami.getId(), role.getResource().getResourceType(), role.getId(),
                AuthzConstants.roleOpModifyRole);
        Collection<ResourceGroup> groups = role.getResourceGroups();
        role.clearResourceGroups();
        if (groups != null && groups.size() > 0) {
            zeventManager.enqueueEventAfterCommit(new GroupsRemovedFromRoleZevent(role, groups));
        }
    }

    /**
     * Get the # of roles within HQ inventory
     * 
     * 
     */
    @Transactional(readOnly = true)
    public Number getRoleCount() {
        return new Integer(roleDAO.size());
    }

    /**
     * Get the # of subjects within HQ inventory
     * 
     * 
     */
    @Transactional(readOnly = true)
    public Number getSubjectCount() {
        return new Integer(authzSubjectDAO.size());
    }

    /**
     * Get a Role by id
     * 
     * 
     */
    @Transactional(readOnly = true)
    public Role getRoleById(int id) {
        return roleDAO.get(new Integer(id));
    }

    /**
    * 
    */
    @Transactional(readOnly = true)
    public Role findRoleById(int id) {
        return lookupRole(new Integer(id));
    }

    /**
    * 
    */
    @Transactional(readOnly = true)
    public Role findRoleByName(String name) {
        return roleDAO.findByName(name);
    }

    /**
     * Create a calendar under a role for a specific type. Calendars created in
     * this manner are tied directly to the role and should not be used by other
     * roles.
     * 
     * @throws PermissionException if user is not allowed to modify role
     * 
     */
    public RoleCalendar createCalendar(AuthzSubject whoami, Role r, String calendarName, RoleCalendarType type)
            throws PermissionException {

        permissionManager.check(whoami.getId(), r.getResource().getResourceType(), r.getId(),
                AuthzConstants.roleOpModifyRole);

        Calendar cal = calendarManager.createCalendar(calendarName);
        RoleCalendar res = new RoleCalendar(r, cal, type);
        r.addCalendar(res);
        return res;
    }

    /**
    * 
    */
    public boolean removeCalendar(RoleCalendar c) {
        boolean res = c.getRole().removeCalendar(c);
        roleCalendarDAO.remove(c);
        calendarManager.remove(c.getCalendar());
        return res;
    }

    /**
     * Find the owned role that has the given ID.
     * 
     * @param id The ID of the role you're looking for.
     * @return The owned value-object of the role of the given ID.
     * 
     * 
     */
    public OwnedRoleValue findOwnedRoleById(AuthzSubject whoami, Integer id) throws PermissionException {

        Role local = roleDAO.findById(id);

        int numSubjects = authzSubjectDAO.size(local.getSubjects());

        permissionManager.check(whoami.getId(), local.getResource().getResourceType(), id,
                AuthzConstants.roleOpViewRole);

        OwnedRoleValue value = new OwnedRoleValue(local);
        value.setMemberCount(numSubjects);

        return value;
    }

    /**
     * Get operations For a given role id, find the resource types and
     * permissions which are supported by it
     * 
     * @param subject
     * @param roleId
     * @return list - values are lists of operation
     * 
     */
    @Transactional(readOnly = true)
    public List<Operation> getRoleOperations(AuthzSubject subject, Integer roleId) throws PermissionException {

        // find the role by id
        Role role = roleDAO.findById(roleId);
        return new ArrayList<Operation>(role.getOperations());
    }

    /**
     * @return a list of {@link Role}s
     * 
     */
    @Transactional(readOnly = true)
    public Collection<Role> getAllRoles() {
        return roleDAO.findAll();
    }

    private Collection<Role> getAllRoles(AuthzSubject subject, int sort, boolean asc) {
        switch (sort) {
        default:
        case SortAttribute.ROLE_NAME:
            return roleDAO.findAll_orderName(asc);
        }
    }

    /**
     * List all Roles in the system
     * 
     * @param pc Paging information for the request
     * @return List a list of RoleValues
     * 
     */
    @Transactional(readOnly = true)
    public List<RoleValue> getAllRoles(AuthzSubject subject, PageControl pc) {
        pc = PageControl.initDefaults(pc, SortAttribute.ROLE_NAME);
        Collection<Role> roles = getAllRoles(subject, pc.getSortattribute(), pc.isAscending());

        return rolePager.seek(roles, pc.getPagenum(), pc.getPagesize());
    }

    /**
     * List all OwnedRoles in the system
     * 
     * @param subject
     * @param pc Paging and sorting information.
     * @return List a list of OwnedRoleValues
     * 
     */
    @Transactional(readOnly = true)
    public List<OwnedRoleValue> getAllOwnedRoles(AuthzSubject subject, PageControl pc) {
        Collection<Role> roles = roleDAO.findAll();
        pc = PageControl.initDefaults(pc, SortAttribute.ROLE_NAME);
        return ownedRolePager.seek(roles, pc.getPagenum(), pc.getPagesize());
    }

    /**
     * List all Roles in the system, except system roles.
     * 
     * @return List a list of OwnedRoleValues that are not system roles
     * @throws NotFoundException if sort attribute is unrecognized
     * 
     */
    @Transactional(readOnly = true)
    public PageList<OwnedRoleValue> getAllNonSystemOwnedRoles(AuthzSubject subject, Integer[] excludeIds,
            PageControl pc) throws PermissionException, NotFoundException {

        pc = PageControl.initDefaults(pc, SortAttribute.ROLE_NAME);
        int attr = pc.getSortattribute();
        Collection<Role> roles;
        switch (attr) {

        case SortAttribute.ROLE_NAME:
            roles = roleDAO.findBySystem_orderName(false, !pc.isDescending());
            break;

        default:
            throw new NotFoundException("Unrecognized sort attribute: " + attr);
        }

        // 6729 - if caller is a member of the root role, show it
        // 5345 - allow access to the root role by the root user so it can
        // be used by others
        Role rootRole = getRootRoleIfMember(subject);
        if (rootRole != null) {
            ArrayList<Role> newList = new ArrayList<Role>();
            newList.add(rootRole);
            newList.addAll(roles);
            roles = newList;
        }

        roles = filterViewableRoles(subject, roles, excludeIds);

        PageList<OwnedRoleValue> plist = ownedRolePager.seek(roles, pc.getPagenum(), pc.getPagesize());
        plist.setTotalSize(roles.size());
        return plist;
    }

    /**
     * Get the roles with the specified ids
     * 
     * @param subject
     * @param ids the role ids
     * @param pc Paging information for the request
     * 
     * @throws PermissionException
     * 
     * 
     */
    @Transactional(readOnly = true)
    public PageList<RoleValue> getRolesById(AuthzSubject whoami, Integer[] ids, PageControl pc)
            throws PermissionException {

        List<Role> roles = getRolesByIds(whoami, ids, pc);

        PageList<RoleValue> plist = rolePager.seek(roles, pc.getPagenum(), pc.getPagesize());
        plist.setTotalSize(roles.size());

        return plist;
    }

    private List<Role> getRolesByIds(AuthzSubject whoami, Integer[] ids, PageControl pc)
            throws PermissionException {

        permissionManager.check(whoami.getId(), AuthzConstants.roleResourceTypeName, AuthzConstants.rootResourceId,
                AuthzConstants.roleOpViewRole);

        Collection<Role> all = getAllRoles(whoami, pc.getSortattribute(), pc.isAscending());

        // build an index of ids
        HashSet<Integer> index = new HashSet<Integer>();
        for (int i = 0; i < ids.length; i++) {
            Integer id = ids[i];
            index.add(id);
        }
        int numToFind = index.size();

        // find the requested roles
        List<Role> roles = new ArrayList<Role>(ids.length);
        Iterator<Role> i = all.iterator();
        while (i.hasNext() && roles.size() < numToFind) {
            Role r = i.next();
            if (index.contains(r.getId())) {
                roles.add(r);
            }
        }
        return roles;
    }

    /**
     * Associate roles with this subject.
     * 
     * @param whoami The current running user.
     * @param subject The subject.
     * @param roles The roles to associate with the subject.
     * @throws PermissionException whoami may not perform addRole on this
     *         subject.
     * 
     */
    public void addRoles(AuthzSubject whoami, AuthzSubject subject, Integer[] roles) throws PermissionException {
        Collection<Role> roleObjects = new HashSet<Role>();
        for (int i = 0; i < roles.length; i++) {
            Role roleLocal = lookupRole(roles[i]);
            roleObjects.add(roleLocal);
            subject.addRole(roleLocal);
        }
        if (roles != null && roles.length > 0) {
            zeventManager.enqueueEventAfterCommit(new SubjectAddedToRolesZevent(subject, roleObjects));
        }
    }

    /**
     * Disassociate roles from this subject.
     * 
     * @param whoami The current running user.
     * @param subject The subject.
     * @param roles The subjects to disassociate.
     * @throws PermissionException whoami may not perform removeRole on this
     *         subject.
     * 
     */
    public void removeRoles(AuthzSubject whoami, AuthzSubject subject, Integer[] roles) throws PermissionException {
        Collection<Role> roleLocals = getRolesByIds(whoami, roles, PageControl.PAGE_ALL);

        for (Role role : roleLocals) {
            subject.removeRole(role);
        }
        if (roles != null && roles.length > 0) {
            zeventManager.enqueueEventAfterCommit(new SubjectRemovedFromRolesZevent(subject, roleLocals));
        }
    }

    /**
     * Get the roles for a subject
     * 
     * @param whoami
     * @param subject
     * @param pc Paging and sorting information.
     * @return Set of Roles
     * 
     */
    @Transactional(readOnly = true)
    public List<RoleValue> getRoles(AuthzSubject subjectValue, PageControl pc) throws PermissionException {
        Collection<Role> roles = subjectValue.getRoles();
        pc = PageControl.initDefaults(pc, SortAttribute.ROLE_NAME);
        return rolePager.seek(roles, pc.getPagenum(), pc.getPagesize());
    }

    /**
     * Get the owned roles for a subject.
     * 
     * @param whoami
     * @param subject
     * @param pc Paging and sorting information.
     * @return Set of Roles
     * 
     */
    @Transactional(readOnly = true)
    public List<OwnedRoleValue> getOwnedRoles(AuthzSubject subject, PageControl pc) throws PermissionException {
        Collection<Role> roles = subject.getRoles();
        pc = PageControl.initDefaults(pc, SortAttribute.ROLE_NAME);
        return ownedRolePager.seek(roles, pc.getPagenum(), pc.getPagesize());
    }

    /**
     * Get the owned roles for a subject, except system roles.
     * 
     * @param callerSubjectValue is the subject of caller.
     * @param intendedSubjectValue is the subject of intended subject.
     * @param pc The PageControl object for paging results.
     * @return List a list of OwnedRoleValues that are not system roles
     *  
     * @throws PermissionException caller is not allowed to perform listRoles on
     *         this role.
        
     */
    @Transactional(readOnly = true)
    public PageList<OwnedRoleValue> getNonSystemOwnedRoles(AuthzSubject callerSubjectValue,
            AuthzSubject intendedSubjectValue, PageControl pc) throws PermissionException {
        return getNonSystemOwnedRoles(callerSubjectValue, intendedSubjectValue, null, pc);
    }

    /**
     * Get the owned roles for a subject, except system roles.
     * 
     * @param callerSubjectValue is the subject of caller.
     * @param intendedSubjectValue is the subject of intended subject.
     * @param pc The PageControl object for paging results.
     * @return List a list of OwnedRoleValues that are not system roles
     * 
     * @throws PermissionException caller is not allowed to perform listRoles on
     *         this role.
     */
    @Transactional(readOnly = true)
    public PageList<OwnedRoleValue> getNonSystemOwnedRoles(AuthzSubject callerSubjectValue,
            AuthzSubject intendedSubjectValue, Integer[] excludeIds, PageControl pc) throws PermissionException {

        // Fetch all roles presently assigned to the assignee
        Collection<Role> roles;

        pc = PageControl.initDefaults(pc, SortAttribute.ROLE_NAME);

        switch (pc.getSortattribute()) {
        case SortAttribute.ROLE_NAME:
            roles = roleDAO.findBySystemAndSubject_orderName(false, intendedSubjectValue.getId(), pc.isAscending());
            break;
        case SortAttribute.ROLE_MEMBER_CNT:
            roles = roleDAO.findBySystemAndSubject_orderMember(false, intendedSubjectValue.getId(),
                    pc.isAscending());
            break;
        default:
            throw new IllegalArgumentException("Invalid sort parameter");
        }

        if (isRootRoleMember(intendedSubjectValue)) {
            ArrayList<Role> roleList = new ArrayList<Role>(roles.size() + 1);

            Role rootRole = roleDAO.findById(AuthzConstants.rootRoleId);

            // We need to insert into the right place
            boolean done = false;
            for (Role role : roles) {
                if (!done) {
                    if (pc.getSortattribute() == SortAttribute.ROLE_NAME) {
                        if ((pc.isAscending() && role.getName().compareTo(rootRole.getName()) > 0)
                                || (pc.isDescending() && role.getName().compareTo(rootRole.getName()) < 0)) {
                            roleList.add(rootRole);
                            done = true;
                        }
                    } else if (pc.getSortattribute() == SortAttribute.ROLE_MEMBER_CNT) {
                        if ((pc.isAscending() && role.getSubjects().size() > rootRole.getSubjects().size())
                                || (pc.isDescending()
                                        && role.getSubjects().size() < rootRole.getSubjects().size())) {
                            roleList.add(rootRole);
                            done = true;
                        }
                    }
                }
                roleList.add(role);
            }

            if (!done) {
                roleList.add(rootRole);
            }

            roles = roleList;
        }

        // Filter out only those roles that the caller is able to see.
        Collection<Role> viewableRoles = filterViewableRoles(callerSubjectValue, roles, excludeIds);

        return ownedRolePager.seek(viewableRoles, pc.getPagenum(), pc.getPagesize());
    }

    /**
     * List the roles that this subject is not in and that are not one of the
     * specified roles.
     * 
     * @param whoami The current running user.
     * @param system If true, then only system roles are returned. If false,
     *        then only non-system roles are returned.
     * @param subjectId The id of the subject.
     * @return List of roles.
     * @throws NotFoundException Unable to find a given or dependent entities.
     * @throws PermissionException whoami is not allowed to perform listRoles on
     *         this role.
     *
     * 
     */
    @Transactional(readOnly = true)
    public PageList<RoleValue> getAvailableRoles(AuthzSubject whoami, boolean system, Integer subjectId,
            Integer[] roleIds, PageControl pc) throws PermissionException, NotFoundException {
        Collection<Role> foundRoles;
        pc = PageControl.initDefaults(pc, SortAttribute.ROLE_NAME);
        int attr = pc.getSortattribute();
        switch (attr) {

        case SortAttribute.ROLE_NAME:
            foundRoles = roleDAO.findBySystemAndAvailableForSubject_orderName(system, whoami.getId(),
                    !pc.isDescending());
            break;

        default:
            throw new NotFoundException("Unrecognized sort attribute: " + attr);
        }

        HashSet<Integer> index = new HashSet<Integer>();
        if (roleIds != null) {
            index.addAll(Arrays.asList(roleIds));
        }

        Collection<Role> roles = new ArrayList<Role>();

        for (Role r : foundRoles) {
            if (!index.contains(r.getId())) {
                roles.add(r);
            }
        }

        // AUTHZ Check
        // filter the viewable roles
        roles = filterViewableRoles(whoami, roles);

        PageList<RoleValue> plist = new PageList<RoleValue>();
        plist = rolePager.seek(roles, pc.getPagenum(), pc.getPagesize());
        plist.setTotalSize(roles.size());
        // 6729 - if caller is a member of the root role, show it
        // 5345 - allow access to the root role by the root user so it can
        // be used by others
        if (isRootRoleMember(whoami) && pc.getPagenum() == 0 && !index.contains(AuthzConstants.rootRoleId)) {
            Role role = roleDAO.findAvailableRoleForSubject(AuthzConstants.rootRoleId, subjectId);
            if (role == null) {
                return plist;
            }
            OwnedRoleValue rootRoleValue = role.getOwnedRoleValue();
            PageList<RoleValue> newList = new PageList<RoleValue>();
            newList.add(rootRoleValue);
            newList.addAll(plist);
            newList.setTotalSize(plist.getTotalSize() + 1);
            return newList;
        }
        return plist;
    }

    /**
     * List the roles that this subject is not in and that are not one of the
     * specified roles.
     * 
     * @param whoami The current running user.
     * @param system If true, then only system roles are returned. If false,
     *        then only non-system roles are returned.
     * @param groupId The id of the subject.
     * @return List of roles.
     * @throws NotFoundException Unable to find a given or dependent entities.
     * @throws PermissionException whoami is not allowed to perform listRoles on
     *         this role.
     * @throws NotFoundException if the sort attribute was not recognized
     * 
     */
    @Transactional(readOnly = true)
    public PageList<RoleValue> getAvailableGroupRoles(AuthzSubject whoami, Integer groupId, Integer[] roleIds,
            PageControl pc) throws PermissionException, NotFoundException {
        Collection<Role> foundRoles;
        pc = PageControl.initDefaults(pc, SortAttribute.ROLE_NAME);
        int attr = pc.getSortattribute();

        switch (attr) {
        case SortAttribute.ROLE_NAME:
            foundRoles = roleDAO.findAvailableForGroup(false, groupId);
            break;
        default:
            throw new NotFoundException("Unrecognized sort attribute: " + attr);
        }

        log.debug("Found " + foundRoles.size() + " available roles for group " + groupId
                + " before permission checking");

        HashSet<Integer> index = new HashSet<Integer>();
        if (roleIds != null) {
            index.addAll(Arrays.asList(roleIds));
        }

        // Grep out the specified roles
        ArrayList<Role> roles = new ArrayList<Role>();

        for (Role r : foundRoles) {
            if (!index.contains(r.getId())) {
                roles.add(r);
            }
        }

        log.debug("Found " + roles.size() + " available roles for group " + groupId + " after exclusions");

        // AUTHZ Check - filter the viewable roles
        roles = (ArrayList) filterViewableRoles(whoami, roles);

        if (isRootRoleMember(whoami) && pc.getPagenum() == 0 && !index.contains(AuthzConstants.rootRoleId)) {
            foundRoles = roleDAO.findAvailableForGroup(true, groupId);
            for (Role role : foundRoles) {
                if (role.getId().equals(AuthzConstants.rootRoleId)) {
                    roles.add(role);
                }
            }
        }

        if (pc.isDescending()) {
            Collections.reverse(roles);
        }

        log.debug("Found " + roles.size() + " available roles for group " + groupId + " after permission checking");

        PageList<RoleValue> plist = rolePager.seek(roles, pc.getPagenum(), pc.getPagesize());
        plist.setTotalSize(roles.size());

        return plist;
    }

    /**
     * Get the resource groups applicable to a given role.
     * @throws NotFoundException 
     *
    */
    @Transactional(readOnly = true)
    public Collection<ResourceGroup> getResourceGroupsByRole(AuthzSubject subject, Role role)
            throws PermissionException, NotFoundException {
        Collection<ResourceGroup> groups = resourceGroupDAO.findByRoleIdAndSystem_orderName(role.getId(), false,
                true);

        // now get viewable group pks
        return filterViewableGroups(subject, groups);
    }

    /**
     * Get the resource groups applicable to a given role.
     * @throws NotFoundException 
     *
    */
    @Transactional(readOnly = true)
    public Collection<ResourceGroup> getResourceGroupsByRoleAndGroupType(AuthzSubject subject, Role role,
            int groupType) throws PermissionException, NotFoundException {
        Collection<ResourceGroup> viewableGroups = getResourceGroupsByRole(subject, role);
        return filterByGroupType(viewableGroups, groupType);
    }

    /**
     * Filter a collection of groupLocal objects to only include those viewable
     * by the specified user
     */
    private Collection<ResourceGroup> filterByGroupType(Collection<ResourceGroup> groups, int groupType) {

        for (Iterator<ResourceGroup> i = groups.iterator(); i.hasNext();) {
            ResourceGroup resGrp = i.next();

            if (resGrp.getGroupType() != groupType) {
                i.remove();
            }
        }
        return groups;
    }

    /**
     * Get the resource groups applicable to a given role
     * 
     * 
     */
    @Transactional(readOnly = true)
    public PageList<ResourceGroupValue> getResourceGroupsByRoleIdAndSystem(AuthzSubject subject, Integer roleId,
            boolean system, PageControl pc) throws PermissionException, NotFoundException {
        // first find the role by its id
        roleDAO.findById(roleId);

        // now check to make sure the user can list resource groups
        Collection<ResourceGroup> groups;
        pc = PageControl.initDefaults(pc, SortAttribute.RESGROUP_NAME);
        int attr = pc.getSortattribute();

        switch (attr) {
        case SortAttribute.RESGROUP_NAME:
            groups = resourceGroupDAO.findByRoleIdAndSystem_orderName(roleId, system, pc.isAscending());
            break;

        default:
            throw new NotFoundException("Unrecognized sort attribute: " + attr);
        }

        // now get viewable group pks
        groups = filterViewableGroups(subject, groups);

        PageList<ResourceGroupValue> plist = groupPager.seek(groups, pc);
        plist.setTotalSize(groups.size());

        return plist;
    }

    /**
     * Return the roles of a group
     * 
     * @throws PermissionException
     * 
     * 
     */
    @Transactional(readOnly = true)
    public PageList<RoleValue> getResourceGroupRoles(AuthzSubject whoami, Integer groupId, PageControl pc)
            throws PermissionException {
        ResourceGroup resGrp = resourceGroupDAO.findById(groupId);

        permissionManager.check(whoami.getId(), AuthzConstants.authzGroup, resGrp.getId(),
                AuthzConstants.perm_viewResourceGroup);

        Collection<Role> roles = resGrp.getRoles();

        TreeMap<String, Role> map = new TreeMap<String, Role>();
        for (Role role : roles) {
            int attr = pc.getSortattribute();
            switch (attr) {
            case SortAttribute.ROLE_NAME:
            default:
                map.put(role.getName(), role);
            }
        }

        ArrayList<Role> list = new ArrayList<Role>(map.values());

        if (pc.isDescending()) {
            Collections.reverse(list);
        }

        PageList<RoleValue> plist = rolePager.seek(list, pc.getPagenum(), pc.getPagesize());
        plist.setTotalSize(roles.size());

        return plist;
    }

    /**
     * Filter a collection of groupLocal objects to only include those viewable
     * by the specified user
     */
    private Collection<ResourceGroup> filterViewableGroups(AuthzSubject who, Collection<ResourceGroup> groups)
            throws PermissionException, NotFoundException {
        // finally scope down to only the ones the user can see

        Collection<Integer> viewable = permissionManager.findOperationScopeBySubject(who,
                AuthzConstants.groupOpViewResourceGroup, AuthzConstants.groupResourceTypeName);

        for (Iterator<ResourceGroup> i = groups.iterator(); i.hasNext();) {
            ResourceGroup resGrp = i.next();

            if (!viewable.contains(resGrp.getId())) {
                i.remove();
            }
        }
        return groups;
    }

    /**
     * List the groups not in this role and not one of the specified groups.
     * 
     * @param whoami The current running user.
     * @param roleId The id of the role.
     * @return List of groups in this role.
     * @throws PermissionException whoami is not allowed to perform listGroups
     *         on this role.
     * @throws NotFoundException
     * 
     */
    @Transactional(readOnly = true)
    public PageList<ResourceGroupValue> getAvailableResourceGroups(AuthzSubject whoami, Integer roleId,
            Integer[] groupIds, PageControl pc) throws PermissionException, NotFoundException {

        Role role = roleDAO.findById(roleId);
        Collection<ResourceGroup> noRoles;
        Collection<ResourceGroup> otherRoles;
        pc = PageControl.initDefaults(pc, SortAttribute.RESGROUP_NAME);
        int attr = pc.getSortattribute();

        switch (attr) {
        case SortAttribute.RESGROUP_NAME:
            noRoles = resourceGroupDAO.findWithNoRoles_orderName(pc.isAscending());
            otherRoles = resourceGroupDAO.findByNotRoleId_orderName(role.getId(), pc.isAscending());
            break;

        default:
            throw new NotFoundException("Unrecognized sort attribute: " + attr);
        }

        // FIXME- merging these two sorted lists probably causes the
        // final list to not be sorted correctly. fix this by
        // combining the two finders into one!
        // FIX for 6924 - dont include duplicate groups
        for (ResourceGroup group : otherRoles) {
            if (!noRoles.contains(group)) {
                noRoles.add(group);
            }
        }

        // build an index of groupIds
        int numToFind = (groupIds == null) ? 0 : groupIds.length;
        HashSet<Integer> index = new HashSet<Integer>();
        for (int i = 0; i < numToFind; i++) {
            index.add(groupIds[i]);
        }

        // Add the groups that the role already owns
        Collection<ResourceGroup> belongs = resourceGroupDAO.findByRoleIdAndSystem_orderName(roleId, false, true);
        for (ResourceGroup s : belongs) {
            index.add(s.getId());
        }

        // grep out the specified groups
        Collection<ResourceGroup> groups = new ArrayList<ResourceGroup>(noRoles.size());
        for (ResourceGroup s : noRoles) {
            if (!index.contains(s.getId())) {
                groups.add(s);
            }
        }

        // AUTHZ Check
        // finally scope down to only the ones the user can see
        groups = filterViewableGroups(whoami, groups);

        PageList<ResourceGroupValue> plist = groupPager.seek(groups, pc.getPagenum(), pc.getPagesize());

        plist.setTotalSize(groups.size());

        return plist;
    }

    /**
     * List the subjects in this role.
     * 
     * @param whoami The current running user.
     * @param roleId The id of the role.
     * @return List of subjects in this role.
     * @throws PermissionException whoami is not allowed to perform listSubjects
     *         on this role.
     * @throws NotFoundException if the sort attribute is not recognized
     * 
     * 
     */
    @Transactional(readOnly = true)
    public PageList<AuthzSubjectValue> getSubjects(AuthzSubject whoami, Integer roleId, PageControl pc)
            throws PermissionException, NotFoundException {
        Role roleLocal = roleDAO.get(roleId);

        if (roleLocal == null) {
            return new PageList<AuthzSubjectValue>();
        }

        // check if this user is a member of this role
        boolean roleHasUser = roleLocal.getSubjects().contains(whoami);
        // check whether the user can see subjects other than himself
        try {

            permissionManager.check(whoami.getId(), resourceTypeDAO.findTypeResourceType(),
                    AuthzConstants.rootResourceId, AuthzConstants.subjectOpViewSubject);
        } catch (PermissionException e) {
            // if the user does not have permission to view subjects
            // but he is in the role, return a collection with only one
            // item... himself.
            if (roleHasUser) {
                PageList<AuthzSubjectValue> subjects = new PageList<AuthzSubjectValue>();
                subjects.add(whoami.getAuthzSubjectValue());
                subjects.setTotalSize(1);
                return subjects;
            }
            // otherwise return an empty list
            // fixes 5628 - user viewing role lacking view subjects
            // causes permissionexception
            return new PageList<AuthzSubjectValue>();
        }
        Collection<AuthzSubject> subjects;
        pc = PageControl.initDefaults(pc, SortAttribute.SUBJECT_NAME);

        switch (pc.getSortattribute()) {
        case SortAttribute.SUBJECT_NAME:
            subjects = authzSubjectDAO.findByRoleId_orderName(roleLocal.getId(), pc.isAscending());
            break;
        default:
            throw new NotFoundException("Unrecognized sort attribute: " + pc.getSortattribute());
        }

        PageList<AuthzSubjectValue> plist = new PageList<AuthzSubjectValue>();
        plist = subjectPager.seek(subjects, pc.getPagenum(), pc.getPagesize());
        plist.setTotalSize(subjects.size());

        return plist;
    }

    /**
     * List the subjects not in this role and not one of the specified subjects.
     * 
     * @param whoami The current running user.
     * @param roleId The id of the role.
     * @return List of subjects in this role.
     * @throws NotFoundException Unable to find a given or dependent entities.
     * @throws PermissionException whoami is not allowed to perform listSubjects
     *         on this role.
     * @throws NotFoundException if the sort attribute is not recognized
     * 
     * 
     */
    @Transactional(readOnly = true)
    public PageList<AuthzSubjectValue> getAvailableSubjects(AuthzSubject whoami, Integer roleId,
            Integer[] subjectIds, PageControl pc) throws PermissionException, NotFoundException {
        Role roleLocal = lookupRole(roleId);

        /** TODO PermissionCheck scope for viewSubject **/
        Collection<AuthzSubject> otherRoles;
        pc = PageControl.initDefaults(pc, SortAttribute.SUBJECT_NAME);

        switch (pc.getSortattribute()) {
        case SortAttribute.SUBJECT_NAME:
            otherRoles = authzSubjectDAO.findByNotRoleId_orderName(roleLocal.getId(), pc.isAscending());
            break;
        default:
            throw new NotFoundException("Unrecognized sort attribute: " + pc.getSortattribute());
        }

        // build an index of subjectIds
        int numToFind = subjectIds.length;
        HashSet<Integer> index = new HashSet<Integer>(Arrays.asList(subjectIds));

        // grep out the specified subjects
        ArrayList<AuthzSubject> subjects = new ArrayList<AuthzSubject>(numToFind);
        for (AuthzSubject subj : otherRoles) {
            if (!index.contains(subj.getId())) {
                subjects.add(subj);
            }
        }

        PageList<AuthzSubjectValue> plist = new PageList<AuthzSubjectValue>();
        plist = subjectPager.seek(subjects, pc.getPagenum(), pc.getPagesize());
        plist.setTotalSize(subjects.size());

        return plist;
    }

    @Transactional(readOnly = true)
    public Collection<Role> getRoles(AuthzSubject subj) {
        subj = authzSubjectDAO.get(subj.getId());
        final Collection<Role> roles = subj.getRoles();
        final Collection<Role> rtn = new ArrayList<Role>(roles.size());
        for (final Role role : roles) {
            final Role r = roleDAO.get(role.getId());
            if (r == null) {
                continue;
            }
            rtn.add(r);
        }
        return rtn;
    }

    /**
     * Add subjects to this role.
     * 
     * @param whoami The current running user.
     * @param id The ID of the role.
     * @param sids Ids of subjects to add to role.
     * @throws PermissionException whoami is not allowed to perform addSubject
     *         on this role.
     * 
     */
    public void addSubjects(AuthzSubject whoami, Integer id, Integer[] sids) throws PermissionException {
        Role role = lookupRole(id);
        Collection<AuthzSubject> subjects = new HashSet<AuthzSubject>();
        if (sids != null && sids.length > 0) {
            for (int i = 0; i < sids.length; i++) {
                AuthzSubject subj = authzSubjectDAO.findById(sids[i]);
                subjects.add(subj);
                subj.addRole(role);
            }
            zeventManager.enqueueEventAfterCommit(new SubjectsAddedToRoleZevent(role, subjects));
        }
    }

    /**
     * Remove subjects from this role.
     * 
     * @param whoami The current running user.
     * @param id The ID of the role.
     * @param ids The ids of the subjects to remove.
     * @throws PermissionException whoami is not allowed to perform
     *         removeSubject on this role.
     * 
     * 
     */
    public void removeSubjects(AuthzSubject whoami, Integer id, Integer[] ids) throws PermissionException {
        Role roleLocal = lookupRole(id);
        Collection<AuthzSubject> subjects = new HashSet<AuthzSubject>();
        for (int i = 0; i < ids.length; i++) {
            AuthzSubject subj = authzSubjectDAO.findById(ids[i]);
            subjects.add(subj);
            subj.removeRole(roleLocal);
        }
        if (ids != null && ids.length > 0) {
            zeventManager.enqueueEventAfterCommit(new SubjectsRemovedFromRoleZevent(roleLocal, subjects));
        }
    }

    /**
     * Find all {@link Operation} objects
     * 
     * 
     */
    @Transactional(readOnly = true)
    public Collection<Operation> findAllOperations() {
        return operationDAO.findAllOrderByName();
    }

    protected Set toPojos(Object[] vals) {
        Set ret = new HashSet();
        if (vals == null || vals.length == 0) {
            return ret;
        }
        for (int i = 0; i < vals.length; i++) {
            if (vals[i] instanceof Operation) {
                ret.add(vals[i]);
            } else if (vals[i] instanceof ResourceValue) {
                ret.add(lookupResource((ResourceValue) vals[i]));
            } else if (vals[i] instanceof RoleValue) {
                ret.add(roleDAO.findById(((RoleValue) vals[i]).getId()));
            } else if (vals[i] instanceof ResourceGroupValue) {
                ret.add(resourceGroupDAO.findById(((ResourceGroupValue) vals[i]).getId()));
            } else {
                log.error("Invalid type.");
            }

        }
        return ret;
    }

    private Resource lookupResource(ResourceValue resource) {
        if (resource.getId() == null) {
            ResourceType type = resource.getResourceType();
            return resourceDAO.findByInstanceId(type, resource.getInstanceId());
        }
        return resourceDAO.findById(resource.getId());
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public void checkCanModify(AuthzSubject authzSubject) throws PermissionException {
        permissionManager.check(authzSubject.getId(), AuthzConstants.authzRole, AuthzConstants.perm_modifyRole);
    }

}