Add UserManager/GroupManager searchAll method

This commit is contained in:
Luck 2020-05-07 03:46:22 +01:00
parent 1af55e3720
commit 7ae532f082
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
28 changed files with 807 additions and 135 deletions

View File

@ -39,6 +39,7 @@ import net.luckperms.api.model.group.GroupManager;
import net.luckperms.api.model.user.User;
import net.luckperms.api.model.user.UserManager;
import net.luckperms.api.node.NodeBuilderRegistry;
import net.luckperms.api.node.matcher.NodeMatcherFactory;
import net.luckperms.api.platform.Platform;
import net.luckperms.api.platform.PluginMetadata;
import net.luckperms.api.query.QueryOptionsRegistry;
@ -192,6 +193,14 @@ public interface LuckPerms {
*/
@NonNull MetaStackFactory getMetaStackFactory();
/**
* Gets the {@link NodeMatcherFactory}.
*
* @return the node matcher factory
* @since 5.1
*/
@NonNull NodeMatcherFactory getNodeMatcherFactory();
/**
* Schedules the execution of an update task, and returns an encapsulation
* of the task as a {@link CompletableFuture}.

View File

@ -26,11 +26,15 @@
package net.luckperms.api.model.group;
import net.luckperms.api.node.HeldNode;
import net.luckperms.api.node.Node;
import net.luckperms.api.node.matcher.NodeMatcher;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
@ -105,13 +109,25 @@ public interface GroupManager {
*/
@NonNull CompletableFuture<Void> loadAllGroups();
/**
* Searches the {@link Group#data() normal node maps} of all known {@link Group}s for {@link Node}
* entries matching the given {@link NodeMatcher matcher}.
*
* @param matcher the matcher
* @return the entries which matched
* @since 5.1
*/
@NonNull <T extends Node> CompletableFuture<Map<String, Collection<T>>> searchAll(@NonNull NodeMatcher<? extends T> matcher);
/**
* Searches for a list of groups with a given permission.
*
* @param permission the permission to search for
* @return a list of held permissions, or null if the operation failed
* @throws NullPointerException if the permission is null
* @deprecated use {@link #searchAll(NodeMatcher)}
*/
@Deprecated
@NonNull CompletableFuture<List<HeldNode<String>>> getWithPermission(@NonNull String permission);
/**

View File

@ -27,11 +27,15 @@ package net.luckperms.api.model.user;
import net.luckperms.api.model.PlayerSaveResult;
import net.luckperms.api.node.HeldNode;
import net.luckperms.api.node.Node;
import net.luckperms.api.node.matcher.NodeMatcher;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@ -131,13 +135,25 @@ public interface UserManager {
*/
@NonNull CompletableFuture<Set<UUID>> getUniqueUsers();
/**
* Searches the {@link User#data() normal node maps} of all known {@link User}s for {@link Node}
* entries matching the given {@link NodeMatcher matcher}.
*
* @param matcher the matcher
* @return the entries which matched
* @since 5.1
*/
@NonNull <T extends Node> CompletableFuture<Map<UUID, Collection<T>>> searchAll(@NonNull NodeMatcher<? extends T> matcher);
/**
* Searches for a list of users with a given permission.
*
* @param permission the permission to search for
* @return a list of held permissions
* @throws NullPointerException if the permission is null
* @deprecated use {@link #searchAll(NodeMatcher)}
*/
@Deprecated
@NonNull CompletableFuture<List<HeldNode<UUID>>> getWithPermission(@NonNull String permission);
/**

View File

@ -34,6 +34,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
*
* @param <T> the identifier type of the holder
*/
@Deprecated
public interface HeldNode<T> {
/**

View File

@ -0,0 +1,146 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.luckperms.api.node.matcher;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.LuckPermsProvider;
import net.luckperms.api.node.Node;
import net.luckperms.api.node.NodeEqualityPredicate;
import net.luckperms.api.node.NodeType;
import net.luckperms.api.node.types.MetaNode;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.function.Predicate;
/**
* A predicate which matches certain {@link Node}s.
*
* @param <T> the node type matched
* @since 5.1
*/
public interface NodeMatcher<T extends Node> extends Predicate<Node> {
/**
* Gets a {@link NodeMatcher} which matches nodes with the same {@link Node#getKey() key}.
*
* <p>The {@link String#equalsIgnoreCase(String)} method is used to test key equality.</p>
*
* @param key the key
* @return the matcher
*/
static @NonNull NodeMatcher<Node> key(@NonNull String key) {
return LuckPermsProvider.get().getNodeMatcherFactory().key(key);
}
/**
* Gets a {@link NodeMatcher} which matches nodes with the same {@link Node#getKey() key}.
*
* <p>The {@link String#equalsIgnoreCase(String)} method is used to test key equality.</p>
*
* @param node the node to use for the key
* @param <T> the node type
* @return the matcher
*/
static <T extends Node> @NonNull NodeMatcher<T> key(@NonNull T node) {
return LuckPermsProvider.get().getNodeMatcherFactory().key(node);
}
/**
* Gets a {@link NodeMatcher} which matches nodes with a {@link Node#getKey() key} starting
* with the given string.
*
* @param startingWith the string to match
* @return the matcher
*/
static @NonNull NodeMatcher<Node> keyStartsWith(@NonNull String startingWith) {
return LuckPermsProvider.get().getNodeMatcherFactory().keyStartsWith(startingWith);
}
/**
* Gets a {@link NodeMatcher} which matches nodes which are
* {@link Node#equals(Node, NodeEqualityPredicate) equal to} the given {@code other} node
* according to the {@link NodeEqualityPredicate}.
*
* @param other the other node to test against
* @param equalityPredicate the equality predicate
* @param <T> the node type
* @return the matcher
*/
static <T extends Node> @NonNull NodeMatcher<T> equals(@NonNull T other, @NonNull NodeEqualityPredicate equalityPredicate) {
return LuckPermsProvider.get().getNodeMatcherFactory().equals(other, equalityPredicate);
}
/**
* Gets a {@link NodeMatcher} which matches {@link MetaNode}s with the same
* {@link MetaNode#getMetaKey() meta key}.
*
* <p>The {@link String#equalsIgnoreCase(String)} method is used to test key equality.</p>
*
* @param metaKey the meta key
* @return the matcher
*/
static @NonNull NodeMatcher<MetaNode> metaKey(@NonNull String metaKey) {
return LuckPermsProvider.get().getNodeMatcherFactory().metaKey(metaKey);
}
/**
* Gets a {@link NodeMatcher} which matches {@link MetaNode}s with the same
* {@link MetaNode#getMetaKey() meta key}.
*
* <p>The {@link String#equalsIgnoreCase(String)} method is used to test key equality.</p>
*
* @param metaNode the meta node to use for the meta key
* @return the matcher
*/
static @NonNull NodeMatcher<MetaNode> metaKey(@NonNull MetaNode metaNode) {
return metaKey(metaNode.getMetaKey());
}
/**
* Gets a {@link NodeMatcher} which matches {@link Node}s with the same
* type as the given {@link NodeType}.
*
* <p>{@link NodeType#PERMISSION}, {@link NodeType#CHAT_META} and
* {@link NodeType#META_OR_CHAT_META} are not supported by this method.</p>
*
* @param type the node type
* @param <T> the node type
* @return the matcher
*/
static <T extends Node> @NonNull NodeMatcher<T> type(NodeType<? extends T> type) {
return LuckPermsProvider.get().getNodeMatcherFactory().type(type);
}
/**
* Tests to see if the given {@link Node} matches.
*
* @param node the node to test
* @return true if the node matched
*/
@Override
boolean test(@NonNull Node node);
}

View File

@ -0,0 +1,120 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.luckperms.api.node.matcher;
import net.luckperms.api.node.Node;
import net.luckperms.api.node.NodeEqualityPredicate;
import net.luckperms.api.node.NodeType;
import net.luckperms.api.node.types.MetaNode;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* A factory which creates {@link NodeMatcher}s.
*
* @since 5.1
*/
public interface NodeMatcherFactory {
/**
* Gets a {@link NodeMatcher} which matches nodes with the same {@link Node#getKey() key}.
*
* <p>The {@link String#equalsIgnoreCase(String)} method is used to test key equality.</p>
*
* <p>Prefer using the {@link NodeMatcher#key(String)} accessor.</p>
*
* @param key the key
* @return the matcher
*/
@NonNull NodeMatcher<Node> key(@NonNull String key);
/**
* Gets a {@link NodeMatcher} which matches nodes with the same {@link Node#getKey() key}.
*
* <p>The {@link String#equalsIgnoreCase(String)} method is used to test key equality.</p>
*
* <p>Prefer using the {@link NodeMatcher#key(Node)} accessor.</p>
*
* @param node the node to use for the key
* @param <T> the node type
* @return the matcher
*/
<T extends Node> @NonNull NodeMatcher<T> key(@NonNull T node);
/**
* Gets a {@link NodeMatcher} which matches nodes with a {@link Node#getKey() key} starting
* with the given string.
*
* <p>Prefer using the {@link NodeMatcher#keyStartsWith(String)} accessor.</p>
*
* @param startingWith the string to match
* @return the matcher
*/
@NonNull NodeMatcher<Node> keyStartsWith(@NonNull String startingWith);
/**
* Gets a {@link NodeMatcher} which matches nodes which are
* {@link Node#equals(Node, NodeEqualityPredicate) equal to} the given {@code other} node
* according to the {@link NodeEqualityPredicate}.
*
* <p>Prefer using the {@link NodeMatcher#equals(Node, NodeEqualityPredicate)} accessor.</p>
*
* @param other the other node to test against
* @param equalityPredicate the equality predicate
* @param <T> the node type
* @return the matcher
*/
@NonNull <T extends Node> NodeMatcher<T> equals(@NonNull T other, @NonNull NodeEqualityPredicate equalityPredicate);
/**
* Gets a {@link NodeMatcher} which matches {@link MetaNode}s with the same
* {@link MetaNode#getMetaKey() meta key}.
*
* <p>The {@link String#equalsIgnoreCase(String)} method is used to test key equality.</p>
*
* <p>Prefer using the {@link NodeMatcher#metaKey(String)} accessor.</p>
*
* @param metaKey the meta key
* @return the matcher
*/
@NonNull NodeMatcher<MetaNode> metaKey(@NonNull String metaKey);
/**
* Gets a {@link NodeMatcher} which matches {@link Node}s with the same
* type as the given {@link NodeType}.
*
* <p>{@link NodeType#PERMISSION}, {@link NodeType#CHAT_META} and
* {@link NodeType#META_OR_CHAT_META} are not supported by this method.</p>
*
* <p>Prefer using the {@link NodeMatcher#type(NodeType)} accessor.</p>
*
* @param type the node type
* @param <T> the node type
* @return the matcher
*/
<T extends Node> @NonNull NodeMatcher<T> type(NodeType<? extends T> type);
}

View File

@ -31,6 +31,7 @@ import me.lucko.luckperms.common.api.implementation.ApiGroupManager;
import me.lucko.luckperms.common.api.implementation.ApiMessagingService;
import me.lucko.luckperms.common.api.implementation.ApiMetaStackFactory;
import me.lucko.luckperms.common.api.implementation.ApiNodeBuilderRegistry;
import me.lucko.luckperms.common.api.implementation.ApiNodeMatcherFactory;
import me.lucko.luckperms.common.api.implementation.ApiPlatform;
import me.lucko.luckperms.common.api.implementation.ApiQueryOptionsRegistry;
import me.lucko.luckperms.common.api.implementation.ApiTrackManager;
@ -49,6 +50,7 @@ import net.luckperms.api.metastacking.MetaStackFactory;
import net.luckperms.api.model.group.GroupManager;
import net.luckperms.api.model.user.UserManager;
import net.luckperms.api.node.NodeBuilderRegistry;
import net.luckperms.api.node.matcher.NodeMatcherFactory;
import net.luckperms.api.platform.Platform;
import net.luckperms.api.platform.PluginMetadata;
import net.luckperms.api.query.QueryOptionsRegistry;
@ -163,4 +165,9 @@ public class LuckPermsApiProvider implements LuckPerms {
return this.metaStackFactory;
}
@Override
public @NonNull NodeMatcherFactory getNodeMatcherFactory() {
return ApiNodeMatcherFactory.INSTANCE;
}
}

View File

@ -25,21 +25,28 @@
package me.lucko.luckperms.common.api.implementation;
import com.google.common.collect.ImmutableListMultimap;
import me.lucko.luckperms.common.api.ApiUtils;
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
import me.lucko.luckperms.common.bulkupdate.comparison.StandardComparison;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.manager.group.GroupManager;
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
import me.lucko.luckperms.common.node.matcher.StandardNodeMatchers;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.misc.NodeEntry;
import me.lucko.luckperms.common.util.ImmutableCollectors;
import net.luckperms.api.event.cause.CreationCause;
import net.luckperms.api.event.cause.DeletionCause;
import net.luckperms.api.node.HeldNode;
import net.luckperms.api.node.Node;
import net.luckperms.api.node.matcher.NodeMatcher;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
@ -89,10 +96,26 @@ public class ApiGroupManager extends ApiAbstractManager<Group, net.luckperms.api
return this.plugin.getStorage().loadAllGroups();
}
@SuppressWarnings({"unchecked", "rawtypes"})
@Override
@Deprecated
public @NonNull CompletableFuture<List<HeldNode<String>>> getWithPermission(@NonNull String permission) {
Objects.requireNonNull(permission, "permission");
return this.plugin.getStorage().getGroupsWithPermission(Constraint.of(StandardComparison.EQUAL, permission));
return (CompletableFuture) this.plugin.getStorage().getUsersWithPermission(StandardNodeMatchers.key(permission));
}
@SuppressWarnings("unchecked")
@Override
public @NonNull <T extends Node> CompletableFuture<Map<String, Collection<T>>> searchAll(@NonNull NodeMatcher<? extends T> matcher) {
Objects.requireNonNull(matcher, "matcher");
ConstraintNodeMatcher<? extends T> constraint = (ConstraintNodeMatcher<? extends T>) matcher;
return this.plugin.getStorage().getGroupsWithPermission(constraint).thenApply(list -> {
ImmutableListMultimap.Builder<String, T> builder = ImmutableListMultimap.builder();
for (NodeEntry<String, ? extends T> row : list) {
builder.put(row.getHolder(), row.getNode());
}
return builder.build().asMap();
});
}
@Override

