@@ -64,124 +64,139 @@ class SchemaMappingInspector {
64
64
65
65
private static final Log logger = LogFactory .getLog (SchemaMappingInspector .class );
66
66
67
- Report inspectSchemaMappings (GraphQLSchema schema , RuntimeWiring runtimeWiring ) {
68
- ReportBuilder report = ReportBuilder .create ();
69
- SchemaMappingInspection inspection = new SchemaMappingInspection (runtimeWiring );
70
- inspection .inspectOperation (schema .getQueryType (), report );
71
- inspection .inspectOperation (schema .getMutationType (), report );
72
- inspection .inspectOperation (schema .getSubscriptionType (), report );
73
- return report .build ();
74
- }
75
67
76
- private static class SchemaMappingInspection {
68
+ private final GraphQLSchema schema ;
77
69
78
- private final RuntimeWiring runtimeWiring ;
70
+ private final RuntimeWiring runtimeWiring ;
79
71
80
- private final Set <String > seenTypes = new HashSet <>();
72
+ private final Set <String > seenTypes = new HashSet <>();
81
73
82
- SchemaMappingInspection (RuntimeWiring runtimeWiring ) {
83
- this .runtimeWiring = runtimeWiring ;
84
- }
85
74
86
- @ SuppressWarnings ("rawtypes" )
87
- void inspectOperation (@ Nullable GraphQLObjectType operationType , ReportBuilder report ) {
88
- if (operationType != null ) {
89
- Map <String , DataFetcher > operationDataFetchers = this .runtimeWiring .getDataFetcherForType (operationType .getName ());
90
- for (GraphQLFieldDefinition fieldDefinition : operationType .getFieldDefinitions ()) {
91
- if (operationDataFetchers .containsKey (fieldDefinition .getName ())) {
92
- DataFetcher fieldDataFetcher = operationDataFetchers .get (fieldDefinition .getName ());
93
- if (fieldDataFetcher instanceof SelfDescribingDataFetcher <?> selfDescribingDataFetcher ) {
94
- inspectType (fieldDefinition .getType (), selfDescribingDataFetcher .getReturnType (), report );
95
- }
96
- }
97
- else {
98
- report .missingOperation (operationType , fieldDefinition );
75
+ private SchemaMappingInspector (GraphQLSchema schema , RuntimeWiring runtimeWiring ) {
76
+ this .schema = schema ;
77
+ this .runtimeWiring = runtimeWiring ;
78
+ }
79
+
80
+
81
+ public Report inspectMappings () {
82
+ ReportBuilder report = ReportBuilder .create ();
83
+ inspectOperation (schema .getQueryType (), report );
84
+ inspectOperation (schema .getMutationType (), report );
85
+ inspectOperation (schema .getSubscriptionType (), report );
86
+ return report .build ();
87
+ }
88
+
89
+
90
+ @ SuppressWarnings ("rawtypes" )
91
+ private void inspectOperation (@ Nullable GraphQLObjectType operationType , ReportBuilder report ) {
92
+ if (operationType != null ) {
93
+ Map <String , DataFetcher > operationDataFetchers = this .runtimeWiring .getDataFetcherForType (operationType .getName ());
94
+ for (GraphQLFieldDefinition fieldDefinition : operationType .getFieldDefinitions ()) {
95
+ if (operationDataFetchers .containsKey (fieldDefinition .getName ())) {
96
+ DataFetcher fieldDataFetcher = operationDataFetchers .get (fieldDefinition .getName ());
97
+ if (fieldDataFetcher instanceof SelfDescribingDataFetcher <?> selfDescribingDataFetcher ) {
98
+ inspectType (fieldDefinition .getType (), selfDescribingDataFetcher .getReturnType (), report );
99
99
}
100
100
}
101
+ else {
102
+ report .missingOperation (operationType , fieldDefinition );
103
+ }
101
104
}
102
105
}
106
+ }
103
107
104
- private void inspectType (GraphQLType type , ResolvableType declaredType , ReportBuilder report ) {
105
- if (type instanceof GraphQLObjectType objectType ) {
106
- inspectObjectType (objectType , declaredType , report );
107
- }
108
- else if (type instanceof GraphQLList listType ) {
109
- inspectType (listType .getWrappedType (), declaredType .getNested (2 ), report );
110
- }
111
- else if (type instanceof GraphQLNonNull nonNullType ) {
112
- inspectType (nonNullType .getWrappedType (), declaredType , report );
113
- }
114
- else if (type instanceof GraphQLNamedType namedType && logger .isTraceEnabled ()){
115
- logger .trace ("Cannot inspect type '" + namedType .getName () + "', inspector does not support "
116
- + type .getClass ().getSimpleName ());
117
- }
108
+ private void inspectType (GraphQLType type , ResolvableType declaredType , ReportBuilder report ) {
109
+ if (type instanceof GraphQLObjectType objectType ) {
110
+ inspectObjectType (objectType , declaredType , report );
111
+ }
112
+ else if (type instanceof GraphQLList listType ) {
113
+ inspectType (listType .getWrappedType (), declaredType .getNested (2 ), report );
118
114
}
115
+ else if (type instanceof GraphQLNonNull nonNullType ) {
116
+ inspectType (nonNullType .getWrappedType (), declaredType , report );
117
+ }
118
+ else if (type instanceof GraphQLNamedType namedType && logger .isTraceEnabled ()){
119
+ logger .trace ("Cannot inspect type '" + namedType .getName () + "', inspector does not support "
120
+ + type .getClass ().getSimpleName ());
121
+ }
122
+ }
119
123
120
- @ SuppressWarnings ("rawtypes" )
121
- private void inspectObjectType (GraphQLObjectType objectType , ResolvableType declaredType , ReportBuilder report ) {
122
- if (isTypeAlreadyInspected (objectType )) {
123
- return ;
124
- }
125
- if (isConnectionType (objectType )) {
126
- objectType = getEdgeNodeType (objectType );
127
- declaredType = declaredType .getNested (2 );
124
+ @ SuppressWarnings ("rawtypes" )
125
+ private void inspectObjectType (GraphQLObjectType objectType , ResolvableType declaredType , ReportBuilder report ) {
126
+ if (isTypeAlreadyInspected (objectType )) {
127
+ return ;
128
+ }
129
+ if (isConnectionType (objectType )) {
130
+ objectType = getEdgeNodeType (objectType );
131
+ declaredType = declaredType .getNested (2 );
132
+ }
133
+ Map <String , DataFetcher > typeDataFetcher = this .runtimeWiring .getDataFetcherForType (objectType .getName ());
134
+ Class <?> declaredClass = unwrapPublisherTypes (declaredType );
135
+ for (GraphQLFieldDefinition field : objectType .getFieldDefinitions ()) {
136
+ if (typeDataFetcher .containsKey (field .getName ())) {
137
+ DataFetcher fieldDataFetcher = typeDataFetcher .get (field .getName ());
138
+ if (fieldDataFetcher instanceof SelfDescribingDataFetcher <?> typedFieldDataFetcher ) {
139
+ inspectType (field .getType (), typedFieldDataFetcher .getReturnType (), report );
140
+ }
128
141
}
129
- Map <String , DataFetcher > typeDataFetcher = this .runtimeWiring .getDataFetcherForType (objectType .getName ());
130
- Class <?> declaredClass = unwrapPublisherTypes (declaredType );
131
- for (GraphQLFieldDefinition field : objectType .getFieldDefinitions ()) {
132
- if (typeDataFetcher .containsKey (field .getName ())) {
133
- DataFetcher fieldDataFetcher = typeDataFetcher .get (field .getName ());
134
- if (fieldDataFetcher instanceof SelfDescribingDataFetcher <?> typedFieldDataFetcher ) {
135
- inspectType (field .getType (), typedFieldDataFetcher .getReturnType (), report );
142
+ else {
143
+ try {
144
+ if (declaredClass == null || BeanUtils .getPropertyDescriptor (declaredClass , field .getName ()) == null ) {
145
+ report .missingField (objectType , field );
136
146
}
137
147
}
138
- else {
139
- try {
140
- if (declaredClass == null || BeanUtils .getPropertyDescriptor (declaredClass , field .getName ()) == null ) {
141
- report .missingField (objectType , field );
142
- }
143
- }
144
- catch (BeansException exc ) {
145
- logger .debug ("Failed while inspecting " + declaredType + " for property " + field .getName () + "" , exc );
146
- }
148
+ catch (BeansException exc ) {
149
+ logger .debug ("Failed while inspecting " + declaredType + " for property " + field .getName () + "" , exc );
147
150
}
148
151
}
149
152
}
153
+ }
150
154
151
- private boolean isConnectionType (GraphQLObjectType objectType ) {
152
- return (objectType .getName ().endsWith ("Connection" ) &&
153
- objectType .getField ("edges" ) != null && objectType .getField ("pageInfo" ) != null );
154
- }
155
+ private boolean isConnectionType (GraphQLObjectType objectType ) {
156
+ return (objectType .getName ().endsWith ("Connection" ) &&
157
+ objectType .getField ("edges" ) != null && objectType .getField ("pageInfo" ) != null );
158
+ }
155
159
156
- @ NotNull
157
- private GraphQLObjectType getEdgeNodeType (GraphQLObjectType objectType ) {
158
- GraphQLList edgesListType = (GraphQLList ) unwrapNonNull (objectType .getField ("edges" ).getType ());
159
- GraphQLObjectType edgeType = (GraphQLObjectType ) edgesListType .getWrappedType ();
160
- return (GraphQLObjectType ) unwrapNonNull (edgeType .getField ("node" ).getType ());
161
- }
160
+ @ NotNull
161
+ private GraphQLObjectType getEdgeNodeType (GraphQLObjectType objectType ) {
162
+ GraphQLList edgesListType = (GraphQLList ) unwrapNonNull (objectType .getField ("edges" ).getType ());
163
+ GraphQLObjectType edgeType = (GraphQLObjectType ) edgesListType .getWrappedType ();
164
+ return (GraphQLObjectType ) unwrapNonNull (edgeType .getField ("node" ).getType ());
165
+ }
162
166
163
- private <T extends GraphQLType > GraphQLType unwrapNonNull (GraphQLType outputType ) {
164
- return (outputType instanceof GraphQLNonNull wrapper ? wrapper .getWrappedType () : outputType );
165
- }
167
+ private <T extends GraphQLType > GraphQLType unwrapNonNull (GraphQLType outputType ) {
168
+ return (outputType instanceof GraphQLNonNull wrapper ? wrapper .getWrappedType () : outputType );
169
+ }
166
170
167
- @ Nullable
168
- private Class <?> unwrapPublisherTypes (ResolvableType declaredType ) {
169
- Class <?> rawClass = declaredType .getRawClass ();
170
- if (rawClass != null ) {
171
- ReactiveAdapter adapter = ReactiveAdapterRegistry .getSharedInstance ().getAdapter (declaredType .getRawClass ());
172
- if (adapter != null ) {
173
- return declaredType .getNested (2 ).getRawClass ();
174
- }
171
+ @ Nullable
172
+ private Class <?> unwrapPublisherTypes (ResolvableType declaredType ) {
173
+ Class <?> rawClass = declaredType .getRawClass ();
174
+ if (rawClass != null ) {
175
+ ReactiveAdapter adapter = ReactiveAdapterRegistry .getSharedInstance ().getAdapter (declaredType .getRawClass ());
176
+ if (adapter != null ) {
177
+ return declaredType .getNested (2 ).getRawClass ();
175
178
}
176
- return rawClass ;
177
179
}
180
+ return rawClass ;
181
+ }
182
+
183
+ private boolean isTypeAlreadyInspected (GraphQLObjectType objectType ) {
184
+ return !this .seenTypes .add (objectType .getName ());
185
+ }
178
186
179
- private boolean isTypeAlreadyInspected (GraphQLObjectType objectType ) {
180
- return !this .seenTypes .add (objectType .getName ());
181
- }
182
187
188
+ /**
189
+ * Inspect the schema mappings and produce a report.
190
+ * @param schema the schema to inspect
191
+ * @param runtimeWiring for {@code DataFetcher} mappings
192
+ * @return the resulting report
193
+ */
194
+ public static Report inspect (GraphQLSchema schema , RuntimeWiring runtimeWiring ) {
195
+ return new SchemaMappingInspector (schema , runtimeWiring ).inspectMappings ();
183
196
}
184
197
198
+
199
+
185
200
record Report (MultiValueMap <String , String > missingOperations , MultiValueMap <String , String > missingFields ) {
186
201
187
202
String getSummary () {
@@ -190,7 +205,7 @@ String getSummary() {
190
205
builder .append ("no missing mapping." );
191
206
}
192
207
else {
193
- builder .append (getDetailedReport ());
208
+ builder .append (getDetailedReport ());
194
209
}
195
210
return builder .toString ();
196
211
}
@@ -210,6 +225,7 @@ boolean isEmpty() {
210
225
211
226
}
212
227
228
+
213
229
private static class ReportBuilder {
214
230
215
231
private final MultiValueMap <String , String > missingOperations = new LinkedMultiValueMap <>();
0 commit comments