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

me.lucko.luckperms.api.Node Maven / Gradle / Ivy

Go to download

An advanced permissions plugin for Bukkit/Spigot, BungeeCord, Sponge, Nukkit and Velocity.

The newest version!
/*
 * 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(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy