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

3 4 5 6 7 8 9 10
import com.kobylynskyi.graphql.codegen.mapper.EnumDefinitionToDataModelMapper;
import com.kobylynskyi.graphql.codegen.mapper.FieldDefinitionToParameterMapper;
import com.kobylynskyi.graphql.codegen.mapper.FieldDefinitionsToResolverDataModelMapper;
import com.kobylynskyi.graphql.codegen.mapper.InputDefinitionToDataModelMapper;
import com.kobylynskyi.graphql.codegen.mapper.InterfaceDefinitionToDataModelMapper;
import com.kobylynskyi.graphql.codegen.mapper.RequestResponseDefinitionToDataModelMapper;
import com.kobylynskyi.graphql.codegen.mapper.TypeDefinitionToDataModelMapper;
import com.kobylynskyi.graphql.codegen.mapper.UnionDefinitionToDataModelMapper;
11
import com.kobylynskyi.graphql.codegen.model.ApiInterfaceStrategy;
12 13
import com.kobylynskyi.graphql.codegen.model.ApiNamePrefixStrategy;
import com.kobylynskyi.graphql.codegen.model.ApiRootInterfaceStrategy;
14
import com.kobylynskyi.graphql.codegen.model.GeneratedInformation;
15
import com.kobylynskyi.graphql.codegen.model.MappingConfig;
16
import com.kobylynskyi.graphql.codegen.model.MappingConfigConstants;
17
import com.kobylynskyi.graphql.codegen.model.MappingContext;
18
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDefinition;
19 20 21 22 23 24 25 26
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 已提交
27
import com.kobylynskyi.graphql.codegen.supplier.MappingConfigSupplier;
28
import com.kobylynskyi.graphql.codegen.utils.Utils;
29 30
import graphql.language.FieldDefinition;
import graphql.language.ScalarTypeExtensionDefinition;
31 32

import java.io.File;
B
Bogdan Kobylynskyi 已提交
33
import java.io.IOException;
34 35 36 37 38 39
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
40

41 42
import static java.util.stream.Collectors.toList;

43 44
/**
 * Generator of:
45 46 47
 * - Interface for each GraphQL query, mutation, subscription, union and field resolvers
 * - POJO Class for each GraphQL type and input
 * - Enum Class for each GraphQL enum
48 49
 *
 * @author kobylynskyi
A
Alberto Valiña 已提交
50
 * @author valinhadev
51
 */
52
public class GraphQLCodegen {
53

54
    private final List<String> schemas;
55
    private final String introspectionResult;
56 57 58
    private final File outputDir;
    private final MappingConfig mappingConfig;
    private final GeneratedInformation generatedInformation;
59

60
    // used in tests
61 62 63 64
    public GraphQLCodegen(List<String> schemas,
                          File outputDir,
                          MappingConfig mappingConfig,
                          GeneratedInformation generatedInformation) {
65
        this(schemas, null, outputDir, mappingConfig, null, generatedInformation);
A
Alberto Valiña 已提交
66 67
    }

68 69 70 71 72 73 74 75 76
    // used in tests
    public GraphQLCodegen(String introspectionResult,
                          File outputDir,
                          MappingConfig mappingConfig,
                          GeneratedInformation generatedInformation) {
        this(null, introspectionResult, outputDir, mappingConfig, null, generatedInformation);
    }

