Skip to content

Commit

Permalink
Add all cursors to the page implementation and remove nextPageable an…
Browse files Browse the repository at this point in the history
…d previousPageable implementation from the CursoredPageable
  • Loading branch information
andriy-dmytruk committed Apr 18, 2024
1 parent 019dacd commit db7cc08
Show file tree
Hide file tree
Showing 10 changed files with 256 additions and 153 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public interface CursoredPageable extends Pageable {
* Constant for no pagination.
*/
CursoredPageable UNPAGED = new DefaultCursoredPageable(
-1, null, null, Mode.CURSOR_NEXT, 0, Sort.UNSORTED, true
-1, null, Mode.CURSOR_NEXT, 0, Sort.UNSORTED, true
);

/**
Expand All @@ -54,16 +54,6 @@ default Mode getMode() {
return isBackward() ? Mode.CURSOR_PREVIOUS : Mode.CURSOR_NEXT;
}

@Override
default @NonNull CursoredPageable next() {
throw new IllegalStateException("Cannot retrieve next page, as a currentCursor for that is not present");
}

@Override
default @NonNull CursoredPageable previous() {
throw new IllegalStateException("Cannot retrieve previous page, as a currentCursor for that is not present");
}

/**
* Creates a new {@link CursoredPageable} with the given sort.
*
Expand All @@ -75,7 +65,7 @@ default Mode getMode() {
return UNPAGED;
}
return new DefaultCursoredPageable(
-1, null, null, Mode.CURSOR_NEXT, 0, sort, true
-1, null, Mode.CURSOR_NEXT, 0, sort, true
);
}

Expand All @@ -93,15 +83,14 @@ default Mode getMode() {
if (sort == null) {
sort = UNSORTED;
}
return new DefaultCursoredPageable(size, null, null, Mode.CURSOR_NEXT, 0, sort, true);
return new DefaultCursoredPageable(size, null, Mode.CURSOR_NEXT, 0, sort, true);
}

/**
* Creates a new {@link CursoredPageable} with the given currentCursor.
*
* @param page The page
* @param cursor The current currentCursor that will be used for querying data.
* @param nextCursor The currentCursor that could be used for querying the next page of data.
* @param mode The pagination mode. Must be either forward or backward currentCursor pagination.
* @param size The page size
* @param sort The sort
Expand All @@ -111,9 +100,8 @@ default Mode getMode() {
@Internal
@JsonCreator
static @NonNull CursoredPageable from(
@JsonProperty("page") int page,
@JsonProperty("number") int page,
@Nullable Cursor cursor,
@Nullable Cursor nextCursor,
Pageable.Mode mode,
int size,
@Nullable Sort sort,
Expand All @@ -122,7 +110,7 @@ default Mode getMode() {
if (sort == null) {
sort = UNSORTED;
}
return new DefaultCursoredPageable(size, cursor, nextCursor, mode, page, sort, requestTotal);
return new DefaultCursoredPageable(size, cursor, mode, page, sort, requestTotal);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* Copyright 2017-2020 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.data.model;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.micronaut.core.annotation.Creator;
import io.micronaut.core.annotation.ReflectiveAccess;
import io.micronaut.data.model.Pageable.Cursor;
import io.micronaut.data.model.Pageable.Mode;
import io.micronaut.serde.annotation.Serdeable;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
* Implementation of {@link Page} to return when {@link CursoredPageable} is requested.
*
* @author Andriy Dmytruk
* @since 4.8.0
* @param <T> The generic type
*/
@Serdeable
class DefaultCursoredPage<T> extends DefaultPage<T> {

private final List<Cursor> cursors;

/**
* Default constructor.
* @param content The content
* @param pageable The pageable
* @param totalSize The total size
*/
@JsonCreator
@Creator
@ReflectiveAccess
DefaultCursoredPage(
@JsonProperty("content")
List<T> content,
@JsonProperty("pageable")
Pageable pageable,
@JsonProperty("cursors")
List<Cursor> cursors,
@JsonProperty("totalSize")
Long totalSize
) {
super(content, pageable, totalSize);
if (content.size() != cursors.size()) {
throw new IllegalArgumentException("The number of cursors must match the number of content items for a page");
}
this.cursors = cursors;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof DefaultCursoredPage<?> that)) {
return false;
}
return Objects.equals(cursors, that.cursors) && super.equals(o);
}

@Override
public Optional<Cursor> getCursor(int i) {
return Optional.of(cursors.get(i));
}

@Override
public boolean hasNext() {
Pageable pageable = getPageable();
if (pageable.getMode() == Mode.CURSOR_NEXT) {
return cursors.size() == pageable.getSize();
} else {
return true;
}
}

@Override
public boolean hasPrevious() {
Pageable pageable = getPageable();
if (pageable.getMode() == Mode.CURSOR_PREVIOUS) {
return cursors.size() == pageable.getSize();
} else {
return true;
}
}

@Override
public Pageable nextPageable() {
Pageable pageable = getPageable();
Cursor cursor = cursors.isEmpty() ? pageable.cursor().orElse(null) : cursors.get(cursors.size() - 1);
return Pageable.afterCursor(cursor, pageable.getNumber() + 1, pageable.getSize(), pageable.getSort());
}

@Override
public Pageable previousPageable() {
Pageable pageable = getPageable();
Cursor cursor = cursors.isEmpty() ? pageable.cursor().orElse(null) : cursors.get(0);
return Pageable.beforeCursor(cursor, Math.max(0, pageable.getNumber() - 1), pageable.getSize(), pageable.getSort());
}

@Override
public int hashCode() {
return Objects.hash(cursors, super.hashCode());
}

@Override
public String toString() {
return "DefaultPage{" +
"totalSize=" + getTotalSize() +
",content=" + getContent() +
",pageable=" + getPageable() +
",cursors=" + cursors +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@
* @param page The page.
* @param currentCursor The current currentCursor. This is the currentCursor that will be used for pagination
* in case this pageable is used in a query.
* @param nextCursor A currentCursor for the next page of data. It is stored in pageable to correctly
* support {@link #next()} for forward or {@link #previous()} for backward
* pagination.
* @param mode The pagination mode. Could be one of {@link Mode#CURSOR_NEXT} or {@link Mode#CURSOR_PREVIOUS}.
* @param size The size of a page
* @param sort The sorting
Expand All @@ -48,8 +45,6 @@ record DefaultCursoredPageable(
@Nullable
@JsonProperty("cursor")
Cursor currentCursor,
@Nullable
Cursor nextCursor,
Mode mode,
@JsonProperty("number") int page,
Sort sort,
Expand Down Expand Up @@ -100,62 +95,29 @@ public boolean isBackward() {

@Override
public CursoredPageable next() {
Cursor requiredCursor = mode == Mode.CURSOR_PREVIOUS ? currentCursor : nextCursor;
if (requiredCursor != null) {
return new DefaultCursoredPageable(
size,
requiredCursor,
null,
Mode.CURSOR_NEXT,
page + 1,
sort,
requestTotal
);
}
return CursoredPageable.super.next();
throw new UnsupportedOperationException("To get next pageable results must be retrieved. Use page.nextPageable() to retrieve the next pageable.");
}

@Override
public CursoredPageable previous() {
Cursor requiredCursor = mode == Mode.CURSOR_PREVIOUS ? nextCursor : currentCursor;
if (requiredCursor != null) {
return new DefaultCursoredPageable(
size,
requiredCursor,
null,
Mode.CURSOR_PREVIOUS,
Math.max(page - 1, 0),
sort,
requestTotal
);
}
return CursoredPageable.super.previous();
throw new UnsupportedOperationException("To get next pageable results must be retrieved. Use page.nextPageable() to retrieve the next pageable.");

}

@Override
public Pageable withTotal() {
if (requestTotal) {
return this;
}
return new DefaultCursoredPageable(size, currentCursor, nextCursor, mode, page, sort, true);
return new DefaultCursoredPageable(size, currentCursor, mode, page, sort, true);
}

@Override
public Pageable withoutTotal() {
if (!requestTotal) {
return this;
}
return new DefaultCursoredPageable(size, currentCursor, nextCursor, mode, page, sort, true);
}

@Override
public boolean hasNext() {
return mode == Mode.CURSOR_PREVIOUS ? currentCursor != null : nextCursor != null;
}

@Override
public boolean hasPrevious() {
return mode == Mode.CURSOR_PREVIOUS ? nextCursor != null : currentCursor != null;
return new DefaultCursoredPageable(size, currentCursor, mode, page, sort, true);
}

@Override
Expand All @@ -168,14 +130,13 @@ public boolean equals(Object o) {
}
return size == that.size
&& Objects.equals(currentCursor, that.currentCursor)
&& Objects.equals(nextCursor, that.nextCursor)
&& Objects.equals(mode, that.mode)
&& Objects.equals(sort, that.sort);
}

@Override
public int hashCode() {
return Objects.hash(size, currentCursor, nextCursor, mode, sort);
return Objects.hash(size, currentCursor, mode, sort);
}

@Override
Expand All @@ -184,7 +145,6 @@ public String toString() {
"size=" + size +
", page=" + page +
", currentCursor=" + currentCursor +
", nextCursor=" + nextCursor +
", mode=" + mode +
", sort=" + sort +
'}';
Expand Down
Loading

0 comments on commit db7cc08

Please sign in to comment.