Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SWI-6678 #30

Merged
merged 4 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 9 additions & 0 deletions src/main/java/com/bandwidth/sdk/numbers/NumbersClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.bandwidth.sdk.numbers.models.orders.Order;
import com.bandwidth.sdk.numbers.models.orders.OrderResponse;
import com.bandwidth.sdk.numbers.models.AvailableNumberSearchRequest;
import com.bandwidth.sdk.numbers.models.orders.OrdersResponse;

public interface NumbersClient extends AutoCloseable {

Expand Down Expand Up @@ -34,4 +35,12 @@ public interface NumbersClient extends AutoCloseable {
* @return {@link OrderResponse} with the details of the results of placing the order
*/
OrderResponse getOrderStatus(String orderId);

/**
* Fetch the details of all orders.
*
* @param customerOrderId The customerOrderId of the order to search on
* @return {@link OrdersResponse} with the details of all orders
*/
OrdersResponse getOrdersByCustomerOrderId(String customerOrderId);
}
37 changes: 37 additions & 0 deletions src/main/java/com/bandwidth/sdk/numbers/NumbersClientImpl.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.bandwidth.sdk.numbers;

import com.bandwidth.sdk.numbers.exception.ExceptionUtils;
import com.bandwidth.sdk.numbers.exception.NumbersApiException;
import com.bandwidth.sdk.numbers.helpers.RetryableRequest;
import com.bandwidth.sdk.numbers.helpers.SleepRetryPolicy;
import com.bandwidth.sdk.numbers.models.AvailableNumberSearchRequest;
import com.bandwidth.sdk.numbers.models.SearchResult;
import com.bandwidth.sdk.numbers.models.orders.Order;
import com.bandwidth.sdk.numbers.models.orders.OrderResponse;
import com.bandwidth.sdk.numbers.models.orders.OrdersResponse;
import com.bandwidth.sdk.numbers.serde.NumbersSerde;
import com.google.common.base.Preconditions;
import io.netty.handler.codec.http.HttpHeaderNames;
Expand Down Expand Up @@ -105,6 +107,41 @@ public OrderResponse getOrderStatus(String orderId) {
});
}

/**
* This queries the /orders API with a required parameter of customerOrderId
* If we need to extend this for any reason, we should implement a getOrders method with a builder for the possible query parameters
* The HTTP client will need to be investigated to see how it will support adding multiple query parameters
*
* @param customerOrderId The customerOrderId of the order to search on
* @return The orders response
*/
@Override
public OrdersResponse getOrdersByCustomerOrderId(String customerOrderId){
return getOrdersByCustomerOrderIdAsync(customerOrderId).join();
}

private CompletableFuture<OrdersResponse> getOrdersByCustomerOrderIdAsync(String customerOrderId) throws NumbersApiException {
// arbitrary
String pageSize = "100";

return catchAsyncClientExceptions(() -> {
String url = MessageFormat.format("{0}/accounts/{1}/orders?customerOrderId={2}&page=1&size={3}", baseUrl, account, customerOrderId, pageSize);
return httpClient.prepareGet(url)
.execute()
.toCompletableFuture()
.thenApply(resp -> {
String responseBodyString = resp.getResponseBody(StandardCharsets.UTF_8);
if (resp.getStatusCode() != 200) {
if (resp.getStatusCode() == 204) {
throw new NumbersApiException("No orders found");
}
throw new NumbersApiException("Error fetching orders. Response body: " + responseBodyString + "; Status code: " + resp.getStatusCode());
}
return NumbersSerde.deserialize(responseBodyString, OrdersResponse.class);
});
});
}