    // used in plugins
77
    public GraphQLCodegen(List<String> schemas,
78
                          String introspectionResult,
79 80 81
                          File outputDir,
                          MappingConfig mappingConfig,
                          MappingConfigSupplier externalMappingConfigSupplier) {
82
        this(schemas, introspectionResult, outputDir, mappingConfig, externalMappingConfigSupplier, new GeneratedInformation());
83 84
    }

85
    // used by other constructors
86
    public GraphQLCodegen(List<String> schemas,
87
                          String introspectionResult,
88 89 90 91
                          File outputDir,
                          MappingConfig mappingConfig,
                          MappingConfigSupplier externalMappingConfigSupplier,
                          GeneratedInformation generatedInformation) {
92
        this.schemas = schemas;
93
        this.introspectionResult = introspectionResult;
94 95
        this.outputDir = outputDir;
        this.mappingConfig = mappingConfig;
A
Alberto Valiña 已提交
96 97
        this.mappingConfig.combine(externalMappingConfigSupplier != null ? externalMappingConfigSupplier.get() : null);
        initDefaultValues(mappingConfig);
98
        validateConfigs(mappingConfig);
99
        sanitizeValues(mappingConfig);
100
        this.generatedInformation = generatedInformation;
A
Alberto Valiña 已提交
101 102
    }

103
    private static void initDefaultValues(MappingConfig mappingConfig) {
A
Alberto Valiña 已提交
104
        if (mappingConfig.getModelValidationAnnotation() == null) {
105
            mappingConfig.setModelValidationAnnotation(MappingConfigConstants.DEFAULT_VALIDATION_ANNOTATION);
A
Alberto Valiña 已提交
106
        }
107
        if (mappingConfig.getGenerateBuilder() == null) {
108
            mappingConfig.setGenerateBuilder(MappingConfigConstants.DEFAULT_BUILDER);
109
        }
A
Alberto Valiña 已提交
110
        if (mappingConfig.getGenerateEqualsAndHashCode() == null) {
111
            mappingConfig.setGenerateEqualsAndHashCode(MappingConfigConstants.DEFAULT_EQUALS_AND_HASHCODE);
A
Alberto Valiña 已提交
112
        }
113 114
        if (mappingConfig.getGenerateClient() == null) {
            mappingConfig.setGenerateClient(MappingConfigConstants.DEFAULT_GENERATE_CLIENT);
115 116
        }
        if (mappingConfig.getRequestSuffix() == null) {
117
            mappingConfig.setRequestSuffix(MappingConfigConstants.DEFAULT_REQUEST_SUFFIX);
118
        }
119 120 121
        if (mappingConfig.getResponseSuffix() == null) {
            mappingConfig.setResponseSuffix(MappingConfigConstants.DEFAULT_RESPONSE_SUFFIX);
        }
122
        if (mappingConfig.getResponseProjectionSuffix() == null) {
123
            mappingConfig.setResponseProjectionSuffix(MappingConfigConstants.DEFAULT_RESPONSE_PROJECTION_SUFFIX);
124
        }
125
        if (mappingConfig.getParametrizedInputSuffix() == null) {
126
            mappingConfig.setParametrizedInputSuffix(MappingConfigConstants.DEFAULT_PARAMETRIZED_INPUT_SUFFIX);
127
        }
128 129 130
        if (mappingConfig.getGenerateImmutableModels() == null) {
            mappingConfig.setGenerateImmutableModels(MappingConfigConstants.DEFAULT_GENERATE_IMMUTABLE_MODELS);
        }
A
Alberto Valiña 已提交
131
        if (mappingConfig.getGenerateToString() == null) {
132
            mappingConfig.setGenerateToString(MappingConfigConstants.DEFAULT_TO_STRING);
A
Alberto Valiña 已提交
133 134
        }
        if (mappingConfig.getGenerateApis() == null) {
135
            mappingConfig.setGenerateApis(MappingConfigConstants.DEFAULT_GENERATE_APIS);
A
Alberto Valiña 已提交
136
        }
137
        if (mappingConfig.getApiNameSuffix() == null) {
138 139 140 141
            mappingConfig.setApiNameSuffix(MappingConfigConstants.DEFAULT_RESOLVER_SUFFIX);
        }
        if (mappingConfig.getTypeResolverSuffix() == null) {
            mappingConfig.setTypeResolverSuffix(MappingConfigConstants.DEFAULT_RESOLVER_SUFFIX);
142
        }
143
        if (mappingConfig.getGenerateParameterizedFieldsResolvers() == null) {
144
            mappingConfig.setGenerateParameterizedFieldsResolvers(MappingConfigConstants.DEFAULT_GENERATE_PARAMETERIZED_FIELDS_RESOLVERS);
145
        }
146
        if (mappingConfig.getGenerateExtensionFieldsResolvers() == null) {
147
            mappingConfig.setGenerateExtensionFieldsResolvers(MappingConfigConstants.DEFAULT_GENERATE_EXTENSION_FIELDS_RESOLVERS);
148
        }
149
        if (mappingConfig.getGenerateDataFetchingEnvironmentArgumentInApis() == null) {
150
            mappingConfig.setGenerateDataFetchingEnvironmentArgumentInApis(MappingConfigConstants.DEFAULT_GENERATE_DATA_FETCHING_ENV);
151
        }
152 153 154
        if (mappingConfig.getGenerateModelsForRootTypes() == null) {
            mappingConfig.setGenerateModelsForRootTypes(MappingConfigConstants.DEFAULT_GENERATE_MODELS_FOR_ROOT_TYPES);
        }
155 156 157
        if (mappingConfig.getUseOptionalForNullableReturnTypes() == null) {
            mappingConfig.setUseOptionalForNullableReturnTypes(MappingConfigConstants.DEFAULT_USE_OPTIONAL_FOR_NULLABLE_RETURN_TYPES);
        }
158 159 160 161 162 163
        if (mappingConfig.getApiNamePrefixStrategy() == null) {
            mappingConfig.setApiNamePrefixStrategy(MappingConfigConstants.DEFAULT_API_NAME_PREFIX_STRATEGY);
        }
        if (mappingConfig.getApiRootInterfaceStrategy() == null) {
            mappingConfig.setApiRootInterfaceStrategy(MappingConfigConstants.DEFAULT_API_ROOT_INTERFACE_STRATEGY);
        }
164 165 166
        if (mappingConfig.getApiInterfaceStrategy() == null) {
            mappingConfig.setApiInterfaceStrategy(MappingConfigConstants.DEFAULT_API_INTERFACE_STRATEGY);
        }
B
Bogdan Kobylynskyi 已提交
167
        if (Boolean.TRUE.equals(mappingConfig.getGenerateClient())) {
168 169 170
            // required for request serialization
            mappingConfig.setGenerateToString(true);
        }
171 172
    }

173 174 175 176 177 178
    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");
        }
179 180
        if (mappingConfig.getApiRootInterfaceStrategy() == ApiRootInterfaceStrategy.INTERFACE_PER_SCHEMA &&
                mappingConfig.getApiNamePrefixStrategy() == ApiNamePrefixStrategy.CONSTANT) {
181
            // we will have a conflict in case there is "type Query" in multiple graphql schema files
182 183
            throw new IllegalArgumentException("API prefix should not be CONSTANT for INTERFACE_PER_SCHEMA option");
        }
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
        if (mappingConfig.getGenerateApis() &&
                mappingConfig.getGenerateModelsForRootTypes() &&
                mappingConfig.getApiNamePrefixStrategy() == ApiNamePrefixStrategy.CONSTANT) {
            // 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");
            }
        }
200 201
    }

202 203 204 205
    private static void sanitizeValues(MappingConfig mappingConfig) {
        mappingConfig.setModelValidationAnnotation(
                Utils.replaceLeadingAtSign(mappingConfig.getModelValidationAnnotation()));

206
        Map<String, List<String>> customAnnotationsMapping = mappingConfig.getCustomAnnotationsMapping();
207
        if (customAnnotationsMapping != null) {
208 209 210 211
            for (Map.Entry<String, List<String>> entry : customAnnotationsMapping.entrySet()) {
                if (entry.getValue() != null) {
                    entry.setValue(entry.getValue().stream().map(Utils::replaceLeadingAtSign).collect(toList()));
                }
212 213
            }
        }
214
        Map<String, List<String>> directiveAnnotationsMapping = mappingConfig.getDirectiveAnnotationsMapping();
215
        if (directiveAnnotationsMapping != null) {
216 217 218 219
            for (Map.Entry<String, List<String>> entry : directiveAnnotationsMapping.entrySet()) {
                if (entry.getValue() != null) {
                    entry.setValue(entry.getValue().stream().map(Utils::replaceLeadingAtSign).collect(toList()));
                }
220 221
            }
        }
222 223
    }

B
Bogdan Kobylynskyi 已提交
224
    public List<File> generate() throws IOException {
225
        GraphQLCodegenFileCreator.prepareOutputDir(outputDir);
226
        long startTime = System.currentTimeMillis();
227
        List<File> generatedFiles = Collections.emptyList();
228 229 230 231 232 233 234 235
        if (!Utils.isEmpty(schemas)) {
            ExtendedDocument document = GraphQLDocumentParser.getDocumentFromSchemas(mappingConfig, schemas);
            initCustomTypeMappings(document.getScalarDefinitions());
            generatedFiles = processDefinitions(document);
            System.out.println(String.format("Finished processing %d schema(s) in %d ms", schemas.size(),
                    System.currentTimeMillis() - startTime));
        } else if (introspectionResult != null) {
            ExtendedDocument document = GraphQLDocumentParser.getDocumentFromIntrospectionResult(mappingConfig, introspectionResult);
236
            initCustomTypeMappings(document.getScalarDefinitions());
237
            generatedFiles = processDefinitions(document);
238 239
            System.out.println(String.format("Finished processing introspection result in %d ms",
                    System.currentTimeMillis() - startTime));
240
        }
241

242
        return generatedFiles;
243 244
    }

245
    private List<File> processDefinitions(ExtendedDocument document) {
246
        MappingContext context = new MappingContext(mappingConfig, document, generatedInformation);
247

248 249
        List<File> generatedFiles = new ArrayList<>();
        for (ExtendedObjectTypeDefinition extendedObjectTypeDefinition : document.getTypeDefinitions()) {
250
            generatedFiles.addAll(generateType(context, extendedObjectTypeDefinition));
251 252
        }
        for (ExtendedObjectTypeDefinition extendedObjectTypeDefinition : document.getTypeDefinitions()) {
253
            generateFieldResolver(context, extendedObjectTypeDefinition.getFieldDefinitions(), extendedObjectTypeDefinition)
254 255 256
                    .ifPresent(generatedFiles::add);
        }
        for (ExtendedObjectTypeDefinition extendedObjectTypeDefinition : document.getOperationDefinitions()) {
B
Bogdan Kobylynskyi 已提交
257
            if (Boolean.TRUE.equals(mappingConfig.getGenerateApis())) {
258 259
                generatedFiles.addAll(generateServerOperations(context, extendedObjectTypeDefinition));
            }
B
Bogdan Kobylynskyi 已提交
260
            if (Boolean.TRUE.equals(mappingConfig.getGenerateClient())) {
261 262
                generatedFiles.addAll(generateClient(context, extendedObjectTypeDefinition));
            }
263 264
        }
        for (ExtendedInputObjectTypeDefinition extendedInputObjectTypeDefinition : document.getInputDefinitions()) {
265
            generatedFiles.add(generateInput(context, extendedInputObjectTypeDefinition));
266 267
        }
        for (ExtendedEnumTypeDefinition extendedEnumTypeDefinition : document.getEnumDefinitions()) {
268
            generatedFiles.add(generateEnum(context, extendedEnumTypeDefinition));
269 270
        }
        for (ExtendedUnionTypeDefinition extendedUnionTypeDefinition : document.getUnionDefinitions()) {
271
            generatedFiles.addAll(generateUnion(context, extendedUnionTypeDefinition));
272 273
        }
        for (ExtendedInterfaceTypeDefinition extendedInterfaceTypeDefinition : document.getInterfaceDefinitions()) {
274
            generatedFiles.addAll(generateInterface(context, extendedInterfaceTypeDefinition));
275 276
        }
        for (ExtendedInterfaceTypeDefinition definition : document.getInterfaceDefinitions()) {
277
            generateFieldResolver(context, definition.getFieldDefinitions(), definition).ifPresent(generatedFiles::add);
278 279 280 281
        }
        System.out.println(String.format("Generated %d definition classes in folder %s",
                generatedFiles.size(), outputDir.getAbsolutePath()));
        return generatedFiles;
282 283
    }

