TypeDefinitionToDataModelMapper.java 7.5 KB
Newer Older
1 2 3
package com.kobylynskyi.graphql.codegen.mapper;

import com.kobylynskyi.graphql.codegen.model.MappingConfig;
4
import com.kobylynskyi.graphql.codegen.model.ParameterDefinition;
5 6
import com.kobylynskyi.graphql.codegen.model.ProjectionParameterDefinition;
import com.kobylynskyi.graphql.codegen.utils.Utils;
7 8 9 10 11 12 13 14
import graphql.language.Document;
import graphql.language.InterfaceTypeDefinition;
import graphql.language.ObjectTypeDefinition;

import java.util.*;
import java.util.stream.Collectors;

import static com.kobylynskyi.graphql.codegen.model.DataModelFields.*;
15
import static java.util.Collections.emptySet;
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

/**
 * Map type definition to a Freemarker data model
 *
 * @author kobylynskyi
 */
public class TypeDefinitionToDataModelMapper {

    /**
     * Map type definition to a Freemarker data model
     *
     * @param mappingConfig  Global mapping configuration
     * @param typeDefinition GraphQL type definition
     * @param document       Parent GraphQL document
     * @return Freemarker data model of the GraphQL type
     */
    public static Map<String, Object> map(MappingConfig mappingConfig, ObjectTypeDefinition typeDefinition,
                                          Document document) {
        Map<String, Object> dataModel = new HashMap<>();
        String packageName = MapperUtils.getModelPackageName(mappingConfig);
        dataModel.put(PACKAGE, packageName);
        dataModel.put(IMPORTS, MapperUtils.getImports(mappingConfig, packageName));
        dataModel.put(CLASS_NAME, MapperUtils.getClassNameWithPrefixAndSuffix(mappingConfig, typeDefinition));
39 40
        Set<String> allInterfaces = new LinkedHashSet<>(
                MapperUtils.getUnionsHavingType(mappingConfig, typeDefinition, document));
41
        typeDefinition.getImplements().stream()
42
                .map(anImplement -> GraphqlTypeToJavaTypeMapper.getJavaType(mappingConfig, anImplement))
43 44
                .forEach(allInterfaces::add);
        dataModel.put(IMPLEMENTS, allInterfaces);
45
        dataModel.put(FIELDS, getFields(mappingConfig, typeDefinition, document));
46
        dataModel.put(BUILDER, mappingConfig.getGenerateBuilder());
A
Alberto Valiña 已提交
47 48
        dataModel.put(EQUALS_AND_HASH_CODE, mappingConfig.getGenerateEqualsAndHashCode());
        dataModel.put(TO_STRING, mappingConfig.getGenerateToString());
49
        dataModel.put(TO_STRING_ESCAPE_JSON, mappingConfig.getGenerateRequests());
50 51
        return dataModel;
    }
A
Alberto Valiña 已提交
52

53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68

