Skip to content

Commit 9867d9c

Browse files
committed
Ability to supply resolverArgumentAnnotations and parametrizedResolverAnnotations #983
1 parent 27ae71e commit 9867d9c

File tree

16 files changed

+429
-104
lines changed

16 files changed

+429
-104
lines changed

docs/codegen-options.md

+91-93
Large diffs are not rendered by default.

plugins/gradle/graphql-java-codegen-gradle-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/gradle/GraphQLCodegenGradleTask.java

+28
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ public class GraphQLCodegenGradleTask extends DefaultTask implements GraphQLCode
8787
private Set<String> fieldsWithResolvers = new HashSet<>();
8888
private Set<String> fieldsWithoutResolvers = new HashSet<>();
8989
private Set<String> typesAsInterfaces = new HashSet<>();
90+
private Set<String> resolverArgumentAnnotations = new HashSet<>();
91+
private Set<String> parametrizedResolverAnnotations = new HashSet<>();
9092
private final RelayConfig relayConfig = new RelayConfig();
9193

9294

@@ -164,6 +166,10 @@ public void generate() throws Exception {
164166
fieldsWithoutResolvers != null ? fieldsWithoutResolvers : new HashSet<>());
165167
mappingConfig.setTypesAsInterfaces(
166168
typesAsInterfaces != null ? typesAsInterfaces : new HashSet<>());
169+
mappingConfig.setResolverArgumentAnnotations(
170+
resolverArgumentAnnotations != null ? resolverArgumentAnnotations : new HashSet<>());
171+
mappingConfig.setParametrizedResolverAnnotations(
172+
parametrizedResolverAnnotations != null ? parametrizedResolverAnnotations : new HashSet<>());
167173
mappingConfig.setRelayConfig(relayConfig);
168174

169175
mappingConfig.setGenerateClient(generateClient);
@@ -689,6 +695,28 @@ public void setTypesAsInterfaces(Set<String> typesAsInterfaces) {
689695
this.typesAsInterfaces = typesAsInterfaces;
690696
}
691697

698+
@Input
699+
@Optional
700+
@Override
701+
public Set<String> getResolverArgumentAnnotations() {
702+
return resolverArgumentAnnotations;
703+
}
704+
705+
public void setResolverArgumentAnnotations(Set<String> resolverArgumentAnnotations) {
706+
this.resolverArgumentAnnotations = resolverArgumentAnnotations;
707+
}
708+
709+
@Input
710+
@Optional
711+
@Override
712+
public Set<String> getParametrizedResolverAnnotations() {
713+
return parametrizedResolverAnnotations;
714+
}
715+
716+
public void setParametrizedResolverAnnotations(Set<String> parametrizedResolverAnnotations) {
717+
this.parametrizedResolverAnnotations = parametrizedResolverAnnotations;
718+
}
719+
692720
@Nested
693721
@Optional
694722
@Override

plugins/maven/graphql-java-codegen-maven-plugin/src/main/java/io/github/kobylynskyi/graphql/codegen/GraphQLCodegenMojo.java

+18
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,12 @@ public class GraphQLCodegenMojo extends AbstractMojo implements GraphQLCodegenCo
185185
@Parameter
186186
private String[] typesAsInterfaces;
187187

188+
@Parameter
189+
private String[] resolverArgumentAnnotations;
190+
191+
@Parameter
192+
private String[] parametrizedResolverAnnotations;
193+
188194
@Parameter(defaultValue = MappingConfigConstants.DEFAULT_RESPONSE_PROJECTION_MAX_DEPTH_STRING)
189195
private int responseProjectionMaxDepth;
190196

