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

com.github.libgraviton.gdk.GravitonApi Maven / Gradle / Ivy

package com.github.libgraviton.gdk;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.libgraviton.gdk.api.NoopRequest;
import com.github.libgraviton.gdk.api.Request;
import com.github.libgraviton.gdk.api.endpoint.EndpointManager;
import com.github.libgraviton.gdk.api.endpoint.GeneratedEndpointManager;
import com.github.libgraviton.gdk.api.endpoint.exception.UnableToLoadEndpointAssociationsException;
import com.github.libgraviton.gdk.api.header.HeaderBag;
import com.github.libgraviton.gdk.api.query.rql.Rql;
import com.github.libgraviton.gdk.data.GravitonBase;
import com.github.libgraviton.gdk.exception.SerializationException;
import com.github.libgraviton.gdk.serialization.JsonPatcher;
import com.github.libgraviton.gdk.serialization.mapper.GravitonObjectMapper;
import com.github.libgraviton.gdk.serialization.mapper.RqlObjectMapper;
import com.github.libgraviton.gdk.util.PropertiesLoader;

import java.io.IOException;
import java.util.Properties;

/**
 * This is the base class used for Graviton API calls.
 *
 * @author List of contributors {@literal }
 * @see http://swisscom.ch
 * @version $Id: $Id
 */
public class GravitonApi {

    /**
     * Defines the base setUrl of the Graviton server
     */
    private String baseUrl;

    /**
     * The object mapper used to serialize / deserialize to / from JSON
     */
    private ObjectMapper objectMapper;

    /**
     * The endpoint manager which is used
     */
    private EndpointManager endpointManager;

    private Properties properties;

    private RequestExecutor executor;

    public GravitonApi() {
        setup();
        this.baseUrl = properties.getProperty("graviton.base.url");

        try {
            this.endpointManager = initEndpointManager();
        } catch (UnableToLoadEndpointAssociationsException e) {
            throw new IllegalStateException(e);
        }
    }

    public GravitonApi(String baseUrl, EndpointManager endpointManager) {
        setup();
        this.baseUrl = baseUrl;
        this.endpointManager = endpointManager;
    }

    protected void setup() {
        try {
            this.properties = PropertiesLoader.load();
        } catch (IOException e) {
            throw new IllegalStateException("Unable to load properties files.", e);
        }
        this.objectMapper = new GravitonObjectMapper(properties);
        this.executor = new RequestExecutor(objectMapper);
    }

    protected GeneratedEndpointManager initEndpointManager() throws UnableToLoadEndpointAssociationsException {
        return new GeneratedEndpointManager();
    }

    /**
     * Returns the endpoint manager
     *
     * @return The endpoint manager
     */
    public EndpointManager getEndpointManager() {
        return endpointManager;
    }

    /**
     * Returns the base url
     *
     * @return The base url
     */
    public String getBaseUrl() {
        return baseUrl;
    }

    /**
     * Creates a new executable request builder to build and perform a new request.
     *
     * @return A new executable request builder
     */
    public Request.Builder request() {
        return new Request.Builder(executor)
                .setHeaders(getDefaultHeaders().build());
    }

    public Request.Builder head(String url) {
        return request().setUrl(url).head();
    }

    public Request.Builder head(GravitonBase resource) {
        return head(extractId(resource), resource.getClass());
    }

    public Request.Builder head(String id, Class clazz) {
        return head(endpointManager.getEndpoint(clazz.getName()).getUrl())
                .addParam("id", id);
    }

    public Request.Builder options(String url) {
        return request().setUrl(url).options();
    }

    public Request.Builder options(GravitonBase resource) {
        return options(extractId(resource), resource.getClass());
    }

    public Request.Builder options(String id, Class clazz) {
        return options(endpointManager.getEndpoint(clazz.getName()).getUrl())
                .addParam("id", id);
    }

    public Request.Builder get(String url) {
        return request().setUrl(url).get();
    }

    public Request.Builder get(GravitonBase resource) {
        return get(extractId(resource), resource.getClass());
    }

    public Request.Builder get(String id, Class clazz) {
        return get(endpointManager.getEndpoint(clazz.getName()).getItemUrl())
                .addParam("id", id);
    }

    /**
     * GET request with a URL query. The response will result in a list of items,
     * even if there is only 1 matching item to the query.
     *
     * @param resource payload
     * @return request builder
     */
    public Request.Builder query(GravitonBase resource) {
        return get(endpointManager.getEndpoint(resource.getClass().getName()).getUrl())
                .setQuery(new Rql.Builder().setResource(resource, new RqlObjectMapper(properties)).build());
    }

    public Request.Builder delete(String url) {
        return request().setUrl(url).delete();
    }

    public Request.Builder delete(GravitonBase resource) {
        return delete(extractId(resource), resource.getClass());
    }

    public Request.Builder delete(String id, Class clazz) {
        return delete(endpointManager.getEndpoint(clazz.getName()).getItemUrl())
                .addParam("id", id);
    }

    public Request.Builder put(GravitonBase resource) throws SerializationException {
        return request()
                .setUrl(endpointManager.getEndpoint(resource.getClass().getName()).getItemUrl())
                .addParam("id", extractId(resource))
                .put(serializeResource(resource));
    }

    public Request.Builder patch(GravitonBase resource) throws SerializationException {
        JsonNode jsonNode = getObjectMapper().convertValue(resource, JsonNode.class);
        String data = serializeResource(JsonPatcher.getPatch(resource, jsonNode));

        Request.Builder builder;
        if(data == null || data.isEmpty() || "[]".equals(data)) {
            builder = new NoopRequest.Builder("PATCH body is empty. Nothing changed.");
        } else {
            builder = request();
        }

        return builder
                .setUrl(endpointManager.getEndpoint(resource.getClass().getName()).getItemUrl())
                .addParam("id", extractId(resource))
                .patch(data);
    }

    public Request.Builder post(GravitonBase resource) throws SerializationException {
        return request()
                .setUrl(endpointManager.getEndpoint(resource.getClass().getName()).getUrl())
                .post(serializeResource(resource));
    }

    /**
     * Extracts the id of a given Graviton resource.
     *
     * @param data The Graviton resource.
     *
     * @return The extracted id.
     */
    protected String extractId(GravitonBase data) {
        String id = data.getId();
        return id != null ? id : "";
    }

    protected String serializeResource(Object data) throws SerializationException {
        if (data == null) {
            return "";
        }

        try {
            return getObjectMapper().writeValueAsString(data);
        } catch (JsonProcessingException e) {
            throw new SerializationException(
                    String.format("Cannot serialize '%s' to json.", data.getClass().getName()),
                    e
            );
        }
    }

    public ObjectMapper getObjectMapper() {
        return objectMapper;
    }

    // TODO make it configurable
    protected HeaderBag.Builder getDefaultHeaders() {
        return new HeaderBag.Builder()
                .set("Content-Type", "application/json")
                .set("Accept", "application/json");
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy