Skip to content

Commit 0d97d9d

Browse files
authored
The Scalar code is now broken down into their own implementations (#2016)
* The Scalar code is now broken down into their own implementations for easier maintenance * deprecated non standard ones
1 parent 7fc94c5 commit 0d97d9d

13 files changed

Lines changed: 867 additions & 650 deletions

src/main/java/graphql/Scalars.java

Lines changed: 55 additions & 650 deletions
Large diffs are not rendered by default.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package graphql.scalar;
2+
3+
import graphql.Internal;
4+
5+
@Internal
6+
class CoercingUtil {
7+
static boolean isNumberIsh(Object input) {
8+
return input instanceof Number || input instanceof String;
9+
}
10+
11+
static String typeName(Object input) {
12+
if (input == null) {
13+
return "null";
14+
}
15+
16+
return input.getClass().getSimpleName();
17+
}
18+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package graphql.scalar;
2+
3+
import graphql.Internal;
4+
import graphql.language.FloatValue;
5+
import graphql.language.IntValue;
6+
import graphql.language.StringValue;
7+
import graphql.schema.Coercing;
8+
import graphql.schema.CoercingParseLiteralException;
9+
import graphql.schema.CoercingParseValueException;
10+
import graphql.schema.CoercingSerializeException;
11+
12+
import java.math.BigDecimal;
13+
14+
import static graphql.scalar.CoercingUtil.isNumberIsh;
15+
import static graphql.scalar.CoercingUtil.typeName;
16+
17+
@Internal
18+
public class GraphqlBigDecimalCoercing implements Coercing<BigDecimal, BigDecimal> {
19+
20+
private BigDecimal convertImpl(Object input) {
21+
if (isNumberIsh(input)) {
22+
try {
23+
return new BigDecimal(input.toString());
24+
} catch (NumberFormatException e) {
25+
return null;
26+
}
27+
}
28+
return null;
29+
30+
}
31+
32+
@Override
33+
public BigDecimal serialize(Object input) {
34+
BigDecimal result = convertImpl(input);
35+
if (result == null) {
36+
throw new CoercingSerializeException(
37+
"Expected type 'BigDecimal' but was '" + typeName(input) + "'."
38+
);
39+
}
40+
return result;
41+
}
42+
43+
@Override
44+
public BigDecimal parseValue(Object input) {
45+
BigDecimal result = convertImpl(input);
46+
if (result == null) {
47+
throw new CoercingParseValueException(
48+
"Expected type 'BigDecimal' but was '" + typeName(input) + "'."
49+
);
50+
}
51+
return result;
52+
}
53+
54+
@Override
55+
public BigDecimal parseLiteral(Object input) {
56+
if (input instanceof StringValue) {
57+
try {
58+
return new BigDecimal(((StringValue) input).getValue());
59+
} catch (NumberFormatException e) {
60+
throw new CoercingParseLiteralException(
61+
"Unable to turn AST input into a 'BigDecimal' : '" + input + "'"
62+
);
63+
}
64+
} else if (input instanceof IntValue) {
65+
return new BigDecimal(((IntValue) input).getValue());
66+
} else if (input instanceof FloatValue) {
67+
return ((FloatValue) input).getValue();
68+
}
69+
throw new CoercingParseLiteralException(
70+
"Expected AST type 'IntValue', 'StringValue' or 'FloatValue' but was '" + typeName(input) + "'."
71+
);
72+
}
73+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package graphql.scalar;
2+
3+
import graphql.Internal;
4+
import graphql.language.FloatValue;
5+
import graphql.language.IntValue;
6+
import graphql.language.StringValue;
7+
import graphql.schema.Coercing;
8+
import graphql.schema.CoercingParseLiteralException;
9+
import graphql.schema.CoercingParseValueException;
10+
import graphql.schema.CoercingSerializeException;
11+
12+
import java.math.BigDecimal;
13+
import java.math.BigInteger;
14+
15+
import static graphql.scalar.CoercingUtil.isNumberIsh;
16+
import static graphql.scalar.CoercingUtil.typeName;
17+
18+
@Internal
19+
public class GraphqlBigIntegerCoercing implements Coercing<BigInteger, BigInteger> {
20+
21+
private BigInteger convertImpl(Object input) {
22+
if (isNumberIsh(input)) {
23+
BigDecimal value;
24+
try {
25+
value = new BigDecimal(input.toString());
26+
} catch (NumberFormatException e) {
27+
return null;
28+
}
29+
try {
30+
return value.toBigIntegerExact();
31+
} catch (ArithmeticException e) {
32+
return null;
33+
}
34+
}
35+
return null;
36+
37+
}
38+
39+
@Override
40+
public BigInteger serialize(Object input) {
41+
BigInteger result = convertImpl(input);
42+
if (result == null) {
43+
throw new CoercingSerializeException(
44+
"Expected type 'BigInteger' but was '" + typeName(input) + "'."
45+
);
46+
}
47+
return result;
48+
}
49+
50+
@Override
51+
public BigInteger parseValue(Object input) {
52+
BigInteger result = convertImpl(input);
53+
if (result == null) {
54+
throw new CoercingParseValueException(
55+
"Expected type 'BigInteger' but was '" + typeName(input) + "'."
56+
);
57+
}
58+
return result;
59+
}
60+
61+
@Override
62+
public BigInteger parseLiteral(Object input) {
63+
if (input instanceof StringValue) {
64+
try {
65+
return new BigDecimal(((StringValue) input).getValue()).toBigIntegerExact();
66+
} catch (NumberFormatException | ArithmeticException e) {
67+
throw new CoercingParseLiteralException(
68+
"Unable to turn AST input into a 'BigInteger' : '" + input + "'"
69+
);
70+
}
71+
} else if (input instanceof IntValue) {
72+
return ((IntValue) input).getValue();
73+
} else if (input instanceof FloatValue) {
74+
try {
75+
return ((FloatValue) input).getValue().toBigIntegerExact();
76+
} catch (ArithmeticException e) {
77+
throw new CoercingParseLiteralException(
78+
"Unable to turn AST input into a 'BigInteger' : '" + input + "'"
79+
);
80+
}
81+
}
82+
throw new CoercingParseLiteralException(
83+
"Expected AST type 'IntValue', 'StringValue' or 'FloatValue' but was '" + typeName(input) + "'."
84+
);
85+
}
86+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package graphql.scalar;
2+
3+
import graphql.Internal;
4+
import graphql.language.BooleanValue;
5+
import graphql.schema.Coercing;
6+
import graphql.schema.CoercingParseLiteralException;
7+
import graphql.schema.CoercingParseValueException;
8+
import graphql.schema.CoercingSerializeException;
9+
10+
import java.math.BigDecimal;
11+
12+
import static graphql.Assert.assertShouldNeverHappen;
13+
import static graphql.scalar.CoercingUtil.isNumberIsh;
14+
import static graphql.scalar.CoercingUtil.typeName;
15+
16+
@Internal
17+
public class GraphqlBooleanCoercing implements Coercing<Boolean, Boolean> {
18+
19+
private Boolean convertImpl(Object input) {
20+
if (input instanceof Boolean) {
21+
return (Boolean) input;
22+
} else if (input instanceof String) {
23+
return Boolean.parseBoolean((String) input);
24+
} else if (isNumberIsh(input)) {
25+
BigDecimal value;
26+
try {
27+
value = new BigDecimal(input.toString());
28+
} catch (NumberFormatException e) {
29+
// this should never happen because String is handled above
30+
return assertShouldNeverHappen();
31+
}
32+
return value.compareTo(BigDecimal.ZERO) != 0;
33+
} else {
34+
return null;
35+
}
36+
37+
}
38+
39+
@Override
40+
public Boolean serialize(Object input) {
41+
Boolean result = convertImpl(input);
42+
if (result == null) {
43+
throw new CoercingSerializeException(
44+
"Expected type 'Boolean' but was '" + typeName(input) + "'."
45+
);
46+
}
47+
return result;
48+
}
49+
50+
@Override
51+
public Boolean parseValue(Object input) {
52+
Boolean result = convertImpl(input);
53+
if (result == null) {
54+
throw new CoercingParseValueException(
55+
"Expected type 'Boolean' but was '" + typeName(input) + "'."
56+
);
57+
}
58+
return result;
59+
}
60+
61+
@Override
62+
public Boolean parseLiteral(Object input) {
63+
if (!(input instanceof BooleanValue)) {
64+
throw new CoercingParseLiteralException(
65+
"Expected AST type 'BooleanValue' but was '" + typeName(input) + "'."
66+
);
67+
}
68+
return ((BooleanValue) input).isValue();
69+
}
70+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package graphql.scalar;
2+
3+
import graphql.Internal;
4+
import graphql.language.IntValue;
5+
import graphql.schema.Coercing;
6+
import graphql.schema.CoercingParseLiteralException;
7+
import graphql.schema.CoercingParseValueException;
8+
import graphql.schema.CoercingSerializeException;
9+
10+
import java.math.BigDecimal;
11+
import java.math.BigInteger;
12+
13+
import static graphql.scalar.CoercingUtil.isNumberIsh;
14+
import static graphql.scalar.CoercingUtil.typeName;
15+
16+
@Internal
17+
public class GraphqlByteCoercing implements Coercing<Byte, Byte> {
18+
19+
private static final BigInteger BYTE_MAX = BigInteger.valueOf(Byte.MAX_VALUE);
20+
private static final BigInteger BYTE_MIN = BigInteger.valueOf(Byte.MIN_VALUE);
21+
22+
private Byte convertImpl(Object input) {
23+
if (input instanceof Byte) {
24+
return (Byte) input;
25+
} else if (isNumberIsh(input)) {
26+
BigDecimal value;
27+
try {
28+
value = new BigDecimal(input.toString());
29+
} catch (NumberFormatException e) {
30+
return null;
31+
}
32+
try {
33+
return value.byteValueExact();
34+
} catch (ArithmeticException e) {
35+
return null;
36+
}
37+
} else {
38+
return null;
39+
}
40+
41+
}
42+
43+
@Override
44+
public Byte serialize(Object input) {
45+
Byte result = convertImpl(input);
46+
if (result == null) {
47+
throw new CoercingSerializeException(
48+
"Expected type 'Byte' but was '" + typeName(input) + "'."
49+
);
50+
}
51+
return result;
52+
}
53+
54+
@Override
55+
public Byte parseValue(Object input) {
56+
Byte result = convertImpl(input);
57+
if (result == null) {
58+
throw new CoercingParseValueException(
59+
"Expected type 'Byte' but was '" + typeName(input) + "'."
60+
);
61+
}
62+
return result;
63+
}
64+
65+
@Override
66+
public Byte parseLiteral(Object input) {
67+
if (!(input instanceof IntValue)) {
68+
throw new CoercingParseLiteralException(
69+
"Expected AST type 'IntValue' but was '" + typeName(input) + "'."
70+
);
71+
}
72+
BigInteger value = ((IntValue) input).getValue();
73+
if (value.compareTo(BYTE_MIN) < 0 || value.compareTo(BYTE_MAX) > 0) {
74+
throw new CoercingParseLiteralException(
75+
"Expected value to be in the Byte range but it was '" + value.toString() + "'"
76+
);
77+
}
78+
return value.byteValue();
79+
}
80+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package graphql.scalar;
2+
3+
import graphql.Internal;
4+
import graphql.language.StringValue;
5+
import graphql.schema.Coercing;
6+
import graphql.schema.CoercingParseLiteralException;
7+
import graphql.schema.CoercingParseValueException;
8+
import graphql.schema.CoercingSerializeException;
9+
10+
import static graphql.scalar.CoercingUtil.typeName;
11+
12+
@Internal
13+
public class GraphqlCharCoercing implements Coercing<Character, Character> {
14+
15+
private Character convertImpl(Object input) {
16+
if (input instanceof String && ((String) input).length() == 1) {
17+
return ((String) input).charAt(0);
18+
} else if (input instanceof Character) {
19+
return (Character) input;
20+
} else {
21+
return null;
22+
}
23+
24+
}
25+
26+
@Override
27+
public Character serialize(Object input) {
28+
Character result = convertImpl(input);
29+
if (result == null) {
30+
throw new CoercingSerializeException(
31+
"Expected type 'Char' but was '" + typeName(input) + "'."
32+
);
33+
}
34+
return result;
35+
}
36+
37+
@Override
38+
public Character parseValue(Object input) {
39+
Character result = convertImpl(input);
40+
if (result == null) {
41+
throw new CoercingParseValueException(
42+
"Expected type 'Char' but was '" + typeName(input) + "'."
43+
);
44+
}
45+
return result;
46+
}
47+
48+
@Override
49+
public Character parseLiteral(Object input) {
50+
if (!(input instanceof StringValue)) {
51+
throw new CoercingParseLiteralException(
52+
"Expected AST type 'StringValue' but was '" + typeName(input) + "'."
53+
);
54+
}
55+
String value = ((StringValue) input).getValue();
56+
if (value.length() != 1) {
57+
throw new CoercingParseLiteralException(
58+
"Empty 'StringValue' provided."
59+
);
60+
}
61+
return value.charAt(0);
62+
}
63+
}

0 commit comments

Comments
 (0)