Improve various javadocs, add LogNotifyEvent

This commit is contained in:
Luck 2017-12-27 17:00:54 +00:00
parent ab115c4a6b
commit 3d6aa69ca1
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
38 changed files with 990 additions and 225 deletions

View File

@ -0,0 +1,100 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull;
/**
* Represents the object responsible for handling action logging.
*
* @since 4.1
*/
public interface ActionLogger {
/**
* Returns a new {@link LogEntry.Builder} instance
*
* @return a new builder
*/
@Nonnull
LogEntry.Builder newEntryBuilder();
/**
* Gets a {@link Log} instance from the plugin storage.
*
* <p>Returns the same result as {@link Storage#getLog()}.</p>
*
* @return a log instance
* @see Storage#getLog()
*/
@Nonnull
CompletableFuture<Log> getLog();
/**
* Submits a log entry to the plugin to be handled.
*
* <p>This method submits the log to the storage provider and broadcasts
* it.</p>
*
* <p>It is therefore roughly equivalent to calling
* {@link #submitToStorage(LogEntry)} and {@link #broadcastAction(LogEntry)},
* however, using this method is preferred to making the calls individually.</p>
*
* <p>If you want to submit a log entry but don't know which method to pick,
* use this one.</p>
*
* @param entry the entry to submit
* @return a future which will complete when the action is done
*/
@Nonnull
CompletableFuture<Void> submit(@Nonnull LogEntry entry);
/**
* Submits a log entry to the plugins storage handler.
*
* <p>Performs the same action as {@link Storage#logAction(LogEntry)}.</p>
*
* @param entry the entry to submit
* @return a future which will complete when the action is done
*/
@Nonnull
CompletableFuture<Void> submitToStorage(@Nonnull LogEntry entry);
/**
* Submits a log entry to the plugins log broadcasting handler.
*
* <p>If enabled, this method will also dispatch the log entry via the
* plugins {@link MessagingService}.</p>
*
* @param entry the entry to submit
* @return a future which will complete when the action is done
*/
@Nonnull
CompletableFuture<Void> broadcastAction(@Nonnull LogEntry entry);
}

View File

