Skip to content

Commit ad32245

Browse files
committed
feat: add more Java Scalars
1 parent e51876b commit ad32245

File tree

1 file changed

+198
-5
lines changed
  • graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema

1 file changed

+198
-5
lines changed

graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/JavaScalars.java

Lines changed: 198 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,39 @@
1717

1818
import java.math.BigDecimal;
1919
import java.math.BigInteger;
20+
import java.nio.charset.StandardCharsets;
2021
import java.text.DateFormat;
2122
import java.text.ParseException;
23+
import java.text.SimpleDateFormat;
2224
import java.time.Instant;
2325
import java.time.LocalDate;
2426
import java.time.LocalDateTime;
2527
import java.time.format.DateTimeParseException;
28+
import java.util.Collections;
2629
import java.util.Date;
2730
import java.util.HashMap;
31+
import java.util.LinkedHashMap;
32+
import java.util.List;
33+
import java.util.Map;
2834
import java.util.TimeZone;
2935
import java.util.UUID;
36+
import java.util.stream.Collectors;
3037

3138
import org.slf4j.Logger;
3239
import org.slf4j.LoggerFactory;
3340

3441
import graphql.Assert;
3542
import graphql.Scalars;
43+
import graphql.language.ArrayValue;
44+
import graphql.language.BooleanValue;
45+
import graphql.language.EnumValue;
46+
import graphql.language.FloatValue;
3647
import graphql.language.IntValue;
48+
import graphql.language.NullValue;
49+
import graphql.language.ObjectField;
50+
import graphql.language.ObjectValue;
3751
import graphql.language.StringValue;
52+
import graphql.language.Value;
3853
import graphql.schema.Coercing;
3954
import graphql.schema.GraphQLScalarType;
4055

