diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiPermissionHolder.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiPermissionHolder.java index 7ea39ace0..d980f64e7 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiPermissionHolder.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiPermissionHolder.java @@ -174,7 +174,7 @@ public class ApiPermissionHolder implements net.luckperms.api.model.PermissionHo @Override public @NonNull Map> toMap() { - return ApiPermissionHolder.this.handle.getData(this.dataType).immutable().asMap(); + return ApiPermissionHolder.this.handle.getData(this.dataType).asMap(); } @Override diff --git a/common/src/main/java/me/lucko/luckperms/common/command/CommandManager.java b/common/src/main/java/me/lucko/luckperms/common/command/CommandManager.java index 76caa140a..112d9beba 100644 --- a/common/src/main/java/me/lucko/luckperms/common/command/CommandManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/command/CommandManager.java @@ -167,7 +167,7 @@ public class CommandManager { } Collection groups = this.plugin.getGroupManager().getAll().values(); - if (groups.size() <= 1 && groups.stream().allMatch(g -> g.normalData().immutable().isEmpty())) { + if (groups.size() <= 1 && groups.stream().allMatch(g -> g.normalData().isEmpty())) { Message.FIRST_TIME_SETUP.send(sender, label, sender.getName()); } else { Message.NO_PERMISSION_FOR_SUBCOMMANDS.send(sender); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaClear.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaClear.java index c0fa02f19..154875974 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaClear.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaClear.java @@ -90,7 +90,7 @@ public class MetaClear extends GenericChildCommand { type = NodeType.META_OR_CHAT_META; } - int before = target.normalData().immutable().size(); + int before = target.normalData().size(); MutableContextSet context = args.getContextOrDefault(0, plugin); @@ -106,7 +106,7 @@ public class MetaClear extends GenericChildCommand { target.removeIf(DataType.NORMAL, context, type::matches, false); } - int changed = before - target.normalData().immutable().size(); + int changed = before - target.normalData().size(); if (changed == 1) { Message.META_CLEAR_SUCCESS_SINGULAR.send(sender, target.getFormattedDisplayName(), type.name().toLowerCase(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context), changed); } else { diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderClear.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderClear.java index 8d44099d8..830069825 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderClear.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderClear.java @@ -62,7 +62,7 @@ public class HolderClear extends ChildCommand { return CommandResult.NO_PERMISSION; } - int before = target.normalData().immutable().size(); + int before = target.normalData().size(); MutableContextSet context = args.getContextOrDefault(0, plugin); @@ -78,7 +78,7 @@ public class HolderClear extends ChildCommand { target.clearNodes(DataType.NORMAL, context, true); } - int changed = before - target.normalData().immutable().size(); + int changed = before - target.normalData().size(); if (changed == 1) { Message.CLEAR_SUCCESS_SINGULAR.send(sender, target.getFormattedDisplayName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context), changed); } else { diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderEditor.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderEditor.java index 8eaf86bc8..f7a85ee46 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderEditor.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderEditor.java @@ -84,7 +84,7 @@ public class HolderEditor extends ChildCommand { Map users = new LinkedHashMap<>(plugin.getUserManager().getAll()); // only include online players who are in the group - users.values().removeIf(user -> user.normalData().immutable().values().stream().noneMatch(matcher)); + users.values().removeIf(user -> user.normalData().asList().stream().noneMatch(matcher)); // fill up with other matching users if (users.size() < EditorCommand.MAX_USERS) { diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderShowTracks.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderShowTracks.java index c8fff78f2..9cb749a8b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderShowTracks.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderShowTracks.java @@ -77,7 +77,7 @@ public class HolderShowTracks extends ChildCommand nodes = target.normalData().immutableInheritance().values().stream() + Set nodes = target.normalData().inheritanceAsList().stream() .filter(Node::getValue) .filter(n -> !n.hasExpiry()) .collect(Collectors.toSet()); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentClear.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentClear.java index 61a40ac52..5e8b36d3b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentClear.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentClear.java @@ -62,7 +62,7 @@ public class ParentClear extends GenericChildCommand { return CommandResult.NO_PERMISSION; } - int before = target.normalData().immutable().size(); + int before = target.normalData().size(); MutableContextSet context = args.getContextOrDefault(0, plugin); @@ -77,7 +77,7 @@ public class ParentClear extends GenericChildCommand { target.removeIf(DataType.NORMAL, context, NodeType.INHERITANCE::matches, true); } - int changed = before - target.normalData().immutable().size(); + int changed = before - target.normalData().size(); if (changed == 1) { Message.PARENT_CLEAR_SUCCESS_SINGULAR.send(sender, target.getFormattedDisplayName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context), changed); } else { diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentClearTrack.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentClearTrack.java index 66986487e..eeb66cd4b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentClearTrack.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentClearTrack.java @@ -82,7 +82,7 @@ public class ParentClearTrack extends GenericChildCommand { return CommandResult.STATE_ERROR; } - int before = target.normalData().immutable().size(); + int before = target.normalData().size(); ImmutableContextSet context = args.getContextOrDefault(1, plugin).immutableCopy(); @@ -99,7 +99,7 @@ public class ParentClearTrack extends GenericChildCommand { plugin.getUserManager().giveDefaultIfNeeded(((User) target), false); } - int changed = before - target.normalData().immutable().size(); + int changed = before - target.normalData().size(); if (changed == 1) { Message.PARENT_CLEAR_TRACK_SUCCESS_SINGULAR.send(sender, target.getFormattedDisplayName(), track.getName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context), changed); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionClear.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionClear.java index 13997814a..b4d604d89 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionClear.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionClear.java @@ -62,7 +62,7 @@ public class PermissionClear extends GenericChildCommand { return CommandResult.NO_PERMISSION; } - int before = target.normalData().immutable().size(); + int before = target.normalData().size(); MutableContextSet context = args.getContextOrDefault(0, plugin); @@ -74,7 +74,7 @@ public class PermissionClear extends GenericChildCommand { target.removeIf(DataType.NORMAL, context.isEmpty() ? null : context, NodeType.PERMISSION::matches, false); - int changed = before - target.normalData().immutable().size(); + int changed = before - target.normalData().size(); if (changed == 1) { Message.PERMISSION_CLEAR_SUCCESS_SINGULAR.send(sender, target.getFormattedDisplayName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context), changed); } else { diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupClone.java b/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupClone.java index 1402cb639..8399077d2 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupClone.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupClone.java @@ -73,7 +73,7 @@ public class GroupClone extends ChildCommand { return CommandResult.NO_PERMISSION; } - newGroup.setNodes(DataType.NORMAL, target.normalData().immutable()); + newGroup.setNodes(DataType.NORMAL, target.normalData().asList()); Message.CLONE_SUCCESS.send(sender, target.getName(), newGroup.getName()); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupRename.java b/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupRename.java index 7d025b232..f76a09343 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupRename.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupRename.java @@ -79,7 +79,7 @@ public class GroupRename extends ChildCommand { return CommandResult.FAILURE; } - newGroup.setNodes(DataType.NORMAL, target.normalData().immutable()); + newGroup.setNodes(DataType.NORMAL, target.normalData().asList()); Message.RENAME_SUCCESS.send(sender, target.getName(), newGroup.getName()); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupSetDisplayName.java b/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupSetDisplayName.java index 6d9e83595..1b335adf4 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupSetDisplayName.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupSetDisplayName.java @@ -67,7 +67,7 @@ public class GroupSetDisplayName extends ChildCommand { String name = args.get(0); ImmutableContextSet context = args.getContextOrDefault(1, plugin).immutableCopy(); - String previousName = target.normalData().immutable().get(context).stream() + String previousName = target.normalData().nodesSetInContext(context).stream() .filter(NodeType.DISPLAY_NAME::matches) .map(NodeType.DISPLAY_NAME::cast) .findFirst() diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/log/LogNotify.java b/common/src/main/java/me/lucko/luckperms/common/commands/log/LogNotify.java index 6f7c3f5f8..05bd2a91f 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/log/LogNotify.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/log/LogNotify.java @@ -59,7 +59,7 @@ public class LogNotify extends ChildCommand { return false; } - Optional node = user.normalData().immutable().get(ImmutableContextSetImpl.EMPTY).stream() + Optional node = user.normalData().nodesSetInContext(ImmutableContextSetImpl.EMPTY).stream() .filter(n -> n.getKey().equalsIgnoreCase(IGNORE_NODE)) .findFirst(); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/misc/ApplyEditsCommand.java b/common/src/main/java/me/lucko/luckperms/common/commands/misc/ApplyEditsCommand.java index 1922e610d..0bc5099ae 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/misc/ApplyEditsCommand.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/misc/ApplyEditsCommand.java @@ -176,7 +176,7 @@ public class ApplyEditsCommand extends SingleCommand { return false; } - Set before = new HashSet<>(holder.normalData().immutable().values()); + Set before = holder.normalData().asSet(); Set after = new HashSet<>(NodeJsonSerializer.deserializeNodes(data.getAsJsonArray("nodes"))); Set diffAdded = getAdded(before, after); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/misc/EditorCommand.java b/common/src/main/java/me/lucko/luckperms/common/commands/misc/EditorCommand.java index aa55fa7d5..0fea84e29 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/misc/EditorCommand.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/misc/EditorCommand.java @@ -110,7 +110,7 @@ public class EditorCommand extends SingleCommand { ConstraintNodeMatcher matcher = StandardNodeMatchers.keyStartsWith(filter); // only include online players matching the permission - users.values().removeIf(user -> user.normalData().immutable().values().stream().noneMatch(matcher)); + users.values().removeIf(user -> user.normalData().asList().stream().noneMatch(matcher)); // fill up with other matching users if (type.includingOffline && users.size() < MAX_USERS) { diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/user/UserClone.java b/common/src/main/java/me/lucko/luckperms/common/commands/user/UserClone.java index a56660cf7..4d36a8f90 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/user/UserClone.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/user/UserClone.java @@ -72,7 +72,7 @@ public class UserClone extends ChildCommand { return CommandResult.NO_PERMISSION; } - otherUser.setNodes(DataType.NORMAL, target.normalData().immutable()); + otherUser.setNodes(DataType.NORMAL, target.normalData().asList()); Message.CLONE_SUCCESS.send(sender, target.getFormattedDisplayName(), otherUser.getFormattedDisplayName()); diff --git a/common/src/main/java/me/lucko/luckperms/common/event/EventDispatcher.java b/common/src/main/java/me/lucko/luckperms/common/event/EventDispatcher.java index deca7003c..1dd421477 100644 --- a/common/src/main/java/me/lucko/luckperms/common/event/EventDispatcher.java +++ b/common/src/main/java/me/lucko/luckperms/common/event/EventDispatcher.java @@ -160,7 +160,7 @@ public final class EventDispatcher { } public void dispatchGroupDelete(Group group, DeletionCause cause) { - post(GroupDeleteEvent.class, () -> generate(GroupDeleteEvent.class, group.getName(), ImmutableSet.copyOf(group.normalData().immutable().values()), cause)); + post(GroupDeleteEvent.class, () -> generate(GroupDeleteEvent.class, group.getName(), ImmutableSet.copyOf(group.normalData().asSet()), cause)); } public void dispatchGroupLoadAll() { diff --git a/common/src/main/java/me/lucko/luckperms/common/model/NodeMap.java b/common/src/main/java/me/lucko/luckperms/common/model/NodeMap.java index 10885ef97..f05a1cc96 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/NodeMap.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/NodeMap.java @@ -25,16 +25,12 @@ package me.lucko.luckperms.common.model; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSetMultimap; -import me.lucko.luckperms.common.cache.Cache; import me.lucko.luckperms.common.config.ConfigKeys; 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.query.QueryOptionsImpl; import net.luckperms.api.context.ContextSatisfyMode; import net.luckperms.api.context.ContextSet; @@ -48,15 +44,14 @@ import net.luckperms.api.node.types.InheritanceNode; import net.luckperms.api.query.Flag; import net.luckperms.api.query.QueryOptions; -import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; import java.util.Collection; -import java.util.Comparator; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -104,40 +99,78 @@ public final class NodeMap { */ private final SortedMap> inheritanceMap = new ConcurrentSkipListMap<>(ContextSetComparator.reverse()); - /** - * A cache which holds an immutable copy of the backing map - */ - private final ImmutableSetMultimapCache mapCache = new ImmutableSetMultimapCache<>(this.map); - private final ImmutableSetMultimapCache inheritanceMapCache = new ImmutableSetMultimapCache<>(this.inheritanceMap); - NodeMap(PermissionHolder holder) { this.holder = holder; } + public boolean isEmpty() { + return this.map.isEmpty(); + } + + public int size() { + return this.map.size(); + } + + public List asList() { + List list = new ArrayList<>(); + copyTo(list); + return list; + } + public LinkedHashSet asSet() { LinkedHashSet set = new LinkedHashSet<>(); - copyTo(set, QueryOptionsImpl.DEFAULT_NON_CONTEXTUAL); + copyTo(set); return set; } public SortedSet asSortedSet() { SortedSet set = new TreeSet<>(NodeWithContextComparator.reverse()); - copyTo(set, QueryOptionsImpl.DEFAULT_NON_CONTEXTUAL); + copyTo(set); + return set; + } + + public ImmutableSet asImmutableSet() { + ImmutableSet.Builder builder = ImmutableSet.builder(); + for (SortedSet values : this.map.values()) { + builder.addAll(values); + } + return builder.build(); + } + + public Map> asMap() { + Map> map = new HashMap<>(); + for (Map.Entry> e : this.map.entrySet()) { + map.put(e.getKey(), new ArrayList<>(e.getValue())); + } + return map; + } + + public List inheritanceAsList() { + List set = new ArrayList<>(); + copyInheritanceNodesTo(set); return set; } public LinkedHashSet inheritanceAsSet() { LinkedHashSet set = new LinkedHashSet<>(); - copyInheritanceNodesTo(set, QueryOptionsImpl.DEFAULT_NON_CONTEXTUAL); + copyInheritanceNodesTo(set); return set; } public SortedSet inheritanceAsSortedSet() { SortedSet set = new TreeSet<>(NodeWithContextComparator.reverse()); - copyInheritanceNodesTo(set, QueryOptionsImpl.DEFAULT_NON_CONTEXTUAL); + copyInheritanceNodesTo(set); return set; } + public Map> inheritanceAsMap() { + Map> map = new HashMap<>(); + for (Map.Entry> e : this.inheritanceMap.entrySet()) { + map.put(e.getKey(), new ArrayList<>(e.getValue())); + } + return map; + } + private static boolean flagExcludeTest(Flag flag, String contextKey, QueryOptions filter, ImmutableContextSet contextSet) { // return true (negative result) if the explicit *include* flag is not set, and if the context set doesn't contain the required context key. return !filter.flag(flag) && !contextSet.containsKey(contextKey); @@ -159,6 +192,12 @@ public final class NodeMap { return this.holder.getPlugin().getConfiguration().get(ConfigKeys.CONTEXT_SATISFY_MODE); } + public void forEach(Consumer consumer) { + for (SortedSet values : this.map.values()) { + values.forEach(consumer); + } + } + public void forEach(QueryOptions filter, Consumer consumer) { for (Map.Entry> e : this.map.entrySet()) { if (!filter.satisfies(e.getKey(), defaultSatisfyMode())) { @@ -179,6 +218,12 @@ public final class NodeMap { } } + public void copyTo(Collection collection) { + for (SortedSet values : this.map.values()) { + collection.addAll(values); + } + } + public void copyTo(Collection collection, QueryOptions filter) { for (Map.Entry> e : this.map.entrySet()) { if (!filter.satisfies(e.getKey(), defaultSatisfyMode())) { @@ -227,6 +272,12 @@ public final class NodeMap { } } + public void copyInheritanceNodesTo(Collection collection) { + for (SortedSet values : this.inheritanceMap.values()) { + collection.addAll(values); + } + } + public void copyInheritanceNodesTo(Collection collection, QueryOptions filter) { for (Map.Entry> e : this.inheritanceMap.entrySet()) { if (!filter.satisfies(e.getKey(), defaultSatisfyMode())) { @@ -239,25 +290,20 @@ public final class NodeMap { } } - /** - * Returns an immutable representation of the maps current state. - * - * @return an immutable copy - */ - public ImmutableSetMultimap immutable() { - return this.mapCache.get(); + public Collection nodesSetInContext(ContextSet context) { + final SortedSet values = this.map.get(context.immutableCopy()); + if (values == null) { + return ImmutableSet.of(); + } + return new ArrayList<>(values); } - public ImmutableSetMultimap immutableInheritance() { - return this.inheritanceMapCache.get(); - } - - /** - * Invalidates the cache - */ - void invalidate() { - this.mapCache.invalidate(); - this.inheritanceMapCache.invalidate(); + public Collection inheritanceNodesSetInContext(ContextSet context) { + final SortedSet values = this.inheritanceMap.get(context.immutableCopy()); + if (values == null) { + return ImmutableSet.of(); + } + return new ArrayList<>(values); } private Node localise(Node node) { @@ -414,45 +460,4 @@ public final class NodeMap { return work; } - private static final class ImmutableSetMultimapCache extends Cache> { - @SuppressWarnings("rawtypes") - private static final Constructor IMMUTABLE_SET_MULTIMAP_CONSTRUCTOR; - static { - try { - IMMUTABLE_SET_MULTIMAP_CONSTRUCTOR = ImmutableSetMultimap.class.getDeclaredConstructor(ImmutableMap.class, int.class, Comparator.class); - IMMUTABLE_SET_MULTIMAP_CONSTRUCTOR.setAccessible(true); - } catch (NoSuchMethodException e) { - throw new ExceptionInInitializerError(e); - } - } - - private final Map> handle; - - private ImmutableSetMultimapCache(Map> handle) { - this.handle = handle; - } - - @Override - protected @NonNull ImmutableSetMultimap supply() { - ImmutableMap.Builder> builder = ImmutableMap.builder(); - int size = 0; - - for (Map.Entry> entry : this.handle.entrySet()) { - K key = entry.getKey(); - ImmutableSet values = ImmutableSet.copyOf(entry.getValue()); - if (!values.isEmpty()) { - builder.put(key, values); - size += values.size(); - } - } - - try { - //noinspection unchecked - return IMMUTABLE_SET_MULTIMAP_CONSTRUCTOR.newInstance(builder.build(), size, null); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - } - } - } diff --git a/common/src/main/java/me/lucko/luckperms/common/model/PermissionHolder.java b/common/src/main/java/me/lucko/luckperms/common/model/PermissionHolder.java index 0f7e260c7..4370d4f36 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/PermissionHolder.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/PermissionHolder.java @@ -25,10 +25,9 @@ package me.lucko.luckperms.common.model; -import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; -import com.google.common.collect.Multimap; import me.lucko.luckperms.common.cacheddata.HolderCachedDataManager; import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator; @@ -39,7 +38,6 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.query.DataSelector; import net.luckperms.api.context.ContextSet; -import net.luckperms.api.context.ImmutableContextSet; import net.luckperms.api.model.data.DataMutateResult; import net.luckperms.api.model.data.DataType; import net.luckperms.api.model.data.TemporaryNodeMergeStrategy; @@ -234,9 +232,6 @@ public abstract class PermissionHolder { public abstract HolderType getType(); protected void invalidateCache() { - this.normalNodes.invalidate(); - this.transientNodes.invalidate(); - getCachedData().invalidate(); getPlugin().getEventDispatcher().dispatchDataRecalculate(this); } @@ -251,11 +246,6 @@ public abstract class PermissionHolder { invalidateCache(); } - public void setNodes(DataType type, Multimap multimap) { - getData(type).setContent(multimap.values()); - invalidateCache(); - } - public void mergeNodes(DataType type, Iterable set) { getData(type).mergeContent(set); invalidateCache(); @@ -446,19 +436,19 @@ public abstract class PermissionHolder { } private boolean auditTemporaryNodes(DataType dataType) { - ImmutableCollection before = getData(dataType).immutable().values(); + ImmutableSet before = getData(dataType).asImmutableSet(); Set removed = new HashSet<>(); boolean work = getData(dataType).auditTemporaryNodes(removed); if (work) { - // invalidate - invalidateCache(); - // call event - ImmutableCollection after = getData(dataType).immutable().values(); + ImmutableSet after = getData(dataType).asImmutableSet(); for (Node r : removed) { this.plugin.getEventDispatcher().dispatchNodeRemove(r, this, dataType, before, after); } + + // invalidate + invalidateCache(); } return work; } @@ -468,7 +458,7 @@ public abstract class PermissionHolder { return Tristate.TRUE; } - return getData(type).immutable().values().stream() + return getData(type).asList().stream() .filter(equalityPredicate.equalTo(node)) .findFirst() .map(n -> Tristate.of(n.getValue())).orElse(Tristate.UNDEFINED); @@ -481,22 +471,23 @@ public abstract class PermissionHolder { NodeMap data = getData(dataType); - ImmutableCollection before = data.immutable().values(); + ImmutableSet before = getData(dataType).asImmutableSet(); data.add(node); - invalidateCache(); - ImmutableCollection after = data.immutable().values(); + ImmutableSet after = getData(dataType).asImmutableSet(); if (callEvent) { this.plugin.getEventDispatcher().dispatchNodeAdd(node, this, dataType, before, after); } + invalidateCache(); + return DataMutateResult.SUCCESS; } public DataMutateResult.WithMergedNode setNode(DataType dataType, Node node, TemporaryNodeMergeStrategy mergeStrategy) { if (node.getExpiry() != null && mergeStrategy != TemporaryNodeMergeStrategy.NONE) { - Node otherMatch = getData(dataType).immutable().values().stream() + Node otherMatch = getData(dataType).asList().stream() .filter(NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE.equalTo(node)) .findFirst().orElse(null); @@ -522,14 +513,15 @@ public abstract class PermissionHolder { if (newNode != null) { // Remove the old Node & add the new one. - ImmutableCollection before = data.immutable().values(); + ImmutableSet before = getData(dataType).asImmutableSet(); data.replace(newNode, otherMatch); - invalidateCache(); - ImmutableCollection after = data.immutable().values(); + ImmutableSet after = getData(dataType).asImmutableSet(); this.plugin.getEventDispatcher().dispatchNodeAdd(newNode, this, dataType, before, after); + invalidateCache(); + return new MergedNodeResult(DataMutateResult.SUCCESS, newNode); } } @@ -544,20 +536,21 @@ public abstract class PermissionHolder { return DataMutateResult.FAIL_LACKS; } - ImmutableCollection before = getData(dataType).immutable().values(); + ImmutableSet before = getData(dataType).asImmutableSet(); getData(dataType).remove(node); - invalidateCache(); - ImmutableCollection after = getData(dataType).immutable().values(); + ImmutableSet after = getData(dataType).asImmutableSet(); this.plugin.getEventDispatcher().dispatchNodeRemove(node, this, dataType, before, after); + invalidateCache(); + return DataMutateResult.SUCCESS; } public DataMutateResult.WithMergedNode unsetNode(DataType dataType, Node node, @Nullable Duration duration) { if (node.getExpiry() != null && duration != null) { - Node otherMatch = getData(dataType).immutable().values().stream() + Node otherMatch = getData(dataType).asList().stream() .filter(NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE.equalTo(node)) .findFirst().orElse(null); @@ -570,15 +563,16 @@ public abstract class PermissionHolder { Node newNode = node.toBuilder().expiry(newExpiry).build(); // Remove the old Node & add the new one. - ImmutableCollection before = data.immutable().values(); + ImmutableSet before = getData(dataType).asImmutableSet(); data.replace(newNode, otherMatch); - invalidateCache(); - ImmutableCollection after = data.immutable().values(); + ImmutableSet after = getData(dataType).asImmutableSet(); this.plugin.getEventDispatcher().dispatchNodeRemove(otherMatch, this, dataType, before, after); this.plugin.getEventDispatcher().dispatchNodeAdd(newNode, this, dataType, before, after); + invalidateCache(); + return new MergedNodeResult(DataMutateResult.SUCCESS, newNode); } } @@ -590,7 +584,7 @@ public abstract class PermissionHolder { public boolean removeIf(DataType dataType, @Nullable ContextSet contextSet, Predicate predicate, boolean giveDefault) { NodeMap data = getData(dataType); - ImmutableCollection before = data.immutable().values(); + ImmutableSet before = getData(dataType).asImmutableSet(); if (contextSet == null) { if (!data.removeIf(predicate)) { @@ -606,17 +600,17 @@ public abstract class PermissionHolder { getPlugin().getUserManager().giveDefaultIfNeeded((User) this, false); } - invalidateCache(); - - ImmutableCollection after = data.immutable().values(); + ImmutableSet after = getData(dataType).asImmutableSet(); this.plugin.getEventDispatcher().dispatchNodeClear(this, dataType, before, after); + invalidateCache(); + return true; } public boolean clearNodes(DataType dataType, ContextSet contextSet, boolean giveDefault) { NodeMap data = getData(dataType); - ImmutableCollection before = data.immutable().values(); + ImmutableSet before = getData(dataType).asImmutableSet(); if (contextSet == null) { data.clear(); @@ -628,15 +622,11 @@ public abstract class PermissionHolder { getPlugin().getUserManager().giveDefaultIfNeeded((User) this, false); } + ImmutableSet after = getData(dataType).asImmutableSet(); + this.plugin.getEventDispatcher().dispatchNodeClear(this, dataType, before, after); + invalidateCache(); - ImmutableCollection after = data.immutable().values(); - - if (before.size() == after.size()) { - return false; - } - - this.plugin.getEventDispatcher().dispatchNodeClear(this, dataType, before, after); return true; } 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 564859f4f..d31290864 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 @@ -275,7 +275,7 @@ public final class Track { } // find all groups that are inherited by the user in the exact contexts given and applicable to this track - List nodes = user.normalData().immutableInheritance().get(context.immutableCopy()).stream() + List nodes = user.normalData().inheritanceNodesSetInContext(context).stream() .filter(Node::getValue) .filter(node -> containsGroup(node.getGroupName())) .distinct() @@ -340,7 +340,7 @@ public final class Track { } // find all groups that are inherited by the user in the exact contexts given and applicable to this track - List nodes = user.normalData().immutableInheritance().get(context.immutableCopy()).stream() + List nodes = user.normalData().inheritanceNodesSetInContext(context).stream() .filter(Node::getValue) .filter(node -> containsGroup(node.getGroupName())) .distinct() diff --git a/common/src/main/java/me/lucko/luckperms/common/model/manager/user/AbstractUserManager.java b/common/src/main/java/me/lucko/luckperms/common/model/manager/user/AbstractUserManager.java index 7f19ba5ae..830fbd3ca 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/manager/user/AbstractUserManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/manager/user/AbstractUserManager.java @@ -25,8 +25,6 @@ package me.lucko.luckperms.common.model.manager.user; -import com.google.common.collect.ImmutableCollection; - import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.context.contextset.ImmutableContextSetImpl; import me.lucko.luckperms.common.model.User; @@ -40,7 +38,9 @@ import net.luckperms.api.model.data.DataType; import net.luckperms.api.node.Node; import net.luckperms.api.node.types.InheritanceNode; +import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Optional; import java.util.Set; import java.util.UUID; @@ -82,12 +82,14 @@ public abstract class AbstractUserManager extends AbstractManage public boolean giveDefaultIfNeeded(User user, boolean save) { boolean work = false; + Collection globalGroups = user.normalData().inheritanceNodesSetInContext(ImmutableContextSetImpl.EMPTY); + // check that they are actually a member of their primary group, otherwise remove it if (this.plugin.getConfiguration().get(ConfigKeys.PRIMARY_GROUP_CALCULATION_METHOD).equals("stored")) { String primaryGroup = user.getCachedData().getMetaData(this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_QUERY_OPTIONS)).getPrimaryGroup(MetaCheckEvent.Origin.INTERNAL); boolean memberOfPrimaryGroup = false; - for (InheritanceNode node : user.normalData().immutableInheritance().get(ImmutableContextSetImpl.EMPTY)) { + for (InheritanceNode node : globalGroups) { if (node.getGroupName().equalsIgnoreCase(primaryGroup)) { memberOfPrimaryGroup = true; break; @@ -96,7 +98,7 @@ public abstract class AbstractUserManager extends AbstractManage // need to find a new primary group for the user. if (!memberOfPrimaryGroup) { - String group = user.normalData().immutableInheritance().get(ImmutableContextSetImpl.EMPTY).stream() + String group = globalGroups.stream() .findFirst() .map(InheritanceNode::getGroupName) .orElse(null); @@ -112,7 +114,7 @@ public abstract class AbstractUserManager extends AbstractManage // check that all users are member of at least one group boolean hasGroup = false; if (user.getPrimaryGroup().getStoredValue().isPresent()) { - hasGroup = !user.normalData().immutableInheritance().get(ImmutableContextSetImpl.EMPTY).isEmpty(); + hasGroup = !globalGroups.isEmpty(); } if (!hasGroup) { @@ -163,7 +165,11 @@ public abstract class AbstractUserManager extends AbstractManage */ @Override public boolean shouldSave(User user) { - ImmutableCollection nodes = user.normalData().immutable().values(); + if (user.normalData().size() != 1) { + return true; + } + + List nodes = user.normalData().asList(); if (nodes.size() != 1) { return true; } diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/AbstractConfigurateStorage.java b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/AbstractConfigurateStorage.java index 122c2b20f..3558ea7a7 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/AbstractConfigurateStorage.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/AbstractConfigurateStorage.java @@ -245,7 +245,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio data.getNode("name").setValue(user.getUsername().orElse("null")); data.getNode(this.loader instanceof JsonLoader ? "primaryGroup" : "primary-group").setValue(user.getPrimaryGroup().getStoredValue().orElse(GroupManager.DEFAULT_GROUP_NAME)); - writeNodes(data, user.normalData().immutable().values()); + writeNodes(data, user.normalData().asList()); saveFile(StorageLocation.USER, user.getUniqueId().toString(), data); } } catch (Exception e) { @@ -270,7 +270,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio data.getNode("name").setValue(group.getName()); } - writeNodes(data, group.normalData().immutable().values()); + writeNodes(data, group.normalData().asList()); saveFile(StorageLocation.GROUP, name, data); } } catch (Exception e) { @@ -321,7 +321,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio data.getNode("name").setValue(group.getName()); } - writeNodes(data, group.normalData().immutable().values()); + writeNodes(data, group.normalData().asList()); saveFile(StorageLocation.GROUP, group.getName(), data); } catch (Exception e) { throw reportException(group.getName(), e); diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/mongodb/MongoStorage.java b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/mongodb/MongoStorage.java index 3ee9c826e..2b3c5282c 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/mongodb/MongoStorage.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/mongodb/MongoStorage.java @@ -650,7 +650,7 @@ public class MongoStorage implements StorageImplementation { } private static Document userToDoc(User user) { - List nodes = user.normalData().immutable().values().stream() + List nodes = user.normalData().asList().stream() .map(MongoStorage::nodeToDoc) .collect(Collectors.toList()); @@ -673,7 +673,7 @@ public class MongoStorage implements StorageImplementation { } private static Document groupToDoc(Group group) { - List nodes = group.normalData().immutable().values().stream() + List nodes = group.normalData().asList().stream() .map(MongoStorage::nodeToDoc) .collect(Collectors.toList()); diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/SqlStorage.java b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/SqlStorage.java index 990d2aca2..f746cca89 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/SqlStorage.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/SqlStorage.java @@ -331,7 +331,7 @@ public class SqlStorage implements StorageImplementation { remote = selectUserPermissions(new HashSet<>(), c, user.getUniqueId()); } - Set local = user.normalData().immutable().values().stream().map(SqlNode::fromNode).collect(Collectors.toSet()); + Set local = user.normalData().asList().stream().map(SqlNode::fromNode).collect(Collectors.toSet()); Set missingFromRemote = getMissingFromRemote(local, remote); Set missingFromLocal = getMissingFromLocal(local, remote); @@ -463,7 +463,7 @@ public class SqlStorage implements StorageImplementation { public void saveGroup(Group group) throws SQLException { group.getIoLock().lock(); try { - if (group.normalData().immutable().isEmpty()) { + if (group.normalData().isEmpty()) { try (Connection c = this.connectionFactory.getConnection()) { deleteGroupPermissions(c, group.getName()); } @@ -475,7 +475,7 @@ public class SqlStorage implements StorageImplementation { remote = selectGroupPermissions(new HashSet<>(), c, group.getName()); } - Set local = group.normalData().immutable().values().stream().map(SqlNode::fromNode).collect(Collectors.toSet()); + Set local = group.normalData().asList().stream().map(SqlNode::fromNode).collect(Collectors.toSet()); Set missingFromRemote = getMissingFromRemote(local, remote); Set missingFromLocal = getMissingFromLocal(local, remote); diff --git a/common/src/main/java/me/lucko/luckperms/common/web/WebEditor.java b/common/src/main/java/me/lucko/luckperms/common/web/WebEditor.java index 3010e64c7..c4e69f3b8 100644 --- a/common/src/main/java/me/lucko/luckperms/common/web/WebEditor.java +++ b/common/src/main/java/me/lucko/luckperms/common/web/WebEditor.java @@ -73,7 +73,7 @@ public final class WebEditor { .add("type", holder.getType().toString()) .add("id", holder.getObjectName()) .add("displayName", holder.getPlainDisplayName()) - .add("nodes", NodeJsonSerializer.serializeNodes(holder.normalData().immutable().values())); + .add("nodes", NodeJsonSerializer.serializeNodes(holder.normalData().asList())); } private static JObject writeData(Track track) { diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/permissionholder/PermissionHolderSubjectData.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/permissionholder/PermissionHolderSubjectData.java index 40159a3bc..11de02bbf 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/permissionholder/PermissionHolderSubjectData.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/permissionholder/PermissionHolderSubjectData.java @@ -98,7 +98,7 @@ public class PermissionHolderSubjectData implements LPSubjectData { @Override public ImmutableMap> getAllPermissions() { ImmutableMap.Builder> permissions = ImmutableMap.builder(); - for (Map.Entry> entry : this.holder.getData(this.type).immutable().asMap().entrySet()) { + for (Map.Entry> entry : this.holder.getData(this.type).asMap().entrySet()) { ImmutableMap.Builder builder = ImmutableMap.builder(); for (Node n : entry.getValue()) { builder.put(n.getKey(), n.getValue()); @@ -111,7 +111,7 @@ public class PermissionHolderSubjectData implements LPSubjectData { @Override public ImmutableMap getPermissions(ImmutableContextSet contexts) { ImmutableMap.Builder builder = ImmutableMap.builder(); - for (Node n : this.holder.getData(this.type).immutable().get(contexts)) { + for (Node n : this.holder.getData(this.type).nodesSetInContext(contexts)) { builder.put(n.getKey(), n.getValue()); } return builder.build(); @@ -159,7 +159,7 @@ public class PermissionHolderSubjectData implements LPSubjectData { @Override public ImmutableMap> getAllParents() { ImmutableMap.Builder> parents = ImmutableMap.builder(); - for (Map.Entry> entry : this.holder.getData(this.type).immutableInheritance().asMap().entrySet()) { + for (Map.Entry> entry : this.holder.getData(this.type).inheritanceAsMap().entrySet()) { ImmutableList.Builder builder = ImmutableList.builder(); for (InheritanceNode n : entry.getValue()) { builder.add(this.service.getGroupSubjects().loadSubject(n.getGroupName()).join().toReference()); @@ -172,7 +172,7 @@ public class PermissionHolderSubjectData implements LPSubjectData { @Override public ImmutableList getParents(ImmutableContextSet contexts) { ImmutableList.Builder builder = ImmutableList.builder(); - for (InheritanceNode n : this.holder.getData(this.type).immutableInheritance().get(contexts)) { + for (InheritanceNode n : this.holder.getData(this.type).inheritanceNodesSetInContext(contexts)) { builder.add(this.service.getGroupSubjects().loadSubject(n.getGroupName()).join().toReference()); } return builder.build(); @@ -241,7 +241,7 @@ public class PermissionHolderSubjectData implements LPSubjectData { @Override public ImmutableMap> getAllOptions() { ImmutableMap.Builder> options = ImmutableMap.builder(); - for (Map.Entry> entry : this.holder.getData(this.type).immutable().asMap().entrySet()) { + for (Map.Entry> entry : this.holder.getData(this.type).asMap().entrySet()) { options.put(entry.getKey(), nodesToOptions(entry.getValue())); } return options.build(); @@ -249,7 +249,7 @@ public class PermissionHolderSubjectData implements LPSubjectData { @Override public ImmutableMap getOptions(ImmutableContextSet contexts) { - return nodesToOptions(this.holder.getData(this.type).immutable().get(contexts)); + return nodesToOptions(this.holder.getData(this.type).nodesSetInContext(contexts)); } private static ImmutableMap nodesToOptions(Iterable nodes) {