View File

@ -0,0 +1,83 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.implementation;
import me.lucko.luckperms.common.node.matcher.StandardNodeMatchers;
import net.luckperms.api.node.Node;
import net.luckperms.api.node.NodeEqualityPredicate;
import net.luckperms.api.node.NodeType;
import net.luckperms.api.node.matcher.NodeMatcher;
import net.luckperms.api.node.matcher.NodeMatcherFactory;
import net.luckperms.api.node.types.MetaNode;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Objects;
public final class ApiNodeMatcherFactory implements NodeMatcherFactory {
public static final ApiNodeMatcherFactory INSTANCE = new ApiNodeMatcherFactory();
private ApiNodeMatcherFactory() {
}
@Override
public @NonNull NodeMatcher<Node> key(@NonNull String key) {
Objects.requireNonNull(key, "key");
return StandardNodeMatchers.key(key);
}
@Override
public @NonNull <T extends Node> NodeMatcher<T> key(@NonNull T node) {
return StandardNodeMatchers.key(node);
}
@Override
public @NonNull NodeMatcher<Node> keyStartsWith(@NonNull String startingWith) {
Objects.requireNonNull(startingWith, "startingWith");
return StandardNodeMatchers.keyStartsWith(startingWith);
}
@Override
public <T extends Node> @NonNull NodeMatcher<T> equals(@NonNull T other, @NonNull NodeEqualityPredicate equalityPredicate) {
Objects.requireNonNull(other, "other");
Objects.requireNonNull(equalityPredicate, "equalityPredicate");
return StandardNodeMatchers.equals(other, equalityPredicate);
}
@Override
public @NonNull NodeMatcher<MetaNode> metaKey(@NonNull String metaKey) {
Objects.requireNonNull(metaKey, "metaKey");
return StandardNodeMatchers.metaKey(metaKey);
}
@Override
public @NonNull <T extends Node> NodeMatcher<T> type(NodeType<? extends T> type) {
Objects.requireNonNull(type, "type");
return StandardNodeMatchers.type(type);
}
}

