diff --git a/gradle.properties b/gradle.properties index d1dd387..9db94c2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,7 +22,7 @@ hibernatePluginVersion=6.6.0.Final quarkusVersion=3.15.1 junitVersion=5.11.0 jmhVersion=1.37 -guavaVersion=33.3.0-jre +guavaVersion=33.3.1-jre slf4jVersion=2.1.0-alpha1 jandexVersion=3.2.2 hibernateVersion=6.6.0.Final diff --git a/gradle/bom.gradle b/gradle/bom.gradle index 9aae2d5..74b04a1 100755 --- a/gradle/bom.gradle +++ b/gradle/bom.gradle @@ -1,7 +1,7 @@ configurations.all { -// collect { configuration -> -// configuration.exclude group: 'junit', module: 'junit' -// } + collect { configuration -> + configuration.exclude group: 'com.google.code.findbugs', module: 'jsr305' + } resolutionStrategy { force "com.fasterxml.jackson.core:jackson-annotations:${jacksonVersion}" force "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}" diff --git a/graphql/build.gradle b/graphql/build.gradle index 46fb579..e23dfee 100644 --- a/graphql/build.gradle +++ b/graphql/build.gradle @@ -1,7 +1,5 @@ dependencies { - api project(":panache") - api "com.google.guava:guava:${guavaVersion}" + api project(":jakarta-data") api "com.graphql-java:graphql-java:${graphqlJavaVersion}" - api "jakarta.validation:jakarta.validation-api:${jakartaValidationApiVersion}" api "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}" } diff --git a/graphql/src/main/java/com/qwlabs/graphql/Gql.java b/graphql/src/main/java/com/qwlabs/graphql/Gql.java index a221acd..c114411 100644 --- a/graphql/src/main/java/com/qwlabs/graphql/Gql.java +++ b/graphql/src/main/java/com/qwlabs/graphql/Gql.java @@ -2,13 +2,12 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.qwlabs.lang.F2; import jakarta.validation.constraints.NotNull; import lombok.extern.slf4j.Slf4j; import java.util.LinkedHashMap; import java.util.Map; -import java.util.Optional; +import java.util.Objects; @Slf4j public class Gql { @@ -43,11 +42,13 @@ public Gql input(Object input) { public String build() { Map result = new LinkedHashMap<>(); - F2.ifPresent(operationName, name -> { - result.put("operationName", name); - }); + if (Objects.nonNull(operationName)) { + result.put("operationName", operationName); + } result.put("query", query); - Optional.ofNullable(variables).ifPresent(vars -> result.put("variables", variables)); + if (Objects.nonNull(variables)) { + result.put("variables", variables); + } try { return initObjectMapper().writeValueAsString(result); } catch (JsonProcessingException e) { diff --git a/graphql/src/main/java/com/qwlabs/graphql/Relays.java b/graphql/src/main/java/com/qwlabs/graphql/Relays.java new file mode 100644 index 0000000..fe7d1eb --- /dev/null +++ b/graphql/src/main/java/com/qwlabs/graphql/Relays.java @@ -0,0 +1,63 @@ +package com.qwlabs.graphql; + +import com.qwlabs.jakarta.data.Pages; +import graphql.relay.Connection; +import graphql.relay.ConnectionCursor; +import graphql.relay.DefaultConnection; +import graphql.relay.DefaultConnectionCursor; +import graphql.relay.DefaultEdge; +import graphql.relay.DefaultPageInfo; +import graphql.relay.Edge; +import graphql.relay.PageInfo; +import jakarta.annotation.Nullable; +import jakarta.data.page.Page; +import jakarta.validation.constraints.NotNull; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; + +public class Relays { + + public static Connection

of(@NotNull Page page, @Nullable Function mapper) { + if (Objects.isNull(mapper)) { + return (Connection

) of(page); + } + return of(Pages.map(page, mapper)); + } + + public static

Connection

of(@NotNull Page

page) { + Objects.requireNonNull(page, "page can not be null."); + List> edges = buildEdges(page); + PageInfo pageInfo = buildPageInfo(page, edges); + return new DefaultConnection<>(edges, pageInfo); + } + + private static

PageInfo buildPageInfo(Page

page, List> edges) { + ConnectionCursor startCursor = null; + ConnectionCursor endCursor = null; + if (!edges.isEmpty()) { + startCursor = edges.get(0).getCursor(); + endCursor = edges.get(edges.size() - 1).getCursor(); + } + return new DefaultPageInfo( + startCursor, + endCursor, + page.hasPrevious(), + page.hasNext() + ); + } + + private static

List> buildEdges(Page

page) { + long startAt = (page.pageRequest().page() - 1) * page.pageRequest().size(); + List> edges = new ArrayList<>(page.numberOfElements()); + Iterator

iterator = page.content().iterator(); + while (iterator.hasNext()) { + P node = iterator.next(); + edges.add(new DefaultEdge<>(node, new DefaultConnectionCursor(String.valueOf(startAt++)))); + } + return edges; + } +} diff --git a/graphql/src/main/java/com/qwlabs/graphql/relay/Connection.java b/graphql/src/main/java/com/qwlabs/graphql/relay/Connection.java deleted file mode 100644 index 3c5b61b..0000000 --- a/graphql/src/main/java/com/qwlabs/graphql/relay/Connection.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.qwlabs.graphql.relay; - -import com.google.common.collect.ImmutableList; -import graphql.PublicApi; -import jakarta.validation.constraints.NotNull; - -import java.util.List; - -import static graphql.Assert.assertNotNull; - -@PublicApi -public class Connection { - @NotNull - private final ImmutableList<@NotNull Edge> edges; - @NotNull - private final PageInfo pageInfo; - @NotNull - private final Long totalCount; - - public Connection(List> edges, PageInfo pageInfo, Long totalCount) { - this.edges = ImmutableList.copyOf(assertNotNull(edges, () -> "edges cannot be null")); - this.pageInfo = assertNotNull(pageInfo, () -> "page info cannot be null"); - this.totalCount = assertNotNull(totalCount, () -> "total count cannot be null"); - } - - public List> getEdges() { - return edges; - } - - public PageInfo getPageInfo() { - return pageInfo; - } - - public Long getTotalCount() { - return totalCount; - } -} diff --git a/graphql/src/main/java/com/qwlabs/graphql/relay/Edge.java b/graphql/src/main/java/com/qwlabs/graphql/relay/Edge.java deleted file mode 100644 index bb58b2f..0000000 --- a/graphql/src/main/java/com/qwlabs/graphql/relay/Edge.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.qwlabs.graphql.relay; - -import graphql.PublicApi; -import jakarta.validation.constraints.NotNull; - -import static graphql.Assert.assertNotNull; - -@PublicApi -public class Edge { - @NotNull - private final T node; - @NotNull - private final String cursor; - - public Edge(T node, String cursor) { - this.cursor = assertNotNull(cursor, () -> "cursor cannot be null"); - this.node = assertNotNull(node, () -> "node can not be null"); - } - - public T getNode() { - return node; - } - - public String getCursor() { - return cursor; - } -} diff --git a/graphql/src/main/java/com/qwlabs/graphql/relay/InvalidCursorException.java b/graphql/src/main/java/com/qwlabs/graphql/relay/InvalidCursorException.java deleted file mode 100644 index a328a4a..0000000 --- a/graphql/src/main/java/com/qwlabs/graphql/relay/InvalidCursorException.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.qwlabs.graphql.relay; - -import graphql.ErrorType; -import graphql.GraphQLError; -import graphql.GraphqlErrorHelper; -import graphql.Internal; -import graphql.language.SourceLocation; - -import java.util.List; - -import static graphql.ErrorType.DataFetchingException; - -@Internal -public class InvalidCursorException extends RuntimeException implements GraphQLError { - - InvalidCursorException(String message) { - this(message, null); - } - - InvalidCursorException(String message, Throwable cause) { - super(message, cause); - } - - @Override - public List getLocations() { - return null; - } - - @Override - public ErrorType getErrorType() { - return DataFetchingException; - } - - @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") - @Override - public boolean equals(Object o) { - return GraphqlErrorHelper.equals(this, o); - } - - @Override - public int hashCode() { - return GraphqlErrorHelper.hashCode(this); - } - -} diff --git a/graphql/src/main/java/com/qwlabs/graphql/relay/InvalidPageSizeException.java b/graphql/src/main/java/com/qwlabs/graphql/relay/InvalidPageSizeException.java deleted file mode 100644 index 743c226..0000000 --- a/graphql/src/main/java/com/qwlabs/graphql/relay/InvalidPageSizeException.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.qwlabs.graphql.relay; - -import graphql.ErrorType; -import graphql.GraphQLError; -import graphql.GraphqlErrorHelper; -import graphql.Internal; -import graphql.language.SourceLocation; - -import java.util.List; - -import static graphql.ErrorType.DataFetchingException; - -@Internal -public class InvalidPageSizeException extends RuntimeException implements GraphQLError { - - InvalidPageSizeException(String message) { - this(message, null); - } - - InvalidPageSizeException(String message, Throwable cause) { - super(message, cause); - } - - @Override - public List getLocations() { - return null; - } - - @Override - public ErrorType getErrorType() { - return DataFetchingException; - } - - @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") - @Override - public boolean equals(Object o) { - return GraphqlErrorHelper.equals(this, o); - } - - @Override - public int hashCode() { - return GraphqlErrorHelper.hashCode(this); - } - -} diff --git a/graphql/src/main/java/com/qwlabs/graphql/relay/PageInfo.java b/graphql/src/main/java/com/qwlabs/graphql/relay/PageInfo.java deleted file mode 100644 index a0b8c72..0000000 --- a/graphql/src/main/java/com/qwlabs/graphql/relay/PageInfo.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.qwlabs.graphql.relay; - - -import graphql.PublicApi; -import jakarta.validation.constraints.NotNull; - -@PublicApi -public class PageInfo { - @NotNull - private final String startCursor; - @NotNull - private final String endCursor; - @NotNull - private final boolean hasPreviousPage; - @NotNull - private final boolean hasNextPage; - - public PageInfo(String startCursor, String endCursor, - boolean hasPreviousPage, boolean hasNextPage) { - this.startCursor = startCursor; - this.endCursor = endCursor; - this.hasPreviousPage = hasPreviousPage; - this.hasNextPage = hasNextPage; - } - - public String getStartCursor() { - return startCursor; - } - - public String getEndCursor() { - return endCursor; - } - - public boolean isHasPreviousPage() { - return hasPreviousPage; - } - - public boolean isHasNextPage() { - return hasNextPage; - } -} diff --git a/graphql/src/main/java/com/qwlabs/graphql/relay/Relays.java b/graphql/src/main/java/com/qwlabs/graphql/relay/Relays.java deleted file mode 100644 index cce0d1b..0000000 --- a/graphql/src/main/java/com/qwlabs/graphql/relay/Relays.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.qwlabs.graphql.relay; - -import com.google.common.primitives.Ints; -import com.qwlabs.panache.Ranged; -import io.quarkus.panache.common.Range; -import io.smallrye.common.constraint.Nullable; -import jakarta.validation.constraints.NotNull; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.function.Function; - -public final class Relays { - private static final Connection EMPTY = createEmptyConnection(); - - private Relays() { - } - - public static Connection of(@NotNull Ranged ranged) { - return of(ranged, null); - } - - public static Connection of(@NotNull Ranged ranged, - @Nullable Function mapper) { - Objects.requireNonNull(ranged, "paged can not be null."); - if (ranged.getTotalCount() == 0) { - return (Connection) EMPTY; - } - Ranged resultRanged = ranged.map(mapper); - List> edges = buildEdges(resultRanged); - PageInfo pageInfo = buildPageInfo(resultRanged, edges); - return new Connection<>(edges, pageInfo, resultRanged.getTotalCount()); - } - - public static Range of(String after, Integer first) { - if (first <= 0) { - throw new InvalidPageSizeException("first can not be less than 1"); - } - int startIndex = Optional.ofNullable(Ints.tryParse(after)).orElse(0); - int lastIndex = startIndex + first - 1; - return Range.of(startIndex, lastIndex); - } - - private static PageInfo buildPageInfo(Ranged ranged, List> edges) { - String firstCursor = null; - String lastCursor = null; - if (!edges.isEmpty()) { - firstCursor = edges.get(0).getCursor(); - lastCursor = edges.get(edges.size() - 1).getCursor(); - } - return new PageInfo( - firstCursor, - lastCursor, - ranged.hasPreviousPage(), - ranged.hasNextPage() - ); - } - - - private static List> buildEdges(Ranged ranged) { - Range range = ranged.getRange(); - List> edges = new ArrayList<>(); - int cursorIndex = range.getStartIndex() + 1; - Iterator iterator = ranged.getData().iterator(); - while (iterator.hasNext()) { - T node = iterator.next(); - edges.add(new Edge<>(node, String.valueOf(cursorIndex++))); - } - return edges; - } - - private static Connection createEmptyConnection() { - PageInfo pageInfo = new PageInfo("0", "0", false, false); - return new Connection<>(Collections.emptyList(), pageInfo, 0L); - } - -} diff --git a/graphql/src/test/java/.gitkeep b/graphql/src/test/java/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/jakarta-data/build.gradle b/jakarta-data/build.gradle index 485b773..ccb4a0d 100644 --- a/jakarta-data/build.gradle +++ b/jakarta-data/build.gradle @@ -1,4 +1,6 @@ dependencies { api "com.google.guava:guava:${guavaVersion}" api "jakarta.data:jakarta.data-api:${jakartaDataApiVersion}" + api "jakarta.validation:jakarta.validation-api:${jakartaValidationApiVersion}" + api "jakarta.annotation:jakarta.annotation-api:${jakartaAnnotationApiVersion}" } diff --git a/jakarta-data/src/main/java/com/qwlabs/jakarta/data/Limits.java b/jakarta-data/src/main/java/com/qwlabs/jakarta/data/Limits.java index 6d74e9d..ebde9b9 100644 --- a/jakarta-data/src/main/java/com/qwlabs/jakarta/data/Limits.java +++ b/jakarta-data/src/main/java/com/qwlabs/jakarta/data/Limits.java @@ -1,16 +1,18 @@ package com.qwlabs.jakarta.data; import com.google.common.primitives.Longs; +import jakarta.annotation.Nullable; import jakarta.data.Limit; +import jakarta.validation.constraints.NotNull; import java.util.Optional; public interface Limits { - static Limit of(String after, Integer first) { + static Limit of(@Nullable String after, @NotNull int first) { if (first <= 0) { throw new IllegalArgumentException("first can not be less than 1"); } - long startAt = Optional.ofNullable(Longs.tryParse(after)).orElse(1L); + var startAt = Optional.ofNullable(after).map(Longs::tryParse).orElse(1L); return new Limit(first, startAt); } } diff --git a/jakarta-data/src/main/java/com/qwlabs/jakarta/data/PageRequests.java b/jakarta-data/src/main/java/com/qwlabs/jakarta/data/PageRequests.java index 69c1b94..097b83c 100644 --- a/jakarta-data/src/main/java/com/qwlabs/jakarta/data/PageRequests.java +++ b/jakarta-data/src/main/java/com/qwlabs/jakarta/data/PageRequests.java @@ -1,6 +1,7 @@ package com.qwlabs.jakarta.data; import com.google.common.primitives.Longs; +import jakarta.annotation.Nullable; import jakarta.data.page.PageRequest; import java.util.Optional; @@ -11,7 +12,7 @@ static PageRequest of(int first) { return of(null, first); } - static PageRequest of(String after, int first) { + static PageRequest of(@Nullable String after, int first) { if (first <= 0) { throw new IllegalArgumentException("first can not be less than 1"); } diff --git a/jakarta-data/src/main/java/com/qwlabs/jakarta/data/Pages.java b/jakarta-data/src/main/java/com/qwlabs/jakarta/data/Pages.java index ec41e7d..a092945 100644 --- a/jakarta-data/src/main/java/com/qwlabs/jakarta/data/Pages.java +++ b/jakarta-data/src/main/java/com/qwlabs/jakarta/data/Pages.java @@ -2,12 +2,13 @@ import jakarta.data.page.Page; import jakarta.data.page.impl.PageRecord; +import jakarta.validation.constraints.NotNull; import java.util.List; import java.util.function.Function; public interface Pages { - static Page map(Page page, Function mapper) { + static Page map(@NotNull Page page, @NotNull Function mapper) { List content = page.stream().map(mapper).toList(); return new PageRecord<>(page.pageRequest(), content, page.totalElements()); }