graphql.relay.SimpleListConnection Maven / Gradle / Ivy
The newest version!
package graphql.relay;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static java.util.Base64.getDecoder;
import static java.util.Base64.getEncoder;
public class SimpleListConnection implements DataFetcher> {
private static final String DUMMY_CURSOR_PREFIX = "simple-cursor";
private final String prefix;
private final List data;
public SimpleListConnection(List data, String prefix) {
if (prefix == null || prefix.length() == 0) {
throw new IllegalArgumentException("prefix cannot be null or empty");
}
this.prefix = prefix;
this.data = data;
}
public SimpleListConnection(List data) {
this(data, DUMMY_CURSOR_PREFIX);
}
private List> buildEdges() {
List> edges = new ArrayList<>();
int ix = 0;
for (T object : data) {
edges.add(new DefaultEdge<>(object, new DefaultConnectionCursor(createCursor(ix++))));
}
return edges;
}
@Override
public Connection get(DataFetchingEnvironment environment) {
List> edges = buildEdges();
int afterOffset = getOffsetFromCursor(environment.getArgument("after"), -1);
int begin = Math.max(afterOffset, -1) + 1;
int beforeOffset = getOffsetFromCursor(environment.getArgument("before"), edges.size());
int end = Math.min(beforeOffset, edges.size());
edges = edges.subList(begin, end);
if (edges.size() == 0) {
return emptyConnection();
}
Integer first = environment.getArgument("first");
Integer last = environment.getArgument("last");
ConnectionCursor firstPresliceCursor = edges.get(0).getCursor();
ConnectionCursor lastPresliceCursor = edges.get(edges.size() - 1).getCursor();
if (first != null) {
edges = edges.subList(0, first <= edges.size() ? first : edges.size());
}
if (last != null) {
edges = edges.subList(last > edges.size() ? 0 : edges.size() - last, edges.size());
}
if (edges.isEmpty()) {
return emptyConnection();
}
Edge firstEdge = edges.get(0);
Edge lastEdge = edges.get(edges.size() - 1);
PageInfo pageInfo = new DefaultPageInfo(
firstEdge.getCursor(),
lastEdge.getCursor(),
!firstEdge.getCursor().equals(firstPresliceCursor),
!lastEdge.getCursor().equals(lastPresliceCursor)
);
return new DefaultConnection<>(
edges,
pageInfo
);
}
private Connection emptyConnection() {
PageInfo pageInfo = new DefaultPageInfo(null, null, false, false);
return new DefaultConnection<>(Collections.emptyList(), pageInfo);
}
/**
* find the object's cursor, or null if the object is not in this connection.
* @param object the object in play
* @return a connection cursor
*/
public ConnectionCursor cursorForObjectInConnection(T object) {
int index = data.indexOf(object);
if (index == -1) {
return null;
}
String cursor = createCursor(index);
return new DefaultConnectionCursor(cursor);
}
private int getOffsetFromCursor(String cursor, int defaultValue) {
if (cursor == null) {
return defaultValue;
}
String string = new String(getDecoder().decode(cursor), StandardCharsets.UTF_8);
return Integer.parseInt(string.substring(prefix.length()));
}
private String createCursor(int offset) {
byte[] bytes = (prefix + Integer.toString(offset)).getBytes(StandardCharsets.UTF_8);
return getEncoder().encodeToString(bytes);
}
}