Created base for client implementation

This commit is contained in:
Andrey Terentev 2024-03-12 15:19:48 +07:00 committed by Andrey Terentev
parent 4695dce10d
commit bde58ef053
7 changed files with 338 additions and 1 deletions

View File

@ -12,7 +12,9 @@ repositories {
dependencies {
implementation project(':client-api')
implementation 'org.jetbrains:annotations:24.1.0'
implementation 'com.squareup.okhttp:okhttp:2.7.5'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.3'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.3'
testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation 'org.junit.jupiter:junit-jupiter'

View File

@ -0,0 +1,59 @@
package ru.dragonestia.picker.api.impl;
import okhttp3.Credentials;
import okhttp3.Request;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.ApiStatus.Internal;
import ru.dragonestia.picker.api.impl.repository.NodeRepositoryImpl;
import ru.dragonestia.picker.api.impl.repository.RoomRepositoryImpl;
import ru.dragonestia.picker.api.impl.repository.UserRepositoryImpl;
import ru.dragonestia.picker.api.impl.util.RestTemplate;
import ru.dragonestia.picker.api.repository.NodeRepository;
import ru.dragonestia.picker.api.repository.RoomRepository;
import ru.dragonestia.picker.api.repository.UserRepository;
public class RoomPickerClient {
private final String url;
private final String username;
private final String password;
private final RestTemplate restTemplate;
private final NodeRepository nodeRepository;
private final RoomRepository roomRepository;
private final UserRepository userRepository;
public RoomPickerClient(@NotNull String url, @NotNull String username, @NotNull String password) {
this.url = url;
this.username = username;
this.password = password;
this.restTemplate = new RestTemplate(this);
this.nodeRepository = new NodeRepositoryImpl(this);
this.roomRepository = new RoomRepositoryImpl(this);
this.userRepository = new UserRepositoryImpl(this);
}
@Internal
public @NotNull RestTemplate getRestTemplate() {
return restTemplate;
}
@Internal
public @NotNull Request.Builder prepareRequestBuilder(@NotNull String uri) {
return new Request.Builder()
.url(url + uri)
.addHeader("Authorization", Credentials.basic(username, password));
}
public @NotNull NodeRepository getNodeRepository() {
return nodeRepository;
}
public @NotNull RoomRepository getRoomRepository() {
return roomRepository;
}
public @NotNull UserRepository getUserRepository() {
return userRepository;
}
}

View File

@ -0,0 +1,50 @@
package ru.dragonestia.picker.api.impl.repository;
import org.jetbrains.annotations.ApiStatus.Internal;
import org.jetbrains.annotations.NotNull;
import ru.dragonestia.picker.api.impl.RoomPickerClient;
import ru.dragonestia.picker.api.impl.util.RestTemplate;
import ru.dragonestia.picker.api.model.node.INode;
import ru.dragonestia.picker.api.model.node.NodeDefinition;
import ru.dragonestia.picker.api.repository.NodeRepository;
import ru.dragonestia.picker.api.repository.request.node.FindNodeById;
import ru.dragonestia.picker.api.repository.request.node.GetAllNodes;
import ru.dragonestia.picker.api.repository.request.node.RemoveNodesByIds;
import java.util.List;
import java.util.Optional;
public class NodeRepositoryImpl implements NodeRepository {
private final RestTemplate rest;
@Internal
public NodeRepositoryImpl(RoomPickerClient client) {
rest = client.getRestTemplate();
}
@Override
public @NotNull List<INode> allNodes(@NotNull GetAllNodes data) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public @NotNull Optional<INode> findNodeById(@NotNull FindNodeById data) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public void removeNodesById(@NotNull RemoveNodesByIds data) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public void removeNode(@NotNull INode node) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public void saveNode(@NotNull NodeDefinition definition) {
throw new UnsupportedOperationException("Not implemented");
}
}

View File

@ -0,0 +1,52 @@
package ru.dragonestia.picker.api.impl.repository;
import org.jetbrains.annotations.ApiStatus.Internal;
import org.jetbrains.annotations.NotNull;
import ru.dragonestia.picker.api.impl.RoomPickerClient;
import ru.dragonestia.picker.api.impl.util.RestTemplate;
import ru.dragonestia.picker.api.model.room.ResponseRoom;
import ru.dragonestia.picker.api.model.room.RoomDefinition;
import ru.dragonestia.picker.api.model.room.ShortResponseRoom;
import ru.dragonestia.picker.api.repository.RoomRepository;
import ru.dragonestia.picker.api.repository.request.room.FindRoomById;
import ru.dragonestia.picker.api.repository.request.room.GetAllRooms;
import ru.dragonestia.picker.api.repository.request.room.RemoveRoomsByIds;
import ru.dragonestia.picker.api.repository.type.RoomPath;
import java.util.List;
import java.util.Optional;
public class RoomRepositoryImpl implements RoomRepository {
private final RestTemplate rest;
@Internal
public RoomRepositoryImpl(RoomPickerClient client) {
rest = client.getRestTemplate();
}
@Override
public void saveRoom(@NotNull RoomDefinition definition) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public void removeRooms(@NotNull RemoveRoomsByIds request) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public @NotNull List<ShortResponseRoom> allRooms(@NotNull GetAllRooms request) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public @NotNull Optional<ResponseRoom> find(@NotNull FindRoomById request) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public void lockRoom(@NotNull RoomPath path, boolean value) {
throw new UnsupportedOperationException("Not implemented");
}
}

View File

@ -0,0 +1,52 @@
package ru.dragonestia.picker.api.impl.repository;
import org.jetbrains.annotations.ApiStatus.Internal;
import org.jetbrains.annotations.NotNull;
import ru.dragonestia.picker.api.impl.RoomPickerClient;
import ru.dragonestia.picker.api.impl.util.RestTemplate;
import ru.dragonestia.picker.api.model.room.ShortResponseRoom;
import ru.dragonestia.picker.api.model.user.ResponseUser;
import ru.dragonestia.picker.api.repository.UserRepository;
import ru.dragonestia.picker.api.repository.request.user.*;
import java.util.List;
public class UserRepositoryImpl implements UserRepository {
private final RestTemplate rest;
@Internal
public UserRepositoryImpl(RoomPickerClient client) {
rest = client.getRestTemplate();
}
@Override
public void linkUsersWithRoom(@NotNull LinkUsersWithRoom request) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public void unlinkUsersFromRoom(@NotNull UnlinkUsersFromRoom request) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public @NotNull List<ResponseUser> getAllUsersFormRoom(@NotNull GetAllUsersFromRoom request) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public @NotNull List<ResponseUser> searchUsers(@NotNull SearchUsers request) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public @NotNull ResponseUser findUserById(@NotNull FindUserById request) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public @NotNull List<ShortResponseRoom> findRoomsLinkedWithUser(@NotNull FindRoomsLinkedWithUser request) {
throw new UnsupportedOperationException("Not implemented");
}
}

View File

@ -0,0 +1,114 @@
package ru.dragonestia.picker.api.impl.util;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Response;
import org.jetbrains.annotations.ApiStatus.Internal;
import ru.dragonestia.picker.api.exception.ExceptionFactory;
import ru.dragonestia.picker.api.impl.RoomPickerClient;
import ru.dragonestia.picker.api.impl.util.type.HttpMethod;
import ru.dragonestia.picker.api.repository.response.ErrorResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Consumer;
@Internal
public class RestTemplate {
private final RoomPickerClient client;
private final OkHttpClient httpClient;
private final ObjectMapper json;
public RestTemplate(RoomPickerClient client) {
this.client = client;
httpClient = new OkHttpClient();
json = configureJackson();
}
private ObjectMapper configureJackson() {
var mapper = new ObjectMapper();
mapper.setVisibility(mapper.getSerializationConfig().getDefaultVisibilityChecker()
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
return mapper;
}
public void query(String uri, HttpMethod method) {
query(uri, method, ParamsConsumer.NONE);
}
public void query(String uri, HttpMethod method, ParamsConsumer paramsConsumer) {
var request = client.prepareRequestBuilder(uri + queryEncode(paramsConsumer))
.method(method.name(), method == HttpMethod.GET? null : new FormBody.Builder().build())
.build();
try (var response = httpClient.newCall(request).execute()) {
checkResponseForErrors(response);
} catch (JsonProcessingException ex) {
throw new RuntimeException("Json processing error", ex);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
public <T> T query(String uri, HttpMethod method, Class<T> clazz) {
return query(uri, method, clazz, ParamsConsumer.NONE);
}
public <T> T query(String uri, HttpMethod method, Class<T> clazz, ParamsConsumer paramsConsumer) {
var request = client.prepareRequestBuilder(uri + queryEncode(paramsConsumer))
.method(method.name(), method == HttpMethod.GET? null : new FormBody.Builder().build())
.build();
try (var response = httpClient.newCall(request).execute()) {
checkResponseForErrors(response);
return json.readValue(new String(Objects.requireNonNull(response.body()).bytes(), StandardCharsets.UTF_8), clazz);
} catch (JsonProcessingException ex) {
throw new RuntimeException("Json processing error", ex);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
private String queryEncode(ParamsConsumer paramsConsumer) {
var params = new HashMap<String, String>();
paramsConsumer.accept(params);
if (params.isEmpty()) return "";
List<String> pairs = new ArrayList<>();
for (var entry: params.entrySet()) {
pairs.add(entry.getKey() + "=" + URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8));
}
return "?" + String.join("&", pairs);
}
private void checkResponseForErrors(Response response) throws IOException {
var code = response.code();
System.out.println(code);
var statusCode = code / 100;
if (statusCode == 4) {
var body = new String(Objects.requireNonNull(response.body()).bytes(), StandardCharsets.UTF_8);
throw ExceptionFactory.of(json.readValue(body, ErrorResponse.class));
}
if (statusCode == 5) {
throw new RuntimeException("Internal server error");
}
}
public interface ParamsConsumer extends Consumer<Map<String, String>> {
ParamsConsumer NONE = map -> {};
}
}

View File

@ -0,0 +1,8 @@
package ru.dragonestia.picker.api.impl.util.type;
public enum HttpMethod {
GET,
POST,
PUT,
DELETE;
}