24
24
import java .time .Instant ;
25
25
import java .time .LocalDate ;
26
26
import java .time .LocalDateTime ;
27
+ import java .time .LocalTime ;
28
+ import java .time .ZoneOffset ;
29
+ import java .time .format .DateTimeFormatter ;
27
30
import java .time .format .DateTimeParseException ;
28
31
import java .util .Collections ;
29
32
import java .util .Date ;
35
38
import java .util .UUID ;
36
39
import java .util .stream .Collectors ;
37
40
38
- import org .slf4j .Logger ;
39
- import org .slf4j .LoggerFactory ;
40
-
41
41
import graphql .Assert ;
42
42
import graphql .Scalars ;
43
43
import graphql .language .ArrayValue ;
51
51
import graphql .language .StringValue ;
52
52
import graphql .language .Value ;
53
53
import graphql .schema .Coercing ;
54
+ import graphql .schema .CoercingParseValueException ;
55
+ import graphql .schema .CoercingSerializeException ;
54
56
import graphql .schema .GraphQLScalarType ;
57
+ import org .slf4j .Logger ;
58
+ import org .slf4j .LoggerFactory ;
55
59
56
60
/**
57
61
* Provides Registry to resolve GraphQL Query Java Scalar Types
@@ -100,6 +104,7 @@ public class JavaScalars {
100
104
101
105
scalarsRegistry .put (LocalDateTime .class , new GraphQLScalarType ("LocalDateTime" , "LocalDateTime type" , new GraphQLLocalDateTimeCoercing ()));
102
106
scalarsRegistry .put (LocalDate .class , new GraphQLScalarType ("LocalDate" , "LocalDate type" , new GraphQLLocalDateCoercing ()));
107
+ scalarsRegistry .put (LocalTime .class , new GraphQLScalarType ("LocalTime" , "LocalTime type" , new GraphQLLocalTimeCoercing ()));
103
108
scalarsRegistry .put (Date .class , new GraphQLScalarType ("Date" , "Date type" , new GraphQLDateCoercing ()));
104
109
scalarsRegistry .put (UUID .class , new GraphQLScalarType ("UUID" , "UUID type" , new GraphQLUUIDCoercing ()));
105
110
scalarsRegistry .put (Object .class , new GraphQLScalarType ("Object" , "Object type" , new GraphQLObjectCoercing ()));
@@ -212,6 +217,51 @@ private LocalDate parseStringToLocalDate(String input) {
212
217
}
213
218
}
214
219
};
220
+
221
+ public static class GraphQLLocalTimeCoercing implements Coercing <LocalTime , String > {
222
+
223
+ public static final DateTimeFormatter FORMATTER = DateTimeFormatter .ISO_LOCAL_TIME .withZone (ZoneOffset .UTC );
224
+
225
+ private LocalTime convertImpl (Object input ) {
226
+ if (input instanceof String ) {
227
+ try {
228
+ return LocalTime .parse ((String ) input , FORMATTER );
229
+ } catch (DateTimeParseException ignored ) {
230
+ }
231
+ }
232
+ return null ;
233
+ }
234
+
235
+ @ Override
236
+ public String serialize (Object input ) {
237
+ if (input instanceof LocalTime ) {
238
+ return DateTimeFormatter .ISO_LOCAL_TIME .format ((LocalTime ) input );
239
+ } else {
240
+ LocalTime result = convertImpl (input );
241
+ if (result == null ) {
242
+ throw new CoercingSerializeException ("Invalid value '" + input + "' for LocalTime" );
243
+ }
244
+ return DateTimeFormatter .ISO_LOCAL_TIME .format (result );
245
+ }
246
+ }
247
+
248
+ @ Override
249
+ public LocalTime parseValue (Object input ) {
250
+ LocalTime result = convertImpl (input );
251
+ if (result == null ) {
252
+ throw new CoercingParseValueException ("Invalid value '" + input + "' for LocalTime" );
253
+ }
254
+ return result ;
255
+ }
256
+
257
+ @ Override
258
+ public LocalTime parseLiteral (Object input ) {
259
+ if (!(input instanceof StringValue )) return null ;
260
+ String value = ((StringValue ) input ).getValue ();
261
+ LocalTime result = convertImpl (value );
262
+ return result ;
263
+ }
264
+ }
215
265
216
266
public static class GraphQLDateCoercing implements Coercing <Object , Object > {
217
267
final DateFormat df ;
@@ -328,111 +378,125 @@ public Object parseLiteral(Object input) {
328
378
};
329
379
330
380
public static class GraphQLSqlDateCoercing implements Coercing <Object , Object > {
381
+
331
382
@ Override
332
- public Object serialize (Object input ) {
333
- if (input instanceof String ) {
334
- return parseStringToDate ((String ) input );
335
- } else if (input instanceof Date ) {
336
- return new java .sql .Date (((Date ) input ).getTime ());
337
- } else if (input instanceof Long ) {
338
- return new java .sql .Date (((Long ) input ).longValue ());
339
- } else if (input instanceof Integer ) {
340
- return new java .sql .Date (((Integer ) input ).longValue ());
341
- }
342
- return null ;
343
- }
383
+ public Object serialize (Object input ) {
384
+ if (input instanceof String ) {
385
+ return parseStringToDate ((String ) input );
386
+ } else if (input instanceof Date ) {
387
+ return new java .sql .Date (((Date ) input ).getTime ());
388
+ } else if (input instanceof Long ) {
389
+ return new java .sql .Date (((Long ) input ).longValue ());
390
+ } else if (input instanceof Integer ) {
391
+ return new java .sql .Date (((Integer ) input ).longValue ());
392
+ }
393
+ return null ;
394
+ }
395
+
344
396
@ Override
345
- public Object parseValue (Object input ) {
346
- return serialize (input );
347
- }
397
+ public Object parseValue (Object input ) {
398
+ return serialize (input );
399
+ }
400
+
348
401
@ Override
349
- public Object parseLiteral (Object input ) {
350
- if (input instanceof StringValue ) {
351
- return parseStringToDate (((StringValue ) input ).getValue ());
352
- } else if (input instanceof IntValue ) {
353
- BigInteger value = ((IntValue ) input ).getValue ();
354
- return new java .sql .Date (value .longValue ());
355
- }
356
- return null ;
357
- }
402
+ public Object parseLiteral (Object input ) {
403
+ if (input instanceof StringValue ) {
404
+ return parseStringToDate (((StringValue ) input ).getValue ());
405
+ } else if (input instanceof IntValue ) {
406
+ BigInteger value = ((IntValue ) input ).getValue ();
407
+ return new java .sql .Date (value .longValue ());
408
+ }
409
+ return null ;
410
+ }
411
+
358
412
private java .sql .Date parseStringToDate (String input ) {
359
- try {
360
- return new java .sql .Date (DateFormat .getInstance ().parse (input ).getTime ());
361
- } catch (ParseException e ) {
362
- log .warn ("Failed to parse SQL Date from input: " + input , e );
363
- return null ;
364
- }
365
- }
366
- }
413
+ try {
414
+ return new java .sql .Date (DateFormat .getInstance ().parse (input ).getTime ());
415
+ } catch (ParseException e ) {
416
+ log .warn ("Failed to parse SQL Date from input: " + input , e );
417
+ return null ;
418
+ }
419
+ }
420
+ }
421
+
367
422
public static class GraphQLSqlTimestampCoercing implements Coercing <Object , Object > {
423
+
368
424
@ Override
369
- public Object serialize (Object input ) {
370
- if (input instanceof String ) {
371
- return parseStringToTimestamp ((String ) input );
372
- } else if (input instanceof Date ) {
373
- return new java .sql .Timestamp (((Date ) input ).getTime ());
374
- } else if (input instanceof Long ) {
375
- return new java .sql .Timestamp (((Long ) input ).longValue ());
376
- } else if (input instanceof Integer ) {
377
- return new java .sql .Timestamp (((Integer ) input ).longValue ());
378
- }
379
- return null ;
380
- }
425
+ public Object serialize (Object input ) {
426
+ if (input instanceof String ) {
427
+ return parseStringToTimestamp ((String ) input );
428
+ } else if (input instanceof Date ) {
429
+ return new java .sql .Timestamp (((Date ) input ).getTime ());
430
+ } else if (input instanceof Long ) {
431
+ return new java .sql .Timestamp (((Long ) input ).longValue ());
432
+ } else if (input instanceof Integer ) {
433
+ return new java .sql .Timestamp (((Integer ) input ).longValue ());
434
+ }
435
+ return null ;
436
+ }
437
+
381
438
@ Override
382
- public Object parseValue (Object input ) {
383
- return serialize (input );
384
- }
439
+ public Object parseValue (Object input ) {
440
+ return serialize (input );
441
+ }
442
+
385
443
@ Override
386
- public Object parseLiteral (Object input ) {
387
- if (input instanceof StringValue ) {
388
- return parseStringToTimestamp (((StringValue ) input ).getValue ());
389
- } else if (input instanceof IntValue ) {
390
- BigInteger value = ((IntValue ) input ).getValue ();
391
- return new java .sql .Date (value .longValue ());
392
- }
393
- return null ;
394
- }
444
+ public Object parseLiteral (Object input ) {
445
+ if (input instanceof StringValue ) {
446
+ return parseStringToTimestamp (((StringValue ) input ).getValue ());
447
+ } else if (input instanceof IntValue ) {
448
+ BigInteger value = ((IntValue ) input ).getValue ();
449
+ return new java .sql .Date (value .longValue ());
450
+ }
451
+ return null ;
452
+ }
453
+
395
454
private java .sql .Timestamp parseStringToTimestamp (String input ) {
396
- try {
397
- return new java .sql .Timestamp (DateFormat .getInstance ().parse (input ).getTime ());
398
- } catch (ParseException e ) {
399
- log .warn ("Failed to parse Timestamp from input: " + input , e );
400
- return null ;
401
- }
402
- }
403
- }
455
+ try {
456
+ return new java .sql .Timestamp (DateFormat .getInstance ().parse (input ).getTime ());
457
+ } catch (ParseException e ) {
458
+ log .warn ("Failed to parse Timestamp from input: " + input , e );
459
+ return null ;
460
+ }
461
+ }
462
+ }
463
+
404
464
public static class GraphQLLOBCoercing implements Coercing <Object , Object > {
465
+
405
466
@ Override
406
- public Object serialize (Object input ) {
407
- if (input .getClass () == byte [].class ) {
408
- return input ;
409
- }
410
- return null ;
411
- }
467
+ public Object serialize (Object input ) {
468
+ if (input .getClass () == byte [].class ) {
469
+ return input ;
470
+ }
471
+ return null ;
472
+ }
473
+
412
474
@ Override
413
- public Object parseValue (Object input ) {
414
- if (input instanceof String ) {
415
- return parseStringToByteArray ((String ) input );
416
- }
417
- return null ;
418
- }
475
+ public Object parseValue (Object input ) {
476
+ if (input instanceof String ) {
477
+ return parseStringToByteArray ((String ) input );
478
+ }
479
+ return null ;
480
+ }
481
+
419
482
@ Override
420
- public Object parseLiteral (Object input ) {
421
- if (input instanceof StringValue ) {
422
- return parseStringToByteArray (((StringValue ) input ).getValue ());
423
- }
424
- return null ;
425
- }
483
+ public Object parseLiteral (Object input ) {
484
+ if (input instanceof StringValue ) {
485
+ return parseStringToByteArray (((StringValue ) input ).getValue ());
486
+ }
487
+ return null ;
488
+ }
489
+
426
490
private byte [] parseStringToByteArray (String input ) {
427
- try {
428
- return input .getBytes (StandardCharsets .UTF_8 );
429
- } catch (IllegalArgumentException e ) {
430
- log .warn ("Failed to parse byte[] from input: " + input , e );
431
- return null ;
432
- }
433
- }
434
- }
435
-
491
+ try {
492
+ return input .getBytes (StandardCharsets .UTF_8 );
493
+ } catch (IllegalArgumentException e ) {
494
+ log .warn ("Failed to parse byte[] from input: " + input , e );
495
+ return null ;
496
+ }
497
+ }
498
+ }
499
+
436
500
public static class GraphQLObjectCoercing implements Coercing <Object , Object > {
437
501
438
502
@ Override
@@ -447,17 +511,16 @@ public Object parseValue(Object input) {
447
511
448
512
@ Override
449
513
public Object parseLiteral (Object input ) {
450
- return parseFieldValue ((Value ) input , Collections .emptyMap ());
514
+ return parseFieldValue ((Value ) input , Collections .emptyMap ());
451
515
}
452
516
453
517
//recursively parse the input into a Map
454
518
private Object parseFieldValue (Object value , Map <String , Object > variables ) {
455
519
if (!(value instanceof Value )) {
456
520
throw new IllegalArgumentException (
457
- "Expected AST type 'StringValue' but was '" + value + "'."
458
- );
459
- }
460
-
521
+ "Expected AST type 'StringValue' but was '" + value + "'." );
522
+ }
523
+
461
524
if (value instanceof StringValue ) {
462
525
return ((StringValue ) value ).getValue ();
463
526
}
@@ -477,27 +540,26 @@ private Object parseFieldValue(Object value, Map<String, Object> variables) {
477
540
return null ;
478
541
}
479
542
if (value instanceof ArrayValue ) {
480
- List <Value > values = ((ArrayValue ) value ).getValues ();
543
+ List <Value > values = ((ArrayValue ) value ).getValues ();
481
544
return values .stream ()
482
- .map (v -> parseFieldValue (v , variables ))
483
- .collect (Collectors .toList ());
545
+ .map (v -> parseFieldValue (v , variables ))
546
+ .collect (Collectors .toList ());
484
547
}
485
548
if (value instanceof ObjectValue ) {
486
- List <ObjectField > values = ((ObjectValue ) value ).getObjectFields ();
549
+ List <ObjectField > values = ((ObjectValue ) value ).getObjectFields ();
487
550
Map <String , Object > parsedValues = new LinkedHashMap <>();
488
-
551
+
489
552
values .forEach (field -> {
490
553
Object parsedValue = parseFieldValue (field .getValue (), variables );
491
554
parsedValues .put (field .getName (), parsedValue );
492
555
});
493
556
return parsedValues ;
494
557
}
495
-
558
+
496
559
//Should never happen, as it would mean the variable was not replaced by the parser
497
560
throw new IllegalArgumentException ("Unsupported scalar value type: " + value .getClass ().getName ());
498
561
}
499
562
500
563
}
501
-
502
564
503
565
}
0 commit comments