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

3
import com.kobylynskyi.graphql.codegen.model.MappingContext;
4
import com.kobylynskyi.graphql.codegen.model.ParameterDefinition;
5 6 7
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDocument;
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedObjectTypeDefinition;
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedUnionTypeDefinition;
8
import com.kobylynskyi.graphql.codegen.utils.Utils;
9

10 11 12 13 14 15 16
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
17 18
import java.util.stream.Collectors;

19
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.ANNOTATIONS;
20 21 22 23
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.BUILDER;
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.CLASS_NAME;
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.EQUALS_AND_HASH_CODE;
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.FIELDS;
24
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.GENERATED_INFO;
25
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.IMMUTABLE_MODELS;
26 27 28 29 30
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.IMPLEMENTS;
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.JAVA_DOC;
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.PACKAGE;
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.TO_STRING;
import static com.kobylynskyi.graphql.codegen.model.DataModelFields.TO_STRING_FOR_REQUEST;
31 32 33 34 35 36 37 38

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

B
Bogdan Kobylynskyi 已提交
39 40 41
    private TypeDefinitionToDataModelMapper() {
    }

42 43 44
    /**
     * Map type definition to a Freemarker data model
     *
45 46
     * @param mappingContext Global mapping context
     * @param definition     Definition of object type including base definition and its extensions
47 48
     * @return Freemarker data model of the GraphQL type
     */
49 50 51 52
    public static Map<String, Object> map(MappingContext mappingContext,
                                          ExtendedObjectTypeDefinition definition) {
        ExtendedDocument document = mappingContext.getDocument();

53
        Map<String, Object> dataModel = new HashMap<>();
54
        // type/enum/input/interface/union classes do not require any imports
55
        dataModel.put(PACKAGE, MapperUtils.getModelPackageName(mappingContext));
56
        dataModel.put(CLASS_NAME, MapperUtils.getModelClassNameWithPrefixAndSuffix(mappingContext, definition));
57
        dataModel.put(JAVA_DOC, definition.getJavaDoc());
58
        dataModel.put(IMPLEMENTS, getInterfaces(mappingContext, definition));
59
        dataModel.put(ANNOTATIONS, GraphqlTypeToJavaTypeMapper.getAnnotations(mappingContext, definition));
60 61 62
        dataModel.put(FIELDS, getFields(mappingContext, definition, document));
        dataModel.put(BUILDER, mappingContext.getGenerateBuilder());
        dataModel.put(EQUALS_AND_HASH_CODE, mappingContext.getGenerateEqualsAndHashCode());
63
        dataModel.put(IMMUTABLE_MODELS, mappingContext.getGenerateImmutableModels());
64
        dataModel.put(TO_STRING, mappingContext.getGenerateToString());
65
        dataModel.put(TO_STRING_FOR_REQUEST, mappingContext.getGenerateClient());
66
        dataModel.put(GENERATED_INFO, mappingContext.getGeneratedInformation());
67 68 69
        return dataModel;
    }

70 71 72
    /**
     * Get merged attributes from the type and attributes from the interface.
     *
73
     * @param mappingContext Global mapping context
74 75 76 77
     * @param typeDefinition GraphQL type definition
     * @param document       Parent GraphQL document
     * @return Freemarker data model of the GraphQL type
     */
78
    private static Collection<ParameterDefinition> getFields(MappingContext mappingContext,
79 80 81 82 83 84
                                                             ExtendedObjectTypeDefinition typeDefinition,
                                                             ExtendedDocument document) {
        // using the map to exclude duplicate fields from the type and interfaces
        Map<String, ParameterDefinition> allParameters = new LinkedHashMap<>();

        // includes parameters from the base definition and extensions
85
        FieldDefinitionToParameterMapper.mapFields(mappingContext, typeDefinition.getFieldDefinitions(), typeDefinition)
86 87
                .forEach(p -> allParameters.put(p.getName(), p));
        // includes parameters from the interface
88
        MapperUtils.getInterfacesOfType(typeDefinition, document).stream()
89
                .map(i -> FieldDefinitionToParameterMapper.mapFields(mappingContext, i.getFieldDefinitions(), i))
90
                .flatMap(Collection::stream)
91 92 93
                .forEach(paramDef -> allParameters.merge(paramDef.getName(), paramDef, TypeDefinitionToDataModelMapper::merge));
        return allParameters.values();
    }
94

95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
    /**
     * Merge parameter definition data from the type and interface
     * Annotations from the type have higher precedence
     *
     * @param typeDef      Definition of the same parameter from the type
     * @param interfaceDef Definition of the same parameter from the interface
     * @return merged parameter definition
     */
    private static ParameterDefinition merge(ParameterDefinition typeDef, ParameterDefinition interfaceDef) {
        if (Utils.isEmpty(typeDef.getAnnotations())) {
            typeDef.setAnnotations(interfaceDef.getAnnotations());
        }
        if (Utils.isEmpty(typeDef.getJavaDoc())) {
            typeDef.setJavaDoc(interfaceDef.getJavaDoc());
        }
        return typeDef;
111 112
    }

113 114 115
    private static Set<String> getInterfaces(MappingContext mappingContext,
                                             ExtendedObjectTypeDefinition definition) {
        List<String> unionsNames = mappingContext.getDocument().getUnionDefinitions()
116 117 118
                .stream()
                .filter(union -> union.isDefinitionPartOfUnion(definition))
                .map(ExtendedUnionTypeDefinition::getName)
119
                .map(unionName -> MapperUtils.getModelClassNameWithPrefixAndSuffix(mappingContext, unionName))
120 121 122
                .collect(Collectors.toList());
        Set<String> interfaceNames = definition.getImplements()
                .stream()
123
                .map(anImplement -> GraphqlTypeToJavaTypeMapper.getJavaType(mappingContext, anImplement))
124 125 126 127 128
                .collect(Collectors.toSet());

        Set<String> allInterfaces = new LinkedHashSet<>();
        allInterfaces.addAll(unionsNames);
        allInterfaces.addAll(interfaceNames);
129 130 131
        return allInterfaces;
    }

132
}