284 285
    private List<File> generateUnion(MappingContext mappingContext, ExtendedUnionTypeDefinition definition) {
        List<File> generatedFiles = new ArrayList<>();
286
        Map<String, Object> dataModel = UnionDefinitionToDataModelMapper.map(mappingContext, definition);
287 288 289 290 291 292 293
        generatedFiles.add(GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.unionTemplate, dataModel, outputDir));

        if (Boolean.TRUE.equals(mappingConfig.getGenerateClient())) {
            Map<String, Object> responseProjDataModel = RequestResponseDefinitionToDataModelMapper.mapResponseProjection(mappingContext, definition);
            generatedFiles.add(GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.responseProjectionTemplate, responseProjDataModel, outputDir));
        }
        return generatedFiles;
294 295
    }

296 297
    private List<File> generateInterface(MappingContext mappingContext, ExtendedInterfaceTypeDefinition definition) {
        List<File> generatedFiles = new ArrayList<>();
298
        Map<String, Object> dataModel = InterfaceDefinitionToDataModelMapper.map(mappingContext, definition);
299 300 301 302 303 304 305
        generatedFiles.add(GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.interfaceTemplate, dataModel, outputDir));

        if (Boolean.TRUE.equals(mappingConfig.getGenerateClient())) {
            Map<String, Object> responseProjDataModel = RequestResponseDefinitionToDataModelMapper.mapResponseProjection(mappingContext, definition);
            generatedFiles.add(GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.responseProjectionTemplate, responseProjDataModel, outputDir));
        }
        return generatedFiles;
306 307
    }

308
    private List<File> generateServerOperations(MappingContext mappingContext, ExtendedObjectTypeDefinition definition) {
309
        List<File> generatedFiles = new ArrayList<>();
310 311 312 313 314 315 316 317
        // 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;
318 319
            case DO_NOT_GENERATE:
                break;
320 321 322 323 324 325
            case SINGLE_INTERFACE:
            default:
                generatedFiles.add(generateRootApi(mappingContext, definition));
                break;
        }

326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
        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;
            }
345
        }
346 347
        return generatedFiles;
    }
348

349 350 351 352 353 354
    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()) {
            Map<String, Object> requestDataModel = RequestResponseDefinitionToDataModelMapper.mapRequest(mappingContext, operationDef, definition.getName(), fieldNames);
            generatedFiles.add(GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.requestTemplate, requestDataModel, outputDir));
355

356 357
            Map<String, Object> responseDataModel = RequestResponseDefinitionToDataModelMapper.mapResponse(mappingContext, operationDef, definition.getName(), fieldNames);
            generatedFiles.add(GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.responseTemplate, responseDataModel, outputDir));
358
        }
359
        return generatedFiles;
360 361
    }

362 363 364 365 366 367 368 369 370 371 372 373 374 375
    private List<File> generateApis(MappingContext mappingContext, ExtendedObjectTypeDefinition definition, List<String> fieldNames) {
        List<File> generatedFiles = new ArrayList<>();
        for (ExtendedFieldDefinition operationDef : definition.getFieldDefinitions()) {
            Map<String, Object> dataModel = FieldDefinitionsToResolverDataModelMapper.mapRootTypeField(mappingContext, operationDef, definition.getName(), fieldNames);
            generatedFiles.add(GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.operationsTemplate, dataModel, outputDir));
        }
        return generatedFiles;
    }

    private File generateRootApi(MappingContext mappingContext, ExtendedObjectTypeDefinition definition) {
        Map<String, Object> dataModel = FieldDefinitionsToResolverDataModelMapper.mapRootTypeFields(mappingContext, definition);
        return GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.operationsTemplate, dataModel, outputDir);
    }