@@ -271,6 +277,8 @@ public void execute() throws MojoExecutionException {
271277
mappingConfig.setResponseProjectionMaxDepth(responseProjectionMaxDepth);
272278
mappingConfig.setUseObjectMapperForRequestSerialization(mapToHashSet(useObjectMapperForRequestSerialization));
273279
mappingConfig.setTypesAsInterfaces(mapToHashSet(typesAsInterfaces));
280+
mappingConfig.setResolverArgumentAnnotations(mapToHashSet(resolverArgumentAnnotations));
281+
mappingConfig.setParametrizedResolverAnnotations(mapToHashSet(parametrizedResolverAnnotations));
274282

275283
mappingConfig.setResolverParentInterface(getResolverParentInterface());
276284
mappingConfig.setQueryResolverParentInterface(getQueryResolverParentInterface());
@@ -590,6 +598,16 @@ public Set<String> getTypesAsInterfaces() {
590598
return mapToHashSet(typesAsInterfaces);
591599
}
592600

601+
@Override
602+
public Set<String> getResolverArgumentAnnotations() {
603+
return mapToHashSet(resolverArgumentAnnotations);
604+
}
605+
606+
@Override
607+
public Set<String> getParametrizedResolverAnnotations() {
608+
return mapToHashSet(parametrizedResolverAnnotations);
609+
}
610+
593611
@Override
594612
public String getQueryResolverParentInterface() {
595613
return parentInterfaces.getQueryResolver();

src/main/java/com/kobylynskyi/graphql/codegen/GraphQLCodegen.java

+10
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.Collection;
2323
import java.util.List;
2424
import java.util.Map;
25+
import java.util.stream.Collectors;
2526

2627
import static java.util.stream.Collectors.toList;
2728

@@ -96,6 +97,15 @@ private static void sanitizeValues(MappingConfig mappingConfig) {
9697
mappingConfig.setModelValidationAnnotation(
9798
Utils.replaceLeadingAtSign(mappingConfig.getModelValidationAnnotation()));
9899

100+
if (mappingConfig.getResolverArgumentAnnotations() != null) {
101+
mappingConfig.setResolverArgumentAnnotations(mappingConfig.getResolverArgumentAnnotations().stream()
102+
.map(Utils::replaceLeadingAtSign).collect(Collectors.toSet()));
103+
}
104+
if (mappingConfig.getParametrizedResolverAnnotations() != null) {
105+
mappingConfig.setParametrizedResolverAnnotations(mappingConfig.getParametrizedResolverAnnotations().stream()
106+
.map(Utils::replaceLeadingAtSign).collect(Collectors.toSet()));
107+
}
108+
99109
Map<String, List<String>> customAnnotationsMapping = mappingConfig.getCustomAnnotationsMapping();
100110
if (customAnnotationsMapping != null) {
101111
for (Map.Entry<String, List<String>> entry : customAnnotationsMapping.entrySet()) {

src/main/java/com/kobylynskyi/graphql/codegen/generators/impl/FieldResolversGenerator.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import java.util.Collections;
1818
import java.util.List;
1919
import java.util.Map;
20+
import java.util.Set;
2021

2122
import static java.util.stream.Collectors.toList;
2223

@@ -51,9 +52,9 @@ private List<File> generate(List<ExtendedFieldDefinition> fieldDefinitions,
5152
if (!Boolean.TRUE.equals(mappingContext.getGenerateApis())) {
5253
return Collections.emptyList();
5354
}
55+
Set<String> fieldNamesWithResolvers = mappingContext.getFieldNamesWithResolvers();
5456
List<ExtendedFieldDefinition> fieldDefsWithResolvers = fieldDefinitions.stream()
55-
.filter(fieldDef -> FieldDefinitionToParameterMapper.generateResolversForField(
56-
mappingContext, fieldDef, parentDefinition))
57+
.filter(fieldDef -> fieldNamesWithResolvers.contains(parentDefinition.getName() + "." + fieldDef.getName()))
5758
.collect(toList());
5859

5960
List<File> generatedFiles = new ArrayList<>();

src/main/java/com/kobylynskyi/graphql/codegen/mapper/AnnotationsMapper.java

+13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.kobylynskyi.graphql.codegen.mapper;
22

3+
import com.kobylynskyi.graphql.codegen.model.MappingConfigConstants;
34
import com.kobylynskyi.graphql.codegen.model.MappingContext;
45
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDefinition;
56
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedFieldDefinition;
@@ -120,6 +121,18 @@ public List<String> getAnnotations(MappingContext mappingContext, String graphQL
120121
annotations.addAll(getAnnotationsForDirective(mappingContext, directiveAnnotations, directive));
121122
}
122123
}
124+
// 6. Add annotations for resolver arguments
125+
if (!Utils.isEmpty(mappingContext.getResolverArgumentAnnotations())
126+
&& mappingContext.getOperationsName().contains(parentTypeName)) {
127+
annotations.addAll(mappingContext.getResolverArgumentAnnotations());
128+
}
129+
// 7. Add annotations for parametrized resolvers
130+
if (!Utils.isEmpty(mappingContext.getParametrizedResolverAnnotations())
131+
&& mappingContext.getFieldNamesWithResolvers().contains(parentTypeName + "." + name)) {
132+
for (String annotation : mappingContext.getParametrizedResolverAnnotations()) {
133+
annotations.add(annotation.replace(MappingConfigConstants.TYPE_NAME_PLACEHOLDER, parentTypeName));
134+
}
135+
}
123136
return annotations;
124137
}
125138

src/main/java/com/kobylynskyi/graphql/codegen/model/GraphQLCodegenConfiguration.java

+24
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,30 @@ public interface GraphQLCodegenConfiguration {
432432
*/
433433
Set<String> getTypesAsInterfaces();
434434

435+
/**
436+
* Annotations that will be added to all resolver arguments.
437+
*
438+
* <p>E.g.:
439+
* <ul>
440+
* <li>{@code @org.springframework.graphql.data.method.annotation.Argument}</li>
441+
* </ul>
442+
*
443+
* @return Set of annotations that every resolver argument will have.
444+
*/
445+
Set<String> getResolverArgumentAnnotations();
446+
447+
/**
448+
* Annotations that will be added to all parametrized resolver methods.
449+
*
450+
* <p>E.g.:
451+
* <ul>
452+
* <li>{@code @org.springframework.graphql.data.method.annotation.Argument}</li>
453+
* </ul>
454+
*
455+
* @return Set of annotations that every parametrized resolver method will have.
456+
*/
457+
Set<String> getParametrizedResolverAnnotations();
458+
435459
/**
436460
* Generate code with lang
437461
*

src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java

+29-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.kobylynskyi.graphql.codegen.model;
22

3+
import java.util.ArrayList;
34
import java.util.HashMap;
45
import java.util.HashSet;
56
import java.util.List;
@@ -15,10 +16,6 @@
1516
*/
1617
public class MappingConfig implements GraphQLCodegenConfiguration, Combinable<MappingConfig> {
1718

18-
private Map<String, String> customTypesMapping = new HashMap<>();
19-
private Map<String, List<String>> customAnnotationsMapping = new HashMap<>();
20-
private Map<String, List<String>> directiveAnnotationsMapping = new HashMap<>();
21-
2219
// package name configs:
2320
private String packageName;
2421
private String apiPackageName;
@@ -77,6 +74,14 @@ public class MappingConfig implements GraphQLCodegenConfiguration, Combinable<Ma
7774
private Integer responseProjectionMaxDepth;
7875
private Set<String> useObjectMapperForRequestSerialization = new HashSet<>();
7976

77+
// annotations:
78+
private Map<String, List<String>> customAnnotationsMapping = new HashMap<>();
79+
private Map<String, List<String>> directiveAnnotationsMapping = new HashMap<>();
80+
private Set<String> resolverArgumentAnnotations = new HashSet<>();
81+
private Set<String> parametrizedResolverAnnotations = new HashSet<>();
82+
83+
private Map<String, String> customTypesMapping = new HashMap<>();
84+
8085
private Set<String> typesAsInterfaces = new HashSet<>();
8186

8287
private boolean generateModelOpenClasses;
@@ -179,6 +184,8 @@ public void combine(MappingConfig source) {
179184
customTypesMapping = combineMap(customTypesMapping, source.customTypesMapping);
180185
customAnnotationsMapping = combineMap(customAnnotationsMapping, source.customAnnotationsMapping);
181186
directiveAnnotationsMapping = combineMap(directiveAnnotationsMapping, source.directiveAnnotationsMapping);
187+
resolverArgumentAnnotations = combineSet(resolverArgumentAnnotations, source.resolverArgumentAnnotations);
188+
parametrizedResolverAnnotations = combineSet(parametrizedResolverAnnotations, source.parametrizedResolverAnnotations);
182189
generateAllMethodInProjection = getValueOrDefaultToThis(source,
183190
GraphQLCodegenConfiguration::getGenerateAllMethodInProjection);
184191
responseProjectionMaxDepth = getValueOrDefaultToThis(source,
@@ -641,6 +648,24 @@ public void setUseObjectMapperForRequestSerialization(Set<String> useObjectMappe
641648
this.useObjectMapperForRequestSerialization = useObjectMapperForRequestSerialization;
642649
}
643650

651+
@Override
652+
public Set<String> getResolverArgumentAnnotations() {
653+
return resolverArgumentAnnotations;
654+
}
655+
656+
public void setResolverArgumentAnnotations(Set<String> resolverArgumentAnnotations) {
657+
this.resolverArgumentAnnotations = resolverArgumentAnnotations;
658+
}
659+
660+
@Override
661+
public Set<String> getParametrizedResolverAnnotations() {
662+
return parametrizedResolverAnnotations;
663+
}
664+
665+
public void setParametrizedResolverAnnotations(Set<String> parametrizedResolverAnnotations) {
666+
this.parametrizedResolverAnnotations = parametrizedResolverAnnotations;
667+
}
668+
644669
@Override
645670
public Set<String> getTypesAsInterfaces() {
646671
return typesAsInterfaces;

src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfigConstants.java

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ public class MappingConfigConstants {
88

99
public static final String DEFAULT_VALIDATION_ANNOTATION = "javax.validation.constraints.NotNull";
1010
public static final String PARENT_INTERFACE_TYPE_PLACEHOLDER = "{{TYPE}}";
11+
public static final String TYPE_NAME_PLACEHOLDER = "{{TYPE_NAME}}";
1112
public static final boolean DEFAULT_GENERATE_APIS = true;
1213
public static final String DEFAULT_GENERATE_APIS_STRING = "true";
1314
public static final boolean DEFAULT_BUILDER = true;

src/main/java/com/kobylynskyi/graphql/codegen/model/MappingContext.java

+39-1
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22

33
import com.kobylynskyi.graphql.codegen.mapper.DataModelMapper;
44
import com.kobylynskyi.graphql.codegen.mapper.DataModelMapperFactory;
5+
import com.kobylynskyi.graphql.codegen.mapper.FieldDefinitionToParameterMapper;
56
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDefinition;
67
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedDocument;
78
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedEnumTypeDefinition;
89
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedFieldDefinition;
910
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedInterfaceTypeDefinition;
11+
import com.kobylynskyi.graphql.codegen.model.definitions.ExtendedObjectTypeDefinition;
1012

1113
import java.io.File;
1214
import java.util.HashMap;
15+
import java.util.HashSet;
1316
import java.util.List;
1417
import java.util.Map;
1518
import java.util.Set;
@@ -26,11 +29,13 @@ public class MappingContext implements GraphQLCodegenConfiguration {
2629
private final ExtendedDocument document;
2730
private final Set<String> typesUnionsInterfacesNames;
2831
private final Set<String> interfacesName;
32+
private final Set<String> operationsName;
2933
private final Map<String, Set<String>> interfaceChildren;
3034
private final GeneratedInformation generatedInformation;
3135
private final DataModelMapperFactory dataModelMapperFactory;
3236
private Set<String> enumImportItSelfInScala;
3337
private Map<String, Set<String>> parentInterfaceProperties;
38+
private Set<String> fieldNamesWithResolvers;
3439

3540
private MappingContext(File outputDirectory,
3641
MappingConfig mappingConfig,
@@ -44,6 +49,7 @@ private MappingContext(File outputDirectory,
4449
this.interfacesName = document.getInterfacesNames();
4550
this.interfaceChildren = document.getInterfaceChildren();
4651
this.generatedInformation = generatedInformation;
52+
this.operationsName = document.getOperationsNames();
4753
this.dataModelMapperFactory = dataModelMapperFactory;
4854
}
4955

@@ -63,7 +69,6 @@ public Boolean isInitializeNullableTypes() {
6369
}
6470

6571

66-
6772
@Override
6873
public Boolean isGenerateSealedInterfaces() {
6974
return config.isGenerateSealedInterfaces();
@@ -309,6 +314,16 @@ public Set<String> getTypesAsInterfaces() {
309314
return config.getTypesAsInterfaces();
310315
}
311316

317+
@Override
318+
public Set<String> getResolverArgumentAnnotations() {
319+
return config.getResolverArgumentAnnotations();
320+
}
321+
322+
@Override
323+
public Set<String> getParametrizedResolverAnnotations() {
324+
return config.getParametrizedResolverAnnotations();
325+
}
326+
312327
@Override
313328
public Boolean isSupportUnknownFields() {
314329
return config.isSupportUnknownFields();
@@ -331,6 +346,10 @@ public Set<String> getInterfacesName() {
331346
return interfacesName;
332347
}
333348

349+
public Set<String> getOperationsName() {
350+
return operationsName;
351+
}
352+
334353
public Map<String, Set<String>> getInterfaceChildren() {
335354
return interfaceChildren;
336355
}
@@ -381,6 +400,25 @@ public Map<String, Set<String>> getParentInterfaceProperties() {
381400
return parentInterfaceProperties;
382401
}
383402

403+
public Set<String> getFieldNamesWithResolvers() {
404+
if (fieldNamesWithResolvers == null) {
405+
fieldNamesWithResolvers = new HashSet<>();
406+
for (ExtendedObjectTypeDefinition definition : document.getTypeDefinitions()) {
407+
definition.getFieldDefinitions().stream()
408+
.filter(fieldDef -> FieldDefinitionToParameterMapper.generateResolversForField(
409+
this, fieldDef, definition))
410+
.forEach(fieldDef -> fieldNamesWithResolvers.add(definition.getName() + "." + fieldDef.getName()));
411+
}
412+
for (ExtendedInterfaceTypeDefinition definition : document.getInterfaceDefinitions()) {
413+
definition.getFieldDefinitions().stream()
414+
.filter(fieldDef -> FieldDefinitionToParameterMapper.generateResolversForField(
415+
this, fieldDef, definition))
416+
.forEach(fieldDef -> fieldNamesWithResolvers.add(definition.getName() + "." + fieldDef.getName()));
417+
}
418+
}
419+
return fieldNamesWithResolvers;
420+
}
421+
384422
private String getModelClassNameWithPrefixAndSuffix(ExtendedEnumTypeDefinition extendedEnumTypeDefinition) {
385423
return DataModelMapper.getModelClassNameWithPrefixAndSuffix(this, extendedEnumTypeDefinition.getName());
386424
}

0 commit comments

Comments
 (0)