17
17
package org .springframework .graphql .execution ;
18
18
19
19
import java .beans .PropertyDescriptor ;
20
+ import java .lang .reflect .Method ;
21
+ import java .lang .reflect .Modifier ;
20
22
import java .util .ArrayList ;
21
23
import java .util .Collections ;
22
24
import java .util .HashSet ;
58
60
import org .springframework .util .CollectionUtils ;
59
61
import org .springframework .util .LinkedMultiValueMap ;
60
62
import org .springframework .util .MultiValueMap ;
63
+ import org .springframework .util .StringUtils ;
61
64
62
65
/**
63
66
* Inspect schema mappings on startup to ensure the following:
@@ -81,6 +84,15 @@ public final class SchemaMappingInspector {
81
84
82
85
private static final Log logger = LogFactory .getLog (SchemaMappingInspector .class );
83
86
87
+ /**
88
+ * GraphQL Java detects "record-like" methods that match field names.
89
+ * This predicate aims to match the method {@code isRecordLike(Method)} in
90
+ * {@link graphql.schema.fetching.LambdaFetchingSupport}.
91
+ */
92
+ private static final Predicate <Method > recordLikePredicate = (method ) ->
93
+ (!method .getDeclaringClass ().equals (Object .class ) && !method .getReturnType ().equals (Void .class ) &&
94
+ method .getParameterCount () == 0 && Modifier .isPublic (method .getModifiers ()));
95
+
84
96
85
97
private final GraphQLSchema schema ;
86
98
@@ -173,6 +185,12 @@ private void checkFieldsContainer(
173
185
checkField (fieldContainer , field , ResolvableType .forMethodReturnType (descriptor .getReadMethod ()));
174
186
continue ;
175
187
}
188
+ // Kotlin function?
189
+ Method method = getRecordLikeMethod (resolvableType , fieldName );
190
+ if (method != null ) {
191
+ checkField (fieldContainer , field , ResolvableType .forMethodReturnType (method ));
192
+ continue ;
193
+ }
176
194
}
177
195
178
196
this .reportBuilder .unmappedField (FieldCoordinates .coordinates (typeName , fieldName ));
@@ -249,6 +267,19 @@ private PropertyDescriptor getProperty(ResolvableType resolvableType, String fie
249
267
}
250
268
}
251
269
270
+ @ Nullable
271
+ private static Method getRecordLikeMethod (ResolvableType resolvableType , String fieldName ) {
272
+ Class <?> clazz = resolvableType .resolve ();
273
+ if (clazz != null ) {
274
+ for (Method method : clazz .getDeclaredMethods ()) {
275
+ if (recordLikePredicate .test (method ) && fieldName .equals (StringUtils .uncapitalize (method .getName ()))) {
276
+ return method ;
277
+ }
278
+ }
279
+ }
280
+ return null ;
281
+ }
282
+
252
283
private static boolean isNotScalarOrEnumType (GraphQLType type ) {
253
284
return !(type instanceof GraphQLScalarType || type instanceof GraphQLEnumType );
254
285
}
0 commit comments