    /**
     * Map type definition to a Freemarker data model of Response Projection.
     *
     * @param mappingConfig  Global mapping configuration
     * @param typeDefinition GraphQL type definition
     * @param document       Parent GraphQL document
     * @param typeNames      Names of all GraphQL types
     * @return Freemarker data model of the GraphQL Response Projection
     */
    public static Map<String, Object> mapResponseProjection(MappingConfig mappingConfig,
                                                            ObjectTypeDefinition typeDefinition, Document document,
                                                            Set<String> typeNames) {
        Map<String, Object> dataModel = new HashMap<>();
        String packageName = MapperUtils.getModelPackageName(mappingConfig);
        dataModel.put(PACKAGE, packageName);
69
        dataModel.put(IMPORTS, MapperUtils.getImportsForRequests(mappingConfig, packageName));
70 71
        dataModel.put(CLASS_NAME, Utils.capitalize(typeDefinition.getName()) + mappingConfig.getResponseProjectionSuffix());
        dataModel.put(FIELDS, getProjectionFields(mappingConfig, typeDefinition, document, typeNames));
72
        dataModel.put(BUILDER, mappingConfig.getGenerateBuilder());
73
        dataModel.put(EQUALS_AND_HASH_CODE, mappingConfig.getGenerateEqualsAndHashCode());
74
        // dataModel.put(TO_STRING, mappingConfig.getGenerateToString()); always generated for serialization purposes
75 76 77
        return dataModel;
    }

78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
    /**
     * Get merged attributes from the type and attributes from the interface.
     *
     * @param mappingConfig  Global mapping configuration
     * @param typeDefinition GraphQL type definition
     * @param document       Parent GraphQL document
     * @return Freemarker data model of the GraphQL type
     */
    @SuppressWarnings("CollectionAddAllCanBeReplacedWithConstructor")
    private static Set<ParameterDefinition> getFields(MappingConfig mappingConfig, ObjectTypeDefinition typeDefinition,
                                                      Document document) {
        Set<ParameterDefinition> allParameters = new LinkedHashSet<>();
        allParameters.addAll(FieldDefinitionToParameterMapper.mapFields(mappingConfig,
                typeDefinition.getFieldDefinitions(), typeDefinition.getName()));
        List<InterfaceTypeDefinition> interfaces = getInterfacesOfType(mappingConfig, typeDefinition, document);
        interfaces.stream().map(i -> FieldDefinitionToParameterMapper.mapFields(mappingConfig,
                i.getFieldDefinitions(), i.getName()))
                .forEach(allParameters::addAll);
        return allParameters;
    }

    /**
     * Get merged attributes from the type and attributes from the interface.
     *
     * @param mappingConfig  Global mapping configuration
     * @param typeDefinition GraphQL type definition
     * @param document       Parent GraphQL document
     * @param typeNames      Names of all GraphQL types
     * @return Freemarker data model of the GraphQL type
     */
    @SuppressWarnings("CollectionAddAllCanBeReplacedWithConstructor")
    private static Set<ProjectionParameterDefinition> getProjectionFields(MappingConfig mappingConfig, ObjectTypeDefinition typeDefinition,
                                                                          Document document, Set<String> typeNames) {
        Set<ProjectionParameterDefinition> allParameters = new LinkedHashSet<>();
        allParameters.addAll(FieldDefinitionToParameterMapper.mapProjectionFields(mappingConfig,
                typeDefinition.getFieldDefinitions(), typeDefinition.getName(), typeNames));
        List<InterfaceTypeDefinition> interfaces = getInterfacesOfType(mappingConfig, typeDefinition, document);
        interfaces.stream().map(i -> FieldDefinitionToParameterMapper.mapProjectionFields(mappingConfig,
                i.getFieldDefinitions(), i.getName(), typeNames))
                .forEach(allParameters::addAll);
        return allParameters;
    }

121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
    /**
     * Scan document and return all interfaces that given type implements.
     *
     * @param mappingConfig Global mapping configuration
     * @param definition    GraphQL type definition
     * @param document      Parent GraphQL document
     * @return all interfaces that given type implements.
     */
    private static List<InterfaceTypeDefinition> getInterfacesOfType(MappingConfig mappingConfig,
                                                                     ObjectTypeDefinition definition,
                                                                     Document document) {
        if (definition.getImplements().isEmpty()) {
            return Collections.emptyList();
        }
        Set<String> typeImplements = definition.getImplements().stream()
136
                .map(type -> GraphqlTypeToJavaTypeMapper.getJavaType(mappingConfig, type))
137 138 139 140 141 142 143 144 145
                .collect(Collectors.toSet());
        return document.getDefinitions().stream()
                .filter(def -> def instanceof InterfaceTypeDefinition)
                .map(def -> (InterfaceTypeDefinition) def)
                .filter(def -> typeImplements.contains(def.getName()))
                .collect(Collectors.toList());
    }

}