From 743b016bfa32cd76ef1dd6e30a218adc78a8cccc Mon Sep 17 00:00:00 2001 From: Henry Tao Date: Thu, 7 Sep 2017 14:06:29 -0400 Subject: [PATCH] Add Input class for supporting nulifying input object --- .../templates/APISchema.java.erb | 26 ++++--- .../com/shopify/graphql/support/Input.java | 34 +++++++++ .../shopify/graphql/support/Generated.java | 76 +++++++++++-------- .../graphql/support/GeneratedMinimal.java | 1 + .../graphql/support/IntegrationTest.java | 21 ++++- 5 files changed, 112 insertions(+), 46 deletions(-) create mode 100644 support/src/main/java/com/shopify/graphql/support/Input.java diff --git a/codegen/lib/graphql_java_gen/templates/APISchema.java.erb b/codegen/lib/graphql_java_gen/templates/APISchema.java.erb index 4258c6b..213fb22 100644 --- a/codegen/lib/graphql_java_gen/templates/APISchema.java.erb +++ b/codegen/lib/graphql_java_gen/templates/APISchema.java.erb @@ -12,6 +12,7 @@ import com.shopify.graphql.support.Error; import com.shopify.graphql.support.Query; import com.shopify.graphql.support.SchemaViolationError; import com.shopify.graphql.support.TopLevelResponse; +import com.shopify.graphql.support.Input; <% imports.each do |import| %> import <%= import %>; <% end %> @@ -264,8 +265,7 @@ public class <%= schema_name %> { private <%= java_input_type(field.type) %> <%= escape_reserved_word(field.camelize_name) %>; <% end %> <% type.optional_input_fields.each do |field| %> - private <%= java_input_type(field.type) %> <%= escape_reserved_word(field.camelize_name) %>; - private boolean <%= field.camelize_name %>Seen = false; + private Input<<%= java_input_type(field.type) %>> <%= escape_reserved_word(field.camelize_name) %> = Input.undefined(); <% end %> <% unless type.required_input_fields.empty? %> @@ -291,19 +291,23 @@ public class <%= schema_name %> { <% type.optional_input_fields.each do |field| %> <%= java_annotations(field) %> public <%= java_input_type(field.type) %> get<%= field.classify_name %>() { + return <%= escape_reserved_word(field.camelize_name) %>.getValue(); + } + + public Input<<%= java_input_type(field.type) %>> get<%= field.classify_name %>Input() { return <%= escape_reserved_word(field.camelize_name) %>; } public <%= type.name %> set<%= field.classify_name %>(<%= java_annotations(field, in_argument: true) %><%= java_input_type(field.type) %> <%= escape_reserved_word(field.camelize_name) %>) { - this.<%= escape_reserved_word(field.camelize_name) %> = <%= escape_reserved_word(field.camelize_name) %>; - this.<%= field.camelize_name %>Seen = true; + this.<%= escape_reserved_word(field.camelize_name) %> = Input.value(<%= escape_reserved_word(field.camelize_name) %>); return this; } - // Unsets the <%= escape_reserved_word(field.camelize_name) %> property so that it is not serialized. - public <%= type.name %> unset<%= field.classify_name %>() { - this.<%= escape_reserved_word(field.camelize_name) %> = null; - this.<%= field.camelize_name %>Seen = false; + public <%= type.name %> set<%= field.classify_name %>Input(Input<<%= java_input_type(field.type) %>> <%= escape_reserved_word(field.camelize_name) %>) { + if (<%= escape_reserved_word(field.camelize_name) %> == null) { + throw new IllegalArgumentException("Input can not be null"); + } + this.<%= escape_reserved_word(field.camelize_name) %> = <%= escape_reserved_word(field.camelize_name) %>; return this; } @@ -319,12 +323,12 @@ public class <%= schema_name %> { <%= generate_build_input_code(escape_reserved_word(field.camelize_name), field.type) %> <% end %> <% type.optional_input_fields.each do |field| %> - if (this.<%= field.camelize_name %>Seen) { + if (this.<%= escape_reserved_word(field.camelize_name) %>.isDefined()) { _queryBuilder.append(separator); separator = ","; _queryBuilder.append("<%= field.name %>:"); - if (<%= escape_reserved_word(field.camelize_name) %> != null) { - <%= generate_build_input_code(escape_reserved_word(field.camelize_name), field.type) %> + if (<%= escape_reserved_word(field.camelize_name) %>.getValue() != null) { + <%= generate_build_input_code(escape_reserved_word(field.camelize_name).concat(".getValue()"), field.type) %> } else { _queryBuilder.append("null"); } diff --git a/support/src/main/java/com/shopify/graphql/support/Input.java b/support/src/main/java/com/shopify/graphql/support/Input.java new file mode 100644 index 0000000..4471047 --- /dev/null +++ b/support/src/main/java/com/shopify/graphql/support/Input.java @@ -0,0 +1,34 @@ +package com.shopify.graphql.support; + +import java.io.Serializable; + +/** + * Created by henrytao on 9/7/17. + */ + +public final class Input implements Serializable { + + private final T value; + private final boolean defined; + + public static Input value(@Nullable T value) { + return new Input<>(value, true); + } + + public static Input undefined() { + return new Input<>(null, false); + } + + private Input(T value, boolean defined) { + this.value = value; + this.defined = defined; + } + + public T getValue() { + return value; + } + + public boolean isDefined() { + return defined; + } +} diff --git a/support/src/test/java/com/shopify/graphql/support/Generated.java b/support/src/test/java/com/shopify/graphql/support/Generated.java index 6ce5bf0..e9258b6 100644 --- a/support/src/test/java/com/shopify/graphql/support/Generated.java +++ b/support/src/test/java/com/shopify/graphql/support/Generated.java @@ -12,6 +12,7 @@ import com.shopify.graphql.support.Query; import com.shopify.graphql.support.SchemaViolationError; import com.shopify.graphql.support.TopLevelResponse; +import com.shopify.graphql.support.Input; import com.shopify.graphql.support.ID; @@ -1076,14 +1077,11 @@ public static class SetIntegerInput implements Serializable { private int value; - private LocalDateTime ttl; - private boolean ttlSeen = false; + private Input ttl = Input.undefined(); - private Boolean negate; - private boolean negateSeen = false; + private Input negate = Input.undefined(); - private String apiClient; - private boolean apiClientSeen = false; + private Input apiClient = Input.undefined(); public SetIntegerInput(String key, int value) { this.key = key; @@ -1111,55 +1109,67 @@ public SetIntegerInput setValue(int value) { @Nullable public LocalDateTime getTtl() { + return ttl.getValue(); + } + + public Input getTtlInput() { return ttl; } public SetIntegerInput setTtl(@Nullable LocalDateTime ttl) { - this.ttl = ttl; - this.ttlSeen = true; + this.ttl = Input.value(ttl); return this; } - // Unsets the ttl property so that it is not serialized. - public SetIntegerInput unsetTtl() { - this.ttl = null; - this.ttlSeen = false; + public SetIntegerInput setTtlInput(Input ttl) { + if (ttl == null) { + throw new IllegalArgumentException("Input can not be null"); + } + this.ttl = ttl; return this; } @Nullable public Boolean getNegate() { + return negate.getValue(); + } + + public Input getNegateInput() { return negate; } public SetIntegerInput setNegate(@Nullable Boolean negate) { - this.negate = negate; - this.negateSeen = true; + this.negate = Input.value(negate); return this; } - // Unsets the negate property so that it is not serialized. - public SetIntegerInput unsetNegate() { - this.negate = null; - this.negateSeen = false; + public SetIntegerInput setNegateInput(Input negate) { + if (negate == null) { + throw new IllegalArgumentException("Input can not be null"); + } + this.negate = negate; return this; } @Nullable public String getApiClient() { + return apiClient.getValue(); + } + + public Input getApiClientInput() { return apiClient; } public SetIntegerInput setApiClient(@Nullable String apiClient) { - this.apiClient = apiClient; - this.apiClientSeen = true; + this.apiClient = Input.value(apiClient); return this; } - // Unsets the apiClient property so that it is not serialized. - public SetIntegerInput unsetApiClient() { - this.apiClient = null; - this.apiClientSeen = false; + public SetIntegerInput setApiClientInput(Input apiClient) { + if (apiClient == null) { + throw new IllegalArgumentException("Input can not be null"); + } + this.apiClient = apiClient; return this; } @@ -1177,34 +1187,34 @@ public void appendTo(StringBuilder _queryBuilder) { _queryBuilder.append("value:"); _queryBuilder.append(value); - if (this.ttlSeen) { + if (this.ttl.isDefined()) { _queryBuilder.append(separator); separator = ","; _queryBuilder.append("ttl:"); - if (ttl != null) { - Query.appendQuotedString(_queryBuilder, ttl.toString()); + if (ttl.getValue() != null) { + Query.appendQuotedString(_queryBuilder, ttl.getValue().toString()); } else { _queryBuilder.append("null"); } } - if (this.negateSeen) { + if (this.negate.isDefined()) { _queryBuilder.append(separator); separator = ","; _queryBuilder.append("negate:"); - if (negate != null) { - _queryBuilder.append(negate); + if (negate.getValue() != null) { + _queryBuilder.append(negate.getValue()); } else { _queryBuilder.append("null"); } } - if (this.apiClientSeen) { + if (this.apiClient.isDefined()) { _queryBuilder.append(separator); separator = ","; _queryBuilder.append("api_client:"); - if (apiClient != null) { - Query.appendQuotedString(_queryBuilder, apiClient.toString()); + if (apiClient.getValue() != null) { + Query.appendQuotedString(_queryBuilder, apiClient.getValue().toString()); } else { _queryBuilder.append("null"); } diff --git a/support/src/test/java/com/shopify/graphql/support/GeneratedMinimal.java b/support/src/test/java/com/shopify/graphql/support/GeneratedMinimal.java index 808e6a8..6e61b5a 100644 --- a/support/src/test/java/com/shopify/graphql/support/GeneratedMinimal.java +++ b/support/src/test/java/com/shopify/graphql/support/GeneratedMinimal.java @@ -12,6 +12,7 @@ import com.shopify.graphql.support.Query; import com.shopify.graphql.support.SchemaViolationError; import com.shopify.graphql.support.TopLevelResponse; +import com.shopify.graphql.support.Input; import com.shopify.graphql.support.ID; diff --git a/support/src/test/java/com/shopify/graphql/support/IntegrationTest.java b/support/src/test/java/com/shopify/graphql/support/IntegrationTest.java index 460b52f..551df9b 100644 --- a/support/src/test/java/com/shopify/graphql/support/IntegrationTest.java +++ b/support/src/test/java/com/shopify/graphql/support/IntegrationTest.java @@ -1,5 +1,6 @@ package com.shopify.graphql.support; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.Arrays; import java.util.List; @@ -166,10 +167,26 @@ public void testOptionalFieldOnInput() throws Exception { } @Test - public void testUnsetOptionalFieldOnInput() throws Exception { + public void testOptionalFieldOnInputAsUndefined() throws Exception { String queryString = Generated.mutation(mutation -> mutation - .setInteger(new Generated.SetIntegerInput("answer", 42).setTtl(null).unsetTtl()) + .setInteger(new Generated.SetIntegerInput("answer", 42).setTtlInput(Input.undefined())) ).toString(); assertEquals("mutation{set_integer(input:{key:\"answer\",value:42})}", queryString); } + + @Test + public void testOptionalFieldOnInputAsExplicitNull() throws Exception { + String queryString = Generated.mutation(mutation -> mutation + .setInteger(new Generated.SetIntegerInput("answer", 42).setTtlInput(Input.value(null))) + ).toString(); + assertEquals("mutation{set_integer(input:{key:\"answer\",value:42,ttl:null})}", queryString); + } + + @Test + public void testOptionalFieldOnInputAsInputValue() throws Exception { + String queryString = Generated.mutation(mutation -> mutation + .setInteger(new Generated.SetIntegerInput("answer", 42).setTtlInput(Input.value(LocalDateTime.of(2017, 1, 31, 10, 9, 48)))) + ).toString(); + assertEquals("mutation{set_integer(input:{key:\"answer\",value:42,ttl:\"2017-01-31T10:09:48\"})}", queryString); + } }