@ -31,14 +31,16 @@ import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.ImmutableContextSet;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
/**
* Encapsulates the options and settings for a permission lookup.
* Encapsulates the options and settings for a permission or meta lookup.
*
* <p>This class is immutable.</p>
*
* @since 2.11
*/
@Immutable
public class Contexts {
/**

View File

@ -36,12 +36,12 @@ public enum DataMutateResult {
SUCCESS(true),
/**
* Indicates the mutation failed because the subject already has something
* Indicates the mutation failed because the subject of the action already has something
*/
ALREADY_HAS(false),
/**
* Indicates the mutation failed because the subject lacks something
* Indicates the mutation failed because the subject of the action lacks something
*/
LACKS(false),

View File

@ -31,13 +31,15 @@ import java.util.Optional;
import java.util.OptionalLong;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
/**
* A relationship between a PermissionHolder and a permission
* A relationship between a {@link PermissionHolder} and a permission.
*
* @param <T> the identifier type of the holder
* @since 2.17
*/
@Immutable
public interface HeldPermission<T> {
/**

View File

@ -26,12 +26,14 @@
package me.lucko.luckperms.api;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
/**
* A node with a traceable origin
*
* @since 2.11
*/
@Immutable
public interface LocalizedNode extends Node {
/**

View File

@ -30,6 +30,7 @@ import java.util.SortedSet;
import java.util.UUID;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
/**
* Represents the internal LuckPerms log.
@ -41,6 +42,7 @@ import javax.annotation.Nonnull;
*
* <p>All methods are thread safe, and return immutable and thread safe collections.</p>
*/
@Immutable
public interface Log {
/**

View File

@ -30,12 +30,14 @@ import java.util.UUID;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
/**
* Represents a logged action.
*
* @see LuckPermsApi#newLogEntryBuilder() for creating an instance
* @see ActionLogger#newEntryBuilder() for creating an instance
*/
@Immutable
public interface LogEntry extends Comparable<LogEntry> {
/**
@ -143,27 +145,81 @@ public interface LogEntry extends Comparable<LogEntry> {
*/
interface Builder {
/**
* Sets the timestamp of the entry.
*
* @param timestamp the timestamp
* @return the builder
* @see LogEntry#getTimestamp()
*/
@Nonnull
Builder setTimestamp(long timestamp);
/**
* Sets the actor of the entry.
*
* @param actor the actor
* @return the builder
* @see LogEntry#getActor()
*/
@Nonnull
Builder setActor(@Nonnull UUID actor);
/**
* Sets the actor name of the entry.
*
* @param actorName the actor name
* @return the builder
* @see LogEntry#getActorName()
*/
@Nonnull
Builder setActorName(@Nonnull String actorName);
/**
* Sets the type of the entry.
*
* @param type the type
* @return the builder
* @see LogEntry#getType()
*/
@Nonnull
Builder setType(@Nonnull Type type);
/**
* Sets the acted object for the entry.
*
* @param acted the acted object
* @return the builder
* @see LogEntry#getActed()
*/
@Nonnull
Builder setActed(@Nullable UUID acted);
/**
* Sets the acted name for the entry.
*
* @param actedName the acted name
* @return the builder
* @see LogEntry#getActedName()
*/
@Nonnull
Builder setActedName(@Nonnull String actedName);
/**
* Sets the action of the entry.
*
* @param action the action
* @return the builder
* @see LogEntry#getAction()
*/
@Nonnull
Builder setAction(@Nonnull String action);
/**
* Creates a {@link LogEntry} instance from the builder.
*
* @return a new log entry instance
*/
@Nonnull
LogEntry build();

View File

@ -65,7 +65,14 @@ public interface LuckPermsApi {
PlatformInfo getPlatformInfo();
/**
* Gets the user manager
* Gets the {@link UserManager}, responsible for managing
* {@link User} instances.
*
* <p>This manager can be used to retrieve instances of {@link User} by uuid
* or name, or query all loaded users.</p>
*
* <p>The {@link #getStorage() storage} instance should be used to
* load/create/save users.</p>
*
* @return the user manager
* @since 4.0
@ -74,7 +81,14 @@ public interface LuckPermsApi {
UserManager getUserManager();
/**
* Gets the group manager
* Gets the {@link GroupManager}, responsible for managing
* {@link Group} instances.
*
* <p>This manager can be used to retrieve instances of {@link Group} by
* name, or query all loaded groups.</p>
*
* <p>The {@link #getStorage() storage} instance should be used to
* load/create/save/delete groups.</p>
*
* @return the group manager
* @since 4.0
@ -83,7 +97,14 @@ public interface LuckPermsApi {
GroupManager getGroupManager();
/**
* Gets the track manager
* Gets the {@link TrackManager}, responsible for managing
* {@link Track} instances.
*
* <p>This manager can be used to retrieve instances of {@link Track} by
* name, or query all loaded tracks.</p>
*
* <p>The {@link #getStorage() storage} instance should be used to
* load/create/save/delete tracks.</p>
*
* @return the track manager
* @since 4.0
@ -92,15 +113,23 @@ public interface LuckPermsApi {
TrackManager getTrackManager();
/**
* Schedules an update task to run
* Schedules the execution of an update task, and returns an encapsulation
* of the task as a {@link CompletableFuture}.
*
* <p>The exact actions performed in an update task remains an
* implementation detail of the plugin, however, as a minimum, it is
* expected to perform a full reload of user, group and track data, and
* ensure that any changes are fully applied and propagated.</p>
*
* @return a future
* @since 4.0
*/
@Nonnull
CompletableFuture<Void> runUpdateTask();
/**
* Gets the event bus, used for subscribing to events
* Gets the {@link EventBus}, used for subscribing to internal LuckPerms
* events.
*
* @return the event bus
* @since 3.0
@ -109,15 +138,18 @@ public interface LuckPermsApi {
EventBus getEventBus();
/**
* Gets the configuration
* Gets a representation of the plugins configuration
*
* @return a configuration instance
* @return the configuration
*/
@Nonnull
LPConfiguration getConfiguration();
/**
* Gets the backend storage dao
* Gets an object representing the plugins primary {@link Storage} backend.
*
* <p>The instance propagates calls to the internal DAO (Data Access Object),
* and applies any changes to the storage provider.</p>
*
* @return a storage instance
* @since 2.14
@ -126,24 +158,47 @@ public interface LuckPermsApi {
Storage getStorage();
/**
* Gets the messaging service
* Gets the {@link MessagingService}, if present.
*
* @return an optional that may contain a messaging service instance.
* <p>The MessagingService is used to dispatch updates throughout a network
* of servers running the plugin.</p>
*
* <p>Not all instances of LuckPerms will have a messaging service setup and
* configured, but it is recommended that all users of the API account for
* and make use of this.</p>
*
* @return the messaging service instance, if present.
*/
@Nonnull
Optional<MessagingService> getMessagingService();
/**
* Gets a {@link UuidCache} instance, providing read access to the LuckPerms
* internal uuid caching system
* Gets the {@link ActionLogger}.
*
* @return a uuid cache instance
* <p>The action logger is responsible for saving and broadcasting defined
* actions occurring on the platform.</p>
*
* @return the action logger
* @since 4.1
*/
ActionLogger getActionLogger();
/**
* Gets a {@link UuidCache}.
*
* <p>The uuid cache provides read access to the internal LuckPerms uuid
* mapping system.</p>
*
* @return the uuid cache
*/
@Nonnull
UuidCache getUuidCache();
/**
* Gets the context manager
* Gets the {@link ContextManager}.
*
* <p>The context manager manages {@link ContextCalculator}s, and calculates
* applicable contexts for a given type.</p>
*
* @return the context manager
* @since 4.0
@ -151,7 +206,9 @@ public interface LuckPermsApi {
ContextManager getContextManager();
/**
* Gets the node factory
* Gets the {@link NodeFactory}.
*
* <p>The node factory provides methods for building {@link Node} instances.</p>
*
* @return the node factory
*/
@ -159,7 +216,11 @@ public interface LuckPermsApi {
NodeFactory getNodeFactory();
/**
* Gets the MetaStackFactory
* Gets the {@link MetaStackFactory}.
*
* <p>The metastack factory provides methods for retrieving
* {@link me.lucko.luckperms.api.metastacking.MetaStackElement}s and constructing
* {@link me.lucko.luckperms.api.metastacking.MetaStackDefinition}s.</p>
*
* @return the meta stack factory
* @since 3.2
@ -167,7 +228,18 @@ public interface LuckPermsApi {
@Nonnull
MetaStackFactory getMetaStackFactory();
// convenience methods
/*
* The following methods are provided only for convenience, and offer no
* additional functionality.
*
* They are implemented as "default" methods, using the manager and factory
* instances provided by the methods above.
*/
/**
* Gets a wrapped user object from the user storage
@ -350,7 +422,9 @@ public interface LuckPermsApi {
* @since 4.0
*/
@Nonnull
LogEntry.Builder newLogEntryBuilder();
default LogEntry.Builder newLogEntryBuilder() {
return getActionLogger().newEntryBuilder();
}
/**
* Returns a permission builder instance

View File

@ -35,6 +35,7 @@ import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
/**
* Represents a permission node.
@ -45,6 +46,7 @@ import javax.annotation.Nullable;
*
* @since 2.6
*/
@Immutable
public interface Node extends Map.Entry<String, Boolean> {
/**
@ -356,7 +358,7 @@ public interface Node extends Map.Entry<String, Boolean> {
interface Builder {
/**
* Sets the value of negated for the node
* Sets the value of negated for the node.
*
* @param negated the value
* @return the builder
@ -366,7 +368,7 @@ public interface Node extends Map.Entry<String, Boolean> {
Builder setNegated(boolean negated);
/**
* Sets the value of the node
* Sets the value of the node.
*
* @param value the value
* @return the builder
@ -376,7 +378,7 @@ public interface Node extends Map.Entry<String, Boolean> {
Builder setValue(boolean value);
/**
* Sets the override property for the node
* Sets the override property for the node.
*
* <p>Warning: this value does not persist, and disappears when the holder is re-loaded.
* It is therefore only useful for transient nodes.</p>
@ -389,7 +391,7 @@ public interface Node extends Map.Entry<String, Boolean> {
Builder setOverride(boolean override);
/**
* Sets the nodes expiry as a unix timestamp in seconds
* Sets the nodes expiry as a unix timestamp in seconds.
*
* @param expireAt the expiry time
* @return the builder
@ -399,7 +401,7 @@ public interface Node extends Map.Entry<String, Boolean> {
Builder setExpiry(long expireAt);
/**
* Sets the world value for the node
* Sets the world value for the node.
*
* @param world the world value
* @return the builder
@ -409,7 +411,7 @@ public interface Node extends Map.Entry<String, Boolean> {
Builder setWorld(@Nullable String world);
/**
* Sets the server value for the node
* Sets the server value for the node.
*
* @param server the world value
* @return the builder
@ -419,7 +421,7 @@ public interface Node extends Map.Entry<String, Boolean> {
Builder setServer(@Nullable String server);
/**
* Appends an extra context onto the node
* Appends an extra context onto the node.
*
* @param key the context key
* @param value the context value
@ -431,9 +433,10 @@ public interface Node extends Map.Entry<String, Boolean> {
Builder withExtraContext(@Nonnull String key, @Nonnull String value);
/**
* Appends extra contexts onto the node
* Appends extra contexts onto the node.
*
* @param map a map of contexts
* @return the builder
* @see ContextSet
* @see Node#getContexts()
*/
@ -441,9 +444,10 @@ public interface Node extends Map.Entry<String, Boolean> {
Builder withExtraContext(@Nonnull Map<String, String> map);
/**
* Appends extra contexts onto the node
* Appends extra contexts onto the node.
*
* @param context a set of contexts
* @return the builder
* @see ContextSet
* @see Node#getContexts()
*/
@ -451,7 +455,7 @@ public interface Node extends Map.Entry<String, Boolean> {
Builder withExtraContext(@Nonnull Set<Map.Entry<String, String>> context);
/**
* Appends an extra context onto the node
* Appends an extra context onto the node.
*
* @param entry the context
* @return the builder
@ -462,9 +466,10 @@ public interface Node extends Map.Entry<String, Boolean> {
Builder withExtraContext(@Nonnull Map.Entry<String, String> entry);
/**
* Appends extra contexts onto the node
* Appends extra contexts onto the node.
*
* @param set a contextset
* @return the builder
* @see ContextSet
* @see Node#getContexts()
*/
@ -472,7 +477,7 @@ public interface Node extends Map.Entry<String, Boolean> {
Builder withExtraContext(@Nonnull ContextSet set);
/**
* Creates a node instance from the builder
* Creates a {@link Node} instance from the builder.
*
* @return a new node instance
*/

View File

@ -92,6 +92,7 @@ public interface NodeFactory {
/**
* Creates a node builder for the given chat meta type
*
* @param type the type
* @param priority the priority
* @param value the value for the prefix/suffix
* @return a node builder instance

View File

@ -88,8 +88,10 @@ public interface Storage {
* @param entry the log entry to be saved
* @return true if the operation completed successfully.
* @throws NullPointerException if entry is null
* @deprecated in favour of {@link ActionLogger#submit(LogEntry)}.
*/
@Nonnull
@Deprecated
CompletableFuture<Boolean> logAction(@Nonnull LogEntry entry);
/**

View File

@ -30,33 +30,40 @@ import java.util.UUID;
import javax.annotation.Nonnull;
/**
* A UUID cache for online users, between external Mojang UUIDs, and internal LuckPerms UUIDs.
* A UUID cache for online users, between external Mojang UUIDs, and internal
* LuckPerms UUIDs.
*
* <p>A user's internal LuckPerms UUID is always the same as their Mojang one,
* unless <code>use-server-uuids</code> is disabled.</p>
*
* <p>When this setting is disabled, this cache becomes active, and allows you to convert
* between 'internal' and 'server provided' uuids.</p>
* <p>When this setting is disabled, this cache becomes active, and allows you
* to convert between 'internal' and 'server provided' uuids.</p>
*
* <p><strong>This is only effective for online players. Use {@link Storage#getUUID(String)} for offline players.</strong></p>
* <p><strong>This is only effective for online players.
* Use {@link Storage#getUUID(String)} for offline players.</strong></p>
*/
public interface UuidCache {
/**
* Gets a users "internal" LuckPerms UUID, from the one given by the server.
*
* <p>When <code>use-server-uuids</code> is true, this returns the same UUID instance.</p>
* <p>When <code>use-server-uuids</code> is true, this returns the same UUID
* instance.</p>
*
* @param mojangUuid the UUID assigned by the server, through <code>Player#getUniqueId</code> or <code>ProxiedPlayer#getUniqueId</code>
* @param mojangUuid the UUID assigned by the server, through
* <code>Player#getUniqueId</code> or
* <code>ProxiedPlayer#getUniqueId</code>
* @return the corresponding internal UUID
*/
@Nonnull
UUID getUUID(@Nonnull UUID mojangUuid);
/**
* Gets a users "external", server assigned unique id, from the internal one used within LuckPerms.
* Gets a users "external", server assigned unique id, from the internal
* one used within LuckPerms.
*
* @param internalUuid the UUID used within LuckPerms, through <code>User#getUuid</code>
* @param internalUuid the UUID used within LuckPerms, through
* <code>User#getUuid</code>
* @return the corresponding external UUID
*/
@Nonnull

View File

@ -210,6 +210,7 @@ public interface CachedData {
*
* @param contexts the contexts to reload in.
* @throws NullPointerException if contexts is null
* @return a future
* @since 4.0
*/
@Nonnull
@ -237,6 +238,7 @@ public interface CachedData {
*
* @param contexts the contexts to reload in.
* @throws NullPointerException if contexts is null
* @return a future
* @since 4.0
*/
@Nonnull
@ -264,6 +266,7 @@ public interface CachedData {
*
* @param contexts the contexts to reload in.
* @throws NullPointerException if contexts is null
* @return a future
* @since 4.0
*/
@Nonnull
@ -309,6 +312,7 @@ public interface CachedData {
* <p>This method returns a Future so users can optionally choose to wait
* until the recalculation has been performed.</p>
*
* @return a future
* @since 4.0
*/
@Nonnull
@ -332,6 +336,7 @@ public interface CachedData {
* <p>This method returns a Future so users can optionally choose to wait
* until the recalculation has been performed.</p>
*
* @return a future
* @since 4.0
*/
@Nonnull

View File

@ -0,0 +1,47 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.caching;
import me.lucko.luckperms.api.Contexts;
import javax.annotation.Nonnull;
/**
* Holds cached lookup data in a specific set of contexts.
*
* @since 4.1
*/
public interface CachedDataContainer {
/**
* Gets the contexts this container is holding data for.
*
* @return the contexts this container is caching
*/
@Nonnull
Contexts getContexts();
}

View File

@ -31,15 +31,17 @@ import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
/**
* Represents the context for a meta lookup.
* Encapsulates the options and settings for a meta lookup.
*
* <p>Consisting of a standard {@link Contexts} element, plus options to define how
* <p>Consists of a standard {@link Contexts} element, plus options to define how
* the meta stack should be constructed.</p>
*
* @since 3.2
*/
@Immutable
public final class MetaContexts {
/**

View File

@ -36,11 +36,19 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Holds cached Meta lookup data for a specific set of contexts
* Holds cached meta lookup data for a specific set of contexts.
*
* @since 2.13
*/
public interface MetaData {
public interface MetaData extends CachedDataContainer {
/**
* Gets the contexts this container is holding data for.
*
* @return the contexts this container is caching
*/
@Nonnull
MetaContexts getMetaContexts();
/**
* Gets an immutable copy of the meta this user has.

View File

@ -32,14 +32,14 @@ import java.util.Map;
import javax.annotation.Nonnull;
/**
* Holds cached Permission lookup data for a specific set of contexts
* Holds cached permission lookup data for a specific set of contexts.
*
* @since 2.13
*/
public interface PermissionData {
public interface PermissionData extends CachedDataContainer {
/**
* Gets a permission value for the given permission node
* Gets a permission check result for the given permission node.
*
* @param permission the permission node
* @return a tristate result

View File

@ -25,10 +25,12 @@
package me.lucko.luckperms.api.context;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
@ -39,6 +41,17 @@ abstract class AbstractContextSet implements ContextSet {
protected abstract Multimap<String, String> backing();
@Nonnull
@Override
@Deprecated
public Map<String, String> toMap() {
ImmutableMap.Builder<String, String> m = ImmutableMap.builder();
for (Map.Entry<String, String> e : backing().entries()) {
m.put(e.getKey(), e.getValue());
}
return m.build();
}
@Override
public boolean containsKey(@Nonnull String key) {
return backing().containsKey(sanitizeKey(key));

View File

@ -40,9 +40,14 @@ import javax.annotation.Nonnull;
* on specific server implementations. In all cases, the "player" or "subject" type for
* the platform must be used.
*
* Specifically, {@code org.bukkit.entity.Player},
* {@code net.md_5.bungee.api.connection.ProxiedPlayer} and
* {@code org.spongepowered.api.service.permission.Subject}.
* Specifically:
*
* <p></p>
* <ul>
* <li>{@code org.bukkit.entity.Player}</li>
* <li>{@code net.md_5.bungee.api.connection.ProxiedPlayer}</li>
* <li>{@code org.spongepowered.api.service.permission.Subject}</li>
* </ul>
*
* @since 4.0
*/

View File

@ -35,26 +35,38 @@ import java.util.Set;
import javax.annotation.Nonnull;
/**
* A set of context pairs.
* A set of contexts.
*
* <p>You can think of ContextSets as a wrapped <code>Multimap&lt;String, String&gt;</code>.
* Each key can be mapped to multiple values.</p>
* <p>Context in the most basic sense simply means the circumstances where
* something will apply.</p>
*
* <p>Keys are automatically converted to lowercase when added, and are therefore
* case-insensitive. Values however are not.</p>
* <p>A single "context" consists of a key and a value, both strings. The key
* represents the type of context, and the value represents the setting of the
* context key.</p>
*
* <p>Implementations may be either mutable or immutable.</p>
* <p>Contexts can be combined with each other to form so called
* "context sets" - simply a collection of context pairs.</p>
*
* <p>Context keys are case-insensitive, and will be converted to
* {@link String#toLowerCase() lowercase} by all implementations.
* Values however are case-sensitive.</p>
*
* <p>Context keys and values may not be null.</p>
*
* <p>Two default ContextSet implementations are provided.
* {@link MutableContextSet} allows the addition and removal of context keys
* after construction, and {@link ImmutableContextSet} does not.</p>
*
* @since 2.13
*/
public interface ContextSet {
/**
* Creates an ImmutableContextSet from a context pair
* Creates an {@link ImmutableContextSet} from a context pair.
*
* @param key the key
* @param value the value
* @return a new ImmutableContextSet containing one KV pair
* @return a new ImmutableContextSet containing one context pair
* @throws NullPointerException if key or value is null
*/
@Nonnull
@ -63,7 +75,7 @@ public interface ContextSet {
}
/**
* Creates an ImmutableContextSet from two context pairs
* Creates an {@link ImmutableContextSet} from two context pairs.
*
* @param key1 the first key
* @param value1 the first value
@ -79,7 +91,7 @@ public interface ContextSet {
}
/**
* Creates an ImmutableContextSet from an existing iterable of Map Entries
* Creates an {@link ImmutableContextSet} from an existing {@link Iterable} of {@link Map.Entry}s.
*
* @param iterable the iterable to copy from
* @return a new ImmutableContextSet representing the pairs in the iterable
@ -91,7 +103,7 @@ public interface ContextSet {
}
/**
* Creates an ImmutableContextSet from an existing map
* Creates an {@link ImmutableContextSet} from an existing {@link Map}.
*
* @param map the map to copy from
* @return a new ImmutableContextSet representing the pairs from the map
@ -103,7 +115,7 @@ public interface ContextSet {
}
/**
* Creates an ImmutableContextSet from an existing multimap
* Creates an {@link ImmutableContextSet} from an existing {@link Multimap}.
*
* @param multimap the multimap to copy from
* @return a new ImmutableContextSet representing the pairs in the multimap
@ -116,8 +128,9 @@ public interface ContextSet {
}
/**
* Creates an new ImmutableContextSet from an existing set.
* Only really useful for converting between mutable and immutable types.
* Creates an new {@link ImmutableContextSet} from an existing {@link Set}.
*
* <p>Only really useful for converting between mutable and immutable types.</p>
*
* @param contextSet the context set to copy from
* @return a new ImmutableContextSet with the same content and the one provided
@ -129,9 +142,9 @@ public interface ContextSet {
}
/**
* Creates a new empty ImmutableContextSet.
* Returns an empty {@link ImmutableContextSet}.
*
* @return a new ImmutableContextSet
* @return an empty ImmutableContextSet
*/
@Nonnull
static ImmutableContextSet empty() {
@ -139,22 +152,30 @@ public interface ContextSet {
}
/**
* Gets if this set is in an immutable form
* Gets if this {@link ContextSet} is immutable.
*
* <p>The state of immutable instances will never change.</p>
*
* @return true if the set is immutable
*/
boolean isImmutable();
/**
* If the set is mutable, this method will return an immutable copy. Otherwise just returns itself.
* Returns an immutable representation of this {@link ContextSet}.
*
* @return an immutable ContextSet
* <p>If the set is already immutable, the same object will be returned.
* If the set is mutable, an immutable copy will be made.</p>
*
* @return an immutable representation of this set
*/
@Nonnull
ImmutableContextSet makeImmutable();
/**
* Creates a mutable copy of this set.
* Creates a mutable copy of this {@link ContextSet}.
*
* <p>A new copy is returned regardless of the
* {@link #isImmutable() mutability} of this set.</p>
*
* @return a mutable ContextSet
* @since 2.16
@ -163,7 +184,11 @@ public interface ContextSet {
MutableContextSet mutableCopy();
/**
* Converts this ContextSet to an immutable {@link Set} of {@link Map.Entry}s.
* Returns a {@link Set} of {@link Map.Entry}s representing the current
* state of this {@link ContextSet}.
*
* <p>The returned set is immutable, and is a copy of the current set.
* (will not update live)</p>
*
* @return an immutable set
*/
@ -171,10 +196,18 @@ public interface ContextSet {
Set<Map.Entry<String, String>> toSet();
/**
* Converts this ContextSet to an immutable {@link Map}
* Returns a {@link Map} <b>loosely</b> representing the current state of
* this {@link ContextSet}.
*
* <b>IMPORTANT: Use of this method may result in data being lost. ContextSets can contain lots of different values for
* one key.</b>
* <p>The returned map is immutable, and is a copy of the current set.
* (will not update live)</p>
*
* <p>As a single context key can be mapped to multiple values, this method
* may not be a true representation of the set.</p>
*
* <p>If you need a representation of the set in a Java collection instance,
* use {@link #toSet()} or {@link #toMultimap()} followed by
* {@link Multimap#asMap()}.</p>
*
* @return an immutable map
* @deprecated because the resultant map may not contain all data in the ContextSet
@ -184,7 +217,11 @@ public interface ContextSet {
Map<String, String> toMap();
/**
* Converts this ContextSet to an immutable {@link Multimap}
* Returns a {@link Multimap} representing the current state of this
* {@link ContextSet}.
*
* <p>The returned multimap is immutable, and is a copy of the current set.
* (will not update live)</p>
*
* @return a multimap
* @since 2.16
@ -193,7 +230,8 @@ public interface ContextSet {
Multimap<String, String> toMultimap();
/**
* Check if the set contains at least one value for the given key.
* Returns if the {@link ContextSet} contains at least one value for the
* given key.
*
* @param key the key to check for
* @return true if the set contains a value for the key
@ -202,9 +240,12 @@ public interface ContextSet {
boolean containsKey(@Nonnull String key);
/**
* Gets a set of all of the values mapped to the given key
* Returns a {@link Set} of the values mapped to the given key.
*
* @param key the key to find values for
* <p>The returned set is immutable, and only represents the current state
* of the {@link ContextSet}. (will not update live)</p>
*
* @param key the key to get values for
* @return a set of values
* @throws NullPointerException if the key is null
*/
@ -212,7 +253,10 @@ public interface ContextSet {
Set<String> getValues(@Nonnull String key);
/**
* Returns any value from this set matching the key, if present.
* Returns any value from this {@link ContextSet} matching the key, if present.
*
* <p>Note that context keys can be mapped to multiple values.
* Use {@link #getValues(String)} to retrieve all associated values.</p>
*
* @param key the key to find values for
* @return an optional containing any match
@ -224,22 +268,38 @@ public interface ContextSet {
}
/**
* Check if thr set contains a given key mapped to a given value
* Returns if the {@link ContextSet} contains a given context pairing.
*
* <p>This lookup is case-sensitive on the value.</p>
*
* @param key the key to look for
* @param value the value to look for (case sensitive)
* @return true if the set contains the KV pair
* @return true if the set contains the context pair
* @throws NullPointerException if the key or value is null
*/
boolean has(@Nonnull String key, @Nonnull String value);
/**
* Check if thr set contains a given key mapped to a given value
* Returns if the {@link ContextSet} contains a given context pairing,
* ignoring the case of values.
*
* <p>This lookup is case-insensitive on the value.</p>
*
* @param key the key to look for
* @param value the value to look for
* @return true if the set contains the context pair
* @throws NullPointerException if the key or value is null
*/
boolean hasIgnoreCase(@Nonnull String key, @Nonnull String value);
/**
* Returns if the {@link ContextSet} contains a given context pairing.
*
* <p>This lookup is case-sensitive on the value.</p>
*
* @param entry the entry to look for
* @return true if the set contains the KV pair
* @return true if the set contains the context pair
* @throws NullPointerException if the key or value is null
* @since 3.4
*/
default boolean has(@Nonnull Map.Entry<String, String> entry) {
Preconditions.checkNotNull(entry, "entry");
@ -247,22 +307,14 @@ public interface ContextSet {
}
/**
* Same as {@link #has(String, String)}, except ignores the case of the value.
* Returns if the {@link ContextSet} contains a given context pairing,
* ignoring the case of values.
*
* @param key the key to look for
* @param value the value to look for
* @return true if the set contains the KV pair
* @throws NullPointerException if the key or value is null
*/
boolean hasIgnoreCase(@Nonnull String key, @Nonnull String value);
/**
* Same as {@link #has(Map.Entry)}, except ignores the case of the value.
* <p>This lookup is case-insensitive on the value.</p>
*
* @param entry the entry to look for
* @return true if the set contains the KV pair
* @return true if the set contains the context pair
* @throws NullPointerException if the key or value is null
* @since 3.4
*/
default boolean hasIgnoreCase(@Nonnull Map.Entry<String, String> entry) {
Preconditions.checkNotNull(entry, "entry");
@ -270,21 +322,34 @@ public interface ContextSet {
}
/**
* Checks to see if all entries in this context set are also included in another set.
* Returns if this {@link ContextSet} is fully "satisfied" by another set.
*
* <p>For a context set to "satisfy" another, it must itself contain all of
* the context pairings in the other set.</p>
*
* <p>Mathematically, this method returns true if this set is a <b>subset</b> of the other.</p>
*
* <p>This check is case-sensitive. For a case-insensitive check,
* use {@link #isSatisfiedBy(ContextSet, boolean)}.</p>
*
* @param other the other set to check
* @return true if all entries in this set are also in the other set
* @since 3.1
*/
default boolean isSatisfiedBy(@Nonnull ContextSet other) {
return this == other || isSatisfiedBy(other, true);
return isSatisfiedBy(other, true);
}
/**
* Checks to see if all entries in this context set are also included in another set.
* Returns if this {@link ContextSet} is fully "satisfied" by another set.
*
* <p>For a context set to "satisfy" another, it must itself contain all of
* the context pairings in the other set.</p>
*
* <p>Mathematically, this method returns true if this set is a <b>subset</b> of the other.</p>
*
* @param other the other set to check
* @param caseSensitive if the lookup should be case sensitive. see {@link #has(Map.Entry)} and {@link #hasIgnoreCase(Map.Entry)}.
* @param caseSensitive if the check should be case sensitive
* @return true if all entries in this set are also in the other set
* @since 3.4
*/
@ -305,31 +370,30 @@ public interface ContextSet {
return false;
} else {
// neither are empty, we need to compare the individual entries
for (Map.Entry<String, String> pair : toSet()) {
for (Map.Entry<String, String> context : toSet()) {
if (caseSensitive) {
if (!other.has(pair)) {
if (!other.has(context)) {
return false;
}
} else {
if (!other.hasIgnoreCase(pair)) {
if (!other.hasIgnoreCase(context)) {
return false;
}
}
}
return true;
}
}
/**
* Check if the set is empty
* Returns if the {@link ContextSet} is empty.
*
* @return true if the set is empty
*/
boolean isEmpty();
/**
* Gets the number of key-value context pairs in the set
* Gets the number of context pairs in the {@link ContextSet}.
*
* @return the size of the set
*/

View File

@ -25,15 +25,14 @@
package me.lucko.luckperms.api.context;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Multimap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
import static com.google.common.base.Preconditions.checkNotNull;
@ -42,13 +41,15 @@ import static com.google.common.base.Preconditions.checkNotNull;
*
* @since 2.16
*/
@Immutable
public final class ImmutableContextSet extends AbstractContextSet implements ContextSet {
private static final ImmutableContextSet EMPTY = new ImmutableContextSet(ImmutableSetMultimap.of());
/**
* Creates a builder
* Creates an {@link ImmutableContextSet.Builder}.
*
* @return a new ImmutableContextSet builder
* @since 4.1
*/
@Nonnull
public static Builder builder() {
@ -56,11 +57,11 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
}
/**
* Creates an ImmutableContextSet from a context pair
* Creates an {@link ImmutableContextSet} from a context pair.
*
* @param key the key
* @param value the value
* @return a new ImmutableContextSet containing one KV pair
* @return a new ImmutableContextSet containing one context pair
* @throws NullPointerException if key or value is null
*/
@Nonnull
@ -69,7 +70,7 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
}
/**
* Creates an ImmutableContextSet from two context pairs
* Creates an {@link ImmutableContextSet} from two context pairs.
*
* @param key1 the first key
* @param value1 the first value
@ -90,7 +91,7 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
}
/**
* Creates an ImmutableContextSet from an existing iterable of Map Entries
* Creates an {@link ImmutableContextSet} from an existing {@link Iterable} of {@link Map.Entry}s.
*
* @param iterable the iterable to copy from
* @return a new ImmutableContextSet representing the pairs in the iterable
@ -99,22 +100,15 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
@Nonnull
public static ImmutableContextSet fromEntries(@Nonnull Iterable<? extends Map.Entry<String, String>> iterable) {
checkNotNull(iterable, "iterable");
Iterator<? extends Map.Entry<String, String>> iterator = iterable.iterator();
if (!iterator.hasNext()) {
return empty();
ImmutableContextSet.Builder builder = builder();
for (Map.Entry<String, String> entry : iterable) {
builder.add(entry);
}
ImmutableSetMultimap.Builder<String, String> b = ImmutableSetMultimap.builder();
while (iterator.hasNext()) {
Map.Entry<String, String> e = checkNotNull(iterator.next(), "entry");
b.put(sanitizeKey(e.getKey()), sanitizeValue(e.getValue()));
}
return new ImmutableContextSet(b.build());
return builder.build();
}
/**
* Creates an ImmutableContextSet from an existing map
* Creates an {@link ImmutableContextSet} from an existing {@link Map}.
*
* @param map the map to copy from
* @return a new ImmutableContextSet representing the pairs from the map
@ -126,11 +120,12 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
}
/**
* Creates an ImmutableContextSet from an existing multimap
* Creates an {@link ImmutableContextSet} from an existing {@link Multimap}.
*
* @param multimap the multimap to copy from
* @return a new ImmutableContextSet representing the pairs in the multimap
* @throws NullPointerException if the multimap is null
* @since 2.16
*/
@Nonnull
public static ImmutableContextSet fromMultimap(@Nonnull Multimap<String, String> multimap) {
@ -138,8 +133,9 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
}
/**
* Creates a new ImmutableContextSet from an existing set.
* Only really useful for converting between mutable and immutable types.
* Creates an new {@link ImmutableContextSet} from an existing {@link Set}.
*
* <p>Only really useful for converting between mutable and immutable types.</p>
*
* @param contextSet the context set to copy from
* @return a new ImmutableContextSet with the same content and the one provided
@ -151,9 +147,9 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
}
/**
* Creates an new empty ContextSet.
* Returns an empty {@link ImmutableContextSet}.
*
* @return a new ContextSet
* @return an empty ImmutableContextSet
*/
@Nonnull
public static ImmutableContextSet empty() {
@ -197,18 +193,6 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
return map.entries();
}
@Nonnull
@Override
@Deprecated
public Map<String, String> toMap() {
ImmutableMap.Builder<String, String> m = ImmutableMap.builder();
for (Map.Entry<String, String> e : map.entries()) {
m.put(e.getKey(), e.getValue());
}
return m.build();
}
@Nonnull
@Override
public Multimap<String, String> toMultimap() {
@ -226,7 +210,9 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
}
/**
* A builder for {@link ImmutableContextSet}
* A builder for {@link ImmutableContextSet}.
*
* @since 4.1
*/
public static final class Builder {
private ImmutableSetMultimap.Builder<String, String> builder;
@ -242,24 +228,32 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
return builder;
}
private void put(String key, String value) {
builder().put(key, value);
}
/**
* Adds a new key value pair to the set
* Adds a context to the set.
*
* @param key the key to add
* @param value the value to add
* @return the builder
* @throws NullPointerException if the key or value is null
* @see MutableContextSet#add(String, String)
*/
@Nonnull
public Builder add(@Nonnull String key, @Nonnull String value) {
builder().put(sanitizeKey(key), sanitizeValue(value));
put(sanitizeKey(key), sanitizeValue(value));
return this;
}
/**
* Adds a new key value pair to the set
* Adds a context to the set.
*
* @param entry the entry to add
* @return the builder
* @throws NullPointerException if the entry is null
* @see MutableContextSet#add(Map.Entry)
*/
@Nonnull
public Builder add(@Nonnull Map.Entry<String, String> entry) {
@ -269,10 +263,12 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
}
/**
* Adds an iterable containing contexts to the set
* Adds the contexts contained in the given {@link Iterable} to the set.
*
* @param iterable an iterable of key value context pairs
* @return the builder
* @throws NullPointerException if iterable is null
* @see MutableContextSet#addAll(Iterable)
*/
@Nonnull
public Builder addAll(@Nonnull Iterable<? extends Map.Entry<String, String>> iterable) {
@ -283,10 +279,12 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
}
/**
* Adds the entry set of a map to the set
* Adds the contexts contained in the given {@link Map} to the set.
*
* @param map the map to add from
* @return the builder
* @throws NullPointerException if the map is null
* @see MutableContextSet#addAll(Map)
*/
@Nonnull
public Builder addAll(@Nonnull Map<String, String> map) {
@ -295,11 +293,13 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
}
/**
* Adds the entries of a multimap to the set
* Adds the contexts contained in the given {@link Multimap} to the set.
*
* @param multimap the multimap to add from
* @return the builder
* @throws NullPointerException if the map is null
* @since 3.4
* @see MutableContextSet#addAll(Multimap)
*/
@Nonnull
public Builder addAll(@Nonnull Multimap<String, String> multimap) {
@ -308,10 +308,12 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
}
/**
* Adds of of the values in another ContextSet to this set
* Adds of of the contexts in another {@link ContextSet} to the set.
*
* @param contextSet the set to add from
* @return the builder
* @throws NullPointerException if the contextSet is null
* @see MutableContextSet#addAll(ContextSet)
*/
@Nonnull
public Builder addAll(@Nonnull ContextSet contextSet) {
@ -327,6 +329,12 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
return this;
}
/**
* Creates a {@link ImmutableContextSet} from the values previously
* added to the builder.
*
* @return an {@link ImmutableContextSet} from the builder
*/
@Nonnull
public ImmutableContextSet build() {
if (builder == null) {
@ -335,6 +343,5 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
return new ImmutableContextSet(builder.build());
}
}
}
}

View File

@ -27,7 +27,6 @@ package me.lucko.luckperms.api.context;
import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Multimap;
@ -50,11 +49,11 @@ import static com.google.common.base.Preconditions.checkNotNull;
public final class MutableContextSet extends AbstractContextSet implements ContextSet {
/**
* Make a singleton MutableContextSet from a context pair
* Creates a {@link MutableContextSet} from a context pair.
*
* @param key the key
* @param value the value
* @return a new MutableContextSet containing one KV pair
* @return a new MutableContextSet containing one context pair
* @throws NullPointerException if key or value is null
*/
@Nonnull
@ -67,7 +66,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
}
/**
* Makes a MutableContextSet from two context pairs
* Creates a {@link MutableContextSet} from two context pairs.
*
* @param key1 the first key
* @param value1 the first value
@ -90,7 +89,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
}
/**
* Creates a MutableContextSet from an existing iterable of Map Entries
* Creates a {@link MutableContextSet} from an existing {@link Iterable} of {@link Map.Entry}s.
*
* @param iterable the iterable to copy from
* @return a new MutableContextSet representing the pairs in the iterable
@ -105,7 +104,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
}
/**
* Creates a MutableContextSet from an existing map
* Creates a {@link MutableContextSet} from an existing {@link Map}.
*
* @param map the map to copy from
* @return a new MutableContextSet representing the pairs from the map
@ -120,11 +119,12 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
}
/**
* Creates a MutableContextSet from an existing multimap
* Creates a {@link MutableContextSet} from an existing {@link Multimap}.
*
* @param multimap the multimap to copy from
* @return a new MutableContextSet representing the pairs in the multimap
* @throws NullPointerException if the multimap is null
* @since 2.16
*/
@Nonnull
public static MutableContextSet fromMultimap(@Nonnull Multimap<String, String> multimap) {
@ -135,8 +135,9 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
}
/**
* Creates a new MutableContextSet from an existing set.
* Only really useful for converting between mutable and immutable types.
* Creates a new {@link MutableContextSet} from an existing {@link Set}.
*
* <p>Only really useful for converting between mutable and immutable types.</p>
*
* @param contextSet the context set to copy from
* @return a new MutableContextSet with the same content and the one provided
@ -183,6 +184,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
@Nonnull
@Override
public ImmutableContextSet makeImmutable() {
// if the map is empty, don't create a new instance
if (map.isEmpty()) {
return ImmutableContextSet.empty();
}
@ -201,17 +203,6 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
return ImmutableSet.copyOf(map.entries());
}
@Nonnull
@Override
@Deprecated
public Map<String, String> toMap() {
ImmutableMap.Builder<String, String> m = ImmutableMap.builder();
for (Map.Entry<String, String> e : map.entries()) {
m.put(e.getKey(), e.getValue());
}
return m.build();
}
@Nonnull
@Override
public Multimap<String, String> toMultimap() {
@ -219,7 +210,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
}
/**
* Adds a new key value pair to the set
* Adds a context to this set.
*
* @param key the key to add
* @param value the value to add
@ -230,7 +221,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
}
/**
* Adds a new key value pair to the set
* Adds a context to this set.
*
* @param entry the entry to add
* @throws NullPointerException if the entry is null
@ -241,7 +232,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
}
/**
* Adds an iterable containing contexts to the set
* Adds the contexts contained in the given {@link Iterable} to this set.
*
* @param iterable an iterable of key value context pairs
* @throws NullPointerException if iterable is null
@ -253,7 +244,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
}
/**
* Adds the entry set of a map to the set
* Adds the contexts contained in the given {@link Map} to this set.
*
* @param map the map to add from
* @throws NullPointerException if the map is null
@ -263,7 +254,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
}
/**
* Adds the entries of a multimap to the set
* Adds the contexts contained in the given {@link Multimap} to this set.
*
* @param multimap the multimap to add from
* @throws NullPointerException if the map is null
@ -274,7 +265,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
}
/**
* Adds of of the values in another ContextSet to this set
* Adds of of the contexts in another {@link ContextSet} to this set.
*
* @param contextSet the set to add from
* @throws NullPointerException if the contextSet is null
@ -290,7 +281,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
}
/**
* Remove a key value pair from this set
* Removes a context from this set.
*
* @param key the key to remove
* @param value the value to remove (case sensitive)
@ -301,7 +292,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
}
/**
* Same as {@link #remove(String, String)}, except ignores the case of the value
* Removes a context from this set. (case-insensitive)
*
* @param key the key to remove
* @param value the value to remove
@ -316,7 +307,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
}
/**
* Removes all pairs with the given key
* Removes all contexts from this set with the given key.
*
* @param key the key to remove
* @throws NullPointerException if the key is null
@ -326,7 +317,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
}
/**
* Clears the set
* Removes all contexts from the set.
*/
public void clear() {
map.clear();

View File

@ -42,4 +42,35 @@ public interface Cancellable {
@Nonnull
AtomicBoolean getCancellationState();
/**
* Returns true if the event is currently cancelled.
*
* @return if the event is cancelled
* @since 4.1
*/
default boolean isCancelled() {
return getCancellationState().get();
}
/**
* Returns true if the event is not currently cancelled.
*
* @return if the event is not cancelled
* @since 4.1
*/
default boolean isNotCancelled() {
return !isCancelled();
}
/**
* Sets the cancellation state of the event.
*
* @param cancelled the new state
* @return the previous state
* @since 4.1
*/
default boolean setCancelled(boolean cancelled) {
return getCancellationState().getAndSet(cancelled);
}
}

View File

@ -31,14 +31,16 @@ import java.util.function.Consumer;
import javax.annotation.Nonnull;
/**
* The LuckPerms event bus. Used for subscribing (or registering listeners) to events.
* The internal LuckPerms event bus.
*
* <p>LuckPerms events are posted to any listeners registered with the bus.</p>
*
* @since 3.0
*/
public interface EventBus {
/**
* Subscribe to an event
* Subscribes to an event.
*
* @param eventClass the event class
* @param handler the event handler
@ -49,7 +51,7 @@ public interface EventBus {
<T extends LuckPermsEvent> EventHandler<T> subscribe(@Nonnull Class<T> eventClass, @Nonnull Consumer<T> handler);
/**
* Gets a set of all registered handlers for a given event
* Gets a set of all registered handlers for a given event.
*
* @param eventClass the event to find handlers for
* @param <T> the event class

View File

@ -34,7 +34,7 @@ import javax.annotation.Nonnull;
*
* @param <T> the event class
*/
public interface EventHandler<T extends LuckPermsEvent> {
public interface EventHandler<T extends LuckPermsEvent> extends AutoCloseable {
/**
* Gets the class this handler is listening to
@ -73,4 +73,8 @@ public interface EventHandler<T extends LuckPermsEvent> {
*/
int getCallCount();
@Override
default void close() {
unregister();
}
}

View File

@ -30,7 +30,7 @@ import me.lucko.luckperms.api.LuckPermsApi;
import javax.annotation.Nonnull;
/**
* The base event interface
* A superinterface for all LuckPerms events.
*
* @since 3.0
*/

View File

@ -61,12 +61,17 @@ public interface LogBroadcastEvent extends LuckPermsEvent, Cancellable {
enum Origin {
/**
* Represents a log entry which originated from the current server instance
* Marks a log entry which originated from the current server instance
*/
LOCAL,
/**
* Represents a log entry which was sent to this server via the messaging service
* Marks a log entry which originated from an API call on the current server instance
*/
LOCAL_API,
/**
* Marks a log entry which was sent to this server via the messaging service
*/
REMOTE
}

View File

@ -0,0 +1,113 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.log;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.event.Cancellable;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import java.util.Optional;
import java.util.UUID;
import javax.annotation.Nonnull;
/**
* Called when a log entry is about to be sent to specific notifiable object on
* the platform.
*
* <p>This event is not called for players without the notify permission,
* but is called for objects which are ignoring log notifications (called with
* the cancelled flag set to true).</p>
*
* @since 4.1
*/
public interface LogNotifyEvent extends LuckPermsEvent, Cancellable {
/**
* Gets the log entry to be sent
*
* @return the log entry to be sent
*/
@Nonnull
LogEntry getEntry();
/**
* Gets where the log entry originated from.
*
* @return the origin of the log
*/
@Nonnull
LogBroadcastEvent.Origin getOrigin();
/**
* Gets the object to be notified.
*
* @return the object to notify
*/
@Nonnull
Notifiable getNotifiable();
/**
* Represents an object which could be notified as a result of a
* {@link LogNotifyEvent}.
*/
interface Notifiable {
/**
* Gets a {@link UUID} for the object, if it has one.
*
* <p>For Players, this method returns their unique id.</p>
*
* @return the uuid of the object, if available
*/
@Nonnull
Optional<UUID> getUuid();
/**
* Gets the name of the object
*
* @return the name
*/
@Nonnull
String getName();
/**
* Gets if the object is a console
*
* @return if the object is a console
*/
boolean isConsole();
/**
* Gets if the object is a player
*
* @return if the object is a player
*/
boolean isPlayer();
}
}

View File

@ -28,6 +28,7 @@ package me.lucko.luckperms.api.metastacking;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
/**
* Represents a meta stack model, consisting of a chain of elements, separated by spacers.
@ -40,6 +41,7 @@ import javax.annotation.Nonnull;
*
* @since 2.3
*/
@Immutable
public interface MetaStackDefinition {
/**

View File

@ -33,12 +33,16 @@ import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
/**
* Represents an element within a {@link MetaStackDefinition}.
*
* <p>The element itself does not contain any mutable state.</p>
*
* @since 3.2
*/
@Immutable
public interface MetaStackElement {
/**

View File

@ -42,6 +42,21 @@ import java.util.Optional;
public class LogDispatcher {
private final LuckPermsPlugin plugin;
private void broadcast(ExtendedLogEntry entry, LogBroadcastEvent.Origin origin, Sender sender) {
plugin.getOnlineSenders()
.filter(CommandPermission.LOG_NOTIFY::isAuthorized)
.filter(s -> {
boolean shouldCancel = LogNotify.isIgnoring(plugin, s.getUuid()) || (sender != null && s.getUuid().equals(sender.getUuid()));
return !plugin.getApiProvider().getEventFactory().handleLogNotify(shouldCancel, entry, origin, s);
})
.forEach(s -> Message.LOG.send(s,
entry.getActorFriendlyString(),
Character.toString(entry.getType().getCode()),
entry.getActedFriendlyString(),
entry.getAction()
));
}
public void dispatch(ExtendedLogEntry entry, Sender sender) {
// set the event to cancelled if the sender is import
if (!plugin.getApiProvider().getEventFactory().handleLogPublish(sender.isImport(), entry)) {
@ -58,35 +73,37 @@ public class LogDispatcher {
messagingService.get().pushLog(entry);
}
if (!plugin.getApiProvider().getEventFactory().handleLogBroadcast(!plugin.getConfiguration().get(ConfigKeys.LOG_NOTIFY), entry, LogBroadcastEvent.Origin.LOCAL)) {
plugin.getOnlineSenders()
.filter(CommandPermission.LOG_NOTIFY::isAuthorized)
.filter(s -> !LogNotify.isIgnoring(plugin, s.getUuid()))
.filter(s -> !s.getUuid().equals(sender.getUuid()))
.forEach(s -> Message.LOG.send(s,
entry.getActorFriendlyString(),
Character.toString(entry.getType().getCode()),
entry.getActedFriendlyString(),
entry.getAction()
));
boolean shouldCancel = !plugin.getConfiguration().get(ConfigKeys.LOG_NOTIFY);
if (!plugin.getApiProvider().getEventFactory().handleLogBroadcast(shouldCancel, entry, LogBroadcastEvent.Origin.LOCAL)) {
broadcast(entry, LogBroadcastEvent.Origin.LOCAL, sender);
}
}
public void dispatchFromApi(ExtendedLogEntry entry) {
if (!plugin.getApiProvider().getEventFactory().handleLogPublish(false, entry)) {
try {
plugin.getStorage().logAction(entry).get();
} catch (Exception e) {
e.printStackTrace();
}
}
broadcastFromApi(entry);
}
public void broadcastFromApi(ExtendedLogEntry entry) {
plugin.getMessagingService().ifPresent(extendedMessagingService -> extendedMessagingService.pushLog(entry));
boolean shouldCancel = !plugin.getConfiguration().get(ConfigKeys.LOG_NOTIFY);
if (!plugin.getApiProvider().getEventFactory().handleLogBroadcast(shouldCancel, entry, LogBroadcastEvent.Origin.LOCAL_API)) {
broadcast(entry, LogBroadcastEvent.Origin.LOCAL_API, null);
}
}
public void dispatchFromRemote(ExtendedLogEntry entry) {
if (!plugin.getConfiguration().get(ConfigKeys.BROADCAST_RECEIVED_LOG_ENTRIES)) {
return;
}
if (!plugin.getApiProvider().getEventFactory().handleLogBroadcast(!plugin.getConfiguration().get(ConfigKeys.LOG_NOTIFY), entry, LogBroadcastEvent.Origin.REMOTE)) {
plugin.getOnlineSenders()
.filter(CommandPermission.LOG_NOTIFY::isAuthorized)
.filter(s -> !LogNotify.isIgnoring(plugin, s.getUuid()))
.forEach(s -> Message.LOG.send(s,
entry.getActorFriendlyString(),
Character.toString(entry.getType().getCode()),
entry.getActedFriendlyString(),
entry.getAction()
));
boolean shouldCancel = !plugin.getConfiguration().get(ConfigKeys.BROADCAST_RECEIVED_LOG_ENTRIES) || !plugin.getConfiguration().get(ConfigKeys.LOG_NOTIFY);
if (!plugin.getApiProvider().getEventFactory().handleLogBroadcast(shouldCancel, entry, LogBroadcastEvent.Origin.REMOTE)) {
broadcast(entry, LogBroadcastEvent.Origin.LOCAL_API, null);
}
}
}

View File

@ -28,8 +28,8 @@ package me.lucko.luckperms.common.api;
import lombok.AccessLevel;
import lombok.Getter;
import me.lucko.luckperms.api.ActionLogger;
import me.lucko.luckperms.api.LPConfiguration;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.LuckPermsApi;
import me.lucko.luckperms.api.MessagingService;
import me.lucko.luckperms.api.NodeFactory;
@ -42,11 +42,11 @@ import me.lucko.luckperms.api.manager.TrackManager;
import me.lucko.luckperms.api.manager.UserManager;
import me.lucko.luckperms.api.metastacking.MetaStackFactory;
import me.lucko.luckperms.api.platform.PlatformInfo;
import me.lucko.luckperms.common.actionlog.ExtendedLogEntry;
import me.lucko.luckperms.common.api.delegates.manager.ApiContextManager;
import me.lucko.luckperms.common.api.delegates.manager.ApiGroupManager;
import me.lucko.luckperms.common.api.delegates.manager.ApiTrackManager;
import me.lucko.luckperms.common.api.delegates.manager.ApiUserManager;
import me.lucko.luckperms.common.api.delegates.misc.ApiActionLogger;
import me.lucko.luckperms.common.api.delegates.misc.ApiMetaStackFactory;
import me.lucko.luckperms.common.api.delegates.misc.ApiNodeFactory;
import me.lucko.luckperms.common.api.delegates.misc.ApiPlatformInfo;
@ -71,6 +71,7 @@ public class ApiProvider implements LuckPermsApi {
private final GroupManager groupManager;
private final TrackManager trackManager;
private final LuckPermsEventBus eventBus;
private final ActionLogger actionLogger;
private final ContextManager contextManager;
private final MetaStackFactory metaStackFactory;
private final EventFactory eventFactory;
@ -83,6 +84,7 @@ public class ApiProvider implements LuckPermsApi {
this.groupManager = new ApiGroupManager(plugin.getGroupManager());
this.trackManager = new ApiTrackManager(plugin.getTrackManager());
this.eventBus = new LuckPermsEventBus(plugin);
this.actionLogger = new ApiActionLogger(plugin);
this.contextManager = new ApiContextManager(plugin, plugin.getContextManager());
this.metaStackFactory = new ApiMetaStackFactory(plugin);
this.eventFactory = new EventFactory(eventBus);
@ -137,6 +139,11 @@ public class ApiProvider implements LuckPermsApi {
return plugin.getMessagingService().map(Function.identity());
}
@Override
public ActionLogger getActionLogger() {
return actionLogger;
}
@Override
public UuidCache getUuidCache() {
return plugin.getUuidCache().getDelegate();
@ -157,8 +164,4 @@ public class ApiProvider implements LuckPermsApi {
return metaStackFactory;
}
@Override
public LogEntry.Builder newLogEntryBuilder() {
return ExtendedLogEntry.build();
}
}

View File

@ -0,0 +1,67 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.misc;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.api.ActionLogger;
import me.lucko.luckperms.api.Log;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.common.actionlog.ExtendedLogEntry;
import me.lucko.luckperms.common.api.delegates.model.ApiLog;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import java.util.concurrent.CompletableFuture;
@RequiredArgsConstructor
public class ApiActionLogger implements ActionLogger {
private final LuckPermsPlugin plugin;
@Override
public LogEntry.Builder newEntryBuilder() {
return ExtendedLogEntry.build();
}
@Override
public CompletableFuture<Log> getLog() {
return plugin.getStorage().noBuffer().getLog().thenApply(log -> log == null ? null : new ApiLog(log));
}
@Override
public CompletableFuture<Void> submit(LogEntry entry) {
return CompletableFuture.runAsync(() -> plugin.getLogDispatcher().dispatchFromApi((ExtendedLogEntry) entry), plugin.getScheduler().async());
}
@Override
public CompletableFuture<Void> submitToStorage(LogEntry entry) {
return plugin.getStorage().noBuffer().logAction(entry);
}
@Override
public CompletableFuture<Void> broadcastAction(LogEntry entry) {
return CompletableFuture.runAsync(() -> plugin.getLogDispatcher().broadcastFromApi((ExtendedLogEntry) entry), plugin.getScheduler().async());
}
}

View File

@ -108,7 +108,7 @@ public abstract class HolderCachedData<T extends PermissionHolder> implements Ca
*/
private MetaCache calculateMeta(@NonNull MetaContexts contexts, MetaCache data) {
if (data == null) {
data = new MetaCache();
data = new MetaCache(contexts);
}
if (contexts.getContexts() == Contexts.allowAll()) {

View File

@ -27,13 +27,15 @@ package me.lucko.luckperms.common.caching.type;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ListMultimap;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.caching.MetaContexts;
import me.lucko.luckperms.api.caching.MetaData;
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
import me.lucko.luckperms.common.metastacking.MetaStack;
@ -48,11 +50,16 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
* Holds cached meta for a given context
*/
@Getter
@NoArgsConstructor
@RequiredArgsConstructor
public class MetaCache implements MetaData {
@Getter(AccessLevel.NONE)
private final ReadWriteLock lock = new ReentrantReadWriteLock();
/**
* The contexts this container is holding data for
*/
private final MetaContexts metaContexts;
private ListMultimap<String, String> metaMultimap = ImmutableListMultimap.of();
private Map<String, String> meta = ImmutableMap.of();
private SortedMap<Integer, String> prefixes = ImmutableSortedMap.of();
@ -118,4 +125,9 @@ public class MetaCache implements MetaData {
return suffixStack.getDefinition();
}
@Override
public Contexts getContexts() {
return metaContexts.getContexts();
}
}

View File

@ -25,6 +25,7 @@
package me.lucko.luckperms.common.caching.type;
import lombok.Getter;
import lombok.NonNull;
import me.lucko.luckperms.api.Contexts;
@ -44,6 +45,12 @@ import java.util.concurrent.ConcurrentHashMap;
*/
public class PermissionCache implements PermissionData {
/**
* The contexts this container is holding data for
*/
@Getter
private final Contexts contexts;
/**
* The raw set of permission strings.
*/
@ -62,6 +69,7 @@ public class PermissionCache implements PermissionData {
private final PermissionCalculator calculator;
public PermissionCache(Contexts contexts, PermissionCalculatorMetadata metadata, CalculatorFactory calculatorFactory) {
this.contexts = contexts;
permissions = new ConcurrentHashMap<>();
permissionsUnmodifiable = Collections.unmodifiableMap(permissions);

View File

@ -38,6 +38,7 @@ import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.cause.CreationCause;
import me.lucko.luckperms.api.event.cause.DeletionCause;
import me.lucko.luckperms.api.event.log.LogBroadcastEvent;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.event.impl.EventConfigReload;
import me.lucko.luckperms.common.event.impl.EventGroupCacheLoad;
import me.lucko.luckperms.common.event.impl.EventGroupCreate;
@ -47,6 +48,7 @@ import me.lucko.luckperms.common.event.impl.EventGroupLoad;
import me.lucko.luckperms.common.event.impl.EventGroupLoadAll;
import me.lucko.luckperms.common.event.impl.EventLogBroadcast;
import me.lucko.luckperms.common.event.impl.EventLogNetworkPublish;
import me.lucko.luckperms.common.event.impl.EventLogNotify;
import me.lucko.luckperms.common.event.impl.EventLogPublish;
import me.lucko.luckperms.common.event.impl.EventLogReceive;
import me.lucko.luckperms.common.event.impl.EventNodeAdd;
@ -142,6 +144,13 @@ public final class EventFactory {
return cancel.get();
}
public boolean handleLogNotify(boolean initialState, LogEntry entry, LogBroadcastEvent.Origin origin, Sender sender) {
AtomicBoolean cancel = new AtomicBoolean(initialState);
EventLogNotify event = new EventLogNotify(cancel, entry, origin, sender);
fireEvent(event);
return cancel.get();
}
public void handleLogReceive(UUID id, LogEntry entry) {
EventLogReceive event = new EventLogReceive(id, entry);
fireEventAsync(event);

View File

@ -0,0 +1,93 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.common.event.impl;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.event.log.LogBroadcastEvent;
import me.lucko.luckperms.api.event.log.LogNotifyEvent;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.event.AbstractEvent;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
@Getter
@ToString
@RequiredArgsConstructor
public class EventLogNotify extends AbstractEvent implements LogNotifyEvent {
private final AtomicBoolean cancellationState;
private final LogEntry entry;
private final LogBroadcastEvent.Origin origin;
private final Sender sender;
@Getter(AccessLevel.NONE)
private Notifiable notifiable;
@Override
public synchronized Notifiable getNotifiable() {
if (notifiable == null) {
notifiable = new SenderNotifiable(sender);
}
return notifiable;
}
@AllArgsConstructor
private static final class SenderNotifiable implements Notifiable {
private final Sender sender;
@Override
public Optional<UUID> getUuid() {
if (sender.isConsole()) {
return Optional.empty();
}
return Optional.of(sender.getUuid());
}
@Override
public String getName() {
return sender.getName();
}
@Override
public boolean isConsole() {
return sender.isConsole();
}
@Override
public boolean isPlayer() {
return !sender.isConsole();
}
}
}