Coverage Report - org.kuali.rice.kim.impl.role.RoleServiceBase
 
Classes in this File Line Coverage Branch Coverage Complexity
RoleServiceBase
0%
0/537
0%
0/438
4.044
RoleServiceBase$1
0%
0/1
N/A
4.044
RoleServiceBase$RoleDaoAction
0%
0/12
N/A
4.044
RoleServiceBase$RoleMemberCacheKeyHelper
0%
0/11
0%
0/2
4.044
 
 1  
 package org.kuali.rice.kim.impl.role;
 2  
 
 3  
 import org.apache.commons.collections.CollectionUtils;
 4  
 import org.apache.commons.lang.StringUtils;
 5  
 import org.kuali.rice.kew.api.action.DelegationType;
 6  
 import org.kuali.rice.kim.api.common.delegate.DelegateMember;
 7  
 import org.kuali.rice.kim.api.group.Group;
 8  
 import org.kuali.rice.kim.api.group.GroupService;
 9  
 import org.kuali.rice.kim.api.identity.principal.Principal;
 10  
 import org.kuali.rice.kim.api.role.Role;
 11  
 import org.kuali.rice.kim.api.role.RoleMember;
 12  
 import org.kuali.rice.kim.api.role.RoleResponsibilityAction;
 13  
 import org.kuali.rice.kim.api.services.IdentityService;
 14  
 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
 15  
 import org.kuali.rice.kim.framework.type.KimDelegationTypeService;
 16  
 import org.kuali.rice.kim.framework.type.KimRoleTypeService;
 17  
 import org.kuali.rice.kim.impl.common.attribute.KimAttributeBo;
 18  
 import org.kuali.rice.kim.impl.common.delegate.DelegateBo;
 19  
 import org.kuali.rice.kim.impl.common.delegate.DelegateMemberBo;
 20  
 import org.kuali.rice.kim.impl.responsibility.ResponsibilityInternalService;
 21  
 import org.kuali.rice.kim.impl.services.KIMServiceLocatorInternal;
 22  
 import org.kuali.rice.kim.service.IdentityManagementNotificationService;
 23  
 import org.kuali.rice.kim.util.KIMPropertyConstants;
 24  
 import org.kuali.rice.kim.util.KimConstants;
 25  
 import org.kuali.rice.krad.service.BusinessObjectService;
 26  
 import org.kuali.rice.krad.service.KRADServiceLocator;
 27  
 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
 28  
 import org.kuali.rice.krad.service.LookupService;
 29  
 import org.kuali.rice.krad.service.SequenceAccessorService;
 30  
 import org.kuali.rice.krad.util.KRADPropertyConstants;
 31  
 import org.kuali.rice.ksb.api.KsbApiServiceLocator;
 32  
 import org.kuali.rice.ksb.api.cache.RiceCacheAdministrator;
 33  
 
 34  
 import javax.xml.namespace.QName;
 35  
 import java.util.ArrayList;
 36  
 import java.util.Collection;
 37  
 import java.util.Collections;
 38  
 import java.util.HashMap;
 39  
 import java.util.HashSet;
 40  
 import java.util.List;
 41  
 import java.util.Map;
 42  
 import java.util.Set;
 43  
 
 44  0
 public class RoleServiceBase {
 45  
     protected static final String ROLE_IMPL_CACHE_PREFIX = "RoleImpl-ID-";
 46  
     protected static final String ROLE_IMPL_BY_NAME_CACHE_PREFIX = "RoleImpl-Name-";
 47  
     protected static final String ROLE_IMPL_CACHE_GROUP = "RoleImpl";
 48  
 
 49  
     protected static final String ROLE_MEMBER_IMPL_CACHE_PREFIX = "RoleMemberBo-ID-";
 50  
     protected static final String ROLE_MEMBER_IMPL_LIST_CACHE_PREFIX = "RoleMemberBo-List-";
 51  
     protected static final String ROLE_MEMBER_IMPL_CACHE_GROUP = "RoleMemberBo";
 52  
 
 53  
     protected static final String DELEGATION_IMPL_CACHE_PREFIX = "DelegateBo-ID-";
 54  
     protected static final String DELEGATION_IMPL_LIST_CACHE_PREFIX = "DelegateBo-List-";
 55  
     protected static final String DELEGATION_IMPL_CACHE_GROUP = "DelegateBo";
 56  
 
 57  
     protected static final String DELEGATION_MEMBER_IMPL_CACHE_PREFIX = "DelegateMemberBo-ID-";
 58  
     protected static final String DELEGATION_MEMBER_IMPL_BY_DLGN_AND_ID_CACHE_PREFIX = "DelegateMemberBo-DelegationAndId-";
 59  
     protected static final String DELEGATION_MEMBER_IMPL_LIST_CACHE_PREFIX = "DelegateMemberBo-List-";
 60  
     protected static final String DELEGATION_MEMBER_IMPL_LIST_BY_MBR_DLGN_CACHE_PREFIX = "DelegateMemberBo-List-MemberAndDelegationId-";
 61  
     protected static final String DELEGATION_MEMBER_IMPL_CACHE_GROUP = "DelegateMemberBo";
 62  
 
 63  
     private BusinessObjectService businessObjectService;
 64  
     private LookupService lookupService;
 65  
     private RiceCacheAdministrator cacheAdministrator;
 66  
     private SequenceAccessorService sequenceAccessorService;
 67  
     private IdentityService identityService;
 68  
     private GroupService groupService;
 69  
     private ResponsibilityInternalService responsibilityInternalService;
 70  
 
 71  0
     private Map<String, KimRoleTypeService> roleTypeServiceCache = Collections.synchronizedMap(new HashMap<String, KimRoleTypeService>());
 72  0
     private Map<String, KimDelegationTypeService> delegationTypeServiceCache = Collections.synchronizedMap(new HashMap<String, KimDelegationTypeService>());
 73  
 
 74  0
     private Map<String, Boolean> applicationRoleTypeCache = Collections.synchronizedMap(new HashMap<String, Boolean>());
 75  
     private RoleDao roleDao;
 76  
 
 77  
     /**
 78  
      * A helper enumeration for indicating which KimRoleDao method to use when attempting to get role/delegation-related lists that are not in the cache.
 79  
      *
 80  
      * @author Kuali Rice Team (rice.collab@kuali.org)
 81  
      */
 82  0
     public static enum RoleDaoAction {
 83  0
         ROLE_PRINCIPALS_FOR_PRINCIPAL_ID_AND_ROLE_IDS("principalMembers-"),
 84  0
         ROLE_GROUPS_FOR_GROUP_IDS_AND_ROLE_IDS("groupMembers-"),
 85  0
         ROLE_MEMBERS_FOR_ROLE_IDS("membersOfRole-"),
 86  0
         ROLE_MEMBERSHIPS_FOR_ROLE_IDS_AS_MEMBERS("rolesAsMembers-"),
 87  0
         ROLE_MEMBERS_FOR_ROLE_IDS_WITH_FILTERS("roleIdsWithFilters-"),
 88  0
         DELEGATION_PRINCIPALS_FOR_PRINCIPAL_ID_AND_DELEGATION_IDS("delegationPrincipals-"),
 89  0
         DELEGATION_GROUPS_FOR_GROUP_IDS_AND_DELEGATION_IDS("delegationGroups-"),
 90  0
         DELEGATION_MEMBERS_FOR_DELEGATION_IDS("delegationMembers-");
 91  
 
 92  
         public final String DAO_ACTION_CACHE_PREFIX;
 93  
 
 94  0
         private RoleDaoAction(String daoActionCachePrefix) {
 95  0
             this.DAO_ACTION_CACHE_PREFIX = daoActionCachePrefix;
 96  0
         }
 97  
     }
 98  
 
 99  
     // -----------------------------------------------------------------------------------------------------------------
 100  
     // Role Membership Caching Methods
 101  
     // -----------------------------------------------------------------------------------------------------------------
 102  
 
 103  
     /**
 104  
      * Generates a String key to use for storing or retrieving a RoleMemberBo to/from the cache.
 105  
      *
 106  
      * @param roleMemberId The ID of the RoleMemberBo to generate a key for.
 107  
      * @return A cache key for the RoleMemberBo with the given ID.
 108  
      */
 109  
     protected String getRoleMemberCacheKey(String roleMemberId) {
 110  0
         return ROLE_MEMBER_IMPL_CACHE_PREFIX + roleMemberId;
 111  
     }
 112  
 
 113  
     /**
 114  
      * Generates a String key to use for storing or retrieving a list of RoleMemberBos to/from the cache. The key is generated by specifying
 115  
      * certain properties that are common to all the RoleMemberBo instances in the list to be cached. Note that at least one common
 116  
      * property will always be null; for instance, a role member cannot have a member ID that refers to both a principal and a group, so at least
 117  
      * the principalId or the groupId parameter will have a null value passed in by the calling code in this RoleService implementation. Also,
 118  
      * the value of the RoleDaoAction parameter passed in will affect which subsequent parameters will be used in generating the cache key.
 119  
      *
 120  
      * @param roleDaoAction  The RoleDaoAction signifying which KimRoleDao call found this list; will determine how and which parameters are used.
 121  
      * @param roleId         The role ID (possibly as a member ID) shared among the members of the list; will be interpreted as an empty String if this is blank.
 122  
      * @param principalId    The (principal) member ID shared among the members of the list; will be interpreted as an empty String if this is blank.
 123  
      * @param groupId        The (group) member ID shared among the members of the list; will be interpreted as an empty String if this is blank.
 124  
      * @param memberTypeCode The member type code shared among the members of the list; will be interpreted as an empty String if this is blank.
 125  
      * @return A cache key for the RoleMemberBo list whose members share the given roleId, principalId, groupId, and memberTypeCode.
 126  
      * @throws IllegalArgumentException if the RoleDaoAction parameter does not refer to a role-member-related enumeration value.
 127  
      */
 128  
     protected String getRoleMemberListCacheKey(RoleDaoAction roleDaoAction, String roleId, String principalId, String groupId, String memberTypeCode) {
 129  0
         switch (roleDaoAction) {
 130  
             case ROLE_PRINCIPALS_FOR_PRINCIPAL_ID_AND_ROLE_IDS: // Search for principal role members only.
 131  0
                 return new StringBuilder(ROLE_MEMBER_IMPL_LIST_CACHE_PREFIX).append(roleDaoAction.DAO_ACTION_CACHE_PREFIX).append(
 132  
                         StringUtils.isBlank(roleId) ? "" : roleId).append('-').append(StringUtils.isBlank(principalId) ? "" : principalId).toString();
 133  
             case ROLE_GROUPS_FOR_GROUP_IDS_AND_ROLE_IDS: // Search for group role members only.
 134  0
                 return new StringBuilder(ROLE_MEMBER_IMPL_LIST_CACHE_PREFIX).append(roleDaoAction.DAO_ACTION_CACHE_PREFIX).append(
 135  
                         StringUtils.isBlank(roleId) ? "" : roleId).append('-').append(StringUtils.isBlank(groupId) ? "" : groupId).toString();
 136  
             case ROLE_MEMBERS_FOR_ROLE_IDS: // Search for role members with the given member type code.
 137  0
                 return new StringBuilder(ROLE_MEMBER_IMPL_LIST_CACHE_PREFIX).append(roleDaoAction.DAO_ACTION_CACHE_PREFIX).append(
 138  
                         StringUtils.isBlank(roleId) ? "" : roleId).append('-').append(StringUtils.isBlank(memberTypeCode) ? "" : memberTypeCode).toString();
 139  
             case ROLE_MEMBERSHIPS_FOR_ROLE_IDS_AS_MEMBERS: // Search for role members who are also roles.
 140  0
                 return new StringBuilder(ROLE_MEMBER_IMPL_LIST_CACHE_PREFIX).append(roleDaoAction.DAO_ACTION_CACHE_PREFIX).append(
 141  
                         StringUtils.isBlank(roleId) ? "" : roleId).toString();
 142  
             case ROLE_MEMBERS_FOR_ROLE_IDS_WITH_FILTERS: // Search for role members that might be roles, principals, or groups.
 143  0
                 return new StringBuilder(ROLE_MEMBER_IMPL_LIST_CACHE_PREFIX).append(roleDaoAction.DAO_ACTION_CACHE_PREFIX).append(
 144  
                         StringUtils.isBlank(roleId) ? "" : roleId).append('-').append(StringUtils.isBlank(principalId) ? "" : principalId).append(
 145  
                         '-').append(StringUtils.isBlank(groupId) ? "" : groupId).append('-').append(
 146  
                         StringUtils.isBlank(memberTypeCode) ? "" : memberTypeCode).toString();
 147  
             default: // The daoActionToTake parameter is invalid; throw an exception.
 148  0
                 throw new IllegalArgumentException("The 'roleDaoAction' parameter cannot refer to a non-role-member-related value!");
 149  
         }
 150  
     }
 151  
 
 152  
     /**
 153  
      * Converts the Qualifier Name/Value Role qualification set into Qualifier AttributeID/Value set
 154  
      *
 155  
      * @param qualification The original role qualification attribute set
 156  
      * @return Converted Map<String, String> containing ID/value pairs
 157  
      */
 158  
     private Map<String, String> convertQualifierKeys(Map<String, String> qualification) {
 159  0
         Map<String, String> convertedQualification = new HashMap<String, String>();
 160  0
         if (qualification != null && CollectionUtils.isNotEmpty(qualification.keySet())) {
 161  0
             for (String attributeName : qualification.keySet()) {
 162  0
                 if (StringUtils.isNotEmpty(getKimAttributeId(attributeName))) {
 163  0
                     convertedQualification.put(getKimAttributeId(attributeName), qualification.get(attributeName));
 164  
                 }
 165  
             }
 166  
         }
 167  0
         return convertedQualification;
 168  
     }
 169  
 
 170  
     public Set<String> getRoleTypeRoleMemberIds(String roleId) {
 171  0
         Set<String> results = new HashSet();
 172  0
         getNestedRoleTypeMemberIds(roleId, results);
 173  0
         return results;
 174  
     }
 175  
 
 176  
     protected void getNestedRoleTypeMemberIds(String roleId, Set members) throws RuntimeException {
 177  0
         ArrayList<String> roleList = new ArrayList<String>(1);
 178  0
         roleList.add(roleId);
 179  0
         List<RoleMemberBo> firstLevelMembers = getStoredRoleMembersForRoleIds(roleList, KimConstants.KimUIConstants.MEMBER_TYPE_ROLE_CODE, null);
 180  0
         for (RoleMemberBo member : firstLevelMembers) {
 181  0
             if (KimConstants.KimUIConstants.MEMBER_TYPE_ROLE_CODE.equals(member.getMemberTypeCode())) {
 182  0
                 if (!members.contains(member.getMemberId())) {
 183  0
                     members.add(member.getMemberId());
 184  0
                     getNestedRoleTypeMemberIds(member.getMemberId(), members);
 185  
                 }
 186  
             }
 187  
         }
 188  0
     }
 189  
 
 190  
     public List<String> getMemberParentRoleIds(String memberType, String memberId) {
 191  0
         List<RoleMemberBo> parentRoleMembers = roleDao.getRoleMembershipsForMemberId(memberType, memberId, null);
 192  
 
 193  0
         List<String> parentRoleIds = new ArrayList<String>(parentRoleMembers.size());
 194  0
         for (RoleMemberBo parentRoleMember : parentRoleMembers) {
 195  0
             parentRoleIds.add(parentRoleMember.getRoleId());
 196  
         }
 197  
 
 198  0
         return parentRoleIds;
 199  
     }
 200  
 
 201  
     /**
 202  
      * Retrieves a list of RoleMemberBo instances from the cache and/or the KimRoleDao as appropriate.
 203  
      *
 204  
      * @param daoActionToTake An indicator for which KimRoleDao method should be used to get the results if the desired RoleMemberBos are not cached.
 205  
      * @param roleIds         The role IDs to filter by; may get used as the IDs for members that are also roles, depending on the daoActionToTake value.
 206  
      * @param principalId     The principal ID to filter by; may get ignored depending on the daoActionToTake value.
 207  
      * @param groupIds        The group IDs to filter by; may get ignored depending on the daoActionToTake value.
 208  
      * @param memberTypeCode  The member type code to filter by; may get overridden depending on the daoActionToTake value.
 209  
      * @param qualification   The original role qualification attribute set
 210  
      * @return A list of RoleMemberBo instances based on the provided parameters.
 211  
      * @throws IllegalArgumentException if daoActionToTake refers to an enumeration constant that is not role-member-related.
 212  
      */
 213  
     protected List<RoleMemberBo> getRoleMemberBoList(RoleDaoAction daoActionToTake, Collection<String> roleIds, String principalId,
 214  
                                                      Collection<String> groupIds, String memberTypeCode, Map<String, String> qualification) {
 215  0
         List<RoleMemberBo> finalResults = new ArrayList<RoleMemberBo>();
 216  0
         List<RoleMemberCacheKeyHelper> searchKeys = new ArrayList<RoleMemberCacheKeyHelper>();
 217  0
         List<RoleMemberCacheKeyHelper> uncachedKeys = new ArrayList<RoleMemberCacheKeyHelper>();
 218  0
         Set<String> usedKeys = new HashSet<String>();
 219  0
         Map<String, String> convertedQualification = convertQualifierKeys(qualification);
 220  
 
 221  0
         if (roleIds == null || roleIds.isEmpty()) {
 222  0
             roleIds = Collections.singletonList(null);
 223  
         }
 224  0
         if (groupIds == null || groupIds.isEmpty()) {
 225  0
             groupIds = Collections.singletonList(null);
 226  
         }
 227  
 
 228  
         // Attempt to find any pre-cached role members based on what KimRoleDao method call is desired.
 229  0
         switch (daoActionToTake) {
 230  
             case ROLE_PRINCIPALS_FOR_PRINCIPAL_ID_AND_ROLE_IDS: // Search for principal role members only.
 231  0
                 for (String roleId : roleIds) {
 232  0
                     searchKeys.add(new RoleMemberCacheKeyHelper(daoActionToTake, roleId, principalId, null, Role.PRINCIPAL_MEMBER_TYPE));
 233  
                 }
 234  0
                 break;
 235  
             case ROLE_GROUPS_FOR_GROUP_IDS_AND_ROLE_IDS: // Search for group role members only.
 236  0
                 for (String roleId : roleIds) {
 237  0
                     for (String groupId : groupIds) {
 238  0
                         searchKeys.add(new RoleMemberCacheKeyHelper(daoActionToTake, roleId, null, groupId, Role.GROUP_MEMBER_TYPE));
 239  
                     }
 240  
                 }
 241  0
                 break;
 242  
             case ROLE_MEMBERS_FOR_ROLE_IDS: // Search for role members with the given member type code.
 243  0
                 for (String roleId : roleIds) {
 244  0
                     searchKeys.add(new RoleMemberCacheKeyHelper(daoActionToTake, roleId, null, null, memberTypeCode));
 245  
                 }
 246  0
                 break;
 247  
             case ROLE_MEMBERSHIPS_FOR_ROLE_IDS_AS_MEMBERS: // Search for role members who are also roles.
 248  0
                 for (String roleId : roleIds) {
 249  0
                     searchKeys.add(new RoleMemberCacheKeyHelper(daoActionToTake, roleId, null, null, Role.ROLE_MEMBER_TYPE));
 250  
                 }
 251  0
                 break;
 252  
             case ROLE_MEMBERS_FOR_ROLE_IDS_WITH_FILTERS: // Search for role members that might be roles, principals, or groups.
 253  0
                 for (String roleId : roleIds) {
 254  0
                     searchKeys.add(new RoleMemberCacheKeyHelper(daoActionToTake, roleId, null, null, Role.ROLE_MEMBER_TYPE));
 255  0
                     searchKeys.add(new RoleMemberCacheKeyHelper(daoActionToTake, roleId, principalId, null, Role.PRINCIPAL_MEMBER_TYPE));
 256  0
                     for (String groupId : groupIds) {
 257  0
                         searchKeys.add(new RoleMemberCacheKeyHelper(daoActionToTake, roleId, null, groupId, Role.GROUP_MEMBER_TYPE));
 258  
                     }
 259  
                 }
 260  0
                 break;
 261  
             default: // The daoActionToTake parameter is invalid; throw an exception.
 262  0
                 throw new IllegalArgumentException("The 'daoActionToTake' parameter cannot refer to a non-role-member-related value!");
 263  
         }
 264  
 
 265  
         // Attempt to find any pre-cached role members.
 266  0
         for (RoleMemberCacheKeyHelper searchKey : searchKeys) {
 267  0
             if (!usedKeys.contains(searchKey.getCacheKey())) {
 268  0
                 List<RoleMemberBo> tempMembers = (List<RoleMemberBo>) getCacheAdministrator().getFromCache(searchKey.getCacheKey());
 269  0
                 if (tempMembers != null) {
 270  0
                     finalResults.addAll(tempMembers);
 271  
                 } else {
 272  0
                     uncachedKeys.add(searchKey);
 273  
                 }
 274  0
                 usedKeys.add(searchKey.getCacheKey());
 275  0
             }
 276  
         }
 277  
 
 278  
         // If any portion of the result set was not in the cache, then retrieve and cache the missing sections.
 279  0
         if (!uncachedKeys.isEmpty()) {
 280  0
             Set<String> uncachedRoleSet = new HashSet<String>();
 281  0
             Set<String> uncachedGroupSet = new HashSet<String>();
 282  0
             for (RoleMemberCacheKeyHelper uncachedKey : uncachedKeys) {
 283  0
                 if (uncachedKey.ROLE_ID != null) {
 284  0
                     uncachedRoleSet.add(uncachedKey.ROLE_ID);
 285  
                 }
 286  0
                 if (uncachedKey.GROUP_ID != null) {
 287  0
                     uncachedGroupSet.add(uncachedKey.GROUP_ID);
 288  
                 }
 289  
             }
 290  
 
 291  0
             List<String> uncachedRoles = (uncachedRoleSet.isEmpty()) ? null : new ArrayList<String>(uncachedRoleSet);
 292  0
             List<String> uncachedGroups = (uncachedGroupSet.isEmpty()) ? null : new ArrayList<String>(uncachedGroupSet);
 293  
             List<RoleMemberBo> uncachedResults;
 294  
 
 295  
             // Retrieve the uncached RoleMemberBos via the appropriate RoleDao method.
 296  0
             switch (daoActionToTake) {
 297  
                 case ROLE_PRINCIPALS_FOR_PRINCIPAL_ID_AND_ROLE_IDS: // Search for principal role members only.
 298  0
                     uncachedResults = roleDao.getRolePrincipalsForPrincipalIdAndRoleIds(uncachedRoles, principalId, convertedQualification);
 299  0
                     break;
 300  
                 case ROLE_GROUPS_FOR_GROUP_IDS_AND_ROLE_IDS: // Search for group role members only.
 301  0
                     uncachedResults = roleDao.getRoleGroupsForGroupIdsAndRoleIds(uncachedRoles, uncachedGroups, convertedQualification);
 302  0
                     break;
 303  
                 case ROLE_MEMBERS_FOR_ROLE_IDS: // Search for role members with the given member type code.
 304  0
                     uncachedResults = roleDao.getRoleMembersForRoleIds(uncachedRoles, memberTypeCode, convertedQualification);
 305  0
                     break;
 306  
                 case ROLE_MEMBERSHIPS_FOR_ROLE_IDS_AS_MEMBERS: // Search for role members who are also roles.
 307  0
                     uncachedResults = roleDao.getRoleMembershipsForRoleIdsAsMembers(uncachedRoles, convertedQualification);
 308  0
                     break;
 309  
                 case ROLE_MEMBERS_FOR_ROLE_IDS_WITH_FILTERS: // Search for role members that might be roles, principals, or groups.
 310  0
                     uncachedResults = roleDao.getRoleMembersForRoleIdsWithFilters(uncachedRoles, principalId, uncachedGroups, convertedQualification);
 311  0
                     break;
 312  
                 default: // This should never happen, since the previous switch block should handle this case appropriately.
 313  0
                     throw new IllegalArgumentException("The 'daoActionToTake' parameter cannot refer to a non-role-member-related value!");
 314  
             }
 315  
 
 316  0
             cacheRoleMemberLists(uncachedKeys, uncachedResults);
 317  0
             for (RoleMemberBo uncachedMember : uncachedResults) {
 318  0
                 addRoleMemberBoToCache(uncachedMember);
 319  
             }
 320  0
             finalResults.addAll(uncachedResults);
 321  
         }
 322  0
         return finalResults;
 323  
     }
 324  
 
 325  
     /**
 326  
      * Caches several Lists of role members that are constructed based on the given search keys. Note that a given List will not be cached if
 327  
      * it contains any role members that belong to a role that disallows caching of its members.
 328  
      *
 329  
      * @param keysToCache    The keys of the role member Lists that will be used to store the uncached results.
 330  
      * @param membersToCache The uncached role members.
 331  
      */
 332  
     private void cacheRoleMemberLists(List<RoleMemberCacheKeyHelper> keysToCache, List<RoleMemberBo> membersToCache) {
 333  0
         if (membersToCache == null) {
 334  0
             membersToCache = new ArrayList<RoleMemberBo>();
 335  
         }
 336  0
         for (RoleMemberCacheKeyHelper keyToCache : keysToCache) {
 337  0
             List<RoleMemberBo> roleMembers = new ArrayList<RoleMemberBo>();
 338  
 
 339  
             // Cache the Lists that do not contain role members belonging to roles that forbid caching of their members.
 340  0
             if (RoleDaoAction.ROLE_MEMBERSHIPS_FOR_ROLE_IDS_AS_MEMBERS.equals(keyToCache.ROLE_DAO_ACTION)) {
 341  0
                 boolean safeToCacheList = true;
 342  0
                 for (RoleMemberBo memberToCache : membersToCache) {
 343  0
                     if ((keyToCache.ROLE_ID == null || keyToCache.ROLE_ID.equals(memberToCache.getMemberId())) &&
 344  
                             (keyToCache.MEMBER_TYPE_CODE == null || keyToCache.MEMBER_TYPE_CODE.equals(memberToCache.getMemberTypeCode()))) {
 345  0
                         if (shouldCacheMembersOfRole(memberToCache.getRoleId())) {
 346  0
                             roleMembers.add(memberToCache);
 347  
                         } else {
 348  0
                             safeToCacheList = false;
 349  0
                             break;
 350  
                         }
 351  
                     }
 352  
                 }
 353  0
                 if (safeToCacheList) {
 354  0
                     getCacheAdministrator().putInCache(keyToCache.getCacheKey(), roleMembers, ROLE_MEMBER_IMPL_CACHE_GROUP);
 355  
                 }
 356  0
             } else if (keyToCache.ROLE_ID == null || shouldCacheMembersOfRole(keyToCache.ROLE_ID)) {
 357  0
                 for (RoleMemberBo memberToCache : membersToCache) {
 358  0
                     if ((keyToCache.ROLE_ID == null || keyToCache.ROLE_ID.equals(memberToCache.getRoleId())) &&
 359  
                             (keyToCache.PRINCIPAL_ID == null || keyToCache.PRINCIPAL_ID.equals(memberToCache.getMemberId())) &&
 360  
                             (keyToCache.GROUP_ID == null || keyToCache.GROUP_ID.equals(memberToCache.getMemberId())) &&
 361  
                             (keyToCache.MEMBER_TYPE_CODE == null || keyToCache.MEMBER_TYPE_CODE.equals(memberToCache.getMemberTypeCode()))) {
 362  0
                         roleMembers.add(memberToCache);
 363  
                     }
 364  
                 }
 365  0
                 getCacheAdministrator().putInCache(keyToCache.getCacheKey(), roleMembers, ROLE_MEMBER_IMPL_CACHE_GROUP);
 366  
             }
 367  0
         }
 368  0
     }
 369  
 
 370  
     /**
 371  
      * Calls the KimRoleDao's "getRolePrincipalsForPrincipalIdAndRoleIds" method and/or retrieves any corresponding members from the cache.
 372  
      */
 373  
     protected List<RoleMemberBo> getStoredRolePrincipalsForPrincipalIdAndRoleIds(Collection<String> roleIds, String principalId, Map<String, String> qualification) {
 374  0
         return getRoleMemberBoList(RoleDaoAction.ROLE_PRINCIPALS_FOR_PRINCIPAL_ID_AND_ROLE_IDS, roleIds, principalId, null, null, qualification);
 375  
     }
 376  
 
 377  
     /**
 378  
      * Calls the KimRoleDao's "getRoleGroupsForGroupIdsAndRoleIds" method and/or retrieves any corresponding members from the cache.
 379  
      */
 380  
     protected List<RoleMemberBo> getStoredRoleGroupsForGroupIdsAndRoleIds(Collection<String> roleIds, Collection<String> groupIds, Map<String, String> qualification) {
 381  0
         return getRoleMemberBoList(RoleDaoAction.ROLE_GROUPS_FOR_GROUP_IDS_AND_ROLE_IDS, roleIds, null, groupIds, null, qualification);
 382  
     }
 383  
 
 384  
     /**
 385  
      * Calls the KimRoleDao's "getRoleMembersForRoleIds" method and/or retrieves any corresponding members from the cache.
 386  
      */
 387  
     protected List<RoleMemberBo> getStoredRoleMembersForRoleIds(Collection<String> roleIds, String memberTypeCode, Map<String, String> qualification) {
 388  0
         return getRoleMemberBoList(RoleDaoAction.ROLE_MEMBERS_FOR_ROLE_IDS, roleIds, null, null, memberTypeCode, qualification);
 389  
     }
 390  
 
 391  
     /**
 392  
      * Calls the KimRoleDao's "getRoleMembershipsForRoleIdsAsMembers" method and/or retrieves any corresponding members from the cache.
 393  
      */
 394  
     protected List<RoleMemberBo> getStoredRoleMembershipsForRoleIdsAsMembers(Collection<String> roleIds, Map<String, String> qualification) {
 395  0
         return getRoleMemberBoList(RoleDaoAction.ROLE_MEMBERSHIPS_FOR_ROLE_IDS_AS_MEMBERS, roleIds, null, null, null, qualification);
 396  
     }
 397  
 
 398  
     /**
 399  
      * Calls the KimRoleDao's "getRoleMembersForRoleIdsWithFilters" method and/or retrieves any corresponding members from the cache.
 400  
      */
 401  
     protected List<RoleMemberBo> getStoredRoleMembersForRoleIdsWithFilters(Collection<String> roleIds, String principalId, List<String> groupIds, Map<String, String> qualification) {
 402  0
         return getRoleMemberBoList(RoleDaoAction.ROLE_MEMBERS_FOR_ROLE_IDS_WITH_FILTERS, roleIds, principalId, groupIds, null, qualification);
 403  
     }
 404  
 
 405  
     /**
 406  
      * Determines whether or not the given role should allow its members to be cached. The default implementation always returns true, but
 407  
      * subclasses can override this method if other non-default Role implementations forbid their members from being cached.
 408  
      *
 409  
      * @param roleId The ID of the role to check for determining whether or not to allow caching of its members.
 410  
      * @return True if the given role allows its members to be cached; false otherwise.
 411  
      */
 412  
     protected boolean shouldCacheMembersOfRole(String roleId) {
 413  0
         return true;
 414  
     }
 415  
 
 416  
     protected void addRoleMemberBoToCache(RoleMemberBo roleMember) {
 417  0
         if (roleMember != null && shouldCacheMembersOfRole(roleMember.getRoleId())) {
 418  0
             getCacheAdministrator().putInCache(getRoleMemberCacheKey(roleMember.getRoleMemberId()), roleMember, ROLE_MEMBER_IMPL_CACHE_GROUP);
 419  
         }
 420  0
     }
 421  
 
 422  
     protected RoleMemberBo getRoleMemberFromCache(String roleMemberId) {
 423  0
         return (RoleMemberBo) getCacheAdministrator().getFromCache(getRoleMemberCacheKey(roleMemberId));
 424  
     }
 425  
 
 426  
     public void flushInternalRoleMemberCache() {
 427  0
         getCacheAdministrator().flushGroup(ROLE_MEMBER_IMPL_CACHE_GROUP);
 428  0
     }
 429  
 
 430  
     /**
 431  
      * Retrieves a RoleMemberBo object by its ID. If the role member already exists in the cache, this method will return the cached
 432  
      * version; otherwise, it will retrieve the uncached version from the database and then cache it (if it belongs to a role that allows
 433  
      * its members to be cached) before returning it.
 434  
      */
 435  
     protected RoleMemberBo getRoleMemberBo(String roleMemberId) {
 436  0
         if (StringUtils.isBlank(roleMemberId)) {
 437  0
             return null;
 438  
         }
 439  
 
 440  
         // If the RoleMemberBo exists in the cache, return the cached one.
 441  0
         RoleMemberBo tempRoleMemberBo = getRoleMemberFromCache(roleMemberId);
 442  0
         if (tempRoleMemberBo != null) {
 443  0
             return tempRoleMemberBo;
 444  
         }
 445  
         // Otherwise, retrieve it normally.
 446  0
         tempRoleMemberBo = getBusinessObjectService().findByPrimaryKey(RoleMemberBo.class,
 447  
                 Collections.singletonMap(KIMPropertyConstants.RoleMember.ROLE_MEMBER_ID, roleMemberId));
 448  0
         addRoleMemberBoToCache(tempRoleMemberBo);
 449  0
         return tempRoleMemberBo;
 450  
     }
 451  
 
 452  
     // -----------------------------------------------------------------------------------------------------------------
 453  
     // Delegation Caching Methods
 454  
     // -----------------------------------------------------------------------------------------------------------------
 455  
 
 456  
     /**
 457  
      * Generates a String key to use for storing or retrieving a DelegateBo to/from the cache.
 458  
      *
 459  
      * @param delegationId The ID of the DelegateBo to generate a key for.
 460  
      * @return A cache key for the DelegateBo with the given ID.
 461  
      */
 462  
     protected String getDelegationCacheKey(String delegationId) {
 463  0
         return DELEGATION_IMPL_CACHE_PREFIX + delegationId;
 464  
     }
 465  
 
 466  
     /**
 467  
      * Generates a String key to use for storing or retrieving a List of DelegationBos to/from the cache based on a role's ID.
 468  
      *
 469  
      * @param roleId The ID of the role that the KIM delegations belong to.
 470  
      * @return A cache key for the DelegationBos with the given role ID.
 471  
      */
 472  
     protected String getDelegationListCacheKey(String roleId) {
 473  0
         return DELEGATION_IMPL_LIST_CACHE_PREFIX + (StringUtils.isBlank(roleId) ? "" : roleId);
 474  
     }
 475  
 
 476  
     /**
 477  
      * Calls the KimRoleDao's "getDelegationImplMapFromRoleIds" method and/or retrieves any corresponding delegations from the cache.
 478  
      */
 479  
     protected Map<String, DelegateBo> getStoredDelegationImplMapFromRoleIds(Collection<String> roleIds) {
 480  0
         Map<String, DelegateBo> finalResults = Collections.emptyMap();
 481  
 
 482  0
         if (roleIds != null && !roleIds.isEmpty()) {
 483  0
             Map<String, List<DelegateBo>> uncachedLists = new HashMap<String, List<DelegateBo>>();
 484  
             // Retrieve any existing results from the cache.
 485  0
             finalResults = getDelegationBoMap(uncachedLists, roleIds);
 486  
 
 487  
             // Retrieve any uncached results from the database and then cache them.
 488  0
             if (!uncachedLists.isEmpty()) {
 489  0
                 Map<String, DelegateBo> uncachedResults = roleDao.getDelegationImplMapFromRoleIds(
 490  
                         uncachedLists.keySet());
 491  
 
 492  0
                 for (Map.Entry<String, DelegateBo> uncachedResult : uncachedResults.entrySet()) {
 493  0
                     finalResults.put(uncachedResult.getKey(), uncachedResult.getValue());
 494  0
                     addDelegationBoToCache(uncachedResult.getValue());
 495  0
                     uncachedLists.get(uncachedResult.getValue().getRoleId()).add(uncachedResult.getValue());
 496  
                 }
 497  0
                 for (Map.Entry<String, List<DelegateBo>> uncachedList : uncachedLists.entrySet()) {
 498  0
                     getCacheAdministrator().putInCache(getDelegationListCacheKey(uncachedList.getKey()),
 499  
                             uncachedList.getValue(), DELEGATION_IMPL_CACHE_GROUP);
 500  
                 }
 501  
             }
 502  
         }
 503  
 
 504  0
         return finalResults;
 505  
     }
 506  
 
 507  
     /**
 508  
      * Calls the KimRoleDao's "getDelegationBosForRoleIds" method and/or retrieves any corresponding delegations from the cache.
 509  
      */
 510  
     protected List<DelegateBo> getStoredDelegationImplsForRoleIds(Collection<String> roleIds) {
 511  0
         List<DelegateBo> finalResults = new ArrayList<DelegateBo>();
 512  
 
 513  0
         if (roleIds != null && !roleIds.isEmpty()) {
 514  0
             Map<String, List<DelegateBo>> uncachedLists = new HashMap<String, List<DelegateBo>>();
 515  
             // Retrieve any existing results from the cache.
 516  0
             Map<String, DelegateBo> tempDelegations = getDelegationBoMap(uncachedLists, roleIds);
 517  0
             finalResults.addAll(tempDelegations.values());
 518  
 
 519  
             // Retrieve any uncached results from the database and then cache them.
 520  0
             if (!uncachedLists.isEmpty()) {
 521  0
                 List<DelegateBo> uncachedResults = roleDao.getDelegationBosForRoleIds(uncachedLists.keySet());
 522  
 
 523  0
                 for (DelegateBo uncachedResult : uncachedResults) {
 524  0
                     addDelegationBoToCache(uncachedResult);
 525  0
                     uncachedLists.get(uncachedResult.getRoleId()).add(uncachedResult);
 526  
                 }
 527  0
                 for (Map.Entry<String, List<DelegateBo>> uncachedList : uncachedLists.entrySet()) {
 528  0
                     getCacheAdministrator().putInCache(getDelegationListCacheKey(uncachedList.getKey()),
 529  
                             uncachedList.getValue(), DELEGATION_IMPL_CACHE_GROUP);
 530  
                 }
 531  0
                 finalResults.addAll(uncachedResults);
 532  
             }
 533  
         }
 534  
 
 535  0
         return finalResults;
 536  
     }
 537  
 
 538  
     /**
 539  
      * Retrieves any existing delegation lists from the cache for the given role IDs. If the delegations for a given role have not been cached,
 540  
      * then a new entry containing the uncached role ID and an empty List will be added to the given Map.
 541  
      *
 542  
      * @param uncachedLists The Map in which to place any uncached lists; cannot be null.
 543  
      * @param roleIds       The IDs of the roles containing the delegations.
 544  
      * @return A mutable Map containing any existing results from the cache and which maps the delegations' IDs to the delegation objects.
 545  
      * @throws IllegalArgumentException if the provided Map is null.
 546  
      */
 547  
     protected Map<String, DelegateBo> getDelegationBoMap(Map<String, List<DelegateBo>> uncachedLists, Collection<String> roleIds) {
 548  0
         if (uncachedLists == null) {
 549  0
             throw new IllegalArgumentException("'uncachedLists' parameter cannot be null!");
 550  
         }
 551  0
         Map<String, DelegateBo> delegationMap = new HashMap<String, DelegateBo>();
 552  
 
 553  
         // Retrieve any existing results from the cache.
 554  0
         if (roleIds != null && !roleIds.isEmpty()) {
 555  0
             for (String roleId : roleIds) {
 556  0
                 List<DelegateBo> tempDelegates = (List<DelegateBo>) getCacheAdministrator().getFromCache(getDelegationListCacheKey(roleId));
 557  0
                 if (tempDelegates != null) {
 558  0
                     for (DelegateBo tempDelegate : tempDelegates) {
 559  0
                         delegationMap.put(tempDelegate.getDelegationId(), tempDelegate);
 560  
                     }
 561  
                 } else {
 562  0
                     uncachedLists.put(roleId, new ArrayList<DelegateBo>());
 563  
                 }
 564  0
             }
 565  
         }
 566  
 
 567  0
         return delegationMap;
 568  
     }
 569  
 
 570  
     protected void addDelegationBoToCache(DelegateBo delegate) {
 571  0
         if (delegate != null) {
 572  0
             getCacheAdministrator().putInCache(getDelegationCacheKey(delegate.getDelegationId()),
 573  
                     delegate, DELEGATION_IMPL_CACHE_GROUP);
 574  
         }
 575  0
     }
 576  
 
 577  
     protected DelegateBo getDelegationFromCache(String delegationId) {
 578  0
         return (DelegateBo) getCacheAdministrator().getFromCache(getDelegationCacheKey(delegationId));
 579  
     }
 580  
 
 581  
     public void flushInternalDelegationCache() {
 582  0
         getCacheAdministrator().flushGroup(DELEGATION_IMPL_CACHE_GROUP);
 583  0
     }
 584  
 
 585  
     /**
 586  
      * Retrieves a DelegateBo object by its ID. If the delegation already exists in the cache, this method will return the cached
 587  
      * version; otherwise, it will retrieve the uncached version from the database and then cache it before returning it.
 588  
      */
 589  
     protected DelegateBo getDelegationBo(String delegationId) {
 590  0
         if (StringUtils.isBlank(delegationId)) {
 591  0
             return null;
 592  
         }
 593  
 
 594  
         // If the DelegateBo exists in the cache, return the cached one.
 595  0
         DelegateBo tempDelegate = getDelegationFromCache(delegationId);
 596  0
         if (tempDelegate != null) {
 597  0
             return tempDelegate;
 598  
         }
 599  
         // Otherwise, retrieve it normally.
 600  0
         tempDelegate = (DelegateBo) getBusinessObjectService().findByPrimaryKey(DelegateBo.class,
 601  
                 Collections.singletonMap(KimConstants.PrimaryKeyConstants.DELEGATION_ID, delegationId));
 602  0
         addDelegationBoToCache(tempDelegate);
 603  0
         return tempDelegate;
 604  
     }
 605  
 
 606  
     // -----------------------------------------------------------------------------------------------------------------
 607  
     // Delegation Membership Caching Methods
 608  
     // -----------------------------------------------------------------------------------------------------------------
 609  
 
 610  
     /**
 611  
      * Generates a String key to use for storing or retrieving a DelegateMemberBo to/from the cache.
 612  
      *
 613  
      * @param delegationMemberId The ID of the DelegateMemberBo to generate a key for.
 614  
      * @return A cache key for the DelegateMemberBo with the given ID.
 615  
      */
 616  
     protected String getDelegationMemberCacheKey(String delegationMemberId) {
 617  0
         return DELEGATION_MEMBER_IMPL_CACHE_PREFIX + delegationMemberId;
 618  
     }
 619  
 
 620  
     /**
 621  
      * Generates a String key to use for storing or retrieving a DelegateMemberBo to/from the cache by both delegation ID and delegation member ID.
 622  
      *
 623  
      * @param delegationId       The ID of the delegation that the DelegateMemberBo belongs to.
 624  
      * @param delegationMemberId The ID of the DelegateMemberBo to generate a key for.
 625  
      * @return A cache key for the DelegateMemberBo with the given delegation ID and delegation member ID.
 626  
      */
 627  
     protected String getDelegationMemberByDelegationAndIdCacheKey(String delegationId, String delegationMemberId) {
 628  0
         return new StringBuilder(DELEGATION_MEMBER_IMPL_BY_DLGN_AND_ID_CACHE_PREFIX).append(delegationId).append('-').append(delegationMemberId).toString();
 629  
     }
 630  
 
 631  
     /**
 632  
      * Generates a String key to use for storing or retrieving a DelegateMemberBo List to/from the cache by both delegation ID and member ID.
 633  
      *
 634  
      * @param memberId     The principal/group/role ID of the DelegateMemberBo(s) in the List.
 635  
      * @param delegationId The ID of the delegation that the DelegateMemberBo(s) in the List belong to.
 636  
      * @return A cache key for the DelegateMemberBo List with the given delegation ID and member ID.
 637  
      */
 638  
     protected String getDelegationMemberListByMemberAndDelegationIdCacheKey(String memberId, String delegationId) {
 639  0
         return new StringBuilder(DELEGATION_MEMBER_IMPL_LIST_BY_MBR_DLGN_CACHE_PREFIX).append(StringUtils.isBlank(memberId) ? "" : memberId).append(
 640  
                 '-').append(StringUtils.isBlank(delegationId) ? "" : delegationId).toString();
 641  
     }
 642  
 
 643  
     /**
 644  
      * Generates a String key to use for storing or retrieving a List of DelegateMemberBo lists to/from the cache. Some parameters may get
 645  
      * ignored depending on which KimRoleDao call is desired.
 646  
      *
 647  
      * @param daoAction    The RoleDaoAction signifying which KimRoleDao call found this list; will determine how and which parameters are used.
 648  
      * @param delegationId The ID of the DelegateBo that the indicated delegation member belongs to; will be interpreted as an empty String if blank.
 649  
      * @param principalId  The (principal) member ID of the delegation members; will be interpreted as an empty String if blank.
 650  
      * @param groupId      The (group) member ID of the delegation members; will be interpreted as an empty String if blank.
 651  
      * @return A cache key for the DelegateMemberBo List with the given criteria.
 652  
      * @throws IllegalArgumentException if daoAction does not represent a delegation-member-related enumeration value.
 653  
      */
 654  
     protected String getDelegationMemberListCacheKey(RoleDaoAction daoAction, String delegationId, String principalId, String groupId) {
 655  0
         switch (daoAction) {
 656  
             case DELEGATION_PRINCIPALS_FOR_PRINCIPAL_ID_AND_DELEGATION_IDS: // Search for principal delegation members.
 657  0
                 return new StringBuilder(DELEGATION_MEMBER_IMPL_LIST_CACHE_PREFIX).append(daoAction.DAO_ACTION_CACHE_PREFIX).append(
 658  
                         StringUtils.isBlank(delegationId) ? "" : delegationId).append('-').append(
 659  
                         StringUtils.isBlank(principalId) ? "" : principalId).toString();
 660  
             case DELEGATION_GROUPS_FOR_GROUP_IDS_AND_DELEGATION_IDS: // Search for group delegation members.
 661  0
                 return new StringBuilder(DELEGATION_MEMBER_IMPL_LIST_CACHE_PREFIX).append(daoAction.DAO_ACTION_CACHE_PREFIX).append(
 662  
                         StringUtils.isBlank(delegationId) ? "" : delegationId).append('-').append(StringUtils.isBlank(groupId) ? "" : groupId).toString();
 663  
             case DELEGATION_MEMBERS_FOR_DELEGATION_IDS: // Search for delegation members regardless of their member type.
 664  0
                 return new StringBuilder(DELEGATION_MEMBER_IMPL_LIST_CACHE_PREFIX).append(daoAction.DAO_ACTION_CACHE_PREFIX).append(
 665  
                         StringUtils.isBlank(delegationId) ? "" : delegationId).toString();
 666  
             default: // daoActionToTake is invalid; throw an exception.
 667  0
                 throw new IllegalArgumentException("The 'daoActionToTake' parameter cannot refer to a non-delegation-member-related value!");
 668  
         }
 669  
     }
 670  
 
 671  
     /**
 672  
      * Retrieves a List of delegation members from the cache and/or the KimRoleDao as appropriate.
 673  
      *
 674  
      * @param daoActionToTake An indicator for which KimRoleDao method to use for retrieving uncached results.
 675  
      * @param delegationIds   The IDs of the delegations that the members belong to.
 676  
      * @param principalId     The principal ID of the principal delegation members; may get ignored depending on the RoleDaoAction value.
 677  
      * @param groupIds        The group IDs of the group delegation members; may get ignored depending on the RoleDaoAction value.
 678  
      * @return A List of DelegateMemberBo objects based on the provided parameters.
 679  
      * @throws IllegalArgumentException if daoActionToTake does not represent a delegation-member-list-related enumeration value.
 680  
      */
 681  
     protected List<DelegateMemberBo> getDelegationMemberBoList(RoleDaoAction daoActionToTake, Collection<String> delegationIds,
 682  
                                                                String principalId, List<String> groupIds) {
 683  0
         List<DelegateMemberBo> finalResults = new ArrayList<DelegateMemberBo>();
 684  0
         List<String[]> uncachedKeys = new ArrayList<String[]>();
 685  0
         Set<String> usedKeys = new HashSet<String>();
 686  0
         if (delegationIds == null || delegationIds.isEmpty()) {
 687  0
             delegationIds = Collections.singletonList(null);
 688  
         }
 689  0
         if (groupIds == null || groupIds.isEmpty()) {
 690  0
             groupIds = Collections.singletonList(null);
 691  
         }
 692  
 
 693  
         // Search for cached values based on the intended search action.
 694  0
         switch (daoActionToTake) {
 695  
             case DELEGATION_PRINCIPALS_FOR_PRINCIPAL_ID_AND_DELEGATION_IDS: // Search for principal delegation members.
 696  0
                 for (String delegationId : delegationIds) {
 697  0
                     String tempKey = getDelegationMemberListCacheKey(daoActionToTake, delegationId, principalId, null);
 698  0
                     if (!usedKeys.contains(tempKey)) {
 699  0
                         List<DelegateMemberBo> tempMembers = (List<DelegateMemberBo>) getCacheAdministrator().getFromCache(tempKey);
 700  0
                         if (tempMembers != null) {
 701  0
                             finalResults.addAll(tempMembers);
 702  
                         } else {
 703  0
                             uncachedKeys.add(new String[]{delegationId, principalId, null});
 704  
                         }
 705  0
                         usedKeys.add(tempKey);
 706  
                     }
 707  0
                 }
 708  0
                 break;
 709  
             case DELEGATION_GROUPS_FOR_GROUP_IDS_AND_DELEGATION_IDS: // Search for group delegation members.
 710  0
                 for (String delegationId : delegationIds) {
 711  0
                     for (String groupId : groupIds) {
 712  0
                         String tempKey = getDelegationMemberListCacheKey(daoActionToTake, delegationId, null, groupId);
 713  0
                         if (!usedKeys.contains(tempKey)) {
 714  0
                             List<DelegateMemberBo> tempMembers = (List<DelegateMemberBo>) getCacheAdministrator().getFromCache(tempKey);
 715  0
                             if (tempMembers != null) {
 716  0
                                 finalResults.addAll(tempMembers);
 717  
                             } else {
 718  0
                                 uncachedKeys.add(new String[]{delegationId, null, groupId});
 719  
                             }
 720  
                         }
 721  0
                     }
 722  
                 }
 723  0
                 break;
 724  
             default: // daoActionToTake is invalid; throw an exception.
 725  0
                 throw new IllegalArgumentException("The 'daoActionToTake' parameter cannot refer to a non-delegation-member-list-related value!");
 726  
         }
 727  
 
 728  
         // Retrieve any uncached values based on the intended search action.
 729  0
         if (!uncachedKeys.isEmpty()) {
 730  0
             List<DelegateMemberBo> uncachedResults = new ArrayList<DelegateMemberBo>();
 731  0
             Set<String> uncachedDelegationSet = new HashSet<String>();
 732  0
             Set<String> uncachedGroupSet = new HashSet<String>();
 733  0
             for (String[] uncachedKey : uncachedKeys) {
 734  0
                 if (uncachedKey[0] != null) {
 735  0
                     uncachedDelegationSet.add(uncachedKey[0]);
 736  
                 }
 737  0
                 if (uncachedKey[2] != null) {
 738  0
                     uncachedGroupSet.add(uncachedKey[2]);
 739  
                 }
 740  
             }
 741  0
             List<String> uncachedDelegations = (uncachedDelegationSet.isEmpty()) ? null : new ArrayList<String>(uncachedDelegationSet);
 742  0
             List<String> uncachedGroups = (uncachedGroupSet.isEmpty()) ? null : new ArrayList<String>(uncachedGroupSet);
 743  0
             String memberTypeCode = null;
 744  
 
 745  
             // Search for uncached values based on the intended search action.
 746  0
             switch (daoActionToTake) {
 747  
                 case DELEGATION_PRINCIPALS_FOR_PRINCIPAL_ID_AND_DELEGATION_IDS: // Search for principal delegation members.
 748  0
                     uncachedResults = roleDao.getDelegationPrincipalsForPrincipalIdAndDelegationIds(uncachedDelegations, principalId);
 749  0
                     memberTypeCode = Role.PRINCIPAL_MEMBER_TYPE;
 750  0
                     break;
 751  
                 case DELEGATION_GROUPS_FOR_GROUP_IDS_AND_DELEGATION_IDS: // Search for group delegation members.
 752  0
                     uncachedResults = roleDao.getDelegationGroupsForGroupIdsAndDelegationIds(uncachedDelegations, uncachedGroups);
 753  0
                     memberTypeCode = Role.GROUP_MEMBER_TYPE;
 754  0
                     break;
 755  
                 default: // This should never happen since the previous switch block should handle this case appropriately.
 756  0
                     throw new IllegalArgumentException("The 'daoActionToTake' parameter cannot refer to a non-delegation-member-list-related value!");
 757  
             }
 758  
 
 759  
             // Cache the delegation members and add them to the final results.
 760  0
             cacheDelegationMemberLists(daoActionToTake, uncachedKeys, memberTypeCode, uncachedResults);
 761  0
             for (DelegateMemberBo uncachedResult : uncachedResults) {
 762  0
                 addDelegateMemberBoToCache(uncachedResult);
 763  
             }
 764  0
             finalResults.addAll(uncachedResults);
 765  
         }
 766  
 
 767  0
         return finalResults;
 768  
     }
 769  
 
 770  
     /**
 771  
      * Caches several Lists of delegation members that are constructed based on the given search parameters.
 772  
      *
 773  
      * @param daoActionToTake The enumeration constant representing the KimRoleDao call that returned the results.
 774  
      * @param uncachedKeys    The keys of the delegation member Lists that will be used to store the uncached results.
 775  
      * @param memberTypeCode  The member type code of all the delegation members in the uncached results.
 776  
      * @param uncachedMembers The uncached delegation members.
 777  
      */
 778  
     private void cacheDelegationMemberLists(RoleDaoAction daoActionToTake, List<String[]> uncachedKeys,
 779  
                                             String memberTypeCode, List<DelegateMemberBo> uncachedMembers) {
 780  
         // Place the uncached delegation members into the list cache appropriately.
 781  0
         for (String[] uncachedKey : uncachedKeys) {
 782  0
             List<DelegateMemberBo> tempMembers = new ArrayList<DelegateMemberBo>();
 783  0
             for (DelegateMemberBo uncachedMember : uncachedMembers) {
 784  0
                 if ((memberTypeCode == null || memberTypeCode.equals(uncachedMember.getTypeCode())) &&
 785  
                         (uncachedKey[0] == null || uncachedKey[0].equals(uncachedMember.getDelegationId())) &&
 786  
                         (uncachedKey[1] == null || uncachedKey[1].equals(uncachedMember.getMemberId())) &&
 787  
                         (uncachedKey[2] == null || uncachedKey[2].equals(uncachedMember.getMemberId()))) {
 788  0
                     tempMembers.add(uncachedMember);
 789  
                 }
 790  
             }
 791  0
             getCacheAdministrator().putInCache(getDelegationMemberListCacheKey(daoActionToTake, uncachedKey[0], uncachedKey[1], uncachedKey[2]),
 792  
                     tempMembers, DELEGATION_MEMBER_IMPL_CACHE_GROUP);
 793  0
         }
 794  0
     }
 795  
 
 796  
     /**
 797  
      * Calls the KimRoleDao's "getDelegationPrincipalsForPrincipalIdAndDelegationIds" method and/or retrieves any corresponding members from the cache.
 798  
      */
 799  
     protected List<DelegateMemberBo> getStoredDelegationPrincipalsForPrincipalIdAndDelegationIds(Collection<String> delegationIds, String principalId) {
 800  0
         return getDelegationMemberBoList(RoleDaoAction.DELEGATION_PRINCIPALS_FOR_PRINCIPAL_ID_AND_DELEGATION_IDS, delegationIds, principalId, null);
 801  
     }
 802  
 
 803  
     /**
 804  
      * Calls the KimRoleDao's "getDelegationGroupsForGroupIdAndDelegationIds" method and/or retrieves any corresponding members from the cache.
 805  
      */
 806  
     protected List<DelegateMemberBo> getStoredDelegationGroupsForGroupIdsAndDelegationIds(Collection<String> delegationIds, List<String> groupIds) {
 807  0
         return getDelegationMemberBoList(RoleDaoAction.DELEGATION_GROUPS_FOR_GROUP_IDS_AND_DELEGATION_IDS, delegationIds, null, groupIds);
 808  
     }
 809  
 
 810  
     /**
 811  
      * Calls the KimRoleDao's "getDelegationMembersForDelegationIds" method and/or retrieves any corresponding members from the cache.
 812  
      */
 813  
     protected Map<String, List<DelegateMemberBo>> getStoredDelegationMembersForDelegationIds(List<String> delegationIds) {
 814  0
         Map<String, List<DelegateMemberBo>> finalResults = new HashMap<String, List<DelegateMemberBo>>();
 815  0
         Set<String> uncachedDelegationIds = new HashSet<String>();
 816  0
         boolean idListWasNullOrEmpty = (delegationIds == null || delegationIds.isEmpty());
 817  0
         if (idListWasNullOrEmpty) {
 818  0
             delegationIds = Collections.singletonList(null);
 819  
         }
 820  
 
 821  
         // Retrieve any existing Lists from the cache.
 822  0
         for (String delegationId : delegationIds) {
 823  0
             List<DelegateMemberBo> tempMembers = (List<DelegateMemberBo>) getCacheAdministrator().getFromCache(
 824  
                     getDelegationMemberListCacheKey(RoleDaoAction.DELEGATION_MEMBERS_FOR_DELEGATION_IDS, delegationId, null, null));
 825  0
             if (tempMembers != null) {
 826  0
                 finalResults.put(delegationId, tempMembers);
 827  
             } else {
 828  0
                 uncachedDelegationIds.add(delegationId);
 829  
             }
 830  0
         }
 831  
 
 832  
         // Retrieve and cache any uncached results. If the initial delegation ID List was null or empty, then also cache a List holding all the results.
 833  0
         if (!uncachedDelegationIds.isEmpty()) {
 834  0
             List<String> uncachedIdsList = (idListWasNullOrEmpty) ? new ArrayList<String>() : new ArrayList<String>(uncachedDelegationIds);
 835  
 
 836  0
             Map<String, List<DelegateMemberBo>> tempMemberMap = roleDao.getDelegationMembersForDelegationIds(uncachedIdsList);
 837  0
             List<DelegateMemberBo> allMembers = new ArrayList<DelegateMemberBo>();
 838  
 
 839  0
             for (Map.Entry<String, List<DelegateMemberBo>> tempMemberEntry : tempMemberMap.entrySet()) {
 840  0
                 getCacheAdministrator().putInCache(getDelegationMemberListCacheKey(RoleDaoAction.DELEGATION_MEMBERS_FOR_DELEGATION_IDS,
 841  
                         tempMemberEntry.getKey(), null, null), tempMemberEntry.getValue(), DELEGATION_MEMBER_IMPL_CACHE_GROUP);
 842  0
                 for (DelegateMemberBo tempMember : tempMemberEntry.getValue()) {
 843  0
                     addDelegateMemberBoToCache(tempMember);
 844  
                 }
 845  0
                 if (idListWasNullOrEmpty) {
 846  0
                     allMembers.addAll(tempMemberEntry.getValue());
 847  
                 }
 848  0
                 finalResults.put(tempMemberEntry.getKey(), tempMemberEntry.getValue());
 849  
             }
 850  
 
 851  0
             if (idListWasNullOrEmpty) {
 852  0
                 getCacheAdministrator().putInCache(getDelegationMemberListCacheKey(RoleDaoAction.DELEGATION_MEMBERS_FOR_DELEGATION_IDS,
 853  
                         null, null, null), allMembers, DELEGATION_MEMBER_IMPL_CACHE_GROUP);
 854  
             }
 855  
         }
 856  
 
 857  0
         return finalResults;
 858  
     }
 859  
 
 860  
     protected void addDelegateMemberBoToCache(DelegateMemberBo delegateMember) {
 861  0
         if (delegateMember != null) {
 862  0
             getCacheAdministrator().putInCache(getDelegationMemberCacheKey(delegateMember.getDelegationMemberId()),
 863  
                     delegateMember, DELEGATION_MEMBER_IMPL_CACHE_GROUP);
 864  0
             getCacheAdministrator().putInCache(getDelegationMemberByDelegationAndIdCacheKey(
 865  
                     delegateMember.getDelegationId(), delegateMember.getDelegationMemberId()), delegateMember, DELEGATION_MEMBER_IMPL_CACHE_GROUP);
 866  
         }
 867  0
     }
 868  
 
 869  
     protected void addDelegationMemberBoListByMemberAndDelegationIdToCache(
 870  
             List<DelegateMemberBo> memberList, String memberId, String delegationId) {
 871  0
         if (memberList != null) {
 872  0
             getCacheAdministrator().putInCache(getDelegationMemberListByMemberAndDelegationIdCacheKey(memberId, delegationId),
 873  
                     memberList, DELEGATION_MEMBER_IMPL_CACHE_GROUP);
 874  
         }
 875  0
     }
 876  
 
 877  
     protected DelegateMemberBo getDelegationMemberFromCache(String delegationMemberId) {
 878  0
         return (DelegateMemberBo) getCacheAdministrator().getFromCache(getDelegationMemberCacheKey(delegationMemberId));
 879  
     }
 880  
 
 881  
     protected DelegateMemberBo getDelegationMemberByDelegationAndIdFromCache(String delegationId, String delegationMemberId) {
 882  0
         return (DelegateMemberBo) getCacheAdministrator().getFromCache(getDelegationMemberByDelegationAndIdCacheKey(
 883  
                 delegationId, delegationMemberId));
 884  
     }
 885  
 
 886  
     protected List<DelegateMemberBo> getDelegationMemberListByMemberAndDelegationIdFromCache(String memberId, String delegationId) {
 887  0
         return (List<DelegateMemberBo>)
 888  
                 getCacheAdministrator().getFromCache(getDelegationMemberListByMemberAndDelegationIdCacheKey(memberId, delegationId));
 889  
     }
 890  
 
 891  
     public void flushInternalDelegationMemberCache() {
 892  0
         getCacheAdministrator().flushGroup(DELEGATION_MEMBER_IMPL_CACHE_GROUP);
 893  0
     }
 894  
 
 895  
     /**
 896  
      * Retrieves a DelegateMemberBo object by its ID. If the delegation member already exists in the cache, this method will return the cached
 897  
      * version; otherwise, it will retrieve the uncached version from the database and then cache it before returning it.
 898  
      */
 899  
     protected DelegateMemberBo getDelegateMemberBo(String delegationMemberId) {
 900  0
         if (StringUtils.isBlank(delegationMemberId)) {
 901  0
             return null;
 902  
         }
 903  
 
 904  
         // If the DelegateMemberBo exists in the cache, return the cached one.
 905  0
         DelegateMemberBo tempDelegateMember = getDelegationMemberFromCache(delegationMemberId);
 906  0
         if (tempDelegateMember != null) {
 907  0
             return tempDelegateMember;
 908  
         }
 909  
         // Otherwise, retrieve it normally.
 910  0
         tempDelegateMember = (DelegateMemberBo) getBusinessObjectService().findByPrimaryKey(DelegateMemberBo.class,
 911  
                 Collections.singletonMap(KimConstants.PrimaryKeyConstants.DELEGATION_MEMBER_ID, delegationMemberId));
 912  0
         addDelegateMemberBoToCache(tempDelegateMember);
 913  0
         return tempDelegateMember;
 914  
     }
 915  
 
 916  
     /**
 917  
      * Retrieves a DelegateMemberBo object by its ID and the ID of the delegation it belongs to. If the delegation member exists in the cache,
 918  
      * this method will return the cached one; otherwise, it will retrieve the uncached version from the database and then cache it before returning it.
 919  
      */
 920  
     protected DelegateMemberBo getDelegationMemberBoByDelegationAndId(String delegationId, String delegationMemberId) {
 921  0
         if (StringUtils.isBlank(delegationId) || StringUtils.isBlank(delegationMemberId)) {
 922  0
             return null;
 923  
         }
 924  
 
 925  
         // If the DelegateMemberBo exists in the cache, return the cached one.
 926  0
         DelegateMemberBo tempDelegateMember = getDelegationMemberByDelegationAndIdFromCache(delegationId, delegationMemberId);
 927  0
         if (tempDelegateMember != null) {
 928  0
             return tempDelegateMember;
 929  
         }
 930  
         // Otherwise, retrieve it normally.
 931  0
         Map<String, String> searchCriteria = new HashMap<String, String>();
 932  0
         searchCriteria.put(KimConstants.PrimaryKeyConstants.DELEGATION_ID, delegationId);
 933  0
         searchCriteria.put(KimConstants.PrimaryKeyConstants.DELEGATION_MEMBER_ID, delegationMemberId);
 934  0
         List<DelegateMemberBo> memberList =
 935  
                 (List<DelegateMemberBo>) getBusinessObjectService().findMatching(DelegateMemberBo.class, searchCriteria);
 936  0
         if (memberList != null && !memberList.isEmpty()) {
 937  0
             tempDelegateMember = memberList.get(0);
 938  0
             addDelegateMemberBoToCache(tempDelegateMember);
 939  
         }
 940  0
         return tempDelegateMember;
 941  
     }
 942  
 
 943  
     /**
 944  
      * Retrieves a DelegateMemberBo List by (principal/group/role) member ID and delegation ID. If the List already exists in the cache,
 945  
      * this method will return the cached one; otherwise, it will retrieve the uncached version from the database and then cache it before returning it.
 946  
      */
 947  
     protected List<DelegateMemberBo> getDelegationMemberBoListByMemberAndDelegationId(String memberId, String delegationId) {
 948  
         // If the DelegateMemberBo List exists in the cache, return the cached one.
 949  0
         List<DelegateMemberBo> memberList = getDelegationMemberListByMemberAndDelegationIdFromCache(memberId, delegationId);
 950  0
         if (memberList != null) {
 951  0
             return memberList;
 952  
         }
 953  
 
 954  
         // Otherwise, retrieve it normally.
 955  0
         Map<String, String> searchCriteria = new HashMap<String, String>();
 956  0
         searchCriteria.put(KimConstants.PrimaryKeyConstants.MEMBER_ID, memberId);
 957  0
         searchCriteria.put(KimConstants.PrimaryKeyConstants.DELEGATION_ID, delegationId);
 958  0
         List<DelegateMemberBo> tempList =
 959  
                 (List<DelegateMemberBo>) getBusinessObjectService().findMatching(DelegateMemberBo.class, searchCriteria);
 960  0
         if (tempList != null && !tempList.isEmpty()) {
 961  0
             memberList = new ArrayList<DelegateMemberBo>();
 962  0
             memberList.addAll(tempList);
 963  0
             addDelegationMemberBoListByMemberAndDelegationIdToCache(memberList, memberId, delegationId);
 964  
         }
 965  0
         return memberList;
 966  
     }
 967  
 
 968  
     public void flushInternalRoleCache() {
 969  0
         getCacheAdministrator().flushGroup(ROLE_IMPL_CACHE_GROUP);
 970  0
     }
 971  
 
 972  
     public RoleMember findRoleMember(String roleMemberId) {
 973  0
         Map<String, String> fieldValues = new HashMap<String, String>();
 974  0
         fieldValues.put(KimConstants.PrimaryKeyConstants.ROLE_MEMBER_ID, roleMemberId);
 975  0
         List<RoleMember> roleMembers = findRoleMembers(fieldValues);
 976  0
         if (roleMembers != null && roleMembers.size() > 0) {
 977  0
             return roleMembers.get(0);
 978  
         }
 979  0
         return null;
 980  
     }
 981  
 
 982  
     public List<RoleMember> findRoleMembers(Map<String, String> fieldValues) {
 983  0
         List<RoleMember> roleMembers = new ArrayList<RoleMember>();
 984  0
         List<RoleMemberBo> roleMemberBos = (List<RoleMemberBo>) getLookupService().findCollectionBySearchHelper(
 985  
                 RoleMemberBo.class, fieldValues, true);
 986  
 
 987  0
         for (RoleMemberBo bo : roleMemberBos) {
 988  0
             RoleMember roleMember = RoleMemberBo.to(bo);
 989  0
             roleMembers.add(roleMember);
 990  0
         }
 991  0
         return roleMembers;
 992  
     }
 993  
 
 994  
     public List<RoleResponsibilityAction> getRoleMemberResponsibilityActions(String roleMemberId) {
 995  0
         Map<String, String> criteria = new HashMap<String, String>(1);
 996  0
         criteria.put(KimConstants.PrimaryKeyConstants.ROLE_MEMBER_ID, roleMemberId);
 997  
 
 998  0
         List<RoleResponsibilityActionBo> responsibilityActionBoList = (List<RoleResponsibilityActionBo>)
 999  
                 getBusinessObjectService().findMatching(RoleResponsibilityActionBo.class, criteria);
 1000  
 
 1001  0
         List<RoleResponsibilityAction> roleResponsibilityActionsList = new ArrayList<RoleResponsibilityAction>();
 1002  0
         for (RoleResponsibilityActionBo roleResponsibilityActionBo : responsibilityActionBoList) {
 1003  0
             RoleResponsibilityAction roleResponsibility = RoleResponsibilityActionBo.to(roleResponsibilityActionBo);
 1004  0
             roleResponsibilityActionsList.add(roleResponsibility);
 1005  0
         }
 1006  0
         return roleResponsibilityActionsList;
 1007  
     }
 1008  
 
 1009  
     public List<DelegateMember> findDelegateMembers(final Map<String, String> fieldValues) {
 1010  0
         List<DelegateMember> delegateMembers = new ArrayList<DelegateMember>();
 1011  0
         List<DelegateBo> delegateBoList = (List<DelegateBo>) getLookupService().findCollectionBySearchHelper(
 1012  
                 DelegateBo.class, fieldValues, true);
 1013  
 
 1014  0
         if (delegateBoList != null && !delegateBoList.isEmpty()) {
 1015  0
             Map<String, String> delegationMemberFieldValues = new HashMap<String, String>();
 1016  0
             for (String key : fieldValues.keySet()) {
 1017  0
                 if (key.startsWith(KimConstants.KimUIConstants.MEMBER_ID_PREFIX)) {
 1018  0
                     delegationMemberFieldValues.put(
 1019  
                             key.substring(key.indexOf(
 1020  
                                     KimConstants.KimUIConstants.MEMBER_ID_PREFIX) + KimConstants.KimUIConstants.MEMBER_ID_PREFIX.length()),
 1021  
                             fieldValues.get(key));
 1022  
                 }
 1023  
             }
 1024  
 
 1025  0
             StringBuffer memberQueryString = new StringBuffer();
 1026  0
             for (DelegateBo delegate : delegateBoList) {
 1027  0
                 memberQueryString.append(delegate.getDelegationId() + KimConstants.KimUIConstants.OR_OPERATOR);
 1028  
             }
 1029  0
             delegationMemberFieldValues.put(KimConstants.PrimaryKeyConstants.DELEGATION_ID,
 1030  
                     StringUtils.stripEnd(memberQueryString.toString(), KimConstants.KimUIConstants.OR_OPERATOR));
 1031  0
             List<DelegateMemberBo> delegateMemberBoList = (List<DelegateMemberBo>) getLookupService().findCollectionBySearchHelper(
 1032  
                     DelegateMemberBo.class, delegationMemberFieldValues, true);
 1033  
 
 1034  
 
 1035  0
             for (DelegateMemberBo delegateMemberBo : delegateMemberBoList) {
 1036  0
                 DelegateMember delegateMember = DelegateMemberBo.to(delegateMemberBo);
 1037  0
                 delegateMembers.add(delegateMember);
 1038  0
             }
 1039  
         }
 1040  0
         return delegateMembers;
 1041  
     }
 1042  
 
 1043  
     protected DelegateBo getDelegationImpl(List<DelegateBo> delegates, String delegationId) {
 1044  0
         if (StringUtils.isEmpty(delegationId) || delegates == null) {
 1045  0
             return null;
 1046  
         }
 1047  0
         for (DelegateBo delegate : delegates) {
 1048  0
             if (StringUtils.equals(delegate.getDelegationId(), delegationId)) {
 1049  0
                 return delegate;
 1050  
             }
 1051  
         }
 1052  0
         return null;
 1053  
     }
 1054  
 
 1055  
     protected Object getMember(String memberTypeCode, String memberId) {
 1056  0
         if (StringUtils.isBlank(memberId)) {
 1057  0
             return null;
 1058  
         }
 1059  0
         if (KimConstants.KimUIConstants.MEMBER_TYPE_PRINCIPAL_CODE.equals(memberTypeCode)) {
 1060  0
             return getIdentityService().getPrincipal(memberId);
 1061  0
         } else if (KimConstants.KimUIConstants.MEMBER_TYPE_GROUP_CODE.equals(memberTypeCode)) {
 1062  0
             return getGroupService().getGroup(memberId);
 1063  0
         } else if (KimConstants.KimUIConstants.MEMBER_TYPE_ROLE_CODE.equals(memberTypeCode)) {
 1064  0
             return getRoleBo(memberId);
 1065  
         }
 1066  0
         return null;
 1067  
     }
 1068  
 
 1069  
     protected String getMemberName(Object member) {
 1070  0
         if (member == null) {
 1071  0
             return "";
 1072  
         }
 1073  0
         if (member instanceof Principal) {
 1074  0
             return ((Principal) member).getPrincipalName();
 1075  
         }
 1076  0
         if (member instanceof Group) {
 1077  0
             return ((Group) member).getName();
 1078  
         }
 1079  0
         if (member instanceof Role) {
 1080  0
             return ((Role) member).getName();
 1081  
         }
 1082  0
         return member.toString();
 1083  
     }
 1084  
 
 1085  
     protected String getMemberNamespaceCode(Object member) {
 1086  0
         if (member == null) {
 1087  0
             return "";
 1088  
         }
 1089  0
         if (member instanceof Principal) {
 1090  0
             return "";
 1091  
         }
 1092  0
         if (member instanceof Group) {
 1093  0
             return ((Group) member).getNamespaceCode();
 1094  
         }
 1095  0
         if (member instanceof Role) {
 1096  0
             return ((Role) member).getNamespaceCode();
 1097  
         }
 1098  0
         return "";
 1099  
     }
 1100  
 
 1101  
     protected RoleBo getRoleBo(String roleId) {
 1102  0
         if (StringUtils.isBlank(roleId)) {
 1103  0
             return null;
 1104  
         }
 1105  
         // check for a non-null result in the cache, return it if found
 1106  0
         RoleBo cachedResult = getRoleFromCache(roleId);
 1107  0
         if (cachedResult != null) {
 1108  0
             return cachedResult;
 1109  
         }
 1110  
         // otherwise, run the query
 1111  0
         RoleBo result = (RoleBo) getBusinessObjectService().findBySinglePrimaryKey(RoleBo.class, roleId);
 1112  0
         addRoleBoToCache(result);
 1113  0
         return result;
 1114  
     }
 1115  
 
 1116  
     protected DelegateBo getDelegationOfType(String roleId, String delegationTypeCode) {
 1117  0
         List<DelegateBo> roleDelegates = getRoleDelegations(roleId);
 1118  0
         if (isDelegationPrimary(delegationTypeCode)) {
 1119  0
             return getPrimaryDelegation(roleId, roleDelegates);
 1120  
         } else {
 1121  0
             return getSecondaryDelegation(roleId, roleDelegates);
 1122  
         }
 1123  
     }
 1124  
 
 1125  
     private DelegateBo getSecondaryDelegation(String roleId, List<DelegateBo> roleDelegates) {
 1126  0
         DelegateBo secondaryDelegate = null;
 1127  0
         RoleBo roleBo = getRoleBo(roleId);
 1128  0
         for (DelegateBo delegate : roleDelegates) {
 1129  0
             if (isDelegationSecondary(delegate.getDelegationTypeCode())) {
 1130  0
                 secondaryDelegate = delegate;
 1131  
             }
 1132  
         }
 1133  0
         if (secondaryDelegate == null) {
 1134  0
             secondaryDelegate = new DelegateBo();
 1135  0
             secondaryDelegate.setRoleId(roleId);
 1136  0
             secondaryDelegate.setDelegationId(getNewDelegationId());
 1137  0
             secondaryDelegate.setDelegationTypeCode(DelegationType.PRIMARY.getCode());
 1138  0
             secondaryDelegate.setKimTypeId(roleBo.getKimTypeId());
 1139  
         }
 1140  0
         return secondaryDelegate;
 1141  
     }
 1142  
 
 1143  
     protected DelegateBo getPrimaryDelegation(String roleId, List<DelegateBo> roleDelegates) {
 1144  0
         DelegateBo primaryDelegate = null;
 1145  0
         RoleBo roleBo = getRoleBo(roleId);
 1146  0
         for (DelegateBo delegate : roleDelegates) {
 1147  0
             if (isDelegationPrimary(delegate.getDelegationTypeCode())) {
 1148  0
                 primaryDelegate = delegate;
 1149  
             }
 1150  
         }
 1151  0
         if (primaryDelegate == null) {
 1152  0
             primaryDelegate = new DelegateBo();
 1153  0
             primaryDelegate.setRoleId(roleId);
 1154  0
             primaryDelegate.setDelegationId(getNewDelegationId());
 1155  0
             primaryDelegate.setDelegationTypeCode(DelegationType.PRIMARY.getCode());
 1156  0
             primaryDelegate.setKimTypeId(roleBo.getKimTypeId());
 1157  
         }
 1158  0
         return primaryDelegate;
 1159  
     }
 1160  
 
 1161  
     protected RoleMemberBo matchingMemberRecord(List<RoleMemberBo> roleMembers, String memberId, String memberTypeCode, Map<String, String> qualifier) {
 1162  0
         for (RoleMemberBo rm : roleMembers) {
 1163  0
             if (doesMemberMatch(rm, memberId, memberTypeCode, qualifier)) {
 1164  0
                 return rm;
 1165  
             }
 1166  
         }
 1167  0
         return null;
 1168  
     }
 1169  
 
 1170  
     protected boolean isDelegationPrimary(String delegationTypeCode) {
 1171  0
         return DelegationType.PRIMARY.getCode().equals(delegationTypeCode);
 1172  
     }
 1173  
 
 1174  
     protected boolean isDelegationSecondary(String delegationTypeCode) {
 1175  0
         return DelegationType.PRIMARY.getCode().equals(delegationTypeCode);
 1176  
     }
 1177  
 
 1178  
 
 1179  
     private List<DelegateBo> getRoleDelegations(String roleId) {
 1180  0
         if (roleId == null) {
 1181  0
             return new ArrayList<DelegateBo>();
 1182  
         }
 1183  0
         return getStoredDelegationImplsForRoleIds(Collections.singletonList(roleId));
 1184  
 
 1185  
     }
 1186  
 
 1187  
     protected RoleBo getRoleBoByName(String namespaceCode, String roleName) {
 1188  0
         if (StringUtils.isBlank(namespaceCode)
 1189  
                 || StringUtils.isBlank(roleName)) {
 1190  0
             return null;
 1191  
         }
 1192  
         // check for a non-null result in the cache, return it if found
 1193  0
         RoleBo cachedResult = getRoleFromCache(namespaceCode, roleName);
 1194  0
         if (cachedResult != null) {
 1195  0
             return cachedResult;
 1196  
         }
 1197  0
         Map<String, String> criteria = new HashMap<String, String>();
 1198  0
         criteria.put(KimConstants.UniqueKeyConstants.NAMESPACE_CODE, namespaceCode);
 1199  0
         criteria.put(KimConstants.UniqueKeyConstants.NAME, roleName);
 1200  0
         criteria.put(KRADPropertyConstants.ACTIVE, "Y");
 1201  
         // while this is not actually the primary key - there will be at most one row with these criteria
 1202  0
         RoleBo result = getBusinessObjectService().findByPrimaryKey(RoleBo.class, criteria);
 1203  0
         addRoleBoToCache(result);
 1204  0
         return result;
 1205  
     }
 1206  
 
 1207  
     protected boolean doAnyMemberRecordsMatch(List<RoleMemberBo> roleMembers, String memberId, String memberTypeCode, Map<String, String> qualifier) {
 1208  0
         for (RoleMemberBo rm : roleMembers) {
 1209  0
             if (doesMemberMatch(rm, memberId, memberTypeCode, qualifier)) {
 1210  0
                 return true;
 1211  
             }
 1212  
         }
 1213  0
         return false;
 1214  
     }
 1215  
 
 1216  
     protected boolean doesMemberMatch(RoleMemberBo roleMember, String memberId, String memberTypeCode, Map<String, String> qualifier) {
 1217  0
         if (roleMember.getMemberId().equals(memberId) && roleMember.getMemberTypeCode().equals(memberTypeCode)) {
 1218  
             // member ID/type match
 1219  0
             Map<String, String> roleQualifier = roleMember.getAttributes();
 1220  0
             if ((qualifier == null || qualifier.isEmpty())
 1221  
                     && (roleQualifier == null || roleQualifier.isEmpty())) {
 1222  0
                 return true; // blank qualifier match
 1223  
             } else {
 1224  0
                 if (qualifier != null && roleQualifier != null && qualifier.equals(roleQualifier)) {
 1225  0
                     return true; // qualifier match
 1226  
                 }
 1227  
             }
 1228  
         }
 1229  0
         return false;
 1230  
     }
 1231  
 
 1232  
     /**
 1233  
      * This method tests to see if assigning a roleBo to another roleBo will create a circular reference.
 1234  
      * The Role is checked to see if it is a member (direct or nested) of the roleBo to be assigned as a member.
 1235  
      *
 1236  
      * @param newMemberId
 1237  
      * @param roleBo
 1238  
      * @return true  - assignment is allowed, no circular reference will be created.
 1239  
      *         false - illegal assignment, it will create a circular membership
 1240  
      */
 1241  
     protected boolean checkForCircularRoleMembership(String newMemberId, RoleBo roleBo) {
 1242  
         // get all nested roleBo members that are of type roleBo
 1243  0
         Set<String> newRoleMemberIds = getRoleTypeRoleMemberIds(newMemberId);
 1244  0
         if (newRoleMemberIds.contains(roleBo.getId())) {
 1245  0
             return false;
 1246  
         }
 1247  0
         return true;
 1248  
     }
 1249  
 
 1250  
     // TODO: pulling attribute IDs repeatedly is inefficient - consider caching the entire list as a map
 1251  
     @SuppressWarnings("unchecked")
 1252  
     protected String getKimAttributeId(String attributeName) {
 1253  0
         String result = null;
 1254  0
         Map<String, Object> critieria = new HashMap<String, Object>(1);
 1255  0
         critieria.put("attributeName", attributeName);
 1256  0
         Collection<KimAttributeBo> defs = getBusinessObjectService().findMatching(KimAttributeBo.class, critieria);
 1257  0
         if (CollectionUtils.isNotEmpty(defs)) {
 1258  0
             result = defs.iterator().next().getId();
 1259  
         }
 1260  0
         return result;
 1261  
     }
 1262  
 
 1263  
     /**
 1264  
      * @return the applicationRoleTypeCache
 1265  
      */
 1266  
     protected Map<String, Boolean> getApplicationRoleTypeCache() {
 1267  0
         return this.applicationRoleTypeCache;
 1268  
     }
 1269  
 
 1270  
     /**
 1271  
      * @return the roleTypeServiceCache
 1272  
      */
 1273  
     protected Map<String, KimRoleTypeService> getRoleTypeServiceCache() {
 1274  0
         return this.roleTypeServiceCache;
 1275  
     }
 1276  
 
 1277  
     /**
 1278  
      * @return the delegationTypeServiceCache
 1279  
      */
 1280  
     protected Map<String, KimDelegationTypeService> getDelegationTypeServiceCache() {
 1281  0
         return this.delegationTypeServiceCache;
 1282  
     }
 1283  
 
 1284  
     protected String getRoleCacheKey(String roleId) {
 1285  0
         return ROLE_IMPL_CACHE_PREFIX + roleId;
 1286  
     }
 1287  
 
 1288  
     protected String getRoleByNameCacheKey(String namespaceCode, String roleName) {
 1289  0
         return ROLE_IMPL_BY_NAME_CACHE_PREFIX + namespaceCode + "-" + roleName;
 1290  
     }
 1291  
 
 1292  
     protected void addRoleBoToCache(RoleBo roleBo) {
 1293  0
         if (roleBo != null) {
 1294  0
             getCacheAdministrator().putInCache(getRoleCacheKey(roleBo.getId()), roleBo, ROLE_IMPL_CACHE_GROUP);
 1295  0
             getCacheAdministrator().putInCache(getRoleByNameCacheKey(roleBo.getNamespaceCode(), roleBo.getName()), roleBo, ROLE_IMPL_CACHE_GROUP);
 1296  
         }
 1297  0
     }
 1298  
 
 1299  
     protected RoleBo getRoleFromCache(String roleId) {
 1300  0
         return (RoleBo) getCacheAdministrator().getFromCache(getRoleCacheKey(roleId));
 1301  
     }
 1302  
 
 1303  
     protected RoleBo getRoleFromCache(String namespaceCode, String roleName) {
 1304  0
         return (RoleBo) getCacheAdministrator().getFromCache(getRoleByNameCacheKey(namespaceCode, roleName));
 1305  
     }
 1306  
 
 1307  
     protected String getNewDelegationId() {
 1308  0
         SequenceAccessorService sas = getSequenceAccessorService();
 1309  0
         Long nextSeq = sas.getNextAvailableSequenceNumber(
 1310  
                 KimConstants.SequenceNames.KRIM_DLGN_ID_S,
 1311  
                 DelegateBo.class);
 1312  0
         return nextSeq.toString();
 1313  
     }
 1314  
 
 1315  
     protected String getNewAttributeDataId() {
 1316  0
         SequenceAccessorService sas = getSequenceAccessorService();
 1317  0
         Long nextSeq = sas.getNextAvailableSequenceNumber(
 1318  
                 KimConstants.SequenceNames.KRIM_ATTR_DATA_ID_S,
 1319  
                 RoleMemberAttributeDataBo.class);
 1320  0
         return nextSeq.toString();
 1321  
     }
 1322  
 
 1323  
     protected String getNewDelegationMemberId() {
 1324  0
         SequenceAccessorService sas = getSequenceAccessorService();
 1325  0
         Long nextSeq = sas.getNextAvailableSequenceNumber(
 1326  
                 KimConstants.SequenceNames.KRIM_DLGN_MBR_ID_S,
 1327  
                 DelegateBo.class);
 1328  0
         return nextSeq.toString();
 1329  
     }
 1330  
 
 1331  
     protected BusinessObjectService getBusinessObjectService() {
 1332  0
         if (businessObjectService == null) {
 1333  0
             businessObjectService = KRADServiceLocator.getBusinessObjectService();
 1334  
         }
 1335  0
         return businessObjectService;
 1336  
     }
 1337  
 
 1338  
     /**
 1339  
      * @return the lookupService
 1340  
      */
 1341  
     protected LookupService getLookupService() {
 1342  0
         if (lookupService == null) {
 1343  0
             lookupService = KRADServiceLocatorWeb.getLookupService();
 1344  
         }
 1345  0
         return lookupService;
 1346  
     }
 1347  
 
 1348  
     protected RiceCacheAdministrator getCacheAdministrator() {
 1349  0
         if (cacheAdministrator == null) {
 1350  0
             cacheAdministrator = KsbApiServiceLocator.getCacheAdministrator();
 1351  
         }
 1352  0
         return cacheAdministrator;
 1353  
     }
 1354  
 
 1355  
     protected IdentityService getIdentityService() {
 1356  0
         if (identityService == null) {
 1357  0
             identityService = KimApiServiceLocator.getIdentityService();
 1358  
         }
 1359  
 
 1360  0
         return identityService;
 1361  
     }
 1362  
     
 1363  
     protected GroupService getGroupService() {
 1364  0
         if (groupService == null) {
 1365  0
             groupService = KimApiServiceLocator.getGroupService();
 1366  
         }
 1367  
 
 1368  0
         return groupService;
 1369  
     }
 1370  
 
 1371  
     protected SequenceAccessorService getSequenceAccessorService() {
 1372  0
         if (sequenceAccessorService == null) {
 1373  0
             sequenceAccessorService = KRADServiceLocator.getSequenceAccessorService();
 1374  
         }
 1375  0
         return sequenceAccessorService;
 1376  
     }
 1377  
 
 1378  
     protected ResponsibilityInternalService getResponsibilityInternalService() {
 1379  0
         if (responsibilityInternalService == null) {
 1380  0
             responsibilityInternalService = KIMServiceLocatorInternal.getResponsibilityInternalService();
 1381  
         }
 1382  0
         return responsibilityInternalService;
 1383  
     }
 1384  
 
 1385  
     protected IdentityManagementNotificationService getIdentityManagementNotificationService() {
 1386  0
         return (IdentityManagementNotificationService) KsbApiServiceLocator.getMessageHelper().getServiceAsynchronously(new QName("KIM", "kimIdentityManagementNotificationService"));
 1387  
     }
 1388  
 
 1389  
     /**
 1390  
      * An internal helper class for encapsulating the information related to generating a key for a RoleMemberBo list.
 1391  
      *
 1392  
      * @author Kuali Rice Team (rice.collab@kuali.org)
 1393  
      */
 1394  0
     private class RoleMemberCacheKeyHelper {
 1395  
         private final RoleDaoAction ROLE_DAO_ACTION;
 1396  
         private final String ROLE_ID;
 1397  
         private final String PRINCIPAL_ID;
 1398  
         private final String GROUP_ID;
 1399  
         private final String MEMBER_TYPE_CODE;
 1400  
         private String cacheKey;
 1401  
 
 1402  0
         private RoleMemberCacheKeyHelper(RoleDaoAction roleDaoAction, String roleId, String principalId, String groupId, String memberTypeCode) {
 1403  0
             this.ROLE_DAO_ACTION = roleDaoAction;
 1404  0
             this.ROLE_ID = roleId;
 1405  0
             this.PRINCIPAL_ID = principalId;
 1406  0
             this.GROUP_ID = groupId;
 1407  0
             this.MEMBER_TYPE_CODE = memberTypeCode;
 1408  0
         }
 1409  
 
 1410  
         private String getCacheKey() {
 1411  0
             if (this.cacheKey == null) {
 1412  0
                 this.cacheKey = getRoleMemberListCacheKey(ROLE_DAO_ACTION, ROLE_ID, PRINCIPAL_ID, GROUP_ID, MEMBER_TYPE_CODE);
 1413  
             }
 1414  0
             return this.cacheKey;
 1415  
         }
 1416  
     }
 1417  
 
 1418  
     /**
 1419  
      * @return the roleDao
 1420  
      */
 1421  
     public RoleDao getRoleDao() {
 1422  0
         return this.roleDao;
 1423  
     }
 1424  
 
 1425  
     /**
 1426  
      * @param roleDao the roleDao to set
 1427  
      */
 1428  
     public void setRoleDao(RoleDao roleDao) {
 1429  0
         this.roleDao = roleDao;
 1430  0
     }
 1431  
 
 1432  
 }