Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions src/main/java/com/twilio/base/ResourceDeleter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.twilio.base;

import com.twilio.Twilio;
import com.twilio.http.TwilioRestClient;

import java.util.concurrent.CompletableFuture;

/**
* Executor for deletes of a resource that return a response object.
*
* @param <T> type of the resource
* @param <R> type of the delete response
*/
public abstract class ResourceDeleter<T extends Resource, R extends Resource> {

Check warning on line 14 in src/main/java/com/twilio/base/ResourceDeleter.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

T is not used in the class.

See more on https://sonarcloud.io/project/issues?id=twilio_twilio-java&issues=AZ0_tCrvip1ffNXdB8Js&open=AZ0_tCrvip1ffNXdB8Js&pullRequest=947

public CompletableFuture<R> deleteAsync() {
return deleteAsync(Twilio.getRestClient());
}

public CompletableFuture<R> deleteAsync(final TwilioRestClient client) {
return CompletableFuture.supplyAsync(() -> delete(client), Twilio.getExecutorService());
}

public R delete() {
return delete(Twilio.getRestClient());
}

public abstract R delete(final TwilioRestClient client);

public TwilioResponse<R> deleteWithResponse() {
return deleteWithResponse(Twilio.getRestClient());
}

public TwilioResponse<R> deleteWithResponse(final TwilioRestClient client) {
throw new UnsupportedOperationException("deleteWithResponse is not supported for this resource.");
}
}
14 changes: 12 additions & 2 deletions src/main/java/com/twilio/base/TokenPaginationPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,18 @@
JsonNode meta = root.get("meta");
String key = meta.get("key").asText();
JsonNode records = root.get(key);
for (final JsonNode record : records) {
results.add(mapper.readValue(record.toString(), recordType));

if ( records == null )
throw new NullPointerException("records not found in response");

if (records != null && records.isArray() && records.size() > 0 && !records.get(0).isObject()) {

Check warning on line 100 in src/main/java/com/twilio/base/TokenPaginationPage.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this expression which always evaluates to "true"

See more on https://sonarcloud.io/project/issues?id=twilio_twilio-java&issues=AZ1s2blgrPR3e44hwX2k&open=AZ1s2blgrPR3e44hwX2k&pullRequest=947
// Records are primitives (e.g., strings/IDs); treat the entire
// response envelope as a single record of type T.
results.add(mapper.readValue(json, recordType));
} else if (records != null) {

Check warning on line 104 in src/main/java/com/twilio/base/TokenPaginationPage.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this expression which always evaluates to "true"

See more on https://sonarcloud.io/project/issues?id=twilio_twilio-java&issues=AZ1s2blgrPR3e44hwX2j&open=AZ1s2blgrPR3e44hwX2j&pullRequest=947
for (final JsonNode record : records) {
results.add(mapper.readValue(record.toString(), recordType));
}
}

return buildPage(meta, results);
Expand Down
42 changes: 42 additions & 0 deletions src/main/java/com/twilio/rest/numbers/v3/HostedNumberOrder.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.io.IOException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import lombok.ToString;

@JsonIgnoreProperties(ignoreUnknown = true)
Expand Down Expand Up @@ -104,6 +105,47 @@
}
}

@JsonIgnoreProperties(ignoreUnknown = true)
static class DeleteHostedNumberOrderResponse extends Resource {

@JsonCreator
private DeleteHostedNumberOrderResponse() {}

public static DeleteHostedNumberOrderResponse fromJson(
final InputStream json,
final ObjectMapper objectMapper
) {
// Convert all checked exceptions to Runtime
try {
return objectMapper.readValue(
json,
DeleteHostedNumberOrderResponse.class
);
} catch (final JsonMappingException | JsonParseException e) {
throw new ApiException(e.getMessage(), e);
} catch (final IOException e) {
throw new ApiConnectionException(e.getMessage(), e);
}
}

@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}

if (o == null || getClass() != o.getClass()) {

Check warning on line 137 in src/main/java/com/twilio/rest/numbers/v3/HostedNumberOrder.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this if-then-else statement by a single return statement.

See more on https://sonarcloud.io/project/issues?id=twilio_twilio-java&issues=AZ0_tCotip1ffNXdB8Jr&open=AZ0_tCotip1ffNXdB8Jr&pullRequest=947
return false;
}
return true;
}

@Override
public int hashCode() {
return Objects.hash();
}
}

