Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

package org.brapi.client.v2;

import com.fasterxml.jackson.databind.JsonNode;
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import okhttp3.*;
Expand Down Expand Up @@ -674,6 +675,8 @@ public RequestBody serialize(Object obj, String contentType) throws ApiException
} else if (obj instanceof File) {
// File body parameter support.
return RequestBody.create(MediaType.parse(contentType), (File) obj);
} else if (obj instanceof JsonNode) {
return RequestBody.create(MediaType.parse(contentType), obj.toString());
} else if (isJsonMime(contentType)) {
String content;
if (obj != null) {
Expand Down Expand Up @@ -759,7 +762,8 @@ public File prepareDownloadFile(Response response) throws IOException {
* @return ApiResponse<T>
*/
public <T> ApiResponse<T> execute(Call call) throws ApiException {
return execute(call, null);
Type returnType = null;
return execute(call, returnType);
}

/**
Expand All @@ -784,6 +788,29 @@ public <T> ApiResponse<T> execute(Call call, Type returnType) throws ApiExceptio
}
}

/**
* Execute HTTP call and deserialize the HTTP response body into a return type based off of the submitted ResponseDeserializer<T>.
*
* @param call Call
* @param responseDeserializer A function passed through which will be applied to the final response.
* In particular, this function needs to set the <T> return datatype.
* See ListsApi.deserializeListItemsResponse() for usage examples.
* @param <T> The return type corresponding to (same with) returnType
* @return ApiResponse object containing response status, headers and data,
* which is a Java object deserialized from response body and would be
* null when returnType is null.
* @throws ApiException If fail to execute the call
*/
public <T> ApiResponse<T> execute(Call call, ResponseDeserializer<T> responseDeserializer) throws ApiException {
try {
Response response = call.execute();
T data = handleResponse(response, responseDeserializer);
return new ApiResponse<T>(response.code(), response.headers().toMultimap(), data);
} catch (IOException e) {
throw new ApiException(e);
}
}

/**
* Execute HTTP call and deserialize the HTTP response body into the given
* return type.
Expand Down Expand Up @@ -908,6 +935,42 @@ public <T> T handleResponse(Response response, Type returnType) throws ApiExcept
}
}

/**
* Handle the given response, return the deserialized object when the response
* is successful, and apply the additional passed ResponseDeserializer logic.
*
* @param response Response
* @param deserializer A function passed through which will be applied to the final response.
* In particular, this function needs to set the <T> return datatype.
* See ListsApi.deserializeListItemsResponse() for usage examples. * @throws ApiException If the response has a unsuccessful status code or fail
* to deserialize the response body
* @return Type
*/
public <T> T handleResponse(Response response, ResponseDeserializer<T> deserializer) throws ApiException, IOException {
if (response.isSuccessful()) {
if (response.code() == 204) {
// returning null if the returnType is not defined,
// or the status code is 204 (No Content)
if (response.body() != null) {
response.body().close();
}
return null;
} else {
return deserializer.deserialize(response);
}
} else {
String respBody = null;
if (response.body() != null) {
try {
respBody = response.body().string();
} catch (IOException e) {
throw new ApiException(response.message(), e, response.code(), response.headers().toMultimap());
}
}
throw new ApiException(response.message(), response.code(), response.headers().toMultimap(), respBody);
}
}

/**
* Build HTTP call with the given options.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.brapi.client.v2;

import okhttp3.Response;
import org.brapi.client.v2.model.exceptions.ApiException;

import java.io.IOException;

/**
* Generic interface to apply extra deserialization logic to handle responses in the BrAPIClient.
* @param <T> The response type this response deserializer should apply to.
*/
@FunctionalInterface
public interface ResponseDeserializer<T> {
T deserialize(Response response) throws ApiException, IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,22 @@

package org.brapi.client.v2.modules.core;

import com.fasterxml.jackson.databind.JsonNode;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;

import okhttp3.Call;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import okhttp3.Response;
import org.apache.commons.lang3.tuple.Pair;
import org.brapi.client.v2.ApiCallback;
import org.brapi.client.v2.BrAPIClient;
Expand All @@ -29,11 +36,14 @@
import org.brapi.client.v2.model.exceptions.ApiException;
import org.brapi.client.v2.model.queryParams.core.ListQueryParams;
import org.brapi.v2.model.BrAPIAcceptedSearchResponse;
import org.brapi.v2.model.core.BrAPIListTypes;
import org.brapi.v2.model.core.request.BrAPIListNewRequest;
import org.brapi.v2.model.core.response.BrAPIListItemsListResponse;
import org.brapi.v2.model.core.response.BrAPIListResponse;
import org.brapi.v2.model.core.request.BrAPIListSearchRequest;
import org.brapi.v2.model.core.response.BrAPIListsListResponse;
import org.brapi.v2.model.core.response.BrAPIListsSingleResponse;
import org.brapi.v2.model.germ.BrAPIGermplasm;

public class ListsApi {
private BrAPIClient apiClient;
Expand All @@ -54,6 +64,12 @@ public void setApiClient(BrAPIClient apiClient) {
this.apiClient = apiClient;
}

private static final Map<BrAPIListTypes, Class<?>> supportedItemClassByBrAPIListTypes = new HashMap<>();

static {
supportedItemClassByBrAPIListTypes.put(BrAPIListTypes.GERMPLASM, BrAPIGermplasm.class);
}

/**
* Build call for listsGet
* @param queryParams
Expand Down Expand Up @@ -537,6 +553,45 @@ private Call searchListsPostCall(BrAPIListSearchRequest body) throws ApiExceptio
return apiClient.buildCall(localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAuthNames);
}

/**
* Build call for searchListsPost
* @param body (optional)
* @return Call to execute
* @throws ApiException If fail to serialize the request body object
*/
private Call searchListItemsPostCall(String listDbId, JsonNode body) throws ApiException {
if(body == null) {
throw new IllegalArgumentException("body cannot be null");
}
Object localVarPostBody = body;

// create path and map variables
String localVarPath = "/search/lists/{listDbId}"
.replaceAll("\\{" + "listDbId" + "\\}", apiClient.escapeString(listDbId)) + "/items";

Map<String, String> localVarQueryParams = new HashMap<>();
Map<String, String> localVarCollectionQueryParams = new HashMap<>();

Map<String, String> localVarHeaderParams = new HashMap<String, String>();

Map<String, Object> localVarFormParams = new HashMap<String, Object>();

final String[] localVarAccepts = {
"application/json"
};
final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
if (localVarAccept != null) localVarHeaderParams.put("Accept", localVarAccept);

final String[] localVarContentTypes = {
"application/json"
};
final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
localVarHeaderParams.put("Content-Type", localVarContentType);

String[] localVarAuthNames = new String[] { "AuthorizationToken" };
return apiClient.buildCall(localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAuthNames);
}

/**
* Submit a search request for Lists
* Advanced searching for the list resource. See Search Services for additional implementation details.
Expand Down Expand Up @@ -642,4 +697,50 @@ public Call searchListsSearchResultsDbIdGetAsync(String searchResultsDbId, Integ
apiClient.executeAsync(call, localVarReturnType, callback);
return call;
}

/**
* Submit a search request for ListItems
* Unlike other endpoints, this endpoint is not strongly typed to the search request, and is detected based off of the submitted listDbId.
* To accommodate for this, a functional interface is passed to the apiClient to ensure the parameterized<T> is properly initialized to the right BrAPI model object.
* Async and searchDbIds are not currently supported for this endpoint.
* @param listDbId (required)
* @param body (required)
* @return ApiResponse&lt;ListsListResponse&gt;
* @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body
*/
public <T> ApiResponse<BrAPIListItemsListResponse<T>> searchListItemsByList(String listDbId, JsonNode body) throws ApiException {
Call call = searchListItemsPostCall(listDbId, body);

return apiClient.execute(call, this::deserializeListItemsResponse);
}

private <T> BrAPIListItemsListResponse<T> deserializeListItemsResponse(Response response) throws ApiException, IOException {

// Ignore NPE check here, this function is used after a response check has already occurred further downstream
String json = response.body().string();

JsonParser parser = new JsonParser();

JsonObject root = parser.parse(json).getAsJsonObject();

// The prod server response will return with the data type.
BrAPIListTypes listType = BrAPIListTypes.fromValue(root.getAsJsonPrimitive("resultListType").getAsString());

// Get the BrAPI model object that corresponds to the returned data type.
Class<?> itemClass = supportedItemClassByBrAPIListTypes.get(listType);

if (itemClass == null) {
throw new ApiException("Unsupported list type: " + listType);
}

// Ensure that BrAPIListItemsListResponse has its parameterized <T> set with the appropriate object, which will
// populate all the way down to BrAPIListItemWithFullItem<T>
Type responseType = TypeToken.getParameterized(
BrAPIListItemsListResponse.class,
itemClass
).getType();

// Apply deserialization of the response
return apiClient.getJSON().deserialize(json, responseType);
}
}
5 changes: 5 additions & 0 deletions brapi-java-model/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
<artifactId>jackson-annotations</artifactId>
<version>${jackson.annotations.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.annotations.version}</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package org.brapi.v2.model.core;

import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonProperty;

/**
* ListItem
*/
public class BrAPIListItem {
@JsonProperty("listItemDbId")
private String listItemDbId = null;

@JsonProperty("position")
private Integer position = null;

// This represents the actual value stored in the list_item table
@JsonProperty("item")
private String item = null;


public String getListItemDbId() {
return listItemDbId;
}

public void setListItemDbId(String listItemDbId) {
this.listItemDbId = listItemDbId;
}

public Integer getPosition() {
return position;
}

public void setPosition(Integer position) {
this.position = position;
}

public String getItem() {
return item;
}

public void setItem(String item) {
this.item = item;
}

@Override
public boolean equals(java.lang.Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
BrAPIListItem ListItem = (BrAPIListItem) o;
return Objects.equals(this.listItemDbId, ListItem.listItemDbId) &&
super.equals(o);
}

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

@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class ListItem {\n");
sb.append(" ").append(toIndentedString(super.toString())).append("\n");
sb.append(" listDbId: ").append(toIndentedString(listItemDbId)).append("\n");
sb.append("}");
return sb.toString();
}

/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(java.lang.Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
}


Loading
Loading