GraphQLCodegenMojo.java 18.3 KB
Newer Older
1 2
package io.github.kobylynskyi.graphql.codegen;

3
import com.kobylynskyi.graphql.codegen.GraphQLCodegen;
4
import com.kobylynskyi.graphql.codegen.model.*;
5 6
import com.kobylynskyi.graphql.codegen.supplier.JsonMappingConfigSupplier;
import com.kobylynskyi.graphql.codegen.supplier.MappingConfigSupplier;
7
import com.kobylynskyi.graphql.codegen.supplier.SchemaFinder;
8
import org.apache.maven.model.Resource;
9 10 11 12 13 14 15 16
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;

import java.io.File;
17
import java.io.IOException;
18
import java.nio.file.Path;
19
import java.nio.file.Paths;
20
import java.util.ArrayList;
21
import java.util.Arrays;
22
import java.util.Collection;
23
import java.util.Collections;
24 25 26 27 28
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
29
import java.util.Properties;
30
import java.util.Set;
31

32
@Mojo(name = "generate", defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true)
33
public class GraphQLCodegenMojo extends AbstractMojo implements GraphQLCodegenConfiguration {
34

35
    @Parameter
36 37
    private String[] graphqlSchemaPaths;

38 39 40
    @Parameter
    private String graphqlQueryIntrospectionResultPath;

41 42 43
    @Parameter
    private SchemaFinderConfig graphqlSchemas = new SchemaFinderConfig();

44 45 46 47
    @Parameter(required = true)
    private File outputDir;

    @Parameter
48
    private Properties customTypesMapping = new Properties();
49

50
    @Parameter
51
    private Map<String, Properties> customAnnotationsMapping;
52

53
    @Parameter
54
    private Map<String, Properties> directiveAnnotationsMapping;
55

56 57 58
    @Parameter
    private String packageName;

59
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_BUILDER_STRING)
60 61
    private boolean generateBuilder;

62
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_GENERATE_APIS_STRING)
63 64
    private boolean generateApis;

65
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_EQUALS_AND_HASHCODE_STRING)
66 67
    private boolean generateEqualsAndHashCode;

68 69 70
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_GENERATE_IMMUTABLE_MODELS_STRING)
    private boolean generateImmutableModels;

71
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_TO_STRING_STRING)
72 73 74 75
    private boolean generateToString;

    @Parameter
    private String apiPackageName;
76

77 78 79
    @Parameter
    private String apiNamePrefix;

80
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_RESOLVER_SUFFIX)
81 82
    private String apiNameSuffix;

83 84
    @Parameter
    private String modelPackageName;
85

86 87
    @Parameter
    private String modelNamePrefix;
88

89 90
    @Parameter
    private String modelNameSuffix;
91

92 93 94 95 96 97
    @Parameter
    private String typeResolverPrefix;

    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_RESOLVER_SUFFIX)
    private String typeResolverSuffix;

98 99
    @Parameter
    private String apiReturnType;
100 101

    @Parameter
102
    private String apiReturnListType;
103

104 105 106
    @Parameter
    private String subscriptionReturnType;

107 108 109
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_API_ROOT_INTERFACE_STRATEGY_STRING)
    private ApiRootInterfaceStrategy apiRootInterfaceStrategy;

110 111 112
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_API_INTERFACE_STRATEGY_STRING)
    private ApiInterfaceStrategy apiInterfaceStrategy;

113 114 115
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_API_NAME_PREFIX_STRATEGY_STRING)
    private ApiNamePrefixStrategy apiNamePrefixStrategy;

116
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_VALIDATION_ANNOTATION)
117 118
    private String modelValidationAnnotation;

119
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_GENERATE_PARAMETERIZED_FIELDS_RESOLVERS_STRING)
120 121
    private boolean generateParameterizedFieldsResolvers;

122
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_GENERATE_EXTENSION_FIELDS_RESOLVERS_STRING)
123 124
    private boolean generateExtensionFieldsResolvers;

125
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_GENERATE_DATA_FETCHING_ENV_STRING)
126 127
    private boolean generateDataFetchingEnvironmentArgumentInApis;

