Class PaginationAction<T,​M extends PaginationAction<T,​M>>

  • Type Parameters:
    M - The current implementation used as chaining return value
    T - The type of entity to paginate
    All Implemented Interfaces:
    java.lang.Iterable<T>
    Direct Known Subclasses:
    AuditLogPaginationAction, MentionPaginationAction, MessagePaginationAction, ReactionPaginationAction

    public abstract class PaginationAction<T,​M extends PaginationAction<T,​M>>
    extends RestAction<java.util.List<T>>
    implements java.lang.Iterable<T>
    RestAction specification used to retrieve entities for paginated endpoints (before, after, limit).

    Examples

    
     /**
       * Retrieves messages until the specified limit is reached. The messages will be limited after being filtered by the user.
       * If the user hasn't sent enough messages this will go through all messages so it is recommended to add an additional end condition.
       */
     public staticList<Message> getMessagesByUser(MessageChannel channel, User user, int limit)
     {
         MessagePaginationAction action = channel.getIterableHistory();
         Stream<Message> messageStream = action.stream()
                 .limit(limit * 2) // used to limit amount of messages to check, if user hasn't sent enough messages it would go on forever
                 .filter( message-> message.getAuthor().equals(user) )
                 .limit(limit); // limit on filtered stream will be checked independently from previous limit
         return messageStream.collect(Collectors.toList());
     }
     
    
     /**
      * Iterates messages in an async stream and stops once the limit has been reached.
      */
     public static void onEachMessageAsync(MessageChannel channel, Consumer<Message> consumer, int limit)
     {
         if (limit< 1)
             return;
         MessagePaginationAction action = channel.getIterableHistory();
         AtomicInteger counter = new AtomicInteger(limit);
         action.forEachAsync( (message)->
         {
             consumer.accept(message);
             // if false the iteration is terminated; else it continues
             return counter.decrementAndGet() == 0;
         });
     }
     
    Since:
    3.1
    • Constructor Detail

      • PaginationAction

        public PaginationAction​(JDA api,
                                net.dv8tion.jda.core.requests.Route.CompiledRoute route,
                                int minLimit,
                                int maxLimit,
                                int initialLimit)
        Creates a new PaginationAction instance
        Parameters:
        api - The current JDA instance
        route - The base route
        maxLimit - The inclusive maximum limit that can be used in limit(int)
        minLimit - The inclusive minimum limit that can be used in limit(int)
        initialLimit - The initial limit to use on the pagination endpoint
      • PaginationAction

        public PaginationAction​(JDA api)
        Creates a new PaginationAction instance
        This is used for PaginationActions that should not deal with limit(int)
        Parameters:
        api - The current JDA instance
    • Method Detail

      • setCheck

        public M setCheck​(java.util.function.BooleanSupplier checks)
        Description copied from class: RestAction
        Sets the last-second checks before finally executing the http request in the queue.
        If the provided supplier evaluates to false or throws an exception this will not be finished. When an exception is thrown from the supplier it will be provided to the failure callback.
        Overrides:
        setCheck in class RestAction<java.util.List<T>>
        Parameters:
        checks - The checks to run before executing the request, or null to run no checks
        Returns:
        The current RestAction for chaining convenience
      • cacheSize

        public int cacheSize()
        The current amount of cached entities for this PaginationAction
        Returns:
        int size of currently cached entities
      • isEmpty

        public boolean isEmpty()
        Whether the cache of this PaginationAction is empty.
        Logically equivalent to cacheSize() == 0.
        Returns:
        True, if no entities have been retrieved yet.
      • getCached

        public java.util.List<T> getCached()
        The currently cached entities of recent execution tasks.
        Every RestAction success adds to this List. (Thread-Safe due to CopyOnWriteArrayList)

        This does not contain all entities for the paginated endpoint unless the pagination has reached an end!
        It only contains those entities which already have been retrieved.

        Returns:
        Immutable List containing all currently cached entities for this PaginationAction
      • getLast

        public T getLast()
        The most recent entity retrieved by this PaginationAction instance
        Returns:
        The most recent cached entity
        Throws:
        java.util.NoSuchElementException - If no entities have been retrieved yet (see isEmpty())
      • getFirst

        public T getFirst()
        The first cached entity retrieved by this PaginationAction instance
        Returns:
        The very first cached entity
        Throws:
        java.util.NoSuchElementException - If no entities have been retrieved yet (see isEmpty())
      • limit

        public M limit​(int limit)
        Sets the limit that should be used in the next RestAction completion call.

        The specified limit may not be below the Minimum Limit nor above the Maximum Limit. Unless these limits are specifically omitted. (See documentation of methods)

        This limit represents how many entities will be retrieved per request and NOT the maximum amount of entities that should be retrieved for iteration/sequencing.
        action.limit(50).complete()
        is not the same as
        action.stream().limit(50).collect(collector)

        Parameters:
        limit - The limit to use
        Returns:
        The current PaginationAction implementation instance
        Throws:
        java.lang.IllegalArgumentException - If the provided limit is out of range
      • cache

        public M cache​(boolean enableCache)
        Whether already retrieved entities should be stored within the internal cache. All cached entities will be available from getCached(). Default: true
        This being disabled allows unused entities to be removed from the memory heap by the garbage collector. If this is enabled this will not take place until all references to this PaginationAction have been cleared.
        Parameters:
        enableCache - Whether to enable entity cache
        Returns:
        The current PaginationAction implementation instance
      • isCacheEnabled

        public boolean isCacheEnabled()
        Whether retrieved entities are stored within an internal cache. If this is false entities retrieved by the iterator or a call to a RestAction terminal operation will not be retrievable from getCached().
        This being disabled allows unused entities to be removed from the memory heap by the garbage collector. If this is enabled this will not take place until all references to this PaginationAction have been cleared.
        Returns:
        True, If entities will be cached.
      • getMaxLimit

        public final int getMaxLimit()
        The maximum limit that can be used for this PaginationAction
        Limits provided to limit(int) must not be greater than the returned value.
        If no maximum limit is used this will return 0. That means there is no upper border for limiting this PaginationAction
        Returns:
        The maximum limit
      • getMinLimit

        public final int getMinLimit()
        The minimum limit that can be used for this PaginationAction
        Limits provided to limit(int) must not be less than the returned value.
        If no minimum limit is used this will return 0. That means there is no lower border for limiting this PaginationAction
        Returns:
        The minimum limit
      • getLimit

        public final int getLimit()
        The currently used limit.
        If this PaginationAction does not use limitation this will return 0
        Returns:
        limit
      • takeRemainingAsync

        public RequestFuture<java.util.List<T>> takeRemainingAsync​(int amount)
        Convenience method to retrieve an amount of entities from this pagination action.
        Unlike takeAsync(int) this does not include already cached entities.
        Parameters:
        amount - The maximum amount to retrieve
        Returns:
        RequestFuture - Type: List
        See Also:
        forEachRemainingAsync(Procedure)
      • forEachAsync

        public RequestFuture<?> forEachAsync​(Procedure<T> action)
        Iterates over all entities until the provided action returns false!
        This operation is different from Iterable.forEach(Consumer) as it uses successive RestAction.queue() tasks to iterate each entity in callback threads instead of the calling active thread. This means that this method fully works on different threads to retrieve new entities.

        This iteration will include already cached entities, in order to exclude cached entities use forEachRemainingAsync(Procedure)

        Example

        
         //deletes messages until it finds a user that is still in guild
         public void cleanupMessages(MessagePaginationAction action)
         {
             action.forEachAsync( (message) ->
             {
                 Guild guild = message.getGuild();
                 if (!guild.isMember(message.getAuthor()))
                     message.delete().queue();
                 else
                     return false;
                 return true;
             });
         }
         
        Parameters:
        action - Procedure returning true if iteration should continue!
        Returns:
        Future that can be cancelled to stop iteration from outside!
        Throws:
        java.lang.IllegalArgumentException - If the provided Procedure is null
      • forEachAsync

        public RequestFuture<?> forEachAsync​(Procedure<T> action,
                                             java.util.function.Consumer<java.lang.Throwable> failure)
        Iterates over all entities until the provided action returns false!
        This operation is different from Iterable.forEach(Consumer) as it uses successive RestAction.queue() tasks to iterate each entity in callback threads instead of the calling active thread. This means that this method fully works on different threads to retrieve new entities.

        This iteration will include already cached entities, in order to exclude cached entities use forEachRemainingAsync(Procedure, Consumer)

        Example

        
         //deletes messages until it finds a user that is still in guild
         public void cleanupMessages(MessagePaginationAction action)
         {
             action.forEachAsync( (message) ->
             {
                 Guild guild = message.getGuild();
                 if (!guild.isMember(message.getAuthor()))
                     message.delete().queue();
                 else
                     return false;
                 return true;
             }, Throwable::printStackTrace);
         }
         
        Parameters:
        action - Procedure returning true if iteration should continue!
        failure - Consumer that should handle any throwables from the action
        Returns:
        Future that can be cancelled to stop iteration from outside!
        Throws:
        java.lang.IllegalArgumentException - If the provided Procedure or the failure Consumer is null
      • forEachRemainingAsync

        public RequestFuture<?> forEachRemainingAsync​(Procedure<T> action)
        Iterates over all remaining entities until the provided action returns false!
        This operation is different from forEachRemaining(Procedure) as it uses successive RestAction.queue() tasks to iterate each entity in callback threads instead of the calling active thread. This means that this method fully works on different threads to retrieve new entities.

        This iteration will exclude already cached entities, in order to include cached entities use forEachAsync(Procedure)

        Example

        
         //deletes messages until it finds a user that is still in guild
         public void cleanupMessages(MessagePaginationAction action)
         {
             action.forEachRemainingAsync( (message) ->
             {
                 Guild guild = message.getGuild();
                 if (!guild.isMember(message.getAuthor()))
                     message.delete().queue();
                 else
                     return false;
                 return true;
             });
         }
         
        Parameters:
        action - Procedure returning true if iteration should continue!
        Returns:
        Future that can be cancelled to stop iteration from outside!
        Throws:
        java.lang.IllegalArgumentException - If the provided Procedure is null
      • forEachRemainingAsync

        public RequestFuture<?> forEachRemainingAsync​(Procedure<T> action,
                                                      java.util.function.Consumer<java.lang.Throwable> failure)
        Iterates over all remaining entities until the provided action returns false!
        This operation is different from forEachRemaining(Procedure) as it uses successive RestAction.queue() tasks to iterate each entity in callback threads instead of the calling active thread. This means that this method fully works on different threads to retrieve new entities.

        This iteration will exclude already cached entities, in order to include cached entities use forEachAsync(Procedure, Consumer)

        Example

        
         //deletes messages until it finds a user that is still in guild
         public void cleanupMessages(MessagePaginationAction action)
         {
             action.forEachRemainingAsync( (message) ->
             {
                 Guild guild = message.getGuild();
                 if (!guild.isMember(message.getAuthor()))
                     message.delete().queue();
                 else
                     return false;
                 return true;
             }, Throwable::printStackTrace);
         }
         
        Parameters:
        action - Procedure returning true if iteration should continue!
        failure - Consumer that should handle any throwables from the action
        Returns:
        Future that can be cancelled to stop iteration from outside!
        Throws:
        java.lang.IllegalArgumentException - If the provided Procedure or the failure Consumer is null
      • forEachRemaining

        public void forEachRemaining​(Procedure<T> action)
        Iterates over all remaining entities until the provided action returns false!
        Skipping past already cached entities to iterate all remaining entities of this PaginationAction.

        This is a blocking operation that might take a while to complete

        Parameters:
        action - The Procedure which should return true to continue iterating
      • spliterator

        public java.util.Spliterator<T> spliterator()
        Specified by:
        spliterator in interface java.lang.Iterable<T>
      • stream

        public java.util.stream.Stream<T> stream()
        A sequential Stream with this PaginationAction as its source.
        Returns:
        a sequential Stream over the elements in this PaginationAction
      • parallelStream

        public java.util.stream.Stream<T> parallelStream()
        Returns a possibly parallel Stream with this PaginationAction as its source. It is allowable for this method to return a sequential stream.
        Returns:
        a sequential Stream over the elements in this PaginationAction