TypeDefinitionToDataModelMapper.java 8.9 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
import graphql.language.Document;
import graphql.language.InterfaceTypeDefinition;
import graphql.language.ObjectTypeDefinition;
10
import graphql.language.ObjectTypeExtensionDefinition;
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

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

import static com.kobylynskyi.graphql.codegen.model.DataModelFields.*;

/**
 * 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) {
        String packageName = MapperUtils.getModelPackageName(mappingConfig);
35 36

        Map<String, Object> dataModel = new HashMap<>();
37 38 39
        dataModel.put(PACKAGE, packageName);
        dataModel.put(IMPORTS, MapperUtils.getImports(mappingConfig, packageName));
        dataModel.put(CLASS_NAME, MapperUtils.getClassNameWithPrefixAndSuffix(mappingConfig, typeDefinition));
40
        dataModel.put(IMPLEMENTS, getInterfaces(mappingConfig, typeDefinition, document));
41
        dataModel.put(FIELDS, getFields(mappingConfig, typeDefinition, document));
42
        dataModel.put(BUILDER, mappingConfig.getGenerateBuilder());
A
Alberto Valiña 已提交
43 44
        dataModel.put(EQUALS_AND_HASH_CODE, mappingConfig.getGenerateEqualsAndHashCode());
        dataModel.put(TO_STRING, mappingConfig.getGenerateToString());
45
        dataModel.put(TO_STRING_ESCAPE_JSON, mappingConfig.getGenerateRequests());
46 47
        return dataModel;
    }
A
Alberto Valiña 已提交
48

49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
    /**
     * 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);
64
        dataModel.put(IMPORTS, MapperUtils.getImportsForRequests(mappingConfig, packageName));
65 66
        dataModel.put(CLASS_NAME, Utils.capitalize(typeDefinition.getName()) + mappingConfig.getResponseProjectionSuffix());
        dataModel.put(FIELDS, getProjectionFields(mappingConfig, typeDefinition, document, typeNames));
67
        dataModel.put(BUILDER, mappingConfig.getGenerateBuilder());
68
        dataModel.put(EQUALS_AND_HASH_CODE, mappingConfig.getGenerateEqualsAndHashCode());
69
        // dataModel.put(TO_STRING, mappingConfig.getGenerateToString()); always generated for serialization purposes
70 71 72
        return dataModel;
    }

73 74 75 76 77 78 79 80 81 82
    /**
     * 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
     */
    private static Set<ParameterDefinition> getFields(MappingConfig mappingConfig, ObjectTypeDefinition typeDefinition,
                                                      Document document) {
83 84 85 86 87 88 89 90 91 92 93 94 95 96
        List<ParameterDefinition> typeParameters = FieldDefinitionToParameterMapper.mapFields(mappingConfig,
                typeDefinition.getFieldDefinitions(), typeDefinition.getName());
        List<ParameterDefinition> typeParametersFromInterfaces = getInterfacesOfType(mappingConfig, typeDefinition, document)
                .stream()
                .map(i -> FieldDefinitionToParameterMapper.mapFields(mappingConfig, i.getFieldDefinitions(), i.getName()))
                .flatMap(Collection::stream)
                .collect(Collectors.toList());
        List<ParameterDefinition> typeParametersFromExtensions = MapperUtils.getDefinitionsOfType(document,
                ObjectTypeExtensionDefinition.class, typeDefinition.getName())
                .stream()
                .map(i -> FieldDefinitionToParameterMapper.mapFields(mappingConfig, i.getFieldDefinitions(), i.getName()))
                .flatMap(Collection::stream)
                .collect(Collectors.toList());

97
        Set<ParameterDefinition> allParameters = new LinkedHashSet<>();
98 99 100
        allParameters.addAll(typeParameters);
        allParameters.addAll(typeParametersFromInterfaces);
        allParameters.addAll(typeParametersFromExtensions);
101 102 103 104 105 106 107 108 109 110 111 112 113 114
        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
     */
    private static Set<ProjectionParameterDefinition> getProjectionFields(MappingConfig mappingConfig, ObjectTypeDefinition typeDefinition,
                                                                          Document document, Set<String> typeNames) {
115 116 117 118 119 120 121 122 123 124 125 126 127 128
        List<ProjectionParameterDefinition> typeParameters = FieldDefinitionToParameterMapper.mapProjectionFields(mappingConfig,
                typeDefinition.getFieldDefinitions(), typeDefinition.getName(), typeNames);
        List<ProjectionParameterDefinition> typeParametersFromInterfaces = getInterfacesOfType(mappingConfig, typeDefinition, document)
                .stream().map(i -> FieldDefinitionToParameterMapper.mapProjectionFields(mappingConfig,
                        i.getFieldDefinitions(), i.getName(), typeNames))
                .flatMap(Collection::stream)
                .collect(Collectors.toList());
        List<ProjectionParameterDefinition> typeParametersFromExtensions = MapperUtils.getDefinitionsOfType(document, ObjectTypeExtensionDefinition.class, typeDefinition.getName())
                .stream()
                .map(ext -> FieldDefinitionToParameterMapper.mapProjectionFields(mappingConfig,
                        ext.getFieldDefinitions(), ext.getName(), typeNames))
                .flatMap(Collection::stream)
                .collect(Collectors.toList());

129
        Set<ProjectionParameterDefinition> allParameters = new LinkedHashSet<>();
130 131 132
        allParameters.addAll(typeParameters);
        allParameters.addAll(typeParametersFromInterfaces);
        allParameters.addAll(typeParametersFromExtensions);
133 134 135
        return allParameters;
    }

136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
    /**
     * 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()
151
                .map(type -> GraphqlTypeToJavaTypeMapper.getJavaType(mappingConfig, type))
152 153 154 155 156 157 158 159
                .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());
    }

160 161 162 163 164 165 166 167 168
    private static Set<String> getInterfaces(MappingConfig mappingConfig, ObjectTypeDefinition typeDefinition, Document document) {
        Set<String> allInterfaces = new LinkedHashSet<>(
                MapperUtils.getUnionNamesHavingType(mappingConfig, typeDefinition, document));
        typeDefinition.getImplements().stream()
                .map(anImplement -> GraphqlTypeToJavaTypeMapper.getJavaType(mappingConfig, anImplement))
                .forEach(allInterfaces::add);
        return allInterfaces;
    }

169
}