@@ -49,6 +64,8 @@ public class JavaScalars {
4964
static final Logger log = LoggerFactory.getLogger(JavaScalars.class);
5065

5166
private static HashMap<Class<?>, GraphQLScalarType> scalarsRegistry = new HashMap<Class<?>, GraphQLScalarType>();
67+
68+
private static JavaScalars instance = new JavaScalars();
5269

5370
static {
5471
scalarsRegistry.put(String.class, Scalars.GraphQLString);
@@ -86,21 +103,24 @@ public class JavaScalars {
86103
scalarsRegistry.put(Date.class, new GraphQLScalarType("Date", "Date type", new GraphQLDateCoercing()));
87104
scalarsRegistry.put(UUID.class, new GraphQLScalarType("UUID", "UUID type", new GraphQLUUIDCoercing()));
88105
scalarsRegistry.put(Object.class, new GraphQLScalarType("Object", "Object type", new GraphQLObjectCoercing()));
106+
scalarsRegistry.put(java.sql.Date.class, new GraphQLScalarType("SqlDate", "SQL Date type", new GraphQLSqlDateCoercing()));
107+
scalarsRegistry.put(java.sql.Timestamp.class, new GraphQLScalarType("SqlTimestamp", "SQL Timestamp type", new GraphQLSqlTimestampCoercing()));
108+
scalarsRegistry.put(Byte[].class, new GraphQLScalarType("ByteArray", "ByteArray type", new GraphQLLOBCoercing()));
89109
}
90110

91111
public static GraphQLScalarType of(Class<?> key) {
92112
return scalarsRegistry.get(key);
93113
}
94114

95-
public JavaScalars register(Class<?> key, GraphQLScalarType value) {
115+
public static JavaScalars register(Class<?> key, GraphQLScalarType value) {
96116
Assert.assertNotNull(key, "key parameter cannot be null.");
97117
Assert.assertNotNull(value, "value parameter cannot be null.");
98118

99119
scalarsRegistry.put(key, value);
100120

101-
return this;
121+
return instance;
102122
}
103-
123+
104124
public static class GraphQLLocalDateTimeCoercing implements Coercing<Object, Object> {
105125

106126
@Override
@@ -227,7 +247,7 @@ public Object parseLiteral(Object input) {
227247

228248
private Date parseStringToDate(String input) {
229249
try {
230-
return DateFormat.getInstance().parse(input);
250+
return new SimpleDateFormat("yyyy-MM-dd").parse(input);
231251
} catch (ParseException e) {
232252
log.warn("Failed to parse Date from input: " + input, e);
233253
return null;
@@ -271,7 +291,7 @@ private UUID parseStringToUUID(String input) {
271291
}
272292
};
273293

274-
public static class GraphQLObjectCoercing implements Coercing<Object, Object> {
294+
public static class GraphQLRawObjectCoercing implements Coercing<Object, Object> {
275295

276296
@Override
277297
public Object serialize(Object input) {
@@ -288,5 +308,178 @@ public Object parseLiteral(Object input) {
288308
return input;
289309
}
290310
};
311+
312+
public static class GraphQLSqlDateCoercing implements Coercing<Object, Object> {
313+
@Override
314+
public Object serialize(Object input) {
315+
if (input instanceof String) {
316+
return parseStringToDate((String) input);
317+
} else if (input instanceof Date) {
318+
return new java.sql.Date(((Date) input).getTime());
319+
} else if (input instanceof Long) {
320+
return new java.sql.Date(((Long) input).longValue());
321+
} else if (input instanceof Integer) {
322+
return new java.sql.Date(((Integer) input).longValue());
323+
}
324+
return null;
325+
}
326+
@Override
327+
public Object parseValue(Object input) {
328+
return serialize(input);
329+
}
330+
@Override
331+
public Object parseLiteral(Object input) {
332+
if (input instanceof StringValue) {
333+
return parseStringToDate(((StringValue) input).getValue());
334+
} else if (input instanceof IntValue) {
335+
BigInteger value = ((IntValue) input).getValue();
336+
return new java.sql.Date(value.longValue());
337+
}
338+
return null;
339+
}
340+
private java.sql.Date parseStringToDate(String input) {
341+
try {
342+
return new java.sql.Date(DateFormat.getInstance().parse(input).getTime());
343+
} catch (ParseException e) {
344+
log.warn("Failed to parse SQL Date from input: " + input, e);
345+
return null;
346+
}
347+
}
348+
}
349+
public static class GraphQLSqlTimestampCoercing implements Coercing<Object, Object> {
350+
@Override
351+
public Object serialize(Object input) {
352+
if (input instanceof String) {
353+
return parseStringToTimestamp((String) input);
354+
} else if (input instanceof Date) {
355+
return new java.sql.Timestamp(((Date) input).getTime());
356+
} else if (input instanceof Long) {
357+
return new java.sql.Timestamp(((Long) input).longValue());
358+
} else if (input instanceof Integer) {
359+
return new java.sql.Timestamp(((Integer) input).longValue());
360+
}
361+
return null;
362+
}
363+
@Override
364+
public Object parseValue(Object input) {
365+
return serialize(input);
366+
}
367+
@Override
368+
public Object parseLiteral(Object input) {
369+
if (input instanceof StringValue) {
370+
return parseStringToTimestamp(((StringValue) input).getValue());
371+
} else if (input instanceof IntValue) {
372+
BigInteger value = ((IntValue) input).getValue();
373+
return new java.sql.Date(value.longValue());
374+
}
375+
return null;
376+
}
377+
private java.sql.Timestamp parseStringToTimestamp(String input) {
378+
try {
379+
return new java.sql.Timestamp(DateFormat.getInstance().parse(input).getTime());
380+
} catch (ParseException e) {
381+
log.warn("Failed to parse Timestamp from input: " + input, e);
382+
return null;
383+
}
384+
}
385+
}
386+
public static class GraphQLLOBCoercing implements Coercing<Object, Object> {
387+
@Override
388+
public Object serialize(Object input) {
389+
if (input.getClass() == byte[].class) {
390+
return input;
391+
}
392+
return null;
393+
}
394+
@Override
395+
public Object parseValue(Object input) {
396+
if (input instanceof String) {
397+
return parseStringToByteArray((String) input);
398+
}
399+
return null;
400+
}
401+
@Override
402+
public Object parseLiteral(Object input) {
403+
if (input instanceof StringValue) {
404+
return parseStringToByteArray(((StringValue) input).getValue());
405+
}
406+
return null;
407+
}
408+
private byte[] parseStringToByteArray(String input) {
409+
try {
410+
return input.getBytes(StandardCharsets.UTF_8);
411+
} catch (IllegalArgumentException e) {
412+
log.warn("Failed to parse byte[] from input: " + input, e);
413+
return null;
414+
}
415+
}
416+
}
417+
418+
public static class GraphQLObjectCoercing implements Coercing<Object, Object> {
419+
420+
@Override
421+
public Object serialize(Object dataFetcherResult) {
422+
return dataFetcherResult;
423+
}
424+
425+
@Override
426+
public Object parseValue(Object input) {
427+
return input;
428+
}
429+
430+
@Override
431+
public Object parseLiteral(Object input) {
432+
return parseFieldValue((Value) input, Collections.emptyMap());
433+
}
434+
435+
//recursively parse the input into a Map
436+
private Object parseFieldValue(Object value, Map<String, Object> variables) {
437+
if (!(value instanceof Value)) {
438+
throw new IllegalArgumentException(
439+
"Expected AST type 'StringValue' but was '" + value + "'."
440+
);
441+
}
442+
443+
if (value instanceof StringValue) {
444+
return ((StringValue) value).getValue();
445+
}
446+
if (value instanceof IntValue) {
447+
return ((IntValue) value).getValue();
448+
}
449+
if (value instanceof FloatValue) {
450+
return ((FloatValue) value).getValue();
451+
}
452+
if (value instanceof BooleanValue) {
453+
return ((BooleanValue) value).isValue();
454+
}
455+
if (value instanceof EnumValue) {
456+
return ((EnumValue) value).getName();
457+
}
458+
if (value instanceof NullValue) {
459+
return null;
460+
}
461+
if (value instanceof ArrayValue) {
462+
List<Value> values = ((ArrayValue) value).getValues();
463+
return values.stream()
464+
.map(v -> parseFieldValue(v, variables))
465+
.collect(Collectors.toList());
466+
}
467+
if (value instanceof ObjectValue) {
468+
List<ObjectField> values = ((ObjectValue) value).getObjectFields();
469+
Map<String, Object> parsedValues = new LinkedHashMap<>();
470+
471+
values.forEach(field -> {
472+
Object parsedValue = parseFieldValue(field.getValue(), variables);
473+
parsedValues.put(field.getName(), parsedValue);
474+
});
475+
return parsedValues;
476+
}
477+
478+
//Should never happen, as it would mean the variable was not replaced by the parser
479+
throw new IllegalArgumentException("Unsupported scalar value type: " + value.getClass().getName());
480+
}
481+
482+
}
483+
291484

292485
}

0 commit comments

Comments
 (0)