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

com.klarna.rest.api.BaseApi Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2018 Klarna AB
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.klarna.rest.api;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.klarna.rest.http_transport.HttpTransport;
import com.klarna.rest.model.ApiException;
import com.klarna.rest.model.ApiResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

/**
 * API Resource helper.
 * Simplifies work with HTTP HttpTransport and Logging.
 * @see HttpTransport
 */
public abstract class BaseApi {
    /**
     * Default URL Encoding.
     */
    private static final String URL_ENCODING = "UTF-8";

    /**
     * Logger instance.
     */
    private static final Logger log = LoggerFactory.getLogger(BaseApi.class);

    /**
     * HTTP Transport.
     */
    protected HttpTransport transport;

    /**
     * Preferred ObjectMapper.
     */
    protected ObjectMapper objectMapper;

    /**
     * Last response instance.
     */
    protected ApiResponse lastResponse;

    /**
     * Fetched location from last response.
     */
    protected String location;

    protected enum Method {
        GET("GET"),
        POST("POST"),
        PUT("PUT"),
        PATCH("PATCH"),
        DELETE("DELETE");

        private final String method;

        Method(String method) {
            this.method = method;
        }

        public String getMethod() {
            return method;
        }

        @Override
        public String toString() {
            return super.toString();
        }
    }

    public BaseApi(HttpTransport transport) {
        this.transport = transport;
        this.objectMapper = new DefaultMapper();
    }

    public BaseApi(HttpTransport transport, ObjectMapper mapper) {
        this.transport = transport;
        this.objectMapper = mapper;
    }

    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    public ObjectMapper getObjectMapper() {
        return this.objectMapper;
    }

    public ApiResponse getLastResponse() {
        return lastResponse;
    }

    /**
     * Converts Map to URL Query string.
     *
     * @param params Params map
     * @return HTTP Query string
     * @throws RuntimeException if Params map has Unsupported encoding
     */
    public static String buildQueryString(final Map params) throws RuntimeException {
        if (params == null) {
            return "";
        }

        StringBuilder stringBuilder = new StringBuilder();

        for (String key : params.keySet()) {
            if (stringBuilder.length() > 0) {
                stringBuilder.append("&");
            }
            String value = params.get(key);
            try {
                if (key != null) {
                    stringBuilder.append(URLEncoder.encode(key, URL_ENCODING));
                    stringBuilder.append("=");
                    stringBuilder.append(value != null ? URLEncoder.encode(value, URL_ENCODING) : "");
                }
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException("Unsupported encoding", e);
            }
        }

        return stringBuilder.toString();
    }

    /**
     * Wraps HTTP GET request to be able to log the query and result.
     *
     * @param path URL path
     * @return Processed response
     * @throws ApiException if API server returned non-20x HTTP CODE and response contains
     *                      a Error
     * @throws IOException if an error occurred when connecting to the server or when parsing a response.
     */
    protected ApiResponse get(final String path) throws ApiException, IOException {
        return this.get(path, null);
    }

    protected ApiResponse get(final String path, final Map headers)
            throws ApiException, IOException {
        return this.makeRequest(Method.GET, path, null, headers);
    }

    /**
     * Wraps HTTP POST request to be able to log the query and result.
     *
     * @param path URL path
     * @param data Data to be sent to API server in a payload.
     * @return Processed response
     * @throws ApiException if API server returned non-20x HTTP CODE and response contains
     *                      a Error
     * @throws IOException if an error occurred when connecting to the server or when parsing a response.
     */
    protected ApiResponse post(final String path, final byte[] data) throws ApiException, IOException {
        return this.post(path, data, null);
    }

    protected ApiResponse post(final String path, final byte[] data, Map headers)
            throws ApiException, IOException {
        return this.makeRequest(Method.POST, path, data, headers);
    }

    /**
     * Wraps HTTP POST request to be able to log the query and result.
     *
     * @param path URL path
     * @param data Data to be sent to API server in a payload
     * @return Processed response
     * @throws ApiException if API server returned non-20x HTTP CODE and response contains
     *                      a Error
     * @throws IOException if an error occurred when connecting to the server or when parsing a response.
     */
    protected ApiResponse put(final String path, final byte[] data) throws ApiException, IOException {
        return this.put(path, data, null);
    }

    protected ApiResponse put(final String path, final byte[] data, Map headers)
            throws ApiException, IOException {
        return this.makeRequest(Method.PUT, path, data, headers);
    }

    protected ApiResponse patch(final String path, final byte[] data) throws ApiException, IOException {
        return this.patch(path, data, null);
    }

    protected ApiResponse patch(final String path, final byte[] data, Map headers)
            throws ApiException, IOException {
        return this.makeRequest(Method.PATCH, path, data, headers);
    }

    protected ApiResponse delete(final String path) throws ApiException, IOException {
        return this.delete(path, null);
    }

    @Deprecated
    protected ApiResponse delete(final String path, Map headers) throws ApiException, IOException {
        return this.makeRequest(Method.DELETE, path, null, headers);
    }

    protected ApiResponse delete(final String path, final byte[] data, Map headers) throws ApiException, IOException {
        return this.makeRequest(Method.DELETE, path, data, headers);
    }

    protected ApiResponse makeRequest(
            final Method method,
            final String path,
            final byte[] data,
            final Map headers)
            throws ApiException, IOException {
        final ApiResponse response;
        switch (method) {
            case GET:
                response = this.transport.get(path, headers);
                break;

            case POST:
                response = this.transport.post(path, data, headers);
                break;

            case PUT:
                response = this.transport.put(path, data, headers);
                break;

            case PATCH:
                response = this.transport.patch(path, data, headers);
                break;

            case DELETE:
                response = this.transport.delete(path, data, headers);
                break;

            default: throw new IOException("Unknown request method " + method);
        }

        // Check if the response has a "Location" header
        List header = response.getHeader("Location");
        if (header != null) {
            this.location = header.get(0);
        }

        this.lastResponse = response;

        return response;
    }

    protected  T fromJson(final byte[] data, Class type) throws IOException {
        if (data == null || data.length == 0) {
            log.warn("No JSON data to convert to " + type);
            return null;
        }

        return objectMapper.readValue(data, type);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy