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;
  }