2121import java .util .Iterator ;
2222import java .util .List ;
2323import java .util .function .Function ;
24- import java .util .stream .Collectors ;
2524
2625import graphql .schema .DataFetchingFieldSelectionSet ;
2726import graphql .schema .SelectedField ;
2827
2928import org .springframework .data .mapping .PropertyPath ;
3029import org .springframework .data .util .TypeInformation ;
30+ import org .springframework .util .CollectionUtils ;
3131
3232/**
3333 * Utility to compute {@link PropertyPath property paths} from
@@ -46,90 +46,60 @@ class PropertySelection {
4646
4747 private final List <PropertyPath > propertyPaths ;
4848
49+
4950 private PropertySelection (List <PropertyPath > propertyPaths ) {
5051 this .propertyPaths = propertyPaths ;
5152 }
5253
54+
55+ /**
56+ * @return the property paths as list.
57+ */
58+ public List <String > toList () {
59+ return this .propertyPaths .stream ().map (PropertyPath ::toDotPath ).toList ();
60+ }
61+
62+
5363 /**
5464 * Create a property selection for the given {@link TypeInformation type} and
5565 * {@link DataFetchingFieldSelectionSet}.
5666 *
57- * @param typeInformation the type to inspect
67+ * @param typeInfo the type to inspect
5868 * @param selectionSet the field selection to apply
5969 * @return a property selection holding all selectable property paths.
6070 */
61- public static PropertySelection create (TypeInformation <?> typeInformation ,
62- DataFetchingFieldSelectionSet selectionSet ) {
63- return create (typeInformation , new DataFetchingFieldSelection (selectionSet ));
71+ public static PropertySelection create (TypeInformation <?> typeInfo , DataFetchingFieldSelectionSet selectionSet ) {
72+ FieldSelection selection = new DataFetchingFieldSelection (selectionSet );
73+ List <PropertyPath > paths = getPropertyPaths (typeInfo , selection , path -> PropertyPath .from (path , typeInfo ));
74+ return new PropertySelection (paths );
6475 }
6576
66- private static PropertySelection create (TypeInformation <?> typeInformation , FieldSelection selection ) {
67- List <PropertyPath > propertyPaths = collectPropertyPaths (typeInformation ,
68- selection ,
69- path -> PropertyPath .from (path , typeInformation ));
70- return new PropertySelection (propertyPaths );
71- }
77+ private static List <PropertyPath > getPropertyPaths (
78+ TypeInformation <?> typeInfo , FieldSelection selection , Function <String , PropertyPath > pathFactory ) {
7279
73- private static List <PropertyPath > collectPropertyPaths (TypeInformation <?> typeInformation ,
74- FieldSelection selection , Function <String , PropertyPath > propertyPathFactory ) {
75- List <PropertyPath > propertyPaths = new ArrayList <>();
80+ List <PropertyPath > result = new ArrayList <>();
7681
7782 for (SelectedField selectedField : selection ) {
78-
7983 String propertyName = selectedField .getName ();
80- TypeInformation <?> property = typeInformation .getProperty (propertyName );
81-
82- if (property == null ) {
84+ TypeInformation <?> propertyTypeInfo = typeInfo .getProperty (propertyName );
85+ if (propertyTypeInfo == null ) {
8386 continue ;
8487 }
8588
86- PropertyPath propertyPath = propertyPathFactory .apply (propertyName );
87- FieldSelection nestedSelection = selection .select (selectedField );
88-
89- List <PropertyPath > pathsToAdd = Collections .singletonList (propertyPath );
90-
91- if (!nestedSelection .isEmpty () && property .getActualType () != null ) {
92- List <PropertyPath > nestedPaths = collectPropertyPaths (property .getRequiredActualType (),
93- nestedSelection , propertyPath ::nested );
89+ PropertyPath propertyPath = pathFactory .apply (propertyName );
9490
95- if (!nestedPaths .isEmpty ()) {
96- pathsToAdd = nestedPaths ;
97- }
91+ List <PropertyPath > nestedPaths = null ;
92+ FieldSelection nestedSelection = selection .select (selectedField );
93+ if (!nestedSelection .isEmpty () && propertyTypeInfo .getActualType () != null ) {
94+ TypeInformation <?> actualType = propertyTypeInfo .getRequiredActualType ();
95+ nestedPaths = getPropertyPaths (actualType , nestedSelection , propertyPath ::nested );
9896 }
9997
100- propertyPaths .addAll (pathsToAdd );
101- }
102-
103- return propertyPaths ;
104- }
105-
106- /**
107- * @return the property paths as list.
108- */
109- public List <String > toList () {
110- return this .propertyPaths .stream ().map (PropertyPath ::toDotPath ).collect (Collectors .toList ());
111- }
112-
113-
114- enum EmptyFieldSelection implements FieldSelection {
115-
116- INSTANCE ;
117-
118- @ Override
119- public boolean isEmpty () {
120- return true ;
121- }
122-
123- @ Override
124- public FieldSelection select (SelectedField field ) {
125- return INSTANCE ;
126- }
127-
128- @ Override
129- public Iterator <SelectedField > iterator () {
130- return Collections .emptyIterator ();
98+ result .addAll (CollectionUtils .isEmpty (nestedPaths ) ?
99+ Collections .singletonList (propertyPath ) : nestedPaths );
131100 }
132101
102+ return result ;
133103 }
134104
135105
@@ -155,7 +125,7 @@ interface FieldSelection extends Iterable<SelectedField> {
155125 }
156126
157127
158- static class DataFetchingFieldSelection implements FieldSelection {
128+ private static class DataFetchingFieldSelection implements FieldSelection {
159129
160130 private final List <SelectedField > selectedFields ;
161131
@@ -166,8 +136,7 @@ static class DataFetchingFieldSelection implements FieldSelection {
166136 this .allFields = selectionSet .getFields ();
167137 }
168138
169- private DataFetchingFieldSelection (List <SelectedField > selectedFields ,
170- List <SelectedField > allFields ) {
139+ private DataFetchingFieldSelection (List <SelectedField > selectedFields , List <SelectedField > allFields ) {
171140 this .selectedFields = selectedFields ;
172141 this .allFields = allFields ;
173142 }
@@ -179,16 +148,18 @@ public boolean isEmpty() {
179148
180149 @ Override
181150 public FieldSelection select (SelectedField field ) {
182- List <SelectedField > selectedFields = new ArrayList <>() ;
151+ List <SelectedField > selectedFields = null ;
183152
184- for (SelectedField selectedField : allFields ) {
153+ for (SelectedField selectedField : this . allFields ) {
185154 if (field .equals (selectedField .getParentField ())) {
155+ selectedFields = (selectedFields != null ? selectedFields : new ArrayList <>());
186156 selectedFields .add (selectedField );
187157 }
188158 }
189159
190- return (selectedFields .isEmpty () ? EmptyFieldSelection .INSTANCE
191- : new DataFetchingFieldSelection (selectedFields , allFields ));
160+ return (selectedFields != null ?
161+ new DataFetchingFieldSelection (selectedFields , this .allFields ) :
162+ EmptyFieldSelection .INSTANCE );
192163 }
193164
194165 @ Override
@@ -198,4 +169,26 @@ public Iterator<SelectedField> iterator() {
198169
199170 }
200171
172+
173+ enum EmptyFieldSelection implements FieldSelection {
174+
175+ INSTANCE ;
176+
177+ @ Override
178+ public boolean isEmpty () {
179+ return true ;
180+ }
181+
182+ @ Override
183+ public FieldSelection select (SelectedField field ) {
184+ return INSTANCE ;
185+ }
186+
187+ @ Override
188+ public Iterator <SelectedField > iterator () {
189+ return Collections .emptyIterator ();
190+ }
191+
192+ }
193+
201194}
0 commit comments