View File

@ -25,21 +25,28 @@
package me.lucko.luckperms.common.api.implementation;
import com.google.common.collect.ImmutableListMultimap;
import me.lucko.luckperms.common.api.ApiUtils;
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
import me.lucko.luckperms.common.bulkupdate.comparison.StandardComparison;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.model.manager.user.UserManager;
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
import me.lucko.luckperms.common.node.matcher.StandardNodeMatchers;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.misc.NodeEntry;
import me.lucko.luckperms.common.util.ImmutableCollectors;
import net.luckperms.api.model.PlayerSaveResult;
import net.luckperms.api.node.HeldNode;
import net.luckperms.api.node.Node;
import net.luckperms.api.node.matcher.NodeMatcher;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
@ -98,10 +105,26 @@ public class ApiUserManager extends ApiAbstractManager<User, net.luckperms.api.m
return this.plugin.getStorage().getUniqueUsers();
}
@SuppressWarnings({"unchecked", "rawtypes"})
@Override
@Deprecated
public @NonNull CompletableFuture<List<HeldNode<UUID>>> getWithPermission(@NonNull String permission) {
Objects.requireNonNull(permission, "permission");
return this.plugin.getStorage().getUsersWithPermission(Constraint.of(StandardComparison.EQUAL, permission));
return (CompletableFuture) this.plugin.getStorage().getUsersWithPermission(StandardNodeMatchers.key(permission));
}
@SuppressWarnings("unchecked")
@Override
public <T extends Node> @NonNull CompletableFuture<Map<UUID, Collection<T>>> searchAll(@NonNull NodeMatcher<? extends T> matcher) {
Objects.requireNonNull(matcher, "matcher");
ConstraintNodeMatcher<? extends T> constraint = (ConstraintNodeMatcher<? extends T>) matcher;
return this.plugin.getStorage().getUsersWithPermission(constraint).thenApply(list -> {
ImmutableListMultimap.Builder<UUID, T> builder = ImmutableListMultimap.builder();
for (NodeEntry<UUID, ? extends T> row : list) {
builder.put(row.getHolder(), row.getNode());
}
return builder.build().asMap();
});
}
@Override

View File

@ -64,6 +64,9 @@ public enum StandardComparison implements Comparison {
}
};
public static final String WILDCARD = "%";
public static final String WILDCARD_ONE = "_";
private final String symbol;
private final String asSql;
@ -101,8 +104,8 @@ public enum StandardComparison implements Comparison {
expression = expression.replace(".", "\\.");
// convert from SQL LIKE syntax to regex
expression = expression.replace("_", ".");
expression = expression.replace("%", ".*");
expression = expression.replace(WILDCARD_ONE, ".");
expression = expression.replace(WILDCARD, ".*");
return Pattern.compile(expression);
}

View File

