1
1
package com .kobylynskyi .graphql .codegen ;
2
2
3
3
import com .kobylynskyi .graphql .codegen .mapper .*;
4
- import com .kobylynskyi .graphql .codegen .model .*;
4
+ import com .kobylynskyi .graphql .codegen .model .DefaultMappingConfigValues ;
5
+ import com .kobylynskyi .graphql .codegen .model .DefinitionTypeDeterminer ;
6
+ import com .kobylynskyi .graphql .codegen .model .MappingConfig ;
7
+ import com .kobylynskyi .graphql .codegen .model .UnsupportedGraphqlDefinitionException ;
5
8
import com .kobylynskyi .graphql .codegen .supplier .MappingConfigSupplier ;
9
+ import com .kobylynskyi .graphql .codegen .utils .Utils ;
6
10
import freemarker .template .TemplateException ;
7
11
import graphql .language .*;
8
12
import lombok .Getter ;
12
16
import java .io .IOException ;
13
17
import java .util .List ;
14
18
import java .util .Map ;
19
+ import java .util .Set ;
20
+ import java .util .stream .Collectors ;
15
21
16
22
import static java .util .stream .Collectors .toList ;
17
23
18
24
/**
19
25
* Generator of:
20
- * - Interface for each GraphQL query
21
- * - Interface for each GraphQL mutation
22
- * - Interface for each GraphQL subscription
23
- * - Class for each GraphQL data type
24
- * - Class for each GraphQL enum type
25
- * - Class for each GraphQL scalar type
26
+ * - Interface for each GraphQL query, mutation, subscription, union and field resolvers
27
+ * - POJO Class for each GraphQL type and input
28
+ * - Enum Class for each GraphQL enum
26
29
*
27
30
* @author kobylynskyi
28
31
* @author valinhadev
@@ -55,6 +58,15 @@ private void initDefaultValues(MappingConfig mappingConfig) {
55
58
if (mappingConfig .getGenerateEqualsAndHashCode () == null ) {
56
59
mappingConfig .setGenerateEqualsAndHashCode (DefaultMappingConfigValues .DEFAULT_EQUALS_AND_HASHCODE );
57
60
}
61
+ if (mappingConfig .getGenerateRequests () == null ) {
62
+ mappingConfig .setGenerateRequests (DefaultMappingConfigValues .DEFAULT_GENERATE_REQUESTS );
63
+ }
64
+ if (mappingConfig .getRequestSuffix () == null ) {
65
+ mappingConfig .setRequestSuffix (DefaultMappingConfigValues .DEFAULT_REQUEST_SUFFIX );
66
+ }
67
+ if (mappingConfig .getResponseProjectionSuffix () == null ) {
68
+ mappingConfig .setResponseProjectionSuffix (DefaultMappingConfigValues .DEFAULT_RESPONSE_PROJECTION_SUFFIX );
69
+ }
58
70
if (mappingConfig .getGenerateToString () == null ) {
59
71
mappingConfig .setGenerateToString (DefaultMappingConfigValues .DEFAULT_TO_STRING );
60
72
}
@@ -64,6 +76,10 @@ private void initDefaultValues(MappingConfig mappingConfig) {
64
76
if (mappingConfig .getGenerateParameterizedFieldsResolvers () == null ) {
65
77
mappingConfig .setGenerateParameterizedFieldsResolvers (DefaultMappingConfigValues .DEFAULT_GENERATE_PARAMETERIZED_FIELDS_RESOLVERS );
66
78
}
79
+ if (mappingConfig .getGenerateRequests ()) {
80
+ // required for request serialization
81
+ mappingConfig .setGenerateToString (true );
82
+ }
67
83
}
68
84
69
85
@@ -72,46 +88,48 @@ public void generate() throws Exception {
72
88
long startTime = System .currentTimeMillis ();
73
89
if (!schemas .isEmpty ()) {
74
90
Document document = GraphqlDocumentParser .getDocument (schemas );
75
- addScalarsToCustomMappingConfig (document );
91
+ initCustomTypeMappings (document );
76
92
processDocument (document );
77
93
}
78
94
long elapsed = System .currentTimeMillis () - startTime ;
79
- System .out .println (String .format ("Finished processing %d schemas in %d ms" , schemas .size (), elapsed ));
95
+ System .out .println (String .format ("Finished processing %d schema(s) in %d ms" , schemas .size (), elapsed ));
80
96
}
81
97
82
98
private void processDocument (Document document ) throws IOException , TemplateException {
99
+ Set <String > typeNames = getAllTypeNames (document );
83
100
for (Definition <?> definition : document .getDefinitions ()) {
84
- GraphqlDefinitionType definitionType ;
85
101
try {
86
- definitionType = DefinitionTypeDeterminer .determine (definition );
87
- } catch (UnsupportedGraphqlDefinitionException ex ) {
88
- continue ;
89
- }
90
- switch (definitionType ) {
91
- case OPERATION :
92
- generateOperation ((ObjectTypeDefinition ) definition );
93
- break ;
94
- case TYPE :
95
- generateType ((ObjectTypeDefinition ) definition , document );
96
- generateFieldResolvers ((ObjectTypeDefinition ) definition );
97
- break ;
98
- case INTERFACE :
99
- generateInterface ((InterfaceTypeDefinition ) definition );
100
- break ;
101
- case ENUM :
102
- generateEnum ((EnumTypeDefinition ) definition );
103
- break ;
104
- case INPUT :
105
- generateInput ((InputObjectTypeDefinition ) definition );
106
- break ;
107
- case UNION :
108
- generateUnion ((UnionTypeDefinition ) definition );
102
+ processDefinition (document , definition , typeNames );
103
+ } catch (UnsupportedGraphqlDefinitionException ignored ) {
109
104
}
110
105
}
111
106
System .out .println (String .format ("Generated %d definitions in folder '%s'" , document .getDefinitions ().size (),
112
107
outputDir .getAbsolutePath ()));
113
108
}
114
109
110
+ private void processDefinition (Document document , Definition <?> definition , Set <String > typeNames ) throws IOException , TemplateException {
111
+ switch (DefinitionTypeDeterminer .determine (definition )) {
112
+ case OPERATION :
113
+ generateOperation ((ObjectTypeDefinition ) definition );
114
+ break ;
115
+ case TYPE :
116
+ generateType ((ObjectTypeDefinition ) definition , document , typeNames );
117
+ generateFieldResolvers ((ObjectTypeDefinition ) definition );
118
+ break ;
119
+ case INTERFACE :
120
+ generateInterface ((InterfaceTypeDefinition ) definition );
121
+ break ;
122
+ case ENUM :
123
+ generateEnum ((EnumTypeDefinition ) definition );
124
+ break ;
125
+ case INPUT :
126
+ generateInput ((InputObjectTypeDefinition ) definition );
127
+ break ;
128
+ case UNION :
129
+ generateUnion ((UnionTypeDefinition ) definition );
130
+ }
131
+ }
132
+
115
133
private void generateUnion (UnionTypeDefinition definition ) throws IOException , TemplateException {
116
134
Map <String , Object > dataModel = UnionDefinitionToDataModelMapper .map (mappingConfig , definition );
117
135
GraphqlCodegenFileCreator .generateFile (FreeMarkerTemplatesRegistry .unionTemplate , dataModel , outputDir );
@@ -124,19 +142,32 @@ private void generateInterface(InterfaceTypeDefinition definition) throws IOExce
124
142
125
143
private void generateOperation (ObjectTypeDefinition definition ) throws IOException , TemplateException {
126
144
if (Boolean .TRUE .equals (mappingConfig .getGenerateApis ())) {
127
- for (FieldDefinition fieldDef : definition .getFieldDefinitions ()) {
128
- Map <String , Object > dataModel = FieldDefinitionToDataModelMapper .map (mappingConfig , fieldDef , definition .getName ());
145
+ for (FieldDefinition operationDef : definition .getFieldDefinitions ()) {
146
+ Map <String , Object > dataModel = FieldDefinitionToDataModelMapper .map (mappingConfig , operationDef , definition .getName ());
129
147
GraphqlCodegenFileCreator .generateFile (FreeMarkerTemplatesRegistry .operationsTemplate , dataModel , outputDir );
130
148
}
131
149
// We need to generate a root object to workaround https://github.com/facebook/relay/issues/112
132
150
Map <String , Object > dataModel = ObjectDefinitionToDataModelMapper .map (mappingConfig , definition );
133
151
GraphqlCodegenFileCreator .generateFile (FreeMarkerTemplatesRegistry .operationsTemplate , dataModel , outputDir );
134
152
}
153
+
154
+ if (Boolean .TRUE .equals (mappingConfig .getGenerateRequests ())) {
155
+ // generate request objects for graphql operations
156
+ for (FieldDefinition operationDef : definition .getFieldDefinitions ()) {
157
+ Map <String , Object > requestDataModel = FieldDefinitionToRequestDataModelMapper .map (mappingConfig , operationDef , definition .getName ());
158
+ GraphqlCodegenFileCreator .generateFile (FreeMarkerTemplatesRegistry .requestTemplate , requestDataModel , outputDir );
159
+ }
160
+ }
135
161
}
136
162
137
- private void generateType (ObjectTypeDefinition definition , Document document ) throws IOException , TemplateException {
163
+ private void generateType (ObjectTypeDefinition definition , Document document , Set < String > typeNames ) throws IOException , TemplateException {
138
164
Map <String , Object > dataModel = TypeDefinitionToDataModelMapper .map (mappingConfig , definition , document );
139
165
GraphqlCodegenFileCreator .generateFile (FreeMarkerTemplatesRegistry .typeTemplate , dataModel , outputDir );
166
+
167
+ if (Boolean .TRUE .equals (mappingConfig .getGenerateRequests ())) {
168
+ Map <String , Object > responseProjDataModel = TypeDefinitionToDataModelMapper .mapResponseProjection (mappingConfig , definition , document , typeNames );
169
+ GraphqlCodegenFileCreator .generateFile (FreeMarkerTemplatesRegistry .responseProjectionTemplate , responseProjDataModel , outputDir );
170
+ }
140
171
}
141
172
142
173
private void generateFieldResolvers (ObjectTypeDefinition definition ) throws IOException , TemplateException {
@@ -154,17 +185,30 @@ private void generateInput(InputObjectTypeDefinition definition) throws IOExcept
154
185
GraphqlCodegenFileCreator .generateFile (FreeMarkerTemplatesRegistry .typeTemplate , dataModel , outputDir );
155
186
}
156
187
188
+ private static Set <String > getAllTypeNames (Document document ) {
189
+ return document .getDefinitionsOfType (ObjectTypeDefinition .class )
190
+ .stream ()
191
+ .filter (typeDef -> !Utils .isGraphqlOperation (typeDef .getName ()))
192
+ .map (ObjectTypeDefinition ::getName )
193
+ .collect (Collectors .toSet ());
194
+ }
195
+
157
196
private void generateEnum (EnumTypeDefinition definition ) throws IOException , TemplateException {
158
197
Map <String , Object > dataModel = EnumDefinitionToDataModelMapper .map (mappingConfig , definition );
159
198
GraphqlCodegenFileCreator .generateFile (FreeMarkerTemplatesRegistry .enumTemplate , dataModel , outputDir );
160
199
}
161
200
162
- private void addScalarsToCustomMappingConfig (Document document ) {
201
+ private void initCustomTypeMappings (Document document ) {
163
202
for (Definition <?> definition : document .getDefinitions ()) {
164
203
if (definition instanceof ScalarTypeDefinition ) {
165
204
String scalarName = ((ScalarTypeDefinition ) definition ).getName ();
166
205
mappingConfig .putCustomTypeMappingIfAbsent (scalarName , "String" );
167
206
}
168
207
}
208
+ mappingConfig .putCustomTypeMappingIfAbsent ("ID" , "String" );
209
+ mappingConfig .putCustomTypeMappingIfAbsent ("String" , "String" );
210
+ mappingConfig .putCustomTypeMappingIfAbsent ("Int" , "Integer" );
211
+ mappingConfig .putCustomTypeMappingIfAbsent ("Float" , "Double" );
212
+ mappingConfig .putCustomTypeMappingIfAbsent ("Boolean" , "Boolean" );
169
213
}
170
214
}
0 commit comments