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

io.smallrye.graphql.client.impl.ResponseImpl Maven / Gradle / Ivy

The newest version!
package io.smallrye.graphql.client.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jakarta.json.JsonArray;
import jakarta.json.JsonNumber;
import jakarta.json.JsonObject;
import jakarta.json.JsonString;
import jakarta.json.JsonValue;

import io.smallrye.graphql.client.GraphQLClientException;
import io.smallrye.graphql.client.GraphQLError;
import io.smallrye.graphql.client.Response;
import io.smallrye.graphql.client.impl.typesafe.json.JsonReader;
import io.smallrye.graphql.client.impl.typesafe.reflection.TypeInfo;

public class ResponseImpl implements Response {

    public static final String STATUS_CODE = "";
    public static final String STATUS_MESSAGE = "";

    private final JsonObject data;
    private final List errors;
    private final JsonObject extensions;
    private final Map> metadata;

    public ResponseImpl(JsonObject data, List errors, Map> headers) {
        this(data, errors, null, headers);
    }

    public ResponseImpl(JsonObject data,
            List errors,
            JsonObject extensions,
            Map> headers) {
        this.data = data;
        this.errors = errors;
        this.extensions = extensions;
        this.metadata = Collections.unmodifiableMap(headers != null ? headers : Collections.emptyMap());
    }

    public ResponseImpl(JsonObject data, List errors, Map> headers,
            Integer statusCode, String statusMessage) {
        this(data, errors, null, headers, statusCode, statusMessage);
    }

    public ResponseImpl(JsonObject data, List errors, JsonObject extensions,
            Map> headers,
            Integer statusCode, String statusMessage) {
        this.data = data;
        this.errors = errors;
        this.extensions = extensions;
        Map> meta = new HashMap<>();
        if (headers != null) {
            meta.putAll(headers);
        }
        if (statusCode != null) {
            meta.put(STATUS_CODE, List.of(String.valueOf(statusCode)));
        }
        if (statusMessage != null) {
            meta.put(STATUS_MESSAGE, List.of(statusMessage));
        }
        this.metadata = Collections.unmodifiableMap(meta);
    }

    @Override
    public  T getObject(Class dataType, String rootField) {
        if (data == null || data.equals(JsonValue.NULL) || data.keySet().isEmpty()) {
            throw SmallRyeGraphQLClientMessages.msg.noDataInResponse();
        }
        JsonValue value = data.get(rootField);
        if (value == null) {
            // field is missing in the response completely
            throw SmallRyeGraphQLClientMessages.msg.fieldNotFoundInResponse(rootField, data.keySet());
        }
        if (value.getValueType().equals(JsonValue.ValueType.NULL)) {
            // field is present in the response, but is null
            return null;
        }
        if (value.getValueType().equals(JsonValue.ValueType.OBJECT)) {
            return (T) JsonReader.readJson(rootField, TypeInfo.of(dataType), value.asJsonObject(), null);
        } else if (value.getValueType().equals(JsonValue.ValueType.ARRAY)) {
            throw SmallRyeGraphQLClientMessages.msg.responseContainsArray(rootField);
        } else {
            Object scalarValue = getScalarValue(value);
            if (scalarValue != null) {
                return (T) scalarValue;
            }
            throw SmallRyeGraphQLClientMessages.msg.unexpectedValueInResponse(rootField, value.getValueType().toString());
        }
    }

    @Override
    public  List getList(Class dataType, String rootField) {
        if (data == null || data.equals(JsonValue.NULL) || data.keySet().isEmpty()) {
            throw SmallRyeGraphQLClientMessages.msg.noDataInResponse();
        }
        JsonValue item = data.get(rootField);
        if (item == null) {
            throw SmallRyeGraphQLClientMessages.msg.fieldNotFoundInResponse(rootField, data.keySet());
        }
        if (item.getValueType().equals(JsonValue.ValueType.NULL)) {
            // field is present in the response, but is null
            return null;
        }
        if (item instanceof JsonObject) {
            throw SmallRyeGraphQLClientMessages.msg.responseContainsSingleObject(rootField);
        }
        if (item instanceof JsonArray) {
            List result = new ArrayList<>();
            JsonArray jsonArray = (JsonArray) item;
            TypeInfo type = TypeInfo.of(dataType);
            jsonArray.forEach(o -> {
                if (o.getValueType().equals(JsonValue.ValueType.OBJECT)) {
                    result.add((T) JsonReader.readJson(rootField, type, o, null));
                } else {
                    result.add((T) getScalarValue(o));
                }
            });
            return result;
        }
        throw SmallRyeGraphQLClientMessages.msg.unexpectedValueInResponse(rootField, item.getValueType().toString());
    }

    private Object getScalarValue(JsonValue value) {
        switch (value.getValueType()) {
            case NUMBER:
                return ((JsonNumber) value).longValue();
            case STRING:
                return ((JsonString) value).getString();
            case TRUE:
                return true;
            case FALSE:
                return false;
            default:
                return null;
        }
    }

    @Override
    public JsonObject getData() {
        return data;
    }

    @Override
    public List getErrors() {
        return errors;
    }

    @Override
    public JsonObject getExtensions() {
        return extensions;
    }

    /**
     * If there are application errors inside this response, this method converts these errors into a `GraphQLClientException`
     * and throws it. If there are no errors, then this method does nothing.
     */
    // This is currently only in the implementation, if this is deemed useful we might move it up to the `Response` interface
    public void throwExceptionIfErrors() {
        if (!errors.isEmpty()) {
            throw new GraphQLClientException("Errors from service", errors);
        }
    }

    @Override
    public boolean hasData() {
        return data != null;
    }

    @Override
    public boolean hasError() {
        return errors != null;
    }

    @Override
    public boolean hasExtensions() {
        return extensions != null && !extensions.isEmpty();
    }

    @Override
    public String toString() {
        return "ResponseImpl{" +
                "data=" + data +
                ", errors=" + errors +
                ", extensions=" + extensions +
                '}';
    }

    public Map> getHeaders() {
        return metadata;
    }

    @Override
    public Map> getTransportMeta() {
        return metadata;
    }

    /**
     * Returns the HTTP status code. Returns null if no HTTP status code is known, for example
     * when this response corresponds to an operation executed over a websocket rather than a simple HTTP exchange.
     */
    public Integer getStatusCode() {
        if (metadata.containsKey(STATUS_CODE)) {
            return Integer.valueOf(metadata.get(STATUS_CODE).get(0));
        } else {
            return null;
        }
    }

    /**
     * Returns the HTTP status message. Returns null if no HTTP status message is known, for example
     * when this response corresponds to an operation executed over a websocket rather than a simple HTTP exchange.
     */
    public String getStatusMessage() {
        if (metadata.containsKey(STATUS_MESSAGE)) {
            return metadata.get(STATUS_MESSAGE).get(0);
        } else {
            return null;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy