GraphQLCodegen.java 26.6 KB
Newer Older
1 2
package com.kobylynskyi.graphql.codegen;

3
import com.kobylynskyi.graphql.codegen.mapper.DataModelMapperFactory;
4
import com.kobylynskyi.graphql.codegen.mapper.FieldDefinitionToParameterMapper;
5
import com.kobylynskyi.graphql.codegen.model.ApiInterfaceStrategy;
6 7
import com.kobylynskyi.graphql.codegen.model.ApiNamePrefixStrategy;
import com.kobylynskyi.graphql.codegen.model.ApiRootInterfaceStrategy;
8
import com.kobylynskyi.graphql.codegen.model.GeneratedInformation;
9
import com.kobylynskyi.graphql.codegen.model.MappingConfig;
10
import com.kobylynskyi.graphql.codegen.model.MappingConfigConstants;
11
import com.kobylynskyi.graphql.codegen.model.MappingContext;
12
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDefinition;
13 14 15 16 17 18 19 20
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDocument;
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedEnumTypeDefinition;
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedFieldDefinition;
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedInputObjectTypeDefinition;
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedInterfaceTypeDefinition;
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedObjectTypeDefinition;
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedScalarTypeDefinition;
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedUnionTypeDefinition;
A
Alberto Valiña 已提交
21
import com.kobylynskyi.graphql.codegen.supplier.MappingConfigSupplier;
22
import com.kobylynskyi.graphql.codegen.utils.Utils;
23 24
import graphql.language.FieldDefinition;
import graphql.language.ScalarTypeExtensionDefinition;
25 26

import java.io.File;
B
Bogdan Kobylynskyi 已提交
27
import java.io.IOException;
28 29 30 31 32 33
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
34

35 36
import static java.util.stream.Collectors.toList;

37
/**
38 39
 * Generates classes based on GraphQL schema.
 * Extendable for customizing code generation for other JVM languages
40 41
 *
 * @author kobylynskyi
A
Alberto Valiña 已提交
42
 * @author valinhadev
43
 */
44 45 46
public abstract class GraphQLCodegen {

    protected final MappingConfig mappingConfig;
47

48
    private final List<String> schemas;
49
    private final String introspectionResult;
50 51
    private final File outputDir;
    private final GeneratedInformation generatedInformation;
52
    private final DataModelMapperFactory dataModelMapperFactory;
53

54
    // used in tests
B
Bogdan Kobylynskyi 已提交
55
    protected GraphQLCodegen(List<String> schemas,
56 57 58 59
                             File outputDir,
                             MappingConfig mappingConfig,
                             GeneratedInformation generatedInformation,
                             MapperFactory mapperFactory) {
60
        this(schemas, null, outputDir, mappingConfig, null, generatedInformation, mapperFactory);
A
Alberto Valiña 已提交
61 62
    }

63
    // used in tests
B
Bogdan Kobylynskyi 已提交
64
    protected GraphQLCodegen(String introspectionResult,
65 66 67 68
                             File outputDir,
                             MappingConfig mappingConfig,
                             GeneratedInformation generatedInformation,
                             MapperFactory mapperFactory) {
69
        this(null, introspectionResult, outputDir, mappingConfig, null, generatedInformation, mapperFactory);
70 71 72
    }

