Cleanup MetaStack, cache the computed prefix/suffix when meta accumulator completes

This commit is contained in:
Luck 2020-05-19 00:36:39 +01:00
parent 4cbbbd390f
commit bfebe6a5d0
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
8 changed files with 169 additions and 346 deletions

View File

@ -34,7 +34,6 @@ import me.lucko.luckperms.common.cacheddata.type.MetaCache;
import me.lucko.luckperms.common.cacheddata.type.PermissionCache;
import me.lucko.luckperms.common.calculator.CalculatorFactory;
import me.lucko.luckperms.common.calculator.PermissionCalculator;
import me.lucko.luckperms.common.metastacking.SimpleMetaStack;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.util.CaffeineFactory;
@ -408,8 +407,8 @@ public abstract class AbstractCachedDataManager implements CachedDataManager {
private MetaAccumulator newAccumulator(QueryOptions queryOptions) {
return new MetaAccumulator(
new SimpleMetaStack(getMetaStackDefinition(queryOptions, ChatMetaType.PREFIX), ChatMetaType.PREFIX),
new SimpleMetaStack(getMetaStackDefinition(queryOptions, ChatMetaType.SUFFIX), ChatMetaType.SUFFIX)
getMetaStackDefinition(queryOptions, ChatMetaType.PREFIX),
getMetaStackDefinition(queryOptions, ChatMetaType.SUFFIX)
);
}

View File

@ -29,11 +29,10 @@ import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.metastacking.MetaStack;
import me.lucko.luckperms.common.metastacking.SimpleMetaStack;
import me.lucko.luckperms.common.node.types.Weight;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import net.luckperms.api.metastacking.MetaStackDefinition;
import net.luckperms.api.node.ChatMetaType;
import net.luckperms.api.node.Node;
import net.luckperms.api.node.types.MetaNode;
@ -55,8 +54,8 @@ public class MetaAccumulator {
public static MetaAccumulator makeFromConfig(LuckPermsPlugin plugin) {
return new MetaAccumulator(
new SimpleMetaStack(plugin.getConfiguration().get(ConfigKeys.PREFIX_FORMATTING_OPTIONS), ChatMetaType.PREFIX),
new SimpleMetaStack(plugin.getConfiguration().get(ConfigKeys.SUFFIX_FORMATTING_OPTIONS), ChatMetaType.SUFFIX)
plugin.getConfiguration().get(ConfigKeys.PREFIX_FORMATTING_OPTIONS),
plugin.getConfiguration().get(ConfigKeys.SUFFIX_FORMATTING_OPTIONS)
);
}
@ -80,17 +79,21 @@ public class MetaAccumulator {
private int weight = 0;
private String primaryGroup;
private final MetaStack prefixStack;
private final MetaStack suffixStack;
private final MetaStackDefinition prefixDefinition;
private final MetaStackDefinition suffixDefinition;
private final MetaStackAccumulator prefixAccumulator;
private final MetaStackAccumulator suffixAccumulator;
public MetaAccumulator(MetaStack prefixStack, MetaStack suffixStack) {
Objects.requireNonNull(prefixStack, "prefixStack");
Objects.requireNonNull(suffixStack, "suffixStack");
public MetaAccumulator(MetaStackDefinition prefixDefinition, MetaStackDefinition suffixDefinition) {
Objects.requireNonNull(prefixDefinition, "prefixDefinition");
Objects.requireNonNull(suffixDefinition, "suffixDefinition");
this.meta = ArrayListMultimap.create();
this.prefixes = new TreeMap<>(Comparator.reverseOrder());
this.suffixes = new TreeMap<>(Comparator.reverseOrder());
this.prefixStack = prefixStack;
this.suffixStack = suffixStack;
this.prefixDefinition = prefixDefinition;
this.suffixDefinition = suffixDefinition;
this.prefixAccumulator = new MetaStackAccumulator(this.prefixDefinition, ChatMetaType.PREFIX);
this.suffixAccumulator = new MetaStackAccumulator(this.suffixDefinition, ChatMetaType.SUFFIX);
}
private void ensureState(State state) {
@ -125,7 +128,7 @@ public class MetaAccumulator {
public void accumulateNode(Node n) {
ensureState(State.ACCUMULATING);
if (n instanceof MetaNode) {
MetaNode mn = (MetaNode) n;
this.meta.put(mn.getMetaKey(), mn.getMetaValue());
@ -134,13 +137,13 @@ public class MetaAccumulator {
if (n instanceof PrefixNode) {
PrefixNode pn = (PrefixNode) n;
this.prefixes.putIfAbsent(pn.getPriority(), pn.getMetaValue());
this.prefixStack.accumulateToAll(pn);
this.prefixAccumulator.offer(pn);
}
if (n instanceof SuffixNode) {
SuffixNode pn = (SuffixNode) n;
this.suffixes.putIfAbsent(pn.getPriority(), pn.getMetaValue());
this.suffixStack.accumulateToAll(pn);
this.suffixAccumulator.offer(pn);
}
}
@ -191,14 +194,24 @@ public class MetaAccumulator {
return this.primaryGroup;
}
public MetaStack getPrefixStack() {
public MetaStackDefinition getPrefixDefinition() {
ensureState(State.COMPLETE);
return this.prefixStack;
return this.prefixDefinition;
}
public MetaStack getSuffixStack() {
public MetaStackDefinition getSuffixDefinition() {
ensureState(State.COMPLETE);
return this.suffixStack;
return this.suffixDefinition;
}
public String getPrefix() {
ensureState(State.COMPLETE);
return this.prefixAccumulator.toFormattedString();
}
public String getSuffix() {
ensureState(State.COMPLETE);
return this.suffixAccumulator.toFormattedString();
}
@Override
@ -209,7 +222,7 @@ public class MetaAccumulator {
"suffixes=" + this.suffixes + ", " +
"weight=" + this.weight + ", " +
"primaryGroup=" + this.primaryGroup + ", " +
"prefixStack=" + this.prefixStack + ", " +
"suffixStack=" + this.suffixStack + ")";
"prefixStack=" + this.prefixAccumulator + ", " +
"suffixStack=" + this.suffixAccumulator + ")";
}
}

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 me.lucko.luckperms.common.cacheddata.type;
import net.luckperms.api.metastacking.MetaStackDefinition;
import net.luckperms.api.metastacking.MetaStackElement;
import net.luckperms.api.node.ChatMetaType;
import net.luckperms.api.node.types.ChatMetaNode;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class MetaStackAccumulator {
private final MetaStackDefinition definition;
private final List<Entry> entries;
public MetaStackAccumulator(MetaStackDefinition definition, ChatMetaType targetType) {
this.definition = definition;
List<MetaStackElement> elements = definition.getElements();
this.entries = new ArrayList<>(elements.size());
for (MetaStackElement element : elements) {
this.entries.add(new Entry(element, targetType));
}
}
public void offer(ChatMetaNode<?, ?> node) {
for (Entry entry : this.entries) {
entry.offer(node);
}
}
public String toFormattedString() {
List<String> elements = new LinkedList<>();
for (Entry entry : this.entries) {
ChatMetaNode<?, ?> node = entry.getNode();
if (node != null) {
elements.add(node.getMetaValue());
}
}
if (elements.isEmpty()) {
return null;
}
this.definition.getDuplicateRemovalFunction().processDuplicates(elements);
Iterator<String> it = elements.iterator();
if (!it.hasNext()) {
return null;
}
StringBuilder sb = new StringBuilder();
sb.append(this.definition.getStartSpacer());
// append first - we've checked hasNext already
sb.append(it.next());
// append rest
while (it.hasNext()){
sb.append(this.definition.getMiddleSpacer());
sb.append(it.next());
}
sb.append(this.definition.getEndSpacer());
return sb.toString();
}
private static final class Entry {
private final MetaStackElement element;
private final ChatMetaType type;
private @Nullable ChatMetaNode<?, ?> current = null;
Entry(MetaStackElement element, ChatMetaType type) {
this.element = element;
this.type = type;
}
public ChatMetaNode<?, ?> getNode() {
return this.current;
}
public boolean offer(ChatMetaNode<?, ?> node) {
if (this.element.shouldAccumulate(this.type, node, this.current)) {
this.current = node;
return true;
}
return false;
}
}
}

View File

@ -31,7 +31,6 @@ import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Multimaps;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.metastacking.MetaStack;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.verbose.event.MetaCheckEvent;
@ -65,8 +64,10 @@ public class SimpleMetaCache implements CachedMetaData {
protected SortedMap<Integer, String> suffixes = ImmutableSortedMap.of();
protected int weight = 0;
protected String primaryGroup = null;
protected MetaStack prefixStack = null;
protected MetaStack suffixStack = null;
private MetaStackDefinition prefixDefinition = null;
private MetaStackDefinition suffixDefinition = null;
private String prefix = null;
private String suffix = null;
public SimpleMetaCache(LuckPermsPlugin plugin, QueryOptions queryOptions) {
this.plugin = plugin;
@ -98,8 +99,10 @@ public class SimpleMetaCache implements CachedMetaData {
this.suffixes = ImmutableSortedMap.copyOfSorted(meta.getSuffixes());
this.weight = meta.getWeight();
this.primaryGroup = meta.getPrimaryGroup();
this.prefixStack = meta.getPrefixStack();
this.suffixStack = meta.getSuffixStack();
this.prefixDefinition = meta.getPrefixDefinition();
this.suffixDefinition = meta.getSuffixDefinition();
this.prefix = meta.getPrefix();
this.suffix = meta.getSuffix();
}
public String getMetaValue(String key, MetaCheckEvent.Origin origin) {
@ -113,8 +116,7 @@ public class SimpleMetaCache implements CachedMetaData {
}
public String getPrefix(MetaCheckEvent.Origin origin) {
MetaStack prefixStack = this.prefixStack;
return prefixStack == null ? null : prefixStack.toFormattedString();
return this.prefix;
}
@Override
@ -123,8 +125,7 @@ public class SimpleMetaCache implements CachedMetaData {
}
public String getSuffix(MetaCheckEvent.Origin origin) {
MetaStack suffixStack = this.suffixStack;
return suffixStack == null ? null : suffixStack.toFormattedString();
return this.suffix;
}
@Override
@ -155,7 +156,7 @@ public class SimpleMetaCache implements CachedMetaData {
return this.weight;
}
//@Override
//@Override - not actually exposed in the API atm
public final int getWeight() {
return getWeight(MetaCheckEvent.Origin.LUCKPERMS_API);
}
@ -171,12 +172,12 @@ public class SimpleMetaCache implements CachedMetaData {
@Override
public @NonNull MetaStackDefinition getPrefixStackDefinition() {
return this.prefixStack.getDefinition();
return this.prefixDefinition;
}
@Override
public @NonNull MetaStackDefinition getSuffixStackDefinition() {
return this.suffixStack.getDefinition();
return this.suffixDefinition;
}
@Override

View File

@ -1,70 +0,0 @@
/*
* 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.metastacking;
import net.luckperms.api.metastacking.MetaStackDefinition;
import net.luckperms.api.node.ChatMetaType;
import net.luckperms.api.node.types.ChatMetaNode;
/**
* A live stack of {@link MetaStackEntry} instances, formed from a
* {@link MetaStackDefinition}.
*
* This class is used to construct a formatted string, by accumulating
* nodes to each element.
*/
public interface MetaStack {
/**
* Gets the definition this stack is based upon
*
* @return the definition of the stack
*/
MetaStackDefinition getDefinition();
/**
* Gets the target of this stack
*
* @return the stack target
*/
ChatMetaType getTargetType();
/**
* Returns a formatted string, as defined by the {@link MetaStackDefinition},
* using the accumulated elements in the stack.
*
* @return the string output
*/
String toFormattedString();
/**
* Tries to accumulate the given node to all elements in the stack.
*
* @param node the node to accumulate
*/
void accumulateToAll(ChatMetaNode<?, ?> node);
}

View File

@ -1,68 +0,0 @@
/*
* 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.metastacking;
import net.luckperms.api.metastacking.MetaStackElement;
import net.luckperms.api.node.types.ChatMetaNode;
import java.util.Optional;
/**
* Represents a specific entry in a {@link MetaStack}.
* An entry is basically a live/mutable version of a {@link MetaStackElement}.
*/
public interface MetaStackEntry {
/**
* Gets the stack this entry belongs to.
*
* @return the parent stack
*/
MetaStack getParentStack();
/**
* Gets the element this entry was formed form
*
* @return the forming element
*/
MetaStackElement getElement();
/**
* Gets the value currently held by this entry.
*
* @return the entry
*/
Optional<ChatMetaNode<?, ?>> getCurrentValue();
/**
* Accumulates a node to this entry
*
* @param node the node to accumulate
* @return if the node was accepted
*/
boolean accumulateNode(ChatMetaNode<?, ?> node);
}

View File

@ -1,96 +0,0 @@
/*
* 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.metastacking;
import me.lucko.luckperms.common.util.ImmutableCollectors;
import net.luckperms.api.metastacking.MetaStackDefinition;
import net.luckperms.api.node.ChatMetaType;
import net.luckperms.api.node.types.ChatMetaNode;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public final class SimpleMetaStack implements MetaStack {
private final MetaStackDefinition definition;
private final ChatMetaType targetType;
private final List<MetaStackEntry> entries;
public SimpleMetaStack(MetaStackDefinition definition, ChatMetaType targetType) {
this.definition = definition;
this.targetType = targetType;
this.entries = definition.getElements().stream()
.map(element -> new SimpleMetaStackEntry(this, element, targetType))
.collect(ImmutableCollectors.toList());
}
@Override
public String toFormattedString() {
List<String> elements = this.entries.stream()
.map(MetaStackEntry::getCurrentValue)
.filter(Optional::isPresent)
.map(Optional::get)
.map(ChatMetaNode::getMetaValue)
.collect(Collectors.toCollection(LinkedList::new));
if (elements.isEmpty()) {
return null;
}
this.definition.getDuplicateRemovalFunction().processDuplicates(elements);
StringBuilder sb = new StringBuilder();
sb.append(this.definition.getStartSpacer());
for (int i = 0; i < elements.size(); i++) {
if (i != 0) {
sb.append(this.definition.getMiddleSpacer());
}
sb.append(elements.get(i));
}
sb.append(this.definition.getEndSpacer());
return sb.toString();
}
@Override
public void accumulateToAll(ChatMetaNode<?, ?> node) {
this.entries.forEach(e -> e.accumulateNode(node));
}
@Override
public MetaStackDefinition getDefinition() {
return this.definition;
}
@Override
public ChatMetaType getTargetType() {
return this.targetType;
}
}

View File

@ -1,76 +0,0 @@
/*
* 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.metastacking;
import net.luckperms.api.metastacking.MetaStackElement;
import net.luckperms.api.node.ChatMetaType;
import net.luckperms.api.node.types.ChatMetaNode;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Optional;
final class SimpleMetaStackEntry implements MetaStackEntry {
private final MetaStack parentStack;
private final MetaStackElement element;
private final ChatMetaType type;
private @Nullable ChatMetaNode<?, ?> current = null;
public SimpleMetaStackEntry(MetaStack parentStack, MetaStackElement element, ChatMetaType type) {
this.parentStack = parentStack;
this.element = element;
this.type = type;
}
@Override
public Optional<ChatMetaNode<?, ?>> getCurrentValue() {
return Optional.ofNullable(this.current);
}
@Override
public boolean accumulateNode(ChatMetaNode<?, ?> node) {
if (this.element.shouldAccumulate(this.type, node, this.current)) {
this.current = node;
return true;
}
return false;
}
@Override
public MetaStack getParentStack() {
return this.parentStack;
}
@Override
public MetaStackElement getElement() {
return this.element;
}
public ChatMetaType getType() {
return this.type;
}
}