3 import io.bytom.exception.*;
4 import com.google.gson.Gson;
5 import com.google.gson.JsonArray;
6 import com.google.gson.JsonElement;
7 import com.google.gson.JsonParser;
8 import com.squareup.okhttp.Response;
10 import java.io.IOException;
11 import java.lang.reflect.Type;
15 * BatchResponse provides a convenient interface for handling the results of
16 * batched API calls. The response contains one success or error per outgoing
17 * request item in the batch. Errors are always of type APIExcpetion.
19 public class BatchResponse<T> {
20 private Response response;
21 private Map<Integer, T> successesByIndex = new LinkedHashMap<>();
22 private Map<Integer, APIException> errorsByIndex = new LinkedHashMap<>();
25 * This constructor is used when deserializing a response from an API call.
27 public BatchResponse(Response response, Gson serializer, Type tClass, Type eClass)
28 throws BytomException, IOException {
29 this.response = response;
32 JsonArray root = new JsonParser().parse(response.body().charStream()).getAsJsonArray();
33 for (int i = 0; i < root.size(); i++) {
34 JsonElement elem = root.get(i);
36 // Test for interleaved errors
37 APIException err = serializer.fromJson(elem, eClass);
38 if (err.code != null) {
39 errorsByIndex.put(i, err);
43 successesByIndex.put(i, (T) serializer.fromJson(elem, tClass));
45 } catch (IllegalStateException e) {
46 throw new JSONException(
47 "Unable to read body: " + e.getMessage(), response.headers().get("Chain-Request-ID"));
52 * This constructor is used for synthetically generating a batch response
53 * object from a map of successes and a map of errors. It ensures that
54 * the successes and errors are stored in an order-preserving fashion.
56 public BatchResponse(Map<Integer, T> successes, Map<Integer, APIException> errors) {
57 List<Integer> successIndexes = new ArrayList<>();
58 Iterator<Integer> successIter = successes.keySet().iterator();
59 while (successIter.hasNext()) successIndexes.add(successIter.next());
60 Collections.sort(successIndexes);
61 for (int i : successIndexes) successesByIndex.put(i, successes.get(i));
63 List<Integer> errorIndexes = new ArrayList<>();
64 Iterator<Integer> errorIter = errors.keySet().iterator();
65 while (errorIter.hasNext()) errorIndexes.add(errorIter.next());
66 Collections.sort(errorIndexes);
67 for (int i : errorIndexes) errorsByIndex.put(i, errors.get(i));
71 * Returns the internal response object.
73 public Response response() {
78 * Returns the total number of response objects. This should equal the number
79 * of request objects in the batch.
82 return successesByIndex.size() + errorsByIndex.size();
86 * Returns whether the request object at the given index produced a success.
87 * @param index the index of the request object
89 public boolean isSuccess(int index) {
90 return successesByIndex.containsKey(index);
94 * Returns whether the request object at the given index produced an error.
95 * @param index the index of the request object
97 public boolean isError(int index) {
98 return errorsByIndex.containsKey(index);
102 * Returns a list of successful response objects in the batch. The order of
103 * the list corresponds to the order of the request objects that produced the
106 public List<T> successes() {
107 List<T> res = new ArrayList<>();
108 res.addAll(successesByIndex.values());
113 * Returns a list of error objects in the batch. The order of the list
114 * corresponds to the order of the request objects that produced the
117 public List<APIException> errors() {
118 List<APIException> res = new ArrayList<>();
119 res.addAll(errorsByIndex.values());
124 * Returns a map of success responses, keyed by the index of the request
125 * object that produced the success. The set of this map's keys is mutually
126 * exclusive of the keys returned by errorsByIndex.
128 public Map<Integer, T> successesByIndex() {
129 return successesByIndex;
133 * Returns a map of error responses, keyed by the index of the request
134 * object that produced the error. The set of this map's keys is mutually
135 * exclusive of the keys returned by successByIndex.
137 public Map<Integer, APIException> errorsByIndex() {
138 return errorsByIndex;