@@ -22,13 +22,45 @@ public class Scalars {
2222 private static final BigInteger SHORT_MAX = BigInteger .valueOf (Short .MAX_VALUE );
2323 private static final BigInteger SHORT_MIN = BigInteger .valueOf (Short .MIN_VALUE );
2424
25+ private static boolean isWholeNumber (Object input ) {
26+ return input instanceof Long
27+ || input instanceof Integer
28+ || input instanceof Short
29+ || input instanceof Byte ;
30+ }
31+
32+ // true if its a number or string that we will attempt to convert to a number via toNumber()
33+ private static boolean isNumberIsh (Object input ) {
34+ return input instanceof Number || input instanceof String ;
35+ }
36+
37+ private static Number toNumber (Object input ) {
38+ if (input instanceof Number ) {
39+ return (Number ) input ;
40+ }
41+ if (input instanceof String ) {
42+ // we go to double and then let each scalar type decide what precision they want from it. This
43+ // will allow lenient behavior in string input as well as Number input... eg "42.3" as a string to a Long
44+ // scalar is the same as new Double(42.3) to a Long scalar.
45+ //
46+ // each type will use Java Narrow casting to turn this into the desired type (Long, Integer, Short etc...)
47+ //
48+ // See http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3
49+ //
50+ return Double .parseDouble ((String ) input );
51+ }
52+ // we never expect this and if we do, the code is wired wrong
53+ throw new AssertException ("Unexpected case - this call should be protected by a previous call to isNumberIsh()" );
54+ }
55+
56+
2557 public static GraphQLScalarType GraphQLInt = new GraphQLScalarType ("Int" , "Built-in Int" , new Coercing <Integer >() {
2658 @ Override
2759 public Integer serialize (Object input ) {
28- if (input instanceof String ) {
29- return Integer .parseInt ((String ) input );
30- } else if (input instanceof Integer ) {
60+ if (input instanceof Integer ) {
3161 return (Integer ) input ;
62+ } else if (isNumberIsh (input )) {
63+ return toNumber (input ).intValue ();
3264 } else {
3365 return null ;
3466 }
@@ -50,16 +82,13 @@ public Integer parseLiteral(Object input) {
5082 }
5183 });
5284
53-
5485 public static GraphQLScalarType GraphQLLong = new GraphQLScalarType ("Long" , "Long type" , new Coercing <Long >() {
5586 @ Override
5687 public Long serialize (Object input ) {
57- if (input instanceof String ) {
58- return Long .parseLong ((String ) input );
59- } else if (input instanceof Long ) {
88+ if (input instanceof Long ) {
6089 return (Long ) input ;
61- } else if (input instanceof Integer ) {
62- return (( Integer ) input ).longValue ();
90+ } else if (isNumberIsh ( input ) ) {
91+ return toNumber ( input ).longValue ();
6392 } else {
6493 return null ;
6594 }
@@ -86,112 +115,89 @@ public Long parseLiteral(Object input) {
86115 }
87116 });
88117
89- public static GraphQLScalarType GraphQLFloat = new GraphQLScalarType ("Float " , "Built-in Float " , new Coercing <Double >() {
118+ public static GraphQLScalarType GraphQLShort = new GraphQLScalarType ("Short " , "Built-in Short as Int " , new Coercing <Short >() {
90119 @ Override
91- public Double serialize (Object input ) {
92- if (input instanceof String ) {
93- return Double .parseDouble ((String ) input );
94- } else if (input instanceof Double ) {
95- return (Double ) input ;
96- } else if (input instanceof Float ) {
97- return (double ) (Float ) input ;
98- } else if (input instanceof Integer ) {
99- return (double ) (Integer ) input ;
120+ public Short serialize (Object input ) {
121+ if (input instanceof Short ) {
122+ return (Short ) input ;
123+ } else if (isNumberIsh (input )) {
124+ return toNumber (input ).shortValue ();
100125 } else {
101126 return null ;
102127 }
103128 }
104129
105130 @ Override
106- public Double parseValue (Object input ) {
131+ public Short parseValue (Object input ) {
107132 return serialize (input );
108133 }
109134
110135 @ Override
111- public Double parseLiteral (Object input ) {
112- if (input instanceof IntValue ) {
113- return ((IntValue ) input ).getValue ().doubleValue ();
114- } else if (input instanceof FloatValue ) {
115- return ((FloatValue ) input ).getValue ().doubleValue ();
116- } else {
117- return null ;
136+ public Short parseLiteral (Object input ) {
137+ if (!(input instanceof IntValue )) return null ;
138+ BigInteger value = ((IntValue ) input ).getValue ();
139+ if (value .compareTo (SHORT_MIN ) < 0 || value .compareTo (SHORT_MAX ) > 0 ) {
140+ throw new GraphQLException ("Int literal is too big or too small for a short, would cause overflow" );
118141 }
142+ return value .shortValue ();
119143 }
120144 });
121145
122- public static GraphQLScalarType GraphQLString = new GraphQLScalarType ("String" , "Built-in String" , new Coercing <String >() {
123- @ Override
124- public String serialize (Object input ) {
125- return input == null ? null : input .toString ();
126- }
127-
128- @ Override
129- public String parseValue (Object input ) {
130- return serialize (input );
131- }
132-
133- @ Override
134- public String parseLiteral (Object input ) {
135- if (!(input instanceof StringValue )) return null ;
136- return ((StringValue ) input ).getValue ();
137- }
138- });
139-
140-
141- public static GraphQLScalarType GraphQLBoolean = new GraphQLScalarType ("Boolean" , "Built-in Boolean" , new Coercing <Boolean >() {
146+ public static GraphQLScalarType GraphQLByte = new GraphQLScalarType ("Byte" , "Built-in Byte as Int" , new Coercing <Byte >() {
142147 @ Override
143- public Boolean serialize (Object input ) {
144- if (input instanceof Boolean ) {
145- return (Boolean ) input ;
146- } else if (input instanceof Integer ) {
147- return (Integer ) input > 0 ;
148- } else if (input instanceof String ) {
149- return Boolean .parseBoolean ((String ) input );
148+ public Byte serialize (Object input ) {
149+ if (input instanceof Byte ) {
150+ return (Byte ) input ;
151+ } else if (isNumberIsh (input )) {
152+ return toNumber (input ).byteValue ();
150153 } else {
151154 return null ;
152155 }
153156 }
154157
155158 @ Override
156- public Boolean parseValue (Object input ) {
159+ public Byte parseValue (Object input ) {
157160 return serialize (input );
158161 }
159162
160163 @ Override
161- public Boolean parseLiteral (Object input ) {
162- if (!(input instanceof BooleanValue )) return null ;
163- return ((BooleanValue ) input ).isValue ();
164+ public Byte parseLiteral (Object input ) {
165+ if (!(input instanceof IntValue )) return null ;
166+ BigInteger value = ((IntValue ) input ).getValue ();
167+ if (value .compareTo (BYTE_MIN ) < 0 || value .compareTo (BYTE_MAX ) > 0 ) {
168+ throw new GraphQLException ("Int literal is too big or too small for a byte, would cause overflow" );
169+ }
170+ return value .byteValue ();
164171 }
165172 });
166173
167174
168- public static GraphQLScalarType GraphQLID = new GraphQLScalarType ("ID " , "Built-in ID " , new Coercing <Object >() {
175+ public static GraphQLScalarType GraphQLFloat = new GraphQLScalarType ("Float " , "Built-in Float " , new Coercing <Double >() {
169176 @ Override
170- public Object serialize (Object input ) {
171- if (input instanceof String ) {
172- return input ;
173- }
174- if (input instanceof Integer ) {
175- return String .valueOf (input );
177+ public Double serialize (Object input ) {
178+ if (input instanceof Double ) {
179+ return (Double ) input ;
180+ } else if (isNumberIsh (input )) {
181+ return toNumber (input ).doubleValue ();
182+ } else {
183+ return null ;
176184 }
177-
178- return null ;
179185 }
180186
181187 @ Override
182- public Object parseValue (Object input ) {
188+ public Double parseValue (Object input ) {
183189 return serialize (input );
184190 }
185191
186192 @ Override
187- public Object parseLiteral (Object input ) {
188- if (input instanceof StringValue ) {
189- return ((StringValue ) input ).getValue ();
190- }
193+ public Double parseLiteral (Object input ) {
191194 if (input instanceof IntValue ) {
192- return ((IntValue ) input ).getValue ().toString ();
195+ return ((IntValue ) input ).getValue ().doubleValue ();
196+ } else if (input instanceof FloatValue ) {
197+ return ((FloatValue ) input ).getValue ().doubleValue ();
198+ } else {
199+ return null ;
193200 }
194- return null ;
195201 }
196202 });
197203
@@ -202,10 +208,8 @@ public BigInteger serialize(Object input) {
202208 return (BigInteger ) input ;
203209 } else if (input instanceof String ) {
204210 return new BigInteger ((String ) input );
205- } else if (input instanceof Integer ) {
206- return BigInteger .valueOf ((Integer ) input );
207- } else if (input instanceof Long ) {
208- return BigInteger .valueOf ((Long ) input );
211+ } else if (isNumberIsh (input )) {
212+ return BigInteger .valueOf (toNumber (input ).longValue ());
209213 } else {
210214 return null ;
211215 }
@@ -234,14 +238,10 @@ public BigDecimal serialize(Object input) {
234238 return (BigDecimal ) input ;
235239 } else if (input instanceof String ) {
236240 return new BigDecimal ((String ) input );
237- } else if (input instanceof Float ) {
238- return BigDecimal .valueOf ((Float ) input );
239- } else if (input instanceof Double ) {
240- return BigDecimal .valueOf ((Double ) input );
241- } else if (input instanceof Integer ) {
242- return BigDecimal .valueOf ((Integer ) input );
243- } else if (input instanceof Long ) {
244- return BigDecimal .valueOf ((Long ) input );
241+ } else if (isWholeNumber (input )) {
242+ return BigDecimal .valueOf (toNumber (input ).longValue ());
243+ } else if (input instanceof Number ) {
244+ return BigDecimal .valueOf (toNumber (input ).doubleValue ());
245245 } else {
246246 return null ;
247247 }
@@ -265,62 +265,84 @@ public BigDecimal parseLiteral(Object input) {
265265 }
266266 });
267267
268- public static GraphQLScalarType GraphQLByte = new GraphQLScalarType ("Byte" , "Built-in Byte as Int" , new Coercing <Byte >() {
268+
269+ public static GraphQLScalarType GraphQLString = new GraphQLScalarType ("String" , "Built-in String" , new Coercing <String >() {
269270 @ Override
270- public Byte serialize (Object input ) {
271- if (input instanceof String ) {
272- return Byte .parseByte ((String ) input );
273- } else if (input instanceof Byte ) {
274- return (Byte ) input ;
271+ public String serialize (Object input ) {
272+ return input == null ? null : input .toString ();
273+ }
274+
275+ @ Override
276+ public String parseValue (Object input ) {
277+ return serialize (input );
278+ }
279+
280+ @ Override
281+ public String parseLiteral (Object input ) {
282+ if (!(input instanceof StringValue )) return null ;
283+ return ((StringValue ) input ).getValue ();
284+ }
285+ });
286+
287+
288+ public static GraphQLScalarType GraphQLBoolean = new GraphQLScalarType ("Boolean" , "Built-in Boolean" , new Coercing <Boolean >() {
289+ @ Override
290+ public Boolean serialize (Object input ) {
291+ if (input instanceof Boolean ) {
292+ return (Boolean ) input ;
293+ } else if (input instanceof Integer ) {
294+ return (Integer ) input > 0 ;
295+ } else if (input instanceof String ) {
296+ return Boolean .parseBoolean ((String ) input );
275297 } else {
276298 return null ;
277299 }
278300 }
279301
280302 @ Override
281- public Byte parseValue (Object input ) {
303+ public Boolean parseValue (Object input ) {
282304 return serialize (input );
283305 }
284306
285307 @ Override
286- public Byte parseLiteral (Object input ) {
287- if (!(input instanceof IntValue )) return null ;
288- BigInteger value = ((IntValue ) input ).getValue ();
289- if (value .compareTo (BYTE_MIN ) < 0 || value .compareTo (BYTE_MAX ) > 0 ) {
290- throw new GraphQLException ("Int literal is too big or too small for a byte, would cause overflow" );
291- }
292- return value .byteValue ();
308+ public Boolean parseLiteral (Object input ) {
309+ if (!(input instanceof BooleanValue )) return null ;
310+ return ((BooleanValue ) input ).isValue ();
293311 }
294312 });
295313
296- public static GraphQLScalarType GraphQLShort = new GraphQLScalarType ("Short" , "Built-in Short as Int" , new Coercing <Short >() {
314+
315+ public static GraphQLScalarType GraphQLID = new GraphQLScalarType ("ID" , "Built-in ID" , new Coercing <Object >() {
297316 @ Override
298- public Short serialize (Object input ) {
317+ public Object serialize (Object input ) {
299318 if (input instanceof String ) {
300- return Short .parseShort ((String ) input );
301- } else if (input instanceof Short ) {
302- return (Short ) input ;
303- } else {
304- return null ;
319+ return input ;
320+ }
321+ if (input instanceof Integer ) {
322+ return String .valueOf (input );
305323 }
324+
325+ return null ;
306326 }
307327
308328 @ Override
309- public Short parseValue (Object input ) {
329+ public Object parseValue (Object input ) {
310330 return serialize (input );
311331 }
312332
313333 @ Override
314- public Short parseLiteral (Object input ) {
315- if (!(input instanceof IntValue )) return null ;
316- BigInteger value = ((IntValue ) input ).getValue ();
317- if (value .compareTo (SHORT_MIN ) < 0 || value .compareTo (SHORT_MAX ) > 0 ) {
318- throw new GraphQLException ("Int literal is too big or too small for a short, would cause overflow" );
334+ public Object parseLiteral (Object input ) {
335+ if (input instanceof StringValue ) {
336+ return ((StringValue ) input ).getValue ();
319337 }
320- return value .shortValue ();
338+ if (input instanceof IntValue ) {
339+ return ((IntValue ) input ).getValue ().toString ();
340+ }
341+ return null ;
321342 }
322343 });
323344
345+
324346 public static GraphQLScalarType GraphQLChar = new GraphQLScalarType ("Char" , "Built-in Char as Character" , new Coercing <Character >() {
325347 @ Override
326348 public Character serialize (Object input ) {
0 commit comments