public List<String> getDepartmentsForPrincipalInRoles(
      String principalId, List<String> roleIds, DateTime asOfDate, boolean isActiveOnly) {
    Set<String> departments = new HashSet<String>();

    Map<String, String> qualifiers = new HashMap<String, String>();
    qualifiers.put(KPMERoleMemberAttribute.WORK_AREA.getRoleMemberAttributeName(), "%");
    qualifiers.put(KPMERoleMemberAttribute.LOCATION.getRoleMemberAttributeName(), "%");
    qualifiers.put(KPMERoleMemberAttribute.DEPARTMENT.getRoleMemberAttributeName(), "%");
    qualifiers.put(KPMERoleMemberAttribute.GROUP_KEY_CODE.getRoleMemberAttributeName(), "%");
    List<Map<String, String>> roleQualifiers =
        getRoleQualifiers(principalId, roleIds, qualifiers, asOfDate, isActiveOnly);

    for (Map<String, String> roleQualifier : roleQualifiers) {
      String department =
          MapUtils.getString(
              roleQualifier, KPMERoleMemberAttribute.DEPARTMENT.getRoleMemberAttributeName());
      String groupKeyCode =
          MapUtils.getString(
              roleQualifier, KPMERoleMemberAttribute.GROUP_KEY_CODE.getRoleMemberAttributeName());
      if (department != null && groupKeyCode != null) {
        departments.add(groupKeyCode + "|" + department);
      }
    }

    List<String> locations =
        getLocationsForPrincipalInRoles(principalId, roleIds, asOfDate, isActiveOnly);
    departments.addAll(
        getDepartmentService().getDepartmentValuesWithLocations(locations, asOfDate.toLocalDate()));

    return new ArrayList<String>(departments);
  }
  @Override
  public List<RoleMember> getPrimaryRoleMembersInWorkArea(
      String namespaceCode,
      String roleName,
      Long workArea,
      DateTime asOfDate,
      boolean isActiveOnly) {
    // the return value
    List<RoleMember> primaryRoleMembers = new ArrayList<RoleMember>();

    Role role = getRoleService().getRoleByNamespaceCodeAndName(namespaceCode, roleName);
    if (role != null) {
      Map<String, String> qualification = new HashMap<String, String>();
      qualification.put(
          KPMERoleMemberAttribute.WORK_AREA.getRoleMemberAttributeName(), String.valueOf(workArea));
      primaryRoleMembers =
          getRoleServiceHelper().getPrimaryRoleMembers(role, qualification, asOfDate, isActiveOnly);
    } else {
      LOG.error(
          "Role instance for role with name "
              + roleName
              + " namespace "
              + namespaceCode
              + " was null");
    }

    return primaryRoleMembers;
  }
  public boolean principalHasRoleInWorkArea(
      String principalId, String namespaceCode, String roleName, Long workArea, DateTime asOfDate) {
    Map<String, String> qualification = new HashMap<String, String>();
    qualification.put(
        KPMERoleMemberAttribute.WORK_AREA.getRoleMemberAttributeName(), String.valueOf(workArea));

    return principalHasRole(principalId, namespaceCode, roleName, qualification, asOfDate);
  }
  @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);
  }
  public List<RoleMember> getRoleMembersInWorkArea(
      String namespaceCode,
      String roleName,
      Long workArea,
      DateTime asOfDate,
      boolean isActiveOnly) {
    Map<String, String> qualification = new HashMap<String, String>();
    qualification.put(
        KPMERoleMemberAttribute.WORK_AREA.getRoleMemberAttributeName(), String.valueOf(workArea));

    return getRoleMembers(namespaceCode, roleName, qualification, asOfDate, isActiveOnly);
  }
  protected void addRoleQualification(Object dataObject, Map<String, String> attributes) {
    super.addRoleQualification(dataObject, attributes);

    // put in the department qualifier for the role membership attributes
    if (dataObject instanceof AssignmentBo && dataObject != null) {
      attributes.put(
          KPMERoleMemberAttribute.DEPARTMENT.getRoleMemberAttributeName(),
          ((AssignmentBo) dataObject).getDept());
      attributes.put(
          KPMERoleMemberAttribute.WORK_AREA.getRoleMemberAttributeName(),
          ((AssignmentBo) dataObject).getWorkArea().toString());
    }
  }
  public List<String> getLocationsForPrincipalInRoles(
      String principalId, List<String> roleIds, DateTime asOfDate, boolean isActiveOnly) {
    Set<String> locations = new HashSet<String>();

    Map<String, String> qualifiers = new HashMap<String, String>();
    qualifiers.put(KPMERoleMemberAttribute.WORK_AREA.getRoleMemberAttributeName(), "%");
    qualifiers.put(KPMERoleMemberAttribute.LOCATION.getRoleMemberAttributeName(), "%");
    qualifiers.put(KPMERoleMemberAttribute.DEPARTMENT.getRoleMemberAttributeName(), "%");
    qualifiers.put(KPMERoleMemberAttribute.GROUP_KEY_CODE.getRoleMemberAttributeName(), "%");
    List<Map<String, String>> roleQualifiers =
        getRoleQualifiers(principalId, roleIds, qualifiers, asOfDate, isActiveOnly);

    for (Map<String, String> roleQualifier : roleQualifiers) {
      String location =
          MapUtils.getString(
              roleQualifier, KPMERoleMemberAttribute.LOCATION.getRoleMemberAttributeName());

      if (location != null) {
        locations.add(location);
      }
    }

    return new ArrayList<String>(locations);
  }