@JsonIgnoreProperties(ignoreUnknown = true)
static class ListHostedNumberOrderResponse extends Resource {

Expand Down
10 changes: 10 additions & 0 deletions src/main/java/com/twilio/rest/studio/v2/flow/ExecutionReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
public class ExecutionReader extends Reader<Execution> {

private String pathFlowSid;
private Execution.Status status;
private ZonedDateTime dateCreatedFrom;
private ZonedDateTime dateCreatedTo;
private Long pageSize;
Expand All @@ -45,6 +46,11 @@ public ExecutionReader(final String pathFlowSid) {
this.pathFlowSid = pathFlowSid;
}

public ExecutionReader setStatus(final Execution.Status status) {
this.status = status;
return this;
}

public ExecutionReader setDateCreatedFrom(
final ZonedDateTime dateCreatedFrom
) {
Expand Down Expand Up @@ -206,6 +212,10 @@ public Page<Execution> getPage(
}

private void addQueryParams(final Request request) {
if (status != null) {
Serializer.toString(request, "status", status, ParameterType.QUERY);
}

if (dateCreatedFrom != null) {
Serializer.toString(
request,
Expand Down
182 changes: 182 additions & 0 deletions src/test/java/com/twilio/base/ResourceDeleterTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
package com.twilio.base;

import com.twilio.Twilio;
import com.twilio.http.TwilioRestClient;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.message.BasicHeader;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class ResourceDeleterTest {

@Mock
TwilioRestClient client;

@Mock
Resource mockResource;

@BeforeClass
public static void setUpClass() {
Twilio.init("test-username", "test-password");
}

@AfterClass
public static void tearDownClass() {
Twilio.destroy();
}

@Before
public void init() {
MockitoAnnotations.openMocks(this);
}

/**
* Test implementation of ResourceDeleter that only implements the abstract delete method.
*/
private static class TestResourceDeleter extends ResourceDeleter<Resource, Resource> {
private final Resource resource;

public TestResourceDeleter(Resource resource) {
this.resource = resource;
}

@Override
public Resource delete(TwilioRestClient client) {
return resource;
}
}

/**
* Test implementation that also overrides deleteWithResponse.
*/
private static class TestResourceDeleterWithResponse extends ResourceDeleter<Resource, Resource> {
private final Resource resource;
private final int statusCode;
private final Header[] headers;

public TestResourceDeleterWithResponse(Resource resource, int statusCode, Header[] headers) {
this.resource = resource;
this.statusCode = statusCode;
this.headers = headers;
}

@Override
public Resource delete(TwilioRestClient client) {
return resource;
}

@Override
public TwilioResponse<Resource> deleteWithResponse(TwilioRestClient client) {
return new TwilioResponse<>(resource, statusCode, headers);
}
}

@Test
public void testDeleteWithClient() {
TestResourceDeleter deleter = new TestResourceDeleter(mockResource);
Resource result = deleter.delete(client);
Assert.assertEquals(mockResource, result);
Assert.assertNotNull(result);
}

@Test
public void testDeleteReturnsCorrectResource() {
Resource customResource = mockResource;
TestResourceDeleter deleter = new TestResourceDeleter(customResource);
Resource result = deleter.delete(client);
Assert.assertSame(customResource, result);
}

@Test
public void testDeleteWithDefaultClient() {
TestResourceDeleter deleter = new TestResourceDeleter(mockResource);
Resource result = deleter.delete();
Assert.assertNotNull(result);
Assert.assertEquals(mockResource, result);
}

@Test
public void testDeleteAsyncWithClient() {
try {
TestResourceDeleter deleter = new TestResourceDeleter(mockResource);
CompletableFuture<Resource> future = deleter.deleteAsync(client);

Assert.assertNotNull(future);
Assert.assertTrue(future instanceof CompletableFuture);

Resource result = future.get();
Assert.assertEquals(mockResource, result);
} catch (InterruptedException | ExecutionException e) {
Assert.fail("Async delete operation failed: " + e.getMessage());
}
}

@Test
public void testDeleteAsyncWithDefaultClient() {
try {
TestResourceDeleter deleter = new TestResourceDeleter(mockResource);
CompletableFuture<Resource> future = deleter.deleteAsync();

Assert.assertNotNull(future);
Assert.assertTrue(future instanceof CompletableFuture);

Resource result = future.get();
Assert.assertEquals(mockResource, result);
} catch (InterruptedException | ExecutionException e) {
Assert.fail("Async delete operation with default client failed: " + e.getMessage());
}
}

@Test(expected = UnsupportedOperationException.class)
public void testDeleteWithResponseThrowsWhenNotOverridden() {
TestResourceDeleter deleter = new TestResourceDeleter(mockResource);
deleter.deleteWithResponse(client);
}

@Test(expected = UnsupportedOperationException.class)
public void testDeleteWithResponseDefaultClientThrowsWhenNotOverridden() {
TestResourceDeleter deleter = new TestResourceDeleter(mockResource);
deleter.deleteWithResponse();
}

@Test
public void testDeleteWithResponseReturnsCorrectContent() {
Header[] headers = new Header[]{new BasicHeader("Content-Type", "application/json")};
TestResourceDeleterWithResponse deleter = new TestResourceDeleterWithResponse(mockResource, 200, headers);

TwilioResponse<Resource> response = deleter.deleteWithResponse(client);

Assert.assertNotNull(response);
Assert.assertEquals(mockResource, response.getContent());
Assert.assertEquals(200, response.getStatusCode());
Assert.assertEquals("application/json", response.getHeaders().get("Content-Type"));
}

@Test
public void testDeleteWithResponseDefaultClient() {
Header[] headers = new Header[]{new BasicHeader("X-Request-Id", "abc123")};
TestResourceDeleterWithResponse deleter = new TestResourceDeleterWithResponse(mockResource, 204, headers);

TwilioResponse<Resource> response = deleter.deleteWithResponse();

Assert.assertNotNull(response);
Assert.assertEquals(mockResource, response.getContent());
Assert.assertEquals(204, response.getStatusCode());
Assert.assertEquals("abc123", response.getHeaders().get("X-Request-Id"));
}

@Test
public void testDeleteReturnsNull() {
TestResourceDeleter deleter = new TestResourceDeleter(null);
Resource result = deleter.delete(client);
Assert.assertNull(result);
}
}
Loading