    // used in plugins
B
Bogdan Kobylynskyi 已提交
73
    protected GraphQLCodegen(List<String> schemas,
74 75 76 77 78
                             String introspectionResult,
                             File outputDir,
                             MappingConfig mappingConfig,
                             MappingConfigSupplier externalMappingConfigSupplier,
                             MapperFactory mapperFactory) {
79
        this(schemas, introspectionResult, outputDir, mappingConfig, externalMappingConfigSupplier, new GeneratedInformation(), mapperFactory);
80 81
    }

82
    // used by other constructors
B
Bogdan Kobylynskyi 已提交
83
    protected GraphQLCodegen(List<String> schemas,
84 85 86 87 88 89
                             String introspectionResult,
                             File outputDir,
                             MappingConfig mappingConfig,
                             MappingConfigSupplier externalMappingConfigSupplier,
                             GeneratedInformation generatedInformation,
                             MapperFactory mapperFactory) {
90
        this.schemas = schemas;
91
        this.introspectionResult = introspectionResult;
92 93
        this.outputDir = outputDir;
        this.mappingConfig = mappingConfig;
A
Alberto Valiña 已提交
94
        this.mappingConfig.combine(externalMappingConfigSupplier != null ? externalMappingConfigSupplier.get() : null);
95 96 97
        this.generatedInformation = generatedInformation;
        this.dataModelMapperFactory = new DataModelMapperFactory(mapperFactory);

A
Alberto Valiña 已提交
98
        initDefaultValues(mappingConfig);
99
        validateConfigs(mappingConfig);
100
        sanitizeValues(mappingConfig);
A
Alberto Valiña 已提交
101 102
    }

103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
    private static void sanitizeValues(MappingConfig mappingConfig) {
        mappingConfig.setModelValidationAnnotation(
                Utils.replaceLeadingAtSign(mappingConfig.getModelValidationAnnotation()));

        Map<String, List<String>> customAnnotationsMapping = mappingConfig.getCustomAnnotationsMapping();
        if (customAnnotationsMapping != null) {
            for (Map.Entry<String, List<String>> entry : customAnnotationsMapping.entrySet()) {
                if (entry.getValue() != null) {
                    entry.setValue(entry.getValue().stream().map(Utils::replaceLeadingAtSign).collect(toList()));
                }
            }
        }
        Map<String, List<String>> directiveAnnotationsMapping = mappingConfig.getDirectiveAnnotationsMapping();
        if (directiveAnnotationsMapping != null) {
            for (Map.Entry<String, List<String>> entry : directiveAnnotationsMapping.entrySet()) {
                if (entry.getValue() != null) {
                    entry.setValue(entry.getValue().stream().map(Utils::replaceLeadingAtSign).collect(toList()));
                }
            }
        }
    }

