GraphqlTypeToJavaTypeMapper.java 8.4 KB
Newer Older
1 2
package com.kobylynskyi.graphql.codegen.mapper;

3 4
import static graphql.language.OperationDefinition.*;

5
import com.kobylynskyi.graphql.codegen.model.MappingConfig;
6
import com.kobylynskyi.graphql.codegen.model.ParameterDefinition;
7
import com.kobylynskyi.graphql.codegen.utils.Utils;
8
import graphql.language.*;
9

10 11
import java.util.ArrayList;
import java.util.List;
12 13 14 15 16 17 18 19 20
import java.util.Map;

/**
 * Map GraphQL type to Java type
 *
 * @author kobylynskyi
 */
class GraphqlTypeToJavaTypeMapper {

21
    /**
22
     * Map GraphQL's FieldDefinition to a Freemarker-understandable format of parameter
23 24 25 26 27 28
     *
     * @param mappingConfig  Global mapping configuration
     * @param fieldDef       GraphQL field definition
     * @param parentTypeName Name of the parent type
     * @return Freemarker-understandable format of parameter (field)
     */
29 30 31 32
    public static ParameterDefinition map(MappingConfig mappingConfig, FieldDefinition fieldDef, String parentTypeName) {
        ParameterDefinition parameter = new ParameterDefinition();
        parameter.setName(MapperUtils.capitalizeIfRestricted(fieldDef.getName()));
        parameter.setType(getJavaType(mappingConfig, fieldDef.getType(), fieldDef.getName(), parentTypeName));
33
        parameter.setAnnotations(getAnnotations(mappingConfig, fieldDef.getType(), fieldDef.getName(), parentTypeName, false));
34
        return parameter;
35 36
    }

37 38 39 40 41 42 43 44
    /**
     * Map GraphQL's InputValueDefinition to a Freemarker-understandable format of operation
     *
     * @param mappingConfig        Global mapping configuration
     * @param inputValueDefinition GraphQL input value definition
     * @param parentTypeName       Name of the parent type
     * @return Freemarker-understandable format of parameter (field)
     */
45
    public static ParameterDefinition map(MappingConfig mappingConfig, InputValueDefinition inputValueDefinition, String parentTypeName) {
46 47 48
        ParameterDefinition parameter = new ParameterDefinition();
        parameter.setName(MapperUtils.capitalizeIfRestricted(inputValueDefinition.getName()));
        parameter.setType(getJavaType(mappingConfig, inputValueDefinition.getType()));
49
        parameter.setAnnotations(getAnnotations(mappingConfig, inputValueDefinition.getType(), inputValueDefinition.getName(), parentTypeName));
50 51 52
        return parameter;
    }

53 54 55 56 57 58 59
    /**
     * Convert GraphQL type to a corresponding Java type
     *
     * @param mappingConfig Global mapping configuration
     * @param type          GraphQL type
     * @return Corresponding Java type
     */
60 61 62 63
    static String getJavaType(MappingConfig mappingConfig, Type type) {
        return getJavaType(mappingConfig, type, null, null);
    }

64 65 66 67
    /**
     * Convert GraphQL type to a corresponding Java type
     *
     * @param mappingConfig  Global mapping configuration
68
     * @param graphqlType    GraphQL type
69 70 71 72
     * @param name           GraphQL type name
     * @param parentTypeName Name of the parent type
     * @return Corresponding Java type
     */
73 74 75 76 77
    static String getJavaType(MappingConfig mappingConfig, Type graphqlType, String name, String parentTypeName) {
        if (graphqlType instanceof TypeName) {
            return getJavaType(mappingConfig, ((TypeName) graphqlType).getName(), name, parentTypeName);
        } else if (graphqlType instanceof ListType) {
            String mappedCollectionType = getJavaType(mappingConfig, ((ListType) graphqlType).getType(), name, parentTypeName);
78
            return wrapIntoJavaCollection(mappedCollectionType);
79 80
        } else if (graphqlType instanceof NonNullType) {
            return getJavaType(mappingConfig, ((NonNullType) graphqlType).getType(), name, parentTypeName);
81 82 83 84
        }
        return null;
    }

85 86 87 88 89 90 91 92 93
    /**
     * Convert GraphQL type to a corresponding Java type
     *
     * @param mappingConfig  Global mapping configuration
     * @param graphlType     GraphQL type
     * @param name           GraphQL type name
     * @param parentTypeName Name of the parent type
     * @return Corresponding Java type
     */
94
    private static String getJavaType(MappingConfig mappingConfig, String graphlType, String name, String parentTypeName) {
95 96 97 98 99
        Map<String, String> customTypesMapping = mappingConfig.getCustomTypesMapping();
        if (name != null && parentTypeName != null && customTypesMapping.containsKey(parentTypeName + "." + name)) {
            return customTypesMapping.get(parentTypeName + "." + name);
        } else if (customTypesMapping.containsKey(graphlType)) {
            return customTypesMapping.get(graphlType);
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
        }
        switch (graphlType) {
            case "ID":
                return "String";
            case "Int":
                return "Integer";
            case "String":
            case "Float":
            case "Boolean":
                return graphlType;
            default:
                // We need to refer other custom types/interfaces/unions with prefix and suffix
                return MapperUtils.getClassNameWithPrefixAndSuffix(mappingConfig, graphlType);
        }
    }

116 117 118 119 120 121 122 123 124 125 126
    /**
     * Get annotations for a given GraphQL type
     *
     * @param mappingConfig  Global mapping configuration
     * @param graphlType     GraphQL type
     * @param name           GraphQL type name
     * @param parentTypeName Name of the parent type
     * @return list of Java annotations for a given GraphQL type
     */
    static List<String> getAnnotations(MappingConfig mappingConfig, Type graphlType, String name, String parentTypeName) {
        return getAnnotations(mappingConfig, graphlType, name, parentTypeName, false);
127 128 129 130
    }

