private static Map<String, String> getKimMemberTypesMap() {
   Map<String, String> kimDocumentActionsMap = new HashMap<String, String>();
   kimDocumentActionsMap.put(MemberType.PRINCIPAL.getCode(), MEMBER_TYPE_PRINCIPAL);
   kimDocumentActionsMap.put(MemberType.GROUP.getCode(), MEMBER_TYPE_GROUP);
   kimDocumentActionsMap.put(MemberType.ROLE.getCode(), MEMBER_TYPE_ROLE);
   return kimDocumentActionsMap;
 }
  @Override
  public List<Long> getWorkAreasForPrincipalInRoles(
      String principalId, List<String> roleIds, DateTime asOfDate, boolean isActiveOnly) {
    Set<Long> workAreas = new HashSet<Long>();

    // iterate through the role ids getting the work areas for each one
    for (String roleId : roleIds) {
      // get the role for the role id from the role service
      Role role = getRoleService().getRole(roleId);
      if (role != null) {
        String roleName = role.getName();
        String namespaceCode = role.getNamespaceCode();

        Map<String, String> qualifiers = new HashMap<String, String>();
        // empty qualifier map will match any attribute in the predicate query, i.e. will work like
        // wildcarded entries
        List<Map<String, String>> roleQualifiers = new ArrayList<Map<String, String>>();
        List<RoleMember> principalAndGroupRoleMembers =
            getRoleMembers(namespaceCode, roleName, qualifiers, asOfDate, isActiveOnly);
        for (RoleMember roleMember : principalAndGroupRoleMembers) {
          // check for principals or groups
          if (MemberType.PRINCIPAL.equals(roleMember.getType())) {
            if (roleMember.getMemberId().equals(principalId)) {
              roleQualifiers.add(roleMember.getAttributes());
            }
          } else if (MemberType.GROUP.equals(roleMember.getType())) {
            // query the helper to see if the principal is a member of this nested member group
            Group nestedGroup = getGroupService().getGroup(roleMember.getMemberId());
            if (getRoleServiceHelper()
                .isMemberOfGroup(principalId, nestedGroup, asOfDate, isActiveOnly)) {
              roleQualifiers.add(roleMember.getAttributes());
            }
          }
        }

        for (Map<String, String> roleQualifier : roleQualifiers) {
          Long workArea =
              MapUtils.getLong(
                  roleQualifier, KPMERoleMemberAttribute.WORK_AREA.getRoleMemberAttributeName());
          if (workArea != null) {
            workAreas.add(workArea);
          }
        }
      }
    }

    List<String> departments =
        getDepartmentsForPrincipalInRoles(principalId, roleIds, asOfDate, isActiveOnly);
    workAreas.addAll(
        getWorkAreaService().getWorkAreasForDepartments(departments, asOfDate.toLocalDate()));

    return new ArrayList<Long>(workAreas);
  }
 protected boolean checkDelegationMember(RoleDocumentDelegationMember newMember) {
   if (StringUtils.isBlank(newMember.getMemberTypeCode())
       || StringUtils.isBlank(newMember.getMemberId())) {
     GlobalVariables.getMessageMap()
         .putError(
             "document.delegationMember.memberId",
             RiceKeyConstants.ERROR_EMPTY_ENTRY,
             new String[] {"Member Type Code and Member ID"});
     return false;
   }
   if (MemberType.PRINCIPAL.getCode().equals(newMember.getMemberTypeCode())) {
     Principal principalInfo = getIdentityService().getPrincipal(newMember.getMemberId());
     if (principalInfo == null) {
       GlobalVariables.getMessageMap()
           .putError(
               "document.delegationMember.memberId",
               RiceKeyConstants.ERROR_MEMBERID_MEMBERTYPE_MISMATCH,
               new String[] {newMember.getMemberId()});
       return false;
     } else {
       newMember.setMemberName(principalInfo.getPrincipalName());
     }
   } else if (MemberType.GROUP.getCode().equals(newMember.getMemberTypeCode())) {
     Group groupInfo = null;
     groupInfo = getGroupService().getGroup(newMember.getMemberId());
     if (groupInfo == null) {
       GlobalVariables.getMessageMap()
           .putError(
               "document.delegationMember.memberId",
               RiceKeyConstants.ERROR_MEMBERID_MEMBERTYPE_MISMATCH,
               new String[] {newMember.getMemberId()});
       return false;
     } else {
       newMember.setMemberName(groupInfo.getName());
       newMember.setMemberNamespaceCode(groupInfo.getNamespaceCode());
     }
   } else if (MemberType.ROLE.getCode().equals(newMember.getMemberTypeCode())) {
     Role roleInfo = KimApiServiceLocator.getRoleService().getRole(newMember.getMemberId());
     if (roleInfo == null) {
       GlobalVariables.getMessageMap()
           .putError(
               "document.delegationMember.memberId",
               RiceKeyConstants.ERROR_MEMBERID_MEMBERTYPE_MISMATCH,
               new String[] {newMember.getMemberId()});
       return false;
     } else {
       newMember.setMemberName(roleInfo.getName());
       newMember.setMemberNamespaceCode(roleInfo.getNamespaceCode());
     }
   }
   return true;
 }
  protected boolean checkKimDocumentRoleMember(KimDocumentRoleMember newMember) {
    boolean memberExists = false;
    String memberName = null;
    String memberNamespace = null;

    if (StringUtils.isBlank(newMember.getMemberId())) {
      GlobalVariables.getMessageMap()
          .putError(
              "document.member.memberId",
              RiceKeyConstants.ERROR_EMPTY_ENTRY,
              new String[] {"Member ID"});
      return false;
    }

    if (MemberType.PRINCIPAL.getCode().equals(newMember.getMemberTypeCode())) {
      Principal pi = this.getIdentityService().getPrincipal(newMember.getMemberId());
      if (pi != null) {
        memberExists = true;
        memberName = pi.getPrincipalName();
        memberNamespace = "";
      }
    } else if (MemberType.GROUP.getCode().equals(newMember.getMemberTypeCode())) {
      Group gi = KimApiServiceLocator.getGroupService().getGroup(newMember.getMemberId());
      if (gi != null) {
        memberExists = true;
        memberName = gi.getName();
        memberNamespace = gi.getNamespaceCode();
      }
    } else if (MemberType.ROLE.getCode().equals(newMember.getMemberTypeCode())) {
      Role ri = KimApiServiceLocator.getRoleService().getRole(newMember.getMemberId());
      if (!validateRole(newMember.getMemberId(), ri, "document.member.memberId", "Role")) {
        return false;
      } else {
        memberExists = true;
        memberName = ri.getName();
        memberNamespace = ri.getNamespaceCode();
      }
    }

    if (!memberExists) {
      GlobalVariables.getMessageMap()
          .putError(
              "document.member.memberId",
              RiceKeyConstants.ERROR_MEMBERID_MEMBERTYPE_MISMATCH,
              new String[] {newMember.getMemberId()});
      return false;
    }
    newMember.setMemberName(memberName);
    newMember.setMemberNamespaceCode(memberNamespace);
    return true;
  }
  /**
   * Helper method to get the role member objects.
   *
   * @param principalId The person to get the role for
   * @param roleIds The role
   * @param asOfDate The effective date of the role
   * @param activeOnly Whether or not to consider only active role members
   * @return the list of role member objects
   */
  private List<RoleMember> getPrincipalIdRoleMembers(
      String principalId, List<String> roleIds, DateTime asOfDate, boolean activeOnly) {
    List<String> groupIds = getGroupService().getGroupIdsByPrincipalId(principalId);

    List<Predicate> predicates = new ArrayList<Predicate>();
    predicates.add(
        in(
            KimConstants.PrimaryKeyConstants.SUB_ROLE_ID,
            roleIds.toArray(new String[roleIds.size()])));

    List<Predicate> principalPredicates = new ArrayList<Predicate>();
    principalPredicates.add(
        equal(KIMPropertyConstants.RoleMember.MEMBER_TYPE_CODE, MemberType.PRINCIPAL.getCode()));
    if (principalId != null) {
      principalPredicates.add(equal(KIMPropertyConstants.RoleMember.MEMBER_ID, principalId));
    }
    Predicate principalPredicate = and(principalPredicates.toArray(new Predicate[] {}));

    Predicate rolePredicate =
        equal(KIMPropertyConstants.RoleMember.MEMBER_TYPE_CODE, MemberType.ROLE.getCode());

    List<Predicate> groupPredicates = new ArrayList<Predicate>();
    groupPredicates.add(
        equal(KIMPropertyConstants.RoleMember.MEMBER_TYPE_CODE, MemberType.GROUP.getCode()));
    if (CollectionUtils.isNotEmpty(groupIds)) {
      groupPredicates.add(
          in(KIMPropertyConstants.RoleMember.MEMBER_ID, groupIds.toArray(new String[] {})));
    }
    Predicate groupPredicate = and(groupPredicates.toArray(new Predicate[] {}));

    predicates.add(or(principalPredicate, rolePredicate, groupPredicate));

    if (activeOnly) {
      predicates.add(
          or(isNull("activeFromDateValue"), lessThanOrEqual("activeFromDateValue", asOfDate)));
      predicates.add(or(isNull("activeToDateValue"), greaterThan("activeToDateValue", asOfDate)));
    }

    return getRoleService()
        .findRoleMembers(
            QueryByCriteria.Builder.fromPredicates(predicates.toArray(new Predicate[] {})))
        .getResults();
  }
  // TODO the else pathway below will return only the top level members and not resolve the nested
  // roles + groups.
  private List<Map<String, String>> getRoleQualifiers(
      String principalId,
      List<String> roleIds,
      Map<String, String> qualifiers,
      DateTime asOfDate,
      boolean activeOnly) {
    List<Map<String, String>> roleQualifiers = new ArrayList<Map<String, String>>();

    if (CollectionUtils.isNotEmpty(roleIds)) {
      if (asOfDate.equals(LocalDate.now().toDateTimeAtStartOfDay()) && activeOnly) {
        List<String> groupIds = getGroupService().getGroupIdsByPrincipalId(principalId);
        List<RoleMembership> principalAndGroupRoleMembers =
            getRoleService().getRoleMembers(roleIds, qualifiers);
        for (RoleMembership roleMember : principalAndGroupRoleMembers) {
          // check for principals or groups
          if (MemberType.PRINCIPAL.equals(roleMember.getType())) {
            if (roleMember.getMemberId().equals(principalId)) {
              roleQualifiers.add(roleMember.getQualifier());
            }
          } else if ((MemberType.GROUP.equals(roleMember.getType()))
              && (CollectionUtils.isNotEmpty(groupIds))) {
            if (groupIds.contains(roleMember.getMemberId())) {
              roleQualifiers.add(roleMember.getQualifier());
            }
          }
        }
      } else {
        List<RoleMember> principalIdRoleMembers =
            getPrincipalIdRoleMembers(principalId, roleIds, asOfDate, activeOnly);
        for (RoleMember principalIdRoleMember : principalIdRoleMembers) {
          roleQualifiers.add(principalIdRoleMember.getAttributes());
        }
      }
    }

    return roleQualifiers;
  }
  public boolean principalHasRole(
      String principalId,
      String namespaceCode,
      String roleName,
      Map<String, String> qualification,
      DateTime asOfDate) {
    boolean principalHasRole = false;

    String roleId = getRoleService().getRoleIdByNamespaceCodeAndName(namespaceCode, roleName);

    if (roleId == null) {
      return false;
    }
    if (asOfDate.compareTo(LocalDate.now().toDateTimeAtStartOfDay()) == 0) {
      principalHasRole =
          getRoleService()
              .principalHasRole(principalId, Collections.singletonList(roleId), qualification);
    } else {
      List<RoleMember> roleMembers =
          getRoleMembers(namespaceCode, roleName, qualification, asOfDate, true);

      for (RoleMember roleMember : roleMembers) {
        if (MemberType.PRINCIPAL.equals(roleMember.getType())) {
          if (StringUtils.equals(roleMember.getMemberId(), principalId)) {
            principalHasRole = true;
            break;
          }
        } else if (MemberType.GROUP.equals(roleMember.getType())) {
          if (HrServiceLocator.getKPMEGroupService()
              .isMemberOfGroupWithId(principalId, roleMember.getMemberId(), asOfDate)) {
            // if (getGroupService().isMemberOfGroup(principalId, roleMember.getMemberId())) {
            principalHasRole = true;
            break;
          }
        } else if (MemberType.ROLE.equals(roleMember.getType())) {
          Role derivedRole =
              getRoleService()
                  .getRoleByNamespaceCodeAndName(
                      KPMENamespace.KPME_HR.getNamespaceCode(),
                      KPMERole.DERIVED_ROLE_POSITION.getRoleName());
          // check if the member represents the (nested) derived role 'position'
          if (derivedRole != null && roleMember.getMemberId().equals(derivedRole.getId())) {
            // add custom attributes
            Map<String, String> qual = new HashMap<String, String>();
            qual.putAll(roleMember.getAttributes());
            qual.put("asOfDate", asOfDate.toString());
            // return true if the principal id is a member of the (nested) derived role 'position'
            RoleTypeService roleTypeService = getRoleTypeService(derivedRole);
            if (roleTypeService.hasDerivedRole(
                principalId,
                new ArrayList<String>(),
                derivedRole.getNamespaceCode(),
                derivedRole.getName(),
                qual)) {
              principalHasRole = true;
              break;
            }
          }
        }
      }
    }

    return principalHasRole;
  }
  /**
   * Helper method to recursively search for role members.
   *
   * @param role The role
   * @param qualification The map of role qualifiers
   * @param asOfDate The effective date of the role
   * @param activeOnly or not to get only active role members
   * @return the list of role members in {@code role}.
   */
  private List<RoleMember> getRoleMembers(
      Role role, Map<String, String> qualification, DateTime asOfDate, boolean activeOnly) {
    List<RoleMember> roleMembers = new ArrayList<RoleMember>();

    if (asOfDate == null) {
      asOfDate = LocalDate.now().toDateTimeAtStartOfDay();
    }
    if (role != null) {
      RoleTypeService roleTypeService = getRoleTypeService(role);

      if (roleTypeService == null || !roleTypeService.isDerivedRoleType()) {
        List<RoleMember> primaryRoleMembers =
            getPrimaryRoleMembers(role, qualification, asOfDate, activeOnly);

        if (CollectionUtils.isNotEmpty(primaryRoleMembers)) {
          // flatten into constituent group and principal role members
          for (RoleMember primaryRoleMember : primaryRoleMembers) {
            if (MemberType.PRINCIPAL.equals(primaryRoleMember.getType())) {
              roleMembers.add(primaryRoleMember);
            } else if (MemberType.GROUP.equals(primaryRoleMember.getType())) {
              roleMembers.add(primaryRoleMember);
            } else if (MemberType.ROLE.equals(primaryRoleMember.getType())) {
              // recursive call to get role members
              Map<String, String> copiedQualification =
                  addCustomDerivedQualifications(
                      primaryRoleMember.getAttributes(), asOfDate, activeOnly);
              List<RoleMembership> memberships =
                  getRoleService()
                      .getRoleMembers(
                          Collections.singletonList(primaryRoleMember.getMemberId()),
                          copiedQualification);
              for (RoleMembership membership : memberships) {
                RoleMember roleMember =
                    RoleMember.Builder.create(
                            membership.getRoleId(),
                            membership.getId(),
                            membership.getMemberId(),
                            membership.getType(),
                            null,
                            null,
                            membership.getQualifier(),
                            "",
                            "")
                        .build();

                roleMembers.add(roleMember);
              }
            }
          }
        }
      } else {
        Map<String, String> qual =
            addCustomDerivedQualifications(qualification, asOfDate, activeOnly);
        List<RoleMembership> derivedRoleMembers =
            roleTypeService.getRoleMembersFromDerivedRole(
                role.getNamespaceCode(), role.getName(), qual);

        if (CollectionUtils.isNotEmpty(derivedRoleMembers)) {
          for (RoleMembership derivedRoleMember : derivedRoleMembers) {
            RoleMember roleMember =
                RoleMember.Builder.create(
                        derivedRoleMember.getRoleId(),
                        derivedRoleMember.getId(),
                        derivedRoleMember.getMemberId(),
                        derivedRoleMember.getType(),
                        null,
                        null,
                        derivedRoleMember.getQualifier(),
                        role.getName(),
                        role.getNamespaceCode())
                    .build();

            roleMembers.add(roleMember);
          }
        }
      }
    }

    return roleMembers;
  }