    protected void initDefaultValues(MappingConfig mappingConfig) {
A
Alberto Valiña 已提交
126
        if (mappingConfig.getModelValidationAnnotation() == null) {
127
            mappingConfig.setModelValidationAnnotation(MappingConfigConstants.DEFAULT_VALIDATION_ANNOTATION);
A
Alberto Valiña 已提交
128
        }
129
        if (mappingConfig.getGenerateBuilder() == null) {
130
            mappingConfig.setGenerateBuilder(MappingConfigConstants.DEFAULT_BUILDER);
131
        }
A
Alberto Valiña 已提交
132
        if (mappingConfig.getGenerateEqualsAndHashCode() == null) {
133
            mappingConfig.setGenerateEqualsAndHashCode(MappingConfigConstants.DEFAULT_EQUALS_AND_HASHCODE);
A
Alberto Valiña 已提交
134
        }
135 136
        if (mappingConfig.getGenerateClient() == null) {
            mappingConfig.setGenerateClient(MappingConfigConstants.DEFAULT_GENERATE_CLIENT);
137 138
        }
        if (mappingConfig.getRequestSuffix() == null) {
139
            mappingConfig.setRequestSuffix(MappingConfigConstants.DEFAULT_REQUEST_SUFFIX);
140
        }
141 142 143
        if (mappingConfig.getResponseSuffix() == null) {
            mappingConfig.setResponseSuffix(MappingConfigConstants.DEFAULT_RESPONSE_SUFFIX);
        }
144
        if (mappingConfig.getResponseProjectionSuffix() == null) {
145
            mappingConfig.setResponseProjectionSuffix(MappingConfigConstants.DEFAULT_RESPONSE_PROJECTION_SUFFIX);
146
        }
147
        if (mappingConfig.getParametrizedInputSuffix() == null) {
148
            mappingConfig.setParametrizedInputSuffix(MappingConfigConstants.DEFAULT_PARAMETRIZED_INPUT_SUFFIX);
149
        }
150
        if (mappingConfig.getGenerateImmutableModels() == null) {
151
            mappingConfig.setGenerateImmutableModels(MappingConfigConstants.DEFAULT_GENERATE_IMMUTABLE_MODELS);
152
        }
A
Alberto Valiña 已提交
153
        if (mappingConfig.getGenerateToString() == null) {
154
            mappingConfig.setGenerateToString(MappingConfigConstants.DEFAULT_TO_STRING);
A
Alberto Valiña 已提交
155 156
        }
        if (mappingConfig.getGenerateApis() == null) {
157
            mappingConfig.setGenerateApis(MappingConfigConstants.DEFAULT_GENERATE_APIS);
A
Alberto Valiña 已提交
158
        }
159
        if (mappingConfig.getApiNameSuffix() == null) {
160 161 162 163
            mappingConfig.setApiNameSuffix(MappingConfigConstants.DEFAULT_RESOLVER_SUFFIX);
        }
        if (mappingConfig.getTypeResolverSuffix() == null) {
            mappingConfig.setTypeResolverSuffix(MappingConfigConstants.DEFAULT_RESOLVER_SUFFIX);
164
        }
165
        if (mappingConfig.getGenerateParameterizedFieldsResolvers() == null) {
166
            mappingConfig.setGenerateParameterizedFieldsResolvers(MappingConfigConstants.DEFAULT_GENERATE_PARAMETERIZED_FIELDS_RESOLVERS);
167
        }
168
        if (mappingConfig.getGenerateExtensionFieldsResolvers() == null) {
169
            mappingConfig.setGenerateExtensionFieldsResolvers(MappingConfigConstants.DEFAULT_GENERATE_EXTENSION_FIELDS_RESOLVERS);
170
        }
171
        if (mappingConfig.getGenerateDataFetchingEnvironmentArgumentInApis() == null) {
172
            mappingConfig.setGenerateDataFetchingEnvironmentArgumentInApis(MappingConfigConstants.DEFAULT_GENERATE_DATA_FETCHING_ENV);
173
        }
174 175 176
        if (mappingConfig.getGenerateModelsForRootTypes() == null) {
            mappingConfig.setGenerateModelsForRootTypes(MappingConfigConstants.DEFAULT_GENERATE_MODELS_FOR_ROOT_TYPES);
        }
177 178 179
        if (mappingConfig.getGenerateApisWithThrowsException() == null) {
            mappingConfig.setGenerateApisWithThrowsException(MappingConfigConstants.DEFAULT_GENERATE_APIS_WITH_THROWS_EXCEPTION);
        }
180 181 182
        if (mappingConfig.getAddGeneratedAnnotation() == null) {
            mappingConfig.setAddGeneratedAnnotation(MappingConfigConstants.DEFAULT_ADD_GENERATED_ANNOTATION);
        }
183 184 185
        if (mappingConfig.getUseOptionalForNullableReturnTypes() == null) {
            mappingConfig.setUseOptionalForNullableReturnTypes(MappingConfigConstants.DEFAULT_USE_OPTIONAL_FOR_NULLABLE_RETURN_TYPES);
        }
186 187 188 189 190 191
        if (mappingConfig.getApiNamePrefixStrategy() == null) {
            mappingConfig.setApiNamePrefixStrategy(MappingConfigConstants.DEFAULT_API_NAME_PREFIX_STRATEGY);
        }
        if (mappingConfig.getApiRootInterfaceStrategy() == null) {
            mappingConfig.setApiRootInterfaceStrategy(MappingConfigConstants.DEFAULT_API_ROOT_INTERFACE_STRATEGY);
        }
192 193 194
        if (mappingConfig.getApiInterfaceStrategy() == null) {
            mappingConfig.setApiInterfaceStrategy(MappingConfigConstants.DEFAULT_API_INTERFACE_STRATEGY);
        }
B
Bogdan Kobylynskyi 已提交
195
        if (Boolean.TRUE.equals(mappingConfig.getGenerateClient())) {
196 197 198
            // required for request serialization
            mappingConfig.setGenerateToString(true);
        }
199 200 201
        if (mappingConfig.getResponseProjectionMaxDepth() == null) {
            mappingConfig.setResponseProjectionMaxDepth(MappingConfigConstants.DEFAULT_RESPONSE_PROJECTION_MAX_DEPTH);
        }
202 203 204
        if (mappingConfig.getGeneratedLanguage() == null) {
            mappingConfig.setGeneratedLanguage(MappingConfigConstants.DEFAULT_GENERATED_LANGUAGE);
        }
205 206
    }

207 208 209 210 211 212
    private void validateConfigs(MappingConfig mappingConfig) {
        if (!Utils.isEmpty(schemas) && introspectionResult != null ||
                (Utils.isEmpty(schemas) && introspectionResult == null)) {
            // either schemas or introspection result should be provided
            throw new IllegalArgumentException("Either graphql schema path or introspection result path should be supplied");
        }
213 214
        if (mappingConfig.getApiRootInterfaceStrategy() == ApiRootInterfaceStrategy.INTERFACE_PER_SCHEMA &&
                mappingConfig.getApiNamePrefixStrategy() == ApiNamePrefixStrategy.CONSTANT) {
215
            // we will have a conflict in case there is "type Query" in multiple graphql schema files
216 217
            throw new IllegalArgumentException("API prefix should not be CONSTANT for INTERFACE_PER_SCHEMA option");
        }
B
Bogdan Kobylynskyi 已提交
218 219 220
        if (Boolean.TRUE.equals(mappingConfig.getGenerateApis())
                && Boolean.TRUE.equals(mappingConfig.getGenerateModelsForRootTypes())
                && mappingConfig.getApiNamePrefixStrategy() == ApiNamePrefixStrategy.CONSTANT) {
221 222 223 224 225 226 227 228 229 230 231 232 233
            // checking for conflict between root type model classes and api interfaces
            if (Utils.stringsEqualIgnoreSpaces(mappingConfig.getApiNamePrefix(), mappingConfig.getModelNamePrefix()) &&
                    Utils.stringsEqualIgnoreSpaces(mappingConfig.getApiNameSuffix(), mappingConfig.getModelNameSuffix())) {
                // we will have a conflict between model pojo (Query.java) and api interface (Query.java)
                throw new IllegalArgumentException("Either disable APIs generation or set different Prefix/Suffix for API classes and model classes");
            }
            // checking for conflict between root type model resolver classes and api interfaces
            if (Utils.stringsEqualIgnoreSpaces(mappingConfig.getApiNamePrefix(), mappingConfig.getTypeResolverPrefix()) &&
                    Utils.stringsEqualIgnoreSpaces(mappingConfig.getApiNameSuffix(), mappingConfig.getTypeResolverSuffix())) {
                // we will have a conflict between model resolver interface (QueryResolver.java) and api interface resolver (QueryResolver.java)
                throw new IllegalArgumentException("Either disable APIs generation or set different Prefix/Suffix for API classes and type resolver classes");
            }
        }
234 235
    }

B
Bogdan Kobylynskyi 已提交
236
    public List<File> generate() throws IOException {
237
        GraphQLCodegenFileCreator.prepareOutputDir(outputDir);
238
        long startTime = System.currentTimeMillis();
239
        List<File> generatedFiles = Collections.emptyList();
240 241 242 243
        if (!Utils.isEmpty(schemas)) {
            ExtendedDocument document = GraphQLDocumentParser.getDocumentFromSchemas(mappingConfig, schemas);
            initCustomTypeMappings(document.getScalarDefinitions());
            generatedFiles = processDefinitions(document);
244 245
            System.out.printf("Finished processing %d schema(s) in %d ms%n", schemas.size(),
                    System.currentTimeMillis() - startTime);
246 247
        } else if (introspectionResult != null) {
            ExtendedDocument document = GraphQLDocumentParser.getDocumentFromIntrospectionResult(mappingConfig, introspectionResult);
248
            initCustomTypeMappings(document.getScalarDefinitions());
249
            generatedFiles = processDefinitions(document);
250 251
            System.out.printf("Finished processing introspection result in %d ms%n",
                    System.currentTimeMillis() - startTime);
252
        }
253

254
        return generatedFiles;
255 256
    }

257
    private List<File> processDefinitions(ExtendedDocument document) {
梦境迷离's avatar
梦境迷离 已提交
258
        MappingContext context = new MappingContext(mappingConfig, document, generatedInformation, dataModelMapperFactory);
259
        List<File> generatedFiles = new ArrayList<>();
260 261 262
        for (ExtendedEnumTypeDefinition extendedEnumTypeDefinition : document.getEnumDefinitions()) {
            generatedFiles.add(generateEnum(context, extendedEnumTypeDefinition));
        }
梦境迷离's avatar
梦境迷离 已提交
263 264 265
        for (ExtendedInterfaceTypeDefinition extendedInterfaceTypeDefinition : document.getInterfaceDefinitions()) {
            generatedFiles.addAll(generateInterface(context, extendedInterfaceTypeDefinition));
        }
266
        for (ExtendedObjectTypeDefinition extendedObjectTypeDefinition : document.getTypeDefinitions()) {
267
            generatedFiles.addAll(generateType(context, extendedObjectTypeDefinition));
268 269
        }
        for (ExtendedObjectTypeDefinition extendedObjectTypeDefinition : document.getTypeDefinitions()) {
270
            generateFieldResolver(context, extendedObjectTypeDefinition.getFieldDefinitions(), extendedObjectTypeDefinition)
271 272 273
                    .ifPresent(generatedFiles::add);
        }
        for (ExtendedObjectTypeDefinition extendedObjectTypeDefinition : document.getOperationDefinitions()) {
B
Bogdan Kobylynskyi 已提交
274
            if (Boolean.TRUE.equals(mappingConfig.getGenerateApis())) {
275 276
                generatedFiles.addAll(generateServerOperations(context, extendedObjectTypeDefinition));
            }
B
Bogdan Kobylynskyi 已提交
277
            if (Boolean.TRUE.equals(mappingConfig.getGenerateClient())) {
278 279
                generatedFiles.addAll(generateClient(context, extendedObjectTypeDefinition));
            }
280 281
        }
        for (ExtendedInputObjectTypeDefinition extendedInputObjectTypeDefinition : document.getInputDefinitions()) {
282
            generatedFiles.add(generateInput(context, extendedInputObjectTypeDefinition));
283 284
        }
        for (ExtendedUnionTypeDefinition extendedUnionTypeDefinition : document.getUnionDefinitions()) {
285
            generatedFiles.addAll(generateUnion(context, extendedUnionTypeDefinition));
286 287
        }
        for (ExtendedInterfaceTypeDefinition definition : document.getInterfaceDefinitions()) {
288
            generateFieldResolver(context, definition.getFieldDefinitions(), definition).ifPresent(generatedFiles::add);
289
        }
290
        System.out.printf("Generated %d definition classes in folder %s%n", generatedFiles.size(), outputDir.getAbsolutePath());
291
        return generatedFiles;
292 293
    }

294 295
    private List<File> generateUnion(MappingContext mappingContext, ExtendedUnionTypeDefinition definition) {
        List<File> generatedFiles = new ArrayList<>();
296
        Map<String, Object> dataModel = dataModelMapperFactory.getUnionDefinitionMapper().map(mappingContext, definition);
297
        generatedFiles.add(GraphQLCodegenFileCreator.generateFile(mappingContext, FreeMarkerTemplateType.UNION, dataModel, outputDir));
298 299

        if (Boolean.TRUE.equals(mappingConfig.getGenerateClient())) {
300
            Map<String, Object> responseProjDataModel = dataModelMapperFactory.getRequestResponseDefinitionMapper().mapResponseProjection(mappingContext, definition);
301
            generatedFiles.add(GraphQLCodegenFileCreator.generateFile(mappingContext, FreeMarkerTemplateType.RESPONSE_PROJECTION, responseProjDataModel, outputDir));
302 303
        }
        return generatedFiles;
304 305
    }

306 307
    private List<File> generateInterface(MappingContext mappingContext, ExtendedInterfaceTypeDefinition definition) {
        List<File> generatedFiles = new ArrayList<>();
308
        Map<String, Object> dataModel = dataModelMapperFactory.getInterfaceDefinitionMapper().map(mappingContext, definition);
309
        generatedFiles.add(GraphQLCodegenFileCreator.generateFile(mappingContext, FreeMarkerTemplateType.INTERFACE, dataModel, outputDir));
310 311

        if (Boolean.TRUE.equals(mappingConfig.getGenerateClient())) {
312
            Map<String, Object> responseProjDataModel = dataModelMapperFactory.getRequestResponseDefinitionMapper().mapResponseProjection(mappingContext, definition);
313
            generatedFiles.add(GraphQLCodegenFileCreator.generateFile(mappingContext, FreeMarkerTemplateType.RESPONSE_PROJECTION, responseProjDataModel, outputDir));
314 315 316

            for (ExtendedFieldDefinition fieldDefinition : definition.getFieldDefinitions()) {
                if (!Utils.isEmpty(fieldDefinition.getInputValueDefinitions())) {
317
                    Map<String, Object> fieldProjDataModel = dataModelMapperFactory.getRequestResponseDefinitionMapper().mapParametrizedInput(mappingContext, fieldDefinition, definition);
318
                    generatedFiles.add(GraphQLCodegenFileCreator.generateFile(mappingContext, FreeMarkerTemplateType.PARAMETRIZED_INPUT, fieldProjDataModel, outputDir));
319 320
                }
            }
321 322
        }
        return generatedFiles;
323 324
    }

325
    private List<File> generateServerOperations(MappingContext mappingContext, ExtendedObjectTypeDefinition definition) {
326
        List<File> generatedFiles = new ArrayList<>();
327 328 329 330 331 332 333 334
        // Generate a root interface with all operations inside
        // Relates to https://github.com/facebook/relay/issues/112
        switch (mappingContext.getApiRootInterfaceStrategy()) {
            case INTERFACE_PER_SCHEMA:
                for (ExtendedObjectTypeDefinition defInFile : definition.groupBySourceLocationFile().values()) {
                    generatedFiles.add(generateRootApi(mappingContext, defInFile));
                }
                break;
335 336
            case DO_NOT_GENERATE:
                break;
337 338 339 340 341 342
            case SINGLE_INTERFACE:
            default:
                generatedFiles.add(generateRootApi(mappingContext, definition));
                break;
        }

343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
        if (mappingContext.getApiInterfaceStrategy() == ApiInterfaceStrategy.INTERFACE_PER_OPERATION) {
            // Generate separate interfaces for all queries, mutations and subscriptions
            List<String> fieldNames = definition.getFieldDefinitions().stream().map(FieldDefinition::getName).collect(toList());
            switch (mappingContext.getApiNamePrefixStrategy()) {
                case FOLDER_NAME_AS_PREFIX:
                    for (ExtendedObjectTypeDefinition fileDef : definition.groupBySourceLocationFolder().values()) {
                        generatedFiles.addAll(generateApis(mappingContext, fileDef, fieldNames));
                    }
                    break;
                case FILE_NAME_AS_PREFIX:
                    for (ExtendedObjectTypeDefinition fileDef : definition.groupBySourceLocationFile().values()) {
                        generatedFiles.addAll(generateApis(mappingContext, fileDef, fieldNames));
                    }
                    break;
                case CONSTANT:
                default:
                    generatedFiles.addAll(generateApis(mappingContext, definition, fieldNames));
                    break;
            }
362
        }
363 364
        return generatedFiles;
    }
365

366 367 368 369
    private List<File> generateClient(MappingContext mappingContext, ExtendedObjectTypeDefinition definition) {
        List<File> generatedFiles = new ArrayList<>();
        List<String> fieldNames = definition.getFieldDefinitions().stream().map(FieldDefinition::getName).collect(toList());
        for (ExtendedFieldDefinition operationDef : definition.getFieldDefinitions()) {
370
            Map<String, Object> requestDataModel = dataModelMapperFactory.getRequestResponseDefinitionMapper().mapRequest(mappingContext, operationDef, definition.getName(), fieldNames);
371
            generatedFiles.add(GraphQLCodegenFileCreator.generateFile(mappingContext, FreeMarkerTemplateType.REQUEST, requestDataModel, outputDir));
372

373
            Map<String, Object> responseDataModel = dataModelMapperFactory.getRequestResponseDefinitionMapper().mapResponse(mappingContext, operationDef, definition.getName(), fieldNames);
374
            generatedFiles.add(GraphQLCodegenFileCreator.generateFile(mappingContext, FreeMarkerTemplateType.RESPONSE, responseDataModel, outputDir));
375
        }
376
        return generatedFiles;
377 378
    }

379 380 381
    private List<File> generateApis(MappingContext mappingContext, ExtendedObjectTypeDefinition definition, List<String> fieldNames) {
        List<File> generatedFiles = new ArrayList<>();
        for (ExtendedFieldDefinition operationDef : definition.getFieldDefinitions()) {
382
            Map<String, Object> dataModel = dataModelMapperFactory.getFieldDefinitionsToResolverMapper().mapRootTypeField(mappingContext, operationDef, definition.getName(), fieldNames);
383
            generatedFiles.add(GraphQLCodegenFileCreator.generateFile(mappingContext, FreeMarkerTemplateType.OPERATIONS, dataModel, outputDir));
384 385 386 387 388
        }
        return generatedFiles;
    }