@Override
public void close() {
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.bandwidth.sdk.numbers.models.orders;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import org.immutables.value.Value;

import javax.annotation.Nullable;

@Value.Immutable
@JsonSerialize(as = ImmutableOrdersResponse.class)
@JsonDeserialize(as = ImmutableOrdersResponse.class)
@JacksonXmlRootElement(localName = "ResponseSelectWrapper")
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class OrdersResponse {
@Value.Redacted
@Nullable
@JacksonXmlProperty(localName = "ListOrderIdUserIdDate")
public abstract OrdersResponseWrapper getOrdersResponseData();

public static ImmutableOrdersResponse.Builder builder() {
return ImmutableOrdersResponse.builder();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.bandwidth.sdk.numbers.models.orders;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import org.immutables.value.Value;

import javax.annotation.Nullable;
import java.util.Date;

@Value.Immutable
@JsonSerialize(as = ImmutableOrdersResponseData.class)
@JsonDeserialize(as = ImmutableOrdersResponseData.class)
@JacksonXmlRootElement(localName = "OrderIdUserIdDate")
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class OrdersResponseData {
@Nullable
@JacksonXmlProperty(localName = "accountId")
public abstract String getAccountId();

@Nullable
@JacksonXmlProperty(localName = "CountOfTNs")
public abstract Integer getCountOfTns();

@Nullable
@JacksonXmlProperty(localName = "CustomerOrderId")
public abstract String getCustomerOrderId();

@Nullable
@JacksonXmlProperty(localName = "userId")
public abstract String getUserId();

@Nullable
@JacksonXmlProperty(localName = "lastModifiedDate")
public abstract Date getLastModifiedDate();

@Nullable
@JacksonXmlProperty(localName = "OrderDate")
public abstract Date getOrderDate();

@Nullable
@JacksonXmlProperty(localName = "OrderType")
public abstract String getOrderType();

@Nullable
@JacksonXmlProperty(localName = "orderId")
public abstract String getOrderId();

@Nullable
@JacksonXmlProperty(localName = "OrderStatus")
public abstract OrderResponse.OrderStatus getOrderStatus();

@Nullable
@JacksonXmlProperty(localName = "Summary")
public abstract String getSummary();

public static ImmutableOrdersResponseData.Builder builder() {
return ImmutableOrdersResponseData.builder();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.bandwidth.sdk.numbers.models.orders;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import org.immutables.value.Value;

import javax.annotation.Nullable;

@Value.Immutable
@JsonSerialize(as = ImmutableOrdersResponseLinks.class)
@JsonDeserialize(as = ImmutableOrdersResponseLinks.class)
@JacksonXmlRootElement(localName = "Links")
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class OrdersResponseLinks {
@Nullable
@JacksonXmlProperty(localName = "first")
public abstract String getFirst();

@Nullable
@JacksonXmlProperty(localName = "next")
public abstract String getNext();

public static ImmutableOrdersResponseLinks.Builder builder() {
return ImmutableOrdersResponseLinks.builder();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.bandwidth.sdk.numbers.models.orders;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import org.immutables.value.Value;

import javax.annotation.Nullable;
import java.util.List;

@Value.Immutable
@JsonSerialize(as = ImmutableOrdersResponseWrapper.class)
@JsonDeserialize(as = ImmutableOrdersResponseWrapper.class)
@JacksonXmlRootElement(localName = "ListOrderIdUserIdDate")
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class OrdersResponseWrapper {
@Nullable
@JacksonXmlProperty(localName = "TotalCount")
public abstract Integer getTotalCount();

@Nullable
@JacksonXmlElementWrapper(localName = "Links")
public abstract OrdersResponseLinks getLinks();

@Nullable
@JacksonXmlElementWrapper(useWrapping = false)
@JacksonXmlProperty(localName = "OrderIdUserIdDate")
public abstract List<OrdersResponseData> getOrders();

public static ImmutableOrdersResponseWrapper.Builder builder() {
return ImmutableOrdersResponseWrapper.builder();
}
}
62 changes: 58 additions & 4 deletions src/test/java/com/bandwidth/sdk/numbers/NumbersClientImplTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@
import com.bandwidth.sdk.numbers.models.ImmutableErrorResponse;
import com.bandwidth.sdk.numbers.models.ImmutableSearchResult;
import com.bandwidth.sdk.numbers.models.SearchResult;
import com.bandwidth.sdk.numbers.models.orders.ExistingTelephoneNumberOrderType;
import com.bandwidth.sdk.numbers.models.orders.ImmutableOrderResponse;
import com.bandwidth.sdk.numbers.models.orders.Order;
import com.bandwidth.sdk.numbers.models.orders.OrderResponse;
import com.bandwidth.sdk.numbers.models.orders.*;
import com.bandwidth.sdk.numbers.serde.NumbersSerde;
import org.assertj.core.api.Assertions;
import org.asynchttpclient.AsyncHttpClient;
Expand All @@ -23,6 +20,7 @@
import org.mockito.junit.MockitoJUnitRunner;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;

Expand Down Expand Up @@ -80,6 +78,23 @@ public class NumbersClientImplTest {
.order(order)
.build();

private final OrdersResponse ordersResponse = ImmutableOrdersResponse.builder()
.ordersResponseData(OrdersResponseWrapper.builder()
.addOrders(ImmutableOrdersResponseData.builder()
.accountId("1")
.countOfTns(1)
.customerOrderId("foo")
.userId("1")
.lastModifiedDate(null)
.orderDate(null)
.orderType("1")
.orderId("1")
.orderStatus(OrderResponse.OrderStatus.COMPLETE)
.summary("1")
.build())
.build())
.build();

@Mock
private AsyncHttpClient asyncHttpClient;
@Mock
Expand Down Expand Up @@ -179,4 +194,43 @@ public void orderNumbersWithError() {
assertThat(thrown).isInstanceOf(NumbersApiException.class);
}

@Test
public void searchForNumberByCustomerOrderId() {
when(asyncHttpClient.prepareGet(anyString())).thenReturn(boundRequestBuilder);
when(boundRequestBuilder.execute()).thenReturn(listenableFuture);
when(listenableFuture.toCompletableFuture()).thenReturn(CompletableFuture.completedFuture(response));
when(response.getStatusCode()).thenReturn(200);
when(response.getResponseBody(StandardCharsets.UTF_8)).thenReturn(NumbersSerde.serialize(ordersResponse));

assertThat(ordersResponse).isEqualTo(numbersClient.getOrdersByCustomerOrderId("foo"));
List<OrdersResponseData> orders = ordersResponse.getOrdersResponseData().getOrders();
assertThat(orders).hasSize(1);
assertThat(orders.get(0).getCustomerOrderId()).isEqualTo("foo");
assertThat(orders.get(0).getOrderId()).isEqualTo("1");

verify(asyncHttpClient, times(1)).prepareGet(anyString());
}

@Test
public void searchForNumberByCustomerOrderIdNoOrdersFound() {
when(asyncHttpClient.prepareGet(anyString())).thenReturn(boundRequestBuilder);
when(boundRequestBuilder.execute()).thenReturn(listenableFuture);
when(listenableFuture.toCompletableFuture()).thenReturn(CompletableFuture.completedFuture(response));
when(response.getStatusCode()).thenReturn(204);

Throwable thrown = Assertions.catchThrowable(() -> numbersClient.getOrdersByCustomerOrderId("foo"));
assertThat(thrown).isInstanceOf(CompletionException.class).hasCauseInstanceOf(NumbersApiException.class);
}

@Test
public void searchForNumberByCustomerOrderIdRequestError() {
when(asyncHttpClient.prepareGet(anyString())).thenReturn(boundRequestBuilder);
when(boundRequestBuilder.execute()).thenReturn(listenableFuture);
when(listenableFuture.toCompletableFuture()).thenReturn(CompletableFuture.completedFuture(response));
when(response.getStatusCode()).thenReturn(400);

Throwable thrown = Assertions.catchThrowable(() -> numbersClient.getOrdersByCustomerOrderId("foo"));
assertThat(thrown).isInstanceOf(CompletionException.class).hasCauseInstanceOf(NumbersApiException.class);
}

}
Loading