Skip to content

Commit

Permalink
Add outbound SMS settings
Browse files Browse the repository at this point in the history
  • Loading branch information
SMadani committed Jan 2, 2024
1 parent 3856aaa commit 10765fd
Show file tree
Hide file tree
Showing 6 changed files with 235 additions and 10 deletions.
7 changes: 4 additions & 3 deletions src/main/java/com/vonage/client/messages/MessageStatus.java
Original file line number Diff line number Diff line change
Expand Up @@ -326,9 +326,10 @@ public Usage getUsage() {
}

/**
* If {@linkplain #getChannel()} is {@linkplain Channel#SMS}, returns the network code for the destination.
* If {@linkplain #getChannel()} is {@linkplain Channel#SMS} or {@linkplain Channel#MMS},
* returns the network code for the destination.
*
* @return The SMS network code as a string, or {@code null} if not applicable.
* @return The mobile network code as a string, or {@code null} if not applicable.
*
* @since 8.1.0
*/
Expand All @@ -339,7 +340,7 @@ public String getDestinationNetworkCode() {

/**
* {@linkplain #getChannel()} is {@linkplain Channel#SMS}, returns the number of SMS messages concatenated together
* to comprise the submitted message.SMS messages are 160 characters, if a submitted message exceeds that size it
* to comprise the submitted message. SMS messages are 160 characters, if a submitted message exceeds that size it
* is sent as multiple SMS messages. This number indicates how many SMS messages are required.
*
* @return The number of SMS messages used for this message, or {@code null} if not applicable.
Expand Down
42 changes: 42 additions & 0 deletions src/main/java/com/vonage/client/messages/sms/EncodingType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2023 Vonage
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.vonage.client.messages.sms;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;

/**
* Represents the encoding type for an SMS text message.
*
* @since 8.1.0
*/
public enum EncodingType {
TEXT,
UNICODE,
AUTO;

@JsonCreator
public static EncodingType fromString(String value) {
if (value == null || value.trim().isEmpty()) return null;
return EncodingType.valueOf(value.toUpperCase());
}

@JsonValue
@Override
public String toString() {
return name().toLowerCase();
}
}
64 changes: 64 additions & 0 deletions src/main/java/com/vonage/client/messages/sms/OutboundSettings.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright 2023 Vonage
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.vonage.client.messages.sms;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;

/**
* Represents optional settings for the SMS message in {@link SmsTextRequest}.
*
* @since 8.1.0
*/
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public final class OutboundSettings {
final EncodingType encodingType;
final String contentId, entityId;

private OutboundSettings(EncodingType encodingType, String contentId, String entityId) {
this.encodingType = encodingType;
this.contentId = contentId;
this.entityId = entityId;
}

static OutboundSettings construct(EncodingType encodingType, String contentId, String entityId) {
if (encodingType == null && contentId == null && entityId == null) {
return null;
}
if (contentId != null && contentId.trim().isEmpty()) {
throw new IllegalArgumentException("Content ID cannot be blank.");
}
if (entityId != null && entityId.trim().isEmpty()) {
throw new IllegalArgumentException("Entity ID cannot be blank.");
}
return new OutboundSettings(encodingType, contentId, entityId);
}

@JsonProperty("encoding_type")
public EncodingType getEncodingType() {
return encodingType;
}

@JsonProperty("content_id")
public String getContentId() {
return contentId;
}

@JsonProperty("entity_id")
public String getEntityId() {
return entityId;
}
}
58 changes: 57 additions & 1 deletion src/main/java/com/vonage/client/messages/sms/SmsTextRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@
public final class SmsTextRequest extends MessageRequest {
final String text;
final Integer ttl;
final OutboundSettings sms;

SmsTextRequest(Builder builder) {
super(builder, Channel.SMS, MessageType.TEXT);
text = new Text(builder.text, 1000).toString();
if ((ttl = builder.ttl) != null && ttl < 1) {
throw new IllegalArgumentException("TTL must be positive.");
}
sms = OutboundSettings.construct(builder.encodingType, builder.contentId, builder.entityId);
}

@JsonProperty("text")
Expand All @@ -45,13 +47,19 @@ public Integer getTtl() {
return ttl;
}

@JsonProperty("sms")
public OutboundSettings getMessageSettings() {
return sms;
}

public static Builder builder() {
return new Builder();
}

public final static class Builder extends MessageRequest.Builder<SmsTextRequest, Builder> {
String text;
String text, contentId, entityId;
Integer ttl;
EncodingType encodingType;

Builder() {}

Expand All @@ -71,6 +79,7 @@ public Builder text(String text) {
}

/**
* (OPTIONAL)
* The duration in milliseconds the delivery of an SMS will be attempted. By default, Vonage attempts
* delivery for 72 hours, however the maximum effective value depends on the operator and is typically
* 24 to 48 hours. We recommend this value should be kept at its default or at least 30 minutes.
Expand All @@ -85,6 +94,53 @@ public Builder ttl(int ttl) {
return this;
}

/**
* (OPTIONAL)
* The encoding type to use for the message. If set to either {@linkplain EncodingType#TEXT} or
* {@linkplain EncodingType#UNICODE}, the specified type will be used. If set to
* {@linkplain EncodingType#AUTO} (the default), the Messages API will automatically set the type based
* on the content of text; i.e. if unicode characters are detected in text, then the message will be
* encoded as unicode, and otherwise as text.
*
* @param encodingType The message encoding type as an enum.
* @return This builder.
*
* @since 8.1.0
*/
public Builder encodingType(EncodingType encodingType) {
this.encodingType = encodingType;
return this;
}

/**
* (OPTIONAL)
* A string parameter that satisfies regulatory requirements when sending an SMS to specific countries.
*
* @param contentId The content ID as a string.
* @return This builder.
*
* @since 8.1.0
*/
public Builder contentId(String contentId) {
this.contentId = contentId;
return this;
}

/**
* (OPTIONAL)
* A string parameter that satisfies regulatory requirements when sending an SMS to specific countries.
*
* @param entityId The entity ID as a string.
* @return This builder.
*
* @since 8.1.0
*/
public Builder entityId(String entityId) {
this.entityId = entityId;
return this;
}

@Override
public SmsTextRequest build() {
return new SmsTextRequest(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public Builder caption(String caption) {
/**
* (OPTIONAL)
* Specifies the name of the file being sent. If not included, the value for caption will be used as
* the file name. If neither name or caption are included, the file name will be parsed from the url.
* the file name. If neither name nor caption are included, the file name will be parsed from the url.
*
* @param name The file name.
* @return This builder.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,89 @@
import static org.junit.jupiter.api.Assertions.*;

public class SmsTextRequestTest {
final String from = "447900000001", to = "317900000002";
final String
from = "447900000001", to = "317900000002", msg = "Hello, World!",
contentId = "1107457532145798767", entityId = "1101456324675322134";

@Test
public void testSerializeValid() {
String msg = "Hello, World!";
public void testSerializeAllParameters() {
int ttl = 900000;
SmsTextRequest sms = SmsTextRequest.builder().from(from).to(to).text(msg).ttl(ttl).build();
SmsTextRequest sms = SmsTextRequest.builder()
.from(from).to(to).text(msg).ttl(ttl).contentId(contentId)
.encodingType(EncodingType.UNICODE).entityId(entityId).build();

String json = sms.toJson();
assertTrue(json.contains("\"text\":\""+msg+"\""));
assertTrue(json.contains("\"from\":\""+from+"\""));
assertTrue(json.contains("\"to\":\""+to+"\""));
assertTrue(json.contains("\"message_type\":\"text\""));
assertTrue(json.contains("\"channel\":\"sms\""));
assertTrue(json.contains("\"ttl\":"+ttl));
assertTrue(json.contains("\"sms\":{" +
"\"encoding_type\":\"unicode\"," +
"\"content_id\":\""+contentId+"\"," +
"\"entity_id\":\""+entityId+"\"}"
));
assertEquals("SmsTextRequest "+json, sms.toString());
}

@Test
public void testRequiredParametersOnly() {
SmsTextRequest sms = SmsTextRequest.builder().from(from).to(to).text(msg).build();

String json = sms.toJson();
assertTrue(json.contains("\"text\":\""+msg+"\""));
assertTrue(json.contains("\"from\":\""+from+"\""));
assertTrue(json.contains("\"to\":\""+to+"\""));
assertTrue(json.contains("\"message_type\":\"text\""));
assertTrue(json.contains("\"channel\":\"sms\""));
assertEquals("SmsTextRequest "+json, sms.toString());

assertNull(sms.getMessageSettings());
assertNull(sms.getTtl());
}

@Test
public void testEncodingTypeSettingsOnly() {
EncodingType encodingType = EncodingType.AUTO;
SmsTextRequest sms = SmsTextRequest.builder()
.from(from).to(to).text(msg).encodingType(encodingType).build();

String json = sms.toJson();
assertTrue(json.contains("\"text\":\""+msg+"\""));
assertTrue(json.contains("\"from\":\""+from+"\""));
assertTrue(json.contains("\"to\":\""+to+"\""));
assertTrue(json.contains("\"message_type\":\"text\""));
assertTrue(json.contains("\"channel\":\"sms\""));
assertTrue(json.contains("\"sms\":{\"encoding_type\":\""+encodingType+"\"}"));
assertEquals("SmsTextRequest "+json, sms.toString());

assertNull(sms.getTtl());
OutboundSettings settings = sms.getMessageSettings();
assertNotNull(settings);
assertEquals(encodingType, EncodingType.fromString(settings.getEncodingType().toString()));
assertNull(settings.getEntityId());
assertNull(settings.getContentId());
}

@Test
public void testInvalidContentId() {
assertThrows(IllegalArgumentException.class, () ->
OutboundSettings.construct(EncodingType.TEXT, " ", entityId)
);
}

@Test
public void testInvalidEntityId() {
assertThrows(IllegalArgumentException.class, () ->
OutboundSettings.construct(EncodingType.TEXT, contentId, " ")
);
}

@Test
public void testTtlTooShort() {
assertThrows(IllegalArgumentException.class, () ->
SmsTextRequest.builder().from(from).to(to).text("What's up?").ttl(0).build()
SmsTextRequest.builder().from(from).to(to).text(msg).ttl(0).build()
);
}

Expand Down

0 comments on commit 10765fd

Please sign in to comment.