getTracks() {
- return getTrackManager().getLoadedTracks();
- }
-
- /**
- * Check if a track is loaded in memory
- *
- * @param name the name to check for
- * @return true if the track is loaded
- * @throws NullPointerException if the name is null
- */
- default boolean isTrackLoaded(@NonNull String name) {
- return getTrackManager().isLoaded(name);
- }
-
- /**
- * Returns a new LogEntry Builder instance
- *
- * @return a new builder
- * @since 4.0
- */
- default LogEntry.@NonNull Builder newLogEntryBuilder() {
- return getActionLogger().newEntryBuilder();
- }
-
- /**
- * Returns a permission builder instance
- *
- * @param permission the main permission node to build
- * @return a {@link Node.Builder} instance
- * @throws IllegalArgumentException if the permission is invalid
- * @throws NullPointerException if the permission is null
- * @since 2.6
- */
- default Node.@NonNull Builder buildNode(@NonNull String permission) throws IllegalArgumentException {
- return getNodeFactory().newBuilder(permission);
- }
-
- /**
- * Register a custom context calculator to the server
- *
- * @param calculator the context calculator to register. The type MUST be the player class of the platform.
- * @throws ClassCastException if the type is not the player class of the platform.
- */
- default void registerContextCalculator(@NonNull ContextCalculator> calculator) {
- getContextManager().registerCalculator(calculator);
- }
-
- /**
- * Gets a calculated context instance for the user using the rules of the platform.
- *
- * These values are calculated using the options in the configuration, and the provided calculators.
- *
- * @param user the user to get contexts for
- * @return an optional containing contexts. Will return empty if the user is not online.
- */
- default @NonNull Optional getContextForUser(@NonNull User user) {
- return getContextManager().lookupApplicableContexts(user);
- }
-
- /**
- * Gets set of contexts applicable to a player using the platforms {@link ContextCalculator}s.
- *
- * @param player the player to calculate for. Must be the player instance for the platform.
- * @return a set of contexts.
- * @since 2.17
- */
- default @NonNull ContextSet getContextForPlayer(@NonNull Object player) {
- return getContextManager().getApplicableContext(player);
- }
-
- /**
- * Gets a Contexts instance for the player using the platforms {@link ContextCalculator}s.
- *
- * @param player the player to calculate for. Must be the player instance for the platform.
- * @return a set of contexts.
- * @since 3.3
- */
- default @NonNull Contexts getContextsForPlayer(@NonNull Object player) {
- return getContextManager().getApplicableContexts(player);
- }
-
-}
diff --git a/api/src/main/java/me/lucko/luckperms/LuckPerms.java b/api/src/main/java/me/lucko/luckperms/api/LuckPermsProvider.java
similarity index 57%
rename from api/src/main/java/me/lucko/luckperms/LuckPerms.java
rename to api/src/main/java/me/lucko/luckperms/api/LuckPermsProvider.java
index a3f806075..6a5cef019 100644
--- a/api/src/main/java/me/lucko/luckperms/LuckPerms.java
+++ b/api/src/main/java/me/lucko/luckperms/api/LuckPermsProvider.java
@@ -23,25 +23,21 @@
* SOFTWARE.
*/
-package me.lucko.luckperms;
-
-import me.lucko.luckperms.api.LuckPermsApi;
+package me.lucko.luckperms.api;
import org.checkerframework.checker.nullness.qual.NonNull;
-import java.util.Optional;
-
/**
- * Provides static access to the {@link LuckPermsApi}.
+ * Provides static access to the {@link LuckPerms} service.
*
- * Ideally, the ServiceManager for the platform should be used to obtain an instance,
- * however, this provider can be used if you need static access.
+ * Ideally, the ServiceManager for the platform should be used to obtain an
+ * instance, however, this provider can be used if you need static access.
*/
-public final class LuckPerms {
- private static LuckPermsApi instance = null;
+public final class LuckPermsProvider {
+ private static LuckPerms instance = null;
/**
- * Gets an instance of the {@link LuckPermsApi},
+ * Gets an instance of the {@link LuckPerms} service,
* throwing {@link IllegalStateException} if an instance is not yet loaded.
*
* Will never return null.
@@ -49,43 +45,22 @@ public final class LuckPerms {
* @return an api instance
* @throws IllegalStateException if the api is not loaded
*/
- public static @NonNull LuckPermsApi getApi() {
+ public static @NonNull LuckPerms get() {
if (instance == null) {
- throw new IllegalStateException("API is not loaded.");
+ throw new IllegalStateException("The LuckPerms API is not loaded.");
}
return instance;
}
- /**
- * Gets an instance of {@link LuckPermsApi}, if it is loaded.
- *
- * Unlike {@link LuckPerms#getApi}, this method will not throw an
- * {@link IllegalStateException} if an instance is not yet loaded, rather return
- * an empty {@link Optional}.
- *
- * @return an optional api instance
- */
- public static @NonNull Optional getApiSafe() {
- return Optional.ofNullable(instance);
+ static void register(LuckPerms instance) {
+ LuckPermsProvider.instance = instance;
}
- /**
- * Registers an instance of the {@link LuckPermsApi} with this provider.
- *
- * @param instance the instance
- */
- static void registerProvider(LuckPermsApi instance) {
- LuckPerms.instance = instance;
+ static void unregister() {
+ LuckPermsProvider.instance = null;
}
- /**
- * Removes the current instance from this provider.
- */
- static void unregisterProvider() {
- LuckPerms.instance = null;
- }
-
- private LuckPerms() {
+ private LuckPermsProvider() {
throw new UnsupportedOperationException("This class cannot be instantiated.");
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/MutateResult.java b/api/src/main/java/me/lucko/luckperms/api/MutateResult.java
deleted file mode 100644
index e2ca32e1c..000000000
--- a/api/src/main/java/me/lucko/luckperms/api/MutateResult.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * This file is part of LuckPerms, licensed under the MIT License.
- *
- * Copyright (c) lucko (Luck)
- * 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;
-
-/**
- * Represents the result to a "mutation" on an object.
- *
- * @since 4.2
- */
-public interface MutateResult {
-
- /**
- * Instance of {@link MutateResult} which always reports success.
- */
- MutateResult GENERIC_SUCCESS = () -> true;
-
- /**
- * Instance of {@link MutateResult} which always reports failure.
- */
- MutateResult GENERIC_FAILURE = () -> false;
-
- /**
- * Gets if the operation which produced this result completed successfully.
- *
- * @return if the result indicates a success
- */
- boolean wasSuccess();
-
- /**
- * Gets if the operation which produced this result failed.
- *
- * @return if the result indicates a failure
- */
- default boolean wasFailure() {
- return !wasSuccess();
- }
-
- /**
- * Gets a boolean representation of the result.
- *
- * A value of true
marks that the operation {@link #wasSuccess() was a success}
- * and a value of false
marks that the operation
- * {@link #wasFailure() was a failure}.
- *
- * @return a boolean representation
- */
- default boolean asBoolean() {
- return wasSuccess();
- }
-
-}
diff --git a/api/src/main/java/me/lucko/luckperms/api/Node.java b/api/src/main/java/me/lucko/luckperms/api/Node.java
deleted file mode 100644
index 5339bbe78..000000000
--- a/api/src/main/java/me/lucko/luckperms/api/Node.java
+++ /dev/null
@@ -1,670 +0,0 @@
-/*
- * This file is part of LuckPerms, licensed under the MIT License.
- *
- * Copyright (c) lucko (Luck)
- * 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 com.google.common.base.Preconditions;
-
-import me.lucko.luckperms.api.context.ContextSet;
-import me.lucko.luckperms.api.nodetype.NodeType;
-import me.lucko.luckperms.api.nodetype.NodeTypeKey;
-import me.lucko.luckperms.api.nodetype.types.DisplayNameType;
-import me.lucko.luckperms.api.nodetype.types.InheritanceType;
-import me.lucko.luckperms.api.nodetype.types.MetaType;
-import me.lucko.luckperms.api.nodetype.types.PrefixType;
-import me.lucko.luckperms.api.nodetype.types.SuffixType;
-import me.lucko.luckperms.api.nodetype.types.WeightType;
-
-import org.checkerframework.checker.nullness.qual.NonNull;
-import org.checkerframework.checker.nullness.qual.Nullable;
-
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Stream;
-
-/**
- * Represents a LuckPerms "node".
- *
- * The {@link Node} class encapsulates more than just permission assignments.
- * Nodes are used to store data about inherited groups, as well as assigned
- * prefixes, suffixes and meta values.
- *
- * Combining these various states into one object (a "node") means that a
- * holder only has to have one type of data set (a set of nodes) in order to
- * take on various properties.
- *
- * It is recommended that users of the API make use of {@link Stream}s
- * to manipulate data and obtain the required information.
- *
- * This interface provides a number of methods to read the attributes of the
- * node, as well as methods to query and extract additional state and properties
- * from these settings.
- *
- * Nodes have the following attributes:
- *
- *
- * {@link #getPermission() permission} - the actual permission string
- * {@link #getValue() value} - the value of the node (false for negated)
- * {@link #isOverride() override} - if the node is marked as having special priority over other nodes
- * {@link #getServer() server} - the specific server where this node should apply
- * {@link #getWorld() world} - the specific world where this node should apply
- * {@link #getContexts() context} - the additional contexts required for this node to apply
- * {@link #getExpiry() expiry} - the time when this node should expire
- *
- *
- * The 'permission' property of a {@link Node} is also used in some cases to represent state
- * beyond a granted permission. This state is encapsulated by extra {@link NodeType} data which
- * can be obtained from this instance using {@link #getTypeData(NodeTypeKey)}.
- *
- * Type data is mapped by {@link NodeTypeKey}s, which are usually stored as static members of the
- * corresponding {@link NodeType} class under the KEY
field.
- *
- * The current types are:
- *
- *
- * normal - just a regular permission
- * {@link InheritanceType} - an "inheritance node" marks that the holder should inherit data from another group
- * {@link PrefixType} - represents an assigned prefix
- * {@link SuffixType} - represents an assigned suffix
- * {@link MetaType} - represents an assigned meta option
- * {@link WeightType} - marks the weight of the object holding this node
- * {@link DisplayNameType} - marks the display name of the object holding this node
- *
- *
- * The core node state must be immutable in all implementations.
- *
- * @see NodeFactory for obtaining and constructing instances.
- * @since 2.6
- */
-public interface Node {
-
- /**
- * Gets the permission string this node encapsulates.
- *
- * The exact value of this string may vary for nodes which aren't regular
- * permission settings.
- *
- * @return the actual permission node
- */
- @NonNull String getPermission();
-
- /**
- * Gets the value of the node.
- *
- * A negated setting would result in a value of false
.
- *
- * @return the nodes value
- */
- boolean getValue();
-
- /**
- * Gets the value of this node as a {@link Tristate}.
- *
- * @return the value of this node as a Tristate
- */
- default @NonNull Tristate getTristate() {
- return Tristate.fromBoolean(getValue());
- }
-
- /**
- * Gets if the node is negated.
- *
- * This is the inverse of the {@link #getValue() value}.
- *
- * @return true if the node is negated
- */
- default boolean isNegated() {
- return !getValue();
- }
-
- /**
- * Gets if this node is set to override explicitly.
- *
- * This value does not persist across saves, and is therefore only
- * useful for transient nodes.
- *
- * @return true if this node is set to override explicitly
- */
- boolean isOverride();
-
- /**
- * Gets the server this node applies on, if the node is server specific.
- *
- * @return an {@link Optional} containing the server, if one is defined
- */
- @NonNull Optional getServer();
-
- /**
- * Gets the world this node applies on, if the node is world specific.
- *
- * @return an {@link Optional} containing the world, if one is defined
- */
- @NonNull Optional getWorld();
-
- /**
- * Gets if this node is server specific.
- *
- * @return true if this node is server specific
- */
- boolean isServerSpecific();
-
- /**
- * Gets if this node is server specific.
- *
- * @return true if this node is server specific
- */
- boolean isWorldSpecific();
-
- /**
- * Gets if this node applies globally, and therefore has no specific context.
- *
- * @return true if this node applies globally, and has no specific context
- * @since 3.1
- */
- boolean appliesGlobally();
-
- /**
- * Gets if this node has any specific context in order for it to apply.
- *
- * @return true if this node has specific context
- * @since 3.1
- */
- boolean hasSpecificContext();
-
- /**
- * Gets if this node should apply in the given context
- *
- * @param contextSet the context set
- * @return true if the node should apply
- * @since 2.13
- */
- boolean shouldApplyWithContext(@NonNull ContextSet contextSet);
-
- /**
- * Resolves any shorthand parts of this node and returns the full list of
- * resolved nodes.
- *
- * The list will not contain the exact permission itself.
- *
- * @return a list of full nodes
- */
- @NonNull List resolveShorthand();
-
- /**
- * Gets if this node is assigned temporarily.
- *
- * @return true if this node will expire in the future
- */
- boolean isTemporary();
-
- /**
- * Gets if this node is permanent (will not expire).
- *
- * @return true if this node will not expire
- */
- default boolean isPermanent() {
- return !isTemporary();
- }
-
- /**
- * Gets the unix timestamp (in seconds) when this node will expire.
- *
- * @return the time in Unix time when this node will expire
- * @throws IllegalStateException if the node is not temporary
- */
- long getExpiryUnixTime() throws IllegalStateException;
-
- /**
- * Gets the date when this node will expire.
- *
- * @return the {@link Date} when this node will expire
- * @throws IllegalStateException if the node is not temporary
- */
- @NonNull Date getExpiry() throws IllegalStateException;
-
- /**
- * Gets the number of seconds until this permission will expire.
- *
- * Will return a negative value if the node has already expired.
- *
- * @return the number of seconds until this permission will expire
- * @throws IllegalStateException if the node is not temporary
- */
- long getSecondsTilExpiry() throws IllegalStateException;
-
- /**
- * Gets if the node has expired.
- *
- * This returns false if the node is not temporary.
- *
- * @return true if this node has expired
- */
- boolean hasExpired();
-
- /**
- * Gets the extra contexts required for this node to apply.
- *
- * @return the extra contexts required for this node to apply
- * @since 2.13
- */
- @NonNull ContextSet getContexts();
-
- /**
- * The same as {@link #getContexts()}, but also includes context pairs for
- * "server" and "world" keys if present.
- *
- * @return the full contexts required for this node to apply
- * @see Contexts#SERVER_KEY
- * @see Contexts#WORLD_KEY
- * @since 3.1
- */
- @NonNull ContextSet getFullContexts();
-
- /**
- * Gets if this node is a wildcard permission.
- *
- * @return true if this node is a wildcard permission
- */
- boolean isWildcard();
-
- /**
- * Gets the level of this wildcard.
- *
- * The node luckperms.*
has a wildcard level of 1.
- * The node luckperms.user.permission.*
has a wildcard level of 3.
- *
- * Nodes with a higher wildcard level are more specific and have priority over
- * less specific nodes (nodes with a lower wildcard level).
- *
- * @return the wildcard level
- * @throws IllegalStateException if this is not a wildcard
- */
- int getWildcardLevel() throws IllegalStateException;
-
- /**
- * Gets if this node has any extra {@link NodeType} data attached to it.
- *
- * @return if this node has any type data
- * @since 4.2
- */
- boolean hasTypeData();
-
- /**
- * Gets the type data corresponding to the given key
, if present.
- *
- * @param key the key
- * @param the {@link NodeType} type
- * @return the data, if present
- * @since 4.2
- */
- Optional getTypeData(NodeTypeKey key);
-
- /**
- * Gets the type data corresponding to the given key
, throwing an exception
- * if no data is present.
- *
- * @param key the key
- * @param the {@link NodeType} type
- * @return the data
- * @throws IllegalStateException if data isn't present
- * @since 4.2
- */
- default T typeData(NodeTypeKey key) throws IllegalStateException {
- return getTypeData(key).orElseThrow(() -> new IllegalStateException("Node '" + getPermission() + "' does not have the '" + key.getTypeName() + "' type."));
- }
-
- /**
- * Gets if this node has {@link InheritanceType} type data.
- *
- * @return true if this is a inheritance (group) node.
- */
- default boolean isGroupNode() {
- return getTypeData(InheritanceType.KEY).isPresent();
- }
-
- /**
- * Gets the name of the inherited group if this node has {@link InheritanceType} type data,
- * throwing an exception if the data is not present.
- *
- * @return the name of the group
- * @throws IllegalStateException if this node doesn't have {@link InheritanceType} data
- */
- default @NonNull String getGroupName() throws IllegalStateException {
- return typeData(InheritanceType.KEY).getGroupName();
- }
-
- /**
- * Gets if this node has {@link MetaType} type data.
- *
- * @return true if this is a meta node.
- */
- default boolean isMeta() {
- return getTypeData(MetaType.KEY).isPresent();
- }
-
- /**
- * Gets the meta entry if this node has {@link MetaType} type data,
- * throwing an exception if the data is not present.
- *
- * @return the meta entry
- * @throws IllegalStateException if this node doesn't have {@link MetaType} data
- */
- default Map.@NonNull Entry getMeta() throws IllegalStateException {
- return typeData(MetaType.KEY);
- }
-
- /**
- * Gets if this node has {@link PrefixType} type data.
- *
- * @return true if this node is a prefix node
- */
- default boolean isPrefix() {
- return getTypeData(PrefixType.KEY).isPresent();
- }
-
- /**
- * Gets the prefix entry if this node has {@link PrefixType} type data,
- * throwing an exception if the data is not present.
- *
- * @return the meta entry
- * @throws IllegalStateException if this node doesn't have {@link PrefixType} data
- */
- default Map.@NonNull Entry getPrefix() throws IllegalStateException {
- return typeData(PrefixType.KEY).getAsEntry();
- }
-
- /**
- * Gets if this node has {@link SuffixType} type data.
- *
- * @return true if this node is a suffix node
- */
- default boolean isSuffix() {
- return getTypeData(SuffixType.KEY).isPresent();
- }
-
- /**
- * Gets the suffix entry if this node has {@link SuffixType} type data,
- * throwing an exception if the data is not present.
- *
- * @return the meta entry
- * @throws IllegalStateException if this node doesn't have {@link SuffixType} data
- */
- default Map.@NonNull Entry getSuffix() throws IllegalStateException {
- return typeData(SuffixType.KEY).getAsEntry();
- }
-
- /**
- * Gets if this Node is equal to another node.
- *
- * @param obj the other node
- * @return true if this node is equal to the other provided
- * @see StandardNodeEquality#EXACT
- */
- @Override
- boolean equals(Object obj);
-
- /**
- * Gets if this Node is equal to another node as defined by the given
- * {@link NodeEqualityPredicate}.
- *
- * @param other the other node
- * @param equalityPredicate the predicate
- * @return true if this node is considered equal
- * @since 4.1
- */
- boolean equals(Node other, NodeEqualityPredicate equalityPredicate);
-
- /**
- * Similar to {@link Node#equals(Object)}, except doesn't take note of the
- * value.
- *
- * @param other the other node
- * @return true if the two nodes are almost equal
- * @see StandardNodeEquality#IGNORE_VALUE
- * @deprecated in favour of {@link #equals(Node, NodeEqualityPredicate)}
- */
- @Deprecated
- default boolean equalsIgnoringValue(@NonNull Node other) {
- return equals(other, StandardNodeEquality.IGNORE_VALUE);
- }
-
- /**
- * Similar to {@link Node#equals(Object)}, except doesn't take note of the
- * expiry time or value.
- *
- * @param other the other node
- * @return true if the two nodes are almost equal
- * @see StandardNodeEquality#IGNORE_EXPIRY_TIME_AND_VALUE
- * @deprecated in favour of {@link #equals(Node, NodeEqualityPredicate)}
- */
- @Deprecated
- default boolean almostEquals(@NonNull Node other) {
- return equals(other, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE);
- }
-
- /**
- * Similar to {@link Node#equals(Object)}, except doesn't take note of the
- * value or if the node is temporary.
- *
- * @param other the other node
- * @return true if the two nodes are almost equal
- * @see StandardNodeEquality#IGNORE_VALUE_OR_IF_TEMPORARY
- * @since 2.8
- * @deprecated in favour of {@link #equals(Node, NodeEqualityPredicate)}
- */
- @Deprecated
- default boolean equalsIgnoringValueOrTemp(@NonNull Node other) {
- return equals(other, StandardNodeEquality.IGNORE_VALUE_OR_IF_TEMPORARY);
- }
-
- /**
- * Constructs a new builder initially containing the current properties of
- * this node.
- *
- * @return a new builder
- * @since 4.1
- */
- Builder toBuilder();
-
- /**
- * Builds a Node instance
- */
- interface Builder {
-
- /**
- * Copies the attributes from the given node and applies them to this
- * builder.
- *
- * Note that this copies all attributes except the
- * permission itself.
- *
- * @param node the node to copy from
- * @return the builder
- * @since 4.2
- */
- Builder copyFrom(@NonNull Node node);
-
- /**
- * Sets the value of negated for the node.
- *
- * @param negated the value
- * @return the builder
- * @see Node#isNegated()
- */
- @NonNull Builder setNegated(boolean negated);
-
- /**
- * Sets the value of the node.
- *
- * @param value the value
- * @return the builder
- * @see Node#getValue()
- */
- @NonNull Builder setValue(boolean value);
-
- /**
- * Sets the override property for the node.
- *
- * Warning: this value does not persist, and disappears when the holder is re-loaded.
- * It is therefore only useful for transient nodes.
- *
- * @param override the override state
- * @return the builder
- * @see Node#isOverride()
- */
- @NonNull Builder setOverride(boolean override);
-
- /**
- * Sets the time when the node should expire.
- *
- * The parameter passed to this method must be the unix timestamp
- * (in seconds) when the node should expire.
- *
- * @param expiryUnixTimestamp the expiry timestamp (unix seconds)
- * @return the builder
- * @see Node#getExpiryUnixTime()
- */
- @NonNull Builder setExpiry(long expiryUnixTimestamp);
-
- /**
- * Sets the time when the node should expire.
- *
- * The expiry timestamp is calculated relative to the current
- * system time.
- *
- * @param duration how long the node should be added for
- * @param unit the unit duration
is measured in
- * @return the builder
- * @since 4.2
- */
- default @NonNull Builder setExpiry(long duration, TimeUnit unit) {
- Preconditions.checkArgument(duration > 0, "duration must be positive");
- long seconds = Objects.requireNonNull(unit, "unit").toSeconds(duration);
- long timeNow = System.currentTimeMillis() / 1000L;
- return setExpiry(timeNow + seconds);
- }
-
- /**
- * Marks that the node being built should never expire.
- *
- * @return the builder
- * @since 4.2
- */
- @NonNull Builder clearExpiry();
-
- /**
- * Sets the world value for the node.
- *
- * @param world the world value
- * @return the builder
- * @see Node#getWorld()
- */
- @NonNull Builder setWorld(@Nullable String world);
-
- /**
- * Sets the server value for the node.
- *
- * @param server the world value
- * @return the builder
- * @see Node#getServer()
- */
- @NonNull Builder setServer(@Nullable String server);
-
- /**
- * Appends an extra context onto the node.
- *
- * @param key the context key
- * @param value the context value
- * @return the builder
- * @see ContextSet
- * @see Node#getContexts()
- */
- @NonNull Builder withExtraContext(@NonNull String key, @NonNull String value);
-
- /**
- * Appends extra contexts onto the node.
- *
- * @param map a map of contexts
- * @return the builder
- * @see ContextSet
- * @see Node#getContexts()
- */
- @NonNull Builder withExtraContext(@NonNull Map map);
-
- /**
- * Appends extra contexts onto the node.
- *
- * @param context a set of contexts
- * @return the builder
- * @see ContextSet
- * @see Node#getContexts()
- */
- @NonNull Builder withExtraContext(@NonNull Set> context);
-
- /**
- * Appends an extra context onto the node.
- *
- * @param entry the context
- * @return the builder
- * @see ContextSet
- * @see Node#getContexts()
- */
- @NonNull Builder withExtraContext(Map.@NonNull Entry entry);
-
- /**
- * Appends extra contexts onto the node.
- *
- * @param contextSet a context set
- * @return the builder
- * @see ContextSet
- * @see Node#getContexts()
- */
- @NonNull Builder withExtraContext(@NonNull ContextSet contextSet);
-
- /**
- * Sets the extra contexts for the node.
- *
- * @param contextSet a context set
- * @return the builder
- * @see ContextSet
- * @see Node#getContexts()
- * @since 4.2
- */
- @NonNull Builder setExtraContext(@NonNull ContextSet contextSet);
-
- /**
- * Creates a {@link Node} instance from the builder.
- *
- * @return a new node instance
- */
- @NonNull Node build();
- }
-
-}
diff --git a/api/src/main/java/me/lucko/luckperms/api/NodeEqualityPredicate.java b/api/src/main/java/me/lucko/luckperms/api/NodeEqualityPredicate.java
deleted file mode 100644
index 428fdcea4..000000000
--- a/api/src/main/java/me/lucko/luckperms/api/NodeEqualityPredicate.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * This file is part of LuckPerms, licensed under the MIT License.
- *
- * Copyright (c) lucko (Luck)
- * 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 org.checkerframework.checker.nullness.qual.NonNull;
-
-/**
- * A rule for determining if two nodes are equal.
- *
- * Generally, individual instances of this interface should fulfil the same
- * requirements as the {@link Object#equals(Object)} contract.
- *
- * Some standard implementations are provided by {@link StandardNodeEquality}.
- *
- * @since 4.1
- */
-@FunctionalInterface
-public interface NodeEqualityPredicate {
-
- /**
- * Returns if the two nodes are equal.
- *
- * This method should avoid making calls to {@link Node#equals(Node, NodeEqualityPredicate)}
- * with {@code this} as the second argument, directly or otherwise.
- *
- * @param o1 the first node
- * @param o2 the second node
- * @return true if equal
- */
- boolean areEqual(@NonNull Node o1, @NonNull Node o2);
-
-}
diff --git a/api/src/main/java/me/lucko/luckperms/api/NodeFactory.java b/api/src/main/java/me/lucko/luckperms/api/NodeFactory.java
deleted file mode 100644
index 226eeca82..000000000
--- a/api/src/main/java/me/lucko/luckperms/api/NodeFactory.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * This file is part of LuckPerms, licensed under the MIT License.
- *
- * Copyright (c) lucko (Luck)
- * 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 org.checkerframework.checker.nullness.qual.NonNull;
-
-/**
- * Assists with constructing {@link Node} instances.
- *
- * @since 2.17
- */
-public interface NodeFactory {
-
- /**
- * Creates a new node builder from a given base permission string
- *
- * @param permission the permission
- * @return a node builder instance
- * @throws NullPointerException if the permission is null
- */
- Node.@NonNull Builder newBuilder(@NonNull String permission);
-
- /**
- * Creates a node builder instance from an existing node
- *
- * @param other the other node
- * @return a node builder instance
- * @throws NullPointerException if the other node is null
- */
- Node.@NonNull Builder newBuilderFromExisting(@NonNull Node other);
-
-
- /**
- * Creates a node builder from a group
- *
- * @param group the group
- * @return a node builder instance
- * @throws NullPointerException if the group is null
- * @throws IllegalStateException if the group instance was not obtained from LuckPerms.
- * @since 3.1
- */
- Node.@NonNull Builder makeGroupNode(@NonNull Group group);
-
- /**
- * Creates a node builder from a group
- *
- * @param groupName the name of the group
- * @return a node builder instance
- * @throws NullPointerException if the groupName is null
- * @since 4.0
- */
- Node.@NonNull Builder makeGroupNode(@NonNull String groupName);
-
- /**
- * Creates a node builder from a key value pair
- *
- * @param key the key
- * @param value the value
- * @return a node builder instance
- * @throws NullPointerException if the key or value is null
- */
- Node.@NonNull Builder makeMetaNode(@NonNull String key, @NonNull String value);
-
- /**
- * 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
- * @throws NullPointerException if the type or value is null
- * @since 3.2
- */
- Node.@NonNull Builder makeChatMetaNode(@NonNull ChatMetaType type, int priority, @NonNull String value);
-
- /**
- * Creates a node builder from a prefix string and priority
- *
- * @param priority the priority
- * @param prefix the prefix string
- * @return a node builder instance
- * @throws NullPointerException if the prefix is null
- */
- Node.@NonNull Builder makePrefixNode(int priority, @NonNull String prefix);
-
- /**
- * Creates a node builder from a prefix string and priority
- *
- * @param priority the priority
- * @param suffix the suffix string
- * @return a node builder instance
- * @throws NullPointerException if the suffix is null
- */
- Node.@NonNull Builder makeSuffixNode(int priority, @NonNull String suffix);
-
-}
diff --git a/api/src/main/java/me/lucko/luckperms/api/PermissionHolder.java b/api/src/main/java/me/lucko/luckperms/api/PermissionHolder.java
deleted file mode 100644
index 48d1c11b2..000000000
--- a/api/src/main/java/me/lucko/luckperms/api/PermissionHolder.java
+++ /dev/null
@@ -1,777 +0,0 @@
-/*
- * This file is part of LuckPerms, licensed under the MIT License.
- *
- * Copyright (c) lucko (Luck)
- * 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 com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.Multimap;
-
-import me.lucko.luckperms.api.caching.CachedData;
-import me.lucko.luckperms.api.context.ContextSet;
-import me.lucko.luckperms.api.context.ImmutableContextSet;
-import me.lucko.luckperms.api.manager.GroupManager;
-import me.lucko.luckperms.api.manager.UserManager;
-import me.lucko.luckperms.api.nodetype.types.MetaType;
-import me.lucko.luckperms.api.nodetype.types.PrefixType;
-import me.lucko.luckperms.api.nodetype.types.SuffixType;
-
-import org.checkerframework.checker.nullness.qual.NonNull;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.UUID;
-import java.util.concurrent.CompletableFuture;
-import java.util.function.Predicate;
-
-/**
- * Generic superinterface for an object which holds permissions.
- */
-public interface PermissionHolder {
-
- /**
- * Gets the objects generic name.
- *
- * The result of this method is guaranteed to be a unique identifier for distinct instances
- * of the same type of object.
- *
- * For {@link User}s, this method returns a {@link UUID#toString() string} representation of
- * the users {@link User#getUuid() unique id}.
- *
- * For {@link Group}s, this method returns the {@link Group#getName() group name}.
- *
- * The {@link User#getUuid()}, {@link User#getName()} and {@link Group#getName()} methods
- * define a "tighter" specification for obtaining object identifiers.
- *
- * @return the identifier for this object. Either a uuid string or name.
- */
- @NonNull String getObjectName();
-
- /**
- * Gets a friendly name for this holder, to be displayed in command output, etc.
- *
- * This will always return a value, eventually falling back to
- * {@link #getObjectName()} if no other "friendlier" identifiers are present.
- *
- * For {@link User}s, this method will attempt to return the {@link User#getName() username},
- * before falling back to {@link #getObjectName()}.
- *
- * For {@link Group}s, this method will attempt to return the groups display name, before
- * falling back to {@link #getObjectName()}.
- *
- * @return a friendly identifier for this holder
- * @since 3.2
- */
- @NonNull String getFriendlyName();
-
- /**
- * Gets the holders {@link CachedData} cache.
- *
- * @return the holders cached data.
- * @since 3.2
- */
- @NonNull CachedData getCachedData();
-
- /**
- * Refreshes and applies any changes to the cached holder data.
- *
- * Calling this method is unnecessary in most cases. Cache updates are handled
- * behind the scenes by the implementation.
- *
- * @return the task future
- * @since 4.0
- */
- @NonNull CompletableFuture refreshCachedData();
-
- /**
- * Gets the backing multimap containing every permission this holder has.
- *
- * This method does not resolve inheritance rules, and returns a
- * view of what's 'in the file'.
- *
- * @return the holders own permissions
- * @since 3.3
- */
- @NonNull ImmutableSetMultimap getNodes();
-
- /**
- * Gets the backing multimap containing every transient permission this holder has.
- *
- * This method does not resolve inheritance rules.
- *
- * Transient permissions only exist for the duration of the session.
- *
- * @return the holders own permissions
- * @since 3.3
- */
- @NonNull ImmutableSetMultimap getTransientNodes();
-
- /**
- * Gets a flattened/squashed view of the holders permissions.
- *
- * This list is constructed using the {@link Multimap#values()} method
- * of both the transient and enduring backing multimaps.
- *
- * This means that it may contain duplicate entries.
- *
- * Use {@link #getPermissions()} for a view without duplicates.
- *
- * This method does not resolve inheritance rules.
- *
- * @return a list of the holders own nodes.
- * @since 3.3
- */
- @NonNull List getOwnNodes();
-
- /**
- * Gets a sorted set of all held permissions.
- *
- * Effectively a sorted version of {@link #getOwnNodes()}, without duplicates. Use the
- * aforementioned method if you don't require either of these attributes.
- *
- * This method does not resolve inheritance rules.
- *
- * Although this method is named getPermissions, it will actually return all types of node.
- *
- * @return an immutable set of permissions in priority order
- * @since 2.6
- */
- @NonNull SortedSet extends Node> getPermissions();
-
- /**
- * Similar to {@link #getPermissions()}, except only including permissions from the enduring
- * node map. (See {@link #getNodes()})
- *
- * Unlike transient permissions, enduring permissions will be saved to storage, and exist
- * after the session.
- *
- * This method does not resolve inheritance rules.
- *
- * Although this method is named getEnduringPermissions, it will actually return all types
- * of node.
- *
- * @return a set of nodes
- * @since 2.6
- */
- @NonNull Set extends Node> getEnduringPermissions();
-
- /**
- * Similar to {@link #getPermissions()}, except only including permissions from the enduring
- * node map. (See {@link #getTransientNodes()})
- *
- * Transient permissions only exist for the duration of the session.
- *
- * This method does not resolve inheritance rules.
- *
- * Although this method is named getTransientPermissions, it will actually return all types
- * of node.
- *
- * @return a set of nodes
- * @since 2.6
- */
- @NonNull Set extends Node> getTransientPermissions();
-
- /**
- * A filtered view of this holders nodes, only including permanent entries.
- *
- * Data is sourced from {@link #getOwnNodes()}, filtered, and then collected to a set.
- *
- * This method does not resolve inheritance rules.
- *
- * Although this method is named getPermanentPermissionNodes, it will actually return all types
- * of node.
- *
- * @return a set of permanent nodes
- * @since 2.6
- */
- @NonNull Set getPermanentPermissionNodes();
-
- /**
- * A filtered view of this holders nodes, only including temporary entries.
- *
- * Data is sourced from {@link #getOwnNodes()}, filtered, and then collected to a set.
- *
- * This method does not resolve inheritance rules.
- *
- * Although this method is named getTemporaryPermissionNodes, it will actually return all types
- * of node.
- *
- * @return a set of temporary nodes
- * @since 2.6
- */
- @NonNull Set getTemporaryPermissionNodes();
-
- /**
- * Recursively resolves this holders permissions.
- *
- * The returned list will contain every inherited
- * node the holder has, in the order that they were inherited in.
- *
- * This means the list will contain duplicates.
- *
- * Inheritance is performed according to the platforms rules, and the order will vary
- * depending on the accumulation order. By default, the holders own nodes are first in the list,
- * with the entries from the end of the inheritance tree appearing last.
- *
- * @param contexts the contexts for the lookup
- * @return a list of nodes
- * @since 3.3
- */
- @NonNull List resolveInheritances(@NonNull Contexts contexts);
-
- /**
- * Recursively resolves this holders permissions.
- *
- * The returned list will contain every inherited
- * node the holder has, in the order that they were inherited in.
- *
- * This means the list will contain duplicates.
- *
- * Unlike {@link #resolveInheritances(Contexts)}, this method does not
- * filter by context, at all.
- *
- * Inheritance is performed according to the platforms rules, and the order will vary
- * depending on the accumulation order. By default, the holders own nodes are first in the list,
- * with the entries from the end of the inheritance tree appearing last.
- *
- * @return a list of nodes
- * @since 3.3
- */
- @NonNull List resolveInheritances();
-
- /**
- * Gets a mutable sorted set of the nodes that this object has and inherits, filtered by context
- *
- * Unlike {@link #getAllNodesFiltered(Contexts)}, this method will not filter individual
- * nodes by context. The context is only used to determine which groups should apply.
- *
- * Nodes are sorted into priority order. The order of inheritance is only important during
- * the process of flattening inherited entries.
- *
- * @param contexts the context for the lookup
- * @return an immutable sorted set of permissions
- * @throws NullPointerException if the context is null
- * @since 2.11
- */
- @NonNull SortedSet getAllNodes(@NonNull Contexts contexts);
-
- /**
- * Gets a mutable sorted set of the nodes that this object has and inherits.
- *
- * Unlike {@link #getAllNodes(Contexts)}, this method does not filter by context, at all.
- *
- * Nodes are sorted into priority order. The order of inheritance is only important during
- * the process of flattening inherited entries.
- *
- * @return an immutable sorted set of permissions
- * @throws NullPointerException if the context is null
- * @since 3.3
- */
- @NonNull SortedSet getAllNodes();
-
- /**
- * Gets a mutable set of the nodes that this object has and inherits, filtered by context.
- *
- * Unlike {@link #getAllNodes(Contexts)}, this method WILL filter individual nodes,
- * and only return ones that fully meet the context provided.
- *
- * @param contexts the context for the lookup
- * @return a mutable set of permissions
- * @throws NullPointerException if the context is null
- * @since 2.11
- */
- @NonNull Set getAllNodesFiltered(@NonNull Contexts contexts);
-
- /**
- * Converts the output of {@link #getAllNodesFiltered(Contexts)} into string and boolean form,
- * and expands shorthand permissions.
- *
- * @param contexts the context for the lookup
- * @param convertToLowercase if the keys should be made lowercase whilst being exported
- * @return a mutable map of permissions
- */
- @NonNull Map exportNodes(@NonNull Contexts contexts, boolean convertToLowercase);
-
- /**
- * Removes any temporary permissions that have expired.
- *
- * This method is called periodically by the platform, so it is only necessary to run
- * if you want to guarentee that the current data is totally up-to-date.
- */
- void auditTemporaryPermissions();
-
- /**
- * Checks to see if the object has a certain permission.
- *
- * Although this method is named hasPermission, it can be used for all node types.
- *
- * @param node the node to check for
- * @param equalityPredicate how to determine if a node matches
- * @return a Tristate for the holders permission status for the node
- * @throws NullPointerException if the node is null
- * @since 4.1
- */
- @NonNull Tristate hasPermission(@NonNull Node node, @NonNull NodeEqualityPredicate equalityPredicate);
-
- /**
- * Checks to see if the object has a certain permission.
- *
- * Although this method is named hasTransientPermission, it can be used for all node types.
- *
- * @param node the node to check for
- * @param equalityPredicate how to determine if a node matches
- * @return a Tristate for the holders permission status for the node
- * @throws NullPointerException if the node is null
- * @since 4.1
- */
- @NonNull Tristate hasTransientPermission(@NonNull Node node, @NonNull NodeEqualityPredicate equalityPredicate);
-
- /**
- * Checks to see if the object inherits a certain permission.
- *
- * Although this method is named inheritsPermission, it can be used for all node types.
- *
- * @param node the node to check for
- * @param equalityPredicate how to determine if a node matches
- * @return a Tristate for the holders inheritance status for the node
- * @throws NullPointerException if the node is null
- * @since 4.1
- */
- @NonNull Tristate inheritsPermission(@NonNull Node node, @NonNull NodeEqualityPredicate equalityPredicate);
-
- /**
- * Checks to see if the object has a certain permission.
- *
- * Although this method is named hasPermission, it can be used for all node types.
- *
- * @param node the node to check for
- * @return a Tristate for the holders permission status for the node
- * @throws NullPointerException if the node is null
- * @since 2.6
- */
- @NonNull Tristate hasPermission(@NonNull Node node);
-
- /**
- * Checks to see if the object has a certain permission.
- *
- * Although this method is named hasTransientPermission, it can be used for all node types.
- *
- * @param node the node to check for
- * @return a Tristate for the holders permission status for the node
- * @throws NullPointerException if the node is null
- * @since 2.6
- */
- @NonNull Tristate hasTransientPermission(@NonNull Node node);
-
- /**
- * Checks to see if the object inherits a certain permission.
- *
- * Although this method is named inheritsPermission, it can be used for all node types.
- *
- * @param node the node to check for
- * @return a Tristate for the holders inheritance status for the node
- * @throws NullPointerException if the node is null
- * @since 2.6
- */
- @NonNull Tristate inheritsPermission(@NonNull Node node);
-
- /**
- * Check to see if this holder inherits another group in the global context.
- *
- * "Global context" simply means an empty context set.
- *
- * This method only checks for direct inheritance - one hop up the inheritance tree.
- *
- * @param group The group to check membership of
- * @return true if the group inherits the other group
- * @throws NullPointerException if the group is null
- * @throws IllegalStateException if the group instance was not obtained from LuckPerms.
- * @since 4.0
- */
- boolean inheritsGroup(@NonNull Group group);
-
- /**
- * Check to see if this holder inherits another group.
- *
- * This method only checks for direct inheritance - one hop up the inheritance tree.
- *
- * @param group The group to check membership of
- * @param contextSet the context set to filter by
- * @return true if the group inherits the other group
- * @throws NullPointerException if the group is null
- * @throws IllegalStateException if the group instance was not obtained from LuckPerms.
- * @since 4.0
- */
- boolean inheritsGroup(@NonNull Group group, @NonNull ContextSet contextSet);
-
- /**
- * Sets a permission node for the permission holder.
- *
- * Although this method is named setPermission, it can be used for all node types.
- *
- * The effect of this mutate operation will not persist in storage unless changes are
- * explicitly saved. If changes are not saved, the effect will only be observed until the next
- * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
- * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
- * using {@link GroupManager#saveGroup(Group)}.
- *
- * Before making changes to a user or group, it may be a good idea to load a fresh copy of
- * the backing data from the storage if you haven't done so already, to avoid overwriting changes
- * made already. This can be done via {@link UserManager#loadUser(UUID)} or
- * {@link GroupManager#loadGroup(String)} respectively.
- *
- * @param node The node to be set
- * @return the result of the operation
- * @throws NullPointerException if the node is null
- * @since 4.0
- */
- @NonNull DataMutateResult setPermission(@NonNull Node node);
-
- /**
- * Sets a permission node for the permission holder.
- *
- * Although this method is named setPermission, it can be used for all node types.
- *
- * The effect of this mutate operation will not persist in storage unless changes are
- * explicitly saved. If changes are not saved, the effect will only be observed until the next
- * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
- * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
- * using {@link GroupManager#saveGroup(Group)}.
- *
- * Before making changes to a user or group, it may be a good idea to load a fresh copy of
- * the backing data from the storage if you haven't done so already, to avoid overwriting changes
- * made already. This can be done via {@link UserManager#loadUser(UUID)} or
- * {@link GroupManager#loadGroup(String)} respectively.
- *
- * @param node The node to be set
- * @param temporaryMergeBehaviour The behaviour used to merge temporary permission entries
- * @return the result of the operation
- * @throws NullPointerException if the node is null
- * @since 4.3
- */
- @NonNull TemporaryDataMutateResult setPermission(@NonNull Node node, @NonNull TemporaryMergeBehaviour temporaryMergeBehaviour);
-
- /**
- * Sets a transient permission for the permission holder.
- *
- * A transient node is a permission that does not persist.
- * Whenever a user logs out of the server, or the server restarts, this permission will
- * disappear. It is never saved to the datastore, and therefore will not apply on other
- * servers.
- *
- * This is useful if you want to temporarily set a permission for a user while they're
- * online, but don't want it to persist, and have to worry about removing it when they log
- * out.
- *
- * For unsetting a transient permission, see {@link #unsetTransientPermission(Node)}.
- *
- * Although this method is named setTransientPermission, it can be used for all node types.
- *
- * @param node The node to be set
- * @return the result of the operation
- * @throws NullPointerException if the node is null
- * @since 4.0
- */
- @NonNull DataMutateResult setTransientPermission(@NonNull Node node);
-
- /**
- * Sets a transient permission for the permission holder.
- *
- * A transient node is a permission that does not persist.
- * Whenever a user logs out of the server, or the server restarts, this permission will
- * disappear. It is never saved to the datastore, and therefore will not apply on other
- * servers.
- *
- * This is useful if you want to temporarily set a permission for a user while they're
- * online, but don't want it to persist, and have to worry about removing it when they log
- * out.
- *
- * For unsetting a transient permission, see {@link #unsetTransientPermission(Node)}.
- *
- * Although this method is named setTransientPermission, it can be used for all node types.
- *
- * @param node The node to be se
- * @param temporaryMergeBehaviour The behaviour used to merge temporary permission entries
- * @return the result of the operation
- * @throws NullPointerException if the node is null
- * @since 4.3
- */
- @NonNull TemporaryDataMutateResult setTransientPermission(@NonNull Node node, @NonNull TemporaryMergeBehaviour temporaryMergeBehaviour);
-
- /**
- * Unsets a permission for the permission holder.
- *
- * Although this method is named unsetPermission, it can be used for all node types.
- *
- * The effect of this mutate operation will not persist in storage unless changes are
- * explicitly saved. If changes are not saved, the effect will only be observed until the next
- * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
- * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
- * using {@link GroupManager#saveGroup(Group)}.
- *
- * Before making changes to a user or group, it may be a good idea to load a fresh copy of
- * the backing data from the storage if you haven't done so already, to avoid overwriting changes
- * made already. This can be done via {@link UserManager#loadUser(UUID)} or
- * {@link GroupManager#loadGroup(String)} respectively.
- *
- * @param node The node to be unset
- * @return the result of the operation
- * @throws NullPointerException if the node is null
- * @since 4.0
- */
- @NonNull DataMutateResult unsetPermission(@NonNull Node node);
-
- /**
- * Unsets a transient permission for the permission holder.
- *
- * Although this method is named unsetTransientPermission, it can be used for all node types.
- *
- * @param node The node to be unset
- * @return the result of the operation
- * @throws NullPointerException if the node is null
- * @since 4.0
- */
- @NonNull DataMutateResult unsetTransientPermission(@NonNull Node node);
-
- /**
- * Clears any nodes from the holder which pass the predicate.
- *
- * This method only targets enduring data.
- *
- * The effect of this mutate operation will not persist in storage unless changes are
- * explicitly saved. If changes are not saved, the effect will only be observed until the next
- * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
- * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
- * using {@link GroupManager#saveGroup(Group)}.
- *
- * Before making changes to a user or group, it may be a good idea to load a fresh copy of
- * the backing data from the storage if you haven't done so already, to avoid overwriting changes
- * made already. This can be done via {@link UserManager#loadUser(UUID)} or
- * {@link GroupManager#loadGroup(String)} respectively.
- *
- * @param test the predicate to test for nodes which should be removed
- * @since 3.2
- */
- void clearMatching(@NonNull Predicate test);
-
- /**
- * Clears any transient nodes from the holder which pass the predicate.
- *
- * The effect of this mutate operation will not persist in storage unless changes are
- * explicitly saved. If changes are not saved, the effect will only be observed until the next
- * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
- * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
- * using {@link GroupManager#saveGroup(Group)}.
- *
- * Before making changes to a user or group, it may be a good idea to load a fresh copy of
- * the backing data from the storage if you haven't done so already, to avoid overwriting changes
- * made already. This can be done via {@link UserManager#loadUser(UUID)} or
- * {@link GroupManager#loadGroup(String)} respectively.
- *
- * @param test the predicate to test for nodes which should be removed
- * @since 3.2
- */
- void clearMatchingTransient(@NonNull Predicate test);
-
- /**
- * Clears all nodes held by the permission holder.
- *
- * The effect of this mutate operation will not persist in storage unless changes are
- * explicitly saved. If changes are not saved, the effect will only be observed until the next
- * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
- * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
- * using {@link GroupManager#saveGroup(Group)}.
- *
- * Before making changes to a user or group, it may be a good idea to load a fresh copy of
- * the backing data from the storage if you haven't done so already, to avoid overwriting changes
- * made already. This can be done via {@link UserManager#loadUser(UUID)} or
- * {@link GroupManager#loadGroup(String)} respectively.
- *
- * @since 2.17
- */
- void clearNodes();
-
- /**
- * Clears all nodes held by the permission holder in a specific context.
- *
- * The effect of this mutate operation will not persist in storage unless changes are
- * explicitly saved. If changes are not saved, the effect will only be observed until the next
- * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
- * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
- * using {@link GroupManager#saveGroup(Group)}.
- *
- * Before making changes to a user or group, it may be a good idea to load a fresh copy of
- * the backing data from the storage if you haven't done so already, to avoid overwriting changes
- * made already. This can be done via {@link UserManager#loadUser(UUID)} or
- * {@link GroupManager#loadGroup(String)} respectively.
- *
- * @param contextSet the contexts to filter by
- * @since 3.2
- */
- void clearNodes(@NonNull ContextSet contextSet);
-
- /**
- * Clears all parent groups.
- *
- * The effect of this mutate operation will not persist in storage unless changes are
- * explicitly saved. If changes are not saved, the effect will only be observed until the next
- * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
- * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
- * using {@link GroupManager#saveGroup(Group)}.
- *
- * Before making changes to a user or group, it may be a good idea to load a fresh copy of
- * the backing data from the storage if you haven't done so already, to avoid overwriting changes
- * made already. This can be done via {@link UserManager#loadUser(UUID)} or
- * {@link GroupManager#loadGroup(String)} respectively.
- *
- * @since 2.17
- */
- void clearParents();
-
- /**
- * Clears all parent groups in a specific context.
- *
- * The effect of this mutate operation will not persist in storage unless changes are
- * explicitly saved. If changes are not saved, the effect will only be observed until the next
- * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
- * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
- * using {@link GroupManager#saveGroup(Group)}.
- *
- * Before making changes to a user or group, it may be a good idea to load a fresh copy of
- * the backing data from the storage if you haven't done so already, to avoid overwriting changes
- * made already. This can be done via {@link UserManager#loadUser(UUID)} or
- * {@link GroupManager#loadGroup(String)} respectively.
- *
- * @param contextSet the contexts to filter by
- * @since 3.2
- */
- void clearParents(@NonNull ContextSet contextSet);
-
- /**
- * Clears all meta held by the permission holder.
- *
- * Meta nodes in this case, are any nodes which have a {@link MetaType}, {@link PrefixType}
- * or {@link SuffixType} type.
- *
- * The effect of this mutate operation will not persist in storage unless changes are
- * explicitly saved. If changes are not saved, the effect will only be observed until the next
- * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
- * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
- * using {@link GroupManager#saveGroup(Group)}.
- *
- * Before making changes to a user or group, it may be a good idea to load a fresh copy of
- * the backing data from the storage if you haven't done so already, to avoid overwriting changes
- * made already. This can be done via {@link UserManager#loadUser(UUID)} or
- * {@link GroupManager#loadGroup(String)} respectively.
- *
- * @since 2.17
- */
- void clearMeta();
-
- /**
- * Clears all meta held by the permission holder in a specific context.
- *
- * Meta nodes in this case, are any nodes which have a {@link MetaType}, {@link PrefixType}
- * or {@link SuffixType} type.
- *
- * The effect of this mutate operation will not persist in storage unless changes are
- * explicitly saved. If changes are not saved, the effect will only be observed until the next
- * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
- * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
- * using {@link GroupManager#saveGroup(Group)}.
- *
- * Before making changes to a user or group, it may be a good idea to load a fresh copy of
- * the backing data from the storage if you haven't done so already, to avoid overwriting changes
- * made already. This can be done via {@link UserManager#loadUser(UUID)} or
- * {@link GroupManager#loadGroup(String)} respectively.
- *
- * @param contextSet the contexts to filter by
- * @since 3.2
- */
- void clearMeta(@NonNull ContextSet contextSet);
-
- /**
- * Clears all transient nodes the permission holder has.
- */
- void clearTransientNodes();
-
- /**
- * Sets a permission for the permission holder.
- *
- * @param node The node to be set
- * @return the result of the operation
- * @throws NullPointerException if the node is null
- * @since 3.1
- * @deprecated now forwards to {@link #setPermission(Node)}.
- */
- @Deprecated
- default @NonNull DataMutateResult setPermissionUnchecked(@NonNull Node node) {
- return setPermission(node);
- }
-
- /**
- * Sets a transient permission for the permission holder.
- *
- * @param node The node to be set
- * @return the result of the operation
- * @throws NullPointerException if the node is null
- * @since 3.1
- * @deprecated now forwards to {@link #setTransientPermission(Node)}
- */
- @Deprecated
- default @NonNull DataMutateResult setTransientPermissionUnchecked(@NonNull Node node) {
- return setTransientPermission(node);
- }
-
- /**
- * Unsets a permission for the permission holder.
- *
- * @param node The node to be unset
- * @return the result of the operation
- * @throws NullPointerException if the node is null
- * @since 3.1
- * @deprecated now forwards to {@link #unsetPermission(Node)}
- */
- @Deprecated
- default @NonNull DataMutateResult unsetPermissionUnchecked(@NonNull Node node) {
- return unsetPermission(node);
- }
-
- /**
- * Unsets a transient permission for the permission holder.
- *
- * @param node The node to be unset
- * @return the result of the operation
- * @throws NullPointerException if the node is null
- * @since 3.1
- * @deprecated now forwards to {@link #unsetTransientPermission(Node)}
- */
- @Deprecated
- default @NonNull DataMutateResult unsetTransientPermissionUnchecked(@NonNull Node node) {
- return unsetTransientPermission(node);
- }
-
-}
diff --git a/api/src/main/java/me/lucko/luckperms/api/LogEntry.java b/api/src/main/java/me/lucko/luckperms/api/actionlog/Action.java
similarity index 83%
rename from api/src/main/java/me/lucko/luckperms/api/LogEntry.java
rename to api/src/main/java/me/lucko/luckperms/api/actionlog/Action.java
index 1502aa759..2631da02c 100644
--- a/api/src/main/java/me/lucko/luckperms/api/LogEntry.java
+++ b/api/src/main/java/me/lucko/luckperms/api/actionlog/Action.java
@@ -23,7 +23,9 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api;
+package me.lucko.luckperms.api.actionlog;
+
+import me.lucko.luckperms.api.LuckPermsProvider;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -33,10 +35,17 @@ import java.util.UUID;
/**
* Represents a logged action.
- *
- * @see ActionLogger#newEntryBuilder() for creating an instance
*/
-public interface LogEntry extends Comparable {
+public interface Action extends Comparable {
+
+ /**
+ * Gets a {@link Action.Builder}
+ *
+ * @return a new builder
+ */
+ static @NonNull Builder builder() {
+ return LuckPermsProvider.get().getActionLogger().actionBuilder();
+ }
/**
* Gets the time in unix seconds when the action occurred.
@@ -95,9 +104,7 @@ public interface LogEntry extends Comparable {
@NonNull String getAction();
/**
- * Represents the type of a {@link LogEntry}.
- *
- * @since 3.3
+ * Represents the type of a {@link Action}.
*/
enum Type {
USER('U'), GROUP('G'), TRACK('T');
@@ -108,7 +115,6 @@ public interface LogEntry extends Comparable {
* @param type the string
* @return a type
* @throws IllegalArgumentException if a type could not be parsed
- * @since 4.4
*/
public static @NonNull Type parse(String type) {
try {
@@ -168,70 +174,70 @@ public interface LogEntry extends Comparable {
*
* @param timestamp the timestamp
* @return the builder
- * @see LogEntry#getTimestamp()
+ * @see Action#getTimestamp()
*/
- @NonNull Builder setTimestamp(long timestamp);
+ @NonNull Builder timestamp(long timestamp);
/**
* Sets the actor of the entry.
*
* @param actor the actor
* @return the builder
- * @see LogEntry#getActor()
+ * @see Action#getActor()
*/
- @NonNull Builder setActor(@NonNull UUID actor);
+ @NonNull Builder actor(@NonNull UUID actor);
/**
* Sets the actor name of the entry.
*
* @param actorName the actor name
* @return the builder
- * @see LogEntry#getActorName()
+ * @see Action#getActorName()
*/
- @NonNull Builder setActorName(@NonNull String actorName);
+ @NonNull Builder actorName(@NonNull String actorName);
/**
* Sets the type of the entry.
*
* @param type the type
* @return the builder
- * @see LogEntry#getType()
+ * @see Action#getType()
*/
- @NonNull Builder setType(@NonNull Type type);
+ @NonNull Builder type(@NonNull Type type);
/**
* Sets the acted object for the entry.
*
* @param acted the acted object
* @return the builder
- * @see LogEntry#getActed()
+ * @see Action#getActed()
*/
- @NonNull Builder setActed(@Nullable UUID acted);
+ @NonNull Builder acted(@Nullable UUID acted);
/**
* Sets the acted name for the entry.
*
* @param actedName the acted name
* @return the builder
- * @see LogEntry#getActedName()
+ * @see Action#getActedName()
*/
- @NonNull Builder setActedName(@NonNull String actedName);
+ @NonNull Builder actedName(@NonNull String actedName);
/**
* Sets the action of the entry.
*
* @param action the action
* @return the builder
- * @see LogEntry#getAction()
+ * @see Action#getAction()
*/
- @NonNull Builder setAction(@NonNull String action);
+ @NonNull Builder action(@NonNull String action);
/**
- * Creates a {@link LogEntry} instance from the builder.
+ * Creates a {@link Action} instance from the builder.
*
* @return a new log entry instance
*/
- @NonNull LogEntry build();
+ @NonNull Action build();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/Log.java b/api/src/main/java/me/lucko/luckperms/api/actionlog/ActionLog.java
similarity index 81%
rename from api/src/main/java/me/lucko/luckperms/api/Log.java
rename to api/src/main/java/me/lucko/luckperms/api/actionlog/ActionLog.java
index 3171f0062..84c90d1b5 100644
--- a/api/src/main/java/me/lucko/luckperms/api/Log.java
+++ b/api/src/main/java/me/lucko/luckperms/api/actionlog/ActionLog.java
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api;
+package me.lucko.luckperms.api.actionlog;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -36,18 +36,18 @@ import java.util.UUID;
* The returned instance provides a copy of the data at the time of retrieval.
*
* Any changes made to log entries will only apply to this instance of the log.
- * You can add to the log using the {@link Storage}, and then request an updated copy.
+ * You can add to the log using the {@link ActionLogger}, and then request an updated copy.
*
* All methods are thread safe, and return immutable and thread safe collections.
*/
-public interface Log {
+public interface ActionLog {
/**
- * Gets the {@link LogEntry}s that make up this log.
+ * Gets the {@link Action}s that make up this log.
*
* @return the content
*/
- @NonNull SortedSet getContent();
+ @NonNull SortedSet getContent();
/**
* Gets the entries in the log performed by the given actor.
@@ -55,7 +55,7 @@ public interface Log {
* @param actor the uuid of the actor to filter by
* @return the content for the given actor
*/
- @NonNull SortedSet getContent(@NonNull UUID actor);
+ @NonNull SortedSet getContent(@NonNull UUID actor);
/**
* Gets the log content for a given user
@@ -63,7 +63,7 @@ public interface Log {
* @param uuid the uuid to filter by
* @return all content in this log where the user = uuid
*/
- @NonNull SortedSet getUserHistory(@NonNull UUID uuid);
+ @NonNull SortedSet getUserHistory(@NonNull UUID uuid);
/**
* Gets the log content for a given group
@@ -71,7 +71,7 @@ public interface Log {
* @param name the name to filter by
* @return all content in this log where the group = name
*/
- @NonNull SortedSet getGroupHistory(@NonNull String name);
+ @NonNull SortedSet getGroupHistory(@NonNull String name);
/**
* Gets the log content for a given track
@@ -79,6 +79,6 @@ public interface Log {
* @param name the name to filter by
* @return all content in this log where the track = name
*/
- @NonNull SortedSet getTrackHistory(@NonNull String name);
+ @NonNull SortedSet getTrackHistory(@NonNull String name);
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/ActionLogger.java b/api/src/main/java/me/lucko/luckperms/api/actionlog/ActionLogger.java
similarity index 79%
rename from api/src/main/java/me/lucko/luckperms/api/ActionLogger.java
rename to api/src/main/java/me/lucko/luckperms/api/actionlog/ActionLogger.java
index fe4aa8455..22c0c797e 100644
--- a/api/src/main/java/me/lucko/luckperms/api/ActionLogger.java
+++ b/api/src/main/java/me/lucko/luckperms/api/actionlog/ActionLogger.java
@@ -23,7 +23,9 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api;
+package me.lucko.luckperms.api.actionlog;
+
+import me.lucko.luckperms.api.messaging.MessagingService;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -31,25 +33,22 @@ import java.util.concurrent.CompletableFuture;
/**
* Represents the object responsible for handling action logging.
- *
- * @since 4.1
*/
public interface ActionLogger {
/**
- * Returns a new {@link LogEntry.Builder} instance
+ * Returns a new {@link Action.Builder} instance
*
* @return a new builder
*/
- LogEntry.@NonNull Builder newEntryBuilder();
+ Action.@NonNull Builder actionBuilder();
/**
- * Gets a {@link Log} instance from the plugin storage.
+ * Gets a {@link ActionLog} instance from the plugin storage.
*
* @return a log instance
- * @see Storage#getLog()
*/
- @NonNull CompletableFuture getLog();
+ @NonNull CompletableFuture getLog();
/**
* Submits a log entry to the plugin to be handled.
@@ -58,7 +57,7 @@ public interface ActionLogger {
* it.
*
* It is therefore roughly equivalent to calling
- * {@link #submitToStorage(LogEntry)} and {@link #broadcastAction(LogEntry)},
+ * {@link #submitToStorage(Action)} and {@link #broadcastAction(Action)},
* however, using this method is preferred to making the calls individually.
*
* If you want to submit a log entry but don't know which method to pick,
@@ -67,17 +66,15 @@ public interface ActionLogger {
* @param entry the entry to submit
* @return a future which will complete when the action is done
*/
- @NonNull CompletableFuture submit(@NonNull LogEntry entry);
+ @NonNull CompletableFuture submit(@NonNull Action entry);
/**
* Submits a log entry to the plugins storage handler.
*
- * Performs the same action as {@link Storage#logAction(LogEntry)}.
- *
* @param entry the entry to submit
* @return a future which will complete when the action is done
*/
- @NonNull CompletableFuture submitToStorage(@NonNull LogEntry entry);
+ @NonNull CompletableFuture submitToStorage(@NonNull Action entry);
/**
* Submits a log entry to the plugins log broadcasting handler.
@@ -88,6 +85,6 @@ public interface ActionLogger {
* @param entry the entry to submit
* @return a future which will complete when the action is done
*/
- @NonNull CompletableFuture broadcastAction(@NonNull LogEntry entry);
+ @NonNull CompletableFuture broadcastAction(@NonNull Action entry);
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/caching/CachedDataContainer.java b/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedData.java
similarity index 79%
rename from api/src/main/java/me/lucko/luckperms/api/caching/CachedDataContainer.java
rename to api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedData.java
index d9aa4b04f..fb829b558 100644
--- a/api/src/main/java/me/lucko/luckperms/api/caching/CachedDataContainer.java
+++ b/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedData.java
@@ -23,24 +23,22 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api.caching;
+package me.lucko.luckperms.api.cacheddata;
-import me.lucko.luckperms.api.Contexts;
+import me.lucko.luckperms.api.query.QueryOptions;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
- * Holds cached lookup data in a specific set of contexts.
- *
- * @since 4.1
+ * Holds cached lookup data for a given set of query options.
*/
-public interface CachedDataContainer {
+public interface CachedData {
/**
- * Gets the contexts this container is holding data for.
+ * Gets the query options this container is holding data for.
*
- * @return the contexts this container is caching
+ * @return the query options this container is caching
*/
- @NonNull Contexts getContexts();
+ @NonNull QueryOptions getQueryOptions();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedDataManager.java b/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedDataManager.java
new file mode 100644
index 000000000..7922b94d2
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedDataManager.java
@@ -0,0 +1,212 @@
+/*
+ * This file is part of LuckPerms, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * 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.cacheddata;
+
+import me.lucko.luckperms.api.model.PermissionHolder;
+import me.lucko.luckperms.api.query.QueryOptions;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Holds cached permission and meta lookup data for a {@link PermissionHolder}.
+ *
+ * All calls will account for inheritance, as well as any default data
+ * provided by the platform. This calls are heavily cached and are therefore
+ * fast.
+ */
+public interface CachedDataManager {
+
+ /**
+ * Gets the manager for {@link CachedPermissionData}.
+ *
+ * @return the permission data manager
+ */
+ @NonNull Container permissionData();
+
+ /**
+ * Gets the manager for {@link CachedMetaData}.
+ *
+ * @return the meta data manager
+ */
+ @NonNull Container metaData();
+
+ /**
+ * Gets PermissionData from the cache, given a specified context.
+ *
+ * @param queryOptions the query options
+ * @return a permission data instance
+ * @throws NullPointerException if contexts is null
+ */
+ @NonNull CachedPermissionData getPermissionData(@NonNull QueryOptions queryOptions);
+
+ /**
+ * Gets MetaData from the cache, given a specified context.
+ *
+ * @param queryOptions the query options
+ * @return a meta data instance
+ * @throws NullPointerException if contexts is null
+ */
+ @NonNull CachedMetaData getMetaData(@NonNull QueryOptions queryOptions);
+
+ /**
+ * Invalidates all cached {@link CachedPermissionData} and {@link CachedMetaData}
+ * instances.
+ */
+ void invalidate();
+
+ /**
+ * Invalidates all of the underlying Permission calculators.
+ *
+ * Can be called to allow for an update in defaults.
+ */
+ void invalidatePermissionCalculators();
+
+ /**
+ * Manages a specific type of {@link CachedData cached data} within
+ * a {@link CachedDataManager} instance.
+ *
+ * @param the data type
+ */
+ interface Container {
+
+ /**
+ * Gets {@link T data} from the cache.
+ *
+ * @param queryOptions the query options
+ * @return a data instance
+ * @throws NullPointerException if contexts is null
+ */
+ @NonNull T get(@NonNull QueryOptions queryOptions);
+
+ /**
+ * Calculates {@link T data}, bypassing the cache.
+ *
+ * The result of this operation is calculated each time the method is called.
+ * The result is not added to the internal cache.
+ *
+ * It is therefore highly recommended to use {@link #get(QueryOptions)} instead.
+ *
+ * The use cases of this method are more around constructing one-time
+ * instances of {@link T data}, without adding the result to the cache.
+ *
+ * @param queryOptions the query options
+ * @return a data instance
+ * @throws NullPointerException if contexts is null
+ */
+ @NonNull T calculate(@NonNull QueryOptions queryOptions);
+
+ /**
+ * (Re)calculates data for a given context.
+ *
+ * This method returns immediately in all cases. The (re)calculation is
+ * performed asynchronously and applied to the cache in the background.
+ *
+ * If there was a previous data instance associated with
+ * the given {@link QueryOptions}, then that instance will continue to be returned by
+ * {@link #get(QueryOptions)} until the recalculation is completed.
+ *
+ * If there was no value calculated and cached prior to the call of this
+ * method, then one will be calculated.
+ *
+ * @param queryOptions the query options
+ * @throws NullPointerException if contexts is null
+ */
+ void recalculate(@NonNull QueryOptions queryOptions);
+
+ /**
+ * (Re)loads permission data for a given context.
+ *
+ * Unlike {@link #recalculate(QueryOptions)}, this method immediately
+ * invalidates any previous data values contained within the cache,
+ * and then schedules a task to reload a new data instance to
+ * replace the one which was invalidated.
+ *
+ * The invalidation happens immediately during the execution of this method.
+ * The result of the re-computation encapsulated by the future.
+ *
+ * Subsequent calls to {@link #get(QueryOptions)} will block until
+ * the result of this operation is complete.
+ *
+ * If there was no value calculated and cached prior to the call of this
+ * method, then one will be calculated.
+ *
+ * This method returns a Future so users can optionally choose to wait
+ * until the recalculation has been performed.
+ *
+ * @param queryOptions the query options.
+ * @return a future
+ * @throws NullPointerException if contexts is null
+ */
+ @NonNull CompletableFuture extends T> reload(@NonNull QueryOptions queryOptions);
+
+ /**
+ * Recalculates data for all known contexts.
+ *
+ * This method returns immediately. The recalculation is performed
+ * asynchronously and applied to the cache in the background.
+ *
+ * The previous data instances will continue to be returned
+ * by {@link #get(QueryOptions)} until the recalculation is completed.
+ */
+ void recalculate();
+
+ /**
+ * Reloads permission data for all known contexts.
+ *
+ * Unlike {@link #recalculate()}, this method immediately
+ * invalidates all previous data values contained within the cache,
+ * and then schedules a task to reload new data instances to
+ * replace the ones which were invalidated.
+ *
+ * The invalidation happens immediately during the execution of this method.
+ * The result of the re-computation encapsulated by the future.
+ *
+ * Subsequent calls to {@link #get(QueryOptions)} will block until
+ * the result of this operation is complete.
+ *
+ * This method returns a Future so users can optionally choose to wait
+ * until the recalculation has been performed.
+ *
+ * @return a future
+ */
+ @NonNull CompletableFuture reload();
+
+ /**
+ * Invalidates any cached data instances mapped to the given context.
+ *
+ * @param queryOptions the queryOptions to invalidate for
+ */
+ void invalidate(@NonNull QueryOptions queryOptions);
+
+ /**
+ * Invalidates all cached data instances.
+ */
+ void invalidate();
+ }
+
+}
diff --git a/api/src/main/java/me/lucko/luckperms/api/caching/MetaData.java b/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedMetaData.java
similarity index 72%
rename from api/src/main/java/me/lucko/luckperms/api/caching/MetaData.java
rename to api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedMetaData.java
index ead912adb..c24984736 100644
--- a/api/src/main/java/me/lucko/luckperms/api/caching/MetaData.java
+++ b/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedMetaData.java
@@ -23,55 +23,50 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api.caching;
-
-import com.google.common.collect.ListMultimap;
+package me.lucko.luckperms.api.cacheddata;
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
+import java.util.List;
import java.util.Map;
import java.util.SortedMap;
/**
* Holds cached meta lookup data for a specific set of contexts.
- *
- * @since 2.13
*/
-public interface MetaData extends CachedDataContainer {
+public interface CachedMetaData extends CachedData {
/**
- * Gets the contexts this container is holding data for.
+ * Gets a value for the given meta key.
*
- * @return the contexts this container is caching
+ * @param key the key
+ * @return the value
*/
- @NonNull MetaContexts getMetaContexts();
+ @Nullable String getMetaValue(String key);
+
+ /**
+ * Gets the user's highest priority prefix, or null if the user has no prefixes
+ *
+ * @return a prefix string, or null
+ */
+ @Nullable String getPrefix();
+
+ /**
+ * Gets the user's highest priority suffix, or null if the user has no suffixes
+ *
+ * @return a suffix string, or null
+ */
+ @Nullable String getSuffix();
/**
* Gets an immutable copy of the meta this user has.
*
- * A list multimap is used because when inherited values are included, each key can be
- * mapped to multiple values.
- *
- * The first value to be accumulated (and used to represent the key in {@link #getMeta()} is at index 0
- * in the list. Any additional values are stored in order of accumulation.
- *
- * @return an immutable multimap of meta
- * @since 3.3
- */
- @NonNull ListMultimap getMetaMultimap();
-
- /**
- * Gets an immutable copy of the meta this user has.
- *
- * This map is formed by taking the entries in {@link #getMetaMultimap()}, and mapping each key
- * to the value at index 0 in the corresponding list.
- *
* @return an immutable map of meta
*/
- @NonNull Map getMeta();
+ @NonNull Map> getMeta();
/**
* Gets an immutable sorted map of all of the prefixes the user has, whereby the first value is the highest priority
@@ -89,25 +84,10 @@ public interface MetaData extends CachedDataContainer {
*/
@NonNull SortedMap getSuffixes();
- /**
- * Gets the user's highest priority prefix, or null if the user has no prefixes
- *
- * @return a prefix string, or null
- */
- @Nullable String getPrefix();
-
- /**
- * Gets the user's highest priority suffix, or null if the user has no suffixes
- *
- * @return a suffix string, or null
- */
- @Nullable String getSuffix();
-
/**
* Gets the definition used for the prefix stack
*
* @return the definition used for the prefix stack
- * @since 3.2
*/
@NonNull MetaStackDefinition getPrefixStackDefinition();
@@ -115,7 +95,6 @@ public interface MetaData extends CachedDataContainer {
* Gets the definition used for the suffix stack
*
* @return the definition used for the suffix stack
- * @since 3.2
*/
@NonNull MetaStackDefinition getSuffixStackDefinition();
diff --git a/api/src/main/java/me/lucko/luckperms/api/caching/PermissionData.java b/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedPermissionData.java
similarity index 87%
rename from api/src/main/java/me/lucko/luckperms/api/caching/PermissionData.java
rename to api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedPermissionData.java
index ac1460de8..94233e763 100644
--- a/api/src/main/java/me/lucko/luckperms/api/caching/PermissionData.java
+++ b/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedPermissionData.java
@@ -23,9 +23,9 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api.caching;
+package me.lucko.luckperms.api.cacheddata;
-import me.lucko.luckperms.api.Tristate;
+import me.lucko.luckperms.api.node.Tristate;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -33,10 +33,8 @@ import java.util.Map;
/**
* Holds cached permission lookup data for a specific set of contexts.
- *
- * @since 2.13
*/
-public interface PermissionData extends CachedDataContainer {
+public interface CachedPermissionData extends CachedData {
/**
* Gets a permission check result for the given permission node.
@@ -45,7 +43,7 @@ public interface PermissionData extends CachedDataContainer {
* @return a tristate result
* @throws NullPointerException if permission is null
*/
- @NonNull Tristate getPermissionValue(@NonNull String permission);
+ @NonNull Tristate checkPermission(@NonNull String permission);
/**
* Invalidates the underlying permission calculator cache.
@@ -59,6 +57,6 @@ public interface PermissionData extends CachedDataContainer {
*
* @return an immutable set of permissions
*/
- @NonNull Map getImmutableBacking();
+ @NonNull Map getPermissionMap();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/caching/CachedData.java b/api/src/main/java/me/lucko/luckperms/api/caching/CachedData.java
deleted file mode 100644
index 1a5e143c8..000000000
--- a/api/src/main/java/me/lucko/luckperms/api/caching/CachedData.java
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * This file is part of LuckPerms, licensed under the MIT License.
- *
- * Copyright (c) lucko (Luck)
- * 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 me.lucko.luckperms.api.PermissionHolder;
-
-import org.checkerframework.checker.nullness.qual.NonNull;
-
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-
-/**
- * Holds cached permission and meta lookup data for a {@link PermissionHolder}.
- *
- * All calls will account for inheritance, as well as any default data
- * provided by the platform. This calls are heavily cached and are therefore
- * fast.
- *
- * For meta, both methods accepting {@link Contexts} and {@link MetaContexts}
- * are provided. The only difference is that the latter allows you to define
- * how the meta stack should be structured internally. Where {@link Contexts}
- * are passed, the values from the configuration are used.
- *
- * @since 4.0
- */
-public interface CachedData {
-
- /**
- * Gets PermissionData from the cache, given a specified context.
- *
- * @param contexts the contexts to get the permission data in
- * @return a permission data instance
- * @throws NullPointerException if contexts is null
- */
- @NonNull PermissionData getPermissionData(@NonNull Contexts contexts);
-
- /**
- * Gets MetaData from the cache, given a specified context.
- *
- * @param contexts the contexts to get the permission data in
- * @return a meta data instance
- * @throws NullPointerException if contexts is null
- * @since 3.2
- */
- @NonNull MetaData getMetaData(@NonNull MetaContexts contexts);
-
- /**
- * Gets MetaData from the cache, given a specified context.
- *
- * @param contexts the contexts to get the permission data in
- * @return a meta data instance
- * @throws NullPointerException if contexts is null
- */
- @NonNull MetaData getMetaData(@NonNull Contexts contexts);
-
- /**
- * Calculates permission data, bypassing the cache.
- *
- * The result of this operation is calculated each time the method is called.
- * The result is not added to the internal cache.
- *
- * It is therefore highly recommended to use {@link #getPermissionData(Contexts)} instead.
- *
- * The use cases of this method are more around constructing one-time
- * instances of {@link PermissionData}, without adding the result to the cache.
- *
- * @param contexts the contexts to get permission data in
- * @return a permission data instance
- * @throws NullPointerException if contexts is null
- */
- @NonNull PermissionData calculatePermissions(@NonNull Contexts contexts);
-
- /**
- * Calculates meta data, bypassing the cache.
- *
- * The result of this operation is calculated each time the method is called.
- * The result is not added to the internal cache.
- *
- * It is therefore highly recommended to use {@link #getMetaData(MetaContexts)} instead.
- *
- * The use cases of this method are more around constructing one-time
- * instances of {@link MetaData}, without adding the result to the cache.
- *
- * @param contexts the contexts to get meta data in
- * @return a meta data instance
- * @throws NullPointerException if contexts is null
- * @since 3.2
- */
- @NonNull MetaData calculateMeta(@NonNull MetaContexts contexts);
-
- /**
- * Calculates meta data, bypassing the cache.
- *
- * The result of this operation is calculated each time the method is called.
- * The result is not added to the internal cache.
- *
- * It is therefore highly recommended to use {@link #getMetaData(Contexts)} instead.
- *
- * The use cases of this method are more around constructing one-time
- * instances of {@link MetaData}, without adding the result to the cache.
- *
- * @param contexts the contexts to get meta data in
- * @return a meta data instance
- * @throws NullPointerException if contexts is null
- */
- @NonNull MetaData calculateMeta(@NonNull Contexts contexts);
-
- /**
- * (Re)calculates permission data for a given context.
- *
- * This method returns immediately in all cases. The (re)calculation is
- * performed asynchronously and applied to the cache in the background.
- *
- * If there was a previous {@link PermissionData} instance associated with
- * the given {@link Contexts}, then that instance will continue to be returned by
- * {@link #getPermissionData(Contexts)} until the recalculation is completed.
- *
- * If there was no value calculated and cached prior to the call of this
- * method, then one will be calculated.
- *
- * @param contexts the contexts to recalculate in.
- * @throws NullPointerException if contexts is null
- */
- void recalculatePermissions(@NonNull Contexts contexts);
-
- /**
- * (Re)calculates meta data for a given context.
- *
- * This method returns immediately in all cases. The (re)calculation is
- * performed asynchronously and applied to the cache in the background.
- *
- * If there was a previous {@link MetaData} instance associated with
- * the given {@link MetaContexts}, then that instance will continue to be returned by
- * {@link #getMetaData(MetaContexts)} until the recalculation is completed.
- *
- * If there was no value calculated and cached prior to the call of this
- * method, then one will be calculated.
- *
- * @param contexts the contexts to recalculate in.
- * @throws NullPointerException if contexts is null
- * @since 3.2
- */
- void recalculateMeta(@NonNull MetaContexts contexts);
-
- /**
- * (Re)calculates meta data for a given context.
- *
- * This method returns immediately in all cases. The (re)calculation is
- * performed asynchronously and applied to the cache in the background.
- *
- * If there was a previous {@link MetaData} instance associated with
- * the given {@link Contexts}, then that instance will continue to be returned by
- * {@link #getMetaData(Contexts)} until the recalculation is completed.
- *
- * If there was no value calculated and cached prior to the call of this
- * method, then one will be calculated.
- *
- * @param contexts the contexts to recalculate in.
- * @throws NullPointerException if contexts is null
- */
- void recalculateMeta(@NonNull Contexts contexts);
-
- /**
- * (Re)loads permission data for a given context.
- *
- * Unlike {@link #recalculatePermissions(Contexts)}, this method immediately
- * invalidates any previous {@link PermissionData} values contained within the cache,
- * and then schedules a task to reload a new {@link PermissionData} instance to
- * replace the one which was invalidated.
- *
- * The invalidation happens immediately during the execution of this method.
- * The result of the re-computation encapsulated by the future.
- *
- * Subsequent calls to {@link #getPermissionData(Contexts)} will block until
- * the result of this operation is complete.
- *
- * If there was no value calculated and cached prior to the call of this
- * method, then one will be calculated.
- *
- * This method returns a Future so users can optionally choose to wait
- * until the recalculation has been performed.
- *
- * @param contexts the contexts to reload in.
- * @return a future
- * @throws NullPointerException if contexts is null
- * @since 4.0
- */
- @NonNull CompletableFuture extends PermissionData> reloadPermissions(@NonNull Contexts contexts);
-
- /**
- * (Re)loads meta data for a given context.
- *
- * Unlike {@link #recalculateMeta(MetaContexts)}, this method immediately
- * invalidates any previous {@link MetaData} values contained within the cache,
- * and then schedules a task to reload a new {@link MetaData} instance to
- * replace the one which was invalidated.
- *
- * The invalidation happens immediately during the execution of this method.
- * The result of the re-computation encapsulated by the future.
- *
- * Subsequent calls to {@link #getMetaData(MetaContexts)} will block until
- * the result of this operation is complete.
- *
- * If there was no value calculated and cached prior to the call of this
- * method, then one will be calculated.
- *
- * This method returns a Future so users can optionally choose to wait
- * until the recalculation has been performed.
- *
- * @param contexts the contexts to reload in.
- * @return a future
- * @throws NullPointerException if contexts is null
- * @since 4.0
- */
- @NonNull CompletableFuture extends MetaData> reloadMeta(@NonNull MetaContexts contexts);
-
- /**
- * (Re)loads meta data for a given context.
- *
- * Unlike {@link #recalculateMeta(Contexts)}, this method immediately
- * invalidates any previous {@link MetaData} values contained within the cache,
- * and then schedules a task to reload a new {@link MetaData} instance to
- * replace the one which was invalidated.
- *
- * The invalidation happens immediately during the execution of this method.
- * The result of the re-computation encapsulated by the future.
- *
- * Subsequent calls to {@link #getMetaData(Contexts)} will block until
- * the result of this operation is complete.
- *
- * If there was no value calculated and cached prior to the call of this
- * method, then one will be calculated.
- *
- * This method returns a Future so users can optionally choose to wait
- * until the recalculation has been performed.
- *
- * @param contexts the contexts to reload in.
- * @return a future
- * @throws NullPointerException if contexts is null
- * @since 4.0
- */
- @NonNull CompletableFuture extends MetaData> reloadMeta(@NonNull Contexts contexts);
-
- /**
- * Recalculates permission data for all known contexts.
- *
- * This method returns immediately. The recalculation is performed
- * asynchronously and applied to the cache in the background.
- *
- * The previous {@link PermissionData} instances will continue to be returned
- * by {@link #getPermissionData(Contexts)} until the recalculation is completed.
- */
- void recalculatePermissions();
-
- /**
- * Recalculates meta data for all known contexts.
- *
- * This method returns immediately. The recalculation is performed
- * asynchronously and applied to the cache in the background.
- *
- * The previous {@link MetaData} instances will continue to be returned
- * by {@link #getMetaData(MetaContexts)} and {@link #getMetaData(Contexts)}
- * until the recalculation is completed.
- */
- void recalculateMeta();
-
- /**
- * Reloads permission data for all known contexts.
- *
- * Unlike {@link #recalculatePermissions()}, this method immediately
- * invalidates all previous {@link PermissionData} values contained within the cache,
- * and then schedules a task to reload a new {@link PermissionData} instances to
- * replace the ones which were invalidated.
- *
- * The invalidation happens immediately during the execution of this method.
- * The result of the re-computation encapsulated by the future.
- *
- * Subsequent calls to {@link #getPermissionData(Contexts)} will block until
- * the result of this operation is complete.
- *
- * This method returns a Future so users can optionally choose to wait
- * until the recalculation has been performed.
- *
- * @return a future
- * @since 4.0
- */
- @NonNull CompletableFuture reloadPermissions();
-
- /**
- * Reloads meta data for all known contexts.
- *
- * Unlike {@link #recalculateMeta()}, this method immediately
- * invalidates all previous {@link MetaData} values contained within the cache,
- * and then schedules a task to reload a new {@link MetaData} instances to
- * replace the ones which were invalidated.
- *
- * The invalidation happens immediately during the execution of this method.
- * The result of the re-computation encapsulated by the future.
- *
- * Subsequent calls to {@link #getMetaData(MetaContexts)} and
- * {@link #getMetaData(Contexts)} will block until the result of this operation
- * is complete.
- *
- * This method returns a Future so users can optionally choose to wait
- * until the recalculation has been performed.
- *
- * @return a future
- * @since 4.0
- */
- @NonNull CompletableFuture reloadMeta();
-
- /**
- * Pre-calculates and caches {@link PermissionData} and {@link MetaData}
- * instances for the given contexts.
- *
- * If the cache already contains a value for the given context,
- * no action is taken.
- *
- * This method blocks until the calculation is completed.
- *
- * @param contexts a set of contexts
- * @throws NullPointerException if contexts is null
- */
- default void preCalculate(@NonNull Set contexts) {
- contexts.forEach(this::preCalculate);
- }
-
- /**
- * Pre-calculates and caches {@link PermissionData} and {@link MetaData}
- * instances for a given context.
- *
- * If the cache already contains a value for the given context,
- * no action is taken.
- *
- * This method blocks until the calculation is completed.
- *
- * @param contexts the contexts to pre-calculate for
- * @throws NullPointerException if contexts is null
- */
- default void preCalculate(@NonNull Contexts contexts) {
- Objects.requireNonNull(contexts, "contexts");
-
- // pre-calculate just by requesting the data from this cache.
- // if the data isn't already loaded, it will be calculated.
- getPermissionData(contexts);
- getMetaData(contexts);
- }
-
- /**
- * Invalidates any cached {@link PermissionData} instances mapped to the given
- * {@link Contexts}.
- *
- * @param contexts the contexts to invalidate for
- * @since 4.0
- */
- void invalidatePermissions(@NonNull Contexts contexts);
-
- /**
- * Invalidates any cached {@link MetaData} instances mapped to the given
- * {@link MetaContexts}.
- *
- * @param contexts the contexts to invalidate for
- * @since 4.0
- */
- void invalidateMeta(@NonNull MetaContexts contexts);
-
- /**
- * Invalidates any cached {@link MetaData} instances mapped to the given
- * {@link Contexts}.
- *
- * @param contexts the contexts to invalidate for
- * @since 4.0
- */
- void invalidateMeta(@NonNull Contexts contexts);
-
- /**
- * Invalidates all cached {@link PermissionData} instances.
- *
- * @since 4.2
- */
- void invalidatePermissions();
-
- /**
- * Invalidates all cached {@link MetaData} instances.
- *
- * @since 4.2
- */
- void invalidateMeta();
-
- /**
- * Invalidates all cached {@link PermissionData} and {@link MetaData}
- * instances.
- *
- * @since 4.5
- */
- void invalidate();
-
- /**
- * Invalidates all of the underlying Permission calculators.
- *
- * Can be called to allow for an update in defaults.
- */
- void invalidatePermissionCalculators();
-
-}
diff --git a/api/src/main/java/me/lucko/luckperms/api/caching/GroupData.java b/api/src/main/java/me/lucko/luckperms/api/caching/GroupData.java
deleted file mode 100644
index 968189c4a..000000000
--- a/api/src/main/java/me/lucko/luckperms/api/caching/GroupData.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is part of LuckPerms, licensed under the MIT License.
- *
- * Copyright (c) lucko (Luck)
- * 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 me.lucko.luckperms.api.Group;
-
-/**
- * Holds cached permission and meta lookup data for a {@link Group}.
- *
- * All calls will account for inheritance, as well as any default data provided
- * by the platform. This calls are heavily cached and are therefore fast.
- *
- * For meta, both methods accepting {@link Contexts} and {@link MetaContexts} are provided. The only difference is that
- * the latter allows you to define how the meta stack should be structured internally. Where {@link Contexts} are passed, the
- * values from the configuration are used.
- *
- * @since 4.0
- */
-public interface GroupData extends CachedData {
-
-}
diff --git a/api/src/main/java/me/lucko/luckperms/api/caching/MetaContexts.java b/api/src/main/java/me/lucko/luckperms/api/caching/MetaContexts.java
deleted file mode 100644
index 1c30a46a4..000000000
--- a/api/src/main/java/me/lucko/luckperms/api/caching/MetaContexts.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * This file is part of LuckPerms, licensed under the MIT License.
- *
- * Copyright (c) lucko (Luck)
- * 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 me.lucko.luckperms.api.metastacking.MetaStackDefinition;
-
-import org.checkerframework.checker.nullness.qual.NonNull;
-
-import java.util.Objects;
-
-/**
- * Encapsulates the options and settings for a meta lookup.
- *
- * Consists of a standard {@link Contexts} element, plus options to define how
- * the meta stack should be constructed.
- *
- * @since 3.2
- */
-public final class MetaContexts {
-
- /**
- * Creates a new meta contexts instance
- *
- * @param contexts the standard contexts for the query
- * @param prefixStackDefinition the prefix stack definition to be used
- * @param suffixStackDefinition the suffix stack definition to be used
- * @return the new instance
- */
- public static MetaContexts of(@NonNull Contexts contexts, @NonNull MetaStackDefinition prefixStackDefinition, @NonNull MetaStackDefinition suffixStackDefinition) {
- return new MetaContexts(contexts, prefixStackDefinition, suffixStackDefinition);
- }
-
- private final Contexts contexts;
- private final MetaStackDefinition prefixStackDefinition;
- private final MetaStackDefinition suffixStackDefinition;
-
- // cache hashcode - this class is immutable, and is used as an index in the permission cache.
- private final int hashCode;
-
- /**
- * Creates a new meta contexts instance
- *
- * @param contexts the standard contexts for the query
- * @param prefixStackDefinition the prefix stack definition to be used
- * @param suffixStackDefinition the suffix stack definition to be used
- */
- public MetaContexts(@NonNull Contexts contexts, @NonNull MetaStackDefinition prefixStackDefinition, @NonNull MetaStackDefinition suffixStackDefinition) {
- this.contexts = Objects.requireNonNull(contexts, "contexts");
- this.prefixStackDefinition = Objects.requireNonNull(prefixStackDefinition, "prefixStackDefinition");
- this.suffixStackDefinition = Objects.requireNonNull(suffixStackDefinition, "suffixStackDefinition");
- this.hashCode = calculateHashCode();
- }
-
- public @NonNull Contexts getContexts() {
- return this.contexts;
- }
-
- public @NonNull MetaStackDefinition getPrefixStackDefinition() {
- return this.prefixStackDefinition;
- }
-
- public @NonNull MetaStackDefinition getSuffixStackDefinition() {
- return this.suffixStackDefinition;
- }
-
- @Override
- public @NonNull String toString() {
- return "MetaContexts(" +
- "contexts=" + this.getContexts() + ", " +
- "prefixStackDefinition=" + this.getPrefixStackDefinition() + ", " +
- "suffixStackDefinition=" + this.getSuffixStackDefinition() +
- ")";
- }
-
- @Override
- public boolean equals(Object o) {
- if (o == this) return true;
- if (!(o instanceof MetaContexts)) return false;
- final MetaContexts that = (MetaContexts) o;
- return this.contexts.equals(that.contexts) &&
- this.prefixStackDefinition.equals(that.prefixStackDefinition) &&
- this.suffixStackDefinition.equals(that.suffixStackDefinition);
- }
-
- private int calculateHashCode() {
- return Objects.hash(this.contexts, this.prefixStackDefinition, this.suffixStackDefinition);
- }
-
- @Override
- public int hashCode() {
- return this.hashCode;
- }
-}
diff --git a/api/src/main/java/me/lucko/luckperms/api/caching/UserData.java b/api/src/main/java/me/lucko/luckperms/api/caching/UserData.java
deleted file mode 100644
index 8de86dcb7..000000000
--- a/api/src/main/java/me/lucko/luckperms/api/caching/UserData.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is part of LuckPerms, licensed under the MIT License.
- *
- * Copyright (c) lucko (Luck)
- * 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 me.lucko.luckperms.api.User;
-
-/**
- * Holds cached permission and meta lookup data for a {@link User}.
- *
- * All calls will account for inheritance, as well as any default data provided by
- * the platform. This calls are heavily cached and are therefore fast.
- *
- * For meta, both methods accepting {@link Contexts} and {@link MetaContexts} are provided. The only difference is that
- * the latter allows you to define how the meta stack should be structured internally. Where {@link Contexts} are passed, the
- * values from the configuration are used.
- *
- * @since 2.13
- */
-public interface UserData extends CachedData {
-
-}
diff --git a/api/src/main/java/me/lucko/luckperms/api/context/ContextCalculator.java b/api/src/main/java/me/lucko/luckperms/api/context/ContextCalculator.java
index ec7b61790..86761cb58 100644
--- a/api/src/main/java/me/lucko/luckperms/api/context/ContextCalculator.java
+++ b/api/src/main/java/me/lucko/luckperms/api/context/ContextCalculator.java
@@ -27,23 +27,71 @@ package me.lucko.luckperms.api.context;
import org.checkerframework.checker.nullness.qual.NonNull;
+import java.util.Objects;
+import java.util.function.Function;
+
/**
- * Calculates whether contexts are applicable to a {@link T subject}.
+ * Calculates the contexts applicable for a contextual subject.
*
- * @param the subject type. Is ALWAYS the player class of the platform.
- * @since 2.13
+ * Implementations of this interface should satisfy the following
+ * requirements:
+ *
+ * Context lookups should be fast : lookup methods are likely to
+ * be invoked frequently, and should therefore be fast to execute. If
+ * determining the current contexts involves a particularly time consuming
+ * lookup (database queries, network requests, etc), then such results
+ * should be cached ahead of time.
+ *
+ * Context lookups should be thread-safe : lookups will sometimes
+ * be performed from "async" threads, and therefore should not access any
+ * part of the server only safe for access from a sync context. If
+ * necessary, such results should be determined ahead of time and stored in
+ * a thread-safe collection for retrieval later.
+ *
+ * Context lookups should not query active contexts : doing so is
+ * likely to result in a stack overflow, or thread deadlock. Care should be
+ * taken to avoid (indirect) calls to the same calculator.
+ *
+ *
+ *
+ * Calculators should be registered using
+ * {@link ContextManager#registerCalculator(ContextCalculator)}.
*/
@FunctionalInterface
public interface ContextCalculator {
/**
- * Gives the subject all of the applicable contexts they meet
+ * Creates a new {@link ContextCalculator} that provides a single context.
*
- * @param subject the subject to add contexts to
- * @param accumulator a map of contexts to add to
- * @return the map
- * @since 2.13
+ * @param key the key of the context provided by the calculator
+ * @param valueFunction the function used to compute the corresponding value
+ * for each query. A context will not be "accumulated"
+ * if the value returned is null.
+ * @param the contextual type
+ * @return the resultant calculator
*/
- @NonNull MutableContextSet giveApplicableContext(@NonNull T subject, @NonNull MutableContextSet accumulator);
+ static @NonNull ContextCalculator forSingleContext(@NonNull String key, @NonNull Function valueFunction) {
+ Objects.requireNonNull(key, "key");
+ Objects.requireNonNull(valueFunction, "valueFunction");
+ return (target, consumer) -> {
+ String value = valueFunction.apply(target);
+ if (value != null) {
+ consumer.accept(key, value);
+ }
+ };
+ }
+
+ /**
+ * Submits any contexts this calculator determines to be applicable to
+ * the {@code target} contextual subject.
+ *
+ * Care should be taken to ensure implementations of this method meet the
+ * general requirements for {@link ContextCalculator}, defined in the class
+ * doc.
+ *
+ * @param target the target contextual subject for this operation
+ * @param consumer the {@link ContextConsumer} to submit contexts to
+ */
+ void giveApplicableContext(@NonNull T target, @NonNull ContextConsumer consumer);
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/DisplayNameType.java b/api/src/main/java/me/lucko/luckperms/api/context/ContextConsumer.java
similarity index 69%
rename from api/src/main/java/me/lucko/luckperms/api/nodetype/types/DisplayNameType.java
rename to api/src/main/java/me/lucko/luckperms/api/context/ContextConsumer.java
index 73995d6b5..83ce5c9fb 100644
--- a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/DisplayNameType.java
+++ b/api/src/main/java/me/lucko/luckperms/api/context/ContextConsumer.java
@@ -23,31 +23,35 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api.nodetype.types;
-
-import me.lucko.luckperms.api.Node;
-import me.lucko.luckperms.api.nodetype.NodeType;
-import me.lucko.luckperms.api.nodetype.NodeTypeKey;
+package me.lucko.luckperms.api.context;
import org.checkerframework.checker.nullness.qual.NonNull;
+import java.util.Map;
+
/**
- * A sub-type of {@link Node} used to mark the display name of the node's holder.
- *
- * @since 4.2
+ * Functional interface that accepts context key value pairs.
*/
-public interface DisplayNameType extends NodeType {
+@FunctionalInterface
+public interface ContextConsumer {
/**
- * The key for this type.
- */
- NodeTypeKey KEY = new NodeTypeKey(){};
-
- /**
- * Gets the display name.
+ * Accepts a context pair.
*
- * @return the display name
+ * @param key the key
+ * @param value the value
*/
- @NonNull String getDisplayName();
+ void accept(@NonNull String key, @NonNull String value);
+
+ /**
+ * Accepts a context set.
+ *
+ * @param contextSet the context set
+ */
+ default void accept(@NonNull ContextSet contextSet) {
+ for (Map.Entry entry : contextSet) {
+ accept(entry.getKey(), entry.getValue());
+ }
+ }
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/context/ContextManager.java b/api/src/main/java/me/lucko/luckperms/api/context/ContextManager.java
index 74a4167f9..d6351227a 100644
--- a/api/src/main/java/me/lucko/luckperms/api/context/ContextManager.java
+++ b/api/src/main/java/me/lucko/luckperms/api/context/ContextManager.java
@@ -25,8 +25,9 @@
package me.lucko.luckperms.api.context;
-import me.lucko.luckperms.api.Contexts;
-import me.lucko.luckperms.api.User;
+import me.lucko.luckperms.api.model.user.User;
+import me.lucko.luckperms.api.query.QueryMode;
+import me.lucko.luckperms.api.query.QueryOptions;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -50,8 +51,6 @@ import java.util.Optional;
* {@code cn.nukkit.Player}
* {@code com.velocitypowered.api.proxy.Player}
*
- *
- * @since 4.0
*/
public interface ContextManager {
@@ -61,15 +60,7 @@ public interface ContextManager {
* @param subject the subject
* @return the applicable context for the subject
*/
- @NonNull ImmutableContextSet getApplicableContext(@NonNull Object subject);
-
- /**
- * Queries the ContextManager for current context values for the subject.
- *
- * @param subject the subject
- * @return the applicable context for the subject
- */
- @NonNull Contexts getApplicableContexts(@NonNull Object subject);
+ @NonNull ImmutableContextSet getContext(@NonNull Object subject);
/**
* Queries the ContextManager for current context values for the given User.
@@ -77,27 +68,14 @@ public interface ContextManager {
* This will only return a value if the player corresponding to the
* {@link User} is online.
*
- * If you need to be a {@link Contexts} instance regardless, you should
- * initially try this method, and then fallback on {@link #getStaticContext()}.
+ * If you need to obtain a {@link ImmutableContextSet} instance
+ * regardless, you should initially try this method, and then fallback on
+ * {@link #getStaticContext()}.
*
* @param user the user
* @return the applicable context for the subject
*/
- @NonNull Optional lookupApplicableContext(@NonNull User user);
-
- /**
- * Queries the ContextManager for current context values for the given User.
- *
- * This will only return a value if the player corresponding to the
- * {@link User} is online.
- *
- * If you need to be a {@link Contexts} instance regardless, you should
- * initially try this method, and then fallback on {@link #getStaticContexts()}.
- *
- * @param user the user
- * @return the applicable context for the subject
- */
- @NonNull Optional lookupApplicableContexts(@NonNull User user);
+ @NonNull Optional lookupContext(@NonNull User user);
/**
* Gets the contexts from the static calculators in this manager.
@@ -110,37 +88,64 @@ public interface ContextManager {
@NonNull ImmutableContextSet getStaticContext();
/**
- * Gets the contexts from the static calculators in this manager.
+ * Creates a new {@link QueryOptions.Builder}.
*
- * Static calculators provide the same context for all subjects, and are
- * marked as such when registered.
- *
- * @return the current active static contexts
+ * @param mode the mode
+ * @return a new query options builder
*/
- @NonNull Contexts getStaticContexts();
+ QueryOptions.@NonNull Builder queryOptionsBuilder(@NonNull QueryMode mode);
/**
- * Forms a {@link Contexts} instance from an {@link ImmutableContextSet}.
+ * Obtains current {@link QueryOptions} for the subject.
+ *
+ * @param subject the subject
+ * @return the query options for the subject
+ */
+ @NonNull QueryOptions getQueryOptions(@NonNull Object subject);
+
+ /**
+ * Obtains current {@link QueryOptions} for the given User.
+ *
+ * This will only return a value if the player corresponding to the
+ * {@link User} is online.
+ *
+ * If you need to obtain a {@link QueryOptions} instance regardless, you should
+ * initially try this method, and then fallback on {@link #getStaticQueryOptions()}.
+ *
+ * @param user the user
+ * @return the query options for the subject
+ */
+ @NonNull Optional lookupQueryOptions(@NonNull User user);
+
+ /**
+ * Gets the static query options, using the registered static context calculators.
+ *
+ * @return the current static query options
+ */
+ @NonNull QueryOptions getStaticQueryOptions();
+
+ /**
+ * Forms a {@link QueryOptions} instance from an {@link ImmutableContextSet}.
*
* This method relies on the plugins configuration to form the
- * {@link Contexts} instance.
+ * {@link QueryOptions} instance.
*
* @param subject the reference subject
* @param contextSet the context set
- * @return a contexts instance
+ * @return a options instance
*/
- @NonNull Contexts formContexts(@NonNull Object subject, @NonNull ImmutableContextSet contextSet);
+ @NonNull QueryOptions formQueryOptions(@NonNull Object subject, @NonNull ImmutableContextSet contextSet);
/**
- * Forms a {@link Contexts} instance from an {@link ImmutableContextSet}.
+ * Forms a {@link QueryOptions} instance from an {@link ImmutableContextSet}.
*
* This method relies on the plugins configuration to form the
- * {@link Contexts} instance.
+ * {@link QueryOptions} instance.
*
* @param contextSet the context set
- * @return a contexts instance
+ * @return a options instance
*/
- @NonNull Contexts formContexts(@NonNull ImmutableContextSet contextSet);
+ @NonNull QueryOptions formQueryOptions(@NonNull ImmutableContextSet contextSet);
/**
* Registers a context calculator with the manager.
@@ -153,10 +158,17 @@ public interface ContextManager {
* Unregisters a context calculator with the manager.
*
* @param calculator the calculator
- * @since 4.4
*/
void unregisterCalculator(@NonNull ContextCalculator> calculator);
+ /**
+ * Gets the {@link ContextSetFactory}, responsible for creating
+ * {@link ContextSet} instances.
+ *
+ * @return the context set factory
+ */
+ @NonNull ContextSetFactory getContextSetFactory();
+
/**
* Invalidates the lookup cache for a given subject
*
diff --git a/api/src/main/java/me/lucko/luckperms/api/context/ContextSet.java b/api/src/main/java/me/lucko/luckperms/api/context/ContextSet.java
index 81f3fd8b3..03d69b55b 100644
--- a/api/src/main/java/me/lucko/luckperms/api/context/ContextSet.java
+++ b/api/src/main/java/me/lucko/luckperms/api/context/ContextSet.java
@@ -25,8 +25,6 @@
package me.lucko.luckperms.api.context;
-import com.google.common.collect.Multimap;
-
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Iterator;
@@ -58,94 +56,9 @@ import java.util.Set;
* Two default ContextSet implementations are provided.
* {@link MutableContextSet} allows the addition and removal of context keys
* after construction, and {@link ImmutableContextSet} does not.
- *
- * @since 2.13
*/
public interface ContextSet extends Iterable> {
- /**
- * Creates an {@link ImmutableContextSet} from a context pair.
- *
- * @param key the key
- * @param value the value
- * @return a new ImmutableContextSet containing one context pair
- * @throws NullPointerException if key or value is null
- */
- static @NonNull ImmutableContextSet singleton(@NonNull String key, @NonNull String value) {
- return ImmutableContextSet.singleton(key, value);
- }
-
- /**
- * Creates an {@link ImmutableContextSet} from two context pairs.
- *
- * @param key1 the first key
- * @param value1 the first value
- * @param key2 the second key
- * @param value2 the second value
- * @return a new ImmutableContextSet containing the two pairs
- * @throws NullPointerException if any of the keys or values are null
- * @since 3.1
- */
- static @NonNull ImmutableContextSet of(@NonNull String key1, @NonNull String value1, @NonNull String key2, @NonNull String value2) {
- return ImmutableContextSet.of(key1, value1, key2, value2);
- }
-
- /**
- * 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
- * @throws NullPointerException if the iterable is null
- */
- static @NonNull ImmutableContextSet fromEntries(@NonNull Iterable extends Map.Entry> iterable) {
- return ImmutableContextSet.fromEntries(iterable);
- }
-
- /**
- * 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
- * @throws NullPointerException if the map is null
- */
- static @NonNull ImmutableContextSet fromMap(@NonNull Map map) {
- return ImmutableContextSet.fromMap(map);
- }
-
- /**
- * 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
- */
- static @NonNull ImmutableContextSet fromMultimap(@NonNull Multimap multimap) {
- return ImmutableContextSet.fromMultimap(multimap);
- }
-
- /**
- * Creates an new {@link ImmutableContextSet} from an existing {@link Set}.
- *
- * Only really useful for converting between mutable and immutable types.
- *
- * @param contextSet the context set to copy from
- * @return a new ImmutableContextSet with the same content and the one provided
- * @throws NullPointerException if contextSet is null
- */
- static @NonNull ImmutableContextSet fromSet(@NonNull ContextSet contextSet) {
- return ImmutableContextSet.fromSet(contextSet);
- }
-
- /**
- * Returns an empty {@link ImmutableContextSet}.
- *
- * @return an empty ImmutableContextSet
- */
- static @NonNull ImmutableContextSet empty() {
- return ImmutableContextSet.empty();
- }
-
/**
* Gets if this {@link ContextSet} is immutable.
*
@@ -163,7 +76,7 @@ public interface ContextSet extends Iterable> {
*
* @return an immutable representation of this set
*/
- @NonNull ImmutableContextSet makeImmutable();
+ @NonNull ImmutableContextSet immutableCopy();
/**
* Creates a mutable copy of this {@link ContextSet}.
@@ -172,7 +85,6 @@ public interface ContextSet extends Iterable> {
* {@link #isImmutable() mutability} of this set.
*
* @return a mutable ContextSet
- * @since 2.16
*/
@NonNull MutableContextSet mutableCopy();
@@ -187,6 +99,17 @@ public interface ContextSet extends Iterable> {
*/
@NonNull Set> toSet();
+ /**
+ * Returns a {@link Map} representing the current state of this
+ * {@link ContextSet}.
+ *
+ * The returned set is immutable, and is a copy of the current set.
+ * (will not update live)
+ *
+ * @return a map
+ */
+ @NonNull Map> toMap();
+
/**
* Returns a {@link Map} loosely representing the current state of
* this {@link ContextSet}.
@@ -197,27 +120,11 @@ public interface ContextSet extends Iterable> {
* As a single context key can be mapped to multiple values, this method
* may not be a true representation of the set.
*
- * If you need a representation of the set in a Java collection instance,
- * use {@link #toSet()} or {@link #toMultimap()} followed by
- * {@link Multimap#asMap()}.
- *
* @return an immutable map
* @deprecated because the resultant map may not contain all data in the ContextSet
*/
@Deprecated
- @NonNull Map toMap();
-
- /**
- * Returns a {@link Multimap} representing the current state of this
- * {@link ContextSet}.
- *
- * The returned multimap is immutable, and is a copy of the current set.
- * (will not update live)
- *
- * @return a multimap
- * @since 2.16
- */
- @NonNull Multimap toMultimap();
+ @NonNull Map toFlattenedMap();
/**
* Returns an {@link Iterator} over each of the context pairs in this set.
@@ -262,7 +169,6 @@ public interface ContextSet extends Iterable> {
*
* @param key the key to find values for
* @return an optional containing any match
- * @since 3.1
*/
default @NonNull Optional getAnyValue(@NonNull String key) {
return getValues(key).stream().findAny();
@@ -276,7 +182,7 @@ public interface ContextSet extends Iterable> {
* @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);
+ boolean contains(@NonNull String key, @NonNull String value);
/**
* Returns if the {@link ContextSet} contains a given context pairing.
@@ -285,9 +191,9 @@ public interface ContextSet extends Iterable> {
* @return true if the set contains the context pair
* @throws NullPointerException if the key or value is null
*/
- default boolean has(Map.@NonNull Entry entry) {
+ default boolean contains(Map.@NonNull Entry entry) {
Objects.requireNonNull(entry, "entry");
- return has(entry.getKey(), entry.getValue());
+ return contains(entry.getKey(), entry.getValue());
}
/**
@@ -300,7 +206,6 @@ public interface ContextSet extends Iterable> {
*
* @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) {
if (this == other) {
@@ -320,7 +225,7 @@ public interface ContextSet extends Iterable> {
} else {
// neither are empty, we need to compare the individual entries
for (Map.Entry context : toSet()) {
- if (!other.has(context)) {
+ if (!other.contains(context)) {
return false;
}
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/context/ContextSetFactory.java b/api/src/main/java/me/lucko/luckperms/api/context/ContextSetFactory.java
new file mode 100644
index 000000000..b30a5cf91
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/context/ContextSetFactory.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of LuckPerms, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * 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.context;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+/**
+ * A factory for creating {@link ContextSet}s.
+ */
+public interface ContextSetFactory {
+
+ ImmutableContextSet.@NonNull Builder immutableBuilder();
+
+ @NonNull ImmutableContextSet immutableOf(@NonNull String key, @NonNull String value);
+
+ @NonNull ImmutableContextSet immutableOf(@NonNull String key1, @NonNull String value1, @NonNull String key2, @NonNull String value2);
+
+ @NonNull ImmutableContextSet immutableEmpty();
+
+ @NonNull MutableContextSet mutable();
+
+}
diff --git a/api/src/main/java/me/lucko/luckperms/api/context/DefaultContextKeys.java b/api/src/main/java/me/lucko/luckperms/api/context/DefaultContextKeys.java
new file mode 100644
index 000000000..16506a6c1
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/context/DefaultContextKeys.java
@@ -0,0 +1,44 @@
+/*
+ * This file is part of LuckPerms, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * 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.context;
+
+/**
+ * Some default context keys used by the plugin.
+ */
+public enum DefaultContextKeys {
+ ;
+
+ /**
+ * The context key used to denote the subjects server.
+ */
+ public static final String SERVER_KEY = "server";
+
+ /**
+ * The context key used to denote the subjects world.
+ */
+ public static final String WORLD_KEY = "world";
+
+}
diff --git a/api/src/main/java/me/lucko/luckperms/api/context/ImmutableContextSet.java b/api/src/main/java/me/lucko/luckperms/api/context/ImmutableContextSet.java
index f1ee27967..35d8306a4 100644
--- a/api/src/main/java/me/lucko/luckperms/api/context/ImmutableContextSet.java
+++ b/api/src/main/java/me/lucko/luckperms/api/context/ImmutableContextSet.java
@@ -25,35 +25,26 @@
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 com.google.common.collect.SetMultimap;
+import me.lucko.luckperms.api.LuckPermsProvider;
import org.checkerframework.checker.nullness.qual.NonNull;
-import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
-import java.util.Spliterator;
/**
* An immutable implementation of {@link ContextSet}.
- *
- * @since 2.16
*/
-public final class ImmutableContextSet extends AbstractContextSet implements ContextSet {
- private static final ImmutableContextSet EMPTY = new ImmutableContextSet(ImmutableSetMultimap.of());
+public interface ImmutableContextSet extends ContextSet {
/**
* Creates an {@link ImmutableContextSet.Builder}.
*
* @return a new ImmutableContextSet builder
- * @since 4.1
*/
- public static @NonNull Builder builder() {
- return new Builder();
+ static @NonNull Builder builder() {
+ return LuckPermsProvider.get().getContextManager().getContextSetFactory().immutableBuilder();
}
/**
@@ -64,8 +55,8 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
* @return a new ImmutableContextSet containing one context pair
* @throws NullPointerException if key or value is null
*/
- public static @NonNull ImmutableContextSet singleton(@NonNull String key, @NonNull String value) {
- return new ImmutableContextSet(ImmutableSetMultimap.of(sanitizeKey(key), sanitizeValue(value)));
+ static @NonNull ImmutableContextSet of(@NonNull String key, @NonNull String value) {
+ return LuckPermsProvider.get().getContextManager().getContextSetFactory().immutableOf(key, value);
}
/**
@@ -77,15 +68,9 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
* @param value2 the second value
* @return a new ImmutableContextSet containing the two pairs
* @throws NullPointerException if any of the keys or values are null
- * @since 3.1
*/
- public static @NonNull ImmutableContextSet of(@NonNull String key1, @NonNull String value1, @NonNull String key2, @NonNull String value2) {
- return new ImmutableContextSet(ImmutableSetMultimap.of(
- sanitizeKey(key1),
- sanitizeValue(value1),
- sanitizeKey(key2),
- sanitizeValue(value2)
- ));
+ static @NonNull ImmutableContextSet of(@NonNull String key1, @NonNull String value1, @NonNull String key2, @NonNull String value2) {
+ return LuckPermsProvider.get().getContextManager().getContextSetFactory().immutableOf(key1, value1, key2, value2);
}
/**
@@ -95,38 +80,15 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
* @return a new ImmutableContextSet representing the pairs in the iterable
* @throws NullPointerException if the iterable is null
*/
- public static @NonNull ImmutableContextSet fromEntries(@NonNull Iterable extends Map.Entry> iterable) {
+ static @NonNull ImmutableContextSet fromEntries(@NonNull Iterable extends Map.Entry> iterable) {
Objects.requireNonNull(iterable, "iterable");
- ImmutableContextSet.Builder builder = builder();
+ Builder builder = builder();
for (Map.Entry entry : iterable) {
builder.add(entry);
}
return builder.build();
}
- /**
- * 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
- * @throws NullPointerException if the map is null
- */
- public static @NonNull ImmutableContextSet fromMap(@NonNull Map map) {
- return fromEntries(Objects.requireNonNull(map, "map").entrySet());
- }
-
- /**
- * 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
- */
- public static @NonNull ImmutableContextSet fromMultimap(@NonNull Multimap multimap) {
- return fromEntries(Objects.requireNonNull(multimap, "multimap").entries());
- }
-
/**
* Creates an new {@link ImmutableContextSet} from an existing {@link Set}.
*
@@ -136,8 +98,8 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
* @return a new ImmutableContextSet with the same content and the one provided
* @throws NullPointerException if contextSet is null
*/
- public static @NonNull ImmutableContextSet fromSet(@NonNull ContextSet contextSet) {
- return Objects.requireNonNull(contextSet, "contextSet").makeImmutable();
+ static @NonNull ImmutableContextSet fromSet(@NonNull ContextSet contextSet) {
+ return Objects.requireNonNull(contextSet, "contextSet").immutableCopy();
}
/**
@@ -145,128 +107,21 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
*
* @return an empty ImmutableContextSet
*/
- public static @NonNull ImmutableContextSet empty() {
- return EMPTY;
- }
-
- private final ImmutableSetMultimap map;
- private final int hashCode;
-
- ImmutableContextSet(ImmutableSetMultimap contexts) {
- this.map = contexts;
- this.hashCode = this.map.hashCode();
- }
-
- @Override
- protected SetMultimap backing() {
- return this.map;
- }
-
- @Override
- protected void copyTo(SetMultimap other) {
- other.putAll(this.map);
- }
-
- @Override
- public boolean isImmutable() {
- return true;
- }
-
- @Deprecated
- @Override // This set is already immutable!
- public @NonNull ImmutableContextSet makeImmutable() {
- return this;
- }
-
- @Override
- public @NonNull MutableContextSet mutableCopy() {
- return MutableContextSet.fromSet(this);
- }
-
- @Override
- public @NonNull Set> toSet() {
- return this.map.entries();
- }
-
- @Deprecated
- @Override
- public @NonNull Map toMap() {
- ImmutableMap.Builder m = ImmutableMap.builder();
- for (Map.Entry e : this.map.entries()) {
- m.put(e.getKey(), e.getValue());
- }
- return m.build();
- }
-
- @Override
- public @NonNull Multimap toMultimap() {
- return this.map;
- }
-
- @Override
- public @NonNull Iterator> iterator() {
- return this.map.entries().iterator();
- }
-
- @Override
- public Spliterator> spliterator() {
- return this.map.entries().spliterator();
- }
-
- @Override
- public boolean equals(Object o) {
- if (o == this) return true;
- if (!(o instanceof ContextSet)) return false;
- final ContextSet that = (ContextSet) o;
-
- // fast(er) path for ImmutableContextSet comparisons
- if (that instanceof ImmutableContextSet) {
- ImmutableContextSet immutableThat = (ImmutableContextSet) that;
- if (this.hashCode != immutableThat.hashCode) return false;
- }
-
- final Multimap thatBacking;
- if (that instanceof AbstractContextSet) {
- thatBacking = ((AbstractContextSet) that).backing();
- } else {
- thatBacking = that.toMultimap();
- }
-
- return backing().equals(thatBacking);
- }
-
- @Override
- public int hashCode() {
- return this.hashCode;
- }
-
- @Override
- public String toString() {
- return "ImmutableContextSet(contexts=" + this.map + ")";
+ static @NonNull ImmutableContextSet empty() {
+ return LuckPermsProvider.get().getContextManager().getContextSetFactory().immutableEmpty();
}
/**
- * A builder for {@link ImmutableContextSet}.
- *
- * @since 4.1
+ * @deprecated Already immutable!
*/
- public static final class Builder {
- private ImmutableSetMultimap.Builder builder;
+ @Override
+ @Deprecated
+ @NonNull ImmutableContextSet immutableCopy();
- private Builder() {
-
- }
-
- private synchronized ImmutableSetMultimap.Builder builder() {
- if (this.builder == null) {
- this.builder = ImmutableSetMultimap.builder();
- }
- return this.builder;
- }
-
- private void put(String key, String value) {
- builder().put(key, value);
- }
+ /**
+ * A builder for {@link ImmutableContextSet}.
+ */
+ interface Builder {
/**
* Adds a context to the set.
@@ -277,10 +132,7 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
* @throws NullPointerException if the key or value is null
* @see MutableContextSet#add(String, String)
*/
- public @NonNull Builder add(@NonNull String key, @NonNull String value) {
- put(sanitizeKey(key), sanitizeValue(value));
- return this;
- }
+ @NonNull Builder add(@NonNull String key, @NonNull String value);
/**
* Adds a context to the set.
@@ -290,7 +142,7 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
* @throws NullPointerException if the entry is null
* @see MutableContextSet#add(Map.Entry)
*/
- public @NonNull Builder add(Map.@NonNull Entry entry) {
+ default @NonNull Builder add(Map.@NonNull Entry entry) {
Objects.requireNonNull(entry, "entry");
add(entry.getKey(), entry.getValue());
return this;
@@ -304,40 +156,13 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
* @throws NullPointerException if iterable is null
* @see MutableContextSet#addAll(Iterable)
*/
- public @NonNull Builder addAll(@NonNull Iterable extends Map.Entry> iterable) {
+ default @NonNull Builder addAll(@NonNull Iterable extends Map.Entry> iterable) {
for (Map.Entry e : Objects.requireNonNull(iterable, "iterable")) {
add(e);
}
return this;
}
- /**
- * 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)
- */
- public @NonNull Builder addAll(@NonNull Map map) {
- addAll(Objects.requireNonNull(map, "map").entrySet());
- return this;
- }
-
- /**
- * 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)
- */
- public @NonNull Builder addAll(@NonNull Multimap multimap) {
- addAll(Objects.requireNonNull(multimap, "multimap").entries());
- return this;
- }
-
/**
* Adds of of the contexts in another {@link ContextSet} to the set.
*
@@ -346,18 +171,7 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
* @throws NullPointerException if the contextSet is null
* @see MutableContextSet#addAll(ContextSet)
*/
- public @NonNull Builder addAll(@NonNull ContextSet contextSet) {
- Objects.requireNonNull(contextSet, "contextSet");
- if (contextSet instanceof AbstractContextSet) {
- AbstractContextSet other = ((AbstractContextSet) contextSet);
- if (!other.isEmpty()) {
- builder().putAll(other.backing());
- }
- } else {
- addAll(contextSet.toMultimap());
- }
- return this;
- }
+ @NonNull Builder addAll(@NonNull ContextSet contextSet);
/**
* Creates a {@link ImmutableContextSet} from the values previously
@@ -365,12 +179,6 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
*
* @return an {@link ImmutableContextSet} from the builder
*/
- public @NonNull ImmutableContextSet build() {
- if (this.builder == null) {
- return empty();
- } else {
- return new ImmutableContextSet(this.builder.build());
- }
- }
+ @NonNull ImmutableContextSet build();
}
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/context/MutableContextSet.java b/api/src/main/java/me/lucko/luckperms/api/context/MutableContextSet.java
index 6ec0f415f..851ee4b1d 100644
--- a/api/src/main/java/me/lucko/luckperms/api/context/MutableContextSet.java
+++ b/api/src/main/java/me/lucko/luckperms/api/context/MutableContextSet.java
@@ -25,28 +25,18 @@
package me.lucko.luckperms.api.context;
-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;
-import com.google.common.collect.Multimaps;
-import com.google.common.collect.SetMultimap;
+import me.lucko.luckperms.api.LuckPermsProvider;
import org.checkerframework.checker.nullness.qual.NonNull;
-import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
-import java.util.Spliterator;
/**
* A mutable implementation of {@link ContextSet}.
- *
- * @since 2.16
*/
-public final class MutableContextSet extends AbstractContextSet implements ContextSet {
+public interface MutableContextSet extends ContextSet {
/**
* Creates a {@link MutableContextSet} from a context pair.
@@ -56,10 +46,10 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
* @return a new MutableContextSet containing one context pair
* @throws NullPointerException if key or value is null
*/
- public static @NonNull MutableContextSet singleton(@NonNull String key, @NonNull String value) {
+ static @NonNull MutableContextSet of(@NonNull String key, @NonNull String value) {
Objects.requireNonNull(key, "key");
Objects.requireNonNull(value, "value");
- MutableContextSet set = MutableContextSet.create();
+ MutableContextSet set = create();
set.add(key, value);
return set;
}
@@ -73,9 +63,8 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
* @param value2 the second value
* @return a new MutableContextSet containing the two pairs
* @throws NullPointerException if any of the keys or values are null
- * @since 3.1
*/
- public static @NonNull MutableContextSet of(@NonNull String key1, @NonNull String value1, @NonNull String key2, @NonNull String value2) {
+ static @NonNull MutableContextSet of(@NonNull String key1, @NonNull String value1, @NonNull String key2, @NonNull String value2) {
Objects.requireNonNull(key1, "key1");
Objects.requireNonNull(value1, "value1");
Objects.requireNonNull(key2, "key2");
@@ -93,42 +82,13 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
* @return a new MutableContextSet representing the pairs in the iterable
* @throws NullPointerException if the iterable is null
*/
- public static @NonNull MutableContextSet fromEntries(@NonNull Iterable extends Map.Entry> iterable) {
+ static @NonNull MutableContextSet fromEntries(@NonNull Iterable extends Map.Entry> iterable) {
Objects.requireNonNull(iterable, "iterable");
MutableContextSet set = create();
set.addAll(iterable);
return set;
}
- /**
- * 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
- * @throws NullPointerException if the map is null
- */
- public static @NonNull MutableContextSet fromMap(@NonNull Map map) {
- Objects.requireNonNull(map, "map");
- MutableContextSet set = create();
- set.addAll(map);
- return set;
- }
-
- /**
- * 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
- */
- public static @NonNull MutableContextSet fromMultimap(@NonNull Multimap multimap) {
- Objects.requireNonNull(multimap, "multimap");
- MutableContextSet set = create();
- set.addAll(multimap);
- return set;
- }
-
/**
* Creates a new {@link MutableContextSet} from an existing {@link Set}.
*
@@ -138,19 +98,8 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
* @return a new MutableContextSet with the same content and the one provided
* @throws NullPointerException if contextSet is null
*/
- public static @NonNull MutableContextSet fromSet(@NonNull ContextSet contextSet) {
- Objects.requireNonNull(contextSet, "contextSet");
-
- if (contextSet instanceof ImmutableContextSet) {
- SetMultimap map = ((ImmutableContextSet) contextSet).backing();
- return new MutableContextSet(map);
- } else if (contextSet instanceof MutableContextSet) {
- return contextSet.mutableCopy();
- } else {
- MutableContextSet set = create();
- set.addAll(contextSet);
- return set;
- }
+ static @NonNull MutableContextSet fromSet(@NonNull ContextSet contextSet) {
+ return contextSet.mutableCopy();
}
/**
@@ -158,90 +107,8 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
*
* @return a new MutableContextSet
*/
- public static @NonNull MutableContextSet create() {
- return new MutableContextSet();
- }
-
- private final SetMultimap map;
-
- public MutableContextSet() {
- this.map = Multimaps.synchronizedSetMultimap(HashMultimap.create());
- }
-
- private MutableContextSet(SetMultimap other) {
- this.map = Multimaps.synchronizedSetMultimap(HashMultimap.create(other));
- }
-
- @Override
- protected SetMultimap backing() {
- return this.map;
- }
-
- @Override
- protected void copyTo(SetMultimap other) {
- synchronized (this.map) {
- other.putAll(this.map);
- }
- }
-
- @Override
- public boolean isImmutable() {
- return false;
- }
-
- @Override
- public @NonNull ImmutableContextSet makeImmutable() {
- // if the map is empty, don't create a new instance
- if (this.map.isEmpty()) {
- return ImmutableContextSet.empty();
- }
- synchronized (this.map) {
- return new ImmutableContextSet(ImmutableSetMultimap.copyOf(this.map));
- }
- }
-
- @Override
- public @NonNull MutableContextSet mutableCopy() {
- synchronized (this.map) {
- return new MutableContextSet(this.map);
- }
- }
-
- @Override
- public @NonNull Set> toSet() {
- synchronized (this.map) {
- // map.entries() returns immutable Map.Entry instances, so we can just call copyOf
- return ImmutableSet.copyOf(this.map.entries());
- }
- }
-
- @Deprecated
- @Override
- public @NonNull Map toMap() {
- ImmutableMap.Builder m = ImmutableMap.builder();
- synchronized (this.map) {
- for (Map.Entry e : this.map.entries()) {
- m.put(e.getKey(), e.getValue());
- }
- }
- return m.build();
- }
-
- @Override
- public @NonNull Multimap toMultimap() {
- synchronized (this.map) {
- return ImmutableSetMultimap.copyOf(this.map);
- }
- }
-
- @Override
- public @NonNull Iterator> iterator() {
- return toSet().iterator();
- }
-
- @Override
- public Spliterator> spliterator() {
- return toSet().spliterator();
+ static @NonNull MutableContextSet create() {
+ return LuckPermsProvider.get().getContextManager().getContextSetFactory().mutable();
}
/**
@@ -251,9 +118,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
* @param value the value to add
* @throws NullPointerException if the key or value is null
*/
- public void add(@NonNull String key, @NonNull String value) {
- this.map.put(sanitizeKey(key), sanitizeValue(value));
- }
+ void add(@NonNull String key, @NonNull String value);
/**
* Adds a context to this set.
@@ -261,7 +126,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
* @param entry the entry to add
* @throws NullPointerException if the entry is null
*/
- public void add(Map.@NonNull Entry entry) {
+ default void add(Map.@NonNull Entry entry) {
Objects.requireNonNull(entry, "entry");
add(entry.getKey(), entry.getValue());
}
@@ -272,50 +137,19 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
* @param iterable an iterable of key value context pairs
* @throws NullPointerException if iterable is null
*/
- public void addAll(@NonNull Iterable extends Map.Entry> iterable) {
+ default void addAll(@NonNull Iterable extends Map.Entry> iterable) {
for (Map.Entry e : Objects.requireNonNull(iterable, "iterable")) {
add(e);
}
}
- /**
- * 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
- */
- public void addAll(@NonNull Map map) {
- addAll(Objects.requireNonNull(map, "map").entrySet());
- }
-
- /**
- * 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
- * @since 3.4
- */
- public void addAll(@NonNull Multimap multimap) {
- addAll(Objects.requireNonNull(multimap, "multimap").entries());
- }
-
/**
* 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
*/
- public void addAll(@NonNull ContextSet contextSet) {
- Objects.requireNonNull(contextSet, "contextSet");
- if (contextSet instanceof AbstractContextSet) {
- AbstractContextSet other = ((AbstractContextSet) contextSet);
- synchronized (this.map) {
- other.copyTo(this.map);
- }
- } else {
- addAll(contextSet.toMultimap());
- }
- }
+ void addAll(@NonNull ContextSet contextSet);
/**
* Removes a context from this set.
@@ -324,9 +158,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
* @param value the value to remove
* @throws NullPointerException if the key or value is null
*/
- public void remove(@NonNull String key, @NonNull String value) {
- this.map.remove(sanitizeKey(key), sanitizeValue(value));
- }
+ void remove(@NonNull String key, @NonNull String value);
/**
* Removes all contexts from this set with the given key.
@@ -334,35 +166,11 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
* @param key the key to remove
* @throws NullPointerException if the key is null
*/
- public void removeAll(@NonNull String key) {
- this.map.removeAll(sanitizeKey(key));
- }
+ void removeAll(@NonNull String key);
/**
* Removes all contexts from the set.
*/
- public void clear() {
- this.map.clear();
- }
+ void clear();
- @Override
- public boolean equals(Object o) {
- if (o == this) return true;
- if (!(o instanceof ContextSet)) return false;
- final ContextSet that = (ContextSet) o;
-
- final Multimap thatBacking;
- if (that instanceof AbstractContextSet) {
- thatBacking = ((AbstractContextSet) that).backing();
- } else {
- thatBacking = that.toMultimap();
- }
-
- return backing().equals(thatBacking);
- }
-
- @Override
- public String toString() {
- return "MutableContextSet(contexts=" + this.map + ")";
- }
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/context/StaticContextCalculator.java b/api/src/main/java/me/lucko/luckperms/api/context/StaticContextCalculator.java
index de4fb8a99..53afa5246 100644
--- a/api/src/main/java/me/lucko/luckperms/api/context/StaticContextCalculator.java
+++ b/api/src/main/java/me/lucko/luckperms/api/context/StaticContextCalculator.java
@@ -26,36 +26,50 @@
package me.lucko.luckperms.api.context;
import org.checkerframework.checker.nullness.qual.NonNull;
-import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.Objects;
+import java.util.function.Supplier;
/**
* Extension of {@link ContextCalculator} which provides the same context
* regardless of the subject.
- *
- * @since 4.0
*/
@FunctionalInterface
public interface StaticContextCalculator extends ContextCalculator {
/**
- * Adds this calculators context to the given accumulator.
+ * Creates a new {@link StaticContextCalculator} that provides a single context.
*
- * @param accumulator a map of contexts to add to
- * @return the map
+ * @param key the key of the context provided by the calculator
+ * @param valueFunction the function used to compute the corresponding value
+ * for each query. A context will not be "accumulated"
+ * if the value returned is null.
+ * @return the resultant calculator
*/
- @NonNull MutableContextSet giveApplicableContext(@NonNull MutableContextSet accumulator);
-
- /**
- * Gives the subject all of the applicable contexts they meet
- *
- * @param subject the subject to add contexts to
- * @param accumulator a map of contexts to add to
- * @return the map
- */
- @Deprecated
- @Override
- default @NonNull MutableContextSet giveApplicableContext(@Nullable Object subject, @NonNull MutableContextSet accumulator) {
- return giveApplicableContext(accumulator);
+ static StaticContextCalculator forSingleContext(String key, Supplier valueFunction) {
+ Objects.requireNonNull(key, "key");
+ Objects.requireNonNull(valueFunction, "valueFunction");
+ return consumer -> {
+ String value = valueFunction.get();
+ if (value != null) {
+ consumer.accept(key, value);
+ }
+ };
}
+ /**
+ * Submits any contexts this calculator determines to be applicable.
+ *
+ * Care should be taken to ensure implementations of this method meet the
+ * general requirements for {@link ContextCalculator}, defined in the class
+ * doc.
+ *
+ * @param consumer the {@link ContextConsumer} to submit contexts to
+ */
+ void giveApplicableContext(@NonNull ContextConsumer consumer);
+
+ @Override
+ default void giveApplicableContext(@NonNull Object target, @NonNull ContextConsumer consumer) {
+ giveApplicableContext(consumer);
+ }
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/Cancellable.java b/api/src/main/java/me/lucko/luckperms/api/event/Cancellable.java
index a63e8e4af..5b8a655c1 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/Cancellable.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/Cancellable.java
@@ -39,13 +39,13 @@ public interface Cancellable {
*
* @return the cancellation
*/
- @NonNull @Param(-1) AtomicBoolean getCancellationState();
+ @Param(-1)
+ @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();
@@ -55,7 +55,6 @@ public interface Cancellable {
* Returns true if the event is not currently cancelled.
*
* @return if the event is not cancelled
- * @since 4.1
*/
default boolean isNotCancelled() {
return !isCancelled();
@@ -66,7 +65,6 @@ public interface Cancellable {
*
* @param cancelled the new state
* @return the previous state
- * @since 4.1
*/
default boolean setCancelled(boolean cancelled) {
return getCancellationState().getAndSet(cancelled);
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/EventBus.java b/api/src/main/java/me/lucko/luckperms/api/event/EventBus.java
index 0dffe5fe6..4f9578242 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/EventBus.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/EventBus.java
@@ -34,15 +34,13 @@ import java.util.function.Consumer;
* The LuckPerms event bus.
*
* Used to subscribe (or "listen") to LuckPerms events.
- *
- * @since 3.0
*/
public interface EventBus {
/**
* Registers a new subscription to the given event.
*
- * The returned {@link EventHandler} instance encapsulates the subscription state. It has
+ *
The returned {@link EventSubscription} instance encapsulates the subscription state. It has
* methods which can be used to terminate the subscription, or view stats about the nature of
* the subscription.
*
@@ -51,18 +49,18 @@ public interface EventBus {
* @param the event class
* @return an event handler instance representing this subscription
*/
- @NonNull EventHandler subscribe(@NonNull Class eventClass, @NonNull Consumer super T> handler);
+ @NonNull EventSubscription subscribe(@NonNull Class eventClass, @NonNull Consumer super T> handler);
/**
* Registers a new subscription to the given event.
*
- * The returned {@link EventHandler} instance encapsulates the subscription state. It has
+ *
The returned {@link EventSubscription} instance encapsulates the subscription state. It has
* methods which can be used to terminate the subscription, or view stats about the nature of
* the subscription.
*
* Unlike {@link #subscribe(Class, Consumer)}, this method accepts an additional parameter
* for {@code plugin}. This object must be a "plugin" instance on the platform, and is used to
- * automatically {@link EventHandler#unregister() unregister} the subscription when the
+ * automatically {@link EventSubscription#close() unregister} the subscription when the
* corresponding plugin is disabled.
*
* @param the event class
@@ -71,7 +69,7 @@ public interface EventBus {
* @param handler the event handler
* @return an event handler instance representing this subscription
*/
- @NonNull EventHandler subscribe(Object plugin, @NonNull Class eventClass, @NonNull Consumer super T> handler);
+ @NonNull EventSubscription subscribe(Object plugin, @NonNull Class eventClass, @NonNull Consumer super T> handler);
/**
* Gets a set of all registered handlers for a given event.
@@ -80,6 +78,6 @@ public interface EventBus {
* @param the event class
* @return an immutable set of event handlers
*/
- @NonNull Set> getHandlers(@NonNull Class eventClass);
+ @NonNull Set> getSubscriptions(@NonNull Class eventClass);
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/EventHandler.java b/api/src/main/java/me/lucko/luckperms/api/event/EventSubscription.java
similarity index 79%
rename from api/src/main/java/me/lucko/luckperms/api/event/EventHandler.java
rename to api/src/main/java/me/lucko/luckperms/api/event/EventSubscription.java
index 4b77721aa..d6288e22c 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/EventHandler.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/EventSubscription.java
@@ -34,7 +34,7 @@ import java.util.function.Consumer;
*
* @param the event class
*/
-public interface EventHandler extends AutoCloseable {
+public interface EventSubscription extends AutoCloseable {
/**
* Gets the class this handler is listening to
@@ -51,28 +51,15 @@ public interface EventHandler extends AutoCloseable {
boolean isActive();
/**
- * Unregisters this handler from the event bus
- *
- * @return true if the handler wasn't already unregistered
+ * Unregisters this handler from the event bus.
*/
- boolean unregister();
+ @Override
+ void close();
/**
* Gets the event consumer responsible for handling the event
*
* @return the event consumer
*/
- @NonNull Consumer super T> getConsumer();
-
- /**
- * Gets the number of times this handler has been called
- *
- * @return the number of times this handler has been called
- */
- int getCallCount();
-
- @Override
- default void close() {
- unregister();
- }
+ @NonNull Consumer super T> getHandler();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/LuckPermsEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/LuckPermsEvent.java
index 638871c4f..77f0ed714 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/LuckPermsEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/LuckPermsEvent.java
@@ -25,14 +25,12 @@
package me.lucko.luckperms.api.event;
-import me.lucko.luckperms.api.LuckPermsApi;
+import me.lucko.luckperms.api.LuckPerms;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* A superinterface for all LuckPerms events.
- *
- * @since 3.0
*/
public interface LuckPermsEvent {
@@ -41,13 +39,12 @@ public interface LuckPermsEvent {
*
* @return the api instance
*/
- @NonNull LuckPermsApi getApi();
+ @NonNull LuckPerms getLuckPerms();
/**
* Gets the type of the event.
*
* @return the type of the event
- * @since 4.4
*/
@NonNull Class extends LuckPermsEvent> getEventType();
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/Sourced.java b/api/src/main/java/me/lucko/luckperms/api/event/Sourced.java
index 921167360..ab7ae04f7 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/Sourced.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/Sourced.java
@@ -31,8 +31,6 @@ import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Represents an event with a {@link Source}.
- *
- * @since 4.1
*/
public interface Sourced {
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupCacheLoadEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupCacheLoadEvent.java
index e4055736f..b30ca3a25 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupCacheLoadEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupCacheLoadEvent.java
@@ -25,17 +25,15 @@
package me.lucko.luckperms.api.event.group;
-import me.lucko.luckperms.api.Group;
-import me.lucko.luckperms.api.caching.GroupData;
+import me.lucko.luckperms.api.cacheddata.CachedDataManager;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
+import me.lucko.luckperms.api.model.group.Group;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
- * Called when a groups {@link GroupData} is loaded.
- *
- * @since 4.0
+ * Called when a groups {@link CachedDataManager} is loaded.
*/
public interface GroupCacheLoadEvent extends LuckPermsEvent {
@@ -44,13 +42,15 @@ public interface GroupCacheLoadEvent extends LuckPermsEvent {
*
* @return the group
*/
- @NonNull @Param(0) Group getGroup();
+ @Param(0)
+ @NonNull Group getGroup();
/**
* Gets the data that was loaded
*
* @return the loaded data
*/
- @NonNull @Param(1) GroupData getLoadedData();
+ @Param(1)
+ @NonNull CachedDataManager getLoadedData();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupCreateEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupCreateEvent.java
index 11015d2f6..d70d3f679 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupCreateEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupCreateEvent.java
@@ -25,10 +25,10 @@
package me.lucko.luckperms.api.event.group;
-import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
import me.lucko.luckperms.api.event.cause.CreationCause;
+import me.lucko.luckperms.api.model.group.Group;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -42,13 +42,15 @@ public interface GroupCreateEvent extends LuckPermsEvent {
*
* @return the new group
*/
- @NonNull @Param(0) Group getGroup();
+ @Param(0)
+ @NonNull Group getGroup();
/**
* Gets the cause of the creation
*
* @return the cause of the creation
*/
- @NonNull @Param(1) CreationCause getCause();
+ @Param(1)
+ @NonNull CreationCause getCause();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupDataRecalculateEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupDataRecalculateEvent.java
index f402f2d72..c018b2b1c 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupDataRecalculateEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupDataRecalculateEvent.java
@@ -25,17 +25,15 @@
package me.lucko.luckperms.api.event.group;
-import me.lucko.luckperms.api.Group;
-import me.lucko.luckperms.api.caching.GroupData;
+import me.lucko.luckperms.api.cacheddata.CachedDataManager;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
+import me.lucko.luckperms.api.model.group.Group;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a groups cached data is refreshed
- *
- * @since 4.0
*/
public interface GroupDataRecalculateEvent extends LuckPermsEvent {
@@ -44,13 +42,15 @@ public interface GroupDataRecalculateEvent extends LuckPermsEvent {
*
* @return the group
*/
- @NonNull @Param(0) Group getGroup();
+ @Param(0)
+ @NonNull Group getGroup();
/**
* Gets the data that was recalculated
*
* @return the data
*/
- @NonNull @Param(1) GroupData getData();
+ @Param(1)
+ @NonNull CachedDataManager getData();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupDeleteEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupDeleteEvent.java
index 2f99dee79..047f8dad5 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupDeleteEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupDeleteEvent.java
@@ -25,10 +25,10 @@
package me.lucko.luckperms.api.event.group;
-import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
import me.lucko.luckperms.api.event.cause.DeletionCause;
+import me.lucko.luckperms.api.node.Node;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -44,20 +44,23 @@ public interface GroupDeleteEvent extends LuckPermsEvent {
*
* @return the name of the deleted group
*/
- @NonNull @Param(0) String getGroupName();
+ @Param(0)
+ @NonNull String getGroupName();
/**
* Gets an immutable copy of the groups existing data
*
* @return a copy of the groups existing data
*/
- @NonNull @Param(1) Set getExistingData();
+ @Param(1)
+ @NonNull Set getExistingData();
/**
* Gets the cause of the deletion
*
* @return the cause of the deletion
*/
- @NonNull @Param(2) DeletionCause getCause();
+ @Param(2)
+ @NonNull DeletionCause getCause();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupLoadEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupLoadEvent.java
index 5a70d9338..c5f661464 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupLoadEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupLoadEvent.java
@@ -25,9 +25,9 @@
package me.lucko.luckperms.api.event.group;
-import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
+import me.lucko.luckperms.api.model.group.Group;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -43,6 +43,7 @@ public interface GroupLoadEvent extends LuckPermsEvent {
*
* @return the group that was loaded
*/
- @NonNull @Param(0) Group getGroup();
+ @Param(0)
+ @NonNull Group getGroup();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/log/LogBroadcastEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/log/LogBroadcastEvent.java
index 10b1838af..25defa791 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/log/LogBroadcastEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/log/LogBroadcastEvent.java
@@ -25,7 +25,7 @@
package me.lucko.luckperms.api.event.log;
-import me.lucko.luckperms.api.LogEntry;
+import me.lucko.luckperms.api.actionlog.Action;
import me.lucko.luckperms.api.event.Cancellable;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
@@ -42,20 +42,19 @@ public interface LogBroadcastEvent extends LuckPermsEvent, Cancellable {
*
* @return the log entry to be broadcasted
*/
- @NonNull @Param(0) LogEntry getEntry();
+ @Param(0)
+ @NonNull Action getEntry();
/**
* Gets where the log entry originated from.
*
* @return the origin of the log
- * @since 3.3
*/
- @NonNull @Param(1) Origin getOrigin();
+ @Param(1)
+ @NonNull Origin getOrigin();
/**
* Represents where a log entry is from
- *
- * @since 3.3
*/
enum Origin {
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/log/LogNetworkPublishEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/log/LogNetworkPublishEvent.java
index 54beca9eb..fd54ca173 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/log/LogNetworkPublishEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/log/LogNetworkPublishEvent.java
@@ -25,7 +25,7 @@
package me.lucko.luckperms.api.event.log;
-import me.lucko.luckperms.api.LogEntry;
+import me.lucko.luckperms.api.actionlog.Action;
import me.lucko.luckperms.api.event.Cancellable;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
@@ -36,8 +36,6 @@ import java.util.UUID;
/**
* Called when a log is about to be published to the network via the MessagingService
- *
- * @since 3.3
*/
public interface LogNetworkPublishEvent extends LuckPermsEvent, Cancellable {
@@ -46,13 +44,15 @@ public interface LogNetworkPublishEvent extends LuckPermsEvent, Cancellable {
*
* @return the id of the log entry being published
*/
- @NonNull @Param(0) UUID getLogId();
+ @Param(0)
+ @NonNull UUID getLogId();
/**
* Gets the log entry to be published
*
* @return the log entry to be published
*/
- @NonNull @Param(1) LogEntry getEntry();
+ @Param(1)
+ @NonNull Action getEntry();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/log/LogNotifyEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/log/LogNotifyEvent.java
index 10ebcda08..cef8a538b 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/log/LogNotifyEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/log/LogNotifyEvent.java
@@ -25,11 +25,11 @@
package me.lucko.luckperms.api.event.log;
-import me.lucko.luckperms.api.Entity;
-import me.lucko.luckperms.api.LogEntry;
+import me.lucko.luckperms.api.actionlog.Action;
import me.lucko.luckperms.api.event.Cancellable;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
+import me.lucko.luckperms.api.platform.PlatformEntity;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -40,8 +40,6 @@ import org.checkerframework.checker.nullness.qual.NonNull;
* 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).
- *
- * @since 4.1
*/
public interface LogNotifyEvent extends LuckPermsEvent, Cancellable {
@@ -50,21 +48,24 @@ public interface LogNotifyEvent extends LuckPermsEvent, Cancellable {
*
* @return the log entry to be sent
*/
- @NonNull @Param(0) LogEntry getEntry();
+ @Param(0)
+ @NonNull Action getEntry();
/**
* Gets where the log entry originated from.
*
* @return the origin of the log
*/
- @NonNull @Param(1) Origin getOrigin();
+ @Param(1)
+ @NonNull Origin getOrigin();
/**
* Gets the object to be notified.
*
* @return the object to notify
*/
- @NonNull @Param(2) Entity getNotifiable();
+ @Param(2)
+ @NonNull PlatformEntity getNotifiable();
/**
* Represents where a log entry is from
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/log/LogPublishEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/log/LogPublishEvent.java
index dd777ca2a..f746b1738 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/log/LogPublishEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/log/LogPublishEvent.java
@@ -25,7 +25,7 @@
package me.lucko.luckperms.api.event.log;
-import me.lucko.luckperms.api.LogEntry;
+import me.lucko.luckperms.api.actionlog.Action;
import me.lucko.luckperms.api.event.Cancellable;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
@@ -42,6 +42,7 @@ public interface LogPublishEvent extends LuckPermsEvent, Cancellable {
*
* @return the log entry to be published
*/
- @NonNull @Param(0) LogEntry getEntry();
+ @Param(0)
+ @NonNull Action getEntry();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/log/LogReceiveEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/log/LogReceiveEvent.java
index a29bb9ac7..40eee6f27 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/log/LogReceiveEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/log/LogReceiveEvent.java
@@ -25,7 +25,7 @@
package me.lucko.luckperms.api.event.log;
-import me.lucko.luckperms.api.LogEntry;
+import me.lucko.luckperms.api.actionlog.Action;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
@@ -35,8 +35,6 @@ import java.util.UUID;
/**
* Called when a log entry is received via the MessagingService
- *
- * @since 3.3
*/
public interface LogReceiveEvent extends LuckPermsEvent {
@@ -45,13 +43,15 @@ public interface LogReceiveEvent extends LuckPermsEvent {
*
* @return the id of the log entry being received
*/
- @NonNull @Param(0) UUID getLogId();
+ @Param(0)
+ @NonNull UUID getLogId();
/**
* Gets the log entry being received
*
* @return the log entry being received
*/
- @NonNull @Param(1) LogEntry getEntry();
+ @Param(1)
+ @NonNull Action getEntry();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/node/NodeAddEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/node/NodeAddEvent.java
index 23f0df5ad..0ceba5248 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/node/NodeAddEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/node/NodeAddEvent.java
@@ -25,8 +25,8 @@
package me.lucko.luckperms.api.event.node;
-import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.event.Param;
+import me.lucko.luckperms.api.node.Node;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -40,6 +40,7 @@ public interface NodeAddEvent extends NodeMutateEvent {
*
* @return the node that was added
*/
- @NonNull @Param(3) Node getNode();
+ @Param(3)
+ @NonNull Node getNode();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/node/NodeMutateEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/node/NodeMutateEvent.java
index de4f49757..4ccb9da31 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/node/NodeMutateEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/node/NodeMutateEvent.java
@@ -25,12 +25,12 @@
package me.lucko.luckperms.api.event.node;
-import me.lucko.luckperms.api.Group;
-import me.lucko.luckperms.api.Node;
-import me.lucko.luckperms.api.PermissionHolder;
-import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
+import me.lucko.luckperms.api.model.PermissionHolder;
+import me.lucko.luckperms.api.model.group.Group;
+import me.lucko.luckperms.api.model.user.User;
+import me.lucko.luckperms.api.node.Node;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -46,24 +46,27 @@ public interface NodeMutateEvent extends LuckPermsEvent {
*
* @return the event target
*/
- @NonNull @Param(0) PermissionHolder getTarget();
+ @Param(0)
+ @NonNull PermissionHolder getTarget();
/**
* Gets an immutable copy of the holders data before the change
*
* @return the data before the change
*/
- @NonNull @Param(1) Set getDataBefore();
+ @Param(1)
+ @NonNull Set getDataBefore();
/**
* Gets an immutable copy of the holders data after the change
*
* @return the data after the change
*/
- @NonNull @Param(2) Set getDataAfter();
+ @Param(2)
+ @NonNull Set getDataAfter();
/**
- * Gets whether the target of this event is a {@link me.lucko.luckperms.api.User}
+ * Gets whether the target of this event is a {@link User}
*
* This is equivalent to checking if getTarget() instanceof User
*
@@ -74,7 +77,7 @@ public interface NodeMutateEvent extends LuckPermsEvent {
}
/**
- * Gets whether the target of this event is a {@link me.lucko.luckperms.api.Group}
+ * Gets whether the target of this event is a {@link Group}
*
* This is equivalent to checking if getTarget() instanceof Group
*
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/node/NodeRemoveEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/node/NodeRemoveEvent.java
index 62222e3c1..68b6777cc 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/node/NodeRemoveEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/node/NodeRemoveEvent.java
@@ -25,8 +25,8 @@
package me.lucko.luckperms.api.event.node;
-import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.event.Param;
+import me.lucko.luckperms.api.node.Node;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -40,6 +40,7 @@ public interface NodeRemoveEvent extends NodeMutateEvent {
*
* @return the node that was removed
*/
- @NonNull @Param(3) Node getNode();
+ @Param(3)
+ @NonNull Node getNode();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/player/PlayerDataSaveEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/player/PlayerDataSaveEvent.java
index af0a03238..8a7609f2d 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/player/PlayerDataSaveEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/player/PlayerDataSaveEvent.java
@@ -25,10 +25,10 @@
package me.lucko.luckperms.api.event.player;
-import me.lucko.luckperms.api.PlayerSaveResult;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
-import me.lucko.luckperms.api.manager.UserManager;
+import me.lucko.luckperms.api.model.PlayerSaveResult;
+import me.lucko.luckperms.api.model.user.UserManager;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -38,8 +38,6 @@ import java.util.UUID;
* Called when player data is saved to the storage.
*
* Data can be saved using {@link UserManager#savePlayerData(UUID, String)}.
- *
- * @since 4.3
*/
public interface PlayerDataSaveEvent extends LuckPermsEvent {
@@ -48,20 +46,23 @@ public interface PlayerDataSaveEvent extends LuckPermsEvent {
*
* @return the uuid
*/
- @NonNull @Param(0) UUID getUuid();
+ @Param(0)
+ @NonNull UUID getUniqueId();
/**
* Gets the username that was saved.
*
* @return the username
*/
- @NonNull @Param(1) String getUsername();
+ @Param(1)
+ @NonNull String getUsername();
/**
* Gets the result of the operation.
*
* @return the result
*/
- @NonNull @Param(2) PlayerSaveResult getResult();
+ @Param(2)
+ @NonNull PlayerSaveResult getResult();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/player/PlayerLoginProcessEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/player/PlayerLoginProcessEvent.java
index 9bc5c2d44..e6673df2e 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/player/PlayerLoginProcessEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/player/PlayerLoginProcessEvent.java
@@ -25,9 +25,10 @@
package me.lucko.luckperms.api.event.player;
-import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
+import me.lucko.luckperms.api.model.user.User;
+import me.lucko.luckperms.api.util.Result;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -49,30 +50,31 @@ import java.util.UUID;
* for all connections, even if the operation to load User data was not
* successful. Note that LuckPerms will usually cancel the platform connection
* event if data could not be loaded.
- *
- * @since 4.4
*/
-public interface PlayerLoginProcessEvent extends LuckPermsEvent {
+public interface PlayerLoginProcessEvent extends LuckPermsEvent, Result {
/**
* Gets the UUID of the connection which was processed
*
* @return the uuid of the connection which was processed
*/
- @NonNull @Param(0) UUID getUuid();
+ @Param(0)
+ @NonNull UUID getUniqueId();
/**
* Gets the username of the connection which was processed
*
* @return the username of the connection which was processed
*/
- @NonNull @Param(1) String getUsername();
+ @Param(1)
+ @NonNull String getUsername();
/**
* Gets if the login was processed successfully.
*
* @return true if the login was successful
*/
+ @Override
default boolean wasSuccessful() {
return getUser() != null;
}
@@ -85,6 +87,7 @@ public interface PlayerLoginProcessEvent extends LuckPermsEvent {
*
* @return the user instance
*/
- @Nullable @Param(2) User getUser();
+ @Param(2)
+ @Nullable User getUser();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/source/EntitySource.java b/api/src/main/java/me/lucko/luckperms/api/event/source/EntitySource.java
index d319a3ba0..2d1e7a136 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/source/EntitySource.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/source/EntitySource.java
@@ -25,14 +25,12 @@
package me.lucko.luckperms.api.event.source;
-import me.lucko.luckperms.api.Entity;
+import me.lucko.luckperms.api.platform.PlatformEntity;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
- * Represents an {@link Entity} which was the {@link Source} of something.
- *
- * @since 4.1
+ * Represents an {@link PlatformEntity} which was the {@link Source} of something.
*/
public interface EntitySource extends Source {
@@ -41,6 +39,6 @@ public interface EntitySource extends Source {
*
* @return the entity
*/
- @NonNull Entity getEntity();
+ @NonNull PlatformEntity getEntity();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/source/Source.java b/api/src/main/java/me/lucko/luckperms/api/event/source/Source.java
index 77456e10a..e49b58ef0 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/source/Source.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/source/Source.java
@@ -25,7 +25,7 @@
package me.lucko.luckperms.api.event.source;
-import me.lucko.luckperms.api.Entity;
+import me.lucko.luckperms.api.platform.PlatformEntity;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -33,8 +33,6 @@ import org.checkerframework.checker.nullness.qual.NonNull;
* Represents the source of an event.
*
* Could also be described as the "thing" that caused an event to occur.
- *
- * @since 4.1
*/
public interface Source {
@@ -51,7 +49,7 @@ public interface Source {
enum Type {
/**
- * Represents an {@link Entity} source
+ * Represents an {@link PlatformEntity} source
*
* @see EntitySource
*/
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/sync/PreNetworkSyncEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/sync/PreNetworkSyncEvent.java
index dab6487f0..6b596c52b 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/sync/PreNetworkSyncEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/sync/PreNetworkSyncEvent.java
@@ -43,6 +43,7 @@ public interface PreNetworkSyncEvent extends LuckPermsEvent, Cancellable {
*
* @return the id of the sync request
*/
- @NonNull @Param(0) UUID getSyncId();
+ @Param(0)
+ @NonNull UUID getSyncId();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/track/TrackCreateEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/track/TrackCreateEvent.java
index 77e7b5225..3c04da10c 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/track/TrackCreateEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/track/TrackCreateEvent.java
@@ -25,10 +25,10 @@
package me.lucko.luckperms.api.event.track;
-import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
import me.lucko.luckperms.api.event.cause.CreationCause;
+import me.lucko.luckperms.api.track.Track;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -42,13 +42,15 @@ public interface TrackCreateEvent extends LuckPermsEvent {
*
* @return the new track
*/
- @NonNull @Param(0) Track getTrack();
+ @Param(0)
+ @NonNull Track getTrack();
/**
* Gets the cause of the creation
*
* @return the cause of the creation
*/
- @NonNull @Param(1) CreationCause getCause();
+ @Param(1)
+ @NonNull CreationCause getCause();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/track/TrackDeleteEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/track/TrackDeleteEvent.java
index 10d7fb82e..493611599 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/track/TrackDeleteEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/track/TrackDeleteEvent.java
@@ -43,20 +43,23 @@ public interface TrackDeleteEvent extends LuckPermsEvent {
*
* @return the name of the deleted track
*/
- @NonNull @Param(0) String getTrackName();
+ @Param(0)
+ @NonNull String getTrackName();
/**
* Gets an immutable copy of the tracks existing data
*
* @return a copy of the tracks existing data
*/
- @NonNull @Param(1) List getExistingData();
+ @Param(1)
+ @NonNull List getExistingData();
/**
* Gets the cause of the deletion
*
* @return the cause of the deletion
*/
- @NonNull @Param(2) DeletionCause getCause();
+ @Param(2)
+ @NonNull DeletionCause getCause();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/track/TrackLoadEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/track/TrackLoadEvent.java
index 3b926f211..e0055b149 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/track/TrackLoadEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/track/TrackLoadEvent.java
@@ -25,9 +25,9 @@
package me.lucko.luckperms.api.event.track;
-import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
+import me.lucko.luckperms.api.track.Track;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -43,6 +43,7 @@ public interface TrackLoadEvent extends LuckPermsEvent {
*
* @return the track that was loaded
*/
- @NonNull @Param(0) Track getTrack();
+ @Param(0)
+ @NonNull Track getTrack();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackAddGroupEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackAddGroupEvent.java
index cbd54ca89..266198d51 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackAddGroupEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackAddGroupEvent.java
@@ -39,6 +39,7 @@ public interface TrackAddGroupEvent extends TrackMutateEvent {
*
* @return the group that was added
*/
- @NonNull @Param(3) String getGroup();
+ @Param(3)
+ @NonNull String getGroup();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackMutateEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackMutateEvent.java
index 9999bb801..91c77f6a5 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackMutateEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackMutateEvent.java
@@ -25,9 +25,9 @@
package me.lucko.luckperms.api.event.track.mutate;
-import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
+import me.lucko.luckperms.api.track.Track;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -43,20 +43,23 @@ public interface TrackMutateEvent extends LuckPermsEvent {
*
* @return the track that was mutated
*/
- @NonNull @Param(0) Track getTrack();
+ @Param(0)
+ @NonNull Track getTrack();
/**
* Gets an immutable copy of the tracks data before the change
*
* @return the data before the change
*/
- @NonNull @Param(1) List getDataBefore();
+ @Param(1)
+ @NonNull List getDataBefore();
/**
* Gets an immutable copy of the tracks data after the change
*
* @return the data after the change
*/
- @NonNull @Param(2) List getDataAfter();
+ @Param(2)
+ @NonNull List getDataAfter();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackRemoveGroupEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackRemoveGroupEvent.java
index 10d061aaa..77063e4bf 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackRemoveGroupEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackRemoveGroupEvent.java
@@ -39,6 +39,7 @@ public interface TrackRemoveGroupEvent extends TrackMutateEvent {
*
* @return the group that was removed
*/
- @NonNull @Param(3) String getGroup();
+ @Param(3)
+ @NonNull String getGroup();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/user/UserCacheLoadEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/user/UserCacheLoadEvent.java
index a2cf80926..9391c3529 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/user/UserCacheLoadEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/user/UserCacheLoadEvent.java
@@ -25,15 +25,15 @@
package me.lucko.luckperms.api.event.user;
-import me.lucko.luckperms.api.User;
-import me.lucko.luckperms.api.caching.UserData;
+import me.lucko.luckperms.api.cacheddata.CachedDataManager;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
+import me.lucko.luckperms.api.model.user.User;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
- * Called when a users {@link UserData} is loaded.
+ * Called when a users {@link CachedDataManager} is loaded.
*/
public interface UserCacheLoadEvent extends LuckPermsEvent {
@@ -42,13 +42,15 @@ public interface UserCacheLoadEvent extends LuckPermsEvent {
*
* @return the user
*/
- @NonNull @Param(0) User getUser();
+ @Param(0)
+ @NonNull User getUser();
/**
* Gets the data that was loaded
*
* @return the loaded data
*/
- @NonNull @Param(1) UserData getLoadedData();
+ @Param(1)
+ @NonNull CachedDataManager getLoadedData();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/user/UserDataRecalculateEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/user/UserDataRecalculateEvent.java
index 7067ae4b6..520ca568c 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/user/UserDataRecalculateEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/user/UserDataRecalculateEvent.java
@@ -25,10 +25,10 @@
package me.lucko.luckperms.api.event.user;
-import me.lucko.luckperms.api.User;
-import me.lucko.luckperms.api.caching.UserData;
+import me.lucko.luckperms.api.cacheddata.CachedDataManager;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
+import me.lucko.luckperms.api.model.user.User;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -42,13 +42,15 @@ public interface UserDataRecalculateEvent extends LuckPermsEvent {
*
* @return the user
*/
- @NonNull @Param(0) User getUser();
+ @Param(0)
+ @NonNull User getUser();
/**
* Gets the data that was recalculated
*
* @return the data
*/
- @NonNull @Param(1) UserData getData();
+ @Param(1)
+ @NonNull CachedDataManager getData();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/user/UserFirstLoginEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/user/UserFirstLoginEvent.java
index e7eae3b5b..a3a6fe602 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/user/UserFirstLoginEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/user/UserFirstLoginEvent.java
@@ -50,13 +50,15 @@ public interface UserFirstLoginEvent extends LuckPermsEvent {
*
* @return the uuid of the user
*/
- @NonNull @Param(0) UUID getUuid();
+ @Param(0)
+ @NonNull UUID getUniqueId();
/**
* Gets the username of the user
*
* @return the username of the user
*/
- @NonNull @Param(1) String getUsername();
+ @Param(1)
+ @NonNull String getUsername();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/user/UserLoadEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/user/UserLoadEvent.java
index 3a9d81e6c..e8233a0c8 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/user/UserLoadEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/user/UserLoadEvent.java
@@ -25,9 +25,9 @@
package me.lucko.luckperms.api.event.user;
-import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
+import me.lucko.luckperms.api.model.user.User;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -41,6 +41,7 @@ public interface UserLoadEvent extends LuckPermsEvent {
*
* @return the user that was loaded
*/
- @NonNull @Param(0) User getUser();
+ @Param(0)
+ @NonNull User getUser();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/user/track/UserTrackEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/user/track/UserTrackEvent.java
index b3013c331..19e974d9c 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/user/track/UserTrackEvent.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/user/track/UserTrackEvent.java
@@ -25,11 +25,11 @@
package me.lucko.luckperms.api.event.user.track;
-import me.lucko.luckperms.api.Track;
-import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
import me.lucko.luckperms.api.event.Sourced;
+import me.lucko.luckperms.api.model.user.User;
+import me.lucko.luckperms.api.track.Track;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -45,14 +45,16 @@ public interface UserTrackEvent extends LuckPermsEvent, Sourced {
*
* @return the track involved in the event
*/
- @NonNull @Param(0) Track getTrack();
+ @Param(0)
+ @NonNull Track getTrack();
/**
* Gets the user who was promoted or demoted
*
* @return the user involved in the event
*/
- @NonNull @Param(1) User getUser();
+ @Param(1)
+ @NonNull User getUser();
/**
* Gets the action performed
@@ -68,13 +70,15 @@ public interface UserTrackEvent extends LuckPermsEvent, Sourced {
*
* @return the group the user was promoted/demoted from
*/
- @NonNull @Param(2) Optional getGroupFrom();
+ @Param(2)
+ @NonNull Optional getGroupFrom();
/**
* Gets the group the user was promoted/demoted to
*
* @return the group the user was promoted/demoted to
*/
- @NonNull @Param(3) Optional getGroupTo();
+ @Param(3)
+ @NonNull Optional getGroupTo();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/MessagingService.java b/api/src/main/java/me/lucko/luckperms/api/messaging/MessagingService.java
similarity index 93%
rename from api/src/main/java/me/lucko/luckperms/api/MessagingService.java
rename to api/src/main/java/me/lucko/luckperms/api/messaging/MessagingService.java
index a35db6b3c..376499f22 100644
--- a/api/src/main/java/me/lucko/luckperms/api/MessagingService.java
+++ b/api/src/main/java/me/lucko/luckperms/api/messaging/MessagingService.java
@@ -23,14 +23,15 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api;
+package me.lucko.luckperms.api.messaging;
+
+import me.lucko.luckperms.api.LuckPerms;
+import me.lucko.luckperms.api.model.user.User;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* A means to push changes to other servers using the platforms networking
- *
- * @since 2.14
*/
public interface MessagingService {
@@ -38,7 +39,6 @@ public interface MessagingService {
* Gets the name of this messaging service
*
* @return the name of this messaging service
- * @since 4.1
*/
String getName();
@@ -48,7 +48,7 @@ public interface MessagingService {
*
* The standard response by other servers will be to execute a overall
* sync of all live data, equivalent to calling
- * {@link LuckPermsApi#runUpdateTask()}.
+ * {@link LuckPerms#runUpdateTask()}.
*
* This will push the update asynchronously, and this method will return
* immediately. Note that this method will not cause an update to be
@@ -69,7 +69,6 @@ public interface MessagingService {
* processed on the local server.
*
* @param user the user to push the update for
- * @since 4.1
*/
void pushUserUpdate(@NonNull User user);
diff --git a/api/src/main/java/me/lucko/luckperms/api/messenger/IncomingMessageConsumer.java b/api/src/main/java/me/lucko/luckperms/api/messenger/IncomingMessageConsumer.java
index 4da213d66..d6e83232d 100644
--- a/api/src/main/java/me/lucko/luckperms/api/messenger/IncomingMessageConsumer.java
+++ b/api/src/main/java/me/lucko/luckperms/api/messenger/IncomingMessageConsumer.java
@@ -33,8 +33,6 @@ import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Encapsulates the LuckPerms system which accepts incoming {@link Message}s
* from implementations of {@link Messenger}.
- *
- * @since 4.1
*/
public interface IncomingMessageConsumer {
diff --git a/api/src/main/java/me/lucko/luckperms/api/messenger/Messenger.java b/api/src/main/java/me/lucko/luckperms/api/messenger/Messenger.java
index a49285384..6245016c6 100644
--- a/api/src/main/java/me/lucko/luckperms/api/messenger/Messenger.java
+++ b/api/src/main/java/me/lucko/luckperms/api/messenger/Messenger.java
@@ -32,8 +32,6 @@ import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Represents an object which dispatches {@link OutgoingMessage}s.
- *
- * @since 4.1
*/
public interface Messenger extends AutoCloseable {
diff --git a/api/src/main/java/me/lucko/luckperms/api/messenger/MessengerProvider.java b/api/src/main/java/me/lucko/luckperms/api/messenger/MessengerProvider.java
index a912c9054..6222473a4 100644
--- a/api/src/main/java/me/lucko/luckperms/api/messenger/MessengerProvider.java
+++ b/api/src/main/java/me/lucko/luckperms/api/messenger/MessengerProvider.java
@@ -25,7 +25,7 @@
package me.lucko.luckperms.api.messenger;
-import me.lucko.luckperms.api.LuckPermsApi;
+import me.lucko.luckperms.api.LuckPerms;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -35,8 +35,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
* Users wishing to provide their own implementation for the plugins
* "Messaging Service" should implement and register this interface.
*
- * @see LuckPermsApi#registerMessengerProvider(MessengerProvider)
- * @since 4.1
+ * @see LuckPerms#registerMessengerProvider(MessengerProvider)
*/
public interface MessengerProvider {
diff --git a/api/src/main/java/me/lucko/luckperms/api/messenger/message/Message.java b/api/src/main/java/me/lucko/luckperms/api/messenger/message/Message.java
index 710844557..f1f68ba23 100644
--- a/api/src/main/java/me/lucko/luckperms/api/messenger/message/Message.java
+++ b/api/src/main/java/me/lucko/luckperms/api/messenger/message/Message.java
@@ -33,8 +33,6 @@ import java.util.UUID;
/**
* Represents a message sent received via a {@link Messenger}.
- *
- * @since 4.1
*/
public interface Message {
diff --git a/api/src/main/java/me/lucko/luckperms/api/messenger/message/OutgoingMessage.java b/api/src/main/java/me/lucko/luckperms/api/messenger/message/OutgoingMessage.java
index cdba6628b..0eabb3124 100644
--- a/api/src/main/java/me/lucko/luckperms/api/messenger/message/OutgoingMessage.java
+++ b/api/src/main/java/me/lucko/luckperms/api/messenger/message/OutgoingMessage.java
@@ -38,8 +38,6 @@ import org.checkerframework.checker.nullness.qual.NonNull;
* Note that all implementations of this interface are guaranteed to be an
* instance of one of the interfaces extending {@link Message} in the
* 'api.messenger.message.type' package.
- *
- * @since 4.1
*/
public interface OutgoingMessage extends Message {
diff --git a/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/LogMessage.java b/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/ActionLogMessage.java
similarity index 82%
rename from api/src/main/java/me/lucko/luckperms/api/messenger/message/type/LogMessage.java
rename to api/src/main/java/me/lucko/luckperms/api/messenger/message/type/ActionLogMessage.java
index 9f8448ed3..3e2286667 100644
--- a/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/LogMessage.java
+++ b/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/ActionLogMessage.java
@@ -25,25 +25,23 @@
package me.lucko.luckperms.api.messenger.message.type;
-import me.lucko.luckperms.api.LogEntry;
+import me.lucko.luckperms.api.actionlog.Action;
import me.lucko.luckperms.api.messenger.message.Message;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
- * Represents an "log" message.
+ * Represents an "action log" message.
*
- * Used to dispatch live log updates to other servers.
- *
- * @since 4.1
+ * Used to dispatch live action log updates to other servers.
*/
-public interface LogMessage extends Message {
+public interface ActionLogMessage extends Message {
/**
- * Gets the log entry being sent
+ * Gets the action being sent
*
- * @return the log entry
+ * @return the action
*/
- @NonNull LogEntry getLogEntry();
+ @NonNull Action getAction();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/UpdateMessage.java b/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/UpdateMessage.java
index e78ed5abf..cc83710b9 100644
--- a/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/UpdateMessage.java
+++ b/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/UpdateMessage.java
@@ -31,8 +31,6 @@ import me.lucko.luckperms.api.messenger.message.Message;
* Represents an "update" message.
*
* Used to notify other servers of general changes.
- *
- * @since 4.1
*/
public interface UpdateMessage extends Message {
diff --git a/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/UserUpdateMessage.java b/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/UserUpdateMessage.java
index 2cfe7cec1..3ca3a5d77 100644
--- a/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/UserUpdateMessage.java
+++ b/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/UserUpdateMessage.java
@@ -35,8 +35,6 @@ import java.util.UUID;
* Represents an "user update" message.
*
* Used to notify other servers of a change to a specific user.
- *
- * @since 4.1
*/
public interface UserUpdateMessage extends Message {
@@ -45,6 +43,6 @@ public interface UserUpdateMessage extends Message {
*
* @return the user
*/
- @NonNull UUID getUser();
+ @NonNull UUID getUserUniqueId();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/metastacking/DuplicateRemovalFunction.java b/api/src/main/java/me/lucko/luckperms/api/metastacking/DuplicateRemovalFunction.java
index d3fc5d1e6..b3895823c 100644
--- a/api/src/main/java/me/lucko/luckperms/api/metastacking/DuplicateRemovalFunction.java
+++ b/api/src/main/java/me/lucko/luckperms/api/metastacking/DuplicateRemovalFunction.java
@@ -36,8 +36,6 @@ import java.util.Set;
* Functional interface which removes duplicate entries from a list.
*
* Used by LuckPerms to remove duplicate entries from a MetaStack.
- *
- * @since 4.4
*/
public interface DuplicateRemovalFunction {
@@ -72,7 +70,7 @@ public interface DuplicateRemovalFunction {
@SuppressWarnings("Java8CollectionRemoveIf")
@Override
public void processDuplicates(@NonNull List list) {
- Set seen = new HashSet<>();
+ Set seen = new HashSet<>(list.size());
for (ListIterator it = list.listIterator(); it.hasNext(); ) {
T next = it.next();
if (!seen.add(next)) {
@@ -93,7 +91,7 @@ public interface DuplicateRemovalFunction {
DuplicateRemovalFunction LAST_ONLY = new DuplicateRemovalFunction() {
@Override
public void processDuplicates(@NonNull List list) {
- Set seen = new HashSet<>();
+ Set seen = new HashSet<>(list.size());
for (ListIterator it = list.listIterator(list.size()); it.hasPrevious(); ) {
T next = it.previous();
if (!seen.add(next)) {
diff --git a/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackDefinition.java b/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackDefinition.java
index 01c0b473f..5c2845603 100644
--- a/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackDefinition.java
+++ b/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackDefinition.java
@@ -25,6 +25,8 @@
package me.lucko.luckperms.api.metastacking;
+import me.lucko.luckperms.api.query.OptionKey;
+
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.List;
@@ -37,11 +39,19 @@ import java.util.List;
*
* Definitions can be passed to a users UserData instance using MetaContexts, and the result of this stack can be
* retrieved from the returned MetaData instance.
- *
- * @since 2.3
*/
public interface MetaStackDefinition {
+ /**
+ * The {@link OptionKey} for the prefix {@link MetaStackDefinition}.
+ */
+ OptionKey PREFIX_STACK_KEY = new OptionKey(){};
+
+ /**
+ * The {@link OptionKey} for the suffix {@link MetaStackDefinition}.
+ */
+ OptionKey SUFFIX_STACK_KEY = new OptionKey(){};
+
/**
* Gets an immutable list of the elements in this stack definition
*
@@ -54,7 +64,6 @@ public interface MetaStackDefinition {
* formatting takes place.
*
* @return the duplicate removal function
- * @since 4.4
*/
@NonNull DuplicateRemovalFunction getDuplicateRemovalFunction();
diff --git a/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackElement.java b/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackElement.java
index 1dc7c04b9..590b158fe 100644
--- a/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackElement.java
+++ b/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackElement.java
@@ -25,34 +25,27 @@
package me.lucko.luckperms.api.metastacking;
-import me.lucko.luckperms.api.ChatMetaType;
-import me.lucko.luckperms.api.LocalizedNode;
-import me.lucko.luckperms.api.Node;
+import me.lucko.luckperms.api.node.ChatMetaType;
+import me.lucko.luckperms.api.node.types.ChatMetaNode;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
-import java.util.Map;
-
/**
* Represents an element within a {@link MetaStackDefinition}.
*
* The element itself does not contain any mutable state.
- *
- * @since 3.2
*/
public interface MetaStackElement {
/**
* Returns if the given node should be accumulated onto the stack.
*
- * The element being considered can be retrieved using {@link ChatMetaType#getEntry(Node)}.
- *
- * @param node the node being considered
* @param type the type of entry being accumulated
+ * @param node the node being considered
* @param current the current value being used. If this returns true, the current value will be replaced by this entry
* @return true if the node should be accumulated into this element, replacing the current value
*/
- boolean shouldAccumulate(@NonNull LocalizedNode node, @NonNull ChatMetaType type, Map.@Nullable Entry current);
+ boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode, ?> node, @Nullable ChatMetaNode, ?> current);
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackFactory.java b/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackFactory.java
index 22d601e10..0b606ed81 100644
--- a/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackFactory.java
+++ b/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackFactory.java
@@ -32,8 +32,6 @@ import java.util.Optional;
/**
* Factory to create meta stack elements and definitions.
- *
- * @since 3.2
*/
public interface MetaStackFactory {
@@ -77,7 +75,6 @@ public interface MetaStackFactory {
* @param middleSpacer the spacer to be included between stack elements
* @param endSpacer the spacer to be included at the end of the stacks output
* @return the new stack definition instance
- * @since 4.4
*/
@NonNull MetaStackDefinition createDefinition(@NonNull List elements, @NonNull DuplicateRemovalFunction duplicateRemovalFunction, @NonNull String startSpacer, @NonNull String middleSpacer, @NonNull String endSpacer);
diff --git a/api/src/main/java/me/lucko/luckperms/api/DataMutateResult.java b/api/src/main/java/me/lucko/luckperms/api/model/DataMutateResult.java
similarity index 90%
rename from api/src/main/java/me/lucko/luckperms/api/DataMutateResult.java
rename to api/src/main/java/me/lucko/luckperms/api/model/DataMutateResult.java
index 8f738d722..48feb3ccf 100644
--- a/api/src/main/java/me/lucko/luckperms/api/DataMutateResult.java
+++ b/api/src/main/java/me/lucko/luckperms/api/model/DataMutateResult.java
@@ -23,14 +23,17 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api;
+package me.lucko.luckperms.api.model;
+
+import me.lucko.luckperms.api.track.Track;
+import me.lucko.luckperms.api.util.Result;
/**
* Represents the result of a data mutation call on a LuckPerms object.
*
* Usually as the result to a call on a {@link PermissionHolder} or {@link Track}.
*/
-public enum DataMutateResult implements MutateResult {
+public enum DataMutateResult implements Result {
/**
* Indicates the mutation was a success
@@ -59,7 +62,7 @@ public enum DataMutateResult implements MutateResult {
}
@Override
- public boolean wasSuccess() {
+ public boolean wasSuccessful() {
return this.success;
}
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/model/PermissionHolder.java b/api/src/main/java/me/lucko/luckperms/api/model/PermissionHolder.java
new file mode 100644
index 000000000..8669316ab
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/model/PermissionHolder.java
@@ -0,0 +1,468 @@
+/*
+ * This file is part of LuckPerms, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * 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.model;
+
+import me.lucko.luckperms.api.cacheddata.CachedDataManager;
+import me.lucko.luckperms.api.context.ContextSet;
+import me.lucko.luckperms.api.context.ImmutableContextSet;
+import me.lucko.luckperms.api.model.group.Group;
+import me.lucko.luckperms.api.model.group.GroupManager;
+import me.lucko.luckperms.api.model.user.User;
+import me.lucko.luckperms.api.model.user.UserManager;
+import me.lucko.luckperms.api.node.Node;
+import me.lucko.luckperms.api.node.NodeEqualityPredicate;
+import me.lucko.luckperms.api.node.Tristate;
+import me.lucko.luckperms.api.node.types.MetaNode;
+import me.lucko.luckperms.api.node.types.PrefixNode;
+import me.lucko.luckperms.api.node.types.SuffixNode;
+import me.lucko.luckperms.api.query.QueryOptions;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Predicate;
+
+/**
+ * Generic superinterface for an object which holds permissions.
+ */
+public interface PermissionHolder {
+
+ /**
+ * Gets the objects generic name.
+ *
+ * The result of this method is guaranteed to be a unique identifier for distinct instances
+ * of the same type of object.
+ *
+ * For {@link User}s, this method returns a {@link UUID#toString() string} representation of
+ * the users {@link User#getUniqueId() unique id}.
+ *
+ * For {@link Group}s, this method returns the {@link Group#getName() group name}.
+ *
+ * The {@link User#getUniqueId()}, {@link User#getUsername()} and {@link Group#getName()} methods
+ * define a "tighter" specification for obtaining object identifiers.
+ *
+ * @return the identifier for this object. Either a uuid string or name.
+ */
+ @NonNull String getObjectName();
+
+ /**
+ * Gets a friendly name for this holder, to be displayed in command output, etc.
+ *
+ * This will always return a value, eventually falling back to
+ * {@link #getObjectName()} if no other "friendlier" identifiers are present.
+ *
+ * For {@link User}s, this method will attempt to return the {@link User#getUsername() username},
+ * before falling back to {@link #getObjectName()}.
+ *
+ * For {@link Group}s, this method will attempt to return the groups display name, before
+ * falling back to {@link #getObjectName()}.
+ *
+ * @return a friendly identifier for this holder
+ */
+ @NonNull String getFriendlyName();
+
+ /**
+ * Gets the holders {@link CachedDataManager} cache.
+ *
+ * @return the holders cached data.
+ */
+ @NonNull CachedDataManager getCachedData();
+
+ /**
+ * Refreshes and applies any changes to the cached holder data.
+ *
+ * Calling this method is unnecessary in most cases. Cache updates are handled
+ * behind the scenes by the implementation.
+ *
+ * @return the task future
+ */
+ @NonNull CompletableFuture refreshCachedData();
+
+ /**
+ * Gets the {@link Data} of a particular type.
+ *
+ * @param dataType the data type
+ * @return the data
+ */
+ Data getData(@NonNull DataType dataType);
+
+ /**
+ * Gets the holders {@link DataType#NORMAL} data.
+ *
+ * @return the normal data
+ */
+ @NonNull Data data();
+
+ /**
+ * Gets the holders {@link DataType#TRANSIENT} data.
+ *
+ * Transient permissions only exist for the duration of the session.
+ *
+ * A transient node is a permission that does not persist.
+ * Whenever a user logs out of the server, or the server restarts, this permission will
+ * disappear. It is never saved to the datastore, and therefore will not apply on other
+ * servers.
+ *
+ * This is useful if you want to temporarily set a permission for a user while they're
+ * online, but don't want it to persist, and have to worry about removing it when they log
+ * out.
+ *
+ * @return the transient data
+ */
+ @NonNull Data transientData();
+
+ /**
+ * Represents a type of data.
+ */
+ enum DataType {
+
+ /**
+ * Normal data.
+ */
+ NORMAL,
+
+ /**
+ * Data which expires automatically at the end of a session.
+ * (when a user logs off)
+ *
+ * This data is never saved to the backend storage provider.
+ */
+ TRANSIENT
+ }
+
+ interface Data {
+
+ /**
+ * Gets the backing map containing every permission this holder has.
+ *
+ * This method does not resolve inheritance rules, and returns a
+ * view of what's 'in the file'.
+ *
+ * @return the holders own nodes
+ */
+ @NonNull Map> getNodes();
+
+ /**
+ * Gets a flattened set of {@link Node}s the holder has.
+ *
+ * Effectively combines the value collections of the map returned by
+ * {@link #getNodes()}.
+ *
+ * @return a flattened set of the holders own nodes
+ */
+ @NonNull Set getFlattenedNodes();
+
+ /**
+ * Checks to see if the object has a certain permission.
+ *
+ * @param node the node to check for
+ * @param equalityPredicate how to determine if a node matches
+ * @return a Tristate for the holders permission status for the node
+ * @throws NullPointerException if the node is null
+ */
+ @NonNull Tristate hasNode(@NonNull Node node, @NonNull NodeEqualityPredicate equalityPredicate);
+
+ /**
+ * Sets a permission node for the permission holder.
+ *
+ * Although this method is named setPermission, it can be used for all node types.
+ *
+ * The effect of this mutate operation will not persist in storage unless changes are
+ * explicitly saved. If changes are not saved, the effect will only be observed until the next
+ * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
+ * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
+ * using {@link GroupManager#saveGroup(Group)}.
+ *
+ * Before making changes to a user or group, it may be a good idea to load a fresh copy of
+ * the backing data from the storage if you haven't done so already, to avoid overwriting changes
+ * made already. This can be done via {@link UserManager#loadUser(UUID)} or
+ * {@link GroupManager#loadGroup(String)} respectively.
+ *
+ * @param node The node to be set
+ * @return the result of the operation
+ * @throws NullPointerException if the node is null
+ */
+ @NonNull DataMutateResult addNode(@NonNull Node node);
+
+ /**
+ * Sets a permission node for the permission holder.
+ *
+ * Although this method is named setPermission, it can be used for all node types.
+ *
+ * The effect of this mutate operation will not persist in storage unless changes are
+ * explicitly saved. If changes are not saved, the effect will only be observed until the next
+ * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
+ * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
+ * using {@link GroupManager#saveGroup(Group)}.
+ *
+ * Before making changes to a user or group, it may be a good idea to load a fresh copy of
+ * the backing data from the storage if you haven't done so already, to avoid overwriting changes
+ * made already. This can be done via {@link UserManager#loadUser(UUID)} or
+ * {@link GroupManager#loadGroup(String)} respectively.
+ *
+ * @param node The node to be set
+ * @param temporaryMergeBehaviour The behaviour used to merge temporary permission entries
+ * @return the result of the operation
+ * @throws NullPointerException if the node is null
+ */
+ @NonNull TemporaryDataMutateResult addNode(@NonNull Node node, @NonNull TemporaryMergeBehaviour temporaryMergeBehaviour);
+
+ /**
+ * Unsets a permission for the permission holder.
+ *
+ * Although this method is named unsetPermission, it can be used for all node types.
+ *
+ * The effect of this mutate operation will not persist in storage unless changes are
+ * explicitly saved. If changes are not saved, the effect will only be observed until the next
+ * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
+ * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
+ * using {@link GroupManager#saveGroup(Group)}.
+ *
+ * Before making changes to a user or group, it may be a good idea to load a fresh copy of
+ * the backing data from the storage if you haven't done so already, to avoid overwriting changes
+ * made already. This can be done via {@link UserManager#loadUser(UUID)} or
+ * {@link GroupManager#loadGroup(String)} respectively.
+ *
+ * @param node The node to be unset
+ * @return the result of the operation
+ * @throws NullPointerException if the node is null
+ */
+ @NonNull DataMutateResult removeNode(@NonNull Node node);
+
+ /**
+ * Clears any nodes from the holder which pass the predicate.
+ *
+ * This method only targets enduring data.
+ *
+ * The effect of this mutate operation will not persist in storage unless changes are
+ * explicitly saved. If changes are not saved, the effect will only be observed until the next
+ * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
+ * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
+ * using {@link GroupManager#saveGroup(Group)}.
+ *
+ * Before making changes to a user or group, it may be a good idea to load a fresh copy of
+ * the backing data from the storage if you haven't done so already, to avoid overwriting changes
+ * made already. This can be done via {@link UserManager#loadUser(UUID)} or
+ * {@link GroupManager#loadGroup(String)} respectively.
+ *
+ * @param test the predicate to test for nodes which should be removed
+ */
+ void clearMatching(@NonNull Predicate super Node> test);
+
+ /**
+ * Clears all nodes held by the permission holder.
+ *
+ * The effect of this mutate operation will not persist in storage unless changes are
+ * explicitly saved. If changes are not saved, the effect will only be observed until the next
+ * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
+ * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
+ * using {@link GroupManager#saveGroup(Group)}.
+ *
+ * Before making changes to a user or group, it may be a good idea to load a fresh copy of
+ * the backing data from the storage if you haven't done so already, to avoid overwriting changes
+ * made already. This can be done via {@link UserManager#loadUser(UUID)} or
+ * {@link GroupManager#loadGroup(String)} respectively.
+ */
+ void clearNodes();
+
+ /**
+ * Clears all nodes held by the permission holder in a specific context.
+ *
+ * The effect of this mutate operation will not persist in storage unless changes are
+ * explicitly saved. If changes are not saved, the effect will only be observed until the next
+ * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
+ * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
+ * using {@link GroupManager#saveGroup(Group)}.
+ *
+ * Before making changes to a user or group, it may be a good idea to load a fresh copy of
+ * the backing data from the storage if you haven't done so already, to avoid overwriting changes
+ * made already. This can be done via {@link UserManager#loadUser(UUID)} or
+ * {@link GroupManager#loadGroup(String)} respectively.
+ *
+ * @param contextSet the contexts to filter by
+ */
+ void clearNodes(@NonNull ContextSet contextSet);
+
+ /**
+ * Clears all parent groups.
+ *
+ * The effect of this mutate operation will not persist in storage unless changes are
+ * explicitly saved. If changes are not saved, the effect will only be observed until the next
+ * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
+ * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
+ * using {@link GroupManager#saveGroup(Group)}.
+ *
+ * Before making changes to a user or group, it may be a good idea to load a fresh copy of
+ * the backing data from the storage if you haven't done so already, to avoid overwriting changes
+ * made already. This can be done via {@link UserManager#loadUser(UUID)} or
+ * {@link GroupManager#loadGroup(String)} respectively.
+ */
+ void clearParents();
+
+ /**
+ * Clears all parent groups in a specific context.
+ *
+ * The effect of this mutate operation will not persist in storage unless changes are
+ * explicitly saved. If changes are not saved, the effect will only be observed until the next
+ * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
+ * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
+ * using {@link GroupManager#saveGroup(Group)}.
+ *
+ * Before making changes to a user or group, it may be a good idea to load a fresh copy of
+ * the backing data from the storage if you haven't done so already, to avoid overwriting changes
+ * made already. This can be done via {@link UserManager#loadUser(UUID)} or
+ * {@link GroupManager#loadGroup(String)} respectively.
+ *
+ * @param contextSet the contexts to filter by
+ */
+ void clearParents(@NonNull ContextSet contextSet);
+
+ /**
+ * Clears all meta held by the permission holder.
+ *
+ * Meta nodes in this case, are any nodes which have a {@link MetaNode}, {@link PrefixNode}
+ * or {@link SuffixNode} type.
+ *
+ * The effect of this mutate operation will not persist in storage unless changes are
+ * explicitly saved. If changes are not saved, the effect will only be observed until the next
+ * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
+ * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
+ * using {@link GroupManager#saveGroup(Group)}.
+ *
+ * Before making changes to a user or group, it may be a good idea to load a fresh copy of
+ * the backing data from the storage if you haven't done so already, to avoid overwriting changes
+ * made already. This can be done via {@link UserManager#loadUser(UUID)} or
+ * {@link GroupManager#loadGroup(String)} respectively.
+ */
+ void clearMeta();
+
+ /**
+ * Clears all meta held by the permission holder in a specific context.
+ *
+ * Meta nodes in this case, are any nodes which have a {@link MetaNode}, {@link PrefixNode}
+ * or {@link SuffixNode} type.
+ *
+ * The effect of this mutate operation will not persist in storage unless changes are
+ * explicitly saved. If changes are not saved, the effect will only be observed until the next
+ * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved
+ * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved
+ * using {@link GroupManager#saveGroup(Group)}.
+ *
+ * Before making changes to a user or group, it may be a good idea to load a fresh copy of
+ * the backing data from the storage if you haven't done so already, to avoid overwriting changes
+ * made already. This can be done via {@link UserManager#loadUser(UUID)} or
+ * {@link GroupManager#loadGroup(String)} respectively.
+ *
+ * @param contextSet the contexts to filter by
+ */
+ void clearMeta(@NonNull ContextSet contextSet);
+
+ }
+
+ /**
+ * Gets a flattened/squashed view of the holders permissions.
+ *
+ * This list is constructed using the values
+ * of both the transient and enduring backing multimaps.
+ *
+ * This means that it may contain duplicate entries.
+ *
+ * Use {@link #getDistinctNodes()} for a view without duplicates.
+ *
+ * This method does not resolve inheritance rules.
+ *
+ * @return a list of the holders own nodes.
+ */
+ @NonNull List getNodes();
+
+ /**
+ * Gets a sorted set of all held nodes.
+ *
+ * Effectively a sorted version of {@link #getNodes()}, without duplicates. Use the
+ * aforementioned method if you don't require either of these attributes.
+ *
+ * This method does not resolve inheritance rules.
+ *
+ * @return an immutable set of permissions in priority order
+ */
+ @NonNull SortedSet getDistinctNodes();
+
+ /**
+ * Recursively resolves this holders permissions.
+ *
+ * The returned list will contain every inherited
+ * node the holder has, in the order that they were inherited in.
+ *
+ * This means the list will contain duplicates.
+ *
+ * Inheritance is performed according to the platforms rules, and the order will vary
+ * depending on the accumulation order. By default, the holders own nodes are first in the list,
+ * with the entries from the end of the inheritance tree appearing last.
+ *
+ * @param queryOptions the query options
+ * @return a list of nodes
+ */
+ @NonNull List resolveInheritedNodes(@NonNull QueryOptions queryOptions);
+
+ /**
+ * Gets a mutable sorted set of the nodes that this object has and inherits, filtered by context
+ *
+ * Nodes are sorted into priority order. The order of inheritance is only important during
+ * the process of flattening inherited entries.
+ *
+ * @param queryOptions the query options
+ * @return an immutable sorted set of permissions
+ * @throws NullPointerException if the context is null
+ */
+ @NonNull SortedSet resolveDistinctInheritedNodes(@NonNull QueryOptions queryOptions);
+
+ /**
+ * Removes any temporary permissions that have expired.
+ *
+ * This method is called periodically by the platform, so it is only necessary to run
+ * if you want to guarantee that the current data is totally up-to-date.
+ */
+ void auditTemporaryPermissions();
+
+ /**
+ * Checks to see if the object inherits a certain permission.
+ *
+ * Although this method is named inheritsPermission, it can be used for all node types.
+ *
+ * @param node the node to check for
+ * @param equalityPredicate how to determine if a node matches
+ * @return a Tristate for the holders inheritance status for the node
+ * @throws NullPointerException if the node is null
+ */
+ @NonNull Tristate inheritsNode(@NonNull Node node, @NonNull NodeEqualityPredicate equalityPredicate);
+
+}
diff --git a/api/src/main/java/me/lucko/luckperms/api/PlayerSaveResult.java b/api/src/main/java/me/lucko/luckperms/api/model/PlayerSaveResult.java
similarity index 81%
rename from api/src/main/java/me/lucko/luckperms/api/PlayerSaveResult.java
rename to api/src/main/java/me/lucko/luckperms/api/model/PlayerSaveResult.java
index cb63dab21..eca839e59 100644
--- a/api/src/main/java/me/lucko/luckperms/api/PlayerSaveResult.java
+++ b/api/src/main/java/me/lucko/luckperms/api/model/PlayerSaveResult.java
@@ -23,9 +23,9 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api;
+package me.lucko.luckperms.api.model;
-import me.lucko.luckperms.api.manager.UserManager;
+import me.lucko.luckperms.api.model.user.UserManager;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -39,8 +39,6 @@ import java.util.UUID;
*
* The corresponding method can be found at
* {@link UserManager#savePlayerData(UUID, String)}.
- *
- * @since 4.2
*/
public interface PlayerSaveResult {
@@ -49,45 +47,45 @@ public interface PlayerSaveResult {
*
* @return the status
*/
- @NonNull Set getStatus();
+ @NonNull Set getOutcomes();
/**
- * Gets if the result includes a certain status code.
+ * Gets if the result includes a certain outcome.
*
- * @param status the status to check for
- * @return if the result includes the status
+ * @param outcome the outcome to check for
+ * @return if the result includes the outcome
*/
- default boolean includes(@NonNull Status status) {
- Objects.requireNonNull(status, "status");
- return getStatus().contains(status);
+ default boolean includes(@NonNull Outcome outcome) {
+ Objects.requireNonNull(outcome, "outcome");
+ return getOutcomes().contains(outcome);
}
/**
* Gets the old username involved in the result.
*
- * Returns null when the result doesn't {@link #includes(Status) include} the
- * {@link Status#USERNAME_UPDATED} status.
+ * Returns null when the result doesn't {@link #includes(Outcome) include} the
+ * {@link Outcome#USERNAME_UPDATED} status.
*
* @return the old username
- * @see Status#USERNAME_UPDATED
+ * @see Outcome#USERNAME_UPDATED
*/
@Nullable String getOldUsername();
/**
* Gets the other uuids involved in the result.
*
- * Returns null when the result doesn't {@link #includes(Status) include} the
- * {@link Status#OTHER_UUIDS_PRESENT_FOR_USERNAME} status.
+ * Returns null when the result doesn't {@link #includes(Outcome) include} the
+ * {@link Outcome#OTHER_UNIQUE_IDS_PRESENT_FOR_USERNAME} status.
*
* @return the other uuids
- * @see Status#OTHER_UUIDS_PRESENT_FOR_USERNAME
+ * @see Outcome#OTHER_UNIQUE_IDS_PRESENT_FOR_USERNAME
*/
- @Nullable Set getOtherUuids();
+ @Nullable Set getOtherUniqueIds();
/**
* The various states the result can take
*/
- enum Status {
+ enum Outcome {
/**
* There was no existing data saved for either the uuid or username
@@ -119,6 +117,6 @@ public interface PlayerSaveResult {
* that the user of the plugin is running a network off a shared database with one
* server in online mode and another in offline mode.
*/
- OTHER_UUIDS_PRESENT_FOR_USERNAME,
+ OTHER_UNIQUE_IDS_PRESENT_FOR_USERNAME,
}
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/TemporaryDataMutateResult.java b/api/src/main/java/me/lucko/luckperms/api/model/TemporaryDataMutateResult.java
similarity index 86%
rename from api/src/main/java/me/lucko/luckperms/api/TemporaryDataMutateResult.java
rename to api/src/main/java/me/lucko/luckperms/api/model/TemporaryDataMutateResult.java
index fa9938302..d16e7c7fc 100644
--- a/api/src/main/java/me/lucko/luckperms/api/TemporaryDataMutateResult.java
+++ b/api/src/main/java/me/lucko/luckperms/api/model/TemporaryDataMutateResult.java
@@ -23,16 +23,17 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api;
+package me.lucko.luckperms.api.model;
+
+import me.lucko.luckperms.api.node.Node;
+import me.lucko.luckperms.api.util.Result;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Extension of {@link DataMutateResult} for temporary set operations.
- *
- * @since 4.3
*/
-public interface TemporaryDataMutateResult {
+public interface TemporaryDataMutateResult extends Result {
/**
* Gets the underlying result.
@@ -52,4 +53,9 @@ public interface TemporaryDataMutateResult {
*/
@NonNull Node getMergedNode();
+ @Override
+ default boolean wasSuccessful() {
+ return getResult().wasSuccessful();
+ }
+
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/TemporaryMergeBehaviour.java b/api/src/main/java/me/lucko/luckperms/api/model/TemporaryMergeBehaviour.java
similarity index 89%
rename from api/src/main/java/me/lucko/luckperms/api/TemporaryMergeBehaviour.java
rename to api/src/main/java/me/lucko/luckperms/api/model/TemporaryMergeBehaviour.java
index 5d6b1a8d7..ca7402ae4 100644
--- a/api/src/main/java/me/lucko/luckperms/api/TemporaryMergeBehaviour.java
+++ b/api/src/main/java/me/lucko/luckperms/api/model/TemporaryMergeBehaviour.java
@@ -23,20 +23,20 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api;
+package me.lucko.luckperms.api.model;
+
+import me.lucko.luckperms.api.node.Node;
/**
* Controls how the implementation should behave when new temporary nodes are set
* that would otherwise conflict with existing entries.
*
- * The default behaviour of {@link PermissionHolder#setPermission(Node)} is
+ *
The default behaviour of {@link PermissionHolder.Data#addNode(Node)} is
* to return a result of {@link DataMutateResult#ALREADY_HAS} when an equivalent
* node is found. This can be replicated using {@link #FAIL_WITH_ALREADY_HAS}.
*
- * However, the {@link PermissionHolder#setPermission(Node, TemporaryMergeBehaviour)}
+ *
However, the {@link PermissionHolder.Data#addNode(Node, TemporaryMergeBehaviour)}
* method allows this behaviour to be customized for temporary permissions.
- *
- * @since 4.3
*/
public enum TemporaryMergeBehaviour {
diff --git a/api/src/main/java/me/lucko/luckperms/api/Group.java b/api/src/main/java/me/lucko/luckperms/api/model/group/Group.java
similarity index 89%
rename from api/src/main/java/me/lucko/luckperms/api/Group.java
rename to api/src/main/java/me/lucko/luckperms/api/model/group/Group.java
index b9167c29c..43f9a2fb3 100644
--- a/api/src/main/java/me/lucko/luckperms/api/Group.java
+++ b/api/src/main/java/me/lucko/luckperms/api/model/group/Group.java
@@ -23,10 +23,10 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api;
+package me.lucko.luckperms.api.model.group;
-import me.lucko.luckperms.api.caching.GroupData;
import me.lucko.luckperms.api.context.ContextSet;
+import me.lucko.luckperms.api.model.PermissionHolder;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -54,7 +54,6 @@ public interface Group extends PermissionHolder {
* {@link #getName() actual name}.
*
* @return the display name
- * @since 4.3
*/
@Nullable String getDisplayName();
@@ -66,7 +65,6 @@ public interface Group extends PermissionHolder {
*
* @param contextSet the contexts to lookup in
* @return the display name
- * @since 4.3
*/
@Nullable String getDisplayName(@NonNull ContextSet contextSet);
@@ -74,17 +72,7 @@ public interface Group extends PermissionHolder {
* Gets the weight of this group, if present.
*
* @return the group weight
- * @since 2.17
*/
@NonNull OptionalInt getWeight();
- /**
- * Gets the groups's {@link GroupData} cache.
- *
- * @return the groups cached data.
- * @since 4.0
- */
- @Override
- @NonNull GroupData getCachedData();
-
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/manager/GroupManager.java b/api/src/main/java/me/lucko/luckperms/api/model/group/GroupManager.java
similarity index 67%
rename from api/src/main/java/me/lucko/luckperms/api/manager/GroupManager.java
rename to api/src/main/java/me/lucko/luckperms/api/model/group/GroupManager.java
index b6557114b..5211c185f 100644
--- a/api/src/main/java/me/lucko/luckperms/api/manager/GroupManager.java
+++ b/api/src/main/java/me/lucko/luckperms/api/model/group/GroupManager.java
@@ -23,11 +23,9 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api.manager;
+package me.lucko.luckperms.api.model.group;
-import me.lucko.luckperms.api.Group;
-import me.lucko.luckperms.api.HeldPermission;
-import me.lucko.luckperms.api.Storage;
+import me.lucko.luckperms.api.node.HeldNode;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -51,8 +49,6 @@ import java.util.function.Consumer;
* not be called on the main server thread. If you need to use
* the result of these operations on the main server thread, register a
* callback using {@link CompletableFuture#thenAcceptAsync(Consumer, Executor)}.
- *
- * @since 4.0
*/
public interface GroupManager {
@@ -62,17 +58,9 @@ public interface GroupManager {
*
* If a group by the same name already exists, it will be loaded.
*
- * This method is effectively the same as
- * {@link Storage#createAndLoadGroup(String)}, however, the Future returns
- * the resultant group instance instead of a boolean flag.
- *
- * Unlike the method in {@link Storage}, when a group cannot be loaded,
- * the future will be {@link CompletableFuture completed exceptionally}.
- *
* @param name the name of the group
* @return the resultant group
* @throws NullPointerException if the name is null
- * @since 4.1
*/
@NonNull CompletableFuture createAndLoadGroup(@NonNull String name);
@@ -82,17 +70,9 @@ public interface GroupManager {
* Returns an {@link Optional#empty() empty optional} if the group does
* not exist.
*
- * This method is effectively the same as
- * {@link Storage#loadGroup(String)}, however, the Future returns
- * the resultant group instance instead of a boolean flag.
- *
- * Unlike the method in {@link Storage}, when a group cannot be loaded,
- * the future will be {@link CompletableFuture completed exceptionally}.
- *
* @param name the name of the group
* @return the resultant group
* @throws NullPointerException if the name is null
- * @since 4.1
*/
@NonNull CompletableFuture> loadGroup(@NonNull String name);
@@ -101,48 +81,27 @@ public interface GroupManager {
*
* You should call this after you make any changes to a group.
*
- * This method is effectively the same as {@link Storage#saveGroup(Group)},
- * however, the Future returns void instead of a boolean flag.
- *
- * Unlike the method in {@link Storage}, when a group cannot be saved,
- * the future will be {@link CompletableFuture completed exceptionally}.
- *
* @param group the group to save
* @return a future to encapsulate the operation.
* @throws NullPointerException if group is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
- * @since 4.1
*/
@NonNull CompletableFuture saveGroup(@NonNull Group group);
/**
* Permanently deletes a group from the plugin's storage provider.
*
- * This method is effectively the same as {@link Storage#deleteGroup(Group)},
- * however, the Future returns void instead of a boolean flag.
- *
- * Unlike the method in {@link Storage}, when a group cannot be deleted,
- * the future will be {@link CompletableFuture completed exceptionally}.
- *
* @param group the group to delete
* @return a future to encapsulate the operation.
* @throws NullPointerException if group is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
- * @since 4.1
*/
@NonNull CompletableFuture deleteGroup(@NonNull Group group);
/**
* Loads all groups into memory.
*
- * This method is effectively the same as {@link Storage#loadAllTracks()},
- * however, the Future returns void instead of a boolean flag.
- *
- * Unlike the method in {@link Storage}, when a group cannot be loaded,
- * the future will be {@link CompletableFuture completed exceptionally}.
- *
* @return a future to encapsulate the operation.
- * @since 4.1
*/
@NonNull CompletableFuture loadAllGroups();
@@ -152,9 +111,8 @@ public interface GroupManager {
* @param permission the permission to search for
* @return a list of held permissions, or null if the operation failed
* @throws NullPointerException if the permission is null
- * @since 4.2
*/
- @NonNull CompletableFuture>> getWithPermission(@NonNull String permission);
+ @NonNull CompletableFuture>> getWithPermission(@NonNull String permission);
/**
* Gets a loaded group.
@@ -165,19 +123,6 @@ public interface GroupManager {
*/
@Nullable Group getGroup(@NonNull String name);
- /**
- * Gets a loaded group.
- *
- * This method does not return null, unlike {@link #getGroup}
- *
- * @param name the name of the group to get
- * @return an optional {@link Group} object
- * @throws NullPointerException if the name is null
- */
- default @NonNull Optional getGroupOpt(@NonNull String name) {
- return Optional.ofNullable(getGroup(name));
- }
-
/**
* Gets a set of all loaded groups.
*
diff --git a/api/src/main/java/me/lucko/luckperms/api/User.java b/api/src/main/java/me/lucko/luckperms/api/model/user/User.java
similarity index 74%
rename from api/src/main/java/me/lucko/luckperms/api/User.java
rename to api/src/main/java/me/lucko/luckperms/api/model/user/User.java
index 147e160e1..8c0be318d 100644
--- a/api/src/main/java/me/lucko/luckperms/api/User.java
+++ b/api/src/main/java/me/lucko/luckperms/api/model/user/User.java
@@ -23,9 +23,10 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api;
+package me.lucko.luckperms.api.model.user;
-import me.lucko.luckperms.api.caching.UserData;
+import me.lucko.luckperms.api.model.DataMutateResult;
+import me.lucko.luckperms.api.model.PermissionHolder;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -42,7 +43,7 @@ public interface User extends PermissionHolder {
*
* @return the users Mojang assigned unique id
*/
- @NonNull UUID getUuid();
+ @NonNull UUID getUniqueId();
/**
* Gets the users username
@@ -51,7 +52,7 @@ public interface User extends PermissionHolder {
*
* @return the users username
*/
- @Nullable String getName();
+ @Nullable String getUsername();
/**
* Gets the users current primary group.
@@ -77,32 +78,4 @@ public interface User extends PermissionHolder {
*/
@NonNull DataMutateResult setPrimaryGroup(@NonNull String group);
- /**
- * Gets the user's {@link UserData} cache.
- *
- * @return the users cached data.
- * @since 3.2
- */
- @Override
- @NonNull UserData getCachedData();
-
- /**
- * Refresh and re-assign the users permissions.
- *
- * @deprecated Calling this method is no longer necessary. Permissions data is now refreshed on
- * demand, as changes are made. Consider use of {@link #refreshCachedData()}
- * instead. This method is now implemented as a no-op.
- */
- @Deprecated
- void refreshPermissions();
-
- /**
- * Pre-calculates some values in the user's data cache.
- *
- * @since 2.17
- * @deprecated Use of this method is no longer necessary. It is implemented as a no-op.
- */
- @Deprecated
- void setupDataCache();
-
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/manager/UserManager.java b/api/src/main/java/me/lucko/luckperms/api/model/user/UserManager.java
similarity index 74%
rename from api/src/main/java/me/lucko/luckperms/api/manager/UserManager.java
rename to api/src/main/java/me/lucko/luckperms/api/model/user/UserManager.java
index 2413fc036..e207719ea 100644
--- a/api/src/main/java/me/lucko/luckperms/api/manager/UserManager.java
+++ b/api/src/main/java/me/lucko/luckperms/api/model/user/UserManager.java
@@ -23,18 +23,15 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api.manager;
+package me.lucko.luckperms.api.model.user;
-import me.lucko.luckperms.api.HeldPermission;
-import me.lucko.luckperms.api.PlayerSaveResult;
-import me.lucko.luckperms.api.Storage;
-import me.lucko.luckperms.api.User;
+import me.lucko.luckperms.api.model.PlayerSaveResult;
+import me.lucko.luckperms.api.node.HeldNode;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.List;
-import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@@ -56,43 +53,25 @@ import java.util.function.Consumer;
* not be called on the main server thread. If you need to use
* the result of these operations on the main server thread, register a
* callback using {@link CompletableFuture#thenAcceptAsync(Consumer, Executor)}.
- *
- * @since 4.0
*/
public interface UserManager {
/**
* Loads a user from the plugin's storage provider into memory.
*
- * This method is effectively the same as
- * {@link Storage#loadUser(UUID, String)}, however, the Future returns the
- * resultant user instance instead of a boolean flag.
- *
- * Unlike the method in {@link Storage}, when a user cannot be loaded,
- * the future will be {@link CompletableFuture completed exceptionally}.
- *
* @param uuid the uuid of the user
* @param username the username, if known
* @return the resultant user
* @throws NullPointerException if the uuid is null
- * @since 4.1
*/
@NonNull CompletableFuture loadUser(@NonNull UUID uuid, @Nullable String username);
/**
* Loads a user from the plugin's storage provider into memory.
*
- * This method is effectively the same as {@link Storage#loadUser(UUID)},
- * however, the Future returns the resultant user instance instead of a
- * boolean flag.
- *
- * Unlike the method in {@link Storage}, when a user cannot be loaded,
- * the future will be {@link CompletableFuture completed exceptionally}.
- *
* @param uuid the uuid of the user
* @return the resultant user
* @throws NullPointerException if the uuid is null
- * @since 4.1
*/
default @NonNull CompletableFuture loadUser(@NonNull UUID uuid) {
return loadUser(uuid, null);
@@ -107,9 +86,8 @@ public interface UserManager {
* @return a uuid, could be null
* @throws NullPointerException if either parameters are null
* @throws IllegalArgumentException if the username is invalid
- * @since 4.2
*/
- @NonNull CompletableFuture lookupUuid(@NonNull String username);
+ @NonNull CompletableFuture lookupUniqueId(@NonNull String username);
/**
* Uses the LuckPerms cache to find a username for the given uuid.
@@ -118,7 +96,6 @@ public interface UserManager {
* @return a username, could be null
* @throws NullPointerException if either parameters are null
* @throws IllegalArgumentException if the username is invalid
- * @since 4.2
*/
@NonNull CompletableFuture lookupUsername(@NonNull UUID uuid);
@@ -127,17 +104,10 @@ public interface UserManager {
*
* You should call this after you make any changes to a user.
*
- * This method is effectively the same as {@link Storage#saveUser(User)},
- * however, the Future returns void instead of a boolean flag.
- *
- * Unlike the method in {@link Storage}, when a user cannot be saved,
- * the future will be {@link CompletableFuture completed exceptionally}.
- *
* @param user the user to save
* @return a future to encapsulate the operation.
* @throws NullPointerException if user is null
* @throws IllegalStateException if the user instance was not obtained from LuckPerms.
- * @since 4.1
*/
@NonNull CompletableFuture saveUser(@NonNull User user);
@@ -149,7 +119,6 @@ public interface UserManager {
* @return the result of the operation.
* @throws NullPointerException if either parameters are null
* @throws IllegalArgumentException if the username is invalid
- * @since 4.2
*/
@NonNull CompletableFuture savePlayerData(@NonNull UUID uuid, @NonNull String username);
@@ -159,7 +128,6 @@ public interface UserManager {
* "Unique" meaning the user isn't just a member of the "default" group.
*
* @return a set of uuids
- * @since 4.2
*/
@NonNull CompletableFuture> getUniqueUsers();
@@ -169,9 +137,8 @@ public interface UserManager {
* @param permission the permission to search for
* @return a list of held permissions
* @throws NullPointerException if the permission is null
- * @since 4.2
*/
- @NonNull CompletableFuture>> getWithPermission(@NonNull String permission);
+ @NonNull CompletableFuture>> getWithPermission(@NonNull String permission);
/**
* Gets a loaded user.
@@ -182,17 +149,6 @@ public interface UserManager {
*/
@Nullable User getUser(@NonNull UUID uuid);
- /**
- * Gets a loaded user.
- *
- * @param uuid the uuid of the user to get
- * @return an optional {@link User} object
- * @throws NullPointerException if the uuid is null
- */
- default @NonNull Optional getUserOpt(@NonNull UUID uuid) {
- return Optional.ofNullable(getUser(uuid));
- }
-
/**
* Gets a loaded user.
*
@@ -202,17 +158,6 @@ public interface UserManager {
*/
@Nullable User getUser(@NonNull String name);
- /**
- * Gets a loaded user.
- *
- * @param name the username of the user to get
- * @return an optional {@link User} object
- * @throws NullPointerException if the name is null
- */
- default @NonNull Optional getUserOpt(@NonNull String name) {
- return Optional.ofNullable(getUser(name));
- }
-
/**
* Gets a set of all loaded users.
*
diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/MetaType.java b/api/src/main/java/me/lucko/luckperms/api/node/ChatMetaType.java
similarity index 64%
rename from api/src/main/java/me/lucko/luckperms/api/nodetype/types/MetaType.java
rename to api/src/main/java/me/lucko/luckperms/api/node/ChatMetaType.java
index 69e30d2aa..6ac530d6c 100644
--- a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/MetaType.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/ChatMetaType.java
@@ -23,45 +23,47 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api.nodetype.types;
+package me.lucko.luckperms.api.node;
-import me.lucko.luckperms.api.Node;
-import me.lucko.luckperms.api.nodetype.NodeType;
-import me.lucko.luckperms.api.nodetype.NodeTypeKey;
+import me.lucko.luckperms.api.node.types.ChatMetaNode;
import org.checkerframework.checker.nullness.qual.NonNull;
-import java.util.Map;
-
/**
- * A sub-type of {@link Node} used to store meta assignments.
- *
- * @since 4.2
+ * Represents a type of chat meta
*/
-public interface MetaType extends NodeType, Map.Entry {
+public enum ChatMetaType {
/**
- * The key for this type.
+ * Represents a prefix
*/
- NodeTypeKey KEY = new NodeTypeKey(){};
+ PREFIX(NodeType.PREFIX),
/**
- * Gets the meta key.
+ * Represents a suffix
+ */
+ SUFFIX(NodeType.SUFFIX);
+
+ private final String name;
+ private final NodeType extends ChatMetaNode, ?>> nodeType;
+
+ ChatMetaType(NodeType extends ChatMetaNode, ?>> nodeType) {
+ this.name = nodeType.name().toLowerCase();
+ this.nodeType = nodeType;
+ }
+
+ /**
+ * Gets the {@link NodeType} for the {@link ChatMetaType}.
*
- * @return the meta key
+ * @return the node type
*/
- @NonNull String getKey();
-
- /**
- * Gets the meta value.
- *
- * @return the meta value
- */
- @NonNull String getValue();
+ public @NonNull NodeType extends ChatMetaNode, ?>> nodeType() {
+ return this.nodeType;
+ }
@Override
- @Deprecated
- default String setValue(String value) {
- throw new UnsupportedOperationException();
+ public String toString() {
+ return this.name;
}
+
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/WeightType.java b/api/src/main/java/me/lucko/luckperms/api/node/HeldNode.java
similarity index 72%
rename from api/src/main/java/me/lucko/luckperms/api/nodetype/types/WeightType.java
rename to api/src/main/java/me/lucko/luckperms/api/node/HeldNode.java
index b4f781922..21077f33d 100644
--- a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/WeightType.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/HeldNode.java
@@ -23,29 +23,31 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api.nodetype.types;
+package me.lucko.luckperms.api.node;
-import me.lucko.luckperms.api.Node;
-import me.lucko.luckperms.api.nodetype.NodeType;
-import me.lucko.luckperms.api.nodetype.NodeTypeKey;
+import me.lucko.luckperms.api.model.PermissionHolder;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
/**
- * A sub-type of {@link Node} used to mark the weight of the node's holder.
+ * A relationship between a {@link PermissionHolder} and a {@link Node}.
*
- * @since 4.2
+ * @param the identifier type of the holder
*/
-public interface WeightType extends NodeType {
+public interface HeldNode {
/**
- * The key for this type.
- */
- NodeTypeKey KEY = new NodeTypeKey(){};
-
- /**
- * Gets the weight value.
+ * Gets the holder of the node
*
- * @return the weight
+ * @return the holder
*/
- int getWeight();
+ @NonNull T getHolder();
+
+ /**
+ * Gets the node
+ *
+ * @return the node
+ */
+ @NonNull Node getNode();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/Node.java b/api/src/main/java/me/lucko/luckperms/api/node/Node.java
new file mode 100644
index 000000000..07186c0c2
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/node/Node.java
@@ -0,0 +1,237 @@
+/*
+ * This file is part of LuckPerms, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * 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.node;
+
+import me.lucko.luckperms.api.LuckPermsProvider;
+import me.lucko.luckperms.api.context.ContextSet;
+import me.lucko.luckperms.api.context.ImmutableContextSet;
+import me.lucko.luckperms.api.node.metadata.NodeMetadata;
+import me.lucko.luckperms.api.node.metadata.NodeMetadataKey;
+import me.lucko.luckperms.api.node.types.DisplayNameNode;
+import me.lucko.luckperms.api.node.types.InheritanceNode;
+import me.lucko.luckperms.api.node.types.MetaNode;
+import me.lucko.luckperms.api.node.types.PermissionNode;
+import me.lucko.luckperms.api.node.types.PrefixNode;
+import me.lucko.luckperms.api.node.types.RegexPermissionNode;
+import me.lucko.luckperms.api.node.types.SuffixNode;
+import me.lucko.luckperms.api.node.types.WeightNode;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.time.Instant;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+/**
+ * Represents a LuckPerms "node".
+ *
+ * The {@link Node} class encapsulates more than just permission assignments.
+ * Nodes are used to store data about inherited groups, as well as assigned
+ * prefixes, suffixes and meta values.
+ *
+ * Combining these various states into one object (a "node") means that a
+ * holder only has to have one type of data set (a set of nodes) in order to
+ * take on various properties.
+ *
+ * It is recommended that users of the API make use of {@link Stream}s
+ * to manipulate data and obtain the required information.
+ *
+ * This interface provides a number of methods to read the attributes of the
+ * node, as well as methods to query and extract additional state and properties
+ * from these settings.
+ *
+ * Nodes have the following attributes:
+ *
+ *
+ * {@link #getKey() key} - the key of the node
+ * {@link #getValue() value} - the value of the node (false for negated)
+ * {@link #getContexts() context} - the contexts required for this node to apply
+ * {@link #getExpiry() expiry} - the time when this node should expire
+ *
+ *
+ * There are a number of node types, all of which extend from this class:
+ *
+ *
+ * {@link PermissionNode} - represents an assigned permission
+ * {@link RegexPermissionNode} - represents an assigned regex permission
+ * {@link InheritanceNode} - an "inheritance node" marks that the holder should inherit data from another group
+ * {@link PrefixNode} - represents an assigned prefix
+ * {@link SuffixNode} - represents an assigned suffix
+ * {@link MetaNode} - represents an assigned meta option
+ * {@link WeightNode} - marks the weight of the object holding this node
+ * {@link DisplayNameNode} - marks the display name of the object holding this node
+ *
+ *
+ * The core node state must be immutable in all implementations.
+ */
+public interface Node {
+
+ /**
+ * Gets a {@link NodeBuilder} for the given node {@link #getKey() key}.
+ *
+ * @param key the key
+ * @return the node builder
+ */
+ static @NonNull NodeBuilder builder(@NonNull String key) {
+ return LuckPermsProvider.get().getNodeBuilderRegistry().forKey(key);
+ }
+
+ /**
+ * Gets the key ({@link String}) of the node.
+ *
+ * @return the key
+ */
+ @NonNull String getKey();
+
+ /**
+ * Gets the value of the node.
+ *
+ * A negated setting would result in a value of false
.
+ *
+ * @return the nodes value
+ */
+ boolean getValue();
+
+ /**
+ * Gets if the node is negated.
+ *
+ * This is the inverse of the {@link #getValue() value}.
+ *
+ * @return true if the node is negated
+ */
+ default boolean isNegated() {
+ return !getValue();
+ }
+
+ /**
+ * Gets if this node applies globally, and therefore has no specific context.
+ *
+ * @return true if this node applies globally, and has no specific context
+ */
+ boolean appliesGlobally();
+
+ /**
+ * Gets if this node should apply in the given context
+ *
+ * @param contextSet the context set
+ * @return true if the node should apply
+ */
+ boolean shouldApplyWithContext(@NonNull ContextSet contextSet);
+
+ /**
+ * Resolves any shorthand parts of this node and returns the full list of
+ * resolved nodes.
+ *
+ * The list will not contain the exact permission itself.
+ *
+ * @return a list of full nodes
+ */
+ @NonNull List resolveShorthand();
+
+ /**
+ * Gets if this node is assigned temporarily.
+ *
+ * @return true if this node will expire in the future
+ */
+ boolean hasExpiry();
+
+ /**
+ * Gets the time when this node will expire.
+ *
+ * @return the {@link Instant} when this node will expire, or null if it
+ * doesn't have an expiry time
+ */
+ @Nullable Instant getExpiry() throws IllegalStateException;
+
+ /**
+ * Gets if the node has expired.
+ *
+ * This returns false if the node is not temporary.
+ *
+ * @return true if this node has expired
+ */
+ boolean hasExpired();
+
+ /**
+ * Gets the contexts required for this node to apply.
+ *
+ * @return the contexts required for this node to apply
+ */
+ @NonNull ImmutableContextSet getContexts();
+
+ /**
+ * Gets the metadata corresponding to the given key
, if present.
+ *
+ * @param key the key
+ * @param the {@link NodeMetadata} type
+ * @return the data, if present
+ */
+ Optional getMetadata(NodeMetadataKey key);
+
+ /**
+ * Gets the metadata corresponding to the given key
, throwing an exception
+ * if no data is present.
+ *
+ * @param key the key
+ * @param the {@link NodeMetadata} type
+ * @return the data
+ * @throws IllegalStateException if data isn't present
+ */
+ default T metadata(NodeMetadataKey key) throws IllegalStateException {
+ return getMetadata(key).orElseThrow(() -> new IllegalStateException("Node '" + getKey() + "' does not have '" + key.name() + "' attached."));
+ }
+
+ /**
+ * Gets if this Node is equal to another node.
+ *
+ * @param obj the other node
+ * @return true if this node is equal to the other provided
+ * @see NodeEqualityPredicate#EXACT
+ */
+ @Override
+ boolean equals(Object obj);
+
+ /**
+ * Gets if this Node is equal to another node as defined by the given
+ * {@link NodeEqualityPredicate}.
+ *
+ * @param other the other node
+ * @param equalityPredicate the predicate
+ * @return true if this node is considered equal
+ */
+ boolean equals(@NonNull Node other, @NonNull NodeEqualityPredicate equalityPredicate);
+
+ /**
+ * Gets a {@link NodeBuilder}, with the attributes of this node already
+ * applied.
+ *
+ * @return an editable, builder form of this node
+ */
+ @NonNull NodeBuilder, ?> toBuilder();
+
+}
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/NodeBuilder.java b/api/src/main/java/me/lucko/luckperms/api/node/NodeBuilder.java
new file mode 100644
index 000000000..71e622848
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/node/NodeBuilder.java
@@ -0,0 +1,149 @@
+/*
+ * This file is part of LuckPerms, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * 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.node;
+
+import me.lucko.luckperms.api.context.ContextSet;
+import me.lucko.luckperms.api.node.metadata.NodeMetadata;
+import me.lucko.luckperms.api.node.metadata.NodeMetadataKey;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Builder for {@link Node}s.
+ *
+ * @param the node type
+ * @param the node builder type
+ */
+public interface NodeBuilder, B extends NodeBuilder> {
+
+ /**
+ * Sets the value of the node.
+ *
+ * @param value the value
+ * @return the builder
+ * @see Node#getValue()
+ */
+ @NonNull B value(boolean value);
+
+ /**
+ * Sets the value of negated for the node.
+ *
+ * @param negated the value
+ * @return the builder
+ * @see Node#isNegated()
+ */
+ @NonNull B negated(boolean negated);
+
+ /**
+ * Sets the time when the node should expire.
+ *
+ * The parameter passed to this method must be the unix timestamp
+ * (in seconds) when the node should expire.
+ *
+ * @param expiryUnixTimestamp the expiry timestamp (unix seconds)
+ * @return the builder
+ * @see Node#getExpiry()
+ */
+ @NonNull B expiry(long expiryUnixTimestamp);
+
+ /**
+ * Sets the time when the node should expire.
+ *
+ * The expiry timestamp is calculated relative to the current
+ * system time.
+ *
+ * @param duration how long the node should be added for
+ * @param unit the unit duration
is measured in
+ * @return the builder
+ */
+ default @NonNull B expiry(long duration, TimeUnit unit) {
+ if (duration <= 0) {
+ throw new IllegalArgumentException("duration must be positive");
+ }
+ long seconds = Objects.requireNonNull(unit, "unit").toSeconds(duration);
+ long timeNow = System.currentTimeMillis() / 1000L;
+ return expiry(timeNow + seconds);
+ }
+
+ /**
+ * Marks that the node being built should never expire.
+ *
+ * @return the builder
+ */
+ @NonNull B clearExpiry();
+
+ /**
+ * Sets the extra contexts for the node.
+ *
+ * @param contextSet a context set
+ * @return the builder
+ * @see ContextSet
+ * @see Node#getContexts()
+ */
+ @NonNull B context(@NonNull ContextSet contextSet);
+
+ /**
+ * Appends an extra context onto the node.
+ *
+ * @param key the context key
+ * @param value the context value
+ * @return the builder
+ * @see ContextSet
+ * @see Node#getContexts()
+ */
+ @NonNull B withContext(@NonNull String key, @NonNull String value);
+
+ /**
+ * Appends extra contexts onto the node.
+ *
+ * @param contextSet a context set
+ * @return the builder
+ * @see ContextSet
+ * @see Node#getContexts()
+ */
+ @NonNull B withContext(@NonNull ContextSet contextSet);
+
+ /**
+ * Sets the given metadata for the node.
+ *
+ * @param key the metadata key
+ * @param metadata the metadata
+ * @param the metadata type
+ * @return the builder
+ */
+ @NonNull B withMetadata(@NonNull NodeMetadataKey key, @Nullable T metadata);
+
+ /**
+ * Creates a {@link Node} instance from the builder.
+ *
+ * @return a new node instance
+ */
+ @NonNull N build();
+}
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/NodeBuilderRegistry.java b/api/src/main/java/me/lucko/luckperms/api/node/NodeBuilderRegistry.java
new file mode 100644
index 000000000..7833fde7a
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/node/NodeBuilderRegistry.java
@@ -0,0 +1,109 @@
+/*
+ * This file is part of LuckPerms, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * 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.node;
+
+import me.lucko.luckperms.api.node.types.DisplayNameNode;
+import me.lucko.luckperms.api.node.types.InheritanceNode;
+import me.lucko.luckperms.api.node.types.MetaNode;
+import me.lucko.luckperms.api.node.types.PermissionNode;
+import me.lucko.luckperms.api.node.types.PrefixNode;
+import me.lucko.luckperms.api.node.types.RegexPermissionNode;
+import me.lucko.luckperms.api.node.types.SuffixNode;
+import me.lucko.luckperms.api.node.types.WeightNode;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+/**
+ * A registry of methods for obtaining {@link NodeBuilder}s for the various
+ * node types.
+ */
+public interface NodeBuilderRegistry {
+
+ /**
+ * Gets a {@link NodeBuilder} applicable for the given key.
+ *
+ * @param key the key
+ * @return the node builder
+ */
+ @NonNull NodeBuilder, ?> forKey(String key);
+
+ /**
+ * Gets a {@link NodeBuilder} for {@link PermissionNode}s.
+ *
+ * @return the node builder
+ */
+ PermissionNode.@NonNull Builder forPermission();
+
+ /**
+ * Gets a {@link NodeBuilder} for {@link RegexPermissionNode}s.
+ *
+ * @return the node builder
+ */
+ RegexPermissionNode.@NonNull Builder forRegexPermission();
+
+ /**
+ * Gets a {@link NodeBuilder} for {@link InheritanceNode}s.
+ *
+ * @return the node builder
+ */
+ InheritanceNode.@NonNull Builder forInheritance();
+
+ /**
+ * Gets a {@link NodeBuilder} for {@link PrefixNode}s.
+ *
+ * @return the node builder
+ */
+ PrefixNode.@NonNull Builder forPrefix();
+
+ /**
+ * Gets a {@link NodeBuilder} for {@link SuffixNode}s.
+ *
+ * @return the node builder
+ */
+ SuffixNode.@NonNull Builder forSuffix();
+
+ /**
+ * Gets a {@link NodeBuilder} for {@link MetaNode}s.
+ *
+ * @return the node builder
+ */
+ MetaNode.@NonNull Builder forMeta();
+
+ /**
+ * Gets a {@link NodeBuilder} for {@link WeightNode}s.
+ *
+ * @return the node builder
+ */
+ WeightNode.@NonNull Builder forWeight();
+
+ /**
+ * Gets a {@link NodeBuilder} for {@link DisplayNameNode}s.
+ *
+ * @return the node builder
+ */
+ DisplayNameNode.@NonNull Builder forDisplayName();
+
+}
diff --git a/api/src/main/java/me/lucko/luckperms/api/StandardNodeEquality.java b/api/src/main/java/me/lucko/luckperms/api/node/NodeEqualityPredicate.java
similarity index 51%
rename from api/src/main/java/me/lucko/luckperms/api/StandardNodeEquality.java
rename to api/src/main/java/me/lucko/luckperms/api/node/NodeEqualityPredicate.java
index 6b06c44db..467e2ddbb 100644
--- a/api/src/main/java/me/lucko/luckperms/api/StandardNodeEquality.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/NodeEqualityPredicate.java
@@ -23,16 +23,39 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api;
+package me.lucko.luckperms.api.node;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
- * Standard {@link NodeEqualityPredicate}s.
+ * A rule for determining if two nodes are equal.
*
- * @since 4.1
+ * Generally, implementations of this interface should fulfil the same
+ * requirements as the {@link Object#equals(Object)} contract.
*/
-public enum StandardNodeEquality implements NodeEqualityPredicate {
+@FunctionalInterface
+public interface NodeEqualityPredicate {
+
+ /**
+ * Returns if the two nodes are equal.
+ *
+ * This method should avoid making calls to {@link Node#equals(Node, NodeEqualityPredicate)}
+ * with {@code this} as the second argument, directly or otherwise.
+ *
+ * @param o1 the first node
+ * @param o2 the second node
+ * @return true if equal
+ */
+ boolean areEqual(@NonNull Node o1, @NonNull Node o2);
+
+
+ /*
+ * Some 'default' implementations of NodeEqualityPredicate are provided below.
+ *
+ * These are implemented in the common code, by a special case in the
+ * implementation of Node#equals. As noted above, this should generally be
+ * avoided.
+ */
/**
* Represents an exact match.
@@ -40,13 +63,17 @@ public enum StandardNodeEquality implements NodeEqualityPredicate {
* All attributes of the nodes must match for them to be considered
* equal.
*/
- EXACT,
+ NodeEqualityPredicate EXACT = new NodeEqualityPredicate() {
+ @Override public boolean areEqual(@NonNull Node o1, @NonNull Node o2) { return o1.equals(o2, this); }
+ };
/**
* All attributes must match, except for
* {@link Node#getValue() value}, which is ignored.
*/
- IGNORE_VALUE,
+ NodeEqualityPredicate IGNORE_VALUE = new NodeEqualityPredicate() {
+ @Override public boolean areEqual(@NonNull Node o1, @NonNull Node o2) { return o1.equals(o2, this); }
+ };
/**
* All attributes must match, except for the
@@ -55,24 +82,26 @@ public enum StandardNodeEquality implements NodeEqualityPredicate {
* Note that with this setting, whether a node is temporary or not is
* still considered.
*/
- IGNORE_EXPIRY_TIME,
+ NodeEqualityPredicate IGNORE_EXPIRY_TIME = new NodeEqualityPredicate() {
+ @Override public boolean areEqual(@NonNull Node o1, @NonNull Node o2) { return o1.equals(o2, this); }
+ };
/**
* All attributes must match, except for
* {@link Node#getValue() value} and the
* {@link Node#getExpiry() expiry time}, which are ignored.
*/
- IGNORE_EXPIRY_TIME_AND_VALUE,
+ NodeEqualityPredicate IGNORE_EXPIRY_TIME_AND_VALUE = new NodeEqualityPredicate() {
+ @Override public boolean areEqual(@NonNull Node o1, @NonNull Node o2) { return o1.equals(o2, this); }
+ };
/**
* All attributes must match, except for
* {@link Node#getValue() value} and the if the node is
- * {@link Node#isTemporary() temporary}, which are ignored.
+ * {@link Node#hasExpiry() temporary}, which are ignored.
*/
- IGNORE_VALUE_OR_IF_TEMPORARY;
+ NodeEqualityPredicate IGNORE_VALUE_OR_IF_TEMPORARY = new NodeEqualityPredicate() {
+ @Override public boolean areEqual(@NonNull Node o1, @NonNull Node o2) { return o1.equals(o2, this); }
+ };
- @Override
- public boolean areEqual(@NonNull Node o1, @NonNull Node o2) {
- return o1.equals(o2, this);
- }
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/NodeType.java b/api/src/main/java/me/lucko/luckperms/api/node/NodeType.java
new file mode 100644
index 000000000..e60a0510a
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/node/NodeType.java
@@ -0,0 +1,166 @@
+/*
+ * This file is part of LuckPerms, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * 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.node;
+
+import me.lucko.luckperms.api.node.types.ChatMetaNode;
+import me.lucko.luckperms.api.node.types.DisplayNameNode;
+import me.lucko.luckperms.api.node.types.InheritanceNode;
+import me.lucko.luckperms.api.node.types.MetaNode;
+import me.lucko.luckperms.api.node.types.PermissionNode;
+import me.lucko.luckperms.api.node.types.PrefixNode;
+import me.lucko.luckperms.api.node.types.RegexPermissionNode;
+import me.lucko.luckperms.api.node.types.SuffixNode;
+import me.lucko.luckperms.api.node.types.WeightNode;
+
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+/**
+ * Represents a type of {@link Node}.
+ */
+public interface NodeType {
+
+ /**
+ * Node type for {@link PermissionNode}.
+ */
+ NodeType PERMISSION = new SimpleNodeType<>("PERMISSION", n -> n instanceof PermissionNode, n -> ((PermissionNode) n));
+
+ /**
+ * Node type for {@link RegexPermissionNode}.
+ */
+ NodeType REGEX_PERMISSION = new SimpleNodeType<>("REGEX_PERMISSION", n -> n instanceof RegexPermissionNode, n -> ((RegexPermissionNode) n));
+
+ /**
+ * Node type for {@link InheritanceNode}.
+ */
+ NodeType INHERITANCE = new SimpleNodeType<>("INHERITANCE", n -> n instanceof InheritanceNode, n -> ((InheritanceNode) n));
+
+ /**
+ * Node type for {@link PrefixNode}.
+ */
+ NodeType PREFIX = new SimpleNodeType<>("PREFIX", n -> n instanceof PrefixNode, n -> ((PrefixNode) n));
+
+ /**
+ * Node type for {@link SuffixNode}.
+ */
+ NodeType SUFFIX = new SimpleNodeType<>("SUFFIX", n -> n instanceof SuffixNode, n -> ((SuffixNode) n));
+
+ /**
+ * Node type for {@link MetaNode}.
+ */
+ NodeType META = new SimpleNodeType<>("META", n -> n instanceof MetaNode, n -> ((MetaNode) n));
+
+ /**
+ * Node type for {@link WeightNode}.
+ */
+ NodeType WEIGHT = new SimpleNodeType<>("WEIGHT", n -> n instanceof WeightNode, n -> ((WeightNode) n));
+
+ /**
+ * Node type for {@link DisplayNameNode}.
+ */
+ NodeType DISPLAY_NAME = new SimpleNodeType<>("DISPLAY_NAME", n -> n instanceof DisplayNameNode, n -> ((DisplayNameNode) n));
+
+ /**
+ * Node type for {@link ChatMetaNode}.
+ */
+ NodeType> CHAT_META = new SimpleNodeType<>("CHAT_META", n -> n instanceof ChatMetaNode, ?>, n -> ((ChatMetaNode, ?>) n));
+
+ /**
+ * Node type for {@link ChatMetaNode} or {@link MetaNode}.
+ */
+ NodeType META_OR_CHAT_META = new SimpleNodeType<>("META_OR_CHAT_META", n -> META.matches(n) || CHAT_META.matches(n), Function.identity());
+
+ /**
+ * Gets a name for the node type.
+ *
+ * @return a name
+ */
+ String name();
+
+ /**
+ * Returns if the passed node matches the type
+ *
+ * @param node the node to test
+ * @return true if the node has the same type
+ */
+ boolean matches(Node node);
+
+ /**
+ * Casts the given {@link Node} to the type defined by the {@link NodeType}.
+ *
+ * An {@link IllegalArgumentException} is thrown if the node to cast does
+ * not {@link #matches(Node) match} the type.
+ *
+ * @param node the node to cast
+ * @return the casted node
+ * @throws IllegalArgumentException if the node to cast does not match the type
+ */
+ T cast(Node node);
+
+ /**
+ * Attempts to cast the given {@link Node} to the type defined by the
+ * {@link NodeType}.
+ *
+ * Returns an {@link Optional#empty() empty optional} if the node to cast
+ * does not {@link #matches(Node) match} the type.
+ *
+ * @param node the node to cast
+ * @return an optional, possibly containing a casted node
+ */
+ default Optional tryCast(Node node) {
+ Objects.requireNonNull(node, "node");
+ if (!matches(node)) {
+ return Optional.empty();
+ } else {
+ return Optional.of(cast(node));
+ }
+ }
+
+ /**
+ * Returns a {@link Predicate}, returning whether a {@link Node}
+ * {@link #matches(Node) matches} this type.
+ *
+ * @return a predicate for the {@link #matches(Node)} method.
+ */
+ default Predicate predicate() {
+ return this::matches;
+ }
+
+ /**
+ * Returns a {@link Predicate}, returning whether a {@link Node}
+ * {@link #matches(Node) matches} this type, and passes the given
+ * {@code and} {@link Predicate}.
+ *
+ * @param and a predicate to AND with the result of the type match check
+ * @return a matching predicate, ANDed with the given predicate parameter
+ */
+ default Predicate predicate(Predicate super T> and) {
+ return node -> matches(node) && and.test(cast(node));
+ }
+
+}
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/ScopedNode.java b/api/src/main/java/me/lucko/luckperms/api/node/ScopedNode.java
new file mode 100644
index 000000000..8a78241f8
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/node/ScopedNode.java
@@ -0,0 +1,42 @@
+/*
+ * This file is part of LuckPerms, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * 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.node;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+/**
+ * A {@link Node}, with its own type and the type of its associated builder
+ * defined as a type parameter.
+ *
+ * @param the node type
+ * @param the node builder type
+ */
+public interface ScopedNode, B extends NodeBuilder> extends Node {
+
+ @Override
+ @NonNull B toBuilder();
+
+}
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableTransientNode.java b/api/src/main/java/me/lucko/luckperms/api/node/SimpleNodeType.java
similarity index 61%
rename from common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableTransientNode.java
rename to api/src/main/java/me/lucko/luckperms/api/node/SimpleNodeType.java
index 47aca455f..6626ecb8b 100644
--- a/common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableTransientNode.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/SimpleNodeType.java
@@ -23,45 +23,44 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.node.model;
-
-import me.lucko.luckperms.api.Node;
+package me.lucko.luckperms.api.node;
import java.util.Objects;
+import java.util.function.Function;
+import java.util.function.Predicate;
-/**
- * Holds a Node and plus an owning object. All calls are passed onto the contained Node instance.
- */
-public final class ImmutableTransientNode extends ForwardingNode implements Node {
- public static ImmutableTransientNode of(Node node, O owner) {
- Objects.requireNonNull(node, "node");
- Objects.requireNonNull(owner, "owner");
- return new ImmutableTransientNode<>(node, owner);
- }
+final class SimpleNodeType implements NodeType {
+ private final String name;
+ private final Predicate matches;
+ private final Function cast;
- private final Node node;
- private final O owner;
-
- private ImmutableTransientNode(Node node, O owner) {
- this.node = node;
- this.owner = owner;
+ SimpleNodeType(String name, Predicate matches, Function cast) {
+ this.name = name;
+ this.matches = matches;
+ this.cast = cast;
}
@Override
- public Node delegate() {
- return this.node;
+ public String name() {
+ return this.name;
}
- public Node getNode() {
- return this.node;
+ @Override
+ public boolean matches(Node node) {
+ Objects.requireNonNull(node, "node");
+ return this.matches.test(node);
}
- public O getOwner() {
- return this.owner;
+ @Override
+ public T cast(Node node) {
+ if (!matches(node)) {
+ throw new IllegalArgumentException("Node " + node.getClass() + " does not match " + this.name);
+ }
+ return this.cast.apply(node);
}
@Override
public String toString() {
- return "ImmutableTransientNode(node=" + this.getNode() + ", owner=" + this.getOwner() + ")";
+ return name();
}
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/Tristate.java b/api/src/main/java/me/lucko/luckperms/api/node/Tristate.java
similarity index 91%
rename from api/src/main/java/me/lucko/luckperms/api/Tristate.java
rename to api/src/main/java/me/lucko/luckperms/api/node/Tristate.java
index 4bd832d0d..7218e75d2 100644
--- a/api/src/main/java/me/lucko/luckperms/api/Tristate.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/Tristate.java
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api;
+package me.lucko.luckperms.api.node;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -61,22 +61,21 @@ public enum Tristate {
* @param val the boolean value
* @return {@link #TRUE} or {@link #FALSE}, if the value is true
or false
, respectively.
*/
- public static @NonNull Tristate fromBoolean(boolean val) {
+ public static @NonNull Tristate of(boolean val) {
return val ? TRUE : FALSE;
}
/**
* Returns a {@link Tristate} from a nullable boolean.
*
- * Unlike {@link #fromBoolean(boolean)}, this method returns {@link #UNDEFINED}
+ *
Unlike {@link #of(boolean)}, this method returns {@link #UNDEFINED}
* if the value is null.
*
* @param val the boolean value
* @return {@link #UNDEFINED}, {@link #TRUE} or {@link #FALSE}, if the value
* is null
, true
or false
, respectively.
- * @since 4.1
*/
- public static @NonNull Tristate fromNullableBoolean(Boolean val) {
+ public static @NonNull Tristate of(Boolean val) {
return val == null ? UNDEFINED : val ? TRUE : FALSE;
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/metadata/NodeMetadata.java b/api/src/main/java/me/lucko/luckperms/api/node/metadata/NodeMetadata.java
new file mode 100644
index 000000000..f46cf0aa5
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/node/metadata/NodeMetadata.java
@@ -0,0 +1,36 @@
+/*
+ * This file is part of LuckPerms, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * 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.node.metadata;
+
+import me.lucko.luckperms.api.node.Node;
+
+/**
+ * Generic interface for an {@link Object} which can be attached to a
+ * {@link Node} as metadata.
+ */
+public interface NodeMetadata {
+
+}
diff --git a/api/src/main/java/me/lucko/luckperms/api/HeldPermission.java b/api/src/main/java/me/lucko/luckperms/api/node/metadata/NodeMetadataKey.java
similarity index 50%
rename from api/src/main/java/me/lucko/luckperms/api/HeldPermission.java
rename to api/src/main/java/me/lucko/luckperms/api/node/metadata/NodeMetadataKey.java
index f56f7f65e..9ddd18089 100644
--- a/api/src/main/java/me/lucko/luckperms/api/HeldPermission.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/metadata/NodeMetadataKey.java
@@ -23,77 +23,56 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api;
-
-import me.lucko.luckperms.api.context.ContextSet;
+package me.lucko.luckperms.api.node.metadata;
import org.checkerframework.checker.nullness.qual.NonNull;
-import java.util.Optional;
-import java.util.OptionalLong;
+import java.util.Objects;
/**
- * A relationship between a {@link PermissionHolder} and a permission.
+ * Represents a key for a specific type of {@link NodeMetadata}.
*
- * @param the identifier type of the holder
- * @since 2.17
+ * Metadata keys are compared using reference equality, the
+ * {@link #equals(Object)} method should not be implemented.
+ *
+ * It is intended that {@link NodeMetadataKey}s are obtained and stored as
+ * follows.
+ *
+ * public static final NodeMetadataKey SPECIAL_METADATA_KEY = NodeMetadataKey.of("SpecialMetadata", SpecialMetadata.class);
+ *
+ *
+ * @param the metadata type
*/
-public interface HeldPermission {
+public interface NodeMetadataKey {
/**
- * Gets the holder of the permission
+ * Creates a new {@link NodeMetadataKey} for the given name and type.
*
- * @return the holder
+ * Note that the returned key implements object reference equality.
+ *
+ * @param name the name
+ * @param type the type
+ * @param the type parameter
+ * @return the key
*/
- @NonNull T getHolder();
+ static @NonNull NodeMetadataKey of(@NonNull String name, @NonNull Class type) {
+ Objects.requireNonNull(name, "name");
+ Objects.requireNonNull(type, "type");
+ return new SimpleNodeMetadataKey<>(name, type);
+ }
/**
- * Gets the permission being held
+ * Gets a name describing the key type.
*
- * @return the permission
+ * @return the key name
*/
- @NonNull String getPermission();
+ @NonNull String name();
/**
- * Gets the value of the permission
+ * Gets the type of the key
*
- * @return the value
+ * @return the type
*/
- boolean getValue();
-
- /**
- * Gets the server where the permission is held
- *
- * @return the server
- */
- @NonNull Optional getServer();
-
- /**
- * Gets the world where the permission is held
- *
- * @return the world
- */
- @NonNull Optional getWorld();
-
- /**
- * Gets the time in unix time when the permission will expire
- *
- * @return the expiry time
- */
- @NonNull OptionalLong getExpiry();
-
- /**
- * Gets the extra context for the permission.
- *
- * @return the extra context
- */
- @NonNull ContextSet getContexts();
-
- /**
- * Converts this permission into a Node
- *
- * @return a Node copy of this permission
- */
- @NonNull Node asNode();
+ @NonNull Class getType();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/metadata/SimpleNodeMetadataKey.java b/api/src/main/java/me/lucko/luckperms/api/node/metadata/SimpleNodeMetadataKey.java
new file mode 100644
index 000000000..740278558
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/node/metadata/SimpleNodeMetadataKey.java
@@ -0,0 +1,53 @@
+/*
+ * This file is part of luckperms, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * 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.node.metadata;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+final class SimpleNodeMetadataKey implements NodeMetadataKey {
+ private final String name;
+ private final Class type;
+
+ SimpleNodeMetadataKey(String name, Class type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ @Override
+ public @NonNull String name() {
+ return this.name;
+ }
+
+ @Override
+ public @NonNull Class getType() {
+ return this.type;
+ }
+
+ @Override
+ public String toString() {
+ return "NodeMetadataKey(name=" + this.name + ", type=" + this.type.getName() + ")";
+ }
+}
diff --git a/api/src/main/java/me/lucko/luckperms/api/LocalizedNode.java b/api/src/main/java/me/lucko/luckperms/api/node/metadata/types/InheritanceOriginMetadata.java
similarity index 74%
rename from api/src/main/java/me/lucko/luckperms/api/LocalizedNode.java
rename to api/src/main/java/me/lucko/luckperms/api/node/metadata/types/InheritanceOriginMetadata.java
index e9bf05c17..0db8be19c 100644
--- a/api/src/main/java/me/lucko/luckperms/api/LocalizedNode.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/metadata/types/InheritanceOriginMetadata.java
@@ -23,26 +23,24 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.api;
+package me.lucko.luckperms.api.node.metadata.types;
+
+import me.lucko.luckperms.api.model.PermissionHolder;
+import me.lucko.luckperms.api.node.Node;
+import me.lucko.luckperms.api.node.metadata.NodeMetadata;
+import me.lucko.luckperms.api.node.metadata.NodeMetadataKey;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
- * An extension of {@link Node}, providing information about
- * where the node originated from.
- *
- * @since 2.11
+ * {@link NodeMetadata} indicating where a node was inherited from.
*/
-public interface LocalizedNode extends Node {
+public interface InheritanceOriginMetadata extends NodeMetadata {
/**
- * Gets the delegate node.
- *
- * Result is never another {@link LocalizedNode} instance.
- *
- * @return the node this instance is representing
+ * The {@link NodeMetadataKey} for {@link InheritanceOriginMetadata}.
*/
- @NonNull Node getNode();
+ NodeMetadataKey KEY = NodeMetadataKey.of("InheritanceOrigin", InheritanceOriginMetadata.class);
/**
* Gets the location where the {@link Node} is inherited from.
@@ -55,6 +53,6 @@ public interface LocalizedNode extends Node {
*
* @return where the node was inherited from.
*/
- @NonNull String getLocation();
+ @NonNull String getOrigin();
}
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/types/ChatMetaNode.java b/api/src/main/java/me/lucko/luckperms/api/node/types/ChatMetaNode.java
new file mode 100644
index 000000000..07b372ebc
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/node/types/ChatMetaNode.java
@@ -0,0 +1,81 @@
+/*
+ * This file is part of LuckPerms, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * 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.node.types;
+
+import me.lucko.luckperms.api.node.ChatMetaType;
+import me.lucko.luckperms.api.node.NodeBuilder;
+import me.lucko.luckperms.api.node.ScopedNode;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+/**
+ * Represents a chat meta node. (a {@link PrefixNode} or {@link SuffixNode})
+ *
+ * @param the node type
+ * @param the node builder type
+ */
+public interface ChatMetaNode, B extends ChatMetaNode.Builder