Skip to content

Commit

Permalink
Polishing in PropertySelection
Browse files Browse the repository at this point in the history
See gh-723
  • Loading branch information
rstoyanchev committed Jun 20, 2023
1 parent 1406ca2 commit 6e1e9b7
Showing 1 changed file with 60 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
import java.util.Iterator;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

import graphql.schema.DataFetchingFieldSelectionSet;
import graphql.schema.SelectedField;

import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.CollectionUtils;

/**
* Utility to compute {@link PropertyPath property paths} from
Expand All @@ -46,90 +46,60 @@ class PropertySelection {

private final List<PropertyPath> propertyPaths;


private PropertySelection(List<PropertyPath> propertyPaths) {
this.propertyPaths = propertyPaths;
}


/**
* @return the property paths as list.
*/
public List<String> toList() {
return this.propertyPaths.stream().map(PropertyPath::toDotPath).toList();
}


/**
* Create a property selection for the given {@link TypeInformation type} and
* {@link DataFetchingFieldSelectionSet}.
*
* @param typeInformation the type to inspect
* @param typeInfo the type to inspect
* @param selectionSet the field selection to apply
* @return a property selection holding all selectable property paths.
*/
public static PropertySelection create(TypeInformation<?> typeInformation,
DataFetchingFieldSelectionSet selectionSet) {
return create(typeInformation, new DataFetchingFieldSelection(selectionSet));
public static PropertySelection create(TypeInformation<?> typeInfo, DataFetchingFieldSelectionSet selectionSet) {
FieldSelection selection = new DataFetchingFieldSelection(selectionSet);
List<PropertyPath> paths = getPropertyPaths(typeInfo, selection, path -> PropertyPath.from(path, typeInfo));
return new PropertySelection(paths);
}

private static PropertySelection create(TypeInformation<?> typeInformation, FieldSelection selection) {
List<PropertyPath> propertyPaths = collectPropertyPaths(typeInformation,
selection,
path -> PropertyPath.from(path, typeInformation));
return new PropertySelection(propertyPaths);
}
private static List<PropertyPath> getPropertyPaths(
TypeInformation<?> typeInfo, FieldSelection selection, Function<String, PropertyPath> pathFactory) {

private static List<PropertyPath> collectPropertyPaths(TypeInformation<?> typeInformation,
FieldSelection selection, Function<String, PropertyPath> propertyPathFactory) {
List<PropertyPath> propertyPaths = new ArrayList<>();
List<PropertyPath> result = new ArrayList<>();

for (SelectedField selectedField : selection) {

String propertyName = selectedField.getName();
TypeInformation<?> property = typeInformation.getProperty(propertyName);

if (property == null) {
TypeInformation<?> propertyTypeInfo = typeInfo.getProperty(propertyName);
if (propertyTypeInfo == null) {
continue;
}

PropertyPath propertyPath = propertyPathFactory.apply(propertyName);
FieldSelection nestedSelection = selection.select(selectedField);

List<PropertyPath> pathsToAdd = Collections.singletonList(propertyPath);

if (!nestedSelection.isEmpty() && property.getActualType() != null) {
List<PropertyPath> nestedPaths = collectPropertyPaths(property.getRequiredActualType(),
nestedSelection, propertyPath::nested);
PropertyPath propertyPath = pathFactory.apply(propertyName);

if (!nestedPaths.isEmpty()) {
pathsToAdd = nestedPaths;
}
List<PropertyPath> nestedPaths = null;
FieldSelection nestedSelection = selection.select(selectedField);
if (!nestedSelection.isEmpty() && propertyTypeInfo.getActualType() != null) {
TypeInformation<?> actualType = propertyTypeInfo.getRequiredActualType();
nestedPaths = getPropertyPaths(actualType, nestedSelection, propertyPath::nested);
}

propertyPaths.addAll(pathsToAdd);
}

return propertyPaths;
}

/**
* @return the property paths as list.
*/
public List<String> toList() {
return this.propertyPaths.stream().map(PropertyPath::toDotPath).collect(Collectors.toList());
}


enum EmptyFieldSelection implements FieldSelection {

INSTANCE;

@Override
public boolean isEmpty() {
return true;
}

@Override
public FieldSelection select(SelectedField field) {
return INSTANCE;
}

@Override
public Iterator<SelectedField> iterator() {
return Collections.emptyIterator();
result.addAll(CollectionUtils.isEmpty(nestedPaths) ?
Collections.singletonList(propertyPath) : nestedPaths);
}

return result;
}


Expand All @@ -155,7 +125,7 @@ interface FieldSelection extends Iterable<SelectedField> {
}


static class DataFetchingFieldSelection implements FieldSelection {
private static class DataFetchingFieldSelection implements FieldSelection {

private final List<SelectedField> selectedFields;

Expand All @@ -166,8 +136,7 @@ static class DataFetchingFieldSelection implements FieldSelection {
this.allFields = selectionSet.getFields();
}

private DataFetchingFieldSelection(List<SelectedField> selectedFields,
List<SelectedField> allFields) {
private DataFetchingFieldSelection(List<SelectedField> selectedFields, List<SelectedField> allFields) {
this.selectedFields = selectedFields;
this.allFields = allFields;
}
Expand All @@ -179,16 +148,18 @@ public boolean isEmpty() {

@Override
public FieldSelection select(SelectedField field) {
List<SelectedField> selectedFields = new ArrayList<>();
List<SelectedField> selectedFields = null;

for (SelectedField selectedField : allFields) {
for (SelectedField selectedField : this.allFields) {
if (field.equals(selectedField.getParentField())) {
selectedFields = (selectedFields != null ? selectedFields : new ArrayList<>());
selectedFields.add(selectedField);
}
}

return (selectedFields.isEmpty() ? EmptyFieldSelection.INSTANCE
: new DataFetchingFieldSelection(selectedFields, allFields));
return (selectedFields != null ?
new DataFetchingFieldSelection(selectedFields, this.allFields) :
EmptyFieldSelection.INSTANCE);
}

@Override
Expand All @@ -198,4 +169,26 @@ public Iterator<SelectedField> iterator() {

}


enum EmptyFieldSelection implements FieldSelection {

INSTANCE;

@Override
public boolean isEmpty() {
return true;
}

@Override
public FieldSelection select(SelectedField field) {
return INSTANCE;
}

@Override
public Iterator<SelectedField> iterator() {
return Collections.emptyIterator();
}

}

}

0 comments on commit 6e1e9b7

Please sign in to comment.