128 129 130
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_GENERATE_MODELS_FOR_ROOT_TYPES_STRING)
    private boolean generateModelsForRootTypes;

131 132 133
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_USE_OPTIONAL_FOR_NULLABLE_RETURN_TYPES_STRING)
    private boolean useOptionalForNullableReturnTypes;

134 135 136
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_GENERATE_APIS_WITH_THROWS_EXCEPTION_STRING)
    private boolean generateApisWithThrowsException;

137
    @Parameter
138
    private String[] fieldsWithResolvers;
139

140
    @Parameter
141
    private String[] fieldsWithoutResolvers;
142

143 144 145
    @Parameter
    private RelayConfig relayConfig = new RelayConfig();

146 147 148
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_GENERATE_CLIENT_STRING)
    private boolean generateClient;

149
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_REQUEST_SUFFIX)
150 151
    private String requestSuffix;

152 153 154
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_RESPONSE_SUFFIX)
    private String responseSuffix;

155
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_RESPONSE_PROJECTION_SUFFIX)
156 157
    private String responseProjectionSuffix;

158
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_PARAMETRIZED_INPUT_SUFFIX)
159 160
    private String parametrizedInputSuffix;

B
Bogdan Kobylynskyi 已提交
161
    @Parameter
162
    private String[] useObjectMapperForRequestSerialization;
B
Bogdan Kobylynskyi 已提交
163

164 165
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_RESPONSE_PROJECTION_MAX_DEPTH_STRING)
    private int responseProjectionMaxDepth;
166

167 168 169
    @Parameter
    private ParentInterfacesConfig parentInterfaces = new ParentInterfacesConfig();

170 171 172
    @Parameter(defaultValue = MappingConfigConstants.DEFAULT_GENERATED_LANGUAGE_STRING)
    private GeneratedLanguage generatedLanguage;

173 174 175
    @Parameter
    private String jsonConfigurationFile;

