private String getGroupAuthorities(ScimGroupMember member) {
   if (member.getRoles() != null && !member.getRoles().isEmpty()) {
     return StringUtils.collectionToCommaDelimitedString(member.getRoles());
   } else {
     return StringUtils.collectionToCommaDelimitedString(ScimGroupMember.GROUP_MEMBER);
   }
 }
  @Test
  public void canGetMemberById() throws Exception {
    addMember("g3", "m2", "USER", "READER,WRITER");

    ScimGroupMember m = dao.getMemberById("g3", "m2");
    assertEquals(ScimGroupMember.Type.USER, m.getType());
    assertEquals(ScimGroupMember.GROUP_ADMIN, m.getRoles());
  }
  @Override
  public ScimGroup deserialize(JsonParser jp, DeserializationContext ctxt)
      throws IOException, JsonProcessingException {
    ScimGroup group = new ScimGroup();

    Map<ScimGroupMember.Role, List<ScimGroupMember>> roles =
        new HashMap<ScimGroupMember.Role, List<ScimGroupMember>>();
    for (ScimGroupMember.Role role : ScimGroupMember.Role.values()) {
      roles.put(role, new ArrayList<ScimGroupMember>());
    }
    Set<ScimGroupMember> allMembers = new HashSet<ScimGroupMember>();

    while (jp.nextToken() != JsonToken.END_OBJECT) {
      if (jp.getCurrentToken() == JsonToken.FIELD_NAME) {
        String fieldName = jp.getCurrentName();
        jp.nextToken();

        if ("id".equalsIgnoreCase(fieldName)) {
          group.setId(jp.readValueAs(String.class));
        } else if ("displayname".equalsIgnoreCase(fieldName)) {
          group.setDisplayName(jp.readValueAs(String.class));
        } else if ("meta".equalsIgnoreCase(fieldName)) {
          group.setMeta(jp.readValueAs(ScimMeta.class));
        } else if ("schemas".equalsIgnoreCase(fieldName)) {
          group.setSchemas(jp.readValueAs(String[].class));
        } else {
          String value = fieldName.substring(0, fieldName.length() - 1);
          ScimGroupMember.Role role;
          try {
            role = ScimGroupMember.Role.valueOf(value.toUpperCase());
          } catch (IllegalArgumentException ex) {
            role = null;
          }
          if (role != null) {
            ScimGroupMember[] members = jp.readValueAs(ScimGroupMember[].class);
            for (ScimGroupMember member : members) {
              member.setRoles(new ArrayList<ScimGroupMember.Role>());
            }
            roles.get(role).addAll(Arrays.asList(members));
            allMembers.addAll(Arrays.asList(members));
          }
        }
      }
    }

    for (ScimGroupMember member : allMembers) {
      for (ScimGroupMember.Role role : roles.keySet()) {
        if (roles.get(role).contains(member)) {
          member.getRoles().add(role);
        }
      }
    }
    group.setMembers(new ArrayList<ScimGroupMember>(allMembers));

    return group;
  }
 @Test
 public void canAddMember() throws Exception {
   validateCount(0);
   ScimGroupMember m1 = new ScimGroupMember("m1", ScimGroupMember.Type.USER, null);
   ScimGroupMember m2 = dao.addMember("g2", m1);
   validateCount(1);
   assertEquals(ScimGroupMember.Type.USER, m2.getType());
   assertEquals(ScimGroupMember.GROUP_MEMBER, m2.getRoles());
   assertEquals("m1", m2.getMemberId());
   validateUserGroups("m1", "test2");
 }
  @Test
  public void canAddNestedGroupMember() {
    addMember("g2", "m1", "USER", "READER");

    ScimGroupMember g2 =
        new ScimGroupMember("g2", ScimGroupMember.Type.GROUP, ScimGroupMember.GROUP_ADMIN);
    g2 = dao.addMember("g1", g2);
    assertEquals(ScimGroupMember.Type.GROUP, g2.getType());
    assertEquals(ScimGroupMember.GROUP_ADMIN, g2.getRoles());
    assertEquals("g2", g2.getMemberId());
    validateUserGroups("m1", "test1.i", "test2");
  }
  @Test
  public void canUpdateMember() throws Exception {
    addMember("g1", "m1", "USER", "READER");
    validateCount(1);
    ScimGroupMember m1 =
        new ScimGroupMember("m1", ScimGroupMember.Type.USER, ScimGroupMember.GROUP_ADMIN);
    ScimGroupMember m2 = dao.updateMember("g1", m1);
    assertEquals(ScimGroupMember.GROUP_ADMIN, m2.getRoles());
    assertNotSame(m1, m2);

    validateCount(1);
    validateUserGroups("m1", "test1");
  }
  @Test
  public void testBackwardsCompatibilityToMemberAuthorities() {
    addMember("g1", "m1", "USER", "READ");
    addMember("g1", "g2", "GROUP", "member");
    addMember("g1", "m2", "USER", "READER,write");

    List<ScimGroupMember> members = dao.getMembers("g1", null, false);
    assertNotNull(members);
    assertEquals(3, members.size());
    List<ScimGroupMember> readers = new ArrayList<ScimGroupMember>(),
        writers = new ArrayList<ScimGroupMember>();
    for (ScimGroupMember member : members) {
      if (member.getRoles().contains(ScimGroupMember.Role.READER)) {
        readers.add(member);
      }
      if (member.getRoles().contains(ScimGroupMember.Role.WRITER)) {
        writers.add(member);
      }
    }
    assertEquals(2, readers.size());
    assertEquals(1, writers.size());
  }