Skip to content

Commit dc5b277

Browse files
Kotlin, Scala: Support custom serialization of parameters in GraphQLOperationRequest #472
* Support custom serialization of parameters in GraphQLOperationRequest #472 * #473 * #473 Co-authored-by: Bogdan Kobylynskyi <92bogdan@gmail.com>
1 parent 5de7c0a commit dc5b277

17 files changed

+554
-0
lines changed

src/main/resources/templates/kotlin-lang/kotlinClassGraphqlRequest.ftl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ open class ${className}(private val alias: String?) : GraphQLOperationRequest {
3737
}
3838

3939
private val input: MutableMap<String, Any?> = LinkedHashMap()
40+
private val useObjectMapperForInputSerialization: MutableSet<String> = HashSet()
4041

4142
constructor(): this(null)
4243

@@ -54,6 +55,9 @@ open class ${className}(private val alias: String?) : GraphQLOperationRequest {
5455
</#if>
5556
fun set${field.name?replace("`", "")?cap_first}(${field.name}: ${field.type}) {
5657
this.input["${field.originalName}"] = ${field.name}
58+
<#if field.serializeUsingObjectMapper>
59+
this.useObjectMapperForInputSerialization.add("${field.originalName}");
60+
</#if>
5761
}
5862

5963
</#list>
@@ -66,7 +70,9 @@ open class ${className}(private val alias: String?) : GraphQLOperationRequest {
6670

6771
override fun getInput(): MutableMap<String, Any?> = input
6872

73+
override fun getUseObjectMapperForInputSerialization(): MutableSet<String> = useObjectMapperForInputSerialization
6974
<#if equalsAndHashCode>
75+
7076
override fun equals(other: Any?): Boolean {
7177
if (this === other) {
7278
return true

src/main/resources/templates/scala-lang/scalaClassGraphqlRequest.ftl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import java.util.{ Map => JMap }
1010
<#if toString || equalsAndHashCode>
1111
import java.util.Objects
1212
</#if>
13+
import scala.collection.mutable
14+
import scala.collection.JavaConverters._
1315
<#if fields?has_content>
1416
<#if enumImportItSelfInScala?has_content>
1517
<#list fields as field>
@@ -48,6 +50,7 @@ class ${className}(alias: String) extends GraphQLOperationRequest {
4850

4951
<#--use Any be prepared for any contingency-->
5052
private final lazy val input = new JLinkedHashMap[String, java.lang.Object]()
53+
private final lazy val useObjectMapperForInputSerialization: mutable.Set[String] = mutable.Set()
5154

5255
<#if fields?has_content>
5356
<#list fields as field>
@@ -67,6 +70,9 @@ class ${className}(alias: String) extends GraphQLOperationRequest {
6770
<#else>
6871
this.input.put("${field.originalName}", ${field.name})
6972
</#if>
73+
<#if field.serializeUsingObjectMapper>
74+
this.useObjectMapperForInputSerialization.add("${field.originalName}");
75+
</#if>
7076
}
7177

7278
</#list>
@@ -78,6 +84,8 @@ class ${className}(alias: String) extends GraphQLOperationRequest {
7884
override def getAlias(): String = if (alias != null) alias else ${className}.OPERATION_NAME
7985

8086
override def getInput(): JMap[String, java.lang.Object] = input
87+
88+
override def getUseObjectMapperForInputSerialization(): java.util.Set[String] = useObjectMapperForInputSerialization.asJava
8189
<#if equalsAndHashCode>
8290

8391
override def equals(obj: Any): Boolean = {
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.kobylynskyi.graphql.codegen.kotlin;
2+
3+
import com.kobylynskyi.graphql.codegen.TestUtils;
4+
import com.kobylynskyi.graphql.codegen.model.GeneratedLanguage;
5+
import com.kobylynskyi.graphql.codegen.model.MappingConfig;
6+
import com.kobylynskyi.graphql.codegen.utils.Utils;
7+
import org.junit.jupiter.api.AfterEach;
8+
import org.junit.jupiter.api.BeforeEach;
9+
import org.junit.jupiter.api.Test;
10+
11+
import java.io.File;
12+
import java.util.HashMap;
13+
import java.util.Objects;
14+
15+
import static com.kobylynskyi.graphql.codegen.TestUtils.assertSameTrimmedContent;
16+
import static com.kobylynskyi.graphql.codegen.TestUtils.getFileByName;
17+
import static java.util.Collections.*;
18+
19+
class GraphQLCodegenCustomScalarMappingTest {
20+
21+
private final File outputBuildDir = new File("build/generated");
22+
private final File outputJavaClassesDir = new File("build/generated/com/kobylynskyi/graphql/test1");
23+
24+
private MappingConfig mappingConfig;
25+
26+
@BeforeEach
27+
void init() {
28+
mappingConfig = new MappingConfig();
29+
mappingConfig.setPackageName("com.kobylynskyi.graphql.test1");
30+
mappingConfig.setGenerateClient(true);
31+
mappingConfig.setGeneratedLanguage(GeneratedLanguage.KOTLIN);
32+
33+
}
34+
35+
@AfterEach
36+
void cleanup() {
37+
Utils.deleteDir(outputBuildDir);
38+
}
39+
40+
@Test
41+
void generate_CustomTypeMapping_WholeScalar() throws Exception {
42+
mappingConfig.setCustomTypesMapping(new HashMap<>(singletonMap("ZonedDateTime", "String")));
43+
44+
new KotlinGraphQLCodegen(singletonList("src/test/resources/schemas/date-scalar.graphqls"),
45+
outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate();
46+
47+
File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles());
48+
49+
assertSameTrimmedContent(
50+
new File("src/test/resources/expected-classes/kt/custom-type/QueryINeedQueryRequest_whole_scalar.kt.txt"),
51+
getFileByName(files, "QueryINeedQueryRequest.kt"));
52+
}
53+
54+
@Test
55+
void generate_CustomTypeMapping_ScalarOnQueryOnly() throws Exception {
56+
HashMap<String, String> customTypesMapping = new HashMap<>();
57+
customTypesMapping.put("queryINeed.input", "String");
58+
customTypesMapping.put("ZonedDateTime", "java.time.ZonedDateTime");
59+
mappingConfig.setCustomTypesMapping(customTypesMapping);
60+
61+
new KotlinGraphQLCodegen(singletonList("src/test/resources/schemas/date-scalar.graphqls"),
62+
outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate();
63+
64+
File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles());
65+
66+
assertSameTrimmedContent(
67+
new File("src/test/resources/expected-classes/kt/custom-type/QueryINeedQueryRequest.kt.txt"),
68+
getFileByName(files, "QueryINeedQueryRequest.kt"));
69+
assertSameTrimmedContent(
70+
new File("src/test/resources/expected-classes/kt/custom-type/ResponseContainingDate.kt.txt"),
71+
getFileByName(files, "ResponseContainingDate.kt"));
72+
}
73+
74+
@Test
75+
void generate_UseObjectMapperToSerializeFields_Parameter() throws Exception {
76+
HashMap<String, String> customTypesMapping = new HashMap<>();
77+
customTypesMapping.put("queryINeed.input", "ZonedDateTime");
78+
customTypesMapping.put("ZonedDateTime", "java.time.ZonedDateTime");
79+
mappingConfig.setCustomTypesMapping(customTypesMapping);
80+
mappingConfig.setUseObjectMapperForRequestSerialization(singleton("ZonedDateTime"));
81+
new KotlinGraphQLCodegen(singletonList("src/test/resources/schemas/date-scalar.graphqls"),
82+
outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate();
83+
84+
File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles());
85+
86+
assertSameTrimmedContent(new File("src/test/resources/expected-classes/kt/QueryINeedQueryRequest_custom_serializer.kt.txt"),
87+
getFileByName(files, "QueryINeedQueryRequest.kt"));
88+
}
89+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package com.kobylynskyi.graphql.codegen.scala;
2+
3+
import com.kobylynskyi.graphql.codegen.TestUtils;
4+
import com.kobylynskyi.graphql.codegen.java.JavaGraphQLCodegen;
5+
import com.kobylynskyi.graphql.codegen.model.GeneratedLanguage;
6+
import com.kobylynskyi.graphql.codegen.model.MappingConfig;
7+
import com.kobylynskyi.graphql.codegen.utils.Utils;
8+
import org.junit.jupiter.api.AfterEach;
9+
import org.junit.jupiter.api.BeforeEach;
10+
import org.junit.jupiter.api.Test;
11+
12+
import java.io.File;
13+
import java.util.HashMap;
14+
import java.util.Objects;
15+
16+
import static com.kobylynskyi.graphql.codegen.TestUtils.assertSameTrimmedContent;
17+
import static com.kobylynskyi.graphql.codegen.TestUtils.getFileByName;
18+
import static java.util.Collections.*;
19+
20+
class GraphQLCodegenCustomScalarMappingTest {
21+
22+
private final File outputBuildDir = new File("build/generated");
23+
private final File outputJavaClassesDir = new File("build/generated/com/kobylynskyi/graphql/test1");
24+
25+
private MappingConfig mappingConfig;
26+
27+
@BeforeEach
28+
void init() {
29+
mappingConfig = new MappingConfig();
30+
mappingConfig.setPackageName("com.kobylynskyi.graphql.test1");
31+
mappingConfig.setGenerateClient(true);
32+
mappingConfig.setGeneratedLanguage(GeneratedLanguage.SCALA);
33+
34+
}
35+
36+
@AfterEach
37+
void cleanup() {
38+
Utils.deleteDir(outputBuildDir);
39+
}
40+
41+
@Test
42+
void generate_CustomTypeMapping_WholeScalar() throws Exception {
43+
mappingConfig.setCustomTypesMapping(new HashMap<>(singletonMap("ZonedDateTime", "String")));
44+
45+
new ScalaGraphQLCodegen(singletonList("src/test/resources/schemas/date-scalar.graphqls"),
46+
outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate();
47+
48+
File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles());
49+
50+
assertSameTrimmedContent(
51+
new File("src/test/resources/expected-classes/scala/custom-type/QueryINeedQueryRequest_whole_scalar.scala.txt"),
52+
getFileByName(files, "QueryINeedQueryRequest.scala"));
53+
}
54+
55+
@Test
56+
void generate_CustomTypeMapping_ScalarOnQueryOnly() throws Exception {
57+
HashMap<String, String> customTypesMapping = new HashMap<>();
58+
customTypesMapping.put("queryINeed.input", "String");
59+
customTypesMapping.put("ZonedDateTime", "java.time.ZonedDateTime");
60+
mappingConfig.setCustomTypesMapping(customTypesMapping);
61+
62+
new ScalaGraphQLCodegen(singletonList("src/test/resources/schemas/date-scalar.graphqls"),
63+
outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate();
64+
65+
File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles());
66+
67+
assertSameTrimmedContent(
68+
new File("src/test/resources/expected-classes/scala/custom-type/QueryINeedQueryRequest.scala.txt"),
69+
getFileByName(files, "QueryINeedQueryRequest.scala"));
70+
assertSameTrimmedContent(
71+
new File("src/test/resources/expected-classes/scala/custom-type/ResponseContainingDate.scala.txt"),
72+
getFileByName(files, "ResponseContainingDate.scala"));
73+
}
74+
75+
@Test
76+
void generate_UseObjectMapperToSerializeFields_Parameter() throws Exception {
77+
HashMap<String, String> customTypesMapping = new HashMap<>();
78+
customTypesMapping.put("queryINeed.input", "ZonedDateTime");
79+
customTypesMapping.put("ZonedDateTime", "java.time.ZonedDateTime");
80+
mappingConfig.setCustomTypesMapping(customTypesMapping);
81+
mappingConfig.setUseObjectMapperForRequestSerialization(singleton("ZonedDateTime"));
82+
new ScalaGraphQLCodegen(singletonList("src/test/resources/schemas/date-scalar.graphqls"),
83+
outputBuildDir, mappingConfig, TestUtils.getStaticGeneratedInfo()).generate();
84+
85+
File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles());
86+
87+
assertSameTrimmedContent(new File("src/test/resources/expected-classes/scala/QueryINeedQueryRequest_custom_serializer.scala.txt"),
88+
getFileByName(files, "QueryINeedQueryRequest.scala"));
89+
}
90+
}

src/test/resources/expected-classes/kt/AddLabelsToLabelableMutationRequest.kt.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ open class AddLabelsToLabelableMutationRequest(private val alias: String?) : Gra
1616
}
1717

1818
private val input: MutableMap<String, Any?> = LinkedHashMap()
19+
private val useObjectMapperForInputSerialization: MutableSet<String> = HashSet()
1920

2021
constructor(): this(null)
2122

@@ -31,6 +32,8 @@ open class AddLabelsToLabelableMutationRequest(private val alias: String?) : Gra
3132

3233
override fun getInput(): MutableMap<String, Any?> = input
3334

35+
override fun getUseObjectMapperForInputSerialization(): MutableSet<String> = useObjectMapperForInputSerialization
36+
3437
override fun equals(other: Any?): Boolean {
3538
if (this === other) {
3639
return true
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.kobylynskyi.graphql.test1
2+
3+
import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperation
4+
import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperationRequest
5+
import java.util.Objects
6+
7+
@javax.annotation.Generated(
8+
value = ["com.kobylynskyi.graphql.codegen.GraphQLCodegen"],
9+
date = "2020-12-31T23:59:59-0500"
10+
)
11+
open class QueryINeedQueryRequest(private val alias: String?) : GraphQLOperationRequest {
12+
13+
companion object {
14+
const val OPERATION_NAME: String = "queryINeed"
15+
val OPERATION_TYPE: GraphQLOperation = GraphQLOperation.QUERY
16+
}
17+
18+
private val input: MutableMap<String, Any?> = LinkedHashMap()
19+
private val useObjectMapperForInputSerialization: MutableSet<String> = HashSet()
20+
21+
constructor(): this(null)
22+
23+
fun setInput(input: ZonedDateTime) {
24+
this.input["input"] = input
25+
this.useObjectMapperForInputSerialization.add("input");
26+
}
27+
28+
override fun getOperationType(): GraphQLOperation = OPERATION_TYPE
29+
30+
override fun getOperationName(): String = OPERATION_NAME
31+
32+
override fun getAlias(): String? = alias ?: OPERATION_NAME
33+
34+
override fun getInput(): MutableMap<String, Any?> = input
35+
36+
override fun getUseObjectMapperForInputSerialization(): MutableSet<String> = useObjectMapperForInputSerialization
37+
38+
override fun toString(): String = Objects.toString(input)
39+
40+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.kobylynskyi.graphql.test1
2+
3+
import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperation
4+
import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperationRequest
5+
import java.util.Objects
6+
7+
@javax.annotation.Generated(
8+
value = ["com.kobylynskyi.graphql.codegen.GraphQLCodegen"],
9+
date = "2020-12-31T23:59:59-0500"
10+
)
11+
open class QueryINeedQueryRequest(private val alias: String?) : GraphQLOperationRequest {
12+
13+
companion object {
14+
const val OPERATION_NAME: String = "queryINeed"
15+
val OPERATION_TYPE: GraphQLOperation = GraphQLOperation.QUERY
16+
}
17+
18+
private val input: MutableMap<String, Any?> = LinkedHashMap()
19+
private val useObjectMapperForInputSerialization: MutableSet<String> = HashSet()
20+
21+
constructor(): this(null)
22+
23+
fun setInput(input: String) {
24+
this.input["input"] = input
25+
}
26+
27+
override fun getOperationType(): GraphQLOperation = OPERATION_TYPE
28+
29+
override fun getOperationName(): String = OPERATION_NAME
30+
31+
override fun getAlias(): String? = alias ?: OPERATION_NAME
32+
33+
override fun getInput(): MutableMap<String, Any?> = input
34+
35+
override fun getUseObjectMapperForInputSerialization(): MutableSet<String> = useObjectMapperForInputSerialization
36+
37+
override fun toString(): String = Objects.toString(input)
38+
39+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.kobylynskyi.graphql.test1
2+
3+
import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperation
4+
import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperationRequest
5+
import java.util.Objects
6+
7+
@javax.annotation.Generated(
8+
value = ["com.kobylynskyi.graphql.codegen.GraphQLCodegen"],
9+
date = "2020-12-31T23:59:59-0500"
10+
)
11+
open class QueryINeedQueryRequest(private val alias: String?) : GraphQLOperationRequest {
12+
13+
companion object {
14+
const val OPERATION_NAME: String = "queryINeed"
15+
val OPERATION_TYPE: GraphQLOperation = GraphQLOperation.QUERY
16+
}
17+
18+
private val input: MutableMap<String, Any?> = LinkedHashMap()
19+
private val useObjectMapperForInputSerialization: MutableSet<String> = HashSet()
20+
21+
constructor(): this(null)
22+
23+
fun setInput(input: String) {
24+
this.input["input"] = input
25+
}
26+
27+
override fun getOperationType(): GraphQLOperation = OPERATION_TYPE
28+
29+
override fun getOperationName(): String = OPERATION_NAME
30+
31+
override fun getAlias(): String? = alias ?: OPERATION_NAME
32+
33+
override fun getInput(): MutableMap<String, Any?> = input
34+
35+
override fun getUseObjectMapperForInputSerialization(): MutableSet<String> = useObjectMapperForInputSerialization
36+
37+
override fun toString(): String = Objects.toString(input)
38+
39+
}

0 commit comments

Comments
 (0)