376
    private List<File> generateType(MappingContext mappingContext, ExtendedObjectTypeDefinition definition) {
377
        List<File> generatedFiles = new ArrayList<>();
378
        Map<String, Object> dataModel = TypeDefinitionToDataModelMapper.map(mappingContext, definition);
379
        generatedFiles.add(GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.typeTemplate, dataModel, outputDir));
380

B
Bogdan Kobylynskyi 已提交
381
        if (Boolean.TRUE.equals(mappingConfig.getGenerateClient())) {
382
            Map<String, Object> responseProjDataModel = RequestResponseDefinitionToDataModelMapper.mapResponseProjection(mappingContext, definition);
383
            generatedFiles.add(GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.responseProjectionTemplate, responseProjDataModel, outputDir));
384 385 386

            for (ExtendedFieldDefinition fieldDefinition : definition.getFieldDefinitions()) {
                if (!Utils.isEmpty(fieldDefinition.getInputValueDefinitions())) {
387
                    Map<String, Object> fieldProjDataModel = RequestResponseDefinitionToDataModelMapper.mapParametrizedInput(mappingContext, fieldDefinition, definition);
388 389 390
                    generatedFiles.add(GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.parametrizedInputTemplate, fieldProjDataModel, outputDir));
                }
            }
391
        }
392
        return generatedFiles;
393 394
    }

395 396 397
    private Optional<File> generateFieldResolver(MappingContext mappingContext,
                                                 List<ExtendedFieldDefinition> fieldDefinitions,
                                                 ExtendedDefinition<?, ?> parentDefinition) {
398
        List<ExtendedFieldDefinition> fieldDefsWithResolvers = fieldDefinitions.stream()
399
                .filter(fieldDef -> FieldDefinitionToParameterMapper.generateResolversForField(mappingContext, fieldDef, parentDefinition))
400 401
                .collect(toList());
        if (!fieldDefsWithResolvers.isEmpty()) {
402
            Map<String, Object> dataModel = FieldDefinitionsToResolverDataModelMapper.mapToTypeResolver(mappingContext, fieldDefsWithResolvers, parentDefinition.getName());
403
            return Optional.of(GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.operationsTemplate, dataModel, outputDir));
404
        }
405
        return Optional.empty();
406 407
    }

408 409
    private File generateInput(MappingContext mappingContext, ExtendedInputObjectTypeDefinition definition) {
        Map<String, Object> dataModel = InputDefinitionToDataModelMapper.map(mappingContext, definition);
410
        return GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.typeTemplate, dataModel, outputDir);
411 412
    }

413 414
    private File generateEnum(MappingContext mappingContext, ExtendedEnumTypeDefinition definition) {
        Map<String, Object> dataModel = EnumDefinitionToDataModelMapper.map(mappingContext, definition);
415
        return GraphQLCodegenFileCreator.generateFile(FreeMarkerTemplatesRegistry.enumTemplate, dataModel, outputDir);
416 417
    }

418 419
    private void initCustomTypeMappings(Collection<ExtendedScalarTypeDefinition> scalarTypeDefinitions) {
        for (ExtendedScalarTypeDefinition definition : scalarTypeDefinitions) {
420 421 422
            if (definition.getDefinition() != null) {
                mappingConfig.putCustomTypeMappingIfAbsent(definition.getDefinition().getName(), "String");
            }
423 424
            for (ScalarTypeExtensionDefinition extension : definition.getExtensions()) {
                mappingConfig.putCustomTypeMappingIfAbsent(extension.getName(), "String");
425 426
            }
        }
427 428 429 430 431
        mappingConfig.putCustomTypeMappingIfAbsent("ID", "String");
        mappingConfig.putCustomTypeMappingIfAbsent("String", "String");
        mappingConfig.putCustomTypeMappingIfAbsent("Int", "Integer");
        mappingConfig.putCustomTypeMappingIfAbsent("Float", "Double");
        mappingConfig.putCustomTypeMappingIfAbsent("Boolean", "Boolean");
432
    }
433

434
}