    private static List<String> getAnnotations(MappingConfig mappingConfig, Type type, String name, String parentTypeName,
                                               boolean mandatory) {
131
        if (type instanceof TypeName) {
132
            return getAnnotations(mappingConfig, ((TypeName) type).getName(), name, parentTypeName, mandatory);
133
        } else if (type instanceof ListType) {
134
            return getAnnotations(mappingConfig, ((ListType) type).getType(), name, parentTypeName, mandatory);
135
        } else if (type instanceof NonNullType) {
136
            return getAnnotations(mappingConfig, ((NonNullType) type).getType(), name, parentTypeName, true);
137 138 139 140
        }
        return null;
    }

141
    private static List<String> getAnnotations(MappingConfig mappingConfig, String graphlType, String name, String parentTypeName, boolean mandatory) {
142
        List<String> annotations = new ArrayList<>();
143 144
        if (mandatory) {
            String modelValidationAnnotation = mappingConfig.getModelValidationAnnotation();
145
            if (!Utils.isBlank(modelValidationAnnotation)) {
146 147 148
                annotations.add(modelValidationAnnotation);
            }
        }
149 150 151 152 153 154 155 156 157
        Map<String, String> customAnnotationsMapping = mappingConfig.getCustomAnnotationsMapping();
        if (name != null && parentTypeName != null && customAnnotationsMapping.containsKey(parentTypeName + "." + name)) {
            annotations.add(customAnnotationsMapping.get(parentTypeName + "." + name));
        } else if (customAnnotationsMapping.containsKey(graphlType)) {
            annotations.add(customAnnotationsMapping.get(graphlType));
        }
        return annotations;
    }

B
Bogdan Kobylynskyi 已提交
158 159 160 161 162 163
    /**
     * Wrap java type into collection. E.g.: "String" becomes "Collection<String"
     *
     * @param type Anything that will be wrapped into Collection<>
     * @return String wrapped into Collection<>
     */
164 165 166 167
    private static String wrapIntoJavaCollection(String type) {
        return String.format("Collection<%s>", type);
    }

B
Bogdan Kobylynskyi 已提交
168 169 170 171 172 173 174 175 176 177 178 179
    /**
     * Wraps type into subscriptionReturnType (defined in the mapping configuration.
     * Example:
     * Given GraphQL schema:                           type Subscription { eventsCreated: [Event!]! }
     * Given subscriptionReturnType in mapping config: org.reactivestreams.Publisher
     * Return: org.reactivestreams.Publisher<Event>
     *
     * @param mappingConfig  Global mapping configuration
     * @param javaTypeName   The type that will be wrapped into
     * @param parentTypeName Name of the parent type
     * @return Java type wrapped into the subscriptionReturnType
     */
180 181
    static String wrapIntoSubscriptionIfRequired(MappingConfig mappingConfig, String javaTypeName, String parentTypeName) {
        if (parentTypeName.equalsIgnoreCase(Operation.SUBSCRIPTION.name())
182
                && !Utils.isBlank(mappingConfig.getSubscriptionReturnType())) {
183 184 185 186 187
            return String.format("%s<%s>", mappingConfig.getSubscriptionReturnType(), javaTypeName);
        }
        return javaTypeName;
    }

188
}