Skip to content

Commit d7768dc

Browse files
Ravi KancherlaRavi Kancherla
Ravi Kancherla
authored and
Ravi Kancherla
committed
Scalar type for UUID
1 parent 508817d commit d7768dc

File tree

5 files changed

+195
-0
lines changed

5 files changed

+195
-0
lines changed

readme.md

+5
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ And example query might look like:
7373
}
7474

7575
```
76+
## ID Scalars
77+
78+
* `UUID`
79+
* A universally unique identifier scalar that accepts uuid values like `2423f0a0-3b81-4115-a189-18df8b35e8fc` and produces
80+
`java.util.UUID` type at runtime
7681

7782
## Object / JSON Scalars
7883

src/main/java/graphql/scalars/ExtendedScalars.java

+9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import graphql.scalars.datetime.DateScalar;
66
import graphql.scalars.datetime.DateTimeScalar;
77
import graphql.scalars.datetime.TimeScalar;
8+
import graphql.scalars.id.UUIDScalar;
89
import graphql.scalars.numeric.NegativeFloatScalar;
910
import graphql.scalars.numeric.NegativeIntScalar;
1011
import graphql.scalars.numeric.NonNegativeFloatScalar;
@@ -20,6 +21,8 @@
2021
import graphql.scalars.locale.LocaleScalar;
2122
import graphql.schema.GraphQLScalarType;
2223

24+
import java.util.UUID;
25+
2326
/**
2427
* This is the API entry point for all the extended scalars
2528
*/
@@ -118,6 +121,12 @@ public class ExtendedScalars {
118121
*/
119122
public static GraphQLScalarType Locale = new LocaleScalar();
120123

124+
/**
125+
* A UUID scalar that accepts a universally unique identifier and produces {@link
126+
* java.util.UUID} objects at runtime.
127+
*/
128+
public static GraphQLScalarType UUID = new UUIDScalar();
129+
121130
/**
122131
* An `Int` scalar that MUST be greater than zero
123132
*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package graphql.scalars.id;
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+
import graphql.schema.GraphQLScalarType;
10+
11+
import java.time.DateTimeException;
12+
import java.time.format.DateTimeFormatter;
13+
import java.util.UUID;
14+
15+
import static graphql.scalars.util.Kit.typeName;
16+
17+
/**
18+
* Access this via {@link graphql.scalars.ExtendedScalars#UUID}
19+
*/
20+
@Internal
21+
public class UUIDScalar extends GraphQLScalarType {
22+
23+
public UUIDScalar() {
24+
super("UUID", "A universally unique identifier compliant UUID Scalar", new Coercing<UUID, String>() {
25+
@Override
26+
public String serialize(Object input) throws CoercingSerializeException {
27+
if (input instanceof String) {
28+
try {
29+
return (UUID.fromString((String)input)).toString();
30+
} catch ( IllegalArgumentException ex) {
31+
throw new CoercingSerializeException(
32+
"Expected a UUID value that can be converted : '" + ex.getMessage() + "'."
33+
);
34+
}
35+
}
36+
else if(input instanceof UUID) {
37+
return input.toString();
38+
}
39+
else {
40+
throw new CoercingSerializeException(
41+
"Expected something we can convert to 'java.util.UUID' but was '" + typeName(input) + "'."
42+
);
43+
}
44+
}
45+
46+
@Override
47+
public UUID parseValue(Object input) throws CoercingParseValueException {
48+
if(input instanceof String) {
49+
try {
50+
return UUID.fromString((String) input);
51+
} catch (IllegalArgumentException ex) {
52+
throw new CoercingParseValueException(
53+
"Expected a 'String' of UUID type but was '" + typeName(input) + "'."
54+
);
55+
}
56+
}
57+
else if(input instanceof UUID) {
58+
return (UUID) input;
59+
}
60+
else {
61+
throw new CoercingParseValueException(
62+
"Expected a 'String' or 'UUID' type but was '" + typeName(input) + "'."
63+
);
64+
}
65+
}
66+
67+
@Override
68+
public UUID parseLiteral(Object input) throws CoercingParseLiteralException {
69+
if (!(input instanceof StringValue)) {
70+
throw new CoercingParseLiteralException(
71+
"Expected a 'java.util.UUID' AST type object but was '" + typeName(input) + "'."
72+
);
73+
}
74+
try {
75+
return UUID.fromString(((StringValue) input).getValue());
76+
} catch (IllegalArgumentException ex) {
77+
throw new CoercingParseLiteralException(
78+
"Expected something that we can convert to a UUID but was invalid"
79+
);
80+
}
81+
82+
}
83+
84+
});
85+
}
86+
87+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package graphql.scalars.id
2+
3+
import graphql.language.StringValue
4+
import graphql.schema.CoercingParseLiteralException
5+
import graphql.schema.CoercingParseValueException
6+
import graphql.schema.CoercingSerializeException
7+
import spock.lang.Specification
8+
import spock.lang.Unroll
9+
10+
import static graphql.scalars.util.TestKit.*
11+
12+
class UUIDScalarTest extends Specification {
13+
14+
def coercing = new UUIDScalar().getCoercing()
15+
16+
@Unroll
17+
def "UUID parseValue"() {
18+
19+
when:
20+
def result = coercing.parseValue(input)
21+
then:
22+
result == expectedValue
23+
where:
24+
input | expectedValue
25+
"43f20307-603c-4ad1-83c6-6010d224fabf" | mkUUIDValue("43f20307-603c-4ad1-83c6-6010d224fabf")
26+
"787dbc2b-3ddb-4098-ad1d-63d026bac111" | mkUUIDValue("787dbc2b-3ddb-4098-ad1d-63d026bac111")
27+
}
28+
29+
@Unroll
30+
def "UUID parseValue bad inputs"() {
31+
32+
when:
33+
coercing.parseValue(input)
34+
then:
35+
thrown(expectedValue)
36+
where:
37+
input | expectedValue
38+
"a-string-that-is-not-uuid" | CoercingParseValueException
39+
100 | CoercingParseValueException
40+
"1985-04-12" | CoercingParseValueException
41+
}
42+
43+
def "UUID AST literal"() {
44+
45+
when:
46+
def result = coercing.parseLiteral(input)
47+
then:
48+
result == expectedValue
49+
where:
50+
input | expectedValue
51+
new StringValue("6972117d-3963-4214-ab2c-fa973d7e996b") | mkUUIDValue("6972117d-3963-4214-ab2c-fa973d7e996b")
52+
}
53+
54+
def "UUID AST literal bad inputs"() {
55+
56+
when:
57+
coercing.parseLiteral(input)
58+
then:
59+
thrown(expectedValue)
60+
where:
61+
input | expectedValue
62+
new StringValue("a-string-that-us-not-uuid") | CoercingParseLiteralException
63+
}
64+
65+
def "UUID serialization"() {
66+
67+
when:
68+
def result = coercing.serialize(input)
69+
then:
70+
result == expectedValue
71+
where:
72+
input | expectedValue
73+
"42287d47-c5bd-45e4-b470-53e426d3d503" | "42287d47-c5bd-45e4-b470-53e426d3d503"
74+
"423df0f3-cf05-4eb5-b708-ae2f4b4a052d" | "423df0f3-cf05-4eb5-b708-ae2f4b4a052d"
75+
mkUUIDValue("6a90b1e6-20f3-43e5-a7ba-34db8010c071") | "6a90b1e6-20f3-43e5-a7ba-34db8010c071"
76+
}
77+
78+
def "UUID serialization bad inputs"() {
79+
80+
when:
81+
coercing.serialize(input)
82+
then:
83+
thrown(expectedValue)
84+
where:
85+
input | expectedValue
86+
"1985-04-12" | CoercingSerializeException
87+
100 | CoercingSerializeException
88+
}
89+
90+
}

src/test/groovy/graphql/scalars/util/TestKit.groovy

+4
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,8 @@ class TestKit {
7575
return new FloatValue(new BigDecimal(d))
7676
}
7777

78+
static UUID mkUUIDValue(String s) {
79+
return UUID.fromString(s)
80+
}
81+
7882
}

0 commit comments

Comments
 (0)