176 177 178 179 180 181 182 183 184 185 186 187
    /**
     * The project being built.
     */
    @Parameter(readonly = true, required = true, defaultValue = "${project}")
    private MavenProject project;

    @Override
    public void execute() throws MojoExecutionException {
        addCompileSourceRootIfConfigured();

        MappingConfig mappingConfig = new MappingConfig();
        mappingConfig.setPackageName(packageName);
188
        mappingConfig.setCustomTypesMapping(convertToMap(customTypesMapping));
189 190
        mappingConfig.setCustomAnnotationsMapping(convertToListsMap(customAnnotationsMapping));
        mappingConfig.setDirectiveAnnotationsMapping(convertToListsMap(directiveAnnotationsMapping));
191 192
        mappingConfig.setApiNameSuffix(apiNameSuffix);
        mappingConfig.setApiNamePrefix(apiNamePrefix);
193
        mappingConfig.setApiRootInterfaceStrategy(apiRootInterfaceStrategy);
194
        mappingConfig.setApiInterfaceStrategy(apiInterfaceStrategy);
195
        mappingConfig.setApiNamePrefixStrategy(apiNamePrefixStrategy);
196 197 198 199
        mappingConfig.setModelNamePrefix(modelNamePrefix);
        mappingConfig.setModelNameSuffix(modelNameSuffix);
        mappingConfig.setApiPackageName(apiPackageName);
        mappingConfig.setModelPackageName(modelPackageName);
200
        mappingConfig.setGenerateBuilder(generateBuilder);
201
        mappingConfig.setGenerateApis(generateApis);
202 203
        mappingConfig.setTypeResolverSuffix(typeResolverSuffix);
        mappingConfig.setTypeResolverPrefix(typeResolverPrefix);
204 205
        mappingConfig.setModelValidationAnnotation(modelValidationAnnotation);
        mappingConfig.setGenerateEqualsAndHashCode(generateEqualsAndHashCode);
206
        mappingConfig.setGenerateImmutableModels(generateImmutableModels);
207
        mappingConfig.setGenerateToString(generateToString);
208 209
        mappingConfig.setApiReturnType(apiReturnType);
        mappingConfig.setApiReturnListType(apiReturnListType);
210
        mappingConfig.setSubscriptionReturnType(subscriptionReturnType);
211
        mappingConfig.setGenerateParameterizedFieldsResolvers(generateParameterizedFieldsResolvers);
212
        mappingConfig.setGenerateDataFetchingEnvironmentArgumentInApis(generateDataFetchingEnvironmentArgumentInApis);
213
        mappingConfig.setGenerateExtensionFieldsResolvers(generateExtensionFieldsResolvers);
214
        mappingConfig.setGenerateModelsForRootTypes(generateModelsForRootTypes);
215
        mappingConfig.setUseOptionalForNullableReturnTypes(useOptionalForNullableReturnTypes);
216
        mappingConfig.setGenerateApisWithThrowsException(generateApisWithThrowsException);
217 218
        mappingConfig.setFieldsWithResolvers(mapToHashSet(fieldsWithResolvers));
        mappingConfig.setFieldsWithoutResolvers(mapToHashSet(fieldsWithoutResolvers));
219 220
        mappingConfig.setRelayConfig(relayConfig);

221
        mappingConfig.setGenerateClient(generateClient);
222
        mappingConfig.setRequestSuffix(requestSuffix);
223
        mappingConfig.setResponseSuffix(responseSuffix);
224
        mappingConfig.setResponseProjectionSuffix(responseProjectionSuffix);
225
        mappingConfig.setParametrizedInputSuffix(parametrizedInputSuffix);
226 227 228
        mappingConfig.setResponseProjectionMaxDepth(responseProjectionMaxDepth);
        mappingConfig.setUseObjectMapperForRequestSerialization(mapToHashSet(useObjectMapperForRequestSerialization));

229 230 231 232
        mappingConfig.setResolverParentInterface(getResolverParentInterface());
        mappingConfig.setQueryResolverParentInterface(getQueryResolverParentInterface());
        mappingConfig.setMutationResolverParentInterface(getMutationResolverParentInterface());
        mappingConfig.setSubscriptionResolverParentInterface(getSubscriptionResolverParentInterface());
233

234 235
        mappingConfig.setGeneratedLanguage(getGeneratedLanguage());

236 237 238
        MappingConfigSupplier mappingConfigSupplier = buildJsonSupplier(jsonConfigurationFile);

        try {
239
            new GraphQLCodegen(getSchemas(), graphqlQueryIntrospectionResultPath, outputDir, mappingConfig, mappingConfigSupplier).generate();
240 241 242 243 244 245
        } catch (Exception e) {
            getLog().error(e);
            throw new MojoExecutionException("Code generation failed. See above for the full exception.");
        }
    }

246
    private List<String> getSchemas() throws IOException {
247 248 249
        if (graphqlSchemaPaths != null) {
            return Arrays.asList(graphqlSchemaPaths);
        }
250 251 252 253 254 255 256 257 258 259 260 261 262
        Path schemasRootDir = getSchemasRootDir();
        SchemaFinder finder = new SchemaFinder(schemasRootDir);
        finder.setRecursive(graphqlSchemas.isRecursive());
        finder.setIncludePattern(graphqlSchemas.getIncludePattern());
        finder.setExcludedFiles(graphqlSchemas.getExcludedFiles());
        return finder.findSchemas();
    }

    private Path getSchemasRootDir() {
        String rootDir = graphqlSchemas.getRootDir();
        if (rootDir == null) {
            return getDefaultResourcesDirectory().orElseThrow(() -> new IllegalStateException(
                    "Default resource folder not found, please provide <rootDir> in <graphqlSchemas>"));
263
        }
264 265 266 267 268
        return Paths.get(rootDir);
    }

    private Optional<Path> getDefaultResourcesDirectory() {
        return project.getResources().stream().findFirst().map(Resource::getDirectory).map(Paths::get);
269 270
    }

