From 02968ac10616e515d0845a2de9ab4b37dbd1a2b3 Mon Sep 17 00:00:00 2001
From: Jean-Pierre Portier <141755467+JPPortier@users.noreply.github.com>
Date: Thu, 16 Nov 2023 11:07:18 +0100
Subject: [PATCH] DEVEXP-165 sms groups (#9)
* feat: SMS Groups
---
.../sinch/sdk/domains/sms/GroupsService.java | 122 ++++++++++
.../com/sinch/sdk/domains/sms/SMSService.java | 8 +
.../domains/sms/adapters/GroupsService.java | 109 +++++++++
.../sdk/domains/sms/adapters/SMSService.java | 9 +
.../converters/GroupsDtoConverter.java | 196 ++++++++++++++++
.../sinch/sdk/domains/sms/models/Group.java | 151 ++++++++++++
.../domains/sms/models/GroupAutoUpdate.java | 71 ++++++
.../sms/models/GroupAutoUpdateKeyword.java | 66 ++++++
.../GroupCreateRequestParameters.java | 117 +++++++++
.../GroupReplaceRequestParameters.java | 75 ++++++
.../GroupUpdateRequestParameters.java | 156 ++++++++++++
.../requests/GroupsListRequestParameters.java | 68 ++++++
.../models/responses/GroupsListResponse.java | 50 ++++
.../sms/adapters/GroupsServiceTest.java | 222 ++++++++++++++++++
.../converters/GroupsDtoConverterTest.java | 131 +++++++++++
.../com/sinch/sdk/core/utils/DateUtil.java | 19 ++
.../models/dto/v1/GroupResponseDtoTest.java | 44 ++++
sample-app/README.md | 61 ++---
.../com/sinch/sample/sms/groups/Create.java | 30 +++
.../com/sinch/sample/sms/groups/Delete.java | 32 +++
.../java/com/sinch/sample/sms/groups/Get.java | 31 +++
.../com/sinch/sample/sms/groups/List.java | 31 +++
.../sinch/sample/sms/groups/ListMembers.java | 33 +++
.../com/sinch/sample/sms/groups/Replace.java | 40 ++++
.../com/sinch/sample/sms/groups/Update.java | 36 +++
.../v1/GroupCreateRequestParametersDto.json | 18 ++
.../v1/GroupReplaceRequestParametersDto.json | 4 +
.../domains/sms/v1/GroupResponseDto.json | 21 ++
.../v1/GroupUpdateRequestParametersDto.json | 22 ++
.../sms/v1/GroupsListResponseDtoPage0.json | 31 +++
.../sms/v1/GroupsListResponseDtoPage1.json | 28 +++
31 files changed, 2005 insertions(+), 27 deletions(-)
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/GroupsService.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/adapters/GroupsService.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/adapters/converters/GroupsDtoConverter.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/Group.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/GroupAutoUpdate.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/GroupAutoUpdateKeyword.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/requests/GroupCreateRequestParameters.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/requests/GroupReplaceRequestParameters.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/requests/GroupUpdateRequestParameters.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/requests/GroupsListRequestParameters.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/responses/GroupsListResponse.java
create mode 100644 client/src/test/java/com/sinch/sdk/domains/sms/adapters/GroupsServiceTest.java
create mode 100644 client/src/test/java/com/sinch/sdk/domains/sms/adapters/converters/GroupsDtoConverterTest.java
create mode 100644 core/src/main/com/sinch/sdk/core/utils/DateUtil.java
create mode 100644 openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/GroupResponseDtoTest.java
create mode 100644 sample-app/src/main/java/com/sinch/sample/sms/groups/Create.java
create mode 100644 sample-app/src/main/java/com/sinch/sample/sms/groups/Delete.java
create mode 100644 sample-app/src/main/java/com/sinch/sample/sms/groups/Get.java
create mode 100644 sample-app/src/main/java/com/sinch/sample/sms/groups/List.java
create mode 100644 sample-app/src/main/java/com/sinch/sample/sms/groups/ListMembers.java
create mode 100644 sample-app/src/main/java/com/sinch/sample/sms/groups/Replace.java
create mode 100644 sample-app/src/main/java/com/sinch/sample/sms/groups/Update.java
create mode 100644 test-resources/src/test/resources/domains/sms/v1/GroupCreateRequestParametersDto.json
create mode 100644 test-resources/src/test/resources/domains/sms/v1/GroupReplaceRequestParametersDto.json
create mode 100644 test-resources/src/test/resources/domains/sms/v1/GroupResponseDto.json
create mode 100644 test-resources/src/test/resources/domains/sms/v1/GroupUpdateRequestParametersDto.json
create mode 100644 test-resources/src/test/resources/domains/sms/v1/GroupsListResponseDtoPage0.json
create mode 100644 test-resources/src/test/resources/domains/sms/v1/GroupsListResponseDtoPage1.json
diff --git a/client/src/main/com/sinch/sdk/domains/sms/GroupsService.java b/client/src/main/com/sinch/sdk/domains/sms/GroupsService.java
new file mode 100644
index 000000000..22c8d8571
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/GroupsService.java
@@ -0,0 +1,122 @@
+package com.sinch.sdk.domains.sms;
+
+import com.sinch.sdk.core.exceptions.ApiException;
+import com.sinch.sdk.domains.sms.models.Group;
+import com.sinch.sdk.domains.sms.models.requests.GroupCreateRequestParameters;
+import com.sinch.sdk.domains.sms.models.requests.GroupReplaceRequestParameters;
+import com.sinch.sdk.domains.sms.models.requests.GroupUpdateRequestParameters;
+import com.sinch.sdk.domains.sms.models.requests.GroupsListRequestParameters;
+import com.sinch.sdk.domains.sms.models.responses.GroupsListResponse;
+import java.util.Collection;
+
+/**
+ * Groups Service
+ *
+ *
A group is a set of phone numbers (or MSISDNs) that can be used as a target when sending an
+ * SMS. An phone number (MSISDN) can only occur once in a group and any attempts to add a duplicate
+ * are ignored but not rejected.
+ *
+ * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Groups
+ * @since 1.0
+ */
+public interface GroupsService {
+
+ /**
+ * Retrieve a group
+ *
+ *
This operation retrieves a specific group with the provided group ID.
+ *
+ * @param groupId The inbound ID found when listing inbound messages
+ * @return Group associated to groupId
+ * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Groups/#tag/Groups/operation/RetrieveGroup
+ * @since 1.0
+ */
+ Group get(String groupId) throws ApiException;
+
+ /**
+ * Create a group
+ *
+ *
A group is a set of phone numbers (MSISDNs) that can be used as a target in the
+ * send_batch_msg
operation. An MSISDN can only occur once in a group and any attempts to
+ * add a duplicate would be ignored but not rejected.
+ *
+ * @param parameters Parameters to be used to define group onto creation
+ * @return Created group
+ * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Groups/#tag/Groups/operation/CreateGroup
+ * @since 1.0
+ */
+ Group create(GroupCreateRequestParameters parameters) throws ApiException;
+
+ Group create() throws ApiException;
+
+ /**
+ * List Groups
+ *
+ *
With the list operation you can list all groups that you have created. This operation
+ * supports pagination.
+ *
+ *
Groups are returned in reverse chronological order.
+ *
+ * @param parameters Filtering parameters
+ * @return group list
+ * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Groups/#tag/Groups/operation/ListGroups
+ * @since 1.0
+ */
+ GroupsListResponse list(GroupsListRequestParameters parameters) throws ApiException;
+
+ GroupsListResponse list() throws ApiException;
+
+ /**
+ * Replace a group
+ *
+ *
The replace operation will replace all parameters, including members, of an existing group
+ * with new values.
+ *
+ *
Replacing a group targeted by a batch message scheduled in the future is allowed and changes
+ * will be reflected when the batch is sent.
+ *
+ * @param groupId ID of a group that you are interested in getting.
+ * @param parameters Parameters to be replaced for group
+ * @return Group associated to groupId
+ * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Groups/#tag/Groups/operation/ReplaceGroup
+ * @since 1.0
+ */
+ Group replace(String groupId, GroupReplaceRequestParameters parameters) throws ApiException;
+
+ /**
+ * Update a group
+ *
+ * @param groupId ID of a group that you are interested in getting.
+ * @param parameters Parameters to be used to update group
+ * @return Modified group associated to groupId
+ * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Groups/#tag/Groups/operation/UpdateGroup
+ * @since 1.0
+ */
+ Group update(String groupId, GroupUpdateRequestParameters parameters) throws ApiException;
+
+ /**
+ * Delete a group
+ *
+ * @param groupId ID of a group that you are interested in getting.
+ * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Groups/#tag/Groups/operation/deleteGroup
+ * @since 1.0
+ */
+ void delete(String groupId) throws ApiException;
+
+ /**
+ * Get phone numbers for a group
+ *
+ * @param groupId ID of a group that you are interested in getting.
+ * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Groups/#tag/Groups/operation/deleteGroup
+ * @since 1.0
+ */
+ Collection listMembers(String groupId) throws ApiException;
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/SMSService.java b/client/src/main/com/sinch/sdk/domains/sms/SMSService.java
index d194def95..1d0da811f 100644
--- a/client/src/main/com/sinch/sdk/domains/sms/SMSService.java
+++ b/client/src/main/com/sinch/sdk/domains/sms/SMSService.java
@@ -40,4 +40,12 @@ public interface SMSService {
* @since 1.0
*/
InboundsService inbounds();
+
+ /**
+ * Groups Service instance
+ *
+ * @return service instance for project
+ * @since 1.0
+ */
+ GroupsService groups();
}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/adapters/GroupsService.java b/client/src/main/com/sinch/sdk/domains/sms/adapters/GroupsService.java
new file mode 100644
index 000000000..b13f91c3a
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/adapters/GroupsService.java
@@ -0,0 +1,109 @@
+package com.sinch.sdk.domains.sms.adapters;
+
+import com.sinch.sdk.core.exceptions.ApiException;
+import com.sinch.sdk.core.http.HttpClient;
+import com.sinch.sdk.core.http.HttpMapper;
+import com.sinch.sdk.core.models.pagination.Page;
+import com.sinch.sdk.core.models.pagination.PageToken;
+import com.sinch.sdk.core.utils.Pair;
+import com.sinch.sdk.domains.sms.adapters.api.v1.GroupsApi;
+import com.sinch.sdk.domains.sms.adapters.converters.GroupsDtoConverter;
+import com.sinch.sdk.domains.sms.models.Group;
+import com.sinch.sdk.domains.sms.models.dto.v1.ApiGroupListDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.CreateGroupResponseDto;
+import com.sinch.sdk.domains.sms.models.requests.GroupCreateRequestParameters;
+import com.sinch.sdk.domains.sms.models.requests.GroupReplaceRequestParameters;
+import com.sinch.sdk.domains.sms.models.requests.GroupUpdateRequestParameters;
+import com.sinch.sdk.domains.sms.models.requests.GroupsListRequestParameters;
+import com.sinch.sdk.domains.sms.models.responses.GroupsListResponse;
+import com.sinch.sdk.models.Configuration;
+import java.util.Collection;
+
+public class GroupsService implements com.sinch.sdk.domains.sms.GroupsService {
+
+ private Configuration configuration;
+ private GroupsApi api;
+
+ public GroupsService() {}
+
+ private GroupsApi getApi() {
+ return this.api;
+ }
+
+ public GroupsService(Configuration configuration, HttpClient httpClient) {
+ this.configuration = configuration;
+ this.api = new GroupsApi(httpClient, configuration.getSmsServer(), new HttpMapper());
+ }
+
+ public Group get(String groupId) throws ApiException {
+
+ CreateGroupResponseDto response = getApi().retrieveGroup(configuration.getProjectId(), groupId);
+ return GroupsDtoConverter.convert(response);
+ }
+
+ public Group create() throws ApiException {
+ return this.create(null);
+ }
+
+ public Group create(GroupCreateRequestParameters parameters) throws ApiException {
+ GroupCreateRequestParameters guardParameters =
+ null != parameters ? parameters : GroupCreateRequestParameters.builder().build();
+
+ CreateGroupResponseDto response =
+ getApi()
+ .createGroup(configuration.getProjectId(), GroupsDtoConverter.convert(guardParameters));
+ return GroupsDtoConverter.convert(response);
+ }
+
+ public GroupsListResponse list() throws ApiException {
+ return this.list(null);
+ }
+
+ public GroupsListResponse list(GroupsListRequestParameters parameters) throws ApiException {
+ GroupsListRequestParameters guardParameters =
+ null != parameters ? parameters : GroupsListRequestParameters.builder().build();
+
+ ApiGroupListDto response =
+ getApi()
+ .listGroups(
+ configuration.getProjectId(),
+ guardParameters.getPage().orElse(null),
+ guardParameters.getPageSize().orElse(null));
+
+ Pair, PageToken> content = GroupsDtoConverter.convert(response);
+
+ return new GroupsListResponse(
+ this, new Page<>(guardParameters, content.getLeft(), content.getRight()));
+ }
+
+ public Group replace(String groupId, GroupReplaceRequestParameters parameters)
+ throws ApiException {
+ GroupReplaceRequestParameters guardParameters =
+ null != parameters ? parameters : GroupReplaceRequestParameters.builder().build();
+
+ CreateGroupResponseDto response =
+ getApi()
+ .replaceGroup(
+ configuration.getProjectId(), groupId, GroupsDtoConverter.convert(guardParameters));
+ return GroupsDtoConverter.convert(response);
+ }
+
+ public Group update(String groupId, GroupUpdateRequestParameters parameters) throws ApiException {
+ GroupUpdateRequestParameters guardParameters =
+ null != parameters ? parameters : GroupUpdateRequestParameters.builder().build();
+
+ CreateGroupResponseDto response =
+ getApi()
+ .updateGroup(
+ configuration.getProjectId(), groupId, GroupsDtoConverter.convert(guardParameters));
+ return GroupsDtoConverter.convert(response);
+ }
+
+ public void delete(String groupId) throws ApiException {
+ getApi().deleteGroup(configuration.getProjectId(), groupId);
+ }
+
+ public Collection listMembers(String groupId) throws ApiException {
+ return getApi().getMembers(configuration.getProjectId(), groupId);
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/adapters/SMSService.java b/client/src/main/com/sinch/sdk/domains/sms/adapters/SMSService.java
index 712f2867d..bbdd773ff 100644
--- a/client/src/main/com/sinch/sdk/domains/sms/adapters/SMSService.java
+++ b/client/src/main/com/sinch/sdk/domains/sms/adapters/SMSService.java
@@ -15,6 +15,7 @@ public class SMSService implements com.sinch.sdk.domains.sms.SMSService {
private WebHooksService webHooks;
private DeliveryReportsService deliveryReports;
private InboundsService inbounds;
+ private GroupsService groups;
public SMSService(Configuration configuration, HttpClient httpClient) {
this.configuration = configuration;
@@ -55,4 +56,12 @@ public InboundsService inbounds() {
}
return this.inbounds;
}
+
+ @Override
+ public GroupsService groups() {
+ if (null == this.groups) {
+ this.groups = new com.sinch.sdk.domains.sms.adapters.GroupsService(configuration, httpClient);
+ }
+ return this.groups;
+ }
}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/adapters/converters/GroupsDtoConverter.java b/client/src/main/com/sinch/sdk/domains/sms/adapters/converters/GroupsDtoConverter.java
new file mode 100644
index 000000000..fa8dda0da
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/adapters/converters/GroupsDtoConverter.java
@@ -0,0 +1,196 @@
+package com.sinch.sdk.domains.sms.adapters.converters;
+
+import com.sinch.sdk.core.models.pagination.PageToken;
+import com.sinch.sdk.core.utils.DateUtil;
+import com.sinch.sdk.core.utils.Pair;
+import com.sinch.sdk.domains.sms.models.Group;
+import com.sinch.sdk.domains.sms.models.GroupAutoUpdate;
+import com.sinch.sdk.domains.sms.models.GroupAutoUpdateKeyword;
+import com.sinch.sdk.domains.sms.models.dto.v1.AddKeywordDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.ApiGroupAutoUpdateDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.ApiGroupDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.ApiGroupListDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.CreateGroupResponseDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.GroupAutoUpdateDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.GroupObjectAutoUpdateDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.GroupObjectAutoUpdateRemoveDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.GroupObjectDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.RemoveKeywordDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.ReplaceGroupRequestDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.UpdateGroupRequestAutoUpdateAddDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.UpdateGroupRequestAutoUpdateDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.UpdateGroupRequestAutoUpdateRemoveDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.UpdateGroupRequestDto;
+import com.sinch.sdk.domains.sms.models.requests.GroupCreateRequestParameters;
+import com.sinch.sdk.domains.sms.models.requests.GroupReplaceRequestParameters;
+import com.sinch.sdk.domains.sms.models.requests.GroupUpdateRequestParameters;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class GroupsDtoConverter {
+
+ public static Group convert(CreateGroupResponseDto dto) {
+ return Group.builder()
+ .setId(dto.getId())
+ .setName(dto.getName())
+ .setSize(dto.getSize())
+ .setCreatedAt(DateUtil.toInstant(dto.getCreatedAt()))
+ .setModifiedAt(DateUtil.toInstant(dto.getModifiedAt()))
+ .setChildGroupIds(convertChildGroups(dto.getChildGroups()))
+ .setAutoUpdate(convert(dto.getAutoUpdate()))
+ .build();
+ }
+
+ public static GroupObjectDto convert(GroupCreateRequestParameters client) {
+ return new GroupObjectDto()
+ .name(client.getName().orElse(null))
+ .members(client.getMembers().map(ArrayList::new).orElse(null))
+ .childGroups(client.getChildGroupIds().map(ArrayList::new).orElse(null))
+ .autoUpdate(client.getAutoUpdate().map(GroupsDtoConverter::convert).orElse(null));
+ }
+
+ public static Pair, PageToken> convert(ApiGroupListDto dto) {
+ // check end of pagination limit reached: (current page number * page size ) cannot be greater
+ // than "count" to be able to call next page
+ Integer nextPageToken =
+ ((dto.getPage() + 1) * Long.valueOf(dto.getPageSize())) >= dto.getCount()
+ ? null
+ : dto.getPage() + 1;
+ Collection collection = dto.getGroups();
+ Collection pageContent = new ArrayList<>();
+ if (null != collection) {
+ for (ApiGroupDto innerDto : collection) {
+ Group convert = convert(innerDto);
+ pageContent.add(convert);
+ }
+ }
+ return new Pair<>(pageContent, new PageToken<>(nextPageToken));
+ }
+
+ public static ReplaceGroupRequestDto convert(GroupReplaceRequestParameters client) {
+ return new ReplaceGroupRequestDto()
+ .name(client.getName().orElse(null))
+ .members(client.getMembers().map(ArrayList::new).orElse(null));
+ }
+
+ public static UpdateGroupRequestDto convert(GroupUpdateRequestParameters client) {
+ return new UpdateGroupRequestDto()
+ .name(client.getName().orElse(null))
+ .add(client.getAdd().map(ArrayList::new).orElse(null))
+ .remove(client.getRemove().map(ArrayList::new).orElse(null))
+ .addFromGroup(client.getAddFromGroup().orElse(null))
+ .removeFromGroup(client.getRemoveFromGroup().orElse(null))
+ .autoUpdate(client.getAutoUpdate().map(GroupsDtoConverter::convertForUpdate).orElse(null));
+ }
+
+ private static Group convert(ApiGroupDto dto) {
+ return Group.builder()
+ .setId(dto.getId())
+ .setName(dto.getName())
+ .setSize(dto.getSize())
+ .setCreatedAt(DateUtil.toInstant(dto.getCreatedAt()))
+ .setModifiedAt(DateUtil.toInstant(dto.getModifiedAt()))
+ .setChildGroupIds(convertChildGroups(dto.getChildGroups()))
+ .setAutoUpdate(convert(dto.getAutoUpdate()))
+ .build();
+ }
+
+ private static Collection convertChildGroups(Set dto) {
+ if (null == dto) {
+ return null;
+ }
+ return dto.stream().map(f -> (String) f).collect(Collectors.toList());
+ }
+
+ private static GroupAutoUpdate convert(GroupAutoUpdateDto dto) {
+ if (null == dto) {
+ return null;
+ }
+ return GroupAutoUpdate.builder()
+ .setTo(dto.getTo())
+ .setAdd(convert(dto.getAdd()))
+ .setRemove(convert(dto.getRemove()))
+ .build();
+ }
+
+ private static GroupAutoUpdate convert(ApiGroupAutoUpdateDto dto) {
+ if (null == dto) {
+ return null;
+ }
+ return GroupAutoUpdate.builder()
+ .setTo(dto.getTo())
+ .setAdd(convert(dto.getAdd()))
+ .setRemove(convert(dto.getRemove()))
+ .build();
+ }
+
+ private static GroupObjectAutoUpdateDto convert(GroupAutoUpdate client) {
+ if (null == client) {
+ return null;
+ }
+ return new GroupObjectAutoUpdateDto()
+ .to(client.getTo())
+ .add(convertAdd(client.getAdd()))
+ .remove(convertRemove(client.getRemove()));
+ }
+
+ private static UpdateGroupRequestAutoUpdateDto convertForUpdate(GroupAutoUpdate client) {
+ if (null == client) {
+ return null;
+ }
+ return new UpdateGroupRequestAutoUpdateDto()
+ .to(client.getTo())
+ .add(convertAdd(client.getAdd()))
+ .remove(convertRemoveForUpdate(client.getRemove()));
+ }
+
+ private static GroupAutoUpdateKeyword convert(AddKeywordDto dto) {
+ if (null == dto) {
+ return null;
+ }
+ return GroupAutoUpdateKeyword.builder()
+ .setFirstWord(dto.getFirstWord())
+ .setSecondWord(dto.getSecondWord())
+ .build();
+ }
+
+ private static UpdateGroupRequestAutoUpdateAddDto convertAdd(GroupAutoUpdateKeyword client) {
+ if (null == client) {
+ return null;
+ }
+ return new UpdateGroupRequestAutoUpdateAddDto()
+ .firstWord(client.getFirstWord())
+ .secondWord(client.getSecondWord());
+ }
+
+ private static GroupAutoUpdateKeyword convert(RemoveKeywordDto dto) {
+ if (null == dto) {
+ return null;
+ }
+ return GroupAutoUpdateKeyword.builder()
+ .setFirstWord(dto.getFirstWord())
+ .setSecondWord(dto.getSecondWord())
+ .build();
+ }
+
+ private static GroupObjectAutoUpdateRemoveDto convertRemove(GroupAutoUpdateKeyword client) {
+ if (null == client) {
+ return null;
+ }
+ return new GroupObjectAutoUpdateRemoveDto()
+ .firstWord(client.getFirstWord())
+ .secondWord(client.getSecondWord());
+ }
+
+ private static UpdateGroupRequestAutoUpdateRemoveDto convertRemoveForUpdate(
+ GroupAutoUpdateKeyword client) {
+ if (null == client) {
+ return null;
+ }
+ return new UpdateGroupRequestAutoUpdateRemoveDto()
+ .firstWord(client.getFirstWord())
+ .secondWord(client.getSecondWord());
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/Group.java b/client/src/main/com/sinch/sdk/domains/sms/models/Group.java
new file mode 100644
index 000000000..b7c6b3be7
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/Group.java
@@ -0,0 +1,151 @@
+package com.sinch.sdk.domains.sms.models;
+
+import com.sinch.sdk.domains.sms.models.GroupAutoUpdateKeyword.Builder;
+import java.time.Instant;
+import java.util.Collection;
+
+public class Group {
+
+ private final String id;
+ private final String name;
+ private final Integer size;
+ private final Instant createdAt;
+ private final Instant modifiedAt;
+ private final Collection childGroupIds;
+ private final GroupAutoUpdate autoUpdate;
+
+ /**
+ * @param id Unique identifier for the group
+ * @param name Name of group if set
+ * @param size The number of members currently in the group
+ * @param createdAt Timestamp for when the group was created
+ * @param modifiedAt Timestamp for when the group was created
+ * @param childGroupIds MSISDNs of child group will be included in this group. If present then
+ * this group will be auto populated. Constraints: Elements must be group IDs
+ * @param autoUpdate Describes how this group is auto updated through user interaction. Is
+ * null
if the group is not auto updated.
+ */
+ public Group(
+ String id,
+ String name,
+ Integer size,
+ Instant createdAt,
+ Instant modifiedAt,
+ Collection childGroupIds,
+ GroupAutoUpdate autoUpdate) {
+ this.id = id;
+ this.name = name;
+ this.size = size;
+ this.createdAt = createdAt;
+ this.modifiedAt = modifiedAt;
+ this.childGroupIds = childGroupIds;
+ this.autoUpdate = autoUpdate;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Integer getSize() {
+ return size;
+ }
+
+ public Instant getCreatedAt() {
+ return createdAt;
+ }
+
+ public Instant getModifiedAt() {
+ return modifiedAt;
+ }
+
+ public Collection getChildGroupIds() {
+ return childGroupIds;
+ }
+
+ public GroupAutoUpdate getAutoUpdate() {
+ return autoUpdate;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public String toString() {
+ return "Group{"
+ + "id='"
+ + id
+ + '\''
+ + ", name='"
+ + name
+ + '\''
+ + ", size="
+ + size
+ + ", createdAt="
+ + createdAt
+ + ", modifiedAt="
+ + modifiedAt
+ + ", childGroupIds="
+ + childGroupIds
+ + ", autoUpdate="
+ + autoUpdate
+ + '}';
+ }
+
+ public static class Builder {
+
+ String id;
+ String name;
+ Integer size;
+ Instant createdAt;
+ Instant modifiedAt;
+ Collection childGroupIds;
+ GroupAutoUpdate autoUpdate;
+
+ private Builder() {}
+ ;
+
+ public Builder setId(String id) {
+ this.id = id;
+ return this;
+ }
+
+ public Builder setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Builder setSize(Integer size) {
+ this.size = size;
+ return this;
+ }
+
+ public Builder setCreatedAt(Instant createdAt) {
+ this.createdAt = createdAt;
+ return this;
+ }
+
+ public Builder setModifiedAt(Instant modifiedAt) {
+ this.modifiedAt = modifiedAt;
+ return this;
+ }
+
+ public Builder setChildGroupIds(Collection childGroupIds) {
+ this.childGroupIds = childGroupIds;
+ return this;
+ }
+
+ public Builder setAutoUpdate(GroupAutoUpdate autoUpdate) {
+ this.autoUpdate = autoUpdate;
+ return this;
+ }
+
+ public Group build() {
+ return new Group(id, name, size, createdAt, modifiedAt, childGroupIds, autoUpdate);
+ }
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/GroupAutoUpdate.java b/client/src/main/com/sinch/sdk/domains/sms/models/GroupAutoUpdate.java
new file mode 100644
index 000000000..951114195
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/GroupAutoUpdate.java
@@ -0,0 +1,71 @@
+package com.sinch.sdk.domains.sms.models;
+
+import com.sinch.sdk.domains.sms.models.GroupAutoUpdateKeyword.Builder;
+
+public class GroupAutoUpdate {
+ private final String to;
+ private final GroupAutoUpdateKeyword add;
+ private final GroupAutoUpdateKeyword remove;
+
+ /**
+ * @param to Short code or long number addressed in MO.
+ * Constraints: Must be valid MSISDN or short code.
+ * @param add Keyword to be sent in MO to add MSISDN to a group
+ * @param remove Keyword to be sent in MO to remove MSISDN to a group
+ */
+ public GroupAutoUpdate(String to, GroupAutoUpdateKeyword add, GroupAutoUpdateKeyword remove) {
+ this.to = to;
+ this.add = add;
+ this.remove = remove;
+ }
+
+ public String getTo() {
+ return to;
+ }
+
+ public GroupAutoUpdateKeyword getAdd() {
+ return add;
+ }
+
+ public GroupAutoUpdateKeyword getRemove() {
+ return remove;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public String toString() {
+ return "GroupAutoUpdate{" + "to='" + to + '\'' + ", add=" + add + ", remove=" + remove + '}';
+ }
+
+ public static class Builder {
+
+ String to;
+ GroupAutoUpdateKeyword add;
+ GroupAutoUpdateKeyword remove;
+
+ private Builder() {}
+ ;
+
+ public Builder setTo(String to) {
+ this.to = to;
+ return this;
+ }
+
+ public Builder setAdd(GroupAutoUpdateKeyword add) {
+ this.add = add;
+ return this;
+ }
+
+ public Builder setRemove(GroupAutoUpdateKeyword remove) {
+ this.remove = remove;
+ return this;
+ }
+
+ public GroupAutoUpdate build() {
+ return new GroupAutoUpdate(to, add, remove);
+ }
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/GroupAutoUpdateKeyword.java b/client/src/main/com/sinch/sdk/domains/sms/models/GroupAutoUpdateKeyword.java
new file mode 100644
index 000000000..49145883a
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/GroupAutoUpdateKeyword.java
@@ -0,0 +1,66 @@
+package com.sinch.sdk.domains.sms.models;
+
+import com.sinch.sdk.domains.sms.models.InboundBinary.Builder;
+
+public class GroupAutoUpdateKeyword {
+
+ private final String firstWord;
+ private final String secondWord;
+
+ /**
+ * @param firstWord Opt-in keyword like "JOIN" if _auto_update.to_ is dedicated long/short number
+ * or unique brand keyword like "Sinch" if it is a shared short code.
+ * @param secondWord Opt-in keyword like "JOIN" if _auto_update.to_ is shared short code.
+ */
+ public GroupAutoUpdateKeyword(String firstWord, String secondWord) {
+ this.firstWord = firstWord;
+ this.secondWord = secondWord;
+ }
+
+ public String getFirstWord() {
+ return firstWord;
+ }
+
+ public String getSecondWord() {
+ return secondWord;
+ }
+
+ @Override
+ public String toString() {
+ return "GroupAutoUpdateKeyword{"
+ + "firstWord='"
+ + firstWord
+ + '\''
+ + ", secondWord='"
+ + secondWord
+ + '\''
+ + '}';
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+
+ String firstWord;
+ String secondWord;
+
+ private Builder() {}
+ ;
+
+ public Builder setFirstWord(String firstWord) {
+ this.firstWord = firstWord;
+ return this;
+ }
+
+ public Builder setSecondWord(String secondWord) {
+ this.secondWord = secondWord;
+ return this;
+ }
+
+ public GroupAutoUpdateKeyword build() {
+ return new GroupAutoUpdateKeyword(firstWord, secondWord);
+ }
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/requests/GroupCreateRequestParameters.java b/client/src/main/com/sinch/sdk/domains/sms/models/requests/GroupCreateRequestParameters.java
new file mode 100644
index 000000000..ffd12e2c3
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/requests/GroupCreateRequestParameters.java
@@ -0,0 +1,117 @@
+package com.sinch.sdk.domains.sms.models.requests;
+
+import com.sinch.sdk.domains.sms.models.GroupAutoUpdate;
+import java.util.Collection;
+import java.util.Optional;
+
+/**
+ * Parameters request to create a group
+ *
+ * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Groups/#tag/Groups/operation/CreateGroup
+ * @since 1.0
+ */
+public class GroupCreateRequestParameters {
+
+ private final String name;
+ private final Collection members;
+ private final Collection childGroupIds;
+ private final GroupAutoUpdate autoUpdate;
+
+ /**
+ * @param name Name of the group
+ * @param members Initial list of phone numbers in E.164 format MSISDNs for the group
+ * @param childGroupIds Child group IDs
+ * @param autoUpdate Auto update settings
+ */
+ public GroupCreateRequestParameters(
+ String name,
+ Collection members,
+ Collection childGroupIds,
+ GroupAutoUpdate autoUpdate) {
+ this.name = name;
+ this.members = members;
+ this.childGroupIds = childGroupIds;
+ this.autoUpdate = autoUpdate;
+ }
+
+ public Optional getName() {
+ return Optional.ofNullable(name);
+ }
+
+ public Optional> getMembers() {
+ return Optional.ofNullable(members);
+ }
+
+ public Optional> getChildGroupIds() {
+ return Optional.ofNullable(childGroupIds);
+ }
+
+ public Optional getAutoUpdate() {
+ return Optional.ofNullable(autoUpdate);
+ }
+
+ @Override
+ public String toString() {
+ return "GroupCreateRequestParameters{"
+ + "name='"
+ + name
+ + '\''
+ + ", members="
+ + members
+ + ", childGroupIds="
+ + childGroupIds
+ + ", autoUpdate="
+ + autoUpdate
+ + '}';
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static Builder builder(GroupCreateRequestParameters parameters) {
+ return new Builder(parameters);
+ }
+
+ public static class Builder {
+
+ String name;
+ Collection members;
+ Collection childGroupIds;
+ GroupAutoUpdate autoUpdate;
+
+ private Builder() {}
+
+ private Builder(GroupCreateRequestParameters parameters) {
+ this.name = parameters.getName().orElse(null);
+ this.members = parameters.getMembers().orElse(null);
+ this.childGroupIds = parameters.getChildGroupIds().orElse(null);
+ this.autoUpdate = parameters.getAutoUpdate().orElse(null);
+ }
+
+ public Builder setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Builder setMembers(Collection members) {
+ this.members = members;
+ return this;
+ }
+
+ public Builder setChildGroupIds(Collection childGroupIds) {
+ this.childGroupIds = childGroupIds;
+ return this;
+ }
+
+ public Builder setAutoUpdate(GroupAutoUpdate autoUpdate) {
+ this.autoUpdate = autoUpdate;
+ return this;
+ }
+
+ public GroupCreateRequestParameters build() {
+ return new GroupCreateRequestParameters(name, members, childGroupIds, autoUpdate);
+ }
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/requests/GroupReplaceRequestParameters.java b/client/src/main/com/sinch/sdk/domains/sms/models/requests/GroupReplaceRequestParameters.java
new file mode 100644
index 000000000..f9d3def79
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/requests/GroupReplaceRequestParameters.java
@@ -0,0 +1,75 @@
+package com.sinch.sdk.domains.sms.models.requests;
+
+import java.util.Collection;
+import java.util.Optional;
+
+/**
+ * Parameters request to replace a group
+ *
+ * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Groups/#tag/Groups/operation/ReplaceGroup
+ * @since 1.0
+ */
+public class GroupReplaceRequestParameters {
+
+ private final String name;
+ private final Collection members;
+
+ /**
+ * @param name Name of the group
+ * @param members The initial members of the group.
+ * Constraints: Elements must be phone numbers in E.164 format MSISDNs.
+ */
+ public GroupReplaceRequestParameters(String name, Collection members) {
+ this.name = name;
+ this.members = members;
+ }
+
+ public Optional getName() {
+ return Optional.ofNullable(name);
+ }
+
+ public Optional> getMembers() {
+ return Optional.ofNullable(members);
+ }
+
+ @Override
+ public String toString() {
+ return "GroupCreateRequestParameters{" + "name='" + name + '\'' + ", members=" + members + '}';
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static Builder builder(GroupReplaceRequestParameters parameters) {
+ return new Builder(parameters);
+ }
+
+ public static class Builder {
+
+ String name;
+ Collection members;
+
+ private Builder() {}
+
+ private Builder(GroupReplaceRequestParameters parameters) {
+ this.name = parameters.getName().orElse(null);
+ this.members = parameters.getMembers().orElse(null);
+ }
+
+ public Builder setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Builder setMembers(Collection members) {
+ this.members = members;
+ return this;
+ }
+
+ public GroupReplaceRequestParameters build() {
+ return new GroupReplaceRequestParameters(name, members);
+ }
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/requests/GroupUpdateRequestParameters.java b/client/src/main/com/sinch/sdk/domains/sms/models/requests/GroupUpdateRequestParameters.java
new file mode 100644
index 000000000..ae63293b7
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/requests/GroupUpdateRequestParameters.java
@@ -0,0 +1,156 @@
+package com.sinch.sdk.domains.sms.models.requests;
+
+import com.sinch.sdk.domains.sms.models.GroupAutoUpdate;
+import java.util.Collection;
+import java.util.Optional;
+
+/**
+ * Parameters request to updat" a group
+ *
+ * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Groups/#tag/Groups/operation/UpdateGroup
+ * @since 1.0
+ */
+public class GroupUpdateRequestParameters {
+
+ private final String name;
+ private final Collection add;
+ private final Collection remove;
+ private final String addFromGroup;
+ private final String removeFromGroup;
+ private final GroupAutoUpdate autoUpdate;
+
+ public GroupUpdateRequestParameters(
+ String name,
+ Collection add,
+ Collection remove,
+ String addFromGroup,
+ String removeFromGroup,
+ GroupAutoUpdate autoUpdate) {
+ this.name = name;
+ this.add = add;
+ this.remove = remove;
+ this.addFromGroup = addFromGroup;
+ this.removeFromGroup = removeFromGroup;
+ this.autoUpdate = autoUpdate;
+ }
+
+ public Optional getName() {
+ return Optional.ofNullable(name);
+ }
+
+ public Optional> getAdd() {
+ return Optional.ofNullable(add);
+ }
+
+ public Optional> getRemove() {
+ return Optional.ofNullable(remove);
+ }
+
+ public Optional getAddFromGroup() {
+ return Optional.ofNullable(addFromGroup);
+ }
+
+ public Optional getRemoveFromGroup() {
+ return Optional.ofNullable(removeFromGroup);
+ }
+
+ public Optional getAutoUpdate() {
+ return Optional.ofNullable(autoUpdate);
+ }
+
+ @Override
+ public String toString() {
+ return "GroupUpdateRequestParameters{"
+ + "name='"
+ + name
+ + '\''
+ + ", add="
+ + add
+ + ", remove="
+ + remove
+ + ", addFromGroup='"
+ + addFromGroup
+ + '\''
+ + ", removeFromGroup='"
+ + removeFromGroup
+ + '\''
+ + ", autoUpdate="
+ + autoUpdate
+ + '}';
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static Builder builder(GroupUpdateRequestParameters parameters) {
+ return new Builder(parameters);
+ }
+
+ public static class Builder {
+
+ String name;
+
+ Collection add;
+
+ Collection remove;
+
+ String addFromGroup;
+
+ String removeFromGroup;
+
+ GroupAutoUpdate autoUpdate;
+
+ private Builder() {}
+
+ private Builder(GroupUpdateRequestParameters parameters) {
+ this.name = parameters.getName().orElse(null);
+
+ this.add = parameters.getAdd().orElse(null);
+
+ this.remove = parameters.getRemove().orElse(null);
+
+ this.addFromGroup = parameters.getAddFromGroup().orElse(null);
+
+ this.removeFromGroup = parameters.getRemoveFromGroup().orElse(null);
+
+ this.autoUpdate = parameters.getAutoUpdate().orElse(null);
+ }
+
+ public Builder setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Builder setAdd(Collection add) {
+ this.add = add;
+ return this;
+ }
+
+ public Builder setRemove(Collection remove) {
+ this.remove = remove;
+ return this;
+ }
+
+ public Builder setAddFromGroup(String addFromGroup) {
+ this.addFromGroup = addFromGroup;
+ return this;
+ }
+
+ public Builder setRemoveFromGroup(String removeFromGroup) {
+ this.removeFromGroup = removeFromGroup;
+ return this;
+ }
+
+ public Builder setAutoUpdate(GroupAutoUpdate autoUpdate) {
+ this.autoUpdate = autoUpdate;
+ return this;
+ }
+
+ public GroupUpdateRequestParameters build() {
+ return new GroupUpdateRequestParameters(
+ name, add, remove, addFromGroup, removeFromGroup, autoUpdate);
+ }
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/requests/GroupsListRequestParameters.java b/client/src/main/com/sinch/sdk/domains/sms/models/requests/GroupsListRequestParameters.java
new file mode 100644
index 000000000..88a695d36
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/requests/GroupsListRequestParameters.java
@@ -0,0 +1,68 @@
+package com.sinch.sdk.domains.sms.models.requests;
+
+import java.util.Optional;
+
+/**
+ * Parameters request to list groups
+ *
+ * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Groups/#tag/Groups/operation/ListGroups
+ * @since 1.0
+ */
+public class GroupsListRequestParameters {
+
+ private final Integer page;
+ private final Integer pageSize;
+
+ /**
+ * @param page The page number starting from 0.
+ * @param pageSize Determines the size of a page.
+ */
+ public GroupsListRequestParameters(Integer page, Integer pageSize) {
+ this.page = page;
+ this.pageSize = pageSize;
+ }
+
+ public Optional getPage() {
+ return Optional.ofNullable(page);
+ }
+
+ public Optional getPageSize() {
+ return Optional.ofNullable(pageSize);
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static Builder builder(GroupsListRequestParameters parameters) {
+ return new Builder(parameters);
+ }
+
+ public static class Builder {
+
+ Integer page;
+ Integer pageSize;
+
+ private Builder() {}
+
+ private Builder(GroupsListRequestParameters parameters) {
+ this.page = parameters.page;
+ this.pageSize = parameters.pageSize;
+ }
+
+ public Builder setPage(Integer page) {
+ this.page = page;
+ return this;
+ }
+
+ public Builder setPageSize(Integer pageSize) {
+ this.pageSize = pageSize;
+ return this;
+ }
+
+ public GroupsListRequestParameters build() {
+ return new GroupsListRequestParameters(page, pageSize);
+ }
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/responses/GroupsListResponse.java b/client/src/main/com/sinch/sdk/domains/sms/models/responses/GroupsListResponse.java
new file mode 100644
index 000000000..bc8f5a11c
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/responses/GroupsListResponse.java
@@ -0,0 +1,50 @@
+package com.sinch.sdk.domains.sms.models.responses;
+
+import com.sinch.sdk.core.models.pagination.ListResponse;
+import com.sinch.sdk.core.models.pagination.Page;
+import com.sinch.sdk.domains.sms.GroupsService;
+import com.sinch.sdk.domains.sms.models.Group;
+import com.sinch.sdk.domains.sms.models.requests.GroupsListRequestParameters;
+import java.util.Collection;
+import java.util.NoSuchElementException;
+
+/**
+ * Groups List response
+ *
+ * @since 1.0
+ */
+public class GroupsListResponse extends ListResponse {
+
+ private final Page page;
+ private final GroupsService service;
+
+ public GroupsListResponse(
+ GroupsService service, Page page) {
+ this.service = service;
+ this.page = page;
+ }
+
+ public boolean hasNextPage() {
+ return (null != page.getNextPageToken() && null != page.getNextPageToken().getToken());
+ }
+
+ public GroupsListResponse nextPage() {
+ if (!hasNextPage()) {
+ throw new NoSuchElementException("Reached the last page of the API response");
+ }
+ GroupsListRequestParameters.Builder newParameters =
+ GroupsListRequestParameters.builder(page.getParameters());
+ Integer nextToken = page.getNextPageToken().getToken();
+ newParameters.setPage(nextToken);
+ return service.list(newParameters.build());
+ }
+
+ public Collection getContent() {
+ return page.getEntities();
+ }
+
+ @Override
+ public String toString() {
+ return "GroupsListResponse{" + "page=" + page + '}';
+ }
+}
diff --git a/client/src/test/java/com/sinch/sdk/domains/sms/adapters/GroupsServiceTest.java b/client/src/test/java/com/sinch/sdk/domains/sms/adapters/GroupsServiceTest.java
new file mode 100644
index 000000000..d08edb551
--- /dev/null
+++ b/client/src/test/java/com/sinch/sdk/domains/sms/adapters/GroupsServiceTest.java
@@ -0,0 +1,222 @@
+package com.sinch.sdk.domains.sms.adapters;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.adelean.inject.resources.junit.jupiter.GivenJsonResource;
+import com.adelean.inject.resources.junit.jupiter.TestWithResources;
+import com.sinch.sdk.BaseTest;
+import com.sinch.sdk.core.exceptions.ApiException;
+import com.sinch.sdk.domains.sms.adapters.api.v1.GroupsApi;
+import com.sinch.sdk.domains.sms.adapters.converters.GroupsDtoConverter;
+import com.sinch.sdk.domains.sms.models.Group;
+import com.sinch.sdk.domains.sms.models.GroupAutoUpdate;
+import com.sinch.sdk.domains.sms.models.GroupAutoUpdateKeyword;
+import com.sinch.sdk.domains.sms.models.dto.v1.ApiGroupListDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.CreateGroupResponseDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.GroupObjectDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.ReplaceGroupRequestDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.UpdateGroupRequestDto;
+import com.sinch.sdk.domains.sms.models.requests.GroupReplaceRequestParameters;
+import com.sinch.sdk.domains.sms.models.requests.GroupUpdateRequestParameters;
+import com.sinch.sdk.domains.sms.models.responses.GroupsListResponse;
+import com.sinch.sdk.models.Configuration;
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+@TestWithResources
+class GroupsServiceTest extends BaseTest {
+
+ @Mock Configuration configuration;
+ @Mock GroupsApi api;
+ @InjectMocks GroupsService service;
+
+ @Captor ArgumentCaptor groupIdCaptor;
+
+ @GivenJsonResource("/domains/sms/v1/GroupResponseDto.json")
+ CreateGroupResponseDto createGroupResponseDto;
+
+ @GivenJsonResource("/domains/sms/v1/GroupsListResponseDtoPage0.json")
+ ApiGroupListDto groupsListResponseDtoPage0;
+
+ @GivenJsonResource("/domains/sms/v1/GroupsListResponseDtoPage1.json")
+ ApiGroupListDto groupsListResponseDtoPage1;
+
+ @Test
+ void get() throws ApiException {
+
+ when(api.retrieveGroup(eq(configuration.getProjectId()), eq("foo group ID")))
+ .thenReturn(createGroupResponseDto);
+
+ Group response = service.get("foo group ID");
+
+ Assertions.assertThat(response)
+ .usingRecursiveComparison()
+ .isEqualTo(GroupsDtoConverter.convert(createGroupResponseDto));
+ }
+
+ @Test
+ void create() throws ApiException {
+
+ when(api.createGroup(eq(configuration.getProjectId()), eq(new GroupObjectDto())))
+ .thenReturn(createGroupResponseDto);
+
+ Group response = service.create(null);
+
+ Assertions.assertThat(response)
+ .usingRecursiveComparison()
+ .isEqualTo(GroupsDtoConverter.convert(createGroupResponseDto));
+ }
+
+ @Test
+ void list() throws ApiException {
+
+ when(api.listGroups(eq(configuration.getProjectId()), eq(null), eq(null)))
+ .thenReturn(groupsListResponseDtoPage0);
+ when(api.listGroups(eq(configuration.getProjectId()), eq(1), eq(null)))
+ .thenReturn(groupsListResponseDtoPage1);
+
+ GroupsListResponse response = service.list(null);
+
+ Iterator iterator = response.autoPageIter();
+ Group item = iterator.next();
+ Assertions.assertThat(iterator.hasNext()).isEqualTo(true);
+
+ Assertions.assertThat(item)
+ .usingRecursiveComparison()
+ .isEqualTo(
+ Group.builder()
+ .setId("01FC66621XXXXX119Z8PMV1QPU")
+ .setName("My new customers")
+ .setSize(2)
+ .setCreatedAt(Instant.parse("2019-08-24T14:15:22Z"))
+ .setModifiedAt(Instant.parse("2019-08-24T14:15:44Z"))
+ .setChildGroupIds(
+ Arrays.asList("01FC66621XXXXX119Z8PMV1AHY", "01FC66621XXXXX119Z8PMV1A00"))
+ .setAutoUpdate(
+ GroupAutoUpdate.builder()
+ .setTo("15551231234")
+ .setAdd(
+ GroupAutoUpdateKeyword.builder()
+ .setFirstWord("Add 1st keyword")
+ .build())
+ .setRemove(
+ GroupAutoUpdateKeyword.builder()
+ .setFirstWord("remove 1st keyword")
+ .setSecondWord("remove 2nd keyword")
+ .build())
+ .build())
+ .build());
+
+ item = iterator.next();
+ Assertions.assertThat(iterator.hasNext()).isEqualTo(true);
+ Assertions.assertThat(item)
+ .usingRecursiveComparison()
+ .isEqualTo(Group.builder().setId("foo id").build());
+
+ item = iterator.next();
+ Assertions.assertThat(iterator.hasNext()).isEqualTo(false);
+ Assertions.assertThat(item)
+ .usingRecursiveComparison()
+ .isEqualTo(
+ Group.builder()
+ .setId("01FC66621XXXXX119Z8PMV1QPU")
+ .setName("My new customers")
+ .setSize(2)
+ .setCreatedAt(Instant.parse("2019-08-24T14:15:22Z"))
+ .setModifiedAt(Instant.parse("2019-08-24T14:15:44Z"))
+ .setChildGroupIds(
+ Arrays.asList("01FC66621XXXXX119Z8PMV1AHY", "01FC66621XXXXX119Z8PMV1A00"))
+ .setAutoUpdate(
+ GroupAutoUpdate.builder()
+ .setTo("15551231234")
+ .setAdd(
+ GroupAutoUpdateKeyword.builder()
+ .setFirstWord("Add 1st keyword")
+ .build())
+ .setRemove(
+ GroupAutoUpdateKeyword.builder()
+ .setFirstWord("remove 1st keyword")
+ .setSecondWord("remove 2nd keyword")
+ .build())
+ .build())
+ .build());
+ }
+
+ @Test
+ void replace() throws ApiException {
+
+ when(api.replaceGroup(
+ eq(configuration.getProjectId()),
+ eq("group id"),
+ eq(
+ new ReplaceGroupRequestDto()
+ .name("foo name")
+ .members(Collections.singletonList("foo member")))))
+ .thenReturn(createGroupResponseDto);
+
+ Group response =
+ service.replace(
+ "group id",
+ GroupReplaceRequestParameters.builder()
+ .setName("foo name")
+ .setMembers(Collections.singletonList("foo member"))
+ .build());
+
+ Assertions.assertThat(response)
+ .usingRecursiveComparison()
+ .isEqualTo(GroupsDtoConverter.convert(createGroupResponseDto));
+ }
+
+ @Test
+ void update() throws ApiException {
+
+ when(api.updateGroup(
+ eq(configuration.getProjectId()),
+ eq("group id"),
+ eq(new UpdateGroupRequestDto().name("foo name"))))
+ .thenReturn(createGroupResponseDto);
+
+ Group response =
+ service.update(
+ "group id", GroupUpdateRequestParameters.builder().setName("foo name").build());
+
+ Assertions.assertThat(response)
+ .usingRecursiveComparison()
+ .isEqualTo(GroupsDtoConverter.convert(createGroupResponseDto));
+ }
+
+ @Test
+ void delete() throws ApiException {
+
+ service.delete("foo group id");
+
+ verify(api).deleteGroup(eq(configuration.getProjectId()), groupIdCaptor.capture());
+
+ String parameter = groupIdCaptor.getValue();
+ Assertions.assertThat(parameter).isEqualTo("foo group id");
+ }
+
+ @Test
+ void listMembers() throws ApiException {
+
+ when(api.getMembers(eq(configuration.getProjectId()), eq("group id")))
+ .thenReturn(Arrays.asList("entry 1", "entry 2"));
+
+ Collection response = service.listMembers("group id");
+
+ Assertions.assertThat(response)
+ .usingRecursiveComparison()
+ .isEqualTo(Arrays.asList("entry 1", "entry 2"));
+ }
+}
diff --git a/client/src/test/java/com/sinch/sdk/domains/sms/adapters/converters/GroupsDtoConverterTest.java b/client/src/test/java/com/sinch/sdk/domains/sms/adapters/converters/GroupsDtoConverterTest.java
new file mode 100644
index 000000000..c5d049fd5
--- /dev/null
+++ b/client/src/test/java/com/sinch/sdk/domains/sms/adapters/converters/GroupsDtoConverterTest.java
@@ -0,0 +1,131 @@
+package com.sinch.sdk.domains.sms.adapters.converters;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import com.adelean.inject.resources.junit.jupiter.GivenJsonResource;
+import com.adelean.inject.resources.junit.jupiter.TestWithResources;
+import com.sinch.sdk.BaseTest;
+import com.sinch.sdk.domains.sms.models.Group;
+import com.sinch.sdk.domains.sms.models.GroupAutoUpdate;
+import com.sinch.sdk.domains.sms.models.GroupAutoUpdateKeyword;
+import com.sinch.sdk.domains.sms.models.dto.v1.CreateGroupResponseDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.GroupAutoUpdateDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.GroupObjectDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.ReplaceGroupRequestDto;
+import com.sinch.sdk.domains.sms.models.dto.v1.UpdateGroupRequestDto;
+import com.sinch.sdk.domains.sms.models.requests.GroupCreateRequestParameters;
+import com.sinch.sdk.domains.sms.models.requests.GroupReplaceRequestParameters;
+import com.sinch.sdk.domains.sms.models.requests.GroupUpdateRequestParameters;
+import java.rmi.UnexpectedException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+@TestWithResources
+class GroupsDtoConverterTest extends BaseTest {
+
+ @GivenJsonResource("/domains/sms/v1/GroupResponseDto.json")
+ CreateGroupResponseDto createGroupResponseDto;
+
+ @GivenJsonResource("/domains/sms/v1/GroupCreateRequestParametersDto.json")
+ GroupObjectDto createGroupRequestParametersDto;
+
+ @GivenJsonResource("/domains/sms/v1/GroupUpdateRequestParametersDto.json")
+ UpdateGroupRequestDto groupUpdateRequestParametersDto;
+
+ @GivenJsonResource("/domains/sms/v1/GroupReplaceRequestParametersDto.json")
+ ReplaceGroupRequestDto groupReplaceRequestParametersDto;
+
+ static void compareWithDto(Group client, CreateGroupResponseDto dto) {
+ assertEquals(dto.getSize(), client.getSize());
+ assertEquals(dto.getCreatedAt().toInstant(), client.getCreatedAt());
+ assertEquals(dto.getModifiedAt().toInstant(), client.getModifiedAt());
+ assertEquals(dto.getId(), client.getId());
+ assertEquals(dto.getName(), client.getName());
+ Iterator> dtoIterator = dto.getChildGroups().iterator();
+ Iterator> clientIterator = client.getChildGroupIds().iterator();
+ dtoIterator.forEachRemaining(dtoItem -> assertEquals(clientIterator.next(), dtoItem));
+ compareWithDto(client.getAutoUpdate(), dto.getAutoUpdate());
+ }
+
+ static void compareWithDto(GroupAutoUpdate client, GroupAutoUpdateDto dto) {
+ assertEquals(dto.getTo(), client.getTo());
+ assertEquals(dto.getAdd().getFirstWord(), client.getAdd().getFirstWord());
+ assertEquals(dto.getAdd().getSecondWord(), client.getAdd().getSecondWord());
+ assertEquals(dto.getRemove().getFirstWord(), client.getRemove().getFirstWord());
+ assertEquals(dto.getRemove().getSecondWord(), client.getRemove().getSecondWord());
+ }
+
+ @Test
+ void convertCreateGroupResponse() throws UnexpectedException {
+ compareWithDto(GroupsDtoConverter.convert(createGroupResponseDto), createGroupResponseDto);
+ }
+
+ @Test
+ void convertCreateRequestParameters() throws UnexpectedException {
+ GroupCreateRequestParameters client =
+ GroupCreateRequestParameters.builder()
+ .setName("My new customers")
+ .setMembers(Collections.singletonList("foo"))
+ .setChildGroupIds(
+ Arrays.asList("01FC66621XXXXX119Z8PMV1AHY", "01FC66621XXXXX119Z8PMV1A00"))
+ .setAutoUpdate(
+ GroupAutoUpdate.builder()
+ .setTo("15551231234")
+ .setAdd(
+ GroupAutoUpdateKeyword.builder().setFirstWord("Add 1st keyword").build())
+ .setRemove(
+ GroupAutoUpdateKeyword.builder()
+ .setFirstWord("remove 1st keyword")
+ .setSecondWord("remove 2nd keyword")
+ .build())
+ .build())
+ .build();
+
+ Assertions.assertThat(createGroupRequestParametersDto)
+ .usingRecursiveComparison()
+ .isEqualTo(GroupsDtoConverter.convert(client));
+ }
+
+ @Test
+ void convertUpdateRequestParameters() throws UnexpectedException {
+ GroupUpdateRequestParameters client =
+ GroupUpdateRequestParameters.builder()
+ .setName("My new customers")
+ .setAdd(Collections.singletonList("foo"))
+ .setRemove(Arrays.asList("01FC66621XXXXX119Z8PMV1AHY", "01FC66621XXXXX119Z8PMV1A00"))
+ .setAddFromGroup("add from group string")
+ .setRemoveFromGroup("remove from group string")
+ .setAutoUpdate(
+ GroupAutoUpdate.builder()
+ .setTo("15551231234")
+ .setAdd(
+ GroupAutoUpdateKeyword.builder().setFirstWord("Add 1st keyword").build())
+ .setRemove(
+ GroupAutoUpdateKeyword.builder()
+ .setFirstWord("remove 1st keyword")
+ .setSecondWord("remove 2nd keyword")
+ .build())
+ .build())
+ .build();
+
+ Assertions.assertThat(groupUpdateRequestParametersDto)
+ .usingRecursiveComparison()
+ .isEqualTo(GroupsDtoConverter.convert(client));
+ }
+
+ @Test
+ void convertReplaceRequestParameters() throws UnexpectedException {
+ GroupReplaceRequestParameters client =
+ GroupReplaceRequestParameters.builder()
+ .setName("My new customers")
+ .setMembers(Collections.singletonList("foo"))
+ .build();
+
+ Assertions.assertThat(groupReplaceRequestParametersDto)
+ .usingRecursiveComparison()
+ .isEqualTo(GroupsDtoConverter.convert(client));
+ }
+}
diff --git a/core/src/main/com/sinch/sdk/core/utils/DateUtil.java b/core/src/main/com/sinch/sdk/core/utils/DateUtil.java
new file mode 100644
index 000000000..8d6c2a237
--- /dev/null
+++ b/core/src/main/com/sinch/sdk/core/utils/DateUtil.java
@@ -0,0 +1,19 @@
+package com.sinch.sdk.core.utils;
+
+import java.time.Instant;
+import java.time.OffsetDateTime;
+
+/** Utility class for Date */
+public class DateUtil {
+
+ /**
+ * Convert an OffsetDateTime to Instant with null value protection
+ *
+ * @param value Value to be converted
+ * @return Converted value to Instant or null if source value was null
+ * @since 1.0
+ */
+ public static Instant toInstant(OffsetDateTime value) {
+ return (null == value ? null : value.toInstant());
+ }
+}
diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/GroupResponseDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/GroupResponseDtoTest.java
new file mode 100644
index 000000000..a5dcb61d8
--- /dev/null
+++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/GroupResponseDtoTest.java
@@ -0,0 +1,44 @@
+package com.sinch.sdk.domains.sms.models.dto.v1;
+
+import com.adelean.inject.resources.junit.jupiter.GivenJsonResource;
+import com.adelean.inject.resources.junit.jupiter.TestWithResources;
+import com.sinch.sdk.BaseTest;
+import java.time.OffsetDateTime;
+import java.util.Arrays;
+import java.util.HashSet;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+@TestWithResources
+class GroupResponseDtoTest extends BaseTest {
+
+ @GivenJsonResource("/domains/sms/v1/GroupResponseDto.json")
+ CreateGroupResponseDto createGroupResponseDto;
+
+ Integer size = 2;
+ OffsetDateTime createdAt = OffsetDateTime.parse("2019-08-24T14:15:22Z");
+ OffsetDateTime modifiedAt = OffsetDateTime.parse("2019-08-24T14:15:44Z");
+ CreateGroupResponseDto groupResponse =
+ new CreateGroupResponseDto(size, createdAt, modifiedAt)
+ .id("01FC66621XXXXX119Z8PMV1QPU")
+ .name("My new customers")
+ .childGroups(
+ new HashSet<>(
+ Arrays.asList("01FC66621XXXXX119Z8PMV1AHY", "01FC66621XXXXX119Z8PMV1A00")))
+ .autoUpdate(
+ new GroupAutoUpdateDto()
+ .to("15551231234")
+ .add(new AddKeywordDto().firstWord("Add 1st keyword"))
+ .remove(
+ new RemoveKeywordDto()
+ .firstWord("remove 1st keyword")
+ .secondWord("remove 2nd keyword")));
+
+ @Test
+ void deserializeGroup() {
+
+ Assertions.assertThat(createGroupResponseDto)
+ .usingRecursiveComparison()
+ .isEqualTo(groupResponse);
+ }
+}
diff --git a/sample-app/README.md b/sample-app/README.md
index c951659d7..c4d5bb0eb 100644
--- a/sample-app/README.md
+++ b/sample-app/README.md
@@ -49,31 +49,38 @@ See https://developers.sinch.com for details about these parameters
## Available samples classes
-| API | Service | Sample | Class | Notes |
-|---------|----------------|------------------------|---------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------|
-| Numbers | Available | - Get | [com.sinch.sample.numbers.available.Get](src/main/java/com/sinch/sample/numbers/available/Get.java) | Require `PHONE_NUMBER` parameter |
-| | | - ListAll | [com.sinch.sample.numbers.available.ListAll](src/main/java/com/sinch/sample/numbers/available/ListAll.java) | |
-| | | - Rent | [com.sinch.sample.numbers.available.Rent](src/main/java/com/sinch/sample/numbers/available/Rent.java) | Require `PHONE_NUMBER` parameter |
-| | | - RentAny | [com.sinch.sample.numbers.available.RentAny](src/main/java/com/sinch/sample/numbers/available/RentAny.java) | |
-| | Active | - Get | [com.sinch.sample.numbers.active.Get](src/main/java/com/sinch/sample/numbers/active/Get.java) | Require `PHONE_NUMBER` parameter |
-| | | - List | [com.sinch.sample.numbers.active.List](src/main/java/com/sinch/sample/numbers/active/List.java) | |
-| | | - Release | [com.sinch.sample.numbers.active.Release](src/main/java/com/sinch/sample/numbers/active/Release.java) | Require `PHONE_NUMBER` parameter |
-| | | - Update | [com.sinch.sample.numbers.active.Update](src/main/java/com/sinch/sample/numbers/active/Update.java) | Require `PHONE_NUMBER` parameter |
-| | Callback | - Get | [com.sinch.sample.numbers.callback.Get](src/main/java/com/sinch/sample/numbers/callback/Get.java) | |
-| | | - Update | [com.sinch.sample.numbers.callback.Update](src/main/java/com/sinch/sample/numbers/callback/Get.java) | |
-| | Regions | - ListAll | [com.sinch.sample.numbers.regions.ListAll](src/main/java/com/sinch/sample/numbers/regions/ListAll.java) | |
-| SMS | Batches | - Get | [com.sinch.sample.sms.batches.Get](src/main/java/com/sinch/sample/sms/batches/Get.java) | Require `BATCH_ID` parameter |
-| | | - List | [com.sinch.sample.sms.batches.List](src/main/java/com/sinch/sample/sms/batches/List.java) | |
-| | | - Send | [com.sinch.sample.sms.batches.Send](src/main/java/com/sinch/sample/sms/batches/Send.java) | |
-| | | - Replace | [com.sinch.sample.sms.batches.Replace](src/main/java/com/sinch/sample/sms/batches/Replace.java) | Require `BATCH_ID` parameter |
-| | | - Update | [com.sinch.sample.sms.batches.Update](src/main/java/com/sinch/sample/sms/batches/Update.java) | Require `BATCH_ID` parameter |
-| | | - DryRun | [com.sinch.sample.sms.batches.DryRun](src/main/java/com/sinch/sample/sms/batches/dryRun.java) | |
-| | | - Cancel | [com.sinch.sample.sms.batches.Cancel](src/main/java/com/sinch/sample/sms/batches/Cancel.java) | Require `BATCH_ID` parameter |
+| API | Service | Sample | Class | Notes |
+|---------|----------------|-----------------------|---------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------|
+| Numbers | Available | - Get | [com.sinch.sample.numbers.available.Get](src/main/java/com/sinch/sample/numbers/available/Get.java) | Require `PHONE_NUMBER` parameter |
+| | | - ListAll | [com.sinch.sample.numbers.available.ListAll](src/main/java/com/sinch/sample/numbers/available/ListAll.java) | |
+| | | - Rent | [com.sinch.sample.numbers.available.Rent](src/main/java/com/sinch/sample/numbers/available/Rent.java) | Require `PHONE_NUMBER` parameter |
+| | | - RentAny | [com.sinch.sample.numbers.available.RentAny](src/main/java/com/sinch/sample/numbers/available/RentAny.java) | |
+| | Active | - Get | [com.sinch.sample.numbers.active.Get](src/main/java/com/sinch/sample/numbers/active/Get.java) | Require `PHONE_NUMBER` parameter |
+| | | - List | [com.sinch.sample.numbers.active.List](src/main/java/com/sinch/sample/numbers/active/List.java) | |
+| | | - Release | [com.sinch.sample.numbers.active.Release](src/main/java/com/sinch/sample/numbers/active/Release.java) | Require `PHONE_NUMBER` parameter |
+| | | - Update | [com.sinch.sample.numbers.active.Update](src/main/java/com/sinch/sample/numbers/active/Update.java) | Require `PHONE_NUMBER` parameter |
+| | Callback | - Get | [com.sinch.sample.numbers.callback.Get](src/main/java/com/sinch/sample/numbers/callback/Get.java) | |
+| | | - Update | [com.sinch.sample.numbers.callback.Update](src/main/java/com/sinch/sample/numbers/callback/Get.java) | |
+| | Regions | - ListAll | [com.sinch.sample.numbers.regions.ListAll](src/main/java/com/sinch/sample/numbers/regions/ListAll.java) | |
+| SMS | Batches | - Get | [com.sinch.sample.sms.batches.Get](src/main/java/com/sinch/sample/sms/batches/Get.java) | Require `BATCH_ID` parameter |
+| | | - List | [com.sinch.sample.sms.batches.List](src/main/java/com/sinch/sample/sms/batches/List.java) | |
+| | | - Send | [com.sinch.sample.sms.batches.Send](src/main/java/com/sinch/sample/sms/batches/Send.java) | |
+| | | - Replace | [com.sinch.sample.sms.batches.Replace](src/main/java/com/sinch/sample/sms/batches/Replace.java) | Require `BATCH_ID` parameter |
+| | | - Update | [com.sinch.sample.sms.batches.Update](src/main/java/com/sinch/sample/sms/batches/Update.java) | Require `BATCH_ID` parameter |
+| | | - DryRun | [com.sinch.sample.sms.batches.DryRun](src/main/java/com/sinch/sample/sms/batches/dryRun.java) | |
+| | | - Cancel | [com.sinch.sample.sms.batches.Cancel](src/main/java/com/sinch/sample/sms/batches/Cancel.java) | Require `BATCH_ID` parameter |
| | | - SendDeliveryFeedback | [com.sinch.sample.sms.batches.SendDeliveryFeedback](src/main/java/com/sinch/sample/sms/batches/SendDeliveryFeedback.java) | Require `BATCH_ID` parameter |
-| | DeliveryReport | - Get | [com.sinch.sample.sms.deliveryReports.Get](src/main/java/com/sinch/sample/sms/deliveryReports/Get.java) | Require `BATCH_ID` parameter |
-| | | - GetForNumber | [com.sinch.sample.sms.deliveryReports.GetForNumber](src/main/java/com/sinch/sample/sms/deliveryReports/GetForNumber.java) | Require `BATCH_ID` and `PHONE_NUMBER` parameters |
-| | | - List | [com.sinch.sample.sms.deliveryReports.List](src/main/java/com/sinch/sample/sms/deliveryReports/List.java) | |
-| | Inbounds | - Get | [com.sinch.sample.sms.inbounds.Get](src/main/java/com/sinch/sample/sms/inbounds/Get.java) | |
-| | | - List | [com.sinch.sample.sms.inbounds.List](src/main/java/com/sinch/sample/sms/inbounds/List.java) | |
-| | WebHooks | - DeliveryReport | [com.sinch.sample.sms.webhooks.DeliveryReport](src/main/java/com/sinch/sample/sms/webhooks/DeliveryReport.java) | |
-| | | - IncomingSMSReport | [com.sinch.sample.sms.webhooks.IncomingSMS](src/main/java/com/sinch/sample/sms/webhooks/IncomingSMS.java) | |
+| | DeliveryReport | - Get | [com.sinch.sample.sms.deliveryReports.Get](src/main/java/com/sinch/sample/sms/deliveryReports/Get.java) | Require `BATCH_ID` parameter |
+| | | - GetForNumber | [com.sinch.sample.sms.deliveryReports.GetForNumber](src/main/java/com/sinch/sample/sms/deliveryReports/GetForNumber.java) | Require `BATCH_ID` and `PHONE_NUMBER` parameters |
+| | | - List | [com.sinch.sample.sms.deliveryReports.List](src/main/java/com/sinch/sample/sms/deliveryReports/List.java) | |
+| | Groups | - Create | [com.sinch.sample.sms.groups.Create](src/main/java/com/sinch/sample/sms/groups/Create.java) | |
+| | | - Get | [com.sinch.sample.sms.groups.Get](src/main/java/com/sinch/sample/sms/groups/Get.java) | |
+| | | - Delete | [com.sinch.sample.sms.groups.Delete](src/main/java/com/sinch/sample/sms/groups/Delete.java) | |
+| | | - List | [com.sinch.sample.sms.groups.List](src/main/java/com/sinch/sample/sms/groups/List.java) | |
+| | | - ListMembers | [com.sinch.sample.sms.groups.ListMembers](src/main/java/com/sinch/sample/sms/groups/ListMembers.java) | |
+| | | - Replace | [com.sinch.sample.sms.groups.Replace](src/main/java/com/sinch/sample/sms/groups/Replace.java) | |
+| | | - Update | [com.sinch.sample.sms.groups.Update](src/main/java/com/sinch/sample/sms/groups/Update.java) | |
+| | Inbounds | - Get | [com.sinch.sample.sms.inbounds.Get](src/main/java/com/sinch/sample/sms/inbounds/Get.java) | |
+| | | - List | [com.sinch.sample.sms.inbounds.List](src/main/java/com/sinch/sample/sms/inbounds/List.java) | |
+| | WebHooks | - DeliveryReport | [com.sinch.sample.sms.webhooks.DeliveryReport](src/main/java/com/sinch/sample/sms/webhooks/DeliveryReport.java) | |
+| | | - IncomingSMSReport | [com.sinch.sample.sms.webhooks.IncomingSMS](src/main/java/com/sinch/sample/sms/webhooks/IncomingSMS.java) | |
diff --git a/sample-app/src/main/java/com/sinch/sample/sms/groups/Create.java b/sample-app/src/main/java/com/sinch/sample/sms/groups/Create.java
new file mode 100644
index 000000000..16e252c0d
--- /dev/null
+++ b/sample-app/src/main/java/com/sinch/sample/sms/groups/Create.java
@@ -0,0 +1,30 @@
+package com.sinch.sample.sms.groups;
+
+import com.sinch.sample.BaseApplication;
+import com.sinch.sdk.domains.sms.models.Group;
+import java.io.IOException;
+import java.util.logging.Logger;
+
+public class Create extends BaseApplication {
+ private static final Logger LOGGER = Logger.getLogger(Create.class.getName());
+
+ public Create() throws IOException {}
+
+ public static void main(String[] args) {
+ try {
+ new Create().run();
+ } catch (Exception e) {
+ LOGGER.severe(e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ public void run() {
+
+ LOGGER.info("Creating group");
+
+ Group response = client.sms().groups().create();
+
+ LOGGER.info("Response: " + response);
+ }
+}
diff --git a/sample-app/src/main/java/com/sinch/sample/sms/groups/Delete.java b/sample-app/src/main/java/com/sinch/sample/sms/groups/Delete.java
new file mode 100644
index 000000000..e611f89d0
--- /dev/null
+++ b/sample-app/src/main/java/com/sinch/sample/sms/groups/Delete.java
@@ -0,0 +1,32 @@
+package com.sinch.sample.sms.groups;
+
+import com.sinch.sample.BaseApplication;
+import java.io.IOException;
+import java.util.logging.Logger;
+
+public class Delete extends BaseApplication {
+
+ private static final Logger LOGGER = Logger.getLogger(Delete.class.getName());
+
+ public Delete() throws IOException {}
+
+ public static void main(String[] args) {
+ try {
+ new Delete().run();
+ } catch (Exception e) {
+ LOGGER.severe(e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ public void run() {
+
+ String groupId = "01HF70ZG5VDZA9EP56HCHVB1R0";
+
+ LOGGER.info("Deleting group: " + groupId);
+
+ client.sms().groups().delete(groupId);
+
+ LOGGER.info("Done");
+ }
+}
diff --git a/sample-app/src/main/java/com/sinch/sample/sms/groups/Get.java b/sample-app/src/main/java/com/sinch/sample/sms/groups/Get.java
new file mode 100644
index 000000000..7379cd086
--- /dev/null
+++ b/sample-app/src/main/java/com/sinch/sample/sms/groups/Get.java
@@ -0,0 +1,31 @@
+package com.sinch.sample.sms.groups;
+
+import com.sinch.sample.BaseApplication;
+import com.sinch.sdk.domains.sms.models.Group;
+import java.io.IOException;
+import java.util.logging.Logger;
+
+public class Get extends BaseApplication {
+ private static final Logger LOGGER = Logger.getLogger(Get.class.getName());
+
+ public Get() throws IOException {}
+
+ public static void main(String[] args) {
+ try {
+ new Get().run();
+ } catch (Exception e) {
+ LOGGER.severe(e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ public void run() {
+
+ String groupId = "01HF714PHPH9SQ2BNWSCY2068R";
+ LOGGER.info("Get for: " + groupId);
+
+ Group response = client.sms().groups().get(groupId);
+
+ LOGGER.info("Response: " + response);
+ }
+}
diff --git a/sample-app/src/main/java/com/sinch/sample/sms/groups/List.java b/sample-app/src/main/java/com/sinch/sample/sms/groups/List.java
new file mode 100644
index 000000000..b6cf8a261
--- /dev/null
+++ b/sample-app/src/main/java/com/sinch/sample/sms/groups/List.java
@@ -0,0 +1,31 @@
+package com.sinch.sample.sms.groups;
+
+import com.sinch.sample.BaseApplication;
+import com.sinch.sdk.domains.sms.models.responses.GroupsListResponse;
+import java.io.IOException;
+import java.util.logging.Logger;
+
+public class List extends BaseApplication {
+
+ private static final Logger LOGGER = Logger.getLogger(List.class.getName());
+
+ public List() throws IOException {}
+
+ public static void main(String[] args) {
+ try {
+ new List().run();
+ } catch (Exception e) {
+ LOGGER.severe(e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ public void run() {
+
+ LOGGER.info("List groups");
+
+ GroupsListResponse response = client.sms().groups().list();
+
+ response.autoPageIter().forEachRemaining(f -> LOGGER.info(f.toString()));
+ }
+}
diff --git a/sample-app/src/main/java/com/sinch/sample/sms/groups/ListMembers.java b/sample-app/src/main/java/com/sinch/sample/sms/groups/ListMembers.java
new file mode 100644
index 000000000..33b00f2cd
--- /dev/null
+++ b/sample-app/src/main/java/com/sinch/sample/sms/groups/ListMembers.java
@@ -0,0 +1,33 @@
+package com.sinch.sample.sms.groups;
+
+import com.sinch.sample.BaseApplication;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.logging.Logger;
+
+public class ListMembers extends BaseApplication {
+
+ private static final Logger LOGGER = Logger.getLogger(ListMembers.class.getName());
+
+ public ListMembers() throws IOException {}
+
+ public static void main(String[] args) {
+ try {
+ new ListMembers().run();
+ } catch (Exception e) {
+ LOGGER.severe(e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ public void run() {
+
+ String groupId = "01HF714PHPH9SQ2BNWSCY2068R";
+
+ LOGGER.info("List members for groupId: " + groupId);
+
+ Collection response = client.sms().groups().listMembers(groupId);
+
+ response.iterator().forEachRemaining(LOGGER::info);
+ }
+}
diff --git a/sample-app/src/main/java/com/sinch/sample/sms/groups/Replace.java b/sample-app/src/main/java/com/sinch/sample/sms/groups/Replace.java
new file mode 100644
index 000000000..dcdc05ff2
--- /dev/null
+++ b/sample-app/src/main/java/com/sinch/sample/sms/groups/Replace.java
@@ -0,0 +1,40 @@
+package com.sinch.sample.sms.groups;
+
+import com.sinch.sample.BaseApplication;
+import com.sinch.sdk.domains.sms.models.Group;
+import com.sinch.sdk.domains.sms.models.requests.GroupReplaceRequestParameters;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.logging.Logger;
+
+public class Replace extends BaseApplication {
+
+ private static final Logger LOGGER = Logger.getLogger(Replace.class.getName());
+
+ public Replace() throws IOException {}
+
+ public static void main(String[] args) {
+ try {
+ new Replace().run();
+ } catch (Exception e) {
+ LOGGER.severe(e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ public void run() {
+
+ String groupId = "01HF70ZG5VDZA9EP56HCHVB1R0";
+ GroupReplaceRequestParameters parameters =
+ GroupReplaceRequestParameters.builder()
+ .setName("foo")
+ .setMembers(Arrays.asList("+3312345678", "+3312345678"))
+ .build();
+
+ LOGGER.info("Replace group: " + groupId + " with: " + parameters);
+
+ Group response = client.sms().groups().replace(groupId, parameters);
+
+ LOGGER.info("Response :" + response);
+ }
+}
diff --git a/sample-app/src/main/java/com/sinch/sample/sms/groups/Update.java b/sample-app/src/main/java/com/sinch/sample/sms/groups/Update.java
new file mode 100644
index 000000000..f1e356d95
--- /dev/null
+++ b/sample-app/src/main/java/com/sinch/sample/sms/groups/Update.java
@@ -0,0 +1,36 @@
+package com.sinch.sample.sms.groups;
+
+import com.sinch.sample.BaseApplication;
+import com.sinch.sdk.domains.sms.models.Group;
+import com.sinch.sdk.domains.sms.models.requests.GroupUpdateRequestParameters;
+import java.io.IOException;
+import java.util.logging.Logger;
+
+public class Update extends BaseApplication {
+
+ private static final Logger LOGGER = Logger.getLogger(Update.class.getName());
+
+ public Update() throws IOException {}
+
+ public static void main(String[] args) {
+ try {
+ new Update().run();
+ } catch (Exception e) {
+ LOGGER.severe(e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ public void run() {
+
+ String groupId = "01HF70ZG5VDZA9EP56HCHVB1R0";
+ GroupUpdateRequestParameters parameters =
+ GroupUpdateRequestParameters.builder().setName("new name").build();
+
+ LOGGER.info("Update group: " + groupId + " with: " + parameters);
+
+ Group response = client.sms().groups().update(groupId, parameters);
+
+ LOGGER.info("Response: " + response);
+ }
+}
diff --git a/test-resources/src/test/resources/domains/sms/v1/GroupCreateRequestParametersDto.json b/test-resources/src/test/resources/domains/sms/v1/GroupCreateRequestParametersDto.json
new file mode 100644
index 000000000..f94104b2e
--- /dev/null
+++ b/test-resources/src/test/resources/domains/sms/v1/GroupCreateRequestParametersDto.json
@@ -0,0 +1,18 @@
+{
+ "name": "My new customers",
+ "members": ["foo"],
+ "child_groups": [
+ "01FC66621XXXXX119Z8PMV1AHY",
+ "01FC66621XXXXX119Z8PMV1A00"
+ ],
+ "auto_update": {
+ "to": 15551231234,
+ "add": {
+ "first_word": "Add 1st keyword"
+ },
+ "remove":{
+ "first_word": "remove 1st keyword",
+ "second_word": "remove 2nd keyword"
+ }
+ }
+}
diff --git a/test-resources/src/test/resources/domains/sms/v1/GroupReplaceRequestParametersDto.json b/test-resources/src/test/resources/domains/sms/v1/GroupReplaceRequestParametersDto.json
new file mode 100644
index 000000000..0b2c63226
--- /dev/null
+++ b/test-resources/src/test/resources/domains/sms/v1/GroupReplaceRequestParametersDto.json
@@ -0,0 +1,4 @@
+{
+ "name": "My new customers",
+ "members": ["foo"]
+}
diff --git a/test-resources/src/test/resources/domains/sms/v1/GroupResponseDto.json b/test-resources/src/test/resources/domains/sms/v1/GroupResponseDto.json
new file mode 100644
index 000000000..ffa0a0ea1
--- /dev/null
+++ b/test-resources/src/test/resources/domains/sms/v1/GroupResponseDto.json
@@ -0,0 +1,21 @@
+{
+ "id": "01FC66621XXXXX119Z8PMV1QPU",
+ "name": "My new customers",
+ "size": 2,
+ "created_at": "2019-08-24T14:15:22Z",
+ "modified_at": "2019-08-24T14:15:44Z",
+ "child_groups": [
+ "01FC66621XXXXX119Z8PMV1AHY",
+ "01FC66621XXXXX119Z8PMV1A00"
+ ],
+ "auto_update": {
+ "to": 15551231234,
+ "add": {
+ "first_word": "Add 1st keyword"
+ },
+ "remove":{
+ "first_word": "remove 1st keyword",
+ "second_word": "remove 2nd keyword"
+ }
+ }
+}
diff --git a/test-resources/src/test/resources/domains/sms/v1/GroupUpdateRequestParametersDto.json b/test-resources/src/test/resources/domains/sms/v1/GroupUpdateRequestParametersDto.json
new file mode 100644
index 000000000..de0b878be
--- /dev/null
+++ b/test-resources/src/test/resources/domains/sms/v1/GroupUpdateRequestParametersDto.json
@@ -0,0 +1,22 @@
+{
+ "name": "My new customers",
+ "add": [
+ "foo"
+ ],
+ "remove": [
+ "01FC66621XXXXX119Z8PMV1AHY",
+ "01FC66621XXXXX119Z8PMV1A00"
+ ],
+ "add_from_group": "add from group string",
+ "remove_from_group": "remove from group string",
+ "auto_update": {
+ "to": 15551231234,
+ "add": {
+ "first_word": "Add 1st keyword"
+ },
+ "remove": {
+ "first_word": "remove 1st keyword",
+ "second_word": "remove 2nd keyword"
+ }
+ }
+}
diff --git a/test-resources/src/test/resources/domains/sms/v1/GroupsListResponseDtoPage0.json b/test-resources/src/test/resources/domains/sms/v1/GroupsListResponseDtoPage0.json
new file mode 100644
index 000000000..a3944d6e5
--- /dev/null
+++ b/test-resources/src/test/resources/domains/sms/v1/GroupsListResponseDtoPage0.json
@@ -0,0 +1,31 @@
+{
+ "count": 3,
+ "page": 0,
+ "page_size": 2,
+ "groups": [
+ {
+ "id": "01FC66621XXXXX119Z8PMV1QPU",
+ "name": "My new customers",
+ "size": 2,
+ "created_at": "2019-08-24T14:15:22Z",
+ "modified_at": "2019-08-24T14:15:44Z",
+ "child_groups": [
+ "01FC66621XXXXX119Z8PMV1AHY",
+ "01FC66621XXXXX119Z8PMV1A00"
+ ],
+ "auto_update": {
+ "to": 15551231234,
+ "add": {
+ "first_word": "Add 1st keyword"
+ },
+ "remove": {
+ "first_word": "remove 1st keyword",
+ "second_word": "remove 2nd keyword"
+ }
+ }
+ },
+ {
+ "id": "foo id"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/test-resources/src/test/resources/domains/sms/v1/GroupsListResponseDtoPage1.json b/test-resources/src/test/resources/domains/sms/v1/GroupsListResponseDtoPage1.json
new file mode 100644
index 000000000..752475637
--- /dev/null
+++ b/test-resources/src/test/resources/domains/sms/v1/GroupsListResponseDtoPage1.json
@@ -0,0 +1,28 @@
+{
+ "count": 3,
+ "page": 1,
+ "page_size": 2,
+ "groups": [
+ {
+ "id": "01FC66621XXXXX119Z8PMV1QPU",
+ "name": "My new customers",
+ "size": 2,
+ "created_at": "2019-08-24T14:15:22Z",
+ "modified_at": "2019-08-24T14:15:44Z",
+ "child_groups": [
+ "01FC66621XXXXX119Z8PMV1AHY",
+ "01FC66621XXXXX119Z8PMV1A00"
+ ],
+ "auto_update": {
+ "to": 15551231234,
+ "add": {
+ "first_word": "Add 1st keyword"
+ },
+ "remove": {
+ "first_word": "remove 1st keyword",
+ "second_word": "remove 2nd keyword"
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file