diff --git a/config/alfresco/public-rest-context.xml b/config/alfresco/public-rest-context.xml index c37d90e2fd..bf3bc658ae 100644 --- a/config/alfresco/public-rest-context.xml +++ b/config/alfresco/public-rest-context.xml @@ -1356,4 +1356,8 @@ + + + + diff --git a/source/java/org/alfresco/rest/api/Groups.java b/source/java/org/alfresco/rest/api/Groups.java index 5b829e246e..96360ae70b 100644 --- a/source/java/org/alfresco/rest/api/Groups.java +++ b/source/java/org/alfresco/rest/api/Groups.java @@ -26,6 +26,7 @@ package org.alfresco.rest.api; import org.alfresco.rest.api.model.Group; +import org.alfresco.rest.api.model.GroupMember; import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; import org.alfresco.rest.framework.resource.parameters.Parameters; @@ -41,6 +42,9 @@ public interface Groups String PARAM_INCLUDE_PARENT_IDS = "parentIds"; String PARAM_INCLUDE_ZONES = "zones"; String PARAM_IS_ROOT = "isRoot"; + String PARAM_MEMBER_TYPE = "memberType"; + String PARAM_MEMBER_TYPE_GROUP = "GROUP"; + String PARAM_MEMBER_TYPE_PERSON = "PERSON"; /** * Gets a list of groups. @@ -53,4 +57,15 @@ public interface Groups */ CollectionWithPagingInfo getGroups(Parameters parameters); + /** + * Gets a list of groups. + * + * @param groupId the identifier of a group. + * @param parameters the {@link Parameters} object to get the parameters passed into the request + * including: + * - filter, sort & paging params (where, orderBy, skipCount, maxItems) + * - incFiles, incFolders (both true by default) + * @return a paged list of {@code org.alfresco.rest.api.model.GroupMember} objects + */ + CollectionWithPagingInfo getGroupMembers(String groupId, Parameters parameters); } diff --git a/source/java/org/alfresco/rest/api/groups/GroupMembersRelation.java b/source/java/org/alfresco/rest/api/groups/GroupMembersRelation.java new file mode 100644 index 0000000000..d989628e59 --- /dev/null +++ b/source/java/org/alfresco/rest/api/groups/GroupMembersRelation.java @@ -0,0 +1,64 @@ +/* + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.rest.api.groups; + +import org.alfresco.rest.api.Groups; +import org.alfresco.rest.api.model.GroupMember; +import org.alfresco.rest.framework.WebApiDescription; +import org.alfresco.rest.framework.resource.RelationshipResource; +import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.util.ParameterCheck; +import org.springframework.beans.factory.InitializingBean; + +/** + + * @author cturlica + */ +@RelationshipResource(name = "members", entityResource = GroupsEntityResource.class, title = "Group Members") +public class GroupMembersRelation implements RelationshipResourceAction.Read, InitializingBean +{ + private Groups groups; + + public void setGroups(Groups groups) + { + this.groups = groups; + } + + @Override + public void afterPropertiesSet() + { + ParameterCheck.mandatory("groups", this.groups); + } + + @Override + @WebApiDescription(title="A paged list of all the members of the group 'groupId'.") + public CollectionWithPagingInfo readAll(String groupId, Parameters params) + { + return groups.getGroupMembers(groupId, params); + } +} \ No newline at end of file diff --git a/source/java/org/alfresco/rest/api/impl/GroupsImpl.java b/source/java/org/alfresco/rest/api/impl/GroupsImpl.java index 67b1404fd2..52461d90d1 100644 --- a/source/java/org/alfresco/rest/api/impl/GroupsImpl.java +++ b/source/java/org/alfresco/rest/api/impl/GroupsImpl.java @@ -47,6 +47,7 @@ import org.alfresco.repo.security.authority.UnknownAuthorityException; import org.alfresco.rest.antlr.WhereClauseParser; import org.alfresco.rest.api.Groups; import org.alfresco.rest.api.model.Group; +import org.alfresco.rest.api.model.GroupMember; import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; @@ -85,6 +86,8 @@ public class GroupsImpl implements Groups // List groups filtering (via where clause) private final static Set LIST_GROUPS_EQUALS_QUERY_PROPERTIES = new HashSet<>(Arrays.asList(new String[] { PARAM_IS_ROOT })); + private final static Set LIST_GROUP_MEMBERS_QUERY_PROPERTIES = new HashSet<>(Arrays.asList(new String[] { PARAM_MEMBER_TYPE })); + protected AuthorityService authorityService; public AuthorityService getAuthorityService() @@ -355,11 +358,11 @@ public class GroupsImpl implements Groups if (v == null) { // Get the value from the group - if (PARAM_DISPLAY_NAME.equals(sortBy)) + if (DISPLAY_NAME.equals(sortBy)) { v = g.getAuthorityDisplayName(); } - else if (PARAM_ID.equals(sortBy)) + else if (SHORT_NAME.equals(sortBy)) { v = g.getAuthorityName(); } @@ -377,4 +380,131 @@ public class GroupsImpl implements Groups return v; } } + + public CollectionWithPagingInfo getGroupMembers(String groupId, final Parameters parameters) + { + validateGroupId(groupId); + + Paging paging = parameters.getPaging(); + + // Retrieve sort column. This is limited for now to sort column due to + // v0 api implementation. Should be improved in the future. + Pair sortProp = getGroupsSortProp(parameters); + + AuthorityType authorityType = null; + + // Parse where clause properties. + Query q = parameters.getQuery(); + if (q != null) + { + MapBasedQueryWalkerOrSupported propertyWalker = new MapBasedQueryWalkerOrSupported(LIST_GROUP_MEMBERS_QUERY_PROPERTIES, null); + QueryHelper.walk(q, propertyWalker); + + String memberTypeStr = propertyWalker.getProperty(PARAM_MEMBER_TYPE, WhereClauseParser.EQUALS, String.class); + + if (memberTypeStr != null && !memberTypeStr.isEmpty()) + { + switch (memberTypeStr) + { + case PARAM_MEMBER_TYPE_GROUP: + authorityType = AuthorityType.GROUP; + break; + case PARAM_MEMBER_TYPE_PERSON: + authorityType = AuthorityType.USER; + break; + default: + throw new InvalidArgumentException("MemberType is invalid (expected eg. GROUP, PERSON)"); + } + } + } + + PagingResults pagingResult = getAuthoritiesInfo(authorityType, groupId, sortProp, paging); + + // Create response. + final List page = pagingResult.getPage(); + int totalItems = pagingResult.getTotalResultCount().getFirst(); + List groupMembers = new AbstractList() + { + @Override + public GroupMember get(int index) + { + AuthorityInfo authorityInfo = page.get(index); + return getGroupMember(authorityInfo); + } + + @Override + public int size() + { + return page.size(); + } + }; + + return CollectionWithPagingInfo.asPaged(paging, groupMembers, pagingResult.hasMoreItems(), totalItems); + } + + private PagingResults getAuthoritiesInfo(AuthorityType authorityType, String groupId, Pair sortProp, Paging paging) + { + Set authorities; + try + { + authorities = authorityService.findAuthorities(authorityType, groupId, true, null, null); + } + catch (UnknownAuthorityException e) + { + authorities = Collections.emptySet(); + } + + List authorityInfoList = new ArrayList<>(authorities.size()); + authorityInfoList.addAll(authorities.stream().map(this::getAuthorityInfo).collect(Collectors.toList())); + + // Post process sorting - this should be moved to service + // layer. It is done here because sorting is not supported at + // service layer. + AuthorityInfoComparator authorityComparator = new AuthorityInfoComparator(sortProp.getFirst(), sortProp.getSecond()); + Collections.sort(authorityInfoList, authorityComparator); + + // Post process paging - this should be moved to service layer. + return Util.wrapPagingResults(paging, authorityInfoList); + } + + private GroupMember getGroupMember(AuthorityInfo authorityInfo) + { + if (authorityInfo == null) + { + return null; + } + + GroupMember groupMember = new GroupMember(); + groupMember.setId(authorityInfo.getAuthorityName()); + groupMember.setDisplayName(authorityInfo.getAuthorityDisplayName()); + + String memberType = null; + AuthorityType authorityType = AuthorityType.getAuthorityType(authorityInfo.getAuthorityName()); + switch (authorityType) + { + case GROUP: + memberType = PARAM_MEMBER_TYPE_GROUP; + break; + case USER: + memberType = PARAM_MEMBER_TYPE_PERSON; + break; + default: + } + groupMember.setMemberType(memberType); + + return groupMember; + } + + private void validateGroupId(String groupId) + { + if (groupId == null || groupId.isEmpty()) + { + throw new InvalidArgumentException("groupId is null or empty"); + } + + if (!authorityService.authorityExists(groupId)) + { + throw new EntityNotFoundException(groupId); + } + } } diff --git a/source/java/org/alfresco/rest/api/model/GroupMember.java b/source/java/org/alfresco/rest/api/model/GroupMember.java new file mode 100644 index 0000000000..b3931d5591 --- /dev/null +++ b/source/java/org/alfresco/rest/api/model/GroupMember.java @@ -0,0 +1,116 @@ +/* + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.rest.api.model; + +import org.alfresco.rest.framework.resource.UniqueId; + +/** + * Represents a group member. + * + * @author cturlica + * + */ +public class GroupMember implements Comparable +{ + + private String id; // group id (aka authority name) + private String displayName; + private String memberType; + + @UniqueId + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public String getDisplayName() + { + return displayName; + } + + public void setDisplayName(String displayName) + { + this.displayName = displayName; + } + + public String getMemberType() + { + return memberType; + } + + public void setMemberType(String memberType) + { + this.memberType = memberType; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + GroupMember other = (GroupMember) obj; + return id.equals(other.id); + } + + @Override + public int compareTo(GroupMember group) + { + return id.compareTo(group.getId()); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public String toString() + { + return "GroupMember [id=" + id + ", displayName=" + displayName + ", memberType=" + memberType + "]"; + } +} \ No newline at end of file diff --git a/source/test-java/org/alfresco/rest/api/tests/GroupsTest.java b/source/test-java/org/alfresco/rest/api/tests/GroupsTest.java index 815af94f11..97a6eca7ea 100644 --- a/source/test-java/org/alfresco/rest/api/tests/GroupsTest.java +++ b/source/test-java/org/alfresco/rest/api/tests/GroupsTest.java @@ -44,6 +44,7 @@ import org.alfresco.rest.api.tests.client.PublicApiClient.Groups; import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; import org.alfresco.rest.api.tests.client.data.Group; +import org.alfresco.rest.api.tests.client.data.GroupMember; import org.alfresco.rest.framework.resource.parameters.SortColumn; import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.AuthorityType; @@ -64,6 +65,8 @@ public class GroupsTest extends AbstractSingleNetworkSiteTest private String rootGroupName = null; private Group groupA = null; private Group groupB = null; + private GroupMember groupMemberA = null; + private GroupMember groupMemberB = null; @Before public void setup() throws Exception @@ -351,6 +354,12 @@ public class GroupsTest extends AbstractSingleNetworkSiteTest groupB = new Group(); groupB.setId(groupBAuthorityName); + + groupMemberA = new GroupMember(); + groupMemberA.setId(groupAAuthorityName); + + groupMemberB = new GroupMember(); + groupMemberB.setId(groupBAuthorityName); } } @@ -377,4 +386,182 @@ public class GroupsTest extends AbstractSingleNetworkSiteTest assertNull(group.getParentIds()); assertNull(group.getZones()); } + + private ListResponse getGroupMembers(String groupId, final PublicApiClient.Paging paging, Map otherParams, String errorMessage, int expectedStatus) throws Exception + { + final Groups groupsProxy = publicApiClient.groups(); + return groupsProxy.getGroupMembers(groupId, createParams(paging, otherParams), errorMessage, expectedStatus); + } + + private ListResponse getGroupMembers(String groupId, final PublicApiClient.Paging paging, Map otherParams) throws Exception + { + return getGroupMembers(groupId, paging, otherParams, "Failed to get group members", HttpServletResponse.SC_OK); + } + + @Test + public void testGetGroupMembers() throws Exception + { + try + { + createAuthorityContext(user1); + + setRequestContext(user1); + + testGetGroupMembersByGroupId(); + testGetGroupMembersSorting(); + testGetGroupMembersSkipPaging(); + testGetGroupsByMemberType(); + } + finally + { + clearAuthorityContext(); + } + } + + private void testGetGroupMembersByGroupId() throws Exception + { + Paging paging = getPaging(0, 4); + + getGroupMembers(null, paging, null, "", HttpServletResponse.SC_METHOD_NOT_ALLOWED); + getGroupMembers("", paging, null, "", HttpServletResponse.SC_BAD_REQUEST); + getGroupMembers("invalidGroupId", paging, null, "", HttpServletResponse.SC_NOT_FOUND); + } + + private void testGetGroupMembersSorting() throws Exception + { + // orderBy=sortColumn should be the same to orderBy=sortColumn ASC + { + // paging + Paging paging = getPaging(0, Integer.MAX_VALUE); + + Map otherParams = new HashMap<>(); + + // Default order. + addOrderBy(otherParams, org.alfresco.rest.api.Groups.PARAM_DISPLAY_NAME, null); + + ListResponse resp = getGroupMembers(rootGroupName, paging, otherParams); + List groupMembers = resp.getList(); + assertTrue("group members order not valid", groupMembers.indexOf(groupMemberA) < groupMembers.indexOf(groupMemberB)); + + // Ascending order + addOrderBy(otherParams, org.alfresco.rest.api.Groups.PARAM_DISPLAY_NAME, true); + + ListResponse respOrderAsc = getGroupMembers(rootGroupName, paging, otherParams); + + checkList(respOrderAsc.getList(), resp.getPaging(), resp); + } + + // Sort by displayName. + { + // paging + Paging paging = getPaging(0, Integer.MAX_VALUE); + + Map otherParams = new HashMap<>(); + + // Default order. + addOrderBy(otherParams, org.alfresco.rest.api.Groups.PARAM_DISPLAY_NAME, true); + + ListResponse resp = getGroupMembers(rootGroupName, paging, otherParams); + List groupMembers = resp.getList(); + assertTrue("group members order not valid", groupMembers.indexOf(groupMemberA) < groupMembers.indexOf(groupMemberB)); + } + + // Sort by id. + { + // paging + Paging paging = getPaging(0, Integer.MAX_VALUE); + + Map otherParams = new HashMap<>(); + addOrderBy(otherParams, org.alfresco.rest.api.Groups.PARAM_ID, false); + + // list sites + ListResponse resp = getGroupMembers(rootGroupName, paging, otherParams); + + List groupMembers = resp.getList(); + assertTrue("group members order not valid", groupMembers.indexOf(groupMemberB) < groupMembers.indexOf(groupMemberA)); + } + + // Multiple sort fields not allowed. + { + // paging + Paging paging = getPaging(0, Integer.MAX_VALUE); + Map otherParams = new HashMap<>(); + otherParams.put("orderBy", org.alfresco.rest.api.Groups.PARAM_ID + " ASC," + org.alfresco.rest.api.Groups.PARAM_DISPLAY_NAME + " ASC"); + + getGroupMembers(rootGroupName, paging, otherParams, "", HttpServletResponse.SC_BAD_REQUEST); + } + } + + private void testGetGroupMembersSkipPaging() throws Exception + { + // +ve: check skip count. + { + // Sort params + Map otherParams = new HashMap<>(); + addOrderBy(otherParams, org.alfresco.rest.api.Groups.PARAM_DISPLAY_NAME, false); + + // Paging and list groups + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems); + + ListResponse resp = getGroupMembers(rootGroupName, paging, otherParams); + + // Paging and list groups with skip count. + + skipCount = 1; + maxItems = 1; + paging = getPaging(skipCount, maxItems); + + ListResponse sublistResponse = getGroupMembers(rootGroupName, paging, otherParams); + + List expectedSublist = sublist(resp.getList(), skipCount, maxItems); + checkList(expectedSublist, sublistResponse.getPaging(), sublistResponse); + } + + // -ve: check skip count. + { + getGroupMembers(rootGroupName, getPaging(-1, null), null, "", HttpServletResponse.SC_BAD_REQUEST); + } + } + + private void testGetGroupsByMemberType() throws Exception + { + testGetGroupsByMemberType(rootGroupName, org.alfresco.rest.api.Groups.PARAM_MEMBER_TYPE_GROUP); + testGetGroupsByMemberType(groupB.getId(), org.alfresco.rest.api.Groups.PARAM_MEMBER_TYPE_PERSON); + + // Invalid member type + { + Map otherParams = new HashMap<>(); + otherParams.put("where", "(memberType=invalidMemberType)"); + + getGroupMembers(rootGroupName, getPaging(0, 4), otherParams, "", HttpServletResponse.SC_BAD_REQUEST); + } + } + + private void testGetGroupsByMemberType(String groupId, String memberType) throws Exception + { + // Sort params + Map otherParams = new HashMap<>(); + otherParams.put("where", "(memberType=" + memberType + ")"); + + // Paging + Paging paging = getPaging(0, 4); + + ListResponse resp = getGroupMembers(groupId, paging, otherParams); + resp.getList().forEach(groupMember -> { + validateGroupMemberDefaultFields(groupMember); + assertEquals("memberType was expected to be " + memberType, memberType, groupMember.getMemberType()); + }); + } + + private void validateGroupMemberDefaultFields(GroupMember groupMember) + { + assertNotNull(groupMember); + assertNotNull(groupMember.getId()); + assertNotNull(groupMember.getDisplayName()); + assertNotNull(groupMember.getMemberType()); + } + } diff --git a/source/test-java/org/alfresco/rest/api/tests/client/PublicApiClient.java b/source/test-java/org/alfresco/rest/api/tests/client/PublicApiClient.java index 2a12c2efe9..ee4a1f3a21 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/PublicApiClient.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/PublicApiClient.java @@ -57,6 +57,7 @@ import org.alfresco.rest.api.tests.client.data.Favourite; import org.alfresco.rest.api.tests.client.data.FavouriteSite; import org.alfresco.rest.api.tests.client.data.FolderNode; import org.alfresco.rest.api.tests.client.data.Group; +import org.alfresco.rest.api.tests.client.data.GroupMember; import org.alfresco.rest.api.tests.client.data.JSONAble; import org.alfresco.rest.api.tests.client.data.MemberOfSite; import org.alfresco.rest.api.tests.client.data.NodeRating; @@ -2262,9 +2263,25 @@ public class PublicApiClient return null; } - public ListResponse getGroups(Map params) throws PublicApiException, ParseException + public ListResponse getGroupMembers(String groupId, Map params) throws PublicApiException, ParseException { - return getGroups(params, "Failed to get groups", HttpServletResponse.SC_OK); + return getGroupMembers(groupId, params, "Failed to get groups", HttpServletResponse.SC_OK); + } + + public ListResponse getGroupMembers(String groupId, Map params, String errorMessage, int expectedStatus) + throws PublicApiException, ParseException + { + HttpResponse response = getAll("groups", groupId, "members", null, params, errorMessage, expectedStatus); + + if (response != null && response.getJsonResponse() != null) + { + JSONObject jsonList = (JSONObject) response.getJsonResponse().get("list"); + if (jsonList != null) + { + return GroupMember.parseGroupMembers(response.getJsonResponse()); + } + } + return null; } } } diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/GroupMember.java b/source/test-java/org/alfresco/rest/api/tests/client/data/GroupMember.java new file mode 100644 index 0000000000..c145a5712e --- /dev/null +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/GroupMember.java @@ -0,0 +1,107 @@ +/* + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +/** + * Represents a group member. + * + * @author cturlica + * + */ +public class GroupMember extends org.alfresco.rest.api.model.GroupMember implements Serializable, ExpectedComparison +{ + + @Override + public void expected(Object o) + { + assertTrue("o is an instance of " + o.getClass(), o instanceof GroupMember); + + GroupMember other = (GroupMember) o; + + AssertUtil.assertEquals("id", getId(), other.getId()); + AssertUtil.assertEquals("displayName", getDisplayName(), other.getDisplayName()); + AssertUtil.assertEquals("memberType", getMemberType(), other.getMemberType()); + } + + public JSONObject toJSON() + { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("id", getId()); + jsonObject.put("displayName", getDisplayName()); + jsonObject.put("memberType", getMemberType()); + + return jsonObject; + } + + public static GroupMember parseGroupMember(JSONObject jsonObject) + { + String id = (String) jsonObject.get("id"); + String displayName = (String) jsonObject.get("displayName"); + String memberType = (String) jsonObject.get("memberType"); + + GroupMember group = new GroupMember(); + group.setId(id); + group.setDisplayName(displayName); + group.setMemberType(memberType); + + return group; + } + + public static ListResponse parseGroupMembers(JSONObject jsonObject) + { + List groupMembers = new ArrayList<>(); + + JSONObject jsonList = (JSONObject) jsonObject.get("list"); + assertNotNull(jsonList); + + JSONArray jsonEntries = (JSONArray) jsonList.get("entries"); + assertNotNull(jsonEntries); + + for (int i = 0; i < jsonEntries.size(); i++) + { + JSONObject jsonEntry = (JSONObject) jsonEntries.get(i); + JSONObject entry = (JSONObject) jsonEntry.get("entry"); + groupMembers.add(parseGroupMember(entry)); + } + + ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); + ListResponse resp = new ListResponse<>(paging, groupMembers); + return resp; + } + +}