Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* Copyright 2015 Shopify
* Copyright 2019 Adobe
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software
* is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.shopify.graphql.support;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.function.BiFunction;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
/**
* Created by dylansmith on 2015-11-23.
*/
public abstract class AbstractResponse implements Serializable {
public final HashMap responseData = new HashMap<>();
public final HashMap optimisticData = new HashMap<>();
private String aliasSuffix = null;
@SuppressWarnings("unchecked")
public T withAlias(String aliasSuffix) {
if (this.aliasSuffix != null) {
throw new IllegalStateException("Can only define a single alias for a field");
}
if (aliasSuffix == null || aliasSuffix.isEmpty()) {
throw new IllegalArgumentException("Can't specify an empty alias");
}
if (aliasSuffix.contains(AbstractQuery.ALIAS_SUFFIX_SEPARATOR)) {
throw new IllegalArgumentException("Alias must not contain __");
}
this.aliasSuffix = aliasSuffix;
return (T) this;
}
/**
* Gets a field as a raw object.
*
* @param field The name of the field.
* @return The raw object.
*/
public Object get(String field) {
String key = getKey(field);
if (optimisticData.containsKey(key)) {
return optimisticData.get(key);
}
return responseData.get(key);
}
@FunctionalInterface
private interface BiFunctionWithException {
R apply(T t, U u) throws SchemaViolationError;
}
private BiFunction converterWrapper(BiFunctionWithException converter) {
return (t, u) -> {
try {
return converter.apply(t, u);
} catch (Exception e) {
throw new RuntimeException(e);
}
};
}
private R getAs(String field, BiFunction converter) {
String key = getKey(field);
if (optimisticData.containsKey(key)) {
return converter.apply((JsonElement) optimisticData.get(key), key);
}
return converter.apply((JsonElement) responseData.get(key), key);
}
/**
* Tries to deserialise and return the given JSON field as a String. The field itself is expected
* to be stored in the object data as a {@link JsonElement}, which is the case for custom simple fields.
*
* @param field The name of the field.
* @return The value of the field.
* @throws SchemaViolationError If the field cannot be converted to a String.
*/
public String getAsString(String field) throws SchemaViolationError {
BiFunction converter = converterWrapper(this::jsonAsString);
return getAs(field, converter);
}
/**
* Tries to deserialise and return the given JSON field as an Integer. The field itself is expected
* to be stored in the object data as a {@link JsonElement}, which is the case for custom simple fields.
*
* @param field The name of the field.
* @return The value of the field.
* @throws SchemaViolationError If the field cannot be converted to an Integer.
*/
public Integer getAsInteger(String field) throws SchemaViolationError {
BiFunction converter = converterWrapper(this::jsonAsInteger);
return getAs(field, converter);
}
/**
* Tries to deserialise and return the given JSON field as a Double. The field itself is expected
* to be stored in the object data as a {@link JsonElement}, which is the case for custom simple fields.
*
* @param field The name of the field.
* @return The value of the field.
* @throws SchemaViolationError If the field cannot be converted to a Double.
*/
public Double getAsDouble(String field) throws SchemaViolationError {
BiFunction converter = converterWrapper(this::jsonAsDouble);
return getAs(field, converter);
}
/**
* Tries to deserialise and return the given JSON field as a Boolean. The field itself is expected
* to be stored in the object data as a {@link JsonElement}, which is the case for custom simple fields.
*
* @param field The name of the field.
* @return The value of the field.
* @throws SchemaViolationError If the field cannot be converted to a Boolean.
*/
public Boolean getAsBoolean(String field) throws SchemaViolationError {
BiFunction converter = converterWrapper(this::jsonAsBoolean);
return getAs(field, converter);
}
/**
* Tries to deserialise and return the given JSON field as an Array. The field itself is expected
* to be stored in the object data as a {@link JsonElement}, which is the case for custom simple fields.
*
* @param field The name of the field.
* @return The value of the field.
* @throws SchemaViolationError If the field cannot be converted to an Array.
*/
public JsonArray getAsArray(String field) throws SchemaViolationError {
BiFunction converter = converterWrapper(this::jsonAsArray);
return getAs(field, converter);
}
/**
* Tries to read a custom field from the GraphQL JSON response. The method throws a schema violation
* exception if the field name does not contain the _custom_ alias suffix added by the library,
* which would indicate that the field does not belong to the GraphQL Schema and was not explicitly requested
* as a custom field.
*
* @param fieldName The field name.
* @param element The JSON element parsed by the JSON deserialiser.
* @throws SchemaViolationError If the field name does not contain the _custom_ suffix.
*/
protected void readCustomField(String fieldName, JsonElement element) throws SchemaViolationError {
if (!fieldName.endsWith(AbstractQuery.CUSTOM_FIELD_LABEL)) {
throw new SchemaViolationError(this, fieldName, element);
}
int end = fieldName.lastIndexOf(AbstractQuery.CUSTOM_FIELD_LABEL);
responseData.put(fieldName.substring(0, end), element);
}
protected String getFieldName(String key) {
int i = key.lastIndexOf(AbstractQuery.ALIAS_SUFFIX_SEPARATOR);
if (i > 1) {
key = key.substring(0, i);
}
return key;
}
protected String getKey(String field) {
if (aliasSuffix != null) {
field += AbstractQuery.ALIAS_SUFFIX_SEPARATOR + aliasSuffix;
aliasSuffix = null;
}
return field;
}
protected String jsonAsString(JsonElement element, String field) throws SchemaViolationError {
if (!element.isJsonPrimitive() || !element.getAsJsonPrimitive().isString()) {
throw new SchemaViolationError(this, field, element);
}
return element.getAsJsonPrimitive().getAsString();
}
protected Integer jsonAsInteger(JsonElement element, String field) throws SchemaViolationError {
if (!element.isJsonPrimitive() || (!element.getAsJsonPrimitive().isNumber() && !element.getAsJsonPrimitive().isString())) {
throw new SchemaViolationError(this, field, element);
}
try {
return element.getAsJsonPrimitive().getAsInt();
} catch (NumberFormatException exc) {
throw new SchemaViolationError(this, field, element);
}
}
protected Double jsonAsDouble(JsonElement element, String field) throws SchemaViolationError {
if (!element.isJsonPrimitive() || (!element.getAsJsonPrimitive().isNumber() && !element.getAsJsonPrimitive().isString())) {
throw new SchemaViolationError(this, field, element);
}
try {
return element.getAsJsonPrimitive().getAsDouble();
} catch (NumberFormatException exc) {
throw new SchemaViolationError(this, field, element);
}
}
protected Boolean jsonAsBoolean(JsonElement element, String field) throws SchemaViolationError {
if (!element.isJsonPrimitive() || (!element.getAsJsonPrimitive().isBoolean() && !element.getAsJsonPrimitive().isString())) {
throw new SchemaViolationError(this, field, element);
}
return element.getAsJsonPrimitive().getAsBoolean();
}
protected JsonObject jsonAsObject(JsonElement element, String field) throws SchemaViolationError {
if (!element.isJsonObject()) {
throw new SchemaViolationError(this, field, element);
}
return element.getAsJsonObject();
}
protected JsonArray jsonAsArray(JsonElement element, String field) throws SchemaViolationError {
if (!element.isJsonArray()) {
throw new SchemaViolationError(this, field, element);
}
return element.getAsJsonArray();
}
public List collectNodes() {
final ArrayList children = new ArrayList<>();
collectNodes(this, children);
return children;
}
private static void collectNodes(Object o, List collection) {
if (o instanceof AbstractResponse) {
final AbstractResponse response = (AbstractResponse) o;
if (response instanceof Node) {
collection.add((Node) response);
}
for (Object key : response.responseData.keySet()) {
collectNodes(response.get((String) key), collection);
}
} else if (o instanceof List) {
for (Object element : (List) o) {
collectNodes(element, collection);
}
}
}
public abstract boolean unwrapsToObject(String key);
}