diff --git a/src/main/java/com/resend/Resend.java b/src/main/java/com/resend/Resend.java index 0de7de9..9042b69 100644 --- a/src/main/java/com/resend/Resend.java +++ b/src/main/java/com/resend/Resend.java @@ -5,6 +5,7 @@ import com.resend.services.batch.Batch; import com.resend.services.broadcasts.Broadcasts; import com.resend.services.contacts.Contacts; +import com.resend.services.contactproperties.ContactProperties; import com.resend.services.domains.Domains; import com.resend.services.emails.Emails; import com.resend.services.webhooks.Webhooks; @@ -67,6 +68,15 @@ public Contacts contacts() { return new Contacts(apiKey); } + /** + * Returns a ContactProperties object that can be used to interact with the ContactProperties service. + * + * @return A ContactProperties object. + */ + public ContactProperties contactProperties() { + return new ContactProperties(apiKey); + } + /** * Returns an Audience object that can be used to interact with the Audiences service. * diff --git a/src/main/java/com/resend/services/contactproperties/ContactProperties.java b/src/main/java/com/resend/services/contactproperties/ContactProperties.java new file mode 100644 index 0000000..1a6d43c --- /dev/null +++ b/src/main/java/com/resend/services/contactproperties/ContactProperties.java @@ -0,0 +1,130 @@ +package com.resend.services.contactproperties; + +import com.resend.core.exception.ResendException; +import com.resend.core.net.AbstractHttpResponse; +import com.resend.core.net.HttpMethod; +import com.resend.core.service.BaseService; +import com.resend.services.contactproperties.model.*; +import okhttp3.MediaType; + +/** + * Represents the Resend ContactProperties module. + */ +public class ContactProperties extends BaseService { + + /** + * Constructs an instance of the {@code ContactProperties} class. + * + * @param apiKey The apiKey used for authentication. + */ + public ContactProperties(final String apiKey) { + super(apiKey); + } + + /** + * Creates a ContactProperty. + * + * @param createContactPropertyOptions The ContactProperty details. + * @return The details of the created contact property. + * @throws ResendException If an error occurs during the ContactProperty creation process. + */ + public CreateContactPropertyResponseSuccess create(CreateContactPropertyOptions createContactPropertyOptions) throws ResendException { + String payload = super.resendMapper.writeValue(createContactPropertyOptions); + AbstractHttpResponse response = httpClient.perform("/contact-properties", super.apiKey, HttpMethod.POST, payload, MediaType.get("application/json")); + + if (!response.isSuccessful()) { + throw new ResendException(response.getCode(), response.getBody()); + } + + String responseBody = response.getBody(); + return resendMapper.readValue(responseBody, CreateContactPropertyResponseSuccess.class); + } + + /** + * Retrieves a list of contact properties and returns a ListContactPropertiesResponseSuccess. + * + * @return A ListContactPropertiesResponseSuccess containing the list of contact properties. + * @throws ResendException If an error occurs during the contact properties list retrieval process. + */ + public ListContactPropertiesResponseSuccess list() throws ResendException { + AbstractHttpResponse response = this.httpClient.perform("/contact-properties", super.apiKey, HttpMethod.GET, null, MediaType.get("application/json")); + + if (!response.isSuccessful()) { + throw new ResendException(response.getCode(), response.getBody()); + } + + String responseBody = response.getBody(); + + return resendMapper.readValue(responseBody, ListContactPropertiesResponseSuccess.class); + } + + /** + * Retrieves a contact property by its unique identifier. + * + * @param id The contact property's id. + * @return The retrieved contact property details. + * @throws ResendException If an error occurs while retrieving the contact property. + */ + public ContactProperty get(String id) throws ResendException { + if (id == null || id.isEmpty()) { + throw new IllegalArgumentException("Contact property id must be provided"); + } + + AbstractHttpResponse response = this.httpClient.perform("/contact-properties/" + id, super.apiKey, HttpMethod.GET, null, MediaType.get("application/json")); + + if (!response.isSuccessful()) { + throw new ResendException(response.getCode(), response.getBody()); + } + + String responseBody = response.getBody(); + + return resendMapper.readValue(responseBody, ContactProperty.class); + } + + /** + * Updates a contact property based on the provided contact property ID. + * + * @param updateContactPropertyOptions The object with the contact property id and fallback value to update. + * @return The UpdateContactPropertyResponseSuccess with the details of the updated contact property. + * @throws ResendException If an error occurs during the contact property update process. + */ + public UpdateContactPropertyResponseSuccess update(UpdateContactPropertyOptions updateContactPropertyOptions) throws ResendException { + if (updateContactPropertyOptions.getId() == null || updateContactPropertyOptions.getId().isEmpty()) { + throw new IllegalArgumentException("Contact property id must be provided"); + } + + String payload = super.resendMapper.writeValue(updateContactPropertyOptions); + AbstractHttpResponse response = httpClient.perform("/contact-properties/" + updateContactPropertyOptions.getId(), super.apiKey, HttpMethod.PATCH, payload, MediaType.get("application/json")); + + if (!response.isSuccessful()) { + throw new ResendException(response.getCode(), response.getBody()); + } + + String responseBody = response.getBody(); + + return resendMapper.readValue(responseBody, UpdateContactPropertyResponseSuccess.class); + } + + /** + * Deletes a contact property based on the provided contact property ID. + * + * @param id The identifier of the contact property to delete. + * @return The RemoveContactPropertyResponseSuccess with the details of the removed contact property. + * @throws ResendException If an error occurs during the contact property deletion process. + */ + public RemoveContactPropertyResponseSuccess remove(String id) throws ResendException { + if (id == null || id.isEmpty()) { + throw new IllegalArgumentException("Contact property id must be provided"); + } + + AbstractHttpResponse response = httpClient.perform("/contact-properties/" + id, super.apiKey, HttpMethod.DELETE, "", null); + + if (!response.isSuccessful()) { + throw new ResendException(response.getCode(), response.getBody()); + } + + String responseBody = response.getBody(); + + return resendMapper.readValue(responseBody, RemoveContactPropertyResponseSuccess.class); + } +} diff --git a/src/main/java/com/resend/services/contactproperties/model/BaseContactProperty.java b/src/main/java/com/resend/services/contactproperties/model/BaseContactProperty.java new file mode 100644 index 0000000..62b6bbc --- /dev/null +++ b/src/main/java/com/resend/services/contactproperties/model/BaseContactProperty.java @@ -0,0 +1,50 @@ +package com.resend.services.contactproperties.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Base contact property with common properties + */ +public abstract class BaseContactProperty { + @JsonProperty("id") + private String id; + + @JsonProperty("object") + private String object; + + /** + * Default constructor + */ + public BaseContactProperty() { + } + + /** + * Constructs a base contact property. + * + * @param id The ID of the contact property. + * @param object The object type of the contact property. + */ + public BaseContactProperty(final String id, final String object) { + this.id = id; + this.object = object; + } + + /** + * Gets the ID of the contact property. + * + * @return The ID of the contact property. + */ + public String getId() { + return id; + } + + /** + * Gets the object type of the contact property. + * + * @return The object type of the contact property. + */ + public String getObject() { + return object; + } + +} diff --git a/src/main/java/com/resend/services/contactproperties/model/ContactProperty.java b/src/main/java/com/resend/services/contactproperties/model/ContactProperty.java new file mode 100644 index 0000000..1c36f83 --- /dev/null +++ b/src/main/java/com/resend/services/contactproperties/model/ContactProperty.java @@ -0,0 +1,107 @@ +package com.resend.services.contactproperties.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Represents a contact property item. + */ +public class ContactProperty { + + @JsonProperty("id") + private String id; + + @JsonProperty("key") + private String key; + + @JsonProperty("object") + private String object; + + @JsonProperty("created_at") + private String createdAt; + + @JsonProperty("type") + private String type; + + @JsonProperty("fallback_value") + private Object fallbackValue; + + /** + * Default constructor + */ + public ContactProperty() { + + } + + /** + * Creates an instance of ContactProperty with the specified attributes. + * + * @param id The ID of the contact property. + * @param key The key of the contact property. + * @param object The object type of the contact property. + * @param createdAt The creation timestamp of the contact property. + * @param type The type of the contact property. + * @param fallbackValue The fallback value of the contact property. + */ + public ContactProperty(final String id, final String key, final String object, final String createdAt, final String type, final Object fallbackValue) { + this.id = id; + this.key = key; + this.object = object; + this.createdAt = createdAt; + this.type = type; + this.fallbackValue = fallbackValue; + } + + /** + * Gets the ID of the contact property. + * + * @return The ID of the contact property. + */ + public String getId() { + return id; + } + + /** + * Gets the key of the contact property. + * + * @return The key of the contact property. + */ + public String getKey() { + return key; + } + + /** + * Gets the object type of the contact property. + * + * @return The object type of the contact property. + */ + public String getObject() { + return object; + } + + /** + * Gets the creation timestamp of the contact property. + * + * @return The creation timestamp of the contact property. + */ + public String getCreatedAt() { + return createdAt; + } + + /** + * Gets the type of the contact property. + * + * @return The type of the contact property. + */ + public String getType() { + return type; + } + + /** + * Gets the fallback value of the contact property. + * + * @return The fallback value of the contact property. + */ + public Object getFallbackValue() { + return fallbackValue; + } +} diff --git a/src/main/java/com/resend/services/contactproperties/model/CreateContactPropertyOptions.java b/src/main/java/com/resend/services/contactproperties/model/CreateContactPropertyOptions.java new file mode 100644 index 0000000..5d30c25 --- /dev/null +++ b/src/main/java/com/resend/services/contactproperties/model/CreateContactPropertyOptions.java @@ -0,0 +1,116 @@ +package com.resend.services.contactproperties.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Represents a request to create a contact property. + */ +public class CreateContactPropertyOptions { + + @JsonProperty("key") + private final String key; + + @JsonProperty("type") + private final String type; + + @JsonProperty("fallback_value") + private final Object fallbackValue; + + /** + * Constructs a CreateContactPropertyOptions object using the provided builder. + * + * @param builder The builder to construct the CreateContactPropertyOptions. + */ + public CreateContactPropertyOptions(Builder builder) { + this.key = builder.key; + this.type = builder.type; + this.fallbackValue = builder.fallbackValue; + } + + /** + * Get the key of the contact property. + * + * @return The key of the contact property. + */ + public String getKey() { + return key; + } + + /** + * Get the type of the contact property. + * + * @return The type of the contact property. + */ + public String getType() { + return type; + } + + /** + * Get the fallback value of the contact property. + * + * @return The fallback value of the contact property. + */ + public Object getFallbackValue() { + return fallbackValue; + } + + /** + * Create a new builder instance for constructing CreateContactPropertyOptions objects. + * + * @return A new builder instance. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Builder class for constructing CreateContactPropertyOptions objects. + */ + public static class Builder { + private String key; + private String type; + private Object fallbackValue; + + /** + * Set the key of the contact property. + * + * @param key The key of the contact property. + * @return The builder instance. + */ + public Builder key(String key) { + this.key = key; + return this; + } + + /** + * Set the type of the contact property. + * + * @param type The type of the contact property. + * @return The builder instance. + */ + public Builder type(String type) { + this.type = type; + return this; + } + + /** + * Set the fallback value of the contact property. + * + * @param fallbackValue The fallback value of the contact property. + * @return The builder instance. + */ + public Builder fallbackValue(Object fallbackValue) { + this.fallbackValue = fallbackValue; + return this; + } + + /** + * Build a new CreateContactPropertyOptions object. + * + * @return A new CreateContactPropertyOptions object. + */ + public CreateContactPropertyOptions build() { + return new CreateContactPropertyOptions(this); + } + } +} diff --git a/src/main/java/com/resend/services/contactproperties/model/CreateContactPropertyResponseSuccess.java b/src/main/java/com/resend/services/contactproperties/model/CreateContactPropertyResponseSuccess.java new file mode 100644 index 0000000..c20def1 --- /dev/null +++ b/src/main/java/com/resend/services/contactproperties/model/CreateContactPropertyResponseSuccess.java @@ -0,0 +1,24 @@ +package com.resend.services.contactproperties.model; + +/** + * Represents a successful response for creating a contact property. + */ +public class CreateContactPropertyResponseSuccess extends BaseContactProperty { + + /** + * Default constructor + */ + public CreateContactPropertyResponseSuccess() { + } + + /** + * Constructs a successful response for creating a contact property. + * + * @param id The ID of the contact property. + * @param object The object type of the contact property. + */ + public CreateContactPropertyResponseSuccess(final String id, final String object) { + super(id, object); + } + +} diff --git a/src/main/java/com/resend/services/contactproperties/model/ListContactPropertiesResponseSuccess.java b/src/main/java/com/resend/services/contactproperties/model/ListContactPropertiesResponseSuccess.java new file mode 100644 index 0000000..5d28e56 --- /dev/null +++ b/src/main/java/com/resend/services/contactproperties/model/ListContactPropertiesResponseSuccess.java @@ -0,0 +1,52 @@ +package com.resend.services.contactproperties.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + +/** + * Represents a successful response for listing contact properties. + */ +public class ListContactPropertiesResponseSuccess { + + @JsonProperty("data") + private List data; + + @JsonProperty("object") + private String object; + + /** + * Default constructor + */ + public ListContactPropertiesResponseSuccess() { + } + + /** + * Constructs a successful response for listing contact properties. + * + * @param data The list of contact properties. + * @param object The object type. + */ + public ListContactPropertiesResponseSuccess(final List data, final String object) { + this.data = data; + this.object = object; + } + + /** + * Gets the list of contact properties. + * + * @return The list of contact properties. + */ + public List getData() { + return data; + } + + /** + * Gets the object type. + * + * @return The object type. + */ + public String getObject() { + return object; + } + +} diff --git a/src/main/java/com/resend/services/contactproperties/model/RemoveContactPropertyResponseSuccess.java b/src/main/java/com/resend/services/contactproperties/model/RemoveContactPropertyResponseSuccess.java new file mode 100644 index 0000000..8a036c0 --- /dev/null +++ b/src/main/java/com/resend/services/contactproperties/model/RemoveContactPropertyResponseSuccess.java @@ -0,0 +1,40 @@ +package com.resend.services.contactproperties.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Represents a successful response for removing a contact property. + */ +public class RemoveContactPropertyResponseSuccess extends BaseContactProperty { + + @JsonProperty("deleted") + private boolean deleted; + + /** + * Default constructor + */ + public RemoveContactPropertyResponseSuccess() { + } + + /** + * Constructs a successful response for removing a contact property. + * + * @param id The ID of the contact property. + * @param object The object type of the contact property. + * @param deleted Whether the contact property was deleted. + */ + public RemoveContactPropertyResponseSuccess(final String id, final String object, final boolean deleted) { + super(id, object); + this.deleted = deleted; + } + + /** + * Gets whether the contact property was deleted. + * + * @return Whether the contact property was deleted. + */ + public boolean isDeleted() { + return deleted; + } + +} diff --git a/src/main/java/com/resend/services/contactproperties/model/UpdateContactPropertyOptions.java b/src/main/java/com/resend/services/contactproperties/model/UpdateContactPropertyOptions.java new file mode 100644 index 0000000..04b425f --- /dev/null +++ b/src/main/java/com/resend/services/contactproperties/model/UpdateContactPropertyOptions.java @@ -0,0 +1,91 @@ +package com.resend.services.contactproperties.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Represents a request to update a contact property. + */ +public class UpdateContactPropertyOptions { + + @JsonProperty("id") + private final String id; + + @JsonProperty("fallback_value") + private final Object fallbackValue; + + /** + * Constructs an UpdateContactPropertyOptions object using the provided builder. + * + * @param builder The builder to construct the UpdateContactPropertyOptions. + */ + public UpdateContactPropertyOptions(Builder builder) { + this.id = builder.id; + this.fallbackValue = builder.fallbackValue; + } + + /** + * Get the ID of the contact property. + * + * @return The ID of the contact property. + */ + public String getId() { + return id; + } + + /** + * Get the fallback value of the contact property. + * + * @return The fallback value of the contact property. + */ + public Object getFallbackValue() { + return fallbackValue; + } + + /** + * Create a new builder instance for constructing UpdateContactPropertyOptions objects. + * + * @return A new builder instance. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Builder class for constructing UpdateContactPropertyOptions objects. + */ + public static class Builder { + private String id; + private Object fallbackValue; + + /** + * Set the ID of the contact property. + * + * @param id The ID of the contact property. + * @return The builder instance. + */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** + * Set the fallback value of the contact property. + * + * @param fallbackValue The fallback value of the contact property. + * @return The builder instance. + */ + public Builder fallbackValue(Object fallbackValue) { + this.fallbackValue = fallbackValue; + return this; + } + + /** + * Build a new UpdateContactPropertyOptions object. + * + * @return A new UpdateContactPropertyOptions object. + */ + public UpdateContactPropertyOptions build() { + return new UpdateContactPropertyOptions(this); + } + } +} diff --git a/src/main/java/com/resend/services/contactproperties/model/UpdateContactPropertyResponseSuccess.java b/src/main/java/com/resend/services/contactproperties/model/UpdateContactPropertyResponseSuccess.java new file mode 100644 index 0000000..ca5a596 --- /dev/null +++ b/src/main/java/com/resend/services/contactproperties/model/UpdateContactPropertyResponseSuccess.java @@ -0,0 +1,24 @@ +package com.resend.services.contactproperties.model; + +/** + * Represents a successful response for updating a contact property. + */ +public class UpdateContactPropertyResponseSuccess extends BaseContactProperty { + + /** + * Default constructor + */ + public UpdateContactPropertyResponseSuccess() { + } + + /** + * Constructs a successful response for updating a contact property. + * + * @param id The ID of the contact property. + * @param object The object type of the contact property. + */ + public UpdateContactPropertyResponseSuccess(final String id, final String object) { + super(id, object); + } + +} diff --git a/src/test/java/com/resend/services/contactproperties/ContactPropertiesTest.java b/src/test/java/com/resend/services/contactproperties/ContactPropertiesTest.java new file mode 100644 index 0000000..aa4183a --- /dev/null +++ b/src/test/java/com/resend/services/contactproperties/ContactPropertiesTest.java @@ -0,0 +1,96 @@ +package com.resend.services.contactproperties; + +import com.resend.core.exception.ResendException; +import com.resend.services.contactproperties.model.*; +import com.resend.services.util.ContactPropertiesUtil; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.*; + +public class ContactPropertiesTest { + + @Mock + private ContactProperties contactProperties; + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + contactProperties = mock(ContactProperties.class); + } + + @Test + public void testCreateContactProperty_Success() throws ResendException { + CreateContactPropertyResponseSuccess expected = ContactPropertiesUtil.createContactPropertyResponseSuccess(); + CreateContactPropertyOptions param = ContactPropertiesUtil.createContactPropertyRequest(); + + when(contactProperties.create(param)) + .thenReturn(expected); + + CreateContactPropertyResponseSuccess created = contactProperties.create(param); + + assertEquals(created, expected); + verify(contactProperties, times(1)).create(param); + } + + @Test + public void testListContactProperties_Success() throws ResendException { + ListContactPropertiesResponseSuccess expectedResponse = ContactPropertiesUtil.createContactPropertiesListResponse(); + + when(contactProperties.list()) + .thenReturn(expectedResponse); + + ListContactPropertiesResponseSuccess res = contactProperties.list(); + + assertNotNull(res); + assertEquals(expectedResponse.getData().size(), res.getData().size()); + assertEquals(expectedResponse.getObject(), res.getObject()); + } + + @Test + public void testGetContactProperty_Success() throws ResendException { + String id = "123"; + ContactProperty expected = ContactPropertiesUtil.getContactProperty(); + + when(contactProperties.get(id)).thenReturn(expected); + + ContactProperty res = contactProperties.get(id); + + assertNotNull(res); + assertEquals(expected, res); + verify(contactProperties, times(1)).get(id); + } + + @Test + public void testUpdateContactProperty_Success() throws ResendException { + UpdateContactPropertyOptions params = ContactPropertiesUtil.createUpdateOptions(); + UpdateContactPropertyResponseSuccess expectedResponse = ContactPropertiesUtil.updateContactPropertyResponseSuccess(); + + when(contactProperties.update(params)) + .thenReturn(expectedResponse); + + UpdateContactPropertyResponseSuccess res = contactProperties.update(params); + + assertNotNull(res); + assertEquals(expectedResponse.getId(), res.getId()); + assertEquals(expectedResponse.getObject(), res.getObject()); + } + + @Test + public void testRemoveContactProperty_Success() throws ResendException { + String id = "123"; + RemoveContactPropertyResponseSuccess removed = ContactPropertiesUtil.removeContactPropertyResponseSuccess(); + + when(contactProperties.remove(id)) + .thenReturn(removed); + + RemoveContactPropertyResponseSuccess res = contactProperties.remove(id); + + assertEquals(removed, res); + verify(contactProperties, times(1)).remove(id); + } +} diff --git a/src/test/java/com/resend/services/util/ContactPropertiesUtil.java b/src/test/java/com/resend/services/util/ContactPropertiesUtil.java new file mode 100644 index 0000000..36082a6 --- /dev/null +++ b/src/test/java/com/resend/services/util/ContactPropertiesUtil.java @@ -0,0 +1,61 @@ +package com.resend.services.util; + +import com.resend.services.contactproperties.model.*; + +import java.util.ArrayList; +import java.util.List; + +public class ContactPropertiesUtil { + + public static CreateContactPropertyOptions createContactPropertyRequest() { + return CreateContactPropertyOptions.builder() + .key("age") + .type("number") + .fallbackValue(25) + .build(); + } + + public static CreateContactPropertyResponseSuccess createContactPropertyResponseSuccess() { + return new CreateContactPropertyResponseSuccess("123", "contact_property"); + } + + public static UpdateContactPropertyOptions createUpdateOptions() { + return UpdateContactPropertyOptions.builder() + .id("123") + .fallbackValue(30) + .build(); + } + + public static UpdateContactPropertyResponseSuccess updateContactPropertyResponseSuccess() { + return new UpdateContactPropertyResponseSuccess("123", "contact_property"); + } + + public static RemoveContactPropertyResponseSuccess removeContactPropertyResponseSuccess() { + return new RemoveContactPropertyResponseSuccess("123", "contact_property", true); + } + + public static ContactProperty getContactProperty() { + return new ContactProperty( + "123", + "age", + "contact_property", + "2023-04-08T00:11:13.110779+00:00", + "number", + 25 + ); + } + + public static ListContactPropertiesResponseSuccess createContactPropertiesListResponse() { + List properties = new ArrayList<>(); + + ContactProperty p1 = new ContactProperty("1", "age", "contact_property", "2023-04-08T00:11:13.110779+00:00", "number", 25); + ContactProperty p2 = new ContactProperty("2", "city", "contact_property", "2023-04-08T00:11:13.110779+00:00", "string", "New York"); + ContactProperty p3 = new ContactProperty("3", "subscribed", "contact_property", "2023-04-08T00:11:13.110779+00:00", "boolean", true); + + properties.add(p1); + properties.add(p2); + properties.add(p3); + + return new ListContactPropertiesResponseSuccess(properties, "list"); + } +}