{@link #getExpiry() expiry} - the time when this node should expire
*
*
- *
Nodes can also fall into the following sub categories.
+ *
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 #isGroupNode() group node} - a "group node" marks that the holder should inherit data from another group
- *
{@link #isPrefix() prefix} - represents an assigned prefix
- *
{@link #isSuffix() suffix} - represents an assigned suffix
- *
{@link #isMeta() meta} - represents an assigned meta option
+ *
{@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
*
*
*
The core node state must be immutable in all implementations.
@@ -108,19 +123,7 @@ public interface Node {
*
* @return the nodes value
*/
- @Nonnull
- default Boolean getValue() {
- return getValuePrimitive();
- }
-
- /**
- * Gets the value of the node.
- *
- *
A negated setting would result in a value of false.
- *
- * @return the nodes value
- */
- boolean getValuePrimitive();
+ boolean getValue();
/**
* Gets the value of this node as a {@link Tristate}.
@@ -129,18 +132,18 @@ public interface Node {
*/
@Nonnull
default Tristate getTristate() {
- return Tristate.fromBoolean(getValuePrimitive());
+ return Tristate.fromBoolean(getValue());
}
/**
* Gets if the node is negated.
*
- *
This is the inverse of the {@link #getValuePrimitive() value}.
+ *
This is the inverse of the {@link #getValue() value}.
*
* @return true if the node is negated
*/
default boolean isNegated() {
- return !getValuePrimitive();
+ return !getValue();
}
/**
@@ -209,7 +212,8 @@ public interface Node {
boolean shouldApplyWithContext(@Nonnull ContextSet contextSet);
/**
- * Resolves any shorthand parts of this node and returns the full list.
+ * Resolves any shorthand parts of this node and returns the full list of
+ * resolved nodes.
*
*
The list will not contain the exact permission itself.
*
@@ -219,7 +223,7 @@ public interface Node {
List resolveShorthand();
/**
- * Gets if this node is temporary (will automatically expire).
+ * Gets if this node is assigned temporarily.
*
* @return true if this node will expire in the future
*/
@@ -291,30 +295,6 @@ public interface Node {
@Nonnull
ContextSet getFullContexts();
- /**
- * Returns if the node is a "standard" permission node.
- *
- * @return true if this is a regular permission node
- * @since 4.2
- */
- boolean isRegularPermissionNode();
-
- /**
- * Returns if this is a group node.
- *
- * @return true if this is a group node
- */
- boolean isGroupNode();
-
- /**
- * Gets the name of the group, if this is a group node.
- *
- * @return the name of the group
- * @throws IllegalStateException if this is not a group node. See {@link #isGroupNode()}
- */
- @Nonnull
- String getGroupName() throws IllegalStateException;
-
/**
* Gets if this node is a wildcard permission.
*
@@ -325,58 +305,135 @@ public interface Node {
/**
* 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 is a meta node.
+ * Gets if this node has any extra {@link NodeType} data attached to it.
*
- * @return true if this node is a meta node
+ * @return if this node has any type data
+ * @since 4.2
*/
- boolean isMeta();
+ boolean hasTypeData();
/**
- * Gets the meta value from this node.
+ * Gets the type data corresponding to the given key, if present.
*
- * @return the meta value
- * @throws IllegalStateException if this node is not a meta node
+ * @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
*/
@Nonnull
- Map.Entry getMeta() throws IllegalStateException;
+ default String getGroupName() throws IllegalStateException {
+ return typeData(InheritanceType.KEY).getGroupName();
+ }
/**
- * Gets if this node is a prefix node.
+ * 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
+ */
+ @Nonnull
+ default Map.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
*/
- boolean isPrefix();
+ default boolean isPrefix() {
+ return getTypeData(PrefixType.KEY).isPresent();
+ }
/**
- * Gets the prefix value from this node.
+ * Gets the prefix entry if this node has {@link PrefixType} type data,
+ * throwing an exception if the data is not present.
*
- * @return the prefix value
- * @throws IllegalStateException if this node is a not a prefix node
+ * @return the meta entry
+ * @throws IllegalStateException if this node doesn't have {@link PrefixType} data
*/
@Nonnull
- Map.Entry getPrefix() throws IllegalStateException;
+ default Map.Entry getPrefix() throws IllegalStateException {
+ return typeData(PrefixType.KEY).getAsEntry();
+ }
/**
- * Gets if this node is a suffix node.
+ * Gets if this node has {@link SuffixType} type data.
*
* @return true if this node is a suffix node
*/
- boolean isSuffix();
+ default boolean isSuffix() {
+ return getTypeData(SuffixType.KEY).isPresent();
+ }
/**
- * Gets the suffix value from this node.
+ * Gets the suffix entry if this node has {@link SuffixType} type data,
+ * throwing an exception if the data is not present.
*
- * @return the suffix value
- * @throws IllegalStateException if this node is a not a suffix node
+ * @return the meta entry
+ * @throws IllegalStateException if this node doesn't have {@link SuffixType} data
*/
@Nonnull
- Map.Entry getSuffix() throws IllegalStateException;
+ default Map.Entry getSuffix() throws IllegalStateException {
+ return typeData(SuffixType.KEY).getAsEntry();
+ }
/**
* Gets if this Node is equal to another node.
diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/NodeType.java b/api/src/main/java/me/lucko/luckperms/api/nodetype/NodeType.java
new file mode 100644
index 00000000..abfb3d13
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/nodetype/NodeType.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.nodetype;
+
+import me.lucko.luckperms.api.Node;
+
+/**
+ * Superinterface for extended {@link Node} types.
+ *
+ *
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 Node#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.
+ *
+ * @since 4.2
+ */
+public interface NodeType {
+
+}
diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/NodeTypeKey.java b/api/src/main/java/me/lucko/luckperms/api/nodetype/NodeTypeKey.java
new file mode 100644
index 00000000..32f2dedc
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/nodetype/NodeTypeKey.java
@@ -0,0 +1,56 @@
+/*
+ * 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.nodetype;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Marks an instance used as a key for a {@link NodeType}.
+ *
+ *
A single instance of this interface is created and stored statically for
+ * each sub-interface of {@link NodeType}.
+ *
+ * @param the type of the {@link NodeType} being indexed by this key
+ * @since 4.2
+ */
+public interface NodeTypeKey {
+
+ /**
+ * Gets the {@link Class#getSimpleName() class name} of the represented type.
+ *
+ * @return the name of the represented type
+ */
+ @Nonnull
+ default String getTypeName() {
+ ParameterizedType thisType = (ParameterizedType) getClass().getGenericSuperclass();
+ Type nodeType = thisType.getActualTypeArguments()[0];
+ return ((Class) nodeType).getSimpleName();
+ }
+
+}
diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/InheritanceType.java b/api/src/main/java/me/lucko/luckperms/api/nodetype/types/InheritanceType.java
new file mode 100644
index 00000000..8f5ba38d
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/nodetype/types/InheritanceType.java
@@ -0,0 +1,57 @@
+/*
+ * 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.nodetype.types;
+
+import me.lucko.luckperms.api.Node;
+import me.lucko.luckperms.api.nodetype.NodeType;
+import me.lucko.luckperms.api.nodetype.NodeTypeKey;
+
+import javax.annotation.Nonnull;
+
+/**
+ * A sub-type of {@link Node} used to mark that the holder of the node should inherit
+ * from another group.
+ *
+ * @since 4.2
+ */
+public interface InheritanceType extends NodeType {
+
+ /**
+ * The key for this type.
+ */
+ NodeTypeKey KEY = new NodeTypeKey(){};
+
+ /**
+ * Gets the name of the group to be inherited.
+ *
+ *
This is no guarantee that this group exists.
+ *
+ * @return the name of the group
+ */
+ @Nonnull
+ String getGroupName();
+
+}
diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/MetaType.java b/api/src/main/java/me/lucko/luckperms/api/nodetype/types/MetaType.java
new file mode 100644
index 00000000..0f9c094c
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/nodetype/types/MetaType.java
@@ -0,0 +1,69 @@
+/*
+ * 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.nodetype.types;
+
+import me.lucko.luckperms.api.Node;
+import me.lucko.luckperms.api.nodetype.NodeType;
+import me.lucko.luckperms.api.nodetype.NodeTypeKey;
+
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+/**
+ * A sub-type of {@link Node} used to store meta assignments.
+ *
+ * @since 4.2
+ */
+public interface MetaType extends NodeType, Map.Entry {
+
+ /**
+ * The key for this type.
+ */
+ NodeTypeKey KEY = new NodeTypeKey(){};
+
+ /**
+ * Gets the meta key.
+ *
+ * @return the meta key
+ */
+ @Nonnull
+ String getKey();
+
+ /**
+ * Gets the meta value.
+ *
+ * @return the meta value
+ */
+ @Nonnull
+ String getValue();
+
+ @Override
+ @Deprecated
+ default String setValue(String value) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/PrefixType.java b/api/src/main/java/me/lucko/luckperms/api/nodetype/types/PrefixType.java
new file mode 100644
index 00000000..c3a052dc
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/nodetype/types/PrefixType.java
@@ -0,0 +1,71 @@
+/*
+ * 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.nodetype.types;
+
+import me.lucko.luckperms.api.Node;
+import me.lucko.luckperms.api.nodetype.NodeType;
+import me.lucko.luckperms.api.nodetype.NodeTypeKey;
+
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+/**
+ * A sub-type of {@link Node} used to store prefix assignments.
+ *
+ * @since 4.2
+ */
+public interface PrefixType extends NodeType {
+
+ /**
+ * The key for this type.
+ */
+ NodeTypeKey KEY = new NodeTypeKey(){};
+
+ /**
+ * Gets the priority of the prefix assignment.
+ *
+ * @return the priority
+ */
+ int getPriority();
+
+ /**
+ * Gets the actual prefix string.
+ *
+ * @return the prefix
+ */
+ @Nonnull
+ String getPrefix();
+
+ /**
+ * Gets a representation of this instance as a {@link Map.Entry}.
+ *
+ * @return a map entry representation of the priority and prefix string
+ */
+ @Nonnull
+ Map.Entry getAsEntry();
+
+}
diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/SuffixType.java b/api/src/main/java/me/lucko/luckperms/api/nodetype/types/SuffixType.java
new file mode 100644
index 00000000..3a5b7187
--- /dev/null
+++ b/api/src/main/java/me/lucko/luckperms/api/nodetype/types/SuffixType.java
@@ -0,0 +1,71 @@
+/*
+ * 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.nodetype.types;
+
+import me.lucko.luckperms.api.Node;
+import me.lucko.luckperms.api.nodetype.NodeType;
+import me.lucko.luckperms.api.nodetype.NodeTypeKey;
+
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+/**
+ * A sub-type of {@link Node} used to store suffix assignments.
+ *
+ * @since 4.2
+ */
+public interface SuffixType extends NodeType {
+
+ /**
+ * The key for this type.
+ */
+ NodeTypeKey KEY = new NodeTypeKey(){};
+
+ /**
+ * Gets the priority of the suffix assignment.
+ *
+ * @return the priority
+ */
+ int getPriority();
+
+ /**
+ * Gets the actual suffix string.
+ *
+ * @return the suffix
+ */
+ @Nonnull
+ String getSuffix();
+
+ /**
+ * Gets a representation of this instance as a {@link Map.Entry}.
+ *
+ * @return a map entry representation of the priority and suffix string
+ */
+ @Nonnull
+ Map.Entry getAsEntry();
+
+}
diff --git a/common/src/main/java/me/lucko/luckperms/common/references/HolderReference.java b/api/src/main/java/me/lucko/luckperms/api/nodetype/types/WeightType.java
similarity index 65%
rename from common/src/main/java/me/lucko/luckperms/common/references/HolderReference.java
rename to api/src/main/java/me/lucko/luckperms/api/nodetype/types/WeightType.java
index 834d01e4..b4f78192 100644
--- a/common/src/main/java/me/lucko/luckperms/common/references/HolderReference.java
+++ b/api/src/main/java/me/lucko/luckperms/api/nodetype/types/WeightType.java
@@ -23,34 +23,29 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.references;
+package me.lucko.luckperms.api.nodetype.types;
-import me.lucko.luckperms.common.model.PermissionHolder;
-import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
-
-import java.util.function.Consumer;
+import me.lucko.luckperms.api.Node;
+import me.lucko.luckperms.api.nodetype.NodeType;
+import me.lucko.luckperms.api.nodetype.NodeTypeKey;
/**
- * A reference to a specific {@link PermissionHolder}.
+ * A sub-type of {@link Node} used to mark the weight of the node's holder.
*
- * @param the holder type
- * @param the holder identifier type
+ * @since 4.2
*/
-public interface HolderReference extends Identifiable {
+public interface WeightType extends NodeType {
/**
- * Gets the holder type
- *
- * @return the holder type
+ * The key for this type.
*/
- HolderType getType();
+ NodeTypeKey KEY = new NodeTypeKey(){};
/**
- * Applies an action to this reference, if it is present and exists.
+ * Gets the weight value.
*
- * @param plugin the plugin
- * @param consumer the action
+ * @return the weight
*/
- void apply(LuckPermsPlugin plugin, Consumer consumer);
+ int getWeight();
}
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculators/BukkitCalculatorFactory.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculators/BukkitCalculatorFactory.java
index 07755aee..55e3ef2a 100644
--- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculators/BukkitCalculatorFactory.java
+++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculators/BukkitCalculatorFactory.java
@@ -36,11 +36,11 @@ import me.lucko.luckperms.common.calculators.AbstractCalculatorFactory;
import me.lucko.luckperms.common.calculators.PermissionCalculator;
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
import me.lucko.luckperms.common.config.ConfigKeys;
+import me.lucko.luckperms.common.model.HolderType;
import me.lucko.luckperms.common.processors.MapProcessor;
import me.lucko.luckperms.common.processors.PermissionProcessor;
import me.lucko.luckperms.common.processors.RegexProcessor;
import me.lucko.luckperms.common.processors.WildcardProcessor;
-import me.lucko.luckperms.common.references.HolderType;
public class BukkitCalculatorFactory extends AbstractCalculatorFactory {
private final LPBukkitPlugin plugin;
diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationBPermissions.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationBPermissions.java
index 7669851a..a0e09b49 100644
--- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationBPermissions.java
+++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationBPermissions.java
@@ -42,7 +42,8 @@ import me.lucko.luckperms.common.logging.ProgressLogger;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.model.User;
-import me.lucko.luckperms.common.node.NodeFactory;
+import me.lucko.luckperms.common.node.factory.NodeFactory;
+import me.lucko.luckperms.common.node.model.NodeTypes;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.utils.Iterators;
@@ -212,7 +213,7 @@ public class MigrationBPermissions extends SubCommand
*
- * @see #getTransientData()
+ * @see #transientData()
*/
private final NodeMap transientNodes = new NodeMap(this);
- /**
- * Caches the holders weight
- * @see #getWeight()
- */
- private final Cache weightCache = WeightCache.getFor(this);
-
/**
* Lock used by Storage implementations to prevent concurrent read/writes
* @see #getIoLock()
@@ -183,10 +171,9 @@ public abstract class PermissionHolder {
return this.stateListeners;
}
- private void invalidateCache() {
+ protected void invalidateCache() {
this.enduringNodes.invalidate();
this.transientNodes.invalidate();
- this.weightCache.invalidate();
// Invalidate listeners
for (StateListener listener : this.stateListeners) {
@@ -196,17 +183,6 @@ public abstract class PermissionHolder {
e.printStackTrace();
}
}
-
- // Declare new state to the state manager
- declareState();
- }
-
- private void declareState() {
- /* only declare state of groups. the state manager isn't really being used now the caches in this class
- are gone, but it's useful for command output. */
- if (this.getType().isGroup()) {
- this.plugin.getCachedStateManager().putAll(toReference(), getGroupReferences());
- }
}
/**
@@ -223,14 +199,12 @@ public abstract class PermissionHolder {
*/
public abstract HolderCachedData> getCachedData();
- public abstract BufferedRequest getRefreshBuffer();
-
/**
- * Forms a HolderReference for this PermissionHolder.
+ * Gets the holders refresh buffer
*
- * @return this holders reference
+ * @return the holders refresh buffer
*/
- public abstract HolderReference, ?> toReference();
+ public abstract BufferedRequest getRefreshBuffer();
/**
* Returns the type of this PermissionHolder.
@@ -254,43 +228,21 @@ public abstract class PermissionHolder {
}
}
- public NodeMap getEnduringData() {
+ public NodeMap enduringData() {
return this.enduringNodes;
}
- public NodeMap getTransientData() {
+ public NodeMap transientData() {
return this.transientNodes;
}
- public ImmutableSetMultimap getNodes(NodeMapType type) {
- return getData(type).immutable();
- }
-
- public ImmutableSetMultimap getEnduringNodes() {
- return this.enduringNodes.immutable();
- }
-
- public ImmutableSetMultimap getTransientNodes() {
- return this.transientNodes.immutable();
- }
-
- /**
- * Sets this objects nodes to the values in the set
- *
- * @param set the set of nodes to apply to the object
- */
- public void setEnduringNodes(Set set) {
- this.enduringNodes.setContent(set);
+ public void setNodes(NodeMapType type, Set set) {
+ getData(type).setContent(set);
invalidateCache();
}
- /**
- * Replaces the multimap backing this object with another
- *
- * @param multimap the replacement multimap
- */
- public void replaceEnduringNodes(Multimap multimap) {
- this.enduringNodes.setContent(multimap);
+ public void replaceNodes(NodeMapType type, Multimap multimap) {
+ getData(type).setContent(multimap);
invalidateCache();
}
@@ -334,7 +286,7 @@ public abstract class PermissionHolder {
}
public boolean removeIf(Predicate predicate, Runnable taskIfSuccess) {
- ImmutableCollection before = getEnduringNodes().values();
+ ImmutableCollection before = enduringData().immutable().values();
if (!this.enduringNodes.removeIf(predicate)) {
return false;
}
@@ -342,7 +294,7 @@ public abstract class PermissionHolder {
taskIfSuccess.run();
}
invalidateCache();
- ImmutableCollection after = getEnduringNodes().values();
+ ImmutableCollection after = enduringData().immutable().values();
this.plugin.getEventFactory().handleNodeClear(this, before, after);
return true;
@@ -353,7 +305,7 @@ public abstract class PermissionHolder {
}
public boolean removeIf(ContextSet contextSet, Predicate predicate, Runnable taskIfSuccess) {
- ImmutableCollection before = getEnduringNodes().values();
+ ImmutableCollection before = enduringData().immutable().values();
if (!this.enduringNodes.removeIf(contextSet, predicate)) {
return false;
}
@@ -361,7 +313,7 @@ public abstract class PermissionHolder {
taskIfSuccess.run();
}
invalidateCache();
- ImmutableCollection after = getEnduringNodes().values();
+ ImmutableCollection after = enduringData().immutable().values();
this.plugin.getEventFactory().handleNodeClear(this, before, after);
return true;
@@ -375,7 +327,7 @@ public abstract class PermissionHolder {
return result;
}
- private void accumulateInheritancesTo(List accumulator, Contexts context) {
+ public void accumulateInheritancesTo(List accumulator, Contexts context) {
InheritanceGraph graph = this.plugin.getInheritanceHandler().getGraph(context);
Iterable traversal = graph.traverse(this.plugin.getConfiguration().get(ConfigKeys.INHERITANCE_TRAVERSAL_ALGORITHM), this);
for (PermissionHolder holder : traversal) {
@@ -393,27 +345,7 @@ public abstract class PermissionHolder {
return accumulator;
}
- public SortedSet resolveInheritancesAlmostEqual(Contexts contexts) {
- List nodes = new LinkedList<>();
- accumulateInheritancesTo(nodes, contexts);
-
- NodeTools.removeEqual(nodes.iterator(), StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE);
- SortedSet ret = new TreeSet<>(NodeWithContextComparator.reverse());
- ret.addAll(nodes);
- return ret;
- }
-
- public SortedSet resolveInheritancesMergeTemp(Contexts contexts) {
- List nodes = new LinkedList<>();
- accumulateInheritancesTo(nodes, contexts);
-
- NodeTools.removeEqual(nodes.iterator(), StandardNodeEquality.IGNORE_VALUE_OR_IF_TEMPORARY);
- SortedSet ret = new TreeSet<>(NodeWithContextComparator.reverse());
- ret.addAll(nodes);
- return ret;
- }
-
- private void accumulateInheritancesTo(List accumulator) {
+ public void accumulateInheritancesTo(List accumulator) {
InheritanceGraph graph = this.plugin.getInheritanceHandler().getGraph();
Iterable traversal = graph.traverse(this.plugin.getConfiguration().get(ConfigKeys.INHERITANCE_TRAVERSAL_ALGORITHM), this);
for (PermissionHolder holder : traversal) {
@@ -431,27 +363,7 @@ public abstract class PermissionHolder {
return accumulator;
}
- public SortedSet resolveInheritancesAlmostEqual() {
- List nodes = new LinkedList<>();
- accumulateInheritancesTo(nodes);
-
- NodeTools.removeEqual(nodes.iterator(), StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE);
- SortedSet ret = new TreeSet<>(NodeWithContextComparator.reverse());
- ret.addAll(nodes);
- return ret;
- }
-
- public SortedSet resolveInheritancesMergeTemp() {
- List nodes = new LinkedList<>();
- accumulateInheritancesTo(nodes);
-
- NodeTools.removeEqual(nodes.iterator(), StandardNodeEquality.IGNORE_VALUE_OR_IF_TEMPORARY);
- SortedSet ret = new TreeSet<>(NodeWithContextComparator.reverse());
- ret.addAll(nodes);
- return ret;
- }
-
- private List getAllEntries(Contexts context) {
+ public List getAllEntries(Contexts context) {
List entries = new LinkedList<>();
if (context.hasSetting(LookupSetting.RESOLVE_INHERITANCE)) {
accumulateInheritancesTo(entries, context);
@@ -472,15 +384,6 @@ public abstract class PermissionHolder {
return entries;
}
- public SortedSet getAllNodes(Contexts context) {
- List entries = getAllEntries(context);
-
- NodeTools.removeSamePermission(entries.iterator());
- SortedSet ret = new TreeSet<>(NodeWithContextComparator.reverse());
- ret.addAll(entries);
- return ret;
- }
-
public Map exportNodesAndShorthand(Contexts context, boolean lowerCase) {
List entries = getAllEntries(context);
@@ -489,12 +392,12 @@ public abstract class PermissionHolder {
for (Node node : entries) {
String perm = lowerCase ? node.getPermission().toLowerCase() : node.getPermission();
- if (perms.putIfAbsent(perm, node.getValuePrimitive()) == null) {
+ if (perms.putIfAbsent(perm, node.getValue()) == null) {
if (applyShorthand) {
List shorthand = node.resolveShorthand();
if (!shorthand.isEmpty()) {
for (String s : shorthand) {
- perms.putIfAbsent(lowerCase ? s.toLowerCase() : s, node.getValuePrimitive());
+ perms.putIfAbsent(lowerCase ? s.toLowerCase() : s, node.getValue());
}
}
}
@@ -512,11 +415,11 @@ public abstract class PermissionHolder {
for (Node node : entries) {
String perm = lowerCase ? node.getPermission().toLowerCase().intern() : node.getPermission();
- if (perms.putIfAbsent(perm, node.getValuePrimitive()) == null && applyShorthand) {
+ if (perms.putIfAbsent(perm, node.getValue()) == null && applyShorthand) {
List shorthand = node.resolveShorthand();
if (!shorthand.isEmpty()) {
for (String s : shorthand) {
- perms.putIfAbsent((lowerCase ? s.toLowerCase() : s).intern(), node.getValuePrimitive());
+ perms.putIfAbsent((lowerCase ? s.toLowerCase() : s).intern(), node.getValue());
}
}
}
@@ -535,7 +438,7 @@ public abstract class PermissionHolder {
for (PermissionHolder holder : traversal) {
List nodes = holder.getOwnNodes(context.getContexts());
for (Node node : nodes) {
- if (!node.getValuePrimitive()) continue;
+ if (!node.getValue()) continue;
if (!node.isMeta() && !node.isPrefix() && !node.isSuffix()) continue;
if (!((context.hasSetting(LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER) || node.isServerSpecific()) && (context.hasSetting(LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD) || node.isWorldSpecific()))) {
@@ -564,7 +467,7 @@ public abstract class PermissionHolder {
for (PermissionHolder holder : traversal) {
List nodes = holder.getOwnNodes();
for (Node node : nodes) {
- if (!node.getValuePrimitive()) continue;
+ if (!node.getValue()) continue;
if (!node.isMeta() && !node.isPrefix() && !node.isSuffix()) continue;
accumulator.accumulateNode(ImmutableLocalizedNode.of(node, holder.getObjectName()));
@@ -589,7 +492,7 @@ public abstract class PermissionHolder {
// we don't call events for transient nodes
boolean transientWork = this.transientNodes.auditTemporaryNodes(null);
- ImmutableCollection before = getEnduringNodes().values();
+ ImmutableCollection before = enduringData().immutable().values();
Set removed = new HashSet<>();
boolean enduringWork = this.enduringNodes.auditTemporaryNodes(removed);
@@ -598,7 +501,7 @@ public abstract class PermissionHolder {
invalidateCache();
// call event
- ImmutableCollection after = getEnduringNodes().values();
+ ImmutableCollection after = enduringData().immutable().values();
for (Node r : removed) {
this.plugin.getEventFactory().handleNodeRemove(r, this, before, after);
}
@@ -636,18 +539,6 @@ public abstract class PermissionHolder {
return searchForMatch(type, node, equalityPredicate).map(Node::getTristate).orElse(Tristate.UNDEFINED);
}
- public Tristate hasPermission(NodeMapType type, Node node) {
- return hasPermission(type, node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE);
- }
-
- public Tristate hasPermission(Node node, NodeEqualityPredicate equalityPredicate) {
- return hasPermission(NodeMapType.ENDURING, node, equalityPredicate);
- }
-
- public Tristate hasPermission(Node node) {
- return hasPermission(NodeMapType.ENDURING, node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE);
- }
-
/**
* Check if the holder inherits a node
*
@@ -676,24 +567,20 @@ public abstract class PermissionHolder {
return searchForInheritedMatch(node, equalityPredicate).getResult();
}
- public Tristate inheritsPermission(Node node) {
- return inheritsPermission(node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE);
- }
-
/**
* Sets a permission node
*
* @param node the node to set
*/
public DataMutateResult setPermission(Node node) {
- if (hasPermission(NodeMapType.ENDURING, node) != Tristate.UNDEFINED) {
+ if (hasPermission(NodeMapType.ENDURING, node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE) != Tristate.UNDEFINED) {
return DataMutateResult.ALREADY_HAS;
}
- ImmutableCollection before = getEnduringNodes().values();
+ ImmutableCollection before = enduringData().immutable().values();
this.enduringNodes.add(node);
invalidateCache();
- ImmutableCollection after = getEnduringNodes().values();
+ ImmutableCollection after = enduringData().immutable().values();
this.plugin.getEventFactory().handleNodeAdd(node, this, before, after);
return DataMutateResult.SUCCESS;
@@ -720,10 +607,10 @@ public abstract class PermissionHolder {
Node newNode = node.toBuilder().setExpiry(previous.getExpiryUnixTime() + node.getSecondsTilExpiry()).build();
// Remove the old node & add the new one.
- ImmutableCollection before = getEnduringNodes().values();
+ ImmutableCollection before = enduringData().immutable().values();
this.enduringNodes.replace(newNode, previous);
invalidateCache();
- ImmutableCollection after = getEnduringNodes().values();
+ ImmutableCollection after = enduringData().immutable().values();
this.plugin.getEventFactory().handleNodeAdd(newNode, this, before, after);
return Maps.immutableEntry(DataMutateResult.SUCCESS, newNode);
@@ -740,10 +627,10 @@ public abstract class PermissionHolder {
// Only replace if the new expiry time is greater than the old one.
if (node.getExpiryUnixTime() > previous.getExpiryUnixTime()) {
- ImmutableCollection before = getEnduringNodes().values();
+ ImmutableCollection before = enduringData().immutable().values();
this.enduringNodes.replace(node, previous);
invalidateCache();
- ImmutableCollection after = getEnduringNodes().values();
+ ImmutableCollection after = enduringData().immutable().values();
this.plugin.getEventFactory().handleNodeAdd(node, this, before, after);
return Maps.immutableEntry(DataMutateResult.SUCCESS, node);
@@ -764,7 +651,7 @@ public abstract class PermissionHolder {
* @param node the node to set
*/
public DataMutateResult setTransientPermission(Node node) {
- if (hasPermission(NodeMapType.TRANSIENT, node) != Tristate.UNDEFINED) {
+ if (hasPermission(NodeMapType.TRANSIENT, node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE) != Tristate.UNDEFINED) {
return DataMutateResult.ALREADY_HAS;
}
@@ -779,14 +666,14 @@ public abstract class PermissionHolder {
* @param node the node to unset
*/
public DataMutateResult unsetPermission(Node node) {
- if (hasPermission(NodeMapType.ENDURING, node) == Tristate.UNDEFINED) {
+ if (hasPermission(NodeMapType.ENDURING, node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE) == Tristate.UNDEFINED) {
return DataMutateResult.LACKS;
}
- ImmutableCollection before = getEnduringNodes().values();
+ ImmutableCollection before = enduringData().immutable().values();
this.enduringNodes.remove(node);
invalidateCache();
- ImmutableCollection after = getEnduringNodes().values();
+ ImmutableCollection after = enduringData().immutable().values();
this.plugin.getEventFactory().handleNodeRemove(node, this, before, after);
return DataMutateResult.SUCCESS;
@@ -798,7 +685,7 @@ public abstract class PermissionHolder {
* @param node the node to unset
*/
public DataMutateResult unsetTransientPermission(Node node) {
- if (hasPermission(NodeMapType.TRANSIENT, node) == Tristate.UNDEFINED) {
+ if (hasPermission(NodeMapType.TRANSIENT, node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE) == Tristate.UNDEFINED) {
return DataMutateResult.LACKS;
}
@@ -808,21 +695,21 @@ public abstract class PermissionHolder {
}
public boolean inheritsGroup(Group group) {
- return group.getName().equalsIgnoreCase(this.getObjectName()) || hasPermission(NodeFactory.buildGroupNode(group.getName()).build()).asBoolean();
+ return group.getName().equalsIgnoreCase(this.getObjectName()) || hasPermission(NodeMapType.ENDURING, NodeFactory.buildGroupNode(group.getName()).build(), StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE).asBoolean();
}
public boolean inheritsGroup(Group group, ContextSet contextSet) {
- return group.getName().equalsIgnoreCase(this.getObjectName()) || hasPermission(NodeFactory.buildGroupNode(group.getName()).withExtraContext(contextSet).build()).asBoolean();
+ return group.getName().equalsIgnoreCase(this.getObjectName()) || hasPermission(NodeMapType.ENDURING, NodeFactory.buildGroupNode(group.getName()).withExtraContext(contextSet).build(), StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE).asBoolean();
}
/**
* Clear all of the holders permission nodes
*/
public boolean clearNodes() {
- ImmutableCollection before = getEnduringNodes().values();
+ ImmutableCollection before = enduringData().immutable().values();
this.enduringNodes.clear();
invalidateCache();
- ImmutableCollection after = getEnduringNodes().values();
+ ImmutableCollection after = enduringData().immutable().values();
if (before.size() == after.size()) {
return false;
@@ -833,10 +720,10 @@ public abstract class PermissionHolder {
}
public boolean clearNodes(ContextSet contextSet) {
- ImmutableCollection before = getEnduringNodes().values();
+ ImmutableCollection before = enduringData().immutable().values();
this.enduringNodes.clear(contextSet);
invalidateCache();
- ImmutableCollection after = getEnduringNodes().values();
+ ImmutableCollection after = enduringData().immutable().values();
if (before.size() == after.size()) {
return false;
@@ -847,11 +734,11 @@ public abstract class PermissionHolder {
}
public boolean clearPermissions() {
- return removeIf(Node::isRegularPermissionNode);
+ return removeIf(node -> !node.hasTypeData());
}
public boolean clearPermissions(ContextSet contextSet) {
- return removeIf(contextSet, Node::isRegularPermissionNode);
+ return removeIf(contextSet, node -> !node.hasTypeData());
}
public boolean clearParents(boolean giveDefault) {
@@ -893,14 +780,6 @@ public abstract class PermissionHolder {
}
public OptionalInt getWeight() {
- return this.weightCache.get();
- }
-
- public Set getGroupReferences() {
- return getOwnGroupNodes().stream()
- .map(Node::getGroupName)
- .map(String::toLowerCase)
- .map(GroupReference::of)
- .collect(Collectors.toSet());
+ return OptionalInt.empty();
}
}
diff --git a/common/src/main/java/me/lucko/luckperms/common/model/Track.java b/common/src/main/java/me/lucko/luckperms/common/model/Track.java
index 3c93ab71..aeb0e1e3 100644
--- a/common/src/main/java/me/lucko/luckperms/common/model/Track.java
+++ b/common/src/main/java/me/lucko/luckperms/common/model/Track.java
@@ -35,9 +35,8 @@ import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.common.api.DemotionResults;
import me.lucko.luckperms.common.api.PromotionResults;
import me.lucko.luckperms.common.api.delegates.model.ApiTrack;
-import me.lucko.luckperms.common.node.NodeFactory;
+import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
-import me.lucko.luckperms.common.references.Identifiable;
import me.lucko.luckperms.common.sender.Sender;
import java.util.ArrayList;
@@ -277,9 +276,9 @@ public final class Track implements Identifiable {
}
// find all groups that are inherited by the user in the exact contexts given and applicable to this track
- List nodes = user.getEnduringNodes().get(context.makeImmutable()).stream()
+ List nodes = user.enduringData().immutable().get(context.makeImmutable()).stream()
.filter(Node::isGroupNode)
- .filter(Node::getValuePrimitive)
+ .filter(Node::getValue)
.filter(node -> containsGroup(node.getGroupName()))
.distinct()
.collect(Collectors.toList());
@@ -339,9 +338,9 @@ public final class Track implements Identifiable {
}
// find all groups that are inherited by the user in the exact contexts given and applicable to this track
- List nodes = user.getEnduringNodes().get(context.makeImmutable()).stream()
+ List nodes = user.enduringData().immutable().get(context.makeImmutable()).stream()
.filter(Node::isGroupNode)
- .filter(Node::getValuePrimitive)
+ .filter(node -> node.getValue())
.filter(node -> containsGroup(node.getGroupName()))
.distinct()
.collect(Collectors.toList());
diff --git a/common/src/main/java/me/lucko/luckperms/common/model/User.java b/common/src/main/java/me/lucko/luckperms/common/model/User.java
index 114949dd..d99bc1a8 100644
--- a/common/src/main/java/me/lucko/luckperms/common/model/User.java
+++ b/common/src/main/java/me/lucko/luckperms/common/model/User.java
@@ -31,10 +31,6 @@ import me.lucko.luckperms.common.caching.UserCachedData;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.primarygroup.PrimaryGroupHolder;
-import me.lucko.luckperms.common.references.HolderType;
-import me.lucko.luckperms.common.references.Identifiable;
-import me.lucko.luckperms.common.references.UserIdentifier;
-import me.lucko.luckperms.common.references.UserReference;
import java.util.Optional;
import java.util.UUID;
@@ -161,11 +157,6 @@ public class User extends PermissionHolder implements Identifiable {
- private static final Cache NULL = new Cache() {
- @Override
- protected OptionalInt supply() {
- return OptionalInt.empty();
- }
- };
-
- public static Cache getFor(PermissionHolder holder) {
- if (holder.getType().isUser()) {
- return NULL;
- }
-
- return new WeightCache(((Group) holder));
- }
-
private final Group group;
- private WeightCache(Group group) {
+ public WeightCache(Group group) {
this.group = group;
}
@@ -64,14 +50,16 @@ public class WeightCache extends Cache {
boolean seen = false;
int best = 0;
for (Node n : this.group.getOwnNodes(ImmutableContextSet.empty())) {
- Integer weight = NodeFactory.parseWeightNode(n.getPermission());
- if (weight == null) {
+ Optional weight = n.getTypeData(WeightType.KEY);
+ if (!weight.isPresent()) {
continue;
}
- if (!seen || weight > best) {
+ int value = weight.get().getWeight();
+
+ if (!seen || value > best) {
seen = true;
- best = weight;
+ best = value;
}
}
OptionalInt weight = seen ? OptionalInt.of(best) : OptionalInt.empty();
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/HeldPermissionComparator.java b/common/src/main/java/me/lucko/luckperms/common/node/comparator/HeldPermissionComparator.java
similarity index 97%
rename from common/src/main/java/me/lucko/luckperms/common/node/HeldPermissionComparator.java
rename to common/src/main/java/me/lucko/luckperms/common/node/comparator/HeldPermissionComparator.java
index e1496061..409fa249 100644
--- a/common/src/main/java/me/lucko/luckperms/common/node/HeldPermissionComparator.java
+++ b/common/src/main/java/me/lucko/luckperms/common/node/comparator/HeldPermissionComparator.java
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.node;
+package me.lucko.luckperms.common.node.comparator;
import me.lucko.luckperms.api.HeldPermission;
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/NodeComparator.java b/common/src/main/java/me/lucko/luckperms/common/node/comparator/NodeComparator.java
similarity index 97%
rename from common/src/main/java/me/lucko/luckperms/common/node/NodeComparator.java
rename to common/src/main/java/me/lucko/luckperms/common/node/comparator/NodeComparator.java
index 6e30faa5..0cc08d0c 100644
--- a/common/src/main/java/me/lucko/luckperms/common/node/NodeComparator.java
+++ b/common/src/main/java/me/lucko/luckperms/common/node/comparator/NodeComparator.java
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.node;
+package me.lucko.luckperms.common.node.comparator;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.utils.CollationKeyCache;
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/NodeWithContextComparator.java b/common/src/main/java/me/lucko/luckperms/common/node/comparator/NodeWithContextComparator.java
similarity index 98%
rename from common/src/main/java/me/lucko/luckperms/common/node/NodeWithContextComparator.java
rename to common/src/main/java/me/lucko/luckperms/common/node/comparator/NodeWithContextComparator.java
index c0c45c55..f9120cca 100644
--- a/common/src/main/java/me/lucko/luckperms/common/node/NodeWithContextComparator.java
+++ b/common/src/main/java/me/lucko/luckperms/common/node/comparator/NodeWithContextComparator.java
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.node;
+package me.lucko.luckperms.common.node.comparator;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.utils.CollationKeyCache;
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/LegacyNodeFactory.java b/common/src/main/java/me/lucko/luckperms/common/node/factory/LegacyNodeFactory.java
similarity index 94%
rename from common/src/main/java/me/lucko/luckperms/common/node/LegacyNodeFactory.java
rename to common/src/main/java/me/lucko/luckperms/common/node/factory/LegacyNodeFactory.java
index 4bf22b3c..fee267ae 100644
--- a/common/src/main/java/me/lucko/luckperms/common/node/LegacyNodeFactory.java
+++ b/common/src/main/java/me/lucko/luckperms/common/node/factory/LegacyNodeFactory.java
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.node;
+package me.lucko.luckperms.common.node.factory;
import com.google.common.base.Splitter;
@@ -40,17 +40,17 @@ public final class LegacyNodeFactory {
/**
* The characters which are delimited when serializing a permission string
*/
- static final String[] PERMISSION_DELIMITERS = new String[]{"/", "-", "$", "(", ")", "=", ","};
+ public static final String[] PERMISSION_DELIMITERS = new String[]{"/", "-", "$", "(", ")", "=", ","};
/**
* The characters which are delimited when serializing a server or world string
*/
- static final String[] SERVER_WORLD_DELIMITERS = new String[]{"/", "-"};
+ public static final String[] SERVER_WORLD_DELIMITERS = new String[]{"/", "-"};
/**
* The characters which are delimited when serializing a context set
*/
- static final String[] CONTEXT_DELIMITERS = new String[]{"=", "(", ")", ","};
+ private static final String[] CONTEXT_DELIMITERS = new String[]{"=", "(", ")", ","};
/**
* The characters which are delimited when serializing meta/prefix/suffix strings
@@ -146,7 +146,7 @@ public final class LegacyNodeFactory {
return escapeDelimiters(s, GENERIC_DELIMITERS);
}
- static String unescapeCharacters(String s) {
+ public static String unescapeCharacters(String s) {
if (s == null) {
throw new NullPointerException();
}
@@ -172,7 +172,7 @@ public final class LegacyNodeFactory {
return s;
}
- static String unescapeDelimiters(String s, String... delimiters) {
+ public static String unescapeDelimiters(String s, String... delimiters) {
if (s == null) {
return null;
}
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/NodeBuilder.java b/common/src/main/java/me/lucko/luckperms/common/node/factory/NodeBuilder.java
similarity index 95%
rename from common/src/main/java/me/lucko/luckperms/common/node/NodeBuilder.java
rename to common/src/main/java/me/lucko/luckperms/common/node/factory/NodeBuilder.java
index 16027117..095fc20b 100644
--- a/common/src/main/java/me/lucko/luckperms/common/node/NodeBuilder.java
+++ b/common/src/main/java/me/lucko/luckperms/common/node/factory/NodeBuilder.java
@@ -23,12 +23,13 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.node;
+package me.lucko.luckperms.common.node.factory;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.ImmutableContextSet;
+import me.lucko.luckperms.common.node.model.ImmutableNode;
import java.util.Map;
import java.util.Objects;
@@ -39,7 +40,7 @@ import javax.annotation.Nonnull;
/**
* Builds node instances
*/
-class NodeBuilder implements Node.Builder {
+public class NodeBuilder implements Node.Builder {
protected String permission;
private ImmutableContextSet.Builder extraContexts = ImmutableContextSet.builder();
private Boolean value = true;
@@ -48,7 +49,7 @@ class NodeBuilder implements Node.Builder {
private String world = null;
private long expireAt = 0L;
- protected NodeBuilder() {
+ NodeBuilder() {
}
@@ -56,7 +57,7 @@ class NodeBuilder implements Node.Builder {
this.permission = permission;
}
- NodeBuilder(Node other) {
+ public NodeBuilder(Node other) {
this.permission = other.getPermission();
copyFrom(other);
}
@@ -64,7 +65,7 @@ class NodeBuilder implements Node.Builder {
@Override
public Node.Builder copyFrom(@Nonnull Node node) {
Objects.requireNonNull(node, "node");
- this.value = node.getValuePrimitive();
+ this.value = node.getValue();
this.override = node.isOverride();
this.server = node.getServer().orElse(null);
this.world = node.getWorld().orElse(null);
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/NodeFactory.java b/common/src/main/java/me/lucko/luckperms/common/node/factory/NodeFactory.java
similarity index 74%
rename from common/src/main/java/me/lucko/luckperms/common/node/NodeFactory.java
rename to common/src/main/java/me/lucko/luckperms/common/node/factory/NodeFactory.java
index ba148643..005dea32 100644
--- a/common/src/main/java/me/lucko/luckperms/common/node/NodeFactory.java
+++ b/common/src/main/java/me/lucko/luckperms/common/node/factory/NodeFactory.java
@@ -23,19 +23,15 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.node;
-
-import com.google.common.base.Splitter;
-import com.google.common.collect.Maps;
+package me.lucko.luckperms.common.node.factory;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.common.model.Group;
-import me.lucko.luckperms.common.references.HolderType;
-import me.lucko.luckperms.common.utils.PatternCache;
+import me.lucko.luckperms.common.model.HolderType;
+import me.lucko.luckperms.common.node.model.NodeTypes;
-import java.util.Iterator;
import java.util.Map;
/**
@@ -44,20 +40,6 @@ import java.util.Map;
public final class NodeFactory {
public static final String DEFAULT_GROUP_NAME = "default";
- public static final String PREFIX_KEY = "prefix";
- public static final String SUFFIX_KEY = "suffix";
- public static final String META_KEY = "meta";
- public static final String WEIGHT_KEY = "weight";
-
- private static final String GROUP_NODE_MARKER = "group.";
- private static final String PREFIX_NODE_MARKER = PREFIX_KEY + ".";
- private static final String SUFFIX_NODE_MARKER = SUFFIX_KEY + ".";
- private static final String META_NODE_MARKER = META_KEY + ".";
- private static final String WEIGHT_NODE_MARKER = WEIGHT_KEY + ".";
-
- // used to split prefix/suffix/meta nodes
- private static final Splitter META_SPLITTER = Splitter.on(PatternCache.compileDelimiterPattern(".", "\\")).limit(2);
-
public static Node.Builder builder(String s) {
return new NodeBuilder(s);
}
@@ -91,7 +73,7 @@ public final class NodeFactory {
}
public static String groupNode(String groupName) {
- return GROUP_NODE_MARKER + groupName;
+ return NodeTypes.GROUP_NODE_MARKER + groupName;
}
public static String chatMetaNode(ChatMetaType type, int priority, String value) {
@@ -99,19 +81,19 @@ public final class NodeFactory {
}
public static String prefixNode(int priority, String prefix) {
- return PREFIX_NODE_MARKER + priority + "." + LegacyNodeFactory.escapeCharacters(prefix);
+ return NodeTypes.PREFIX_NODE_MARKER + priority + "." + LegacyNodeFactory.escapeCharacters(prefix);
}
public static String suffixNode(int priority, String suffix) {
- return SUFFIX_NODE_MARKER + priority + "." + LegacyNodeFactory.escapeCharacters(suffix);
+ return NodeTypes.SUFFIX_NODE_MARKER + priority + "." + LegacyNodeFactory.escapeCharacters(suffix);
}
public static String metaNode(String key, String value) {
- return META_NODE_MARKER + LegacyNodeFactory.escapeCharacters(key) + "." + LegacyNodeFactory.escapeCharacters(value);
+ return NodeTypes.META_NODE_MARKER + LegacyNodeFactory.escapeCharacters(key) + "." + LegacyNodeFactory.escapeCharacters(value);
}
public static String weightNode(int weight) {
- return WEIGHT_NODE_MARKER + weight;
+ return NodeTypes.WEIGHT_NODE_MARKER + weight;
}
public static Node make(String node) {
@@ -232,7 +214,7 @@ public final class NodeFactory {
return appendContextToCommand(sb, node).toString();
}
- if (node.getValuePrimitive() && (node.isPrefix() || node.isSuffix())) {
+ if (node.getValue() && (node.isPrefix() || node.isSuffix())) {
ChatMetaType chatMetaType = node.isPrefix() ? ChatMetaType.PREFIX : ChatMetaType.SUFFIX;
sb.append("meta ");
@@ -267,7 +249,7 @@ public final class NodeFactory {
return appendContextToCommand(sb, node).toString();
}
- if (node.getValuePrimitive() && node.isMeta()) {
+ if (node.getValue() && node.isMeta()) {
sb.append("meta ");
if (set) {
@@ -329,7 +311,7 @@ public final class NodeFactory {
sb.append(perm);
}
if (set) {
- sb.append(" ").append(node.getValuePrimitive());
+ sb.append(" ").append(node.getValue());
if (node.isTemporary()) {
sb.append(" ").append(node.getExpiryUnixTime());
@@ -355,73 +337,6 @@ public final class NodeFactory {
return sb;
}
- public static String parseGroupNode(String s) {
- String lower = s.toLowerCase();
- if (!lower.startsWith(GROUP_NODE_MARKER)) {
- return null;
- }
- return lower.substring(GROUP_NODE_MARKER.length()).intern();
- }
-
- public static Map.Entry parseMetaNode(String s) {
- if (!s.toLowerCase().startsWith(META_NODE_MARKER)) {
- return null;
- }
-
- Iterator metaParts = META_SPLITTER.split(s.substring(META_NODE_MARKER.length())).iterator();
-
- if (!metaParts.hasNext()) return null;
- String key = metaParts.next();
-
- if (!metaParts.hasNext()) return null;
- String value = metaParts.next();
-
- return Maps.immutableEntry(LegacyNodeFactory.unescapeCharacters(key).intern(), LegacyNodeFactory.unescapeCharacters(value).intern());
- }
-
- private static Map.Entry parseChatMetaNode(String marker, String s) {
- if (!s.toLowerCase().startsWith(marker)) {
- return null;
- }
-
- Iterator metaParts = META_SPLITTER.split(s.substring(marker.length())).iterator();
-
- if (!metaParts.hasNext()) return null;
- String priority = metaParts.next();
-
- if (!metaParts.hasNext()) return null;
- String value = metaParts.next();
-
- try {
- int p = Integer.parseInt(priority);
- String v = LegacyNodeFactory.unescapeCharacters(value).intern();
- return Maps.immutableEntry(p, v);
- } catch (NumberFormatException e) {
- return null;
- }
- }
-
- public static Map.Entry parsePrefixNode(String s) {
- return parseChatMetaNode(PREFIX_NODE_MARKER, s);
- }
-
- public static Map.Entry parseSuffixNode(String s) {
- return parseChatMetaNode(SUFFIX_NODE_MARKER, s);
- }
-
- public static Integer parseWeightNode(String s) {
- String lower = s.toLowerCase();
- if (!lower.startsWith(WEIGHT_NODE_MARKER)) {
- return null;
- }
- String i = lower.substring(WEIGHT_NODE_MARKER.length());
- try {
- return Integer.parseInt(i);
- } catch (NumberFormatException e) {
- return null;
- }
- }
-
private NodeFactory() {}
}
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/ForwardingNode.java b/common/src/main/java/me/lucko/luckperms/common/node/model/ForwardingNode.java
similarity index 91%
rename from common/src/main/java/me/lucko/luckperms/common/node/ForwardingNode.java
rename to common/src/main/java/me/lucko/luckperms/common/node/model/ForwardingNode.java
index a0dcc59d..a861dce6 100644
--- a/common/src/main/java/me/lucko/luckperms/common/node/ForwardingNode.java
+++ b/common/src/main/java/me/lucko/luckperms/common/node/model/ForwardingNode.java
@@ -23,13 +23,15 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.node;
+package me.lucko.luckperms.common.node.model;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.NodeEqualityPredicate;
import me.lucko.luckperms.api.StandardNodeEquality;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.context.ContextSet;
+import me.lucko.luckperms.api.nodetype.NodeType;
+import me.lucko.luckperms.api.nodetype.NodeTypeKey;
import java.util.Date;
import java.util.List;
@@ -58,17 +60,11 @@ public abstract class ForwardingNode implements Node {
return delegate().getPermission();
}
- @Nonnull
@Override
- public Boolean getValue() {
+ public boolean getValue() {
return delegate().getValue();
}
- @Override
- public boolean getValuePrimitive() {
- return delegate().getValuePrimitive();
- }
-
@Nonnull
@Override
public Tristate getTristate() {
@@ -171,11 +167,6 @@ public abstract class ForwardingNode implements Node {
return delegate().getFullContexts();
}
- @Override
- public boolean isRegularPermissionNode() {
- return delegate().isRegularPermissionNode();
- }
-
@Override
public boolean isGroupNode() {
return delegate().isGroupNode();
@@ -197,6 +188,21 @@ public abstract class ForwardingNode implements Node {
return delegate().getWildcardLevel();
}
+ @Override
+ public boolean hasTypeData() {
+ return delegate().hasTypeData();
+ }
+
+ @Override
+ public Optional getTypeData(NodeTypeKey key) {
+ return delegate().getTypeData(key);
+ }
+
+ @Override
+ public T typeData(NodeTypeKey key) throws IllegalStateException {
+ return delegate().typeData(key);
+ }
+
@Override
public boolean isMeta() {
return delegate().isMeta();
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/ImmutableLocalizedNode.java b/common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableLocalizedNode.java
similarity index 98%
rename from common/src/main/java/me/lucko/luckperms/common/node/ImmutableLocalizedNode.java
rename to common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableLocalizedNode.java
index 0e474b8c..1de4bc80 100644
--- a/common/src/main/java/me/lucko/luckperms/common/node/ImmutableLocalizedNode.java
+++ b/common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableLocalizedNode.java
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.node;
+package me.lucko.luckperms.common.node.model;
import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.api.Node;
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/ImmutableNode.java b/common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableNode.java
similarity index 83%
rename from common/src/main/java/me/lucko/luckperms/common/node/ImmutableNode.java
rename to common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableNode.java
index cc8a1660..e49c2e2f 100644
--- a/common/src/main/java/me/lucko/luckperms/common/node/ImmutableNode.java
+++ b/common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableNode.java
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.node;
+package me.lucko.luckperms.common.node.model;
import com.google.common.collect.ImmutableList;
@@ -33,75 +33,67 @@ import me.lucko.luckperms.api.StandardNodeEquality;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.api.context.MutableContextSet;
+import me.lucko.luckperms.api.nodetype.NodeType;
+import me.lucko.luckperms.api.nodetype.NodeTypeKey;
+import me.lucko.luckperms.common.node.factory.LegacyNodeFactory;
+import me.lucko.luckperms.common.node.factory.NodeBuilder;
+import me.lucko.luckperms.common.node.utils.ShorthandParser;
import me.lucko.luckperms.common.processors.WildcardProcessor;
import java.util.Date;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkState;
/**
* An immutable implementation of {@link Node}.
*/
+@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public final class ImmutableNode implements Node {
/**
* The character which separates each part of a permission node
*/
public static final char NODE_SEPARATOR = '.';
- public static final int NODE_SEPARATOR_CODE = Character.getNumericValue('.');
+
+ /**
+ * The numeric value of {@link #NODE_SEPARATOR}
+ */
+ public static final int NODE_SEPARATOR_CODE = Character.getNumericValue(NODE_SEPARATOR);
+
+ // node attributes
private final String permission;
-
private final boolean value;
-
private boolean override;
- // nullable
+ @Nullable
private final String server;
- // nullable
+ @Nullable
private final String world;
- // 0L for no expiry
- private final long expireAt;
-
+ private final long expireAt; // 0L for no expiry
private final ImmutableContextSet contexts;
-
private final ImmutableContextSet fullContexts;
- /*
- * CACHED STATE
- *
- * These values are based upon the node state above, and are stored here
- * to make node comparison and manipulation faster.
- *
- * This increases the memory footprint of this class by a bit, but it is
- * worth it for the gain in speed.
- *
- * The methods on this class are called v. frequently.
- */
- // storing optionals as a field type is usually a bad idea, however, the
- // #getServer and #getWorld methods are called frequently when comparing nodes.
- // without caching these values, it creates quite a bit of object churn
- @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
+
+ // cached state
+
private final Optional optServer;
- @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
private final Optional optWorld;
+ // this class is immutable, so we can cache the hashcode calculation
private final int hashCode;
- // all nullable
- private String groupName;
private final int wildcardLevel;
- private Map.Entry meta;
- private Map.Entry prefix;
- private Map.Entry suffix;
-
+ private final Map, NodeType> resolvedTypes;
private final List resolvedShorthand;
/**
@@ -114,8 +106,7 @@ public final class ImmutableNode implements Node {
* @param world the world this node applies on
* @param contexts any additional contexts applying to this node
*/
- @SuppressWarnings("deprecation")
- ImmutableNode(String permission, boolean value, boolean override, long expireAt, String server, String world, ContextSet contexts) {
+ public ImmutableNode(String permission, boolean value, boolean override, long expireAt, String server, String world, ContextSet contexts) {
if (permission == null || permission.isEmpty()) {
throw new IllegalArgumentException("Empty permission");
}
@@ -134,11 +125,8 @@ public final class ImmutableNode implements Node {
this.contexts = contexts == null ? ContextSet.empty() : contexts.makeImmutable();
// define cached state
- this.groupName = NodeFactory.parseGroupNode(this.permission);
this.wildcardLevel = this.permission.endsWith(WildcardProcessor.WILDCARD_SUFFIX) ? this.permission.chars().filter(num -> num == NODE_SEPARATOR_CODE).sum() : -1;
- this.meta = NodeFactory.parseMetaNode(this.permission);
- this.prefix = NodeFactory.parsePrefixNode(this.permission);
- this.suffix = NodeFactory.parseSuffixNode(this.permission);
+ this.resolvedTypes = NodeTypes.parseTypes(this.permission);
this.resolvedShorthand = ImmutableList.copyOf(ShorthandParser.parseShorthand(getPermission()));
this.optServer = Optional.ofNullable(this.server);
this.optWorld = Optional.ofNullable(this.world);
@@ -173,7 +161,7 @@ public final class ImmutableNode implements Node {
}
@Override
- public boolean getValuePrimitive() {
+ public boolean getValue() {
return this.value;
}
@@ -226,6 +214,11 @@ public final class ImmutableNode implements Node {
return this.server != null || this.world != null || !this.contexts.isEmpty();
}
+ @Override
+ public boolean shouldApplyWithContext(@Nonnull ContextSet contextSet) {
+ return getFullContexts().isSatisfiedBy(contextSet);
+ }
+
@Override
public boolean isTemporary() {
return this.expireAt != 0L;
@@ -255,23 +248,6 @@ public final class ImmutableNode implements Node {
return isTemporary() && this.expireAt < System.currentTimeMillis() / 1000L;
}
- @Override
- public boolean isRegularPermissionNode() {
- return !isGroupNode() && !isPrefix() && !isSuffix() && !isMeta();
- }
-
- @Override
- public boolean isGroupNode() {
- return this.groupName != null;
- }
-
- @Nonnull
- @Override
- public String getGroupName() {
- checkState(isGroupNode(), "Node is not a group node");
- return this.groupName;
- }
-
@Override
public boolean isWildcard() {
return this.wildcardLevel != -1;
@@ -284,44 +260,17 @@ public final class ImmutableNode implements Node {
}
@Override
- public boolean isMeta() {
- return this.meta != null;
- }
-
- @Nonnull
- @Override
- public Map.Entry getMeta() {
- checkState(isMeta(), "Node is not a meta node");
- return this.meta;
+ public boolean hasTypeData() {
+ return !this.resolvedTypes.isEmpty();
}
@Override
- public boolean isPrefix() {
- return this.prefix != null;
- }
+ public Optional getTypeData(NodeTypeKey key) {
+ Objects.requireNonNull(key, "key");
- @Nonnull
- @Override
- public Map.Entry getPrefix() {
- checkState(isPrefix(), "Node is not a prefix node");
- return this.prefix;
- }
-
- @Override
- public boolean isSuffix() {
- return this.suffix != null;
- }
-
- @Nonnull
- @Override
- public Map.Entry getSuffix() {
- checkState(isSuffix(), "Node is not a suffix node");
- return this.suffix;
- }
-
- @Override
- public boolean shouldApplyWithContext(@Nonnull ContextSet contextSet) {
- return getFullContexts().isSatisfiedBy(contextSet);
+ //noinspection unchecked
+ T result = (T) this.resolvedTypes.get(key);
+ return Optional.ofNullable(result);
}
@Nonnull
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/ImmutableTransientNode.java b/common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableTransientNode.java
similarity index 98%
rename from common/src/main/java/me/lucko/luckperms/common/node/ImmutableTransientNode.java
rename to common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableTransientNode.java
index 7ecf493b..fc330cd1 100644
--- a/common/src/main/java/me/lucko/luckperms/common/node/ImmutableTransientNode.java
+++ b/common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableTransientNode.java
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.node;
+package me.lucko.luckperms.common.node.model;
import me.lucko.luckperms.api.Node;
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/NodeModel.java b/common/src/main/java/me/lucko/luckperms/common/node/model/NodeDataContainer.java
similarity index 81%
rename from common/src/main/java/me/lucko/luckperms/common/node/NodeModel.java
rename to common/src/main/java/me/lucko/luckperms/common/node/model/NodeDataContainer.java
index 11d09ca4..b84cf03b 100644
--- a/common/src/main/java/me/lucko/luckperms/common/node/NodeModel.java
+++ b/common/src/main/java/me/lucko/luckperms/common/node/model/NodeDataContainer.java
@@ -23,10 +23,11 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.node;
+package me.lucko.luckperms.common.node.model;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.context.ImmutableContextSet;
+import me.lucko.luckperms.common.node.factory.NodeFactory;
import java.util.Objects;
@@ -36,12 +37,12 @@ import java.util.Objects;
*
* All values are non-null.
*/
-public final class NodeModel {
+public final class NodeDataContainer {
- public static NodeModel fromNode(Node node) {
- NodeModel model = of(
+ public static NodeDataContainer fromNode(Node node) {
+ NodeDataContainer model = of(
node.getPermission(),
- node.getValuePrimitive(),
+ node.getValue(),
node.getServer().orElse("global"),
node.getWorld().orElse("global"),
node.isTemporary() ? node.getExpiryUnixTime() : 0L,
@@ -51,11 +52,11 @@ public final class NodeModel {
return model;
}
- public static NodeModel of(String permission, boolean value, String server, String world, long expiry, ImmutableContextSet contexts) {
- return new NodeModel(permission, value, server, world, expiry, contexts);
+ public static NodeDataContainer of(String permission, boolean value, String server, String world, long expiry, ImmutableContextSet contexts) {
+ return new NodeDataContainer(permission, value, server, world, expiry, contexts);
}
- public static NodeModel of(String permission) {
+ public static NodeDataContainer of(String permission) {
return of(permission, true, "global", "global", 0L, ImmutableContextSet.empty());
}
@@ -67,7 +68,7 @@ public final class NodeModel {
private final ImmutableContextSet contexts;
private Node node = null;
- private NodeModel(String permission, boolean value, String server, String world, long expiry, ImmutableContextSet contexts) {
+ private NodeDataContainer(String permission, boolean value, String server, String world, long expiry, ImmutableContextSet contexts) {
this.permission = Objects.requireNonNull(permission, "permission");
this.value = value;
this.server = Objects.requireNonNull(server, "server");
@@ -114,35 +115,35 @@ public final class NodeModel {
return this.contexts;
}
- public NodeModel setPermission(String permission) {
+ public NodeDataContainer setPermission(String permission) {
return of(permission, this.value, this.server, this.world, this.expiry, this.contexts);
}
- public NodeModel setValue(boolean value) {
+ public NodeDataContainer setValue(boolean value) {
return of(this.permission, value, this.server, this.world, this.expiry, this.contexts);
}
- public NodeModel setServer(String server) {
+ public NodeDataContainer setServer(String server) {
return of(this.permission, this.value, server, this.world, this.expiry, this.contexts);
}
- public NodeModel setWorld(String world) {
+ public NodeDataContainer setWorld(String world) {
return of(this.permission, this.value, this.server, world, this.expiry, this.contexts);
}
- public NodeModel setExpiry(long expiry) {
+ public NodeDataContainer setExpiry(long expiry) {
return of(this.permission, this.value, this.server, this.world, expiry, this.contexts);
}
- public NodeModel setContexts(ImmutableContextSet contexts) {
+ public NodeDataContainer setContexts(ImmutableContextSet contexts) {
return of(this.permission, this.value, this.server, this.world, this.expiry, contexts);
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
- if (!(o instanceof NodeModel)) return false;
- final NodeModel other = (NodeModel) o;
+ if (!(o instanceof NodeDataContainer)) return false;
+ final NodeDataContainer other = (NodeDataContainer) o;
return this.getPermission().equals(other.getPermission()) &&
this.getValue() == other.getValue() &&
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/NodeHeldPermission.java b/common/src/main/java/me/lucko/luckperms/common/node/model/NodeHeldPermission.java
similarity index 94%
rename from common/src/main/java/me/lucko/luckperms/common/node/NodeHeldPermission.java
rename to common/src/main/java/me/lucko/luckperms/common/node/model/NodeHeldPermission.java
index ff57a888..c9f20aed 100644
--- a/common/src/main/java/me/lucko/luckperms/common/node/NodeHeldPermission.java
+++ b/common/src/main/java/me/lucko/luckperms/common/node/model/NodeHeldPermission.java
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.node;
+package me.lucko.luckperms.common.node.model;
import me.lucko.luckperms.api.HeldPermission;
import me.lucko.luckperms.api.Node;
@@ -31,13 +31,12 @@ import me.lucko.luckperms.api.context.ContextSet;
import java.util.Optional;
import java.util.OptionalLong;
-import java.util.UUID;
import javax.annotation.Nonnull;
public final class NodeHeldPermission> implements HeldPermission {
- public static > NodeHeldPermission of(T holder, NodeModel nodeModel) {
- return of(holder, nodeModel.toNode());
+ public static > NodeHeldPermission of(T holder, NodeDataContainer node) {
+ return of(holder, node.toNode());
}
public static > NodeHeldPermission of(T holder, Node node) {
@@ -60,7 +59,7 @@ public final class NodeHeldPermission> implements HeldPe
@Override
public boolean getValue() {
- return this.node.getValuePrimitive();
+ return this.node.getValue();
}
@Nonnull
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/model/NodeTypes.java b/common/src/main/java/me/lucko/luckperms/common/node/model/NodeTypes.java
new file mode 100644
index 00000000..e1a9be50
--- /dev/null
+++ b/common/src/main/java/me/lucko/luckperms/common/node/model/NodeTypes.java
@@ -0,0 +1,319 @@
+/*
+ * 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.common.node.model;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableMap;
+
+import me.lucko.luckperms.api.nodetype.NodeType;
+import me.lucko.luckperms.api.nodetype.NodeTypeKey;
+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 me.lucko.luckperms.common.node.factory.LegacyNodeFactory;
+import me.lucko.luckperms.common.utils.PatternCache;
+
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+public final class NodeTypes {
+
+ public static final String PREFIX_KEY = "prefix";
+ public static final String SUFFIX_KEY = "suffix";
+ public static final String META_KEY = "meta";
+ public static final String WEIGHT_KEY = "weight";
+
+ public static final String GROUP_NODE_MARKER = "group.";
+ public static final String PREFIX_NODE_MARKER = PREFIX_KEY + ".";
+ public static final String SUFFIX_NODE_MARKER = SUFFIX_KEY + ".";
+ public static final String META_NODE_MARKER = META_KEY + ".";
+ public static final String WEIGHT_NODE_MARKER = WEIGHT_KEY + ".";
+
+ // used to split prefix/suffix/meta nodes
+ private static final Splitter META_SPLITTER = Splitter.on(PatternCache.compileDelimiterPattern(".", "\\")).limit(2);
+
+ public static Map, NodeType> parseTypes(String s) {
+ Map, NodeType> results = new IdentityHashMap<>();
+
+ NodeType type = parseInheritanceType(s);
+ if (type != null) {
+ results.put(InheritanceType.KEY, type);
+ }
+
+ type = parseMetaType(s);
+ if (type != null) {
+ results.put(MetaType.KEY, type);
+ }
+
+ type = parsePrefixType(s);
+ if (type != null) {
+ results.put(PrefixType.KEY, type);
+ }
+
+ type = parseSuffixType(s);
+ if (type != null) {
+ results.put(SuffixType.KEY, type);
+ }
+
+ type = parseWeightType(s);
+ if (type != null) {
+ results.put(WeightType.KEY, type);
+ }
+
+ if (results.isEmpty()) {
+ return ImmutableMap.of();
+ }
+
+ return results;
+ }
+
+ private static InheritanceType parseInheritanceType(String s) {
+ s = s.toLowerCase();
+ if (!s.startsWith(GROUP_NODE_MARKER)) {
+ return null;
+ }
+
+ String groupName = s.substring(GROUP_NODE_MARKER.length()).intern();
+ return new Inheritance(groupName);
+ }
+
+ private static MetaType parseMetaType(String s) {
+ if (!s.toLowerCase().startsWith(META_NODE_MARKER)) {
+ return null;
+ }
+
+ Iterator metaParts = META_SPLITTER.split(s.substring(META_NODE_MARKER.length())).iterator();
+
+ if (!metaParts.hasNext()) return null;
+ String key = metaParts.next();
+
+ if (!metaParts.hasNext()) return null;
+ String value = metaParts.next();
+
+ return new Meta(
+ LegacyNodeFactory.unescapeCharacters(key).intern(),
+ LegacyNodeFactory.unescapeCharacters(value).intern()
+ );
+ }
+
+ private static PrefixType parsePrefixType(String s) {
+ if (!s.toLowerCase().startsWith(PREFIX_NODE_MARKER)) {
+ return null;
+ }
+
+ Iterator metaParts = META_SPLITTER.split(s.substring(PREFIX_NODE_MARKER.length())).iterator();
+
+ if (!metaParts.hasNext()) return null;
+ String priority = metaParts.next();
+
+ if (!metaParts.hasNext()) return null;
+ String value = metaParts.next();
+
+ try {
+ int p = Integer.parseInt(priority);
+ String v = LegacyNodeFactory.unescapeCharacters(value).intern();
+ return new Prefix(p, v);
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ }
+
+ private static SuffixType parseSuffixType(String s) {
+ if (!s.toLowerCase().startsWith(SUFFIX_NODE_MARKER)) {
+ return null;
+ }
+
+ Iterator metaParts = META_SPLITTER.split(s.substring(SUFFIX_NODE_MARKER.length())).iterator();
+
+ if (!metaParts.hasNext()) return null;
+ String priority = metaParts.next();
+
+ if (!metaParts.hasNext()) return null;
+ String value = metaParts.next();
+
+ try {
+ int p = Integer.parseInt(priority);
+ String v = LegacyNodeFactory.unescapeCharacters(value).intern();
+ return new Suffix(p, v);
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ }
+
+ private static WeightType parseWeightType(String s) {
+ String lower = s.toLowerCase();
+ if (!lower.startsWith(WEIGHT_NODE_MARKER)) {
+ return null;
+ }
+ String i = lower.substring(WEIGHT_NODE_MARKER.length());
+ try {
+ return new Weight(Integer.parseInt(i));
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ }
+
+ private static final class Inheritance implements InheritanceType {
+ private final String groupName;
+
+ private Inheritance(String groupName) {
+ this.groupName = groupName;
+ }
+
+ @Nonnull
+ @Override
+ public String getGroupName() {
+ return this.groupName;
+ }
+ }
+
+ private static final class Meta implements MetaType {
+ private final String key;
+ private final String value;
+
+ private Meta(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ @Nonnull
+ @Override
+ public String getKey() {
+ return this.key;
+ }
+
+ @Nonnull
+ @Override
+ public String getValue() {
+ return this.value;
+ }
+ }
+
+ private static final class Prefix implements PrefixType, Map.Entry {
+ private final int priority;
+ private final String prefix;
+
+ private Prefix(int priority, String prefix) {
+ this.priority = priority;
+ this.prefix = prefix;
+ }
+
+ @Override
+ public int getPriority() {
+ return this.priority;
+ }
+
+ @Nonnull
+ @Override
+ public String getPrefix() {
+ return this.prefix;
+ }
+
+ @Nonnull
+ @Override
+ public Map.Entry getAsEntry() {
+ return this;
+ }
+
+ @Override
+ public Integer getKey() {
+ return getPriority();
+ }
+
+ @Override
+ public String getValue() {
+ return getPrefix();
+ }
+
+ @Override
+ public String setValue(String value) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private static final class Suffix implements SuffixType, Map.Entry {
+ private final int priority;
+ private final String suffix;
+
+ private Suffix(int priority, String suffix) {
+ this.priority = priority;
+ this.suffix = suffix;
+ }
+
+ @Override
+ public int getPriority() {
+ return this.priority;
+ }
+
+ @Nonnull
+ @Override
+ public String getSuffix() {
+ return this.suffix;
+ }
+
+ @Nonnull
+ @Override
+ public Map.Entry getAsEntry() {
+ return this;
+ }
+
+ @Override
+ public Integer getKey() {
+ return getPriority();
+ }
+
+ @Override
+ public String getValue() {
+ return getSuffix();
+ }
+
+ @Override
+ public String setValue(String value) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private static final class Weight implements WeightType {
+ private final int weight;
+
+ private Weight(int weight) {
+ this.weight = weight;
+ }
+
+ @Override
+ public int getWeight() {
+ return this.weight;
+ }
+ }
+
+ private NodeTypes() {}
+
+}
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/InheritanceInfo.java b/common/src/main/java/me/lucko/luckperms/common/node/utils/InheritanceInfo.java
similarity index 98%
rename from common/src/main/java/me/lucko/luckperms/common/node/InheritanceInfo.java
rename to common/src/main/java/me/lucko/luckperms/common/node/utils/InheritanceInfo.java
index 2463fa22..f5768df1 100644
--- a/common/src/main/java/me/lucko/luckperms/common/node/InheritanceInfo.java
+++ b/common/src/main/java/me/lucko/luckperms/common/node/utils/InheritanceInfo.java
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.node;
+package me.lucko.luckperms.common.node.utils;
import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.api.Tristate;
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/MetaType.java b/common/src/main/java/me/lucko/luckperms/common/node/utils/MetaType.java
similarity index 98%
rename from common/src/main/java/me/lucko/luckperms/common/node/MetaType.java
rename to common/src/main/java/me/lucko/luckperms/common/node/utils/MetaType.java
index 0a8f02ce..08126d0f 100644
--- a/common/src/main/java/me/lucko/luckperms/common/node/MetaType.java
+++ b/common/src/main/java/me/lucko/luckperms/common/node/utils/MetaType.java
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.node;
+package me.lucko.luckperms.common.node.utils;
import me.lucko.luckperms.api.Node;
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/NodeTools.java b/common/src/main/java/me/lucko/luckperms/common/node/utils/NodeTools.java
similarity index 98%
rename from common/src/main/java/me/lucko/luckperms/common/node/NodeTools.java
rename to common/src/main/java/me/lucko/luckperms/common/node/utils/NodeTools.java
index 0ec9ff7f..466dea20 100644
--- a/common/src/main/java/me/lucko/luckperms/common/node/NodeTools.java
+++ b/common/src/main/java/me/lucko/luckperms/common/node/utils/NodeTools.java
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.node;
+package me.lucko.luckperms.common.node.utils;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.NodeEqualityPredicate;
diff --git a/common/src/main/java/me/lucko/luckperms/common/node/ShorthandParser.java b/common/src/main/java/me/lucko/luckperms/common/node/utils/ShorthandParser.java
similarity index 99%
rename from common/src/main/java/me/lucko/luckperms/common/node/ShorthandParser.java
rename to common/src/main/java/me/lucko/luckperms/common/node/utils/ShorthandParser.java
index 11e49e63..b327515e 100644
--- a/common/src/main/java/me/lucko/luckperms/common/node/ShorthandParser.java
+++ b/common/src/main/java/me/lucko/luckperms/common/node/utils/ShorthandParser.java
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-package me.lucko.luckperms.common.node;
+package me.lucko.luckperms.common.node.utils;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
diff --git a/common/src/main/java/me/lucko/luckperms/common/plugin/AbstractLuckPermsPlugin.java b/common/src/main/java/me/lucko/luckperms/common/plugin/AbstractLuckPermsPlugin.java
index 7e2d1d99..69498f80 100644
--- a/common/src/main/java/me/lucko/luckperms/common/plugin/AbstractLuckPermsPlugin.java
+++ b/common/src/main/java/me/lucko/luckperms/common/plugin/AbstractLuckPermsPlugin.java
@@ -31,7 +31,6 @@ import me.lucko.luckperms.common.api.ApiRegistrationUtil;
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
import me.lucko.luckperms.common.buffers.BufferedRequest;
import me.lucko.luckperms.common.buffers.UpdateTaskBuffer;
-import me.lucko.luckperms.common.caching.handlers.CachedStateManager;
import me.lucko.luckperms.common.calculators.PlatformCalculatorFactory;
import me.lucko.luckperms.common.command.utils.MessageUtils;
import me.lucko.luckperms.common.config.AbstractConfiguration;
@@ -80,7 +79,6 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
private InternalMessagingService messagingService = null;
private BufferedRequest updateTaskBuffer;
private InheritanceHandler inheritanceHandler;
- private CachedStateManager cachedStateManager;
private PlatformCalculatorFactory calculatorFactory;
private LuckPermsApiProvider apiProvider;
private EventFactory eventFactory;
@@ -147,7 +145,6 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
// load internal managers
getLogger().info("Loading internal permission managers...");
this.inheritanceHandler = new InheritanceHandler(this);
- this.cachedStateManager = new CachedStateManager();
// setup user/group/track manager
setupManagers();
@@ -314,11 +311,6 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
return this.inheritanceHandler;
}
- @Override
- public CachedStateManager getCachedStateManager() {
- return this.cachedStateManager;
- }
-
@Override
public PlatformCalculatorFactory getCalculatorFactory() {
return this.calculatorFactory;
diff --git a/common/src/main/java/me/lucko/luckperms/common/plugin/LuckPermsPlugin.java b/common/src/main/java/me/lucko/luckperms/common/plugin/LuckPermsPlugin.java
index 38862893..13fdc87d 100644
--- a/common/src/main/java/me/lucko/luckperms/common/plugin/LuckPermsPlugin.java
+++ b/common/src/main/java/me/lucko/luckperms/common/plugin/LuckPermsPlugin.java
@@ -29,7 +29,6 @@ import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.common.actionlog.LogDispatcher;
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
import me.lucko.luckperms.common.buffers.BufferedRequest;
-import me.lucko.luckperms.common.caching.handlers.CachedStateManager;
import me.lucko.luckperms.common.calculators.CalculatorFactory;
import me.lucko.luckperms.common.command.CommandManager;
import me.lucko.luckperms.common.command.abstraction.Command;
@@ -186,13 +185,6 @@ public interface LuckPermsPlugin {
*/
InheritanceHandler getInheritanceHandler();
- /**
- * Gets the cached state manager for the platform.
- *
- * @return the cached state manager
- */
- CachedStateManager getCachedStateManager();
-
/**
* Gets the class responsible for constructing PermissionCalculators on this platform.
*
diff --git a/common/src/main/java/me/lucko/luckperms/common/primarygroup/CachedPrimaryGroupHolder.java b/common/src/main/java/me/lucko/luckperms/common/primarygroup/CachedPrimaryGroupHolder.java
index 71a4b881..b55f81de 100644
--- a/common/src/main/java/me/lucko/luckperms/common/primarygroup/CachedPrimaryGroupHolder.java
+++ b/common/src/main/java/me/lucko/luckperms/common/primarygroup/CachedPrimaryGroupHolder.java
@@ -28,7 +28,7 @@ package me.lucko.luckperms.common.primarygroup;
import me.lucko.luckperms.common.buffers.Cache;
import me.lucko.luckperms.common.caching.handlers.StateListener;
import me.lucko.luckperms.common.model.User;
-import me.lucko.luckperms.common.node.NodeFactory;
+import me.lucko.luckperms.common.node.factory.NodeFactory;
/**
* Abstract implementation of {@link StateListener} which caches all lookups.
diff --git a/common/src/main/java/me/lucko/luckperms/common/primarygroup/ParentsByWeightHolder.java b/common/src/main/java/me/lucko/luckperms/common/primarygroup/ParentsByWeightHolder.java
index 87b009db..7e3bcbf1 100644
--- a/common/src/main/java/me/lucko/luckperms/common/primarygroup/ParentsByWeightHolder.java
+++ b/common/src/main/java/me/lucko/luckperms/common/primarygroup/ParentsByWeightHolder.java
@@ -47,7 +47,7 @@ public class ParentsByWeightHolder extends CachedPrimaryGroupHolder {
Set groups = new LinkedHashSet<>();
for (Node node : this.user.getOwnNodes(contexts.getContexts())) {
- if (!node.getValuePrimitive() || !node.isGroupNode()) {
+ if (!node.getValue() || !node.isGroupNode()) {
continue;
}
diff --git a/common/src/main/java/me/lucko/luckperms/common/processors/WildcardProcessor.java b/common/src/main/java/me/lucko/luckperms/common/processors/WildcardProcessor.java
index 9b93620e..60dceaf8 100644
--- a/common/src/main/java/me/lucko/luckperms/common/processors/WildcardProcessor.java
+++ b/common/src/main/java/me/lucko/luckperms/common/processors/WildcardProcessor.java
@@ -28,7 +28,7 @@ package me.lucko.luckperms.common.processors;
import com.google.common.collect.ImmutableMap;
import me.lucko.luckperms.api.Tristate;
-import me.lucko.luckperms.common.node.ImmutableNode;
+import me.lucko.luckperms.common.node.model.ImmutableNode;
import java.util.Collections;
import java.util.Map;
diff --git a/common/src/main/java/me/lucko/luckperms/common/references/GroupReference.java b/common/src/main/java/me/lucko/luckperms/common/references/GroupReference.java
deleted file mode 100644
index 66835fc5..00000000
--- a/common/src/main/java/me/lucko/luckperms/common/references/GroupReference.java
+++ /dev/null
@@ -1,79 +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.common.references;
-
-import me.lucko.luckperms.common.model.Group;
-import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
-
-import java.util.function.Consumer;
-
-public final class GroupReference implements HolderReference {
- public static GroupReference of(String id) {
- return new GroupReference(id);
- }
-
- private final String id;
-
- private GroupReference(String id) {
- this.id = id;
- }
-
- @Override
- public HolderType getType() {
- return HolderType.GROUP;
- }
-
- @Override
- public void apply(LuckPermsPlugin plugin, Consumer consumer) {
- Group group = plugin.getGroupManager().getIfLoaded(this.id);
- if (group == null) return;
-
- consumer.accept(group);
- }
-
- @Override
- public String getId() {
- return this.id;
- }
-
- @Override
- public boolean equals(Object o) {
- if (o == this) return true;
- if (!(o instanceof GroupReference)) return false;
- final GroupReference other = (GroupReference) o;
- return this.getId().equals(other.getId());
- }
-
- @Override
- public int hashCode() {
- return this.id.hashCode();
- }
-
- @Override
- public String toString() {
- return "GroupReference(id=" + this.getId() + ")";
- }
-}
diff --git a/common/src/main/java/me/lucko/luckperms/common/references/UserReference.java b/common/src/main/java/me/lucko/luckperms/common/references/UserReference.java
deleted file mode 100644
index cf60ad1d..00000000
--- a/common/src/main/java/me/lucko/luckperms/common/references/UserReference.java
+++ /dev/null
@@ -1,79 +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.common.references;
-
-import me.lucko.luckperms.common.model.User;
-import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
-
-import java.util.function.Consumer;
-
-public final class UserReference implements HolderReference {
- public static UserReference of(UserIdentifier id) {
- return new UserReference(id);
- }
-
- private final UserIdentifier id;
-
- private UserReference(UserIdentifier id) {
- this.id = id;
- }
-
- @Override
- public HolderType getType() {
- return HolderType.USER;
- }
-
- @Override
- public void apply(LuckPermsPlugin plugin, Consumer consumer) {
- User user = plugin.getUserManager().getIfLoaded(this.id);
- if (user == null) return;
-
- consumer.accept(user);
- }
-
- @Override
- public UserIdentifier getId() {
- return this.id;
- }
-
- @Override
- public boolean equals(Object o) {
- if (o == this) return true;
- if (!(o instanceof UserReference)) return false;
- final UserReference other = (UserReference) o;
- return this.id.equals(other.id);
- }
-
- @Override
- public int hashCode() {
- return this.id.hashCode();
- }
-
- @Override
- public String toString() {
- return "UserReference(id=" + this.getId() + ")";
- }
-}
diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/dao/file/AbstractConfigurateDao.java b/common/src/main/java/me/lucko/luckperms/common/storage/dao/file/AbstractConfigurateDao.java
index 5f3e2fe2..efe9a30d 100644
--- a/common/src/main/java/me/lucko/luckperms/common/storage/dao/file/AbstractConfigurateDao.java
+++ b/common/src/main/java/me/lucko/luckperms/common/storage/dao/file/AbstractConfigurateDao.java
@@ -37,13 +37,14 @@ import me.lucko.luckperms.common.actionlog.Log;
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
import me.lucko.luckperms.common.contexts.ContextSetConfigurateSerializer;
import me.lucko.luckperms.common.model.Group;
+import me.lucko.luckperms.common.model.NodeMapType;
import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.User;
-import me.lucko.luckperms.common.node.MetaType;
-import me.lucko.luckperms.common.node.NodeFactory;
-import me.lucko.luckperms.common.node.NodeModel;
+import me.lucko.luckperms.common.model.UserIdentifier;
+import me.lucko.luckperms.common.node.factory.NodeFactory;
+import me.lucko.luckperms.common.node.model.NodeDataContainer;
+import me.lucko.luckperms.common.node.utils.MetaType;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
-import me.lucko.luckperms.common.references.UserIdentifier;
import me.lucko.luckperms.common.storage.PlayerSaveResult;
import me.lucko.luckperms.common.storage.dao.AbstractDao;
import me.lucko.luckperms.common.storage.dao.file.loader.ConfigurateLoader;
@@ -156,8 +157,8 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
}
protected ConfigurationNode processBulkUpdate(BulkUpdate bulkUpdate, ConfigurationNode node) {
- Set nodes = readNodes(node);
- Set results = nodes.stream()
+ Set nodes = readNodes(node);
+ Set results = nodes.stream()
.map(bulkUpdate::apply)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
@@ -180,8 +181,8 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
String name = object.getNode("name").getString();
user.getPrimaryGroup().setStoredValue(object.getNode(this.loader instanceof JsonLoader ? "primaryGroup" : "primary-group").getString());
- Set nodes = readNodes(object).stream().map(NodeModel::toNode).collect(Collectors.toSet());
- user.setEnduringNodes(nodes);
+ Set nodes = readNodes(object).stream().map(NodeDataContainer::toNode).collect(Collectors.toSet());
+ user.setNodes(NodeMapType.ENDURING, nodes);
user.setName(name, true);
boolean save = this.plugin.getUserManager().giveDefaultIfNeeded(user, false);
@@ -222,7 +223,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
data.getNode("name").setValue(user.getName().orElse("null"));
data.getNode(this.loader instanceof JsonLoader ? "primaryGroup" : "primary-group").setValue(user.getPrimaryGroup().getStoredValue().orElse(NodeFactory.DEFAULT_GROUP_NAME));
- Set nodes = user.getEnduringNodes().values().stream().map(NodeModel::fromNode).collect(Collectors.toCollection(LinkedHashSet::new));
+ Set nodes = user.enduringData().immutable().values().stream().map(NodeDataContainer::fromNode).collect(Collectors.toCollection(LinkedHashSet::new));
writeNodes(data, nodes);
saveFile(StorageLocation.USER, user.getUuid().toString(), data);
@@ -242,15 +243,15 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
ConfigurationNode object = readFile(StorageLocation.GROUP, name);
if (object != null) {
- Set nodes = readNodes(object).stream().map(NodeModel::toNode).collect(Collectors.toSet());
- group.setEnduringNodes(nodes);
+ Set nodes = readNodes(object).stream().map(NodeDataContainer::toNode).collect(Collectors.toSet());
+ group.setNodes(NodeMapType.ENDURING, nodes);
} else {
ConfigurationNode data = SimpleConfigurationNode.root();
if (this instanceof SeparatedConfigurateDao) {
data.getNode("name").setValue(group.getName());
}
- Set nodes = group.getEnduringNodes().values().stream().map(NodeModel::fromNode).collect(Collectors.toCollection(LinkedHashSet::new));
+ Set nodes = group.enduringData().immutable().values().stream().map(NodeDataContainer::fromNode).collect(Collectors.toCollection(LinkedHashSet::new));
writeNodes(data, nodes);
saveFile(StorageLocation.GROUP, name, data);
@@ -283,9 +284,9 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
group.getIoLock().lock();
}
- Set data = readNodes(object);
- Set nodes = data.stream().map(NodeModel::toNode).collect(Collectors.toSet());
- group.setEnduringNodes(nodes);
+ Set data = readNodes(object);
+ Set nodes = data.stream().map(NodeDataContainer::toNode).collect(Collectors.toSet());
+ group.setNodes(NodeMapType.ENDURING, nodes);
} catch (Exception e) {
throw reportException(name, e);
@@ -307,7 +308,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
data.getNode("name").setValue(group.getName());
}
- Set nodes = group.getEnduringNodes().values().stream().map(NodeModel::fromNode).collect(Collectors.toCollection(LinkedHashSet::new));
+ Set nodes = group.enduringData().immutable().values().stream().map(NodeDataContainer::fromNode).collect(Collectors.toCollection(LinkedHashSet::new));
writeNodes(data, nodes);
saveFile(StorageLocation.GROUP, group.getName(), data);
@@ -441,7 +442,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
return this.uuidCache.lookupUsername(uuid);
}
- private static NodeModel readAttributes(ConfigurationNode attributes, Function permissionFunction) {
+ private static NodeDataContainer readAttributes(ConfigurationNode attributes, Function permissionFunction) {
boolean value = attributes.getNode("value").getBoolean(true);
String server = attributes.getNode("server").getString("global");
String world = attributes.getNode("world").getString("global");
@@ -453,10 +454,10 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
context = ContextSetConfigurateSerializer.deserializeContextSet(contextMap).makeImmutable();
}
- return NodeModel.of(permissionFunction.apply(attributes), value, server, world, expiry, context);
+ return NodeDataContainer.of(permissionFunction.apply(attributes), value, server, world, expiry, context);
}
- private static Collection readAttributes(ConfigurationNode attributes, String permission) {
+ private static Collection readAttributes(ConfigurationNode attributes, String permission) {
boolean value = attributes.getNode("value").getBoolean(true);
String server = attributes.getNode("server").getString("global");
String world = attributes.getNode("world").getString("global");
@@ -470,13 +471,13 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
ConfigurationNode batchAttribute = attributes.getNode("permissions");
if (permission.startsWith("luckperms.batch") && !batchAttribute.isVirtual() && batchAttribute.hasListChildren()) {
- List nodes = new ArrayList<>();
+ List nodes = new ArrayList<>();
for (ConfigurationNode element : batchAttribute.getChildrenList()) {
- nodes.add(NodeModel.of(element.getString(), value, server, world, expiry, context));
+ nodes.add(NodeDataContainer.of(element.getString(), value, server, world, expiry, context));
}
return nodes;
} else {
- return Collections.singleton(NodeModel.of(permission, value, server, world, expiry, context));
+ return Collections.singleton(NodeDataContainer.of(permission, value, server, world, expiry, context));
}
}
@@ -513,15 +514,15 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
return Maps.immutableEntry(permission, appended);
}
- protected static Set readNodes(ConfigurationNode data) {
- Set nodes = new HashSet<>();
+ protected static Set readNodes(ConfigurationNode data) {
+ Set nodes = new HashSet<>();
if (data.getNode("permissions").hasListChildren()) {
List extends ConfigurationNode> children = data.getNode("permissions").getChildrenList();
for (ConfigurationNode appended : children) {
String plainValue = appended.getValue(Types::strictAsString);
if (plainValue != null) {
- nodes.add(NodeModel.of(plainValue));
+ nodes.add(NodeDataContainer.of(plainValue));
continue;
}
@@ -538,7 +539,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
for (ConfigurationNode appended : children) {
String stringValue = appended.getValue(Types::strictAsString);
if (stringValue != null) {
- nodes.add(NodeModel.of(NodeFactory.groupNode(stringValue)));
+ nodes.add(NodeDataContainer.of(NodeFactory.groupNode(stringValue)));
continue;
}
@@ -578,7 +579,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
return nodes;
}
- private static void writeAttributesTo(ConfigurationNode attributes, NodeModel node, boolean writeValue) {
+ private static void writeAttributesTo(ConfigurationNode attributes, NodeDataContainer node, boolean writeValue) {
if (writeValue) {
attributes.getNode("value").setValue(node.getValue());
}
@@ -600,7 +601,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
}
}
- private static boolean isPlain(NodeModel node) {
+ private static boolean isPlain(NodeDataContainer node) {
return node.getValue() &&
node.getServer().equalsIgnoreCase("global") &&
node.getWorld().equalsIgnoreCase("global") &&
@@ -625,14 +626,14 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
}
}
- private void writeNodes(ConfigurationNode to, Set nodes) {
+ private void writeNodes(ConfigurationNode to, Set nodes) {
ConfigurationNode permissionsSection = SimpleConfigurationNode.root();
ConfigurationNode parentsSection = SimpleConfigurationNode.root();
ConfigurationNode prefixesSection = SimpleConfigurationNode.root();
ConfigurationNode suffixesSection = SimpleConfigurationNode.root();
ConfigurationNode metaSection = SimpleConfigurationNode.root();
- for (NodeModel node : nodes) {
+ for (NodeDataContainer node : nodes) {
Node n = node.toNode();
// just add a string to the list.
@@ -648,7 +649,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
}
ChatMetaType chatMetaType = ChatMetaType.ofNode(n).orElse(null);
- if (chatMetaType != null && n.getValuePrimitive()) {
+ if (chatMetaType != null && n.getValue()) {
// handle prefixes / suffixes
Map.Entry entry = chatMetaType.getEntry(n);
@@ -666,7 +667,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
default:
throw new AssertionError();
}
- } else if (n.isMeta() && n.getValuePrimitive()) {
+ } else if (n.isMeta() && n.getValue()) {
// handle meta nodes
Map.Entry meta = n.getMeta();
@@ -675,7 +676,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
writeAttributesTo(attributes, node, false);
appendNode(metaSection, meta.getKey(), attributes, "key");
- } else if (n.isGroupNode() && n.getValuePrimitive()) {
+ } else if (n.isGroupNode() && n.getValue()) {
// handle group nodes
ConfigurationNode attributes = SimpleConfigurationNode.root();
writeAttributesTo(attributes, node, false);
diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/dao/file/CombinedConfigurateDao.java b/common/src/main/java/me/lucko/luckperms/common/storage/dao/file/CombinedConfigurateDao.java
index 359943d8..7b4f01a5 100644
--- a/common/src/main/java/me/lucko/luckperms/common/storage/dao/file/CombinedConfigurateDao.java
+++ b/common/src/main/java/me/lucko/luckperms/common/storage/dao/file/CombinedConfigurateDao.java
@@ -29,8 +29,8 @@ import me.lucko.luckperms.api.HeldPermission;
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
import me.lucko.luckperms.common.managers.group.GroupManager;
import me.lucko.luckperms.common.managers.track.TrackManager;
-import me.lucko.luckperms.common.node.NodeHeldPermission;
-import me.lucko.luckperms.common.node.NodeModel;
+import me.lucko.luckperms.common.node.model.NodeDataContainer;
+import me.lucko.luckperms.common.node.model.NodeHeldPermission;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.dao.file.loader.ConfigurateLoader;
@@ -270,8 +270,8 @@ public class CombinedConfigurateDao extends AbstractConfigurateDao {
UUID holder = UUID.fromString(entry.getKey().toString());
ConfigurationNode object = entry.getValue();
- Set nodes = readNodes(object);
- for (NodeModel e : nodes) {
+ Set nodes = readNodes(object);
+ for (NodeDataContainer e : nodes) {
if (!e.getPermission().equalsIgnoreCase(permission)) {
continue;
}
@@ -324,8 +324,8 @@ public class CombinedConfigurateDao extends AbstractConfigurateDao {
String holder = entry.getKey().toString();
ConfigurationNode object = entry.getValue();
- Set nodes = readNodes(object);
- for (NodeModel e : nodes) {
+ Set nodes = readNodes(object);
+ for (NodeDataContainer e : nodes) {
if (!e.getPermission().equalsIgnoreCase(permission)) {
continue;
}
diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/dao/file/SeparatedConfigurateDao.java b/common/src/main/java/me/lucko/luckperms/common/storage/dao/file/SeparatedConfigurateDao.java
index 4b6a3f2c..af5c593d 100644
--- a/common/src/main/java/me/lucko/luckperms/common/storage/dao/file/SeparatedConfigurateDao.java
+++ b/common/src/main/java/me/lucko/luckperms/common/storage/dao/file/SeparatedConfigurateDao.java
@@ -30,8 +30,8 @@ import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
import me.lucko.luckperms.common.managers.group.GroupManager;
import me.lucko.luckperms.common.managers.track.TrackManager;
import me.lucko.luckperms.common.model.User;
-import me.lucko.luckperms.common.node.NodeHeldPermission;
-import me.lucko.luckperms.common.node.NodeModel;
+import me.lucko.luckperms.common.node.model.NodeDataContainer;
+import me.lucko.luckperms.common.node.model.NodeHeldPermission;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.dao.file.loader.ConfigurateLoader;
import me.lucko.luckperms.common.utils.MoreFiles;
@@ -263,8 +263,8 @@ public class SeparatedConfigurateDao extends AbstractConfigurateDao {
registerFileAction(StorageLocation.USER, file);
ConfigurationNode object = readFile(file);
UUID holder = UUID.fromString(fileName.substring(0, fileName.length() - this.fileExtension.length()));
- Set nodes = readNodes(object);
- for (NodeModel e : nodes) {
+ Set nodes = readNodes(object);
+ for (NodeDataContainer e : nodes) {
if (!e.getPermission().equalsIgnoreCase(permission)) {
continue;
}
@@ -319,8 +319,8 @@ public class SeparatedConfigurateDao extends AbstractConfigurateDao {
registerFileAction(StorageLocation.GROUP, file);
ConfigurationNode object = readFile(file);
String holder = fileName.substring(0, fileName.length() - this.fileExtension.length());
- Set nodes = readNodes(object);
- for (NodeModel e : nodes) {
+ Set nodes = readNodes(object);
+ for (NodeDataContainer e : nodes) {
if (!e.getPermission().equalsIgnoreCase(permission)) {
continue;
}
diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/dao/mongodb/MongoDao.java b/common/src/main/java/me/lucko/luckperms/common/storage/dao/mongodb/MongoDao.java
index 49de4fa5..bc1812da 100644
--- a/common/src/main/java/me/lucko/luckperms/common/storage/dao/mongodb/MongoDao.java
+++ b/common/src/main/java/me/lucko/luckperms/common/storage/dao/mongodb/MongoDao.java
@@ -49,14 +49,15 @@ import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
import me.lucko.luckperms.common.managers.group.GroupManager;
import me.lucko.luckperms.common.managers.track.TrackManager;
import me.lucko.luckperms.common.model.Group;
+import me.lucko.luckperms.common.model.NodeMapType;
import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.User;
-import me.lucko.luckperms.common.node.LegacyNodeFactory;
-import me.lucko.luckperms.common.node.NodeFactory;
-import me.lucko.luckperms.common.node.NodeHeldPermission;
-import me.lucko.luckperms.common.node.NodeModel;
+import me.lucko.luckperms.common.model.UserIdentifier;
+import me.lucko.luckperms.common.node.factory.LegacyNodeFactory;
+import me.lucko.luckperms.common.node.factory.NodeFactory;
+import me.lucko.luckperms.common.node.model.NodeDataContainer;
+import me.lucko.luckperms.common.node.model.NodeHeldPermission;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
-import me.lucko.luckperms.common.references.UserIdentifier;
import me.lucko.luckperms.common.storage.PlayerSaveResult;
import me.lucko.luckperms.common.storage.StorageCredentials;
import me.lucko.luckperms.common.storage.dao.AbstractDao;
@@ -204,8 +205,8 @@ public class MongoDao extends AbstractDao {
Document d = cursor.next();
UUID uuid = d.get("_id", UUID.class);
- Set nodes = new HashSet<>(nodesFromDoc(d));
- Set results = nodes.stream()
+ Set nodes = new HashSet<>(nodesFromDoc(d));
+ Set results = nodes.stream()
.map(bulkUpdate::apply)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
@@ -229,8 +230,8 @@ public class MongoDao extends AbstractDao {
Document d = cursor.next();
String holder = d.getString("_id");
- Set nodes = new HashSet<>(nodesFromDoc(d));
- Set results = nodes.stream()
+ Set nodes = new HashSet<>(nodesFromDoc(d));
+ Set results = nodes.stream()
.map(bulkUpdate::apply)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
@@ -262,8 +263,8 @@ public class MongoDao extends AbstractDao {
String name = d.getString("name");
user.getPrimaryGroup().setStoredValue(d.getString("primaryGroup"));
- Set nodes = nodesFromDoc(d).stream().map(NodeModel::toNode).collect(Collectors.toSet());
- user.setEnduringNodes(nodes);
+ Set nodes = nodesFromDoc(d).stream().map(NodeDataContainer::toNode).collect(Collectors.toSet());
+ user.setNodes(NodeMapType.ENDURING, nodes);
user.setName(name, true);
boolean save = this.plugin.getUserManager().giveDefaultIfNeeded(user, false);
@@ -326,8 +327,8 @@ public class MongoDao extends AbstractDao {
Document d = cursor.next();
UUID holder = d.get("_id", UUID.class);
- Set nodes = new HashSet<>(nodesFromDoc(d));
- for (NodeModel e : nodes) {
+ Set nodes = new HashSet<>(nodesFromDoc(d));
+ for (NodeDataContainer e : nodes) {
if (!e.getPermission().equalsIgnoreCase(permission)) {
continue;
}
@@ -347,8 +348,8 @@ public class MongoDao extends AbstractDao {
try (MongoCursor cursor = c.find(new Document("_id", group.getName())).iterator()) {
if (cursor.hasNext()) {
Document d = cursor.next();
- Set nodes = nodesFromDoc(d).stream().map(NodeModel::toNode).collect(Collectors.toSet());
- group.setEnduringNodes(nodes);
+ Set nodes = nodesFromDoc(d).stream().map(NodeDataContainer::toNode).collect(Collectors.toSet());
+ group.setNodes(NodeMapType.ENDURING, nodes);
} else {
c.insertOne(groupToDoc(group));
}
@@ -379,8 +380,8 @@ public class MongoDao extends AbstractDao {
}
Document d = cursor.next();
- Set nodes = nodesFromDoc(d).stream().map(NodeModel::toNode).collect(Collectors.toSet());
- group.setEnduringNodes(nodes);
+ Set nodes = nodesFromDoc(d).stream().map(NodeDataContainer::toNode).collect(Collectors.toSet());
+ group.setNodes(NodeMapType.ENDURING, nodes);
}
} finally {
if (group != null) {
@@ -453,8 +454,8 @@ public class MongoDao extends AbstractDao {
Document d = cursor.next();
String holder = d.getString("_id");
- Set nodes = new HashSet<>(nodesFromDoc(d));
- for (NodeModel e : nodes) {
+ Set nodes = new HashSet<>(nodesFromDoc(d));
+ for (NodeDataContainer e : nodes) {
if (!e.getPermission().equalsIgnoreCase(permission)) {
continue;
}
@@ -623,8 +624,8 @@ public class MongoDao extends AbstractDao {
}
private static Document userToDoc(User user) {
- List nodes = user.getEnduringNodes().values().stream()
- .map(NodeModel::fromNode)
+ List nodes = user.enduringData().immutable().values().stream()
+ .map(NodeDataContainer::fromNode)
.map(MongoDao::nodeToDoc)
.collect(Collectors.toList());
@@ -634,8 +635,8 @@ public class MongoDao extends AbstractDao {
.append("permissions", nodes);
}
- private static List nodesFromDoc(Document document) {
- List nodes = new ArrayList<>();
+ private static List nodesFromDoc(Document document) {
+ List nodes = new ArrayList<>();
// legacy
if (document.containsKey("perms") && document.get("perms") instanceof Map) {
@@ -644,7 +645,7 @@ public class MongoDao extends AbstractDao {
for (Map.Entry e : permsMap.entrySet()) {
// legacy permission key deserialisation
String permission = e.getKey().replace("[**DOT**]", ".").replace("[**DOLLAR**]", "$");
- nodes.add(NodeModel.fromNode(LegacyNodeFactory.fromLegacyString(permission, e.getValue())));
+ nodes.add(NodeDataContainer.fromNode(LegacyNodeFactory.fromLegacyString(permission, e.getValue())));
}
}
@@ -661,8 +662,8 @@ public class MongoDao extends AbstractDao {
}
private static Document groupToDoc(Group group) {
- List nodes = group.getEnduringNodes().values().stream()
- .map(NodeModel::fromNode)
+ List nodes = group.enduringData().immutable().values().stream()
+ .map(NodeDataContainer::fromNode)
.map(MongoDao::nodeToDoc)
.collect(Collectors.toList());
@@ -673,7 +674,7 @@ public class MongoDao extends AbstractDao {
return new Document("_id", track.getName()).append("groups", track.getGroups());
}
- private static Document nodeToDoc(NodeModel node) {
+ private static Document nodeToDoc(NodeDataContainer node) {
Document document = new Document();
document.append("permission", node.getPermission());
@@ -698,7 +699,7 @@ public class MongoDao extends AbstractDao {
return document;
}
- private static NodeModel nodeFromDoc(Document document) {
+ private static NodeDataContainer nodeFromDoc(Document document) {
String permission = document.getString("permission");
boolean value = true;
String server = "global";
@@ -725,7 +726,7 @@ public class MongoDao extends AbstractDao {
context = docsToContextSet(contexts).makeImmutable();
}
- return NodeModel.of(permission, value, server, world, expiry, context);
+ return NodeDataContainer.of(permission, value, server, world, expiry, context);
}
private static List contextSetToDocs(ContextSet contextSet) {
diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/dao/sql/SqlDao.java b/common/src/main/java/me/lucko/luckperms/common/storage/dao/sql/SqlDao.java
index b0023369..83f21e7d 100644
--- a/common/src/main/java/me/lucko/luckperms/common/storage/dao/sql/SqlDao.java
+++ b/common/src/main/java/me/lucko/luckperms/common/storage/dao/sql/SqlDao.java
@@ -39,13 +39,14 @@ import me.lucko.luckperms.common.contexts.ContextSetJsonSerializer;
import me.lucko.luckperms.common.managers.group.GroupManager;
import me.lucko.luckperms.common.managers.track.TrackManager;
import me.lucko.luckperms.common.model.Group;
+import me.lucko.luckperms.common.model.NodeMapType;
import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.User;
-import me.lucko.luckperms.common.node.NodeFactory;
-import me.lucko.luckperms.common.node.NodeHeldPermission;
-import me.lucko.luckperms.common.node.NodeModel;
+import me.lucko.luckperms.common.model.UserIdentifier;
+import me.lucko.luckperms.common.node.factory.NodeFactory;
+import me.lucko.luckperms.common.node.model.NodeDataContainer;
+import me.lucko.luckperms.common.node.model.NodeHeldPermission;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
-import me.lucko.luckperms.common.references.UserIdentifier;
import me.lucko.luckperms.common.storage.PlayerSaveResult;
import me.lucko.luckperms.common.storage.dao.AbstractDao;
import me.lucko.luckperms.common.storage.dao.sql.connection.AbstractConnectionFactory;
@@ -287,7 +288,7 @@ public class SqlDao extends AbstractDao {
User user = this.plugin.getUserManager().getOrMake(UserIdentifier.of(uuid, username));
user.getIoLock().lock();
try {
- List data = new ArrayList<>();
+ List data = new ArrayList<>();
String primaryGroup = null;
String userName = null;
@@ -335,8 +336,8 @@ public class SqlDao extends AbstractDao {
// If the user has any data in storage
if (!data.isEmpty()) {
- Set nodes = data.stream().map(NodeModel::toNode).collect(Collectors.toSet());
- user.setEnduringNodes(nodes);
+ Set nodes = data.stream().map(NodeDataContainer::toNode).collect(Collectors.toSet());
+ user.setNodes(NodeMapType.ENDURING, nodes);
// Save back to the store if data they were given any defaults or had permissions expire
if (this.plugin.getUserManager().giveDefaultIfNeeded(user, false) | user.auditTemporaryPermissions()) {
@@ -380,7 +381,7 @@ public class SqlDao extends AbstractDao {
}
// Get a snapshot of current data.
- Set remote = new HashSet<>();
+ Set remote = new HashSet<>();
try (Connection c = this.provider.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.prefix.apply(USER_PERMISSIONS_SELECT))) {
ps.setString(1, user.getUuid().toString());
@@ -399,17 +400,17 @@ public class SqlDao extends AbstractDao {
}
}
- Set local = user.getEnduringNodes().values().stream().map(NodeModel::fromNode).collect(Collectors.toSet());
+ Set local = user.enduringData().immutable().values().stream().map(NodeDataContainer::fromNode).collect(Collectors.toSet());
- Map.Entry, Set> diff = compareSets(local, remote);
+ Map.Entry, Set> diff = compareSets(local, remote);
- Set toAdd = diff.getKey();
- Set toRemove = diff.getValue();
+ Set toAdd = diff.getKey();
+ Set toRemove = diff.getValue();
if (!toRemove.isEmpty()) {
try (Connection c = this.provider.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.prefix.apply(USER_PERMISSIONS_DELETE_SPECIFIC))) {
- for (NodeModel nd : toRemove) {
+ for (NodeDataContainer nd : toRemove) {
ps.setString(1, user.getUuid().toString());
ps.setString(2, nd.getPermission());
ps.setBoolean(3, nd.getValue());
@@ -427,7 +428,7 @@ public class SqlDao extends AbstractDao {
if (!toAdd.isEmpty()) {
try (Connection c = this.provider.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.prefix.apply(USER_PERMISSIONS_INSERT))) {
- for (NodeModel nd : toAdd) {
+ for (NodeDataContainer nd : toAdd) {
ps.setString(1, user.getUuid().toString());
ps.setString(2, nd.getPermission());
ps.setBoolean(3, nd.getValue());
@@ -506,7 +507,7 @@ public class SqlDao extends AbstractDao {
long expiry = rs.getLong("expiry");
String contexts = rs.getString("contexts");
- NodeModel data = deserializeNode(permission, value, server, world, expiry, contexts);
+ NodeDataContainer data = deserializeNode(permission, value, server, world, expiry, contexts);
held.add(NodeHeldPermission.of(holder, data));
}
}
@@ -565,7 +566,7 @@ public class SqlDao extends AbstractDao {
Group group = this.plugin.getGroupManager().getOrMake(name);
group.getIoLock().lock();
try {
- List data = new ArrayList<>();
+ List data = new ArrayList<>();
try (Connection c = this.provider.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.prefix.apply(GROUP_PERMISSIONS_SELECT))) {
@@ -586,8 +587,8 @@ public class SqlDao extends AbstractDao {
}
if (!data.isEmpty()) {
- Set nodes = data.stream().map(NodeModel::toNode).collect(Collectors.toSet());
- group.setEnduringNodes(nodes);
+ Set nodes = data.stream().map(NodeDataContainer::toNode).collect(Collectors.toSet());
+ group.setNodes(NodeMapType.ENDURING, nodes);
} else {
group.clearNodes();
}
@@ -636,7 +637,7 @@ public class SqlDao extends AbstractDao {
group.getIoLock().lock();
try {
// Empty data, just delete.
- if (group.getEnduringNodes().isEmpty()) {
+ if (group.enduringData().immutable().isEmpty()) {
try (Connection c = this.provider.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.prefix.apply(GROUP_PERMISSIONS_DELETE))) {
ps.setString(1, group.getName());
@@ -647,7 +648,7 @@ public class SqlDao extends AbstractDao {
}
// Get a snapshot of current data
- Set remote = new HashSet<>();
+ Set remote = new HashSet<>();
try (Connection c = this.provider.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.prefix.apply(GROUP_PERMISSIONS_SELECT))) {
ps.setString(1, group.getName());
@@ -666,17 +667,17 @@ public class SqlDao extends AbstractDao {
}
}
- Set local = group.getEnduringNodes().values().stream().map(NodeModel::fromNode).collect(Collectors.toSet());
+ Set local = group.enduringData().immutable().values().stream().map(NodeDataContainer::fromNode).collect(Collectors.toSet());
- Map.Entry, Set> diff = compareSets(local, remote);
+ Map.Entry, Set> diff = compareSets(local, remote);
- Set toAdd = diff.getKey();
- Set toRemove = diff.getValue();
+ Set toAdd = diff.getKey();
+ Set toRemove = diff.getValue();
if (!toRemove.isEmpty()) {
try (Connection c = this.provider.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.prefix.apply(GROUP_PERMISSIONS_DELETE_SPECIFIC))) {
- for (NodeModel nd : toRemove) {
+ for (NodeDataContainer nd : toRemove) {
ps.setString(1, group.getName());
ps.setString(2, nd.getPermission());
ps.setBoolean(3, nd.getValue());
@@ -694,7 +695,7 @@ public class SqlDao extends AbstractDao {
if (!toAdd.isEmpty()) {
try (Connection c = this.provider.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.prefix.apply(GROUP_PERMISSIONS_INSERT))) {
- for (NodeModel nd : toAdd) {
+ for (NodeDataContainer nd : toAdd) {
ps.setString(1, group.getName());
ps.setString(2, nd.getPermission());
ps.setBoolean(3, nd.getValue());
@@ -750,7 +751,7 @@ public class SqlDao extends AbstractDao {
long expiry = rs.getLong("expiry");
String contexts = rs.getString("contexts");
- NodeModel data = deserializeNode(permission, value, server, world, expiry, contexts);
+ NodeDataContainer data = deserializeNode(permission, value, server, world, expiry, contexts);
held.add(NodeHeldPermission.of(holder, data));
}
}
@@ -994,20 +995,20 @@ public class SqlDao extends AbstractDao {
* @param remote the remote set
* @return the entries to add to remote, and the entries to remove from remote
*/
- private static Map.Entry, Set> compareSets(Set local, Set remote) {
+ private static Map.Entry, Set> compareSets(Set local, Set remote) {
// entries in local but not remote need to be added
// entries in remote but not local need to be removed
- Set toAdd = new HashSet<>(local);
+ Set toAdd = new HashSet<>(local);
toAdd.removeAll(remote);
- Set toRemove = new HashSet<>(remote);
+ Set