net.morimekta.providence.graphql.gql.GQLSelection Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of providence-graphql Show documentation
Show all versions of providence-graphql Show documentation
Providence Core extension for GraphQL.
package net.morimekta.providence.graphql.gql;
import net.morimekta.providence.descriptor.PField;
import net.morimekta.util.collect.UnmodifiableList;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* When defining a graphql each point in a selection set is called a
* 'selection'. A selection may be a field or a fragment, each having
* a distinct definition and uses.
*
* Most selections can be recursive, i.e. containing a selection set
* of it's own. The selection set is ordered, therefore it is returned
* as a list, not a set.
*/
public interface GQLSelection {
/**
* @return List if selections contained within this selection.
*/
@Nullable
List getSelectionSet();
/**
* Check if any of the given fields are in the selection.
* It will only look the the current struct, but check in all contained
* and referenced fragments. If only one field is given, this method
* will return true if and only if {@link #getSelection(PField)} returns
* a non-empty list.
*
* @param fields Fields to check selection for.
* @return True only if the current selection set contains ony
* of the provided fields.
*/
default boolean hasSelection(@Nonnull PField... fields) {
// Everything requested.
if (getSelectionSet() == null) return true;
if (fields.length == 0) return false;
for (GQLSelection sel : getSelectionSet()) {
if (sel instanceof GQLField) {
GQLField sf = (GQLField) sel;
for (PField field : fields) {
if (sf.getField() == field) {
return true;
}
}
} else if (sel instanceof GQLFragment) {
GQLFragment fragment = (GQLFragment) sel;
if (fragment.hasSelection(fields)) {
return true;
}
}
}
return false;
}
/**
* Get all selection entries related to the given field. It will
* only look at the current struct, but look at all levels of
* fragments.
*
* The result will contain one entry for each time the field is
* requested, so if multiple fragments requests the same field, this
* will return one entry per reference. If it contains more than one,
* the query should only have one such without alias, and all
* others should use unique aliases, but is not required.
*
* This method will return a non-empty list if and only if
* {@link #hasSelection(PField[])} called with the same field returns
* true.
*
* @param field The field to get selection for.
* @return List of selection related to the field.
*/
@Nonnull
default List getSelection(@Nonnull PField field) {
if (getSelectionSet() == null) return UnmodifiableList.listOf();
List selection = new ArrayList<>();
for (GQLSelection sel : getSelectionSet()) {
if (sel instanceof GQLField) {
GQLField sf = (GQLField) sel;
if (field.equals(sf.getField())) {
selection.add(sf);
}
} else if (sel instanceof GQLFragment) {
GQLFragment fragment = (GQLFragment) sel;
selection.addAll(fragment.getSelection(field));
}
}
return UnmodifiableList.copyOf(selection);
}
}