44import graphql .PublicApi ;
55import graphql .schema .GraphQLEnumType ;
66import graphql .schema .GraphQLFieldDefinition ;
7+ import graphql .schema .GraphQLFieldsContainer ;
78import graphql .schema .GraphQLImplementingType ;
89import graphql .schema .GraphQLInputObjectField ;
910import graphql .schema .GraphQLInputObjectType ;
2425
2526import java .util .ArrayList ;
2627import java .util .HashSet ;
28+ import java .util .LinkedHashSet ;
2729import java .util .List ;
2830import java .util .Map ;
2931import java .util .Objects ;
@@ -45,7 +47,9 @@ public class FieldVisibilitySchemaTransformation {
4547 private final Runnable afterTransformationHook ;
4648
4749 public FieldVisibilitySchemaTransformation (VisibleFieldPredicate visibleFieldPredicate ) {
48- this (visibleFieldPredicate , () -> {}, () -> {});
50+ this (visibleFieldPredicate , () -> {
51+ }, () -> {
52+ });
4953 }
5054
5155 public FieldVisibilitySchemaTransformation (VisibleFieldPredicate visibleFieldPredicate ,
@@ -155,16 +159,53 @@ private static class FieldRemovalVisitor extends GraphQLTypeVisitorStub {
155159 private final VisibleFieldPredicate visibilityPredicate ;
156160 private final Set <GraphQLType > removedTypes ;
157161
162+ private final Set <GraphQLFieldDefinition > fieldDefinitionsToActuallyRemove = new LinkedHashSet <>();
163+
158164 private FieldRemovalVisitor (VisibleFieldPredicate visibilityPredicate ,
159165 Set <GraphQLType > removedTypes ) {
160166 this .visibilityPredicate = visibilityPredicate ;
161167 this .removedTypes = removedTypes ;
162168 }
163169
170+ @ Override
171+ public TraversalControl visitGraphQLObjectType (GraphQLObjectType objectType , TraverserContext <GraphQLSchemaElement > context ) {
172+ return visitFieldsContainer (objectType , context );
173+ }
174+
175+ @ Override
176+ public TraversalControl visitGraphQLInterfaceType (GraphQLInterfaceType objectType , TraverserContext <GraphQLSchemaElement > context ) {
177+ return visitFieldsContainer (objectType , context );
178+ }
179+
180+ private TraversalControl visitFieldsContainer (GraphQLFieldsContainer fieldsContainer , TraverserContext <GraphQLSchemaElement > context ) {
181+ boolean allFieldsDeleted = true ;
182+ for (GraphQLFieldDefinition fieldDefinition : fieldsContainer .getFieldDefinitions ()) {
183+ VisibleFieldPredicateEnvironment environment = new VisibleFieldPredicateEnvironmentImpl (
184+ fieldDefinition , fieldsContainer );
185+ if (!visibilityPredicate .isVisible (environment )) {
186+ fieldDefinitionsToActuallyRemove .add (fieldDefinition );
187+ removedTypes .add (fieldDefinition .getType ());
188+ } else {
189+ allFieldsDeleted = false ;
190+ }
191+ }
192+ if (allFieldsDeleted ) {
193+ // we are deleting the whole interface type because all fields are supposed to be deleted
194+ return deleteNode (context );
195+ } else {
196+ return TraversalControl .CONTINUE ;
197+ }
198+ }
199+
200+
164201 @ Override
165202 public TraversalControl visitGraphQLFieldDefinition (GraphQLFieldDefinition definition ,
166203 TraverserContext <GraphQLSchemaElement > context ) {
167- return visitField (definition , context );
204+ if (fieldDefinitionsToActuallyRemove .contains (definition )) {
205+ return deleteNode (context );
206+ } else {
207+ return TraversalControl .CONTINUE ;
208+ }
168209 }
169210
170211 @ Override
@@ -216,12 +257,12 @@ public TraversalControl visitGraphQLInterfaceType(GraphQLInterfaceType node,
216257 public TraversalControl visitGraphQLType (GraphQLSchemaElement node ,
217258 TraverserContext <GraphQLSchemaElement > context ) {
218259 if (observedBeforeTransform .contains (node ) &&
219- !observedAfterTransform .contains (node ) &&
220- (node instanceof GraphQLObjectType ||
221- node instanceof GraphQLEnumType ||
222- node instanceof GraphQLInputObjectType ||
223- node instanceof GraphQLInterfaceType ||
224- node instanceof GraphQLUnionType )) {
260+ !observedAfterTransform .contains (node ) &&
261+ (node instanceof GraphQLObjectType ||
262+ node instanceof GraphQLEnumType ||
263+ node instanceof GraphQLInputObjectType ||
264+ node instanceof GraphQLInterfaceType ||
265+ node instanceof GraphQLUnionType )) {
225266
226267 return deleteNode (context );
227268 }
0 commit comments