All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.useful_solutions.tosamara_sdk.api.APIRequestImpl Maven / Gradle / Ivy

There is a newer version: 1.5
Show newest version
package com.github.useful_solutions.tosamara_sdk.api;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.github.useful_solutions.tosamara_sdk.api.record.pojo.*;
import com.github.useful_solutions.tosamara_sdk.api.record.request.*;
import com.github.useful_solutions.tosamara_sdk.api.record.response.*;
import com.github.useful_solutions.tosamara_sdk.exception.APIResponseException;
import com.github.useful_solutions.tosamara_sdk.util.HttpConnectionManager;
import okhttp3.FormBody;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.apache.commons.codec.digest.DigestUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import static java.net.HttpURLConnection.HTTP_OK;

public class APIRequestImpl implements APIRequest {

    private static final String API_URL = "https://tosamara.ru/api/json";
    private static final String TEST_AUTH_KEY_URL = "https://tosamara.ru/test_files/api/handler.php";

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
            .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
            .enable(SerializationFeature.INDENT_OUTPUT)
            .configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true)
            .configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false)
            .setSerializationInclusion(JsonInclude.Include.NON_NULL)
            .registerModule(new JavaTimeModule());

    private final String clientId;
    private final String key;
    private final String os;

    /**
     * @param clientId идентификатор клиента.
     * @param key      ключ.
     * @param os       операционная система, с которой будут отправляться запросы.
     */
    public APIRequestImpl(@NotNull String clientId, @NotNull String key, @NotNull String os) {
        this.clientId = clientId;
        this.key = key;
        this.os = os;
    }

    /**
     * Для запросов к API будет использоваться тестовый ключ.
     * В качестве операционной системы будет использоваться "android".
     */
    public APIRequestImpl() {
        this("android");
    }

    /**
     * Для запросов к API будет использоваться тестовый ключ.
     *
     * @param os операционная система, с которой будут отправляться запросы.
     */
    public APIRequestImpl(@NotNull String os) {
        clientId = "test";
        key = null;
        this.os = os;
    }

    @Override
    public GetFirstArrivalToStopResponse getFirstArrivalToStop(List ksIds, @Nullable Integer count) throws APIResponseException, IOException {
        GetFirstArrivalToStopRequest request = new GetFirstArrivalToStopRequest(ksIds, count);
        return doRequest(request, GetFirstArrivalToStopResponse.class);
    }

    @Override
    public GetFirstArrivalToStopResponse getFirstArrivalToStop(Integer ksId, @Nullable Integer count) throws APIResponseException, IOException {
        return getFirstArrivalToStop(Collections.singletonList(ksId), count);
    }

    @Override
    public GetRouteArrivalToStopResponse getRouteArrivalToStop(Integer ksId, Integer krId) throws APIResponseException, IOException {
        GetRouteArrivalToStopRequest request = new GetRouteArrivalToStopRequest(ksId, krId);
        return doRequest(request, GetRouteArrivalToStopResponse.class);
    }

    @Override
    public GetRouteScheduleResponse getRouteSchedule(Integer krId, String day) throws APIResponseException, IOException {
        GetRouteScheduleRequest request = new GetRouteScheduleRequest(krId, day);
        return doRequest(request, GetRouteScheduleResponse.class);
    }

    @Override
    public FindShortestPathResponse findShortestPath(GeoPoint geoPoint1, GeoPoint geoPoint2,
                                                     FindShortestPathRequest.Criterion criterion, TransportType... transports) throws APIResponseException, IOException {
        FindShortestPathRequest request = new FindShortestPathRequest(geoPoint1, geoPoint2, criterion, transports);
        return doRequest(request, FindShortestPathResponse.class);
    }

    @Override
    public GetTransportPositionResponse getTransportPosition(Integer hullNo) throws APIResponseException, IOException {
        GetTransportPositionRequest request = new GetTransportPositionRequest(hullNo);
        return doRequest(request, GetTransportPositionResponse.class);
    }

    @Override
    public List getSurroundingTransports(GeoPoint geoPoint, Double radius, Integer count) throws APIResponseException, IOException {
        GetSurroundingTransportsRequest request = new GetSurroundingTransportsRequest(geoPoint, radius, count);
        GetSurroundingTransportsResponse response = doRequest(request, GetSurroundingTransportsResponse.class);
        return response.transports;
    }

    @Override
    public List getTransportsOnRoute(List krIds, Integer count) throws APIResponseException, IOException {
        GetTransportsOnRouteRequest request = new GetTransportsOnRouteRequest(krIds, count);
        GetTransportsOnRouteResponse response = doRequest(request, GetTransportsOnRouteResponse.class);
        return response.transports;
    }

    @Override
    public List getTransportsOnRoute(Integer krId, Integer count) throws APIResponseException, IOException {
        return getTransportsOnRoute(Collections.singletonList(krId), count);
    }

    public List getNearestBuilding(GeoPoint geoPoint, Double radius, Integer count) throws APIResponseException, IOException {
        GetNearestBuildingRequest request = new GetNearestBuildingRequest(geoPoint, radius, count);
        GetNearestBuildingResponse response = doRequest(request, GetNearestBuildingResponse.class);
        return response.buildings;
    }

    public List findBuildingByAddress(@Nullable GeoPoint geoPoint, String address, Integer count) throws APIResponseException, IOException {
        FindBuildingByAddressRequest request = new FindBuildingByAddressRequest(geoPoint, address, count);
        FindBuildingByAddressResponse response = doRequest(request, FindBuildingByAddressResponse.class);
        return response.buildings;
    }

    public List getUserMessages(GeoPoint geoPoint, Double radius, String deviceId) throws APIResponseException, IOException {
        GetUserMessagesRequest request = new GetUserMessagesRequest(geoPoint, radius, deviceId);
        GetUserMessagesResponse response = doRequest(request, GetUserMessagesResponse.class);
        return response.messages;
    }

    public VoteForMessageResponse voteForMessage(Integer id, Message.Vote vote, GeoPoint geoPoint, String deviceId) throws APIResponseException, IOException {
        VoteForMessageRequest request = new VoteForMessageRequest(id, vote, geoPoint, deviceId);
        return doRequest(request, VoteForMessageResponse.class);
    }

    public SendUserMessageResponse sendUserMessage(String text, String textEn, String link,
                                                   List links, Integer expireTime, String deviceId) throws APIResponseException, IOException {
        SendUserMessageRequest request = new SendUserMessageRequest(text, textEn, link, links, expireTime, deviceId);
        return doRequest(request, SendUserMessageResponse.class);
    }

    private  T doRequest(Object request, Class responseType) throws APIResponseException, IOException {
        RequestBody requestBody = getFormParams(OBJECT_MAPPER.writeValueAsString(request));
        String rawData = doAPIRequest(requestBody);
        return OBJECT_MAPPER.readValue(rawData, responseType);
    }

    /**
     * Метод создания тела HTTP-запроса в виде формы.
     *
     * @param message сообщение.
     * @return тело запроса.
     */
    private RequestBody getFormParams(String message) throws IOException, APIResponseException {
        FormBody.Builder form = new FormBody.Builder();
        form.add("os", os);
        form.add("message", message);
        form.add("clientId", clientId);
        String authKey = (key == null ? getTestAuthKey(message) : DigestUtils.shaHex(message + key));
        form.add("authKey", authKey);
        return form.build();
    }

    /**
     * Метод получения тестового ключа.
     *
     * @param message сообщение серверу.
     * @return тестовый ключ.
     * @throws APIResponseException выбрасывается, если код ответа не равен 200.
     * @throws IOException          выбрасывается, когда есть несоответствие полей классов и полей JSON или произошла ошибка запроса.
     */
    private String getTestAuthKey(String message) throws IOException, APIResponseException {
        FormBody.Builder form = new FormBody.Builder();
        form.add("msg", message);
        try (Response response = HttpConnectionManager.buildPostCall(TEST_AUTH_KEY_URL, form.build()).execute()) {
            return handleResponse(response);
        }
    }

    private String doAPIRequest(RequestBody requestBody) throws APIResponseException, IOException {
        try (Response response = HttpConnectionManager.buildPostCall(API_URL, requestBody).execute()) {
            return handleResponse(response);
        }
    }

    private String handleResponse(Response response) throws IOException, APIResponseException {
        int statusCode = response.code();
        if (statusCode != HTTP_OK) {
            throw new APIResponseException(statusCode);
        }
        try (ResponseBody responseBody = Optional.ofNullable(response.body()).orElseThrow(APIResponseException::new)) {
            return responseBody.string();
        }
    }

    private static class GetSurroundingTransportsResponse {
        public List transports;
    }

    private static class GetTransportsOnRouteResponse {
        public List transports;
    }

    private static class GetNearestBuildingResponse {
        public List buildings;
    }

    private static class FindBuildingByAddressResponse {
        public List buildings;
    }

    private static class GetUserMessagesResponse {
        public List messages;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy