All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.dv8tion.jda.api.utils.cache.CacheView Maven / Gradle / Ivy

Go to download

Java wrapper for the popular chat & VOIP service: Discord https://discord.com

There is a newer version: 5.1.0
Show newest version
/*
 * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
 *
 * 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
 *
 *    http://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 net.dv8tion.jda.api.utils.cache;

import net.dv8tion.jda.api.entities.ISnowflake;
import net.dv8tion.jda.api.utils.ClosableIterator;
import net.dv8tion.jda.internal.utils.Checks;
import net.dv8tion.jda.internal.utils.cache.AbstractCacheView;
import net.dv8tion.jda.internal.utils.cache.ShardCacheViewImpl;
import net.dv8tion.jda.internal.utils.cache.SortedSnowflakeCacheViewImpl;
import net.dv8tion.jda.internal.utils.cache.UnifiedCacheViewImpl;
import org.jetbrains.annotations.Unmodifiable;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * Read-only view on internal JDA cache of items.
 * 
This can be useful to check information such as size without creating * an immutable snapshot first. * *

Memory Efficient Usage
* The {@link #forEach(Consumer)} method can be used to avoid creating a snapshot * of the backing data store, it is implemented by first acquiring a read-lock and then iterating the code. * The enhanced-for-loop uses the {@link #iterator()} which has to first create a snapshot to avoid * concurrent modifications. Alternatively the {@link #lockedIterator()} can be used to acquire an iterator * which holds a read-lock on the data store and thus prohibits concurrent modifications, for more details * read the documentation of {@link ClosableIterator}. Streams from {@link #stream()}/{@link #parallelStream()} * both use {@link #iterator()} with a snapshot of the backing data store to avoid concurrent modifications. *
Using {@link #getElementsByName(String)} is more efficient than {@link #asList()} as it uses {@link #forEach(Consumer)} * for pattern matching and thus does not need to create a snapshot of the entire data store like {@link #asList()} does. *
Both {@link #size()} and {@link #isEmpty()} are atomic operations. * *

Note that making a copy is a requirement if a specific order is desired. If using {@link #lockedIterator()} * the order is not guaranteed as it directly iterates the backing cache. * Using {@link #forEach(Consumer)} on a {@link SortedSnowflakeCacheView} will copy the cache in order to sort * it, use {@link SortedSnowflakeCacheView#forEachUnordered(Consumer)} to avoid this overhead. * The backing cache is stored using an un-ordered hash map. * * @param * The cache type */ public interface CacheView extends Iterable { /** * Creates an immutable snapshot of the current cache state. *
This will copy all elements contained in this cache into a list. *
This will be sorted for a {@link SortedSnowflakeCacheViewImpl SortedSnowflakeCacheView}. * * @return Immutable list of cached elements */ @Nonnull @Unmodifiable List asList(); /** * Creates an immutable snapshot of the current cache state. *
This will copy all elements contained in this cache into a set. * * @return Immutable set of cached elements */ @Nonnull @Unmodifiable Set asSet(); /** * Returns an iterator with direct access to the underlying data store. * This iterator does not support removing elements. *
After usage this iterator should be closed to allow modifications by the library internals. * *

Note: Order is not preserved in this iterator to be more efficient, * if order is desired use {@link #iterator()} instead! * * @return {@link ClosableIterator} holding a read-lock on the data structure. * * @since 4.0.0 */ @Nonnull ClosableIterator lockedIterator(); /** * Behavior similar to {@link #forEach(Consumer)} but does not preserve order. *
This will not copy the data store as sorting is not needed. * * @param action * The action to perform * * @throws NullPointerException * If provided with null * * @since 4.0.0 */ default void forEachUnordered(@Nonnull final Consumer action) { forEach(action); } /** * Creates an unordered sequenced stream of the elements in this cache. *
This does not copy the backing cache prior to consumption unlike {@link #stream()}. * *

The stream will be closed once this method returns and cannot be used anymore. * *

Example
* * {@literal CacheView} view = jda.getUserCache();
* long shortNames = view.applyStream(stream {@literal ->} stream.filter(it {@literal ->} it.getName().length() {@literal <} 4).count());
* System.out.println(shortNames + " users with less than 4 characters in their name"); *
* * @param action * The action to perform on the stream * @param * The return type after performing the specified action * * @throws IllegalArgumentException * If the action is null * * @return The resulting value after the action was performed * * @since 4.0.0 * * @see #acceptStream(Consumer) */ default R applyStream(@Nonnull Function, ? extends R> action) { Checks.notNull(action, "Action"); try (ClosableIterator it = lockedIterator()) { Spliterator spliterator = Spliterators.spliterator(it, size(), Spliterator.IMMUTABLE | Spliterator.NONNULL); Stream stream = StreamSupport.stream(spliterator, false); return action.apply(stream); } } /** * Creates an unordered sequenced stream of the elements in this cache. *
This does not copy the backing cache prior to consumption unlike {@link #stream()}. * *

The stream will be closed once this method returns and cannot be used anymore. * *

Example
* * {@literal CacheView} view = guild.getTextChannelCache();
* view.acceptStream(stream {@literal ->} stream.filter(it {@literal ->} it.isNSFW()).forEach(it {@literal ->} it.sendMessage("lewd").queue())); *
* * @param action * The action to perform on the stream * * @throws IllegalArgumentException * If the action is null * * @since 4.0.0 * * @see #applyStream(Function) */ default void acceptStream(@Nonnull Consumer> action) { Checks.notNull(action, "Action"); try (ClosableIterator it = lockedIterator()) { Spliterator spliterator = Spliterators.spliterator(it, size(), Spliterator.IMMUTABLE | Spliterator.NONNULL); Stream stream = StreamSupport.stream(spliterator, false); action.accept(stream); } } /** * The current size of this cache *
This is a {@code long} as it may be a projected view of multiple caches * (See {@link net.dv8tion.jda.api.utils.cache.CacheView#all(java.util.function.Supplier)}) * *

This is more efficient than creating a list or set snapshot first as it checks the size * of the internal cache directly. * * @return The current size of this cache */ long size(); /** * Whether the cache is empty * *

This is more efficient than creating a list or set snapshot first as it checks the size * of the internal cache directly. *
On a projected cache view this will simply look through all projected views and return false * the moment it finds one that is not empty. * * @return True, if this cache is currently empty */ boolean isEmpty(); /** * Creates an immutable list of all elements matching the given name. *
For a {@link net.dv8tion.jda.api.utils.cache.MemberCacheView MemberCacheView} this will * check the {@link net.dv8tion.jda.api.entities.Member#getEffectiveName() Effective Name} of the cached members. * * @param name * The name to check * @param ignoreCase * Whether to ignore case when comparing names * * @throws java.lang.IllegalArgumentException * If the provided name is {@code null} * * @return Immutable list of elements with the given name */ @Nonnull @Unmodifiable List getElementsByName(@Nonnull String name, boolean ignoreCase); /** * Creates an immutable list of all elements matching the given name. *
For a {@link net.dv8tion.jda.api.utils.cache.MemberCacheView MemberCacheView} this will * check the {@link net.dv8tion.jda.api.entities.Member#getEffectiveName() Effective Name} of the cached members. * * @param name * The name to check * * @throws java.lang.IllegalArgumentException * If the provided name is {@code null} * * @return Immutable list of elements with the given name */ @Nonnull @Unmodifiable default List getElementsByName(@Nonnull String name) { return getElementsByName(name, false); } /** * Creates a {@link java.util.stream.Stream Stream} of all cached elements. *
This will be sorted for a {@link SortedSnowflakeCacheViewImpl SortedSnowflakeCacheView}. * * @return Stream of elements */ @Nonnull Stream stream(); /** * Creates a parallel {@link java.util.stream.Stream Stream} of all cached elements. *
This will be sorted for a {@link SortedSnowflakeCacheViewImpl SortedSnowflakeCacheView}. * * @return Parallel Stream of elements */ @Nonnull Stream parallelStream(); /** * Collects all cached entities into a single Collection using the provided * {@link java.util.stream.Collector Collector}. * Shortcut for {@code stream().collect(collector)}. * * @param collector * The collector used to collect the elements * * @param * The output type * @param * The accumulator type * * @throws java.lang.IllegalArgumentException * If the provided collector is {@code null} * * @return Resulting collections */ @Nonnull default R collect(@Nonnull Collector collector) { return stream().collect(collector); } /** * Creates a combined {@link net.dv8tion.jda.api.utils.cache.CacheView CacheView} * for all provided CacheView implementations. This allows to combine cache of multiple * JDA sessions or Guilds. * * @param cacheViews * Collection of {@link net.dv8tion.jda.api.utils.cache.CacheView CacheView} implementations * * @param * The target type of the projection * * @return Combined CacheView spanning over all provided implementation instances */ @Nonnull static CacheView all(@Nonnull Collection> cacheViews) { Checks.noneNull(cacheViews, "Collection"); return new UnifiedCacheViewImpl<>(cacheViews::stream); } /** * Creates a combined {@link net.dv8tion.jda.api.utils.cache.CacheView CacheView} * for all provided CacheView implementations. This allows to combine cache of multiple * JDA sessions or Guilds. * * @param generator * Stream generator of {@link net.dv8tion.jda.api.utils.cache.CacheView CacheView} implementations * * @param * The target type of the projection * * @return Combined CacheView spanning over all provided implementation instances */ @Nonnull static CacheView all(@Nonnull Supplier>> generator) { Checks.notNull(generator, "Generator"); return new UnifiedCacheViewImpl<>(generator); } /** * Creates a combined {@link ShardCacheView ShardCacheView} * for all provided ShardCacheView implementations. * * @param cacheViews * Collection of {@link ShardCacheView ShardCacheView} implementations * * @return Combined ShardCacheView spanning over all provided implementation instances */ @Nonnull static ShardCacheView allShards(@Nonnull Collection cacheViews) { Checks.noneNull(cacheViews, "Collection"); return new ShardCacheViewImpl.UnifiedShardCacheViewImpl(cacheViews::stream); } /** * Creates a combined {@link ShardCacheView ShardCacheView} * for all provided ShardCacheView implementations. * * @param generator * Stream generator of {@link ShardCacheView ShardCacheView} implementations * * @return Combined ShardCacheView spanning over all provided implementation instances */ @Nonnull static ShardCacheView allShards(@Nonnull Supplier> generator) { Checks.notNull(generator, "Generator"); return new ShardCacheViewImpl.UnifiedShardCacheViewImpl(generator); } /** * Creates a combined {@link net.dv8tion.jda.api.utils.cache.SnowflakeCacheView SnowflakeCacheView} * for all provided SnowflakeCacheView implementations. *
This allows to combine cache of multiple JDA sessions or Guilds. * * @param cacheViews * Collection of {@link net.dv8tion.jda.api.utils.cache.SnowflakeCacheView SnowflakeCacheView} implementations * * @param * The target type of the chain * * @return Combined SnowflakeCacheView spanning over all provided implementation instances */ @Nonnull static SnowflakeCacheView allSnowflakes(@Nonnull Collection> cacheViews) { Checks.noneNull(cacheViews, "Collection"); return new UnifiedCacheViewImpl.UnifiedSnowflakeCacheView<>(cacheViews::stream); } /** * Creates a combined {@link net.dv8tion.jda.api.utils.cache.SnowflakeCacheView SnowflakeCacheView} * for all provided SnowflakeCacheView implementations. *
This allows to combine cache of multiple JDA sessions or Guilds. * * @param generator * Stream generator of {@link net.dv8tion.jda.api.utils.cache.SnowflakeCacheView SnowflakeCacheView} implementations * * @param * The target type of the chain * * @return Combined SnowflakeCacheView spanning over all provided implementation instances */ @Nonnull static SnowflakeCacheView allSnowflakes(@Nonnull Supplier>> generator) { Checks.notNull(generator, "Generator"); return new UnifiedCacheViewImpl.UnifiedSnowflakeCacheView<>(generator); } /** * Creates a combined {@link UnifiedMemberCacheView UnifiedMemberCacheView} * for all provided MemberCacheView implementations. *
This allows to combine cache of multiple JDA sessions or Guilds. * * @param cacheViews * Collection of {@link net.dv8tion.jda.api.utils.cache.MemberCacheView MemberCacheView} instances * * @return Combined MemberCacheView spanning over all provided instances */ @Nonnull static UnifiedMemberCacheView allMembers(@Nonnull Collection cacheViews) { Checks.noneNull(cacheViews, "Collection"); return new UnifiedCacheViewImpl.UnifiedMemberCacheViewImpl(cacheViews::stream); } /** * Creates a combined {@link UnifiedMemberCacheView UnifiedMemberCacheView} * for all provided MemberCacheView implementations. *
This allows to combine cache of multiple JDA sessions or Guilds. * * @param generator * Stream generator of {@link net.dv8tion.jda.api.utils.cache.MemberCacheView MemberCacheView} instances * * @return Combined MemberCacheView spanning over all provided instances */ @Nonnull static UnifiedMemberCacheView allMembers(@Nonnull Supplier> generator) { Checks.notNull(generator, "Generator"); return new UnifiedCacheViewImpl.UnifiedMemberCacheViewImpl(generator); } /** * Basic implementation of {@link net.dv8tion.jda.api.utils.cache.CacheView CacheView} interface. *
Using {@link gnu.trove.map.TLongObjectMap TLongObjectMap} to cache entities! * * @param * The type this should cache */ class SimpleCacheView extends AbstractCacheView { public SimpleCacheView(@Nonnull Class type, @Nullable Function nameMapper) { super(type, nameMapper); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy