Skip to content

Commit

Permalink
🐛 Implement valueToLiteral() in GraphQL BSON scalar classes
Browse files Browse the repository at this point in the history
  • Loading branch information
ujibang committed Nov 7, 2023
1 parent eb59f7b commit 0e75a10
Show file tree
Hide file tree
Showing 11 changed files with 290 additions and 150 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,46 @@
*/
package org.restheart.graphql.scalars.bsonCoercing;

import graphql.schema.Coercing;
import graphql.schema.CoercingSerializeException;
import java.util.Locale;

import org.bson.BsonBoolean;
import org.bson.BsonNull;
import static org.restheart.graphql.scalars.bsonCoercing.CoercingUtils.typeName;

@SuppressWarnings({"deprecated", "deprecation"})
import graphql.GraphQLContext;
import graphql.execution.CoercedVariables;
import graphql.language.Value;
import graphql.schema.Coercing;
import graphql.schema.CoercingParseLiteralException;
import graphql.schema.CoercingParseValueException;
import graphql.schema.CoercingSerializeException;

public class GraphQLBsonBooleanCoercing implements Coercing<Boolean, Boolean> {
@Override
public Boolean serialize(Object dataFetcherResult) throws CoercingSerializeException {
if(dataFetcherResult == null || dataFetcherResult instanceof BsonNull) {
public Boolean serialize(Object input, GraphQLContext graphQLContext, Locale locale) throws CoercingSerializeException {
if(input == null || input instanceof BsonNull) {
return null;
} else if (dataFetcherResult instanceof BsonBoolean bsonBoolean) {
} else if (input instanceof BsonBoolean bsonBoolean) {
return bsonBoolean.getValue();
} else if (dataFetcherResult instanceof Boolean value) {
} else if (input instanceof Boolean value) {
return value;
}else {
throw new CoercingSerializeException("Expected types 'Boolean' or 'BsonBoolean' but was '" + typeName(dataFetcherResult) + "'.");
} else {
throw new CoercingSerializeException("Expected types 'Boolean' or 'BsonBoolean' but was '" + typeName(input) + "'.");
}
}

@Override
public Boolean parseValue(Object input) {
public Boolean parseValue(Object input, GraphQLContext graphQLContext, Locale locale) throws CoercingParseValueException {
return (Boolean) CoercingUtils.builtInCoercing.get("Boolean").parseValue(input);
}

@Override
public Boolean parseLiteral(Object AST) {
return (Boolean) CoercingUtils.builtInCoercing.get("Boolean").parseLiteral(AST);
public Boolean parseLiteral(Value<?> input, CoercedVariables variables, GraphQLContext graphQLContext, Locale locale) throws CoercingParseLiteralException {
return (Boolean) CoercingUtils.builtInCoercing.get("Boolean").parseLiteral(input);
}

@Override
public Value<?> valueToLiteral(Object input) {
return CoercingUtils.builtInCoercing.get("Boolean").valueToLiteral(input);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,35 +20,39 @@
*/
package org.restheart.graphql.scalars.bsonCoercing;

import graphql.language.StringValue;
import graphql.schema.Coercing;
import graphql.schema.CoercingParseLiteralException;
import graphql.schema.CoercingParseValueException;
import graphql.schema.CoercingSerializeException;
import org.bson.BsonDateTime;
import org.bson.BsonNull;

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Locale;

import org.bson.BsonDateTime;
import org.bson.BsonNull;
import static org.restheart.graphql.scalars.bsonCoercing.CoercingUtils.typeName;
import org.restheart.utils.BsonUtils;

import graphql.GraphQLContext;
import graphql.execution.CoercedVariables;
import graphql.language.StringValue;
import graphql.language.Value;
import graphql.schema.Coercing;
import graphql.schema.CoercingParseLiteralException;
import graphql.schema.CoercingParseValueException;
import graphql.schema.CoercingSerializeException;

@SuppressWarnings("deprecation")
public class GraphQLBsonDateCoercing implements Coercing<BsonDateTime, BsonDateTime> {
@Override
public BsonDateTime serialize(Object dataFetcherResult) throws CoercingSerializeException {
if(dataFetcherResult == null || dataFetcherResult instanceof BsonNull) {
public BsonDateTime serialize(Object input, GraphQLContext graphQLContext, Locale locale) throws CoercingSerializeException {
if(input == null || input instanceof BsonNull) {
return null;
} else if (dataFetcherResult instanceof BsonDateTime bsonDateTime){
} else if (input instanceof BsonDateTime bsonDateTime){
return bsonDateTime;
} else {
throw new CoercingSerializeException("Expected type 'BsonDateTime' but was '" + typeName(dataFetcherResult) +"'.");
throw new CoercingSerializeException("Expected type 'BsonDateTime' but was '" + typeName(input) +"'.");
}
}

@Override
public BsonDateTime parseValue(Object input) throws CoercingParseValueException {
public BsonDateTime parseValue(Object input, GraphQLContext graphQLContext, Locale locale) throws CoercingParseValueException {
var possibleDate = convertImpl(input);
if (possibleDate == null){
throw new CoercingParseValueException("Expected type 'Long' or 'String' (with a valid OffsetDateTime) but was '" + typeName(input) +"'.");
Expand All @@ -58,8 +62,8 @@ public BsonDateTime parseValue(Object input) throws CoercingParseValueException
}

@Override
public BsonDateTime parseLiteral(Object AST) throws CoercingParseLiteralException {
if (AST instanceof StringValue stringValue) {
public BsonDateTime parseLiteral(Value<?> input, CoercedVariables variables, GraphQLContext graphQLContext, Locale locale) throws CoercingParseLiteralException {
if (input instanceof StringValue stringValue) {
var possibleDate = stringValue.getValue();
try {
var ofsDate = OffsetDateTime.parse(possibleDate, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
Expand All @@ -72,7 +76,7 @@ public BsonDateTime parseLiteral(Object AST) throws CoercingParseLiteralExceptio
}
}
} else {
throw new CoercingParseLiteralException("Expected AST type 'StringValue' but was '" + typeName(AST) + "'.");
throw new CoercingParseLiteralException("Expected input type 'StringValue' but was '" + typeName(input) + "'.");
}
}

Expand All @@ -84,8 +88,8 @@ private Long convertImpl(Object input){
var ofsDate = OffsetDateTime.parse(string, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
return ofsDate.toInstant().toEpochMilli();
} catch (DateTimeParseException dtpe){
try{
return Long.parseLong(string);
try {
return Long.valueOf(string);
} catch (NumberFormatException nfe) {
return null;
}
Expand All @@ -96,4 +100,11 @@ private Long convertImpl(Object input){

return null;
}

@Override
public Value<?> valueToLiteral(Object input) {
var value = serialize(input);
var s = BsonUtils.toJson(value);
return StringValue.newStringValue(s).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,38 +20,43 @@
*/
package org.restheart.graphql.scalars.bsonCoercing;

import java.util.Locale;

import org.bson.BsonDecimal128;
import org.bson.BsonNull;
import org.bson.BsonValue;
import org.bson.types.Decimal128;
import static org.restheart.graphql.scalars.bsonCoercing.CoercingUtils.typeName;
import org.restheart.utils.BsonUtils;

import graphql.GraphQLContext;
import graphql.execution.CoercedVariables;
import graphql.language.FloatValue;
import graphql.language.IntValue;
import graphql.language.StringValue;
import graphql.language.Value;
import graphql.schema.Coercing;
import graphql.schema.CoercingParseLiteralException;
import graphql.schema.CoercingParseValueException;
import graphql.schema.CoercingSerializeException;
import org.bson.BsonDecimal128;
import org.bson.BsonNull;
import org.bson.BsonValue;
import org.bson.types.Decimal128;

import static org.restheart.graphql.scalars.bsonCoercing.CoercingUtils.typeName;

@SuppressWarnings("deprecation")
public class GraphQLBsonDecimal128Coercing implements Coercing<BsonDecimal128, Decimal128> {
@Override
public Decimal128 serialize(Object dataFetcherResult) throws CoercingSerializeException {
if(dataFetcherResult == null || dataFetcherResult instanceof BsonNull) {
public Decimal128 serialize(Object input, GraphQLContext graphQLContext, Locale locale) throws CoercingSerializeException {
if(input == null || input instanceof BsonNull) {
return null;
}

var possibleDecimal = convertImpl(dataFetcherResult);
var possibleDecimal = convertImpl(input);
if (possibleDecimal == null){
throw new CoercingSerializeException("Expected type 'Decimal128' but was '" + typeName(dataFetcherResult) +"'.");
throw new CoercingSerializeException("Expected type 'Decimal128' but was '" + typeName(input) +"'.");
} else {
return possibleDecimal;
}
}

@Override
public BsonDecimal128 parseValue(Object input) throws CoercingParseValueException {
public BsonDecimal128 parseValue(Object input, GraphQLContext graphQLContext, Locale locale) throws CoercingParseValueException {
var possibleDecimal = convertImpl(input);
if (possibleDecimal == null){
throw new CoercingParseValueException("Expected type 'Decimal128' but was '" + typeName(input) +"'.");
Expand All @@ -61,7 +66,7 @@ public BsonDecimal128 parseValue(Object input) throws CoercingParseValueExceptio
}

@Override
public BsonDecimal128 parseLiteral(Object input) throws CoercingParseLiteralException {
public BsonDecimal128 parseLiteral(Value<?> input, CoercedVariables variables, GraphQLContext graphQLContext, Locale locale) throws CoercingParseLiteralException {
if (input instanceof StringValue || input instanceof IntValue || input instanceof FloatValue){
String value = null;
if (input instanceof IntValue intValue){
Expand Down Expand Up @@ -98,4 +103,11 @@ private Decimal128 convertImpl(Object obj){
private boolean isANumber(Object input) {
return input instanceof Number || input instanceof String;
}

@Override
public Value<?> valueToLiteral(Object input) {
var value = parseValue(input);
var s = BsonUtils.toJson(value);
return StringValue.newStringValue(s).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,35 +19,54 @@
* =========================LICENSE_END==================================
*/
package org.restheart.graphql.scalars.bsonCoercing;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;

import org.bson.BsonArray;
import org.bson.BsonBoolean;
import org.bson.BsonDocument;
import org.bson.BsonDouble;
import org.bson.BsonInt32;
import org.bson.BsonNull;
import org.bson.BsonString;
import org.bson.BsonValue;
import static org.restheart.graphql.scalars.bsonCoercing.CoercingUtils.typeName;
import org.restheart.utils.BsonUtils;

import graphql.Assert;
import graphql.language.*;
import graphql.GraphQLContext;
import graphql.execution.CoercedVariables;
import graphql.language.ArrayValue;
import graphql.language.BooleanValue;
import graphql.language.EnumValue;
import graphql.language.FloatValue;
import graphql.language.IntValue;
import graphql.language.NullValue;
import graphql.language.ObjectValue;
import graphql.language.StringValue;
import graphql.language.Value;
import graphql.language.VariableReference;
import graphql.schema.Coercing;
import graphql.schema.CoercingParseLiteralException;
import graphql.schema.CoercingParseValueException;
import graphql.schema.CoercingSerializeException;
import org.bson.*;
import org.restheart.utils.BsonUtils;

import java.util.*;

import static org.restheart.graphql.scalars.bsonCoercing.CoercingUtils.typeName;

@SuppressWarnings("deprecation")
public class GraphQLBsonDocumentCoercing implements Coercing<BsonDocument, BsonDocument> {
@Override
public BsonDocument serialize(Object dataFetcherResult) throws CoercingSerializeException {
if(dataFetcherResult == null || dataFetcherResult instanceof BsonNull) {
public BsonDocument serialize(Object input, GraphQLContext graphQLContext, Locale locale) throws CoercingSerializeException {
if(input == null || input instanceof BsonNull) {
return null;
} else if(dataFetcherResult instanceof BsonDocument){
return (BsonDocument) dataFetcherResult;
} else if(input instanceof BsonDocument){
return (BsonDocument) input;
} else {
throw new CoercingSerializeException("Expected type 'BsonDocument' but was '" + typeName(dataFetcherResult) +"'.");
throw new CoercingSerializeException("Expected type 'BsonDocument' but was '" + typeName(input) +"'.");
}
}

@Override
@SuppressWarnings("unchecked")
public BsonDocument parseValue(Object input) throws CoercingParseValueException {
public BsonDocument parseValue(Object input, GraphQLContext graphQLContext, Locale locale) throws CoercingParseValueException {
if (input instanceof Map<?,?> map) {
return BsonUtils.toBsonDocument((Map<String,Object>) map);
} else {
Expand All @@ -56,8 +75,8 @@ public BsonDocument parseValue(Object input) throws CoercingParseValueException
}

@Override
public BsonDocument parseLiteral(Object AST) throws CoercingParseLiteralException {
if (AST instanceof ObjectValue objectValue) {
public BsonDocument parseLiteral(Value<?> input, CoercedVariables variables, GraphQLContext graphQLContext, Locale locale) throws CoercingParseLiteralException {
if (input instanceof ObjectValue objectValue) {
var fields = objectValue.getObjectFields();
var parsedValues = new BsonDocument();
fields.forEach(field ->{
Expand All @@ -66,13 +85,13 @@ public BsonDocument parseLiteral(Object AST) throws CoercingParseLiteralExceptio
});
return parsedValues;
} else {
throw new CoercingParseLiteralException("Expected AST type 'Value' but was '" + typeName(AST) + "'.");
throw new CoercingParseLiteralException("Expected input type 'Value' but was '" + typeName(input) + "'.");
}
}

public BsonValue parseObjectField(Object input, Map<String, Object> variables) throws CoercingParseLiteralException {
if(!(input instanceof Value)) {
throw new CoercingParseLiteralException("Expected AST type 'Value' but was '" + typeName(input) + "'.");
throw new CoercingParseLiteralException("Expected input type 'Value' but was '" + typeName(input) + "'.");
} else if (input instanceof StringValue stringValue) {
return new BsonString(stringValue.getValue());
} else if (input instanceof IntValue intValue) {
Expand Down Expand Up @@ -105,4 +124,11 @@ public BsonValue parseObjectField(Object input, Map<String, Object> variables) t
return Assert.assertShouldNeverHappen("All types have been covered");
}
}

@Override
public Value<?> valueToLiteral(Object input) {
var value = parseValue(input);
var s = BsonUtils.toJson(value);
return StringValue.newStringValue(s).build();
}
}
Loading

0 comments on commit 0e75a10

Please sign in to comment.