Add 'sdk/java-v2/' from commit '55f103e336ca9fb8bf1720d2ef4ee8dd4e221118'
[arvados.git] / sdk / java-v2 / src / main / java / org / arvados / client / api / client / BaseStandardApiClient.java
1 /*
2  * Copyright (C) The Arvados Authors. All rights reserved.
3  *
4  * SPDX-License-Identifier: AGPL-3.0 OR Apache-2.0
5  *
6  */
7
8 package org.arvados.client.api.client;
9
10 import com.fasterxml.jackson.core.JsonProcessingException;
11 import com.fasterxml.jackson.core.type.TypeReference;
12 import com.fasterxml.jackson.databind.ObjectWriter;
13 import okhttp3.MediaType;
14 import okhttp3.HttpUrl;
15 import okhttp3.HttpUrl.Builder;
16 import okhttp3.Request;
17 import okhttp3.RequestBody;
18 import org.arvados.client.exception.ArvadosApiException;
19 import org.arvados.client.api.model.Item;
20 import org.arvados.client.api.model.ItemList;
21 import org.arvados.client.api.model.argument.ListArgument;
22 import org.arvados.client.config.ConfigProvider;
23 import org.slf4j.Logger;
24
25 import java.io.IOException;
26 import java.util.Map;
27
28 public abstract class BaseStandardApiClient<T extends Item, L extends ItemList> extends BaseApiClient {
29
30     private static final MediaType JSON = MediaType.parse(com.google.common.net.MediaType.JSON_UTF_8.toString());
31     private final Logger log = org.slf4j.LoggerFactory.getLogger(BaseStandardApiClient.class);
32
33     BaseStandardApiClient(ConfigProvider config) {
34         super(config);
35     }
36
37     public L list(ListArgument listArguments) {
38         log.debug("Get list of {}", getType().getSimpleName());
39         Builder urlBuilder = getUrlBuilder();
40         addQueryParameters(urlBuilder, listArguments);
41         HttpUrl url = urlBuilder.build();
42         Request request = getRequestBuilder().url(url).build();
43         return callForList(request);
44     }
45     
46     public L list() {
47         return list(ListArgument.builder().build());
48     }
49
50     public T get(String uuid) {
51         log.debug("Get {} by UUID {}", getType().getSimpleName(), uuid);
52         HttpUrl url = getUrlBuilder().addPathSegment(uuid).build();
53         Request request = getRequestBuilder().get().url(url).build();
54         return callForType(request);
55     }
56
57     public T create(T type) {
58         log.debug("Create {}", getType().getSimpleName());
59         String json = mapToJson(type);
60         RequestBody body = RequestBody.create(JSON, json);
61         Request request = getRequestBuilder().post(body).build();
62         return callForType(request);
63     }
64
65     public T delete(String uuid) {
66         log.debug("Delete {} by UUID {}", getType().getSimpleName(), uuid);
67         HttpUrl url = getUrlBuilder().addPathSegment(uuid).build();
68         Request request = getRequestBuilder().delete().url(url).build();
69         return callForType(request);
70     }
71
72     public T update(T type) {
73         String uuid = type.getUuid();
74         log.debug("Update {} by UUID {}", getType().getSimpleName(), uuid);
75         String json = mapToJson(type);
76         RequestBody body = RequestBody.create(JSON, json);
77         HttpUrl url = getUrlBuilder().addPathSegment(uuid).build();
78         Request request = getRequestBuilder().put(body).url(url).build();
79         return callForType(request);
80     }
81
82     @Override
83     Request.Builder getRequestBuilder() {
84         return super.getRequestBuilder().url(getUrlBuilder().build());
85     }
86
87     HttpUrl.Builder getUrlBuilder() {
88         return new HttpUrl.Builder()
89                 .scheme(config.getApiProtocol())
90                 .host(config.getApiHost())
91                 .port(config.getApiPort())
92                 .addPathSegment("arvados")
93                 .addPathSegment("v1")
94                 .addPathSegment(getResource());
95     }
96
97     <TL> TL call(Request request, Class<TL> cls) {
98         String bodyAsString = newCall(request);
99         try {
100             return mapToObject(bodyAsString, cls);
101         } catch (IOException e) {
102             throw new ArvadosApiException("A problem occurred while parsing JSON data", e);
103         }
104     }
105
106     private <TL> TL mapToObject(String content, Class<TL> cls) throws IOException {
107         return MAPPER.readValue(content, cls);
108     }
109
110     private <TL> String mapToJson(TL type) {
111         ObjectWriter writer = MAPPER.writer().withDefaultPrettyPrinter();
112         try {
113             return writer.writeValueAsString(type);
114         } catch (JsonProcessingException e) {
115             log.error(e.getMessage());
116             return null;
117         }
118     }
119
120     T callForType(Request request) {
121         return call(request, getType());
122     }
123
124     L callForList(Request request) {
125         return call(request, getListType());
126     }
127
128     abstract String getResource();
129
130     abstract Class<T> getType();
131
132     abstract Class<L> getListType();
133     
134     Request getNoArgumentMethodRequest(String method) {
135         HttpUrl url = getUrlBuilder().addPathSegment(method).build();
136         return getRequestBuilder().get().url(url).build();
137     }
138     
139     RequestBody getJsonRequestBody(Object object) {
140         return RequestBody.create(JSON, mapToJson(object));
141     }
142     
143     void addQueryParameters(Builder urlBuilder, Object object) {
144         Map<String, Object> queryMap = MAPPER.convertValue(object, new TypeReference<Map<String, Object>>() {});
145         queryMap.keySet().forEach(key -> {
146             Object type = queryMap.get(key);
147             if (!(type instanceof String)) {
148                 type = mapToJson(type);
149             }
150             urlBuilder.addQueryParameter(key, (String) type);
151         });
152     }
153 }