@ -27,8 +27,6 @@ package me.lucko.luckperms.common.commands.group;
import com.google.common.collect.Maps;
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
import me.lucko.luckperms.common.bulkupdate.comparison.StandardComparison;
import me.lucko.luckperms.common.cache.LoadingMap;
import me.lucko.luckperms.common.command.CommandResult;
import me.lucko.luckperms.common.command.abstraction.ChildCommand;
@ -42,11 +40,14 @@ import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.HolderType;
import me.lucko.luckperms.common.node.comparator.HeldNodeComparator;
import me.lucko.luckperms.common.node.comparator.NodeEntryComparator;
import me.lucko.luckperms.common.node.factory.NodeCommandFactory;
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
import me.lucko.luckperms.common.node.matcher.StandardNodeMatchers;
import me.lucko.luckperms.common.node.types.Inheritance;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.misc.NodeEntry;
import me.lucko.luckperms.common.util.DurationFormatter;
import me.lucko.luckperms.common.util.Iterators;
import me.lucko.luckperms.common.util.Predicates;
@ -56,7 +57,6 @@ import net.kyori.text.ComponentBuilder;
import net.kyori.text.TextComponent;
import net.kyori.text.event.ClickEvent;
import net.kyori.text.event.HoverEvent;
import net.luckperms.api.node.HeldNode;
import net.luckperms.api.node.Node;
import net.luckperms.api.node.types.InheritanceNode;
@ -80,16 +80,16 @@ public class GroupListMembers extends ChildCommand<Group> {
return CommandResult.NO_PERMISSION;
}
Constraint constraint = Constraint.of(StandardComparison.EQUAL, Inheritance.key(group.getName()));
ConstraintNodeMatcher<InheritanceNode> matcher = StandardNodeMatchers.key(Inheritance.builder(group.getName()).build());
int page = ArgumentParser.parseIntOrElse(0, args, 1);
Message.SEARCH_SEARCHING_MEMBERS.send(sender, group.getName());
List<HeldNode<UUID>> matchedUsers = plugin.getStorage().getUsersWithPermission(constraint).join().stream()
List<NodeEntry<UUID, InheritanceNode>> matchedUsers = plugin.getStorage().getUsersWithPermission(matcher).join().stream()
.filter(n -> n.getNode().getValue())
.collect(Collectors.toList());
List<HeldNode<String>> matchedGroups = plugin.getStorage().getGroupsWithPermission(constraint).join().stream()
List<NodeEntry<String, InheritanceNode>> matchedGroups = plugin.getStorage().getGroupsWithPermission(matcher).join().stream()
.filter(n -> n.getNode().getValue())
.collect(Collectors.toList());
@ -124,28 +124,28 @@ public class GroupListMembers extends ChildCommand<Group> {
return CommandResult.SUCCESS;
}
private static <T extends Comparable<T>> void sendResult(Sender sender, List<HeldNode<T>> results, Function<T, String> lookupFunction, Message headerMessage, HolderType holderType, String label, int page) {
private static <T extends Comparable<T>> void sendResult(Sender sender, List<NodeEntry<T, InheritanceNode>> results, Function<T, String> lookupFunction, Message headerMessage, HolderType holderType, String label, int page) {
results = new ArrayList<>(results);
results.sort(HeldNodeComparator.normal());
results.sort(NodeEntryComparator.normal());
int pageIndex = page - 1;
List<List<HeldNode<T>>> pages = Iterators.divideIterable(results, 15);
List<List<NodeEntry<T, InheritanceNode>>> pages = Iterators.divideIterable(results, 15);
if (pageIndex < 0 || pageIndex >= pages.size()) {
page = 1;
pageIndex = 0;
}
List<HeldNode<T>> content = pages.get(pageIndex);
List<NodeEntry<T, InheritanceNode>> content = pages.get(pageIndex);
List<Map.Entry<String, HeldNode<T>>> mappedContent = content.stream()
List<Map.Entry<String, NodeEntry<T, InheritanceNode>>> mappedContent = content.stream()
.map(hp -> Maps.immutableEntry(lookupFunction.apply(hp.getHolder()), hp))
.collect(Collectors.toList());
// send header
headerMessage.send(sender, page, pages.size(), results.size());
for (Map.Entry<String, HeldNode<T>> ent : mappedContent) {
for (Map.Entry<String, NodeEntry<T, InheritanceNode>> ent : mappedContent) {
String s = "&3> &b" + ent.getKey() + " " + getNodeExpiryString(ent.getValue().getNode()) + MessageUtils.getAppendableNodeContextString(sender.getPlugin().getLocaleManager(), ent.getValue().getNode());
TextComponent message = TextUtils.fromLegacy(s, TextUtils.AMPERSAND_CHAR).toBuilder().applyDeep(makeFancy(ent.getKey(), holderType, label, ent.getValue(), sender.getPlugin())).build();
sender.sendMessage(message);
@ -160,7 +160,7 @@ public class GroupListMembers extends ChildCommand<Group> {
return " &8(&7expires in " + DurationFormatter.LONG.format(node.getExpiryDuration()) + "&8)";
}
private static Consumer<ComponentBuilder<? ,?>> makeFancy(String holderName, HolderType holderType, String label, HeldNode<?> perm, LuckPermsPlugin plugin) {
private static Consumer<ComponentBuilder<? ,?>> makeFancy(String holderName, HolderType holderType, String label, NodeEntry<?, ?> perm, LuckPermsPlugin plugin) {
HoverEvent hoverEvent = HoverEvent.showText(TextUtils.fromLegacy(TextUtils.joinNewline(
"&3> &b" + ((InheritanceNode) perm.getNode()).getGroupName(),
" ",

View File

@ -43,10 +43,13 @@ import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.model.HolderType;
import me.lucko.luckperms.common.node.comparator.HeldNodeComparator;
import me.lucko.luckperms.common.node.comparator.NodeEntryComparator;
import me.lucko.luckperms.common.node.factory.NodeCommandFactory;
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
import me.lucko.luckperms.common.node.matcher.StandardNodeMatchers;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.misc.NodeEntry;
import me.lucko.luckperms.common.util.DurationFormatter;
import me.lucko.luckperms.common.util.Iterators;
import me.lucko.luckperms.common.util.Predicates;
@ -56,7 +59,6 @@ import net.kyori.text.ComponentBuilder;
import net.kyori.text.TextComponent;
import net.kyori.text.event.ClickEvent;
import net.kyori.text.event.HoverEvent;
import net.luckperms.api.node.HeldNode;
import net.luckperms.api.node.Node;
import java.util.ArrayList;
@ -80,13 +82,13 @@ public class SearchCommand extends SingleCommand {
args.add(0, "==");
}
Constraint query = Constraint.of(comparison, args.get(1));
ConstraintNodeMatcher<Node> matcher = StandardNodeMatchers.of(Constraint.of(comparison, args.get(1)));
int page = ArgumentParser.parseIntOrElse(2, args, 1);
Message.SEARCH_SEARCHING.send(sender, query);
Message.SEARCH_SEARCHING.send(sender, matcher);
List<HeldNode<UUID>> matchedUsers = plugin.getStorage().getUsersWithPermission(query).join();
List<HeldNode<String>> matchedGroups = plugin.getStorage().getGroupsWithPermission(query).join();
List<NodeEntry<UUID, Node>> matchedUsers = plugin.getStorage().getUsersWithPermission(matcher).join();
List<NodeEntry<String, Node>> matchedGroups = plugin.getStorage().getGroupsWithPermission(matcher).join();
int users = matchedUsers.size();
int groups = matchedGroups.size();
@ -126,28 +128,28 @@ public class SearchCommand extends SingleCommand {
.complete(args);
}
private static <T extends Comparable<T>> void sendResult(Sender sender, List<HeldNode<T>> results, Function<T, String> lookupFunction, Message headerMessage, HolderType holderType, String label, int page, Comparison comparison) {
private static <T extends Comparable<T>> void sendResult(Sender sender, List<NodeEntry<T, Node>> results, Function<T, String> lookupFunction, Message headerMessage, HolderType holderType, String label, int page, Comparison comparison) {
results = new ArrayList<>(results);
results.sort(HeldNodeComparator.normal());
results.sort(NodeEntryComparator.normal());
int pageIndex = page - 1;
List<List<HeldNode<T>>> pages = Iterators.divideIterable(results, 15);
List<List<NodeEntry<T, Node>>> pages = Iterators.divideIterable(results, 15);
if (pageIndex < 0 || pageIndex >= pages.size()) {
page = 1;
pageIndex = 0;
}
List<HeldNode<T>> content = pages.get(pageIndex);
List<NodeEntry<T, Node>> content = pages.get(pageIndex);
List<Map.Entry<String, HeldNode<T>>> mappedContent = content.stream()
List<Map.Entry<String, NodeEntry<T, Node>>> mappedContent = content.stream()
.map(hp -> Maps.immutableEntry(lookupFunction.apply(hp.getHolder()), hp))
.collect(Collectors.toList());
// send header
headerMessage.send(sender, page, pages.size(), results.size());
for (Map.Entry<String, HeldNode<T>> ent : mappedContent) {
for (Map.Entry<String, NodeEntry<T, Node>> ent : mappedContent) {
// only show the permission in the results if the comparison isn't equals
String permission = "";
if (comparison != StandardComparison.EQUAL) {
@ -168,7 +170,7 @@ public class SearchCommand extends SingleCommand {
return " &8(&7expires in " + DurationFormatter.LONG.format(node.getExpiryDuration()) + "&8)";
}
private static Consumer<ComponentBuilder<?, ?>> makeFancy(String holderName, HolderType holderType, String label, HeldNode<?> perm, LuckPermsPlugin plugin) {
private static Consumer<ComponentBuilder<?, ?>> makeFancy(String holderName, HolderType holderType, String label, NodeEntry<?, ?> perm, LuckPermsPlugin plugin) {
HoverEvent hoverEvent = HoverEvent.showText(TextUtils.fromLegacy(TextUtils.joinNewline(
"&3> " + (perm.getNode().getValue() ? "&a" : "&c") + perm.getNode().getKey(),
" ",

View File

@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.node.model;
package me.lucko.luckperms.common.model;
import net.luckperms.api.model.PermissionHolder;
import net.luckperms.api.node.metadata.types.InheritanceOriginMetadata;

View File

@ -34,7 +34,6 @@ import me.lucko.luckperms.common.cache.Cache;
import me.lucko.luckperms.common.context.ContextSetComparator;
import me.lucko.luckperms.common.node.comparator.NodeComparator;
import me.lucko.luckperms.common.node.comparator.NodeWithContextComparator;
import me.lucko.luckperms.common.node.model.InheritanceOrigin;
import me.lucko.luckperms.common.query.QueryOptionsImpl;
import net.luckperms.api.context.ContextSet;

View File

@ -25,22 +25,22 @@
package me.lucko.luckperms.common.node.comparator;
import net.luckperms.api.node.HeldNode;
import me.lucko.luckperms.common.storage.misc.NodeEntry;
import java.util.Comparator;
public class HeldNodeComparator<T extends Comparable<T>> implements Comparator<HeldNode<T>> {
public class NodeEntryComparator<T extends Comparable<T>> implements Comparator<NodeEntry<T, ?>> {
public static <T extends Comparable<T>> Comparator<? super HeldNode<T>> normal() {
return new HeldNodeComparator<>();
public static <T extends Comparable<T>> Comparator<? super NodeEntry<T, ?>> normal() {
return new NodeEntryComparator<>();
}
public static <T extends Comparable<T>> Comparator<? super HeldNode<T>> reverse() {
return HeldNodeComparator.<T>normal().reversed();
public static <T extends Comparable<T>> Comparator<? super NodeEntry<T, ?>> reverse() {
return NodeEntryComparator.<T>normal().reversed();
}
@Override
public int compare(HeldNode<T> o1, HeldNode<T> o2) {
public int compare(NodeEntry<T, ?> o1, NodeEntry<T, ?> o2) {
int i = NodeWithContextComparator.normal().compare(o1.getNode(), o2.getNode());
if (i != 0) {
return i;

View File

@ -0,0 +1,60 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.common.node.matcher;
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
import net.luckperms.api.node.Node;
import net.luckperms.api.node.matcher.NodeMatcher;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Abstract implementation of {@link NodeMatcher} backed by a {@link Constraint}.
*/
public abstract class ConstraintNodeMatcher<T extends Node> implements NodeMatcher<T> {
private final Constraint constraint;
protected ConstraintNodeMatcher(Constraint constraint) {
this.constraint = constraint;
}
public Constraint getConstraint() {
return this.constraint;
}
public abstract @Nullable T filterConstraintMatch(@NonNull Node node);
public @Nullable T match(Node node) {
return getConstraint().eval(node.getKey()) ? filterConstraintMatch(node) : null;
}
@Override
public boolean test(@NonNull Node node) {
return match(node) != null;
}
}

View File

@ -0,0 +1,157 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.common.node.matcher;
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
import me.lucko.luckperms.common.bulkupdate.comparison.StandardComparison;
import me.lucko.luckperms.common.node.AbstractNode;
import me.lucko.luckperms.common.node.types.DisplayName;
import me.lucko.luckperms.common.node.types.Inheritance;
import me.lucko.luckperms.common.node.types.Meta;
import me.lucko.luckperms.common.node.types.Prefix;
import me.lucko.luckperms.common.node.types.RegexPermission;
import me.lucko.luckperms.common.node.types.Suffix;
import me.lucko.luckperms.common.node.types.Weight;
import net.luckperms.api.node.Node;
import net.luckperms.api.node.NodeEqualityPredicate;
import net.luckperms.api.node.NodeType;
import net.luckperms.api.node.types.MetaNode;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class StandardNodeMatchers {
private StandardNodeMatchers() {}
public static ConstraintNodeMatcher<Node> of(Constraint constraint) {
return new Generic(constraint);
}
public static ConstraintNodeMatcher<Node> key(String key) {
return new Generic(Constraint.of(StandardComparison.EQUAL, key));
}
public static <T extends Node> ConstraintNodeMatcher<T> key(T node) {
return new NodeEquals<>(node, NodeEqualityPredicate.ONLY_KEY);
}
public static ConstraintNodeMatcher<Node> keyStartsWith(String startsWith) {
return new Generic(Constraint.of(StandardComparison.SIMILAR, startsWith + StandardComparison.WILDCARD));
}
public static <T extends Node> ConstraintNodeMatcher<T> equals(T other, NodeEqualityPredicate equalityPredicate) {
return new NodeEquals<>(other, equalityPredicate);
}
public static ConstraintNodeMatcher<MetaNode> metaKey(String metaKey) {
return new MetaKeyEquals(metaKey);
}
public static <T extends Node> ConstraintNodeMatcher<T> type(NodeType<? extends T> type) {
return new TypeEquals<>(type);
}
private static class Generic extends ConstraintNodeMatcher<Node> {
Generic(Constraint constraint) {
super(constraint);
}
@Nullable
@Override
public Node filterConstraintMatch(@NonNull Node node) {
return node;
}
}
private static final class NodeEquals<T extends Node> extends ConstraintNodeMatcher<T> {
private final T node;
private final NodeEqualityPredicate equalityPredicate;
NodeEquals(T node, NodeEqualityPredicate equalityPredicate) {
super(Constraint.of(StandardComparison.EQUAL, node.getKey()));
this.node = node;
this.equalityPredicate = equalityPredicate;
}
@SuppressWarnings("unchecked")
@Override
public @Nullable T filterConstraintMatch(@NonNull Node node) {
if (this.equalityPredicate == NodeEqualityPredicate.ONLY_KEY || this.node.equals(node, this.equalityPredicate)) {
return (T) node;
}
return null;
}
}
private static final class MetaKeyEquals extends ConstraintNodeMatcher<MetaNode> {
MetaKeyEquals(String metaKey) {
super(Constraint.of(StandardComparison.SIMILAR, Meta.key(metaKey, StandardComparison.WILDCARD)));
}
@Nullable
@Override
public MetaNode filterConstraintMatch(@NonNull Node node) {
return NodeType.META.tryCast(node).orElse(null);
}
}
private static final class TypeEquals<T extends Node> extends ConstraintNodeMatcher<T> {
private final NodeType<? extends T> type;
protected TypeEquals(NodeType<? extends T> type) {
super(getConstraintForType(type));
this.type = type;
}
@Nullable
@Override
public T filterConstraintMatch(@NonNull Node node) {
return this.type.tryCast(node).orElse(null);
}
private static Constraint getConstraintForType(NodeType<?> type) {
if (type == NodeType.REGEX_PERMISSION) {
return Constraint.of(StandardComparison.SIMILAR, RegexPermission.key(StandardComparison.WILDCARD));
} else if (type == NodeType.INHERITANCE) {
return Constraint.of(StandardComparison.SIMILAR, Inheritance.key(StandardComparison.WILDCARD));
} else if (type == NodeType.PREFIX) {
return Constraint.of(StandardComparison.SIMILAR, Prefix.NODE_MARKER + StandardComparison.WILDCARD + AbstractNode.NODE_SEPARATOR + StandardComparison.WILDCARD);
} else if (type == NodeType.SUFFIX) {
return Constraint.of(StandardComparison.SIMILAR, Suffix.NODE_MARKER + StandardComparison.WILDCARD + AbstractNode.NODE_SEPARATOR + StandardComparison.WILDCARD);
} else if (type == NodeType.META) {
return Constraint.of(StandardComparison.SIMILAR, Meta.key(StandardComparison.WILDCARD, StandardComparison.WILDCARD));
} else if (type == NodeType.WEIGHT) {
return Constraint.of(StandardComparison.SIMILAR, Weight.NODE_MARKER + StandardComparison.WILDCARD);
} else if (type == NodeType.DISPLAY_NAME) {
return Constraint.of(StandardComparison.SIMILAR, DisplayName.key(StandardComparison.WILDCARD));
}
throw new IllegalArgumentException("Unable to create a NodeMatcher for NodeType " + type.name());
}
}
}

View File

@ -29,20 +29,21 @@ import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.actionlog.Log;
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
import me.lucko.luckperms.common.storage.implementation.split.SplitStorage;
import me.lucko.luckperms.common.storage.misc.NodeEntry;
import me.lucko.luckperms.common.util.Throwing;
import net.luckperms.api.actionlog.Action;
import net.luckperms.api.event.cause.CreationCause;
import net.luckperms.api.event.cause.DeletionCause;
import net.luckperms.api.model.PlayerSaveResult;
import net.luckperms.api.node.HeldNode;
import net.luckperms.api.node.Node;
import java.util.Collection;
import java.util.Collections;
@ -161,9 +162,9 @@ public class Storage {
return makeFuture(this.implementation::getUniqueUsers);
}
public CompletableFuture<List<HeldNode<UUID>>> getUsersWithPermission(Constraint constraint) {
public <N extends Node> CompletableFuture<List<NodeEntry<UUID, N>>> getUsersWithPermission(ConstraintNodeMatcher<N> constraint) {
return makeFuture(() -> {
List<HeldNode<UUID>> result = this.implementation.getUsersWithPermission(constraint);
List<NodeEntry<UUID, N>> result = this.implementation.getUsersWithPermission(constraint);
result.removeIf(entry -> entry.getNode().hasExpired());
return ImmutableList.copyOf(result);
});
@ -207,9 +208,9 @@ public class Storage {
});
}
public CompletableFuture<List<HeldNode<String>>> getGroupsWithPermission(Constraint constraint) {
public <N extends Node> CompletableFuture<List<NodeEntry<String, N>>> getGroupsWithPermission(ConstraintNodeMatcher<N> constraint) {
return makeFuture(() -> {
List<HeldNode<String>> result = this.implementation.getGroupsWithPermission(constraint);
List<NodeEntry<String, N>> result = this.implementation.getGroupsWithPermission(constraint);
result.removeIf(entry -> entry.getNode().hasExpired());
return ImmutableList.copyOf(result);
});

View File

@ -27,15 +27,16 @@ package me.lucko.luckperms.common.storage.implementation;
import me.lucko.luckperms.common.actionlog.Log;
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.misc.NodeEntry;
import net.luckperms.api.actionlog.Action;
import net.luckperms.api.model.PlayerSaveResult;
import net.luckperms.api.node.HeldNode;
import net.luckperms.api.node.Node;
import org.checkerframework.checker.nullness.qual.Nullable;
@ -71,7 +72,7 @@ public interface StorageImplementation {
Set<UUID> getUniqueUsers() throws Exception;
List<HeldNode<UUID>> getUsersWithPermission(Constraint constraint) throws Exception;
<N extends Node> List<NodeEntry<UUID, N>> getUsersWithPermission(ConstraintNodeMatcher<N> constraint) throws Exception;
Group createAndLoadGroup(String name) throws Exception;
@ -83,7 +84,7 @@ public interface StorageImplementation {
void deleteGroup(Group group) throws Exception;
List<HeldNode<String>> getGroupsWithPermission(Constraint constraint) throws Exception;
<N extends Node> List<NodeEntry<String, N>> getGroupsWithPermission(ConstraintNodeMatcher<N> constraint) throws Exception;
Track createAndLoadTrack(String name) throws Exception;

View File

@ -26,14 +26,13 @@
package me.lucko.luckperms.common.storage.implementation.file;
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
import me.lucko.luckperms.common.node.model.HeldNodeImpl;
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.implementation.file.loader.ConfigurateLoader;
import me.lucko.luckperms.common.storage.implementation.file.watcher.FileWatcher;
import me.lucko.luckperms.common.storage.misc.NodeEntry;
import me.lucko.luckperms.common.util.Iterators;
import net.luckperms.api.node.HeldNode;
import net.luckperms.api.node.Node;
import ninja.leaping.configurate.ConfigurationNode;
@ -262,8 +261,8 @@ public class CombinedConfigurateStorage extends AbstractConfigurateStorage {
}
@Override
public List<HeldNode<UUID>> getUsersWithPermission(Constraint constraint) throws Exception {
List<HeldNode<UUID>> held = new ArrayList<>();
public <N extends Node> List<NodeEntry<UUID, N>> getUsersWithPermission(ConstraintNodeMatcher<N> constraint) throws Exception {
List<NodeEntry<UUID, N>> held = new ArrayList<>();
this.usersLoader.apply(false, true, root -> {
for (Map.Entry<Object, ? extends ConfigurationNode> entry : root.getChildrenMap().entrySet()) {
try {
@ -272,10 +271,10 @@ public class CombinedConfigurateStorage extends AbstractConfigurateStorage {
Set<Node> nodes = readNodes(object);
for (Node e : nodes) {
if (!constraint.eval(e.getKey())) {
continue;
N match = constraint.match(e);
if (match != null) {
held.add(NodeEntry.of(holder, match));
}
held.add(HeldNodeImpl.of(holder, e));
}
} catch (Exception e) {
e.printStackTrace();
@ -302,8 +301,8 @@ public class CombinedConfigurateStorage extends AbstractConfigurateStorage {
}
@Override
public List<HeldNode<String>> getGroupsWithPermission(Constraint constraint) throws Exception {
List<HeldNode<String>> held = new ArrayList<>();
public <N extends Node> List<NodeEntry<String, N>> getGroupsWithPermission(ConstraintNodeMatcher<N> constraint) throws Exception {
List<NodeEntry<String, N>> held = new ArrayList<>();
this.groupsLoader.apply(false, true, root -> {
for (Map.Entry<Object, ? extends ConfigurationNode> entry : root.getChildrenMap().entrySet()) {
try {
@ -312,10 +311,10 @@ public class CombinedConfigurateStorage extends AbstractConfigurateStorage {
Set<Node> nodes = readNodes(object);
for (Node e : nodes) {
if (!constraint.eval(e.getKey())) {
continue;
N match = constraint.match(e);
if (match != null) {
held.add(NodeEntry.of(holder, match));
}
held.add(HeldNodeImpl.of(holder, e));
}
} catch (Exception e) {
e.printStackTrace();

View File

@ -26,17 +26,16 @@
package me.lucko.luckperms.common.storage.implementation.file;
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.node.model.HeldNodeImpl;
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.implementation.file.loader.ConfigurateLoader;
import me.lucko.luckperms.common.storage.implementation.file.watcher.FileWatcher;
import me.lucko.luckperms.common.storage.misc.NodeEntry;
import me.lucko.luckperms.common.util.Iterators;
import me.lucko.luckperms.common.util.MoreFiles;
import me.lucko.luckperms.common.util.Uuids;
import net.luckperms.api.node.HeldNode;
import net.luckperms.api.node.Node;
import ninja.leaping.configurate.ConfigurationNode;
@ -255,8 +254,8 @@ public class SeparatedConfigurateStorage extends AbstractConfigurateStorage {
}
@Override
public List<HeldNode<UUID>> getUsersWithPermission(Constraint constraint) throws Exception {
List<HeldNode<UUID>> held = new ArrayList<>();
public <N extends Node> List<NodeEntry<UUID, N>> getUsersWithPermission(ConstraintNodeMatcher<N> constraint) throws Exception {
List<NodeEntry<UUID, N>> held = new ArrayList<>();
try (Stream<Path> stream = Files.list(getDirectory(StorageLocation.USER))) {
stream.filter(getFileTypeFilter())
.forEach(file -> {
@ -267,10 +266,10 @@ public class SeparatedConfigurateStorage extends AbstractConfigurateStorage {
UUID holder = UUID.fromString(fileName.substring(0, fileName.length() - this.fileExtension.length()));
Set<Node> nodes = readNodes(object);
for (Node e : nodes) {
if (!constraint.eval(e.getKey())) {
continue;
N match = constraint.match(e);
if (match != null) {
held.add(NodeEntry.of(holder, match));
}
held.add(HeldNodeImpl.of(holder, e));
}
} catch (Exception e) {
throw reportException(file.getFileName().toString(), e);
@ -298,8 +297,8 @@ public class SeparatedConfigurateStorage extends AbstractConfigurateStorage {
}
@Override
public List<HeldNode<String>> getGroupsWithPermission(Constraint constraint) throws Exception {
List<HeldNode<String>> held = new ArrayList<>();
public <N extends Node> List<NodeEntry<String, N>> getGroupsWithPermission(ConstraintNodeMatcher<N> constraint) throws Exception {
List<NodeEntry<String, N>> held = new ArrayList<>();
try (Stream<Path> stream = Files.list(getDirectory(StorageLocation.GROUP))) {
stream.filter(getFileTypeFilter())
.forEach(file -> {
@ -310,10 +309,10 @@ public class SeparatedConfigurateStorage extends AbstractConfigurateStorage {
String holder = fileName.substring(0, fileName.length() - this.fileExtension.length());
Set<Node> nodes = readNodes(object);
for (Node e : nodes) {
if (!constraint.eval(e.getKey())) {
continue;
N match = constraint.match(e);
if (match != null) {
held.add(NodeEntry.of(holder, match));
}
held.add(HeldNodeImpl.of(holder, e));
}
} catch (Exception e) {
throw reportException(file.getFileName().toString(), e);

View File

@ -40,16 +40,16 @@ import com.mongodb.client.model.ReplaceOptions;
import me.lucko.luckperms.common.actionlog.Log;
import me.lucko.luckperms.common.actionlog.LoggedAction;
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
import me.lucko.luckperms.common.context.contextset.MutableContextSetImpl;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.model.manager.group.GroupManager;
import me.lucko.luckperms.common.node.factory.NodeBuilders;
import me.lucko.luckperms.common.node.model.HeldNodeImpl;
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
import me.lucko.luckperms.common.storage.misc.NodeEntry;
import me.lucko.luckperms.common.storage.misc.PlayerSaveResultImpl;
import me.lucko.luckperms.common.storage.misc.StorageCredentials;
import me.lucko.luckperms.common.util.Iterators;
@ -61,7 +61,6 @@ import net.luckperms.api.context.DefaultContextKeys;
import net.luckperms.api.context.MutableContextSet;
import net.luckperms.api.model.PlayerSaveResult;
import net.luckperms.api.model.data.DataType;
import net.luckperms.api.node.HeldNode;
import net.luckperms.api.node.Node;
import net.luckperms.api.node.NodeBuilder;
@ -361,8 +360,8 @@ public class MongoStorage implements StorageImplementation {
}
@Override
public List<HeldNode<UUID>> getUsersWithPermission(Constraint constraint) {
List<HeldNode<UUID>> held = new ArrayList<>();
public <N extends Node> List<NodeEntry<UUID, N>> getUsersWithPermission(ConstraintNodeMatcher<N> constraint) throws Exception {
List<NodeEntry<UUID, N>> held = new ArrayList<>();
MongoCollection<Document> c = this.database.getCollection(this.prefix + "users");
try (MongoCursor<Document> cursor = c.find().iterator()) {
while (cursor.hasNext()) {
@ -371,10 +370,10 @@ public class MongoStorage implements StorageImplementation {
Set<Node> nodes = new HashSet<>(nodesFromDoc(d));
for (Node e : nodes) {
if (!constraint.eval(e.getKey())) {
continue;
N match = constraint.match(e);
if (match != null) {
held.add(NodeEntry.of(holder, match));
}
held.add(HeldNodeImpl.of(holder, e));
}
}
}
@ -471,8 +470,8 @@ public class MongoStorage implements StorageImplementation {
}
@Override
public List<HeldNode<String>> getGroupsWithPermission(Constraint constraint) {
List<HeldNode<String>> held = new ArrayList<>();
public <N extends Node> List<NodeEntry<String, N>> getGroupsWithPermission(ConstraintNodeMatcher<N> constraint) throws Exception {
List<NodeEntry<String, N>> held = new ArrayList<>();
MongoCollection<Document> c = this.database.getCollection(this.prefix + "groups");
try (MongoCursor<Document> cursor = c.find().iterator()) {
while (cursor.hasNext()) {
@ -481,10 +480,10 @@ public class MongoStorage implements StorageImplementation {
Set<Node> nodes = new HashSet<>(nodesFromDoc(d));
for (Node e : nodes) {
if (!constraint.eval(e.getKey())) {
continue;
N match = constraint.match(e);
if (match != null) {
held.add(NodeEntry.of(holder, match));
}
held.add(HeldNodeImpl.of(holder, e));
}
}
}

View File

@ -29,17 +29,18 @@ import com.google.common.collect.ImmutableMap;
import me.lucko.luckperms.common.actionlog.Log;
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.StorageType;
import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
import me.lucko.luckperms.common.storage.misc.NodeEntry;
import net.luckperms.api.actionlog.Action;
import net.luckperms.api.model.PlayerSaveResult;
import net.luckperms.api.node.HeldNode;
import net.luckperms.api.node.Node;
import java.util.LinkedHashMap;
import java.util.List;
@ -153,7 +154,7 @@ public class SplitStorage implements StorageImplementation {
}
@Override
public List<HeldNode<UUID>> getUsersWithPermission(Constraint constraint) throws Exception {
public <N extends Node> List<NodeEntry<UUID, N>> getUsersWithPermission(ConstraintNodeMatcher<N> constraint) throws Exception {
return implFor(SplitStorageType.USER).getUsersWithPermission(constraint);
}
@ -183,7 +184,7 @@ public class SplitStorage implements StorageImplementation {
}
@Override
public List<HeldNode<String>> getGroupsWithPermission(Constraint constraint) throws Exception {
public <N extends Node> List<NodeEntry<String, N>> getGroupsWithPermission(ConstraintNodeMatcher<N> constraint) throws Exception {
return implFor(SplitStorageType.GROUP).getGroupsWithPermission(constraint);
}

View File

@ -32,16 +32,16 @@ import me.lucko.luckperms.common.actionlog.Log;
import me.lucko.luckperms.common.actionlog.LoggedAction;
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
import me.lucko.luckperms.common.bulkupdate.PreparedStatementBuilder;
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
import me.lucko.luckperms.common.context.ContextSetJsonSerializer;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.model.manager.group.GroupManager;
import me.lucko.luckperms.common.node.model.HeldNodeImpl;
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
import me.lucko.luckperms.common.storage.implementation.sql.connection.ConnectionFactory;
import me.lucko.luckperms.common.storage.misc.NodeEntry;
import me.lucko.luckperms.common.storage.misc.PlayerSaveResultImpl;
import me.lucko.luckperms.common.util.Iterators;
import me.lucko.luckperms.common.util.gson.GsonProvider;
@ -49,7 +49,6 @@ import me.lucko.luckperms.common.util.gson.GsonProvider;
import net.luckperms.api.actionlog.Action;
import net.luckperms.api.model.PlayerSaveResult;
import net.luckperms.api.model.data.DataType;
import net.luckperms.api.node.HeldNode;
import net.luckperms.api.node.Node;
import java.io.IOException;
@ -363,18 +362,22 @@ public class SqlStorage implements StorageImplementation {
}
@Override
public List<HeldNode<UUID>> getUsersWithPermission(Constraint constraint) throws SQLException {
public <N extends Node> List<NodeEntry<UUID, N>> getUsersWithPermission(ConstraintNodeMatcher<N> constraint) throws SQLException {
PreparedStatementBuilder builder = new PreparedStatementBuilder().append(USER_PERMISSIONS_SELECT_PERMISSION);
constraint.appendSql(builder, "permission");
constraint.getConstraint().appendSql(builder, "permission");
List<HeldNode<UUID>> held = new ArrayList<>();
List<NodeEntry<UUID, N>> held = new ArrayList<>();
try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = builder.build(c, this.statementProcessor)) {
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
UUID holder = UUID.fromString(rs.getString("uuid"));
Node node = readNode(rs).toNode();
held.add(HeldNodeImpl.of(holder, node));
N match = constraint.filterConstraintMatch(node);
if (match != null) {
held.add(NodeEntry.of(holder, match));
}
}
}
}
@ -490,18 +493,22 @@ public class SqlStorage implements StorageImplementation {
}
@Override
public List<HeldNode<String>> getGroupsWithPermission(Constraint constraint) throws SQLException {
public <N extends Node> List<NodeEntry<String, N>> getGroupsWithPermission(ConstraintNodeMatcher<N> constraint) throws SQLException {
PreparedStatementBuilder builder = new PreparedStatementBuilder().append(GROUP_PERMISSIONS_SELECT_PERMISSION);
constraint.appendSql(builder, "permission");
constraint.getConstraint().appendSql(builder, "permission");
List<HeldNode<String>> held = new ArrayList<>();
List<NodeEntry<String, N>> held = new ArrayList<>();
try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = builder.build(c, this.statementProcessor)) {
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
String holder = rs.getString("name");
Node node = readNode(rs).toNode();
held.add(HeldNodeImpl.of(holder, node));
N match = constraint.filterConstraintMatch(node);
if (match != null) {
held.add(NodeEntry.of(holder, match));
}
}
}
}

View File

@ -23,42 +23,42 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.node.model;
package me.lucko.luckperms.common.storage.misc;
import net.luckperms.api.node.HeldNode;
import net.luckperms.api.node.Node;
import org.checkerframework.checker.nullness.qual.NonNull;
public final class HeldNodeImpl<T extends Comparable<T>> implements HeldNode<T> {
public final class NodeEntry<H extends Comparable<H>, N extends Node> implements HeldNode<H> {
public static <T extends Comparable<T>> HeldNodeImpl<T> of(T holder, Node node) {
return new HeldNodeImpl<>(holder, node);
public static <H extends Comparable<H>, N extends Node> NodeEntry<H, N> of(H holder, N node) {
return new NodeEntry<>(holder, node);
}
private final T holder;
private final Node node;
private final H holder;
private final N node;
private HeldNodeImpl(T holder, Node node) {
private NodeEntry(H holder, N node) {
this.holder = holder;
this.node = node;
}
@Override
public @NonNull Node getNode() {
return this.node;
public @NonNull H getHolder() {
return this.holder;
}
@Override
public @NonNull T getHolder() {
return this.holder;
public @NonNull N getNode() {
return this.node;
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof HeldNodeImpl)) return false;
final HeldNodeImpl<?> other = (HeldNodeImpl<?>) o;
if (!(o instanceof NodeEntry)) return false;
final NodeEntry<?, ?> other = (NodeEntry<?, ?>) o;
return this.getHolder().equals(other.getHolder()) && this.getNode().equals(other.getNode());
}

View File

@ -32,11 +32,11 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
import me.lucko.luckperms.common.bulkupdate.comparison.StandardComparison;
import me.lucko.luckperms.common.context.contextset.ImmutableContextSetImpl;
import me.lucko.luckperms.common.model.manager.group.AbstractGroupManager;
import me.lucko.luckperms.common.node.matcher.StandardNodeMatchers;
import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.storage.misc.NodeEntry;
import me.lucko.luckperms.common.util.ImmutableCollectors;
import me.lucko.luckperms.sponge.LPSpongePlugin;
import me.lucko.luckperms.sponge.model.SpongeGroup;
@ -48,7 +48,7 @@ import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import net.luckperms.api.context.ImmutableContextSet;
import net.luckperms.api.event.cause.CreationCause;
import net.luckperms.api.node.HeldNode;
import net.luckperms.api.node.Node;
import net.luckperms.api.util.Tristate;
import org.spongepowered.api.service.permission.PermissionService;
@ -193,8 +193,8 @@ public class SpongeGroupManager extends AbstractGroupManager<SpongeGroup> implem
return CompletableFuture.supplyAsync(() -> {
ImmutableMap.Builder<LPSubjectReference, Boolean> builder = ImmutableMap.builder();
List<HeldNode<String>> lookup = this.plugin.getStorage().getGroupsWithPermission(Constraint.of(StandardComparison.EQUAL, permission)).join();
for (HeldNode<String> holder : lookup) {
List<NodeEntry<String, Node>> lookup = this.plugin.getStorage().getGroupsWithPermission(StandardNodeMatchers.key(permission)).join();
for (NodeEntry<String, Node> holder : lookup) {
if (holder.getNode().getContexts().equals(ImmutableContextSetImpl.EMPTY)) {
builder.put(getService().getReferenceFactory().obtain(getIdentifier(), holder.getHolder()), holder.getNode().getValue());
}
@ -209,8 +209,8 @@ public class SpongeGroupManager extends AbstractGroupManager<SpongeGroup> implem
return CompletableFuture.supplyAsync(() -> {
ImmutableMap.Builder<LPSubjectReference, Boolean> builder = ImmutableMap.builder();
List<HeldNode<String>> lookup = this.plugin.getStorage().getGroupsWithPermission(Constraint.of(StandardComparison.EQUAL, permission)).join();
for (HeldNode<String> holder : lookup) {
List<NodeEntry<String, Node>> lookup = this.plugin.getStorage().getGroupsWithPermission(StandardNodeMatchers.key(permission)).join();
for (NodeEntry<String, Node> holder : lookup) {
if (holder.getNode().getContexts().equals(contexts)) {
builder.put(getService().getReferenceFactory().obtain(getIdentifier(), holder.getHolder()), holder.getNode().getValue());
}

View File

@ -32,11 +32,11 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
import me.lucko.luckperms.common.bulkupdate.comparison.StandardComparison;
import me.lucko.luckperms.common.context.contextset.ImmutableContextSetImpl;
import me.lucko.luckperms.common.model.manager.user.AbstractUserManager;
import me.lucko.luckperms.common.model.manager.user.UserHousekeeper;
import me.lucko.luckperms.common.node.matcher.StandardNodeMatchers;
import me.lucko.luckperms.common.storage.misc.NodeEntry;
import me.lucko.luckperms.common.util.ImmutableCollectors;
import me.lucko.luckperms.common.util.Uuids;
import me.lucko.luckperms.sponge.LPSpongePlugin;
@ -48,7 +48,7 @@ import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import net.luckperms.api.context.ImmutableContextSet;
import net.luckperms.api.node.HeldNode;
import net.luckperms.api.node.Node;
import net.luckperms.api.util.Tristate;
import org.spongepowered.api.service.permission.PermissionService;
@ -212,8 +212,8 @@ public class SpongeUserManager extends AbstractUserManager<SpongeUser> implement
return CompletableFuture.supplyAsync(() -> {
ImmutableMap.Builder<LPSubjectReference, Boolean> builder = ImmutableMap.builder();
List<HeldNode<UUID>> lookup = this.plugin.getStorage().getUsersWithPermission(Constraint.of(StandardComparison.EQUAL, permission)).join();
for (HeldNode<UUID> holder : lookup) {
List<NodeEntry<UUID, Node>> lookup = this.plugin.getStorage().getUsersWithPermission(StandardNodeMatchers.key(permission)).join();
for (NodeEntry<UUID, Node> holder : lookup) {
if (holder.getNode().getContexts().equals(ImmutableContextSetImpl.EMPTY)) {
builder.put(getService().getReferenceFactory().obtain(getIdentifier(), holder.getHolder().toString()), holder.getNode().getValue());
}
@ -228,8 +228,8 @@ public class SpongeUserManager extends AbstractUserManager<SpongeUser> implement
return CompletableFuture.supplyAsync(() -> {
ImmutableMap.Builder<LPSubjectReference, Boolean> builder = ImmutableMap.builder();
List<HeldNode<UUID>> lookup = this.plugin.getStorage().getUsersWithPermission(Constraint.of(StandardComparison.EQUAL, permission)).join();
for (HeldNode<UUID> holder : lookup) {
List<NodeEntry<UUID, Node>> lookup = this.plugin.getStorage().getUsersWithPermission(StandardNodeMatchers.key(permission)).join();
for (NodeEntry<UUID, Node> holder : lookup) {
if (holder.getNode().getContexts().equals(contexts)) {
builder.put(getService().getReferenceFactory().obtain(getIdentifier(), holder.getHolder().toString()), holder.getNode().getValue());
}