diff --git a/client/implementation/src/main/java/io/smallrye/graphql/client/impl/core/utils/ValueFormatter.java b/client/implementation/src/main/java/io/smallrye/graphql/client/impl/core/utils/ValueFormatter.java index e0d810cf3..924627bb8 100644 --- a/client/implementation/src/main/java/io/smallrye/graphql/client/impl/core/utils/ValueFormatter.java +++ b/client/implementation/src/main/java/io/smallrye/graphql/client/impl/core/utils/ValueFormatter.java @@ -2,6 +2,7 @@ import java.lang.reflect.Array; import java.time.LocalDate; +import java.util.UUID; import io.smallrye.graphql.client.core.exceptions.BuildException; import io.smallrye.graphql.client.impl.core.EnumImpl; @@ -10,6 +11,18 @@ public class ValueFormatter { + private final static Class[] QUOTED_VALUES = new Class[] { String.class, Character.class, LocalDate.class, UUID.class }; + private final static Class[] UNQUOTED_VALUES = new Class[] { Number.class, Boolean.class }; + + public static boolean assignableFrom(Class clazz, Class[] candidates) { + for (Class candidate : candidates) { + if (candidate.isAssignableFrom(clazz)) { + return true; + } + } + return false; + } + public static String format(Object value) throws BuildException { if (value == null) { return "null"; @@ -24,17 +37,36 @@ public static String format(Object value) throws BuildException { return gqlEnum.build(); } else if (value.getClass().isArray()) { return _processArray(value); - } else if (value instanceof String) { - return _getAsQuotedString(String.valueOf(value)); - } else if (value instanceof Character) { - return _getAsQuotedString(String.valueOf(value)); - } else if (value instanceof LocalDate) { - return _getAsQuotedString(String.valueOf(value)); + } else if (value instanceof Iterable) { + return _processIterable((Iterable) value); } else { - return value.toString(); + if (assignableFrom(value.getClass(), QUOTED_VALUES)) { + return _getAsQuotedString(String.valueOf(value)); + } else if (assignableFrom(value.getClass(), UNQUOTED_VALUES)) { + return value.toString(); + } + throw new IllegalStateException("Could not format " + value.getClass() + ": Unsupported type."); } } + private static String _processIterable(Iterable iterable) throws BuildException { + StringBuilder builder = new StringBuilder(); + + boolean first = true; + builder.append("["); + for (Object v : iterable) { + if (first) { + first = false; + } else { + builder.append(","); + } + builder.append(format(v)); + } + builder.append("]"); + + return builder.toString(); + } + private static String _processArray(Object array) throws BuildException { StringBuilder builder = new StringBuilder(); diff --git a/client/implementation/src/test/java/io/smallrye/graphql/client/impl/core/utils/ValueFormatterTest.java b/client/implementation/src/test/java/io/smallrye/graphql/client/impl/core/utils/ValueFormatterTest.java new file mode 100644 index 000000000..10914f9f7 --- /dev/null +++ b/client/implementation/src/test/java/io/smallrye/graphql/client/impl/core/utils/ValueFormatterTest.java @@ -0,0 +1,28 @@ +package io.smallrye.graphql.client.impl.core.utils; + +import org.junit.jupiter.api.Test; + +import java.util.Date; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +class ValueFormatterTest { + + @Test + public void testUnsupportedInput() { + + assertThrows(IllegalStateException.class, () -> { + ValueFormatter.format(new Object()); + }); + + assertThrows(IllegalStateException.class, () -> { + ValueFormatter.format(Map.of("test", "value")); + }); + + assertThrows(IllegalStateException.class, () -> { + ValueFormatter.format(new Date()); + }); + } + +} \ No newline at end of file diff --git a/client/tck/src/main/java/tck/graphql/dynamic/core/ArraysTest.java b/client/tck/src/main/java/tck/graphql/dynamic/core/ArraysTest.java index aeab064ee..1bbe582c4 100644 --- a/client/tck/src/main/java/tck/graphql/dynamic/core/ArraysTest.java +++ b/client/tck/src/main/java/tck/graphql/dynamic/core/ArraysTest.java @@ -13,6 +13,9 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; import org.junit.jupiter.api.Test; @@ -61,7 +64,11 @@ public void arraysTest() throws IOException, URISyntaxException { prop("charPrimitiveArray", new char[] { 'f', 'o', 'o' }), prop("charObjectArray", new Character[] { 'f', 'o', 'o' }), - prop("stringArray", new String[] { "foo", "bar", "baz" })))), + prop("stringArray", new String[] { "foo", "bar", "baz" }), + + prop("uuidArray", new UUID[]{UUID.fromString("fc4bb4f4-13fe-4908-8d6a-afa64f1b56c9"), + UUID.fromString("863c9e3c-7538-41b9-9d63-0852f6a50815")}) + ))), field("boolPrimitiveArray"), field("boolObjectArray"), @@ -89,7 +96,10 @@ public void arraysTest() throws IOException, URISyntaxException { field("charPrimitiveArray"), field("charObjectArray"), - field("stringArray")))); + field("stringArray"), + + field("uuidArray") + ))); String generatedRequest = document.build(); AssertGraphQL.assertEquivalentGraphQLRequest(expectedRequest, generatedRequest); diff --git a/client/tck/src/main/java/tck/graphql/dynamic/core/IterableTest.java b/client/tck/src/main/java/tck/graphql/dynamic/core/IterableTest.java new file mode 100644 index 000000000..d7eba23f6 --- /dev/null +++ b/client/tck/src/main/java/tck/graphql/dynamic/core/IterableTest.java @@ -0,0 +1,94 @@ +package tck.graphql.dynamic.core; + +import io.smallrye.graphql.client.core.Document; +import org.junit.jupiter.api.Test; +import tck.graphql.dynamic.helper.AssertGraphQL; +import tck.graphql.dynamic.helper.Utils; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +import static io.smallrye.graphql.client.core.Argument.arg; +import static io.smallrye.graphql.client.core.Argument.args; +import static io.smallrye.graphql.client.core.Document.document; +import static io.smallrye.graphql.client.core.Field.field; +import static io.smallrye.graphql.client.core.InputObject.inputObject; +import static io.smallrye.graphql.client.core.InputObjectField.prop; +import static io.smallrye.graphql.client.core.Operation.operation; +import static io.smallrye.graphql.client.core.OperationType.QUERY; + +public class IterableTest { + + @Test + public void iterableTest() throws IOException, URISyntaxException { + String expectedRequest = Utils.getResourceFileContent("core/iterable.graphql"); + + Document document = document( + operation(QUERY, "iterableHolderQuery", + field("iterableHolder", + args( + arg("iterableHolder", inputObject( + + prop("boolObjectList", List.of(true, false)), + + prop("byteObjectList", List.of( (byte)0, (byte)2, (byte)3)), + + prop("shortObjectList", List.of( (short)78,(short) 789,(short) 645 )), + + prop("intObjectList", List.of( 78, 65, 12354 )), + + prop("longObjectList", List.of( 789L, 947894L, 1874448L )), + + prop("floatObjectList", List.of( 1567.654f, 8765f, 123789456.1851f )), + + prop("doubleObjectList", List.of( 789.3242d, 1815d, 98765421.654897d )), + + prop("bigIntegerList", + List.of( BigInteger.ZERO, BigInteger.ONE, BigInteger.TEN )), + + prop("bigDecimalList", + List.of( BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN )), + + prop("charObjectList", List.of( 'f', 'o', 'o' )), + + prop("stringList", List.of( "foo", "bar", "baz" )), + + prop("uuidList", + List.of(UUID.fromString("fc4bb4f4-13fe-4908-8d6a-afa64f1b56c9"), + UUID.fromString("863c9e3c-7538-41b9-9d63-0852f6a50815"))) + + ))), + field("boolObjectList"), + + field("byteObjectList"), + + field("shortObjectList"), + + field("intObjectList"), + + field("longObjectList"), + + field("floatObjectList"), + + field("doubleObjectList"), + + field("bigIntegerList"), + + field("bigDecimalList"), + + field("charObjectList"), + + field("stringList"), + + field("uuidList") + ))); + + String generatedRequest = document.build(); + AssertGraphQL.assertEquivalentGraphQLRequest(expectedRequest, generatedRequest); + } +} diff --git a/client/tck/src/main/resources/core/arrays.graphql b/client/tck/src/main/resources/core/arrays.graphql index 4b306d724..c35c0e521 100644 --- a/client/tck/src/main/resources/core/arrays.graphql +++ b/client/tck/src/main/resources/core/arrays.graphql @@ -28,6 +28,8 @@ query arrayHolderQuery { charObjectArray: ["f", "o", "o"], stringArray: ["foo", "bar", "baz"], + + uuidArray: ["fc4bb4f4-13fe-4908-8d6a-afa64f1b56c9", "863c9e3c-7538-41b9-9d63-0852f6a50815"] }) { boolPrimitiveArray boolObjectArray @@ -57,5 +59,7 @@ query arrayHolderQuery { charObjectArray stringArray + + uuidArray } } \ No newline at end of file diff --git a/client/tck/src/main/resources/core/iterable.graphql b/client/tck/src/main/resources/core/iterable.graphql new file mode 100644 index 000000000..a1265df45 --- /dev/null +++ b/client/tck/src/main/resources/core/iterable.graphql @@ -0,0 +1,53 @@ +query iterableHolderQuery { + iterableHolder(iterableHolder:{ + + boolObjectList: [true, false] + + byteObjectList: [0, 2, 3] + + shortObjectList: [78, 789, 645] + + intObjectList: [78, 65, 12354] + + longObjectList: [789, 947894, 1874448] + + floatObjectList: [1567.654, 8765.0, 1.23789456E8] + + doubleObjectList: [789.3242, 1815.0, 9.8765421654897E7] + + bigIntegerList: [0, 1, 10] + + bigDecimalList: [0, 1, 10] + + charObjectList: ["f", "o", "o"] + + stringList: ["foo", "bar", "baz"] + + uuidList: ["fc4bb4f4-13fe-4908-8d6a-afa64f1b56c9", "863c9e3c-7538-41b9-9d63-0852f6a50815"] + + }) { + boolObjectList + + byteObjectList + + shortObjectList + + intObjectList + + longObjectList + + floatObjectList + + doubleObjectList + + bigIntegerList + + bigDecimalList + + charObjectList + + stringList + + uuidList + } +} \ No newline at end of file