    private File generateRootApi(MappingContext mappingContext, ExtendedObjectTypeDefinition definition) {
389
        Map<String, Object> dataModel = dataModelMapperFactory.getFieldDefinitionsToResolverMapper().mapRootTypeFields(mappingContext, definition);
390
        return GraphQLCodegenFileCreator.generateFile(mappingContext, FreeMarkerTemplateType.OPERATIONS, dataModel, outputDir);
391 392
    }

393
    private List<File> generateType(MappingContext mappingContext, ExtendedObjectTypeDefinition definition) {
394
        List<File> generatedFiles = new ArrayList<>();
395
        Map<String, Object> dataModel = dataModelMapperFactory.getTypeDefinitionMapper().map(mappingContext, definition);
396
        generatedFiles.add(GraphQLCodegenFileCreator.generateFile(mappingContext, FreeMarkerTemplateType.TYPE, dataModel, outputDir));
397

B
Bogdan Kobylynskyi 已提交
398
        if (Boolean.TRUE.equals(mappingConfig.getGenerateClient())) {
399
            Map<String, Object> responseProjDataModel = dataModelMapperFactory.getRequestResponseDefinitionMapper().mapResponseProjection(mappingContext, definition);
400
            generatedFiles.add(GraphQLCodegenFileCreator.generateFile(mappingContext, FreeMarkerTemplateType.RESPONSE_PROJECTION, responseProjDataModel, outputDir));
401 402 403

            for (ExtendedFieldDefinition fieldDefinition : definition.getFieldDefinitions()) {
                if (!Utils.isEmpty(fieldDefinition.getInputValueDefinitions())) {
404
                    Map<String, Object> fieldProjDataModel = dataModelMapperFactory.getRequestResponseDefinitionMapper().mapParametrizedInput(mappingContext, fieldDefinition, definition);
405
                    generatedFiles.add(GraphQLCodegenFileCreator.generateFile(mappingContext, FreeMarkerTemplateType.PARAMETRIZED_INPUT, fieldProjDataModel, outputDir));
406 407
                }
            }
408
        }
409
        return generatedFiles;
410 411
    }

412 413 414
    private Optional<File> generateFieldResolver(MappingContext mappingContext,
                                                 List<ExtendedFieldDefinition> fieldDefinitions,
                                                 ExtendedDefinition<?, ?> parentDefinition) {
415 416 417 418 419
        if (Boolean.TRUE.equals(mappingConfig.getGenerateApis())) {
            List<ExtendedFieldDefinition> fieldDefsWithResolvers = fieldDefinitions.stream()
                    .filter(fieldDef -> FieldDefinitionToParameterMapper.generateResolversForField(mappingContext, fieldDef, parentDefinition))
                    .collect(toList());
            if (!fieldDefsWithResolvers.isEmpty()) {
420
                Map<String, Object> dataModel = dataModelMapperFactory.getFieldDefinitionsToResolverMapper().mapToTypeResolver(mappingContext, fieldDefsWithResolvers, parentDefinition.getName());
421
                return Optional.of(GraphQLCodegenFileCreator.generateFile(mappingContext, FreeMarkerTemplateType.OPERATIONS, dataModel, outputDir));
422
            }
423
        }
424
        return Optional.empty();
425 426
    }

427
    private File generateInput(MappingContext mappingContext, ExtendedInputObjectTypeDefinition definition) {
428
        Map<String, Object> dataModel = dataModelMapperFactory.getInputDefinitionMapper().map(mappingContext, definition);
429
        return GraphQLCodegenFileCreator.generateFile(mappingContext, FreeMarkerTemplateType.TYPE, dataModel, outputDir);
430 431
    }

432
    private File generateEnum(MappingContext mappingContext, ExtendedEnumTypeDefinition definition) {
433
        Map<String, Object> dataModel = dataModelMapperFactory.getEnumDefinitionMapper().map(mappingContext, definition);
434
        return GraphQLCodegenFileCreator.generateFile(mappingContext, FreeMarkerTemplateType.ENUM, dataModel, outputDir);
435 436
    }

437
    protected void initCustomTypeMappings(Collection<ExtendedScalarTypeDefinition> scalarTypeDefinitions) {
438
        for (ExtendedScalarTypeDefinition definition : scalarTypeDefinitions) {
439 440 441
            if (definition.getDefinition() != null) {
                mappingConfig.putCustomTypeMappingIfAbsent(definition.getDefinition().getName(), "String");
            }
442 443
            for (ScalarTypeExtensionDefinition extension : definition.getExtensions()) {
                mappingConfig.putCustomTypeMappingIfAbsent(extension.getName(), "String");
444 445 446
            }
        }
    }
447

448
}