Skip to content

Commit

Permalink
Add PaginationAction#order (#1945)
Browse files Browse the repository at this point in the history
  • Loading branch information
MinnDevelopment committed Feb 19, 2022
1 parent ce9b22d commit 09f75ff
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 44 deletions.
Expand Up @@ -114,7 +114,7 @@ public interface PaginationAction<T, M extends PaginationAction<T, M>> extends R
* The snowflake ID to skip before, this is exclusive rather than inclusive
*
* @throws IllegalArgumentException
* If cache is enabled and you are attempting to skip forward in time {@literal (id > last)}
* If cache is enabled, and you are attempting to skip forward in time {@literal (id > last)}
*
* @return The current PaginationAction for chaining convenience
*
Expand Down Expand Up @@ -146,6 +146,68 @@ public interface PaginationAction<T, M extends PaginationAction<T, M>> extends R
@Override
M deadline(long timestamp);

/**
* The supported {@link PaginationOrder PaginationOrders} for this pagination action.
* <br>All enum values that are not returned will cause a throw for {@link #order(PaginationOrder)}.
*
* <p>Most pagination endpoints only support a single order, however some endpoints such as message pagination supports both.
*
* @return {@link EnumSet} of {@link PaginationOrder} (Modifying this set does not affect this class)
*/
@Nonnull
default EnumSet<PaginationOrder> getSupportedOrders()
{
return EnumSet.allOf(PaginationOrder.class);
}

/**
* The current iteration order.
* <br>This defaults to {@link PaginationOrder#BACKWARD}, meaning most recent first, for most pagination endpoints.
*
* @return The {@link PaginationOrder}
*
* @see #order(PaginationOrder)
*/
@Nonnull
PaginationOrder getOrder();

/**
* Configure the {@link PaginationOrder} of this pagination action.
*
* <p>You can only supply supported orders, see {@link #getSupportedOrders()}.
*
* @param order
* The pagination order
*
* @throws IllegalArgumentException
* If the provided pagination order is null or unsupported
* @throws IllegalStateException
* If this pagination action has already been used to retrieve entities
*
* @return The current PaginationAction implementation instance
*
* @see #getSupportedOrders()
* @see #reverse()
*/
@Nonnull
M order(@Nonnull PaginationOrder order);

/**
* Flips the {@link #order(PaginationOrder)} of this pagination action.
*
* @throws IllegalArgumentException
* If this pagination action does not support the reversed order
*
* @return The current PaginationAction implementation instance
*/
@Nonnull
default M reverse()
{
if (getOrder() == PaginationOrder.BACKWARD)
return order(PaginationOrder.FORWARD);
return order(PaginationOrder.BACKWARD);
}

/**
* The current amount of cached entities for this PaginationAction
*
Expand Down Expand Up @@ -632,6 +694,39 @@ default Stream<T> parallelStream()
@Override
PaginationIterator<T> iterator();

/**
* Defines the pagination order for a pagination endpoint.
*/
enum PaginationOrder
{
/**
* Iterates backwards in time, listing the most recent entities first.
*/
BACKWARD("before"),
/**
* Iterates forward in time, listing the oldest entities first.
*/
FORWARD("after");

private final String key;

PaginationOrder(String key)
{
this.key = key;
}

/**
* The API query parameter key
*
* @return The query key
*/
@Nonnull
public String getKey()
{
return key;
}
}

/**
* Iterator implementation for a {@link PaginationAction PaginationAction}.
* <br>This iterator will first iterate over all currently cached entities and continue to retrieve new entities
Expand Down
Expand Up @@ -37,6 +37,7 @@

import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

public class AuditLogPaginationActionImpl
Expand All @@ -54,6 +55,7 @@ public AuditLogPaginationActionImpl(Guild guild)
if (!guild.getSelfMember().hasPermission(Permission.VIEW_AUDIT_LOGS))
throw new InsufficientPermissionException(guild, Permission.VIEW_AUDIT_LOGS);
this.guild = guild;
super.order(PaginationOrder.BACKWARD);
}

@Nonnull
Expand Down Expand Up @@ -95,25 +97,24 @@ public Guild getGuild()
return guild;
}

@Nonnull
@Override
public EnumSet<PaginationOrder> getSupportedOrders()
{
return EnumSet.of(PaginationOrder.BACKWARD);
}

@Override
protected Route.CompiledRoute finalizeRoute()
{
Route.CompiledRoute route = super.finalizeRoute();

final String limit = String.valueOf(this.limit.get());
final long last = this.lastKey;

route = route.withQueryParams("limit", limit);

if (type != null)
route = route.withQueryParams("action_type", String.valueOf(type.getKey()));

if (userId != null)
route = route.withQueryParams("user_id", userId);

if (last != 0)
route = route.withQueryParams("before", Long.toUnsignedString(last));

return route;
}

Expand Down
Expand Up @@ -30,6 +30,7 @@

import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MessagePaginationActionImpl
Expand Down Expand Up @@ -63,22 +64,6 @@ public MessageChannel getChannel()
return channel;
}

@Override
protected Route.CompiledRoute finalizeRoute()
{
Route.CompiledRoute route = super.finalizeRoute();

final String limit = String.valueOf(this.getLimit());
final long last = this.lastKey;

route = route.withQueryParams("limit", limit);

if (last != 0)
route = route.withQueryParams("before", Long.toUnsignedString(last));

return route;
}

@Override
protected void handleSuccess(Response response, Request<List<Message>> request)
{
Expand All @@ -91,10 +76,6 @@ protected void handleSuccess(Response response, Request<List<Message>> request)
{
Message msg = builder.createMessage(array.getObject(i), channel, false);
messages.add(msg);
if (useCache)
cached.add(msg);
last = msg;
lastKey = last.getIdLong();
}
catch (ParsingException | NullPointerException e)
{
Expand All @@ -109,6 +90,17 @@ protected void handleSuccess(Response response, Request<List<Message>> request)
}
}

if (order == PaginationOrder.FORWARD)
Collections.reverse(messages);
if (useCache)
cached.addAll(messages);

if (!messages.isEmpty())
{
last = messages.get(messages.size() - 1);
lastKey = last.getIdLong();
}

request.onSuccess(messages);
}

Expand Down
Expand Up @@ -42,6 +42,8 @@ public abstract class PaginationActionImpl<T, M extends PaginationAction<T, M>>
protected final int minLimit;
protected final AtomicInteger limit;

protected PaginationOrder order = PaginationOrder.BACKWARD;

protected volatile long iteratorIndex = 0;
protected volatile long lastKey = 0;
protected volatile T last = null;
Expand Down Expand Up @@ -109,6 +111,30 @@ public long getLastKey()
return lastKey;
}

@Nonnull
@Override
public PaginationOrder getOrder()
{
return order;
}

@Nonnull
@Override
@SuppressWarnings("unchecked")
public M order(@Nonnull PaginationAction.PaginationOrder order)
{
Checks.notNull(order, "PaginationOrder");
if (order != this.order)
{
if (!isEmpty())
throw new IllegalStateException("Cannot change pagination order after retrieving.");
if (!getSupportedOrders().contains(order))
throw new IllegalArgumentException("Cannot use PaginationOrder." + order + " for this pagination endpoint.");
}
this.order = order;
return (M) this;
}

@Nonnull
@Override
@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -321,6 +347,24 @@ public void forEachRemaining(@Nonnull final Procedure<? super T> action)
}
}

@Override
protected Route.CompiledRoute finalizeRoute()
{
Route.CompiledRoute route = super.finalizeRoute();

final String limit = String.valueOf(this.getLimit());
final long last = this.lastKey;

route = route.withQueryParams("limit", limit);

if (last != 0)
route = route.withQueryParams(order.getKey(), Long.toUnsignedString(last));
else if (order == PaginationOrder.FORWARD)
route = route.withQueryParams("after", "0");

return route;
}

protected List<T> getRemainingCache()
{
int index = getIteratorIndex();
Expand Down
Expand Up @@ -30,6 +30,7 @@
import net.dv8tion.jda.internal.utils.EncodingUtil;

import javax.annotation.Nonnull;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;

Expand All @@ -48,18 +49,21 @@ public class ReactionPaginationActionImpl
public ReactionPaginationActionImpl(MessageReaction reaction)
{
super(reaction.getJDA(), Route.Messages.GET_REACTION_USERS.compile(reaction.getChannel().getId(), reaction.getMessageId(), getCode(reaction)), 1, 100, 100);
super.order(PaginationOrder.FORWARD);
this.reaction = reaction;
}

public ReactionPaginationActionImpl(Message message, String code)
{
super(message.getJDA(), Route.Messages.GET_REACTION_USERS.compile(message.getChannel().getId(), message.getId(), code), 1, 100, 100);
super.order(PaginationOrder.FORWARD);
this.reaction = null;
}

public ReactionPaginationActionImpl(MessageChannel channel, String messageId, String code)
{
super(channel.getJDA(), Route.Messages.GET_REACTION_USERS.compile(channel.getId(), messageId, code), 1, 100, 100);
super.order(PaginationOrder.FORWARD);
this.reaction = null;
}

Expand All @@ -81,23 +85,11 @@ public MessageReaction getReaction()
return reaction;
}

@Nonnull
@Override
protected Route.CompiledRoute finalizeRoute()
public EnumSet<PaginationOrder> getSupportedOrders()
{
Route.CompiledRoute route = super.finalizeRoute();

String after = null;
String limit = String.valueOf(getLimit());
long last = this.lastKey;
if (last != 0)
after = Long.toUnsignedString(last);

route = route.withQueryParams("limit", limit);

if (after != null)
route = route.withQueryParams("after", after);

return route;
return EnumSet.of(PaginationOrder.FORWARD);
}

@Override
Expand Down
Expand Up @@ -17,6 +17,7 @@

import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

public class ThreadChannelPaginationActionImpl extends PaginationActionImpl<ThreadChannel, ThreadChannelPaginationAction> implements ThreadChannelPaginationAction
Expand All @@ -38,6 +39,13 @@ public IThreadContainer getChannel()
return channel;
}

@Nonnull
@Override
public EnumSet<PaginationOrder> getSupportedOrders()
{
return EnumSet.of(PaginationOrder.BACKWARD);
}

@Override
protected Route.CompiledRoute finalizeRoute()
{
Expand Down

0 comments on commit 09f75ff

Please sign in to comment.