271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
    private MappingConfigSupplier buildJsonSupplier(String jsonConfigurationFile) {
        if (jsonConfigurationFile != null && !jsonConfigurationFile.isEmpty()) {
            return new JsonMappingConfigSupplier(jsonConfigurationFile);
        }
        return null;
    }

    private void addCompileSourceRootIfConfigured() {
        String path = outputDir.getPath();
        getLog().info("Added the following path to the source root: " + path);
        project.addCompileSourceRoot(path);
    }

    public String[] getGraphqlSchemaPaths() {
        return graphqlSchemaPaths;
    }

288 289 290 291
    public String getGraphqlQueryIntrospectionResultPath() {
        return graphqlQueryIntrospectionResultPath;
    }

292 293 294 295
    public SchemaFinderConfig getGraphqlSchemas() {
        return graphqlSchemas;
    }

296 297 298 299
    public File getOutputDir() {
        return outputDir;
    }

300
    @Override
301
    public Map<String, String> getCustomTypesMapping() {
302
        return convertToMap(customTypesMapping);
303 304
    }

305
    @Override
306 307
    public Map<String, List<String>> getCustomAnnotationsMapping() {
        return convertToListsMap(customAnnotationsMapping);
308 309 310
    }

    @Override
311 312
    public Map<String, List<String>> getDirectiveAnnotationsMapping() {
        return convertToListsMap(directiveAnnotationsMapping);
313 314
    }

315
    @Override
316 317 318 319
    public String getPackageName() {
        return packageName;
    }

320
    @Override
321 322 323 324
    public String getApiPackageName() {
        return apiPackageName;
    }

325 326 327 328 329 330 331 332 333 334
    @Override
    public String getApiNamePrefix() {
        return apiNamePrefix;
    }

    @Override
    public String getApiNameSuffix() {
        return apiNameSuffix;
    }

335
    @Override
336 337 338 339
    public String getModelPackageName() {
        return modelPackageName;
    }

340
    @Override
341 342 343 344
    public String getModelNamePrefix() {
        return modelNamePrefix;
    }

345
    @Override
346 347 348 349
    public String getModelNameSuffix() {
        return modelNameSuffix;
    }

350
    @Override
351 352 353 354
    public String getModelValidationAnnotation() {
        return modelValidationAnnotation;
    }

355 356
    @Override
    public Boolean getGenerateBuilder() {
357 358 359
        return generateBuilder;
    }

360 361
    @Override
    public Boolean getGenerateApis() {
362 363 364
        return generateApis;
    }

365 366 367 368 369
    @Override
    public Boolean getGenerateModelsForRootTypes() {
        return generateModelsForRootTypes;
    }

370 371
    @Override
    public Boolean getGenerateEqualsAndHashCode() {
372 373 374
        return generateEqualsAndHashCode;
    }

375 376 377 378 379
    @Override
    public Boolean getGenerateImmutableModels() {
        return generateImmutableModels;
    }

380 381
    @Override
    public Boolean getGenerateToString() {
382 383 384
        return generateToString;
    }

385
    @Override
386 387
    public String getApiReturnType() {
        return apiReturnType;
388 389 390
    }

    @Override
391 392
    public String getApiReturnListType() {
        return apiReturnListType;
393 394
    }

395 396 397
    @Override
    public String getSubscriptionReturnType() {
        return subscriptionReturnType;
398 399
    }

400 401 402
    @Override
    public Boolean getGenerateExtensionFieldsResolvers() {
        return generateExtensionFieldsResolvers;
403
    }
404

405 406
    @Override
    public Boolean getGenerateParameterizedFieldsResolvers() {
407 408 409
        return generateParameterizedFieldsResolvers;
    }

410 411 412 413 414 415 416 417 418 419
    @Override
    public String getTypeResolverPrefix() {
        return typeResolverPrefix;
    }

    @Override
    public String getTypeResolverSuffix() {
        return typeResolverSuffix;
    }

420 421
    @Override
    public Boolean getGenerateDataFetchingEnvironmentArgumentInApis() {
422 423 424
        return generateDataFetchingEnvironmentArgumentInApis;
    }

B
Bogdan Kobylynskyi 已提交
425 426 427 428 429
    @Override
    public RelayConfig getRelayConfig() {
        return relayConfig;
    }

430 431 432 433 434
    @Override
    public Boolean getUseOptionalForNullableReturnTypes() {
        return useOptionalForNullableReturnTypes;
    }

435
    @Override
436 437 438 439 440
    public Boolean getGenerateApisWithThrowsException() {
        return generateApisWithThrowsException;
    }

    @Override
441 442 443 444
    public ApiRootInterfaceStrategy getApiRootInterfaceStrategy() {
        return apiRootInterfaceStrategy;
    }

445 446 447 448 449
    @Override
    public ApiInterfaceStrategy getApiInterfaceStrategy() {
        return apiInterfaceStrategy;
    }

450 451 452 453 454
    @Override
    public ApiNamePrefixStrategy getApiNamePrefixStrategy() {
        return apiNamePrefixStrategy;
    }

455
    @Override
456
    public Set<String> getFieldsWithResolvers() {
457
        return mapToHashSet(fieldsWithResolvers);
458 459
    }

460 461
    @Override
    public Set<String> getFieldsWithoutResolvers() {
462
        return mapToHashSet(fieldsWithoutResolvers);
463 464
    }

465 466 467 468 469
    @Override
    public Integer getResponseProjectionMaxDepth() {
        return responseProjectionMaxDepth;
    }

470
    @Override
471 472 473 474
    public Boolean getGenerateClient() {
        return generateClient;
    }

475
    @Override
476 477 478 479
    public String getRequestSuffix() {
        return requestSuffix;
    }

480 481 482 483 484
    @Override
    public String getResponseSuffix() {
        return responseSuffix;
    }

485
    @Override
486 487 488 489
    public String getResponseProjectionSuffix() {
        return responseProjectionSuffix;
    }

490 491 492 493 494
    @Override
    public String getParametrizedInputSuffix() {
        return parametrizedInputSuffix;
    }

495 496 497 498 499
    @Override
    public Set<String> getUseObjectMapperForRequestSerialization() {
        return mapToHashSet(useObjectMapperForRequestSerialization);
    }

500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
    @Override
    public String getQueryResolverParentInterface() {
        return parentInterfaces.getQueryResolver();
    }

    @Override
    public String getMutationResolverParentInterface() {
        return parentInterfaces.getMutationResolver();
    }

    @Override
    public String getSubscriptionResolverParentInterface() {
        return parentInterfaces.getSubscriptionResolver();
    }

    @Override
    public String getResolverParentInterface() {
        return parentInterfaces.getResolver();
    }

520 521 522 523 524
    @Override
    public GeneratedLanguage getGeneratedLanguage() {
        return generatedLanguage;
    }

525 526
    public ParentInterfacesConfig getParentInterfaces() {
        return parentInterfaces;
527 528
    }

529 530
    public String getJsonConfigurationFile() {
        return jsonConfigurationFile;
531 532
    }

533
    private static Map<String, List<String>> convertToListsMap(Map<String, Properties> sourceMap) {
534 535 536
        if (sourceMap == null) {
            return new HashMap<>();
        }
537 538
        Map<String, List<String>> map = new HashMap<>(sourceMap.size());
        for (Map.Entry<String, Properties> e : sourceMap.entrySet()) {
539
            if (e.getValue() != null) {
540 541 542 543 544 545
                Collection<Object> values = e.getValue().values();
                List<String> stringValues = new ArrayList<>(values.size());
                for (Object value : values) {
                    stringValues.add(value.toString());
                }
                map.put(e.getKey(), stringValues);
546 547 548 549 550 551 552 553 554 555 556 557
            }
        }
        return map;
    }

    private static Set<String> mapToHashSet(String[] sourceSet) {
        if (sourceSet == null) {
            return Collections.emptySet();
        }
        return new HashSet<>(Arrays.asList(sourceSet));
    }

558 559 560 561 562 563 564 565 566 567 568
    private static Map<String, String> convertToMap(Properties properties) {
        if (properties == null) {
            return null;
        }
        Map<String, String> result = new HashMap<>(properties.size());
        for (String name : properties.stringPropertyNames()) {
            result.put(name, properties.getProperty(name));
        }
        return result;
    }

569
}