mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-12-28 03:57:36 +01:00
refactor context sets
This commit is contained in:
parent
dfb1b8f841
commit
0bec93ab1c
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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.api.context;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
abstract class AbstractContextSet implements ContextSet {
|
||||
|
||||
protected abstract Multimap<String, String> backing();
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public boolean containsKey(@Nonnull String key) {
|
||||
return backing().containsKey(sanitizeKey(key));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Set<String> getValues(@Nonnull String key) {
|
||||
Collection<String> values = backing().asMap().get(sanitizeKey(key));
|
||||
return values != null ? ImmutableSet.copyOf(values) : ImmutableSet.of();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public boolean has(@Nonnull String key, @Nonnull String value) {
|
||||
return backing().containsEntry(sanitizeKey(key), sanitizeValue(value));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public boolean hasIgnoreCase(@Nonnull String key, @Nonnull String value) {
|
||||
String v = sanitizeValue(value);
|
||||
|
||||
Collection<String> values = backing().asMap().get(sanitizeKey(key));
|
||||
if (values == null || values.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (values.contains(v)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (String val : values) {
|
||||
if (val.equalsIgnoreCase(v)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return backing().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return backing().size();
|
||||
}
|
||||
|
||||
static String sanitizeKey(String key) {
|
||||
return checkNotNull(key, "key is null").toLowerCase().intern();
|
||||
}
|
||||
|
||||
static String sanitizeValue(String value) {
|
||||
return checkNotNull(value, "value is null").intern();
|
||||
}
|
||||
|
||||
}
|
@ -26,11 +26,10 @@
|
||||
package me.lucko.luckperms.api.context;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@ -46,9 +45,19 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
*
|
||||
* @since 2.16
|
||||
*/
|
||||
public final class ImmutableContextSet implements ContextSet {
|
||||
public final class ImmutableContextSet extends AbstractContextSet implements ContextSet {
|
||||
private static final ImmutableContextSet EMPTY = new ImmutableContextSet(ImmutableSetMultimap.of());
|
||||
|
||||
/**
|
||||
* Creates a builder
|
||||
*
|
||||
* @return a new ImmutableContextSet builder
|
||||
*/
|
||||
@Nonnull
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ImmutableContextSet from a context pair
|
||||
*
|
||||
@ -59,10 +68,7 @@ public final class ImmutableContextSet implements ContextSet {
|
||||
*/
|
||||
@Nonnull
|
||||
public static ImmutableContextSet singleton(@Nonnull String key, @Nonnull String value) {
|
||||
return new ImmutableContextSet(ImmutableSetMultimap.of(
|
||||
checkNotNull(key, "key").toLowerCase().intern(),
|
||||
checkNotNull(value, "value").intern()
|
||||
));
|
||||
return new ImmutableContextSet(ImmutableSetMultimap.of(sanitizeKey(key), sanitizeValue(value)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,10 +85,10 @@ public final class ImmutableContextSet implements ContextSet {
|
||||
@Nonnull
|
||||
public static ImmutableContextSet of(@Nonnull String key1, @Nonnull String value1, @Nonnull String key2, @Nonnull String value2) {
|
||||
return new ImmutableContextSet(ImmutableSetMultimap.of(
|
||||
checkNotNull(key1, "key1").toLowerCase().intern(),
|
||||
checkNotNull(value1, "value1").intern(),
|
||||
checkNotNull(key2, "key2").toLowerCase().intern(),
|
||||
checkNotNull(value2, "value2").intern()
|
||||
sanitizeKey(key1),
|
||||
sanitizeValue(value1),
|
||||
sanitizeKey(key2),
|
||||
sanitizeValue(value2)
|
||||
));
|
||||
}
|
||||
|
||||
@ -97,11 +103,16 @@ public final class ImmutableContextSet implements ContextSet {
|
||||
public static ImmutableContextSet fromEntries(@Nonnull Iterable<? extends Map.Entry<String, String>> iterable) {
|
||||
checkNotNull(iterable, "iterable");
|
||||
|
||||
ImmutableSetMultimap.Builder<String, String> b = ImmutableSetMultimap.builder();
|
||||
for (Map.Entry<String, String> e : iterable) {
|
||||
b.put(checkNotNull(e.getKey()).toLowerCase().intern(), checkNotNull(e.getValue()).intern());
|
||||
Iterator<? extends Map.Entry<String, String>> iterator = iterable.iterator();
|
||||
if (!iterator.hasNext()) {
|
||||
return empty();
|
||||
}
|
||||
|
||||
ImmutableSetMultimap.Builder<String, String> b = ImmutableSetMultimap.builder();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, String> e = checkNotNull(iterator.next(), "entry");
|
||||
b.put(sanitizeKey(e.getKey()), sanitizeValue(e.getValue()));
|
||||
}
|
||||
return new ImmutableContextSet(b.build());
|
||||
}
|
||||
|
||||
@ -158,6 +169,11 @@ public final class ImmutableContextSet implements ContextSet {
|
||||
this.map = contexts;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Multimap<String, String> backing() {
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImmutable() {
|
||||
return true;
|
||||
@ -200,67 +216,21 @@ public final class ImmutableContextSet implements ContextSet {
|
||||
return map;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public boolean containsKey(@Nonnull String key) {
|
||||
return map.containsKey(checkNotNull(key, "key").toLowerCase().intern());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Set<String> getValues(@Nonnull String key) {
|
||||
Collection<String> values = map.get(checkNotNull(key, "key").toLowerCase().intern());
|
||||
return values != null ? ImmutableSet.copyOf(values) : ImmutableSet.of();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public boolean has(@Nonnull String key, @Nonnull String value) {
|
||||
return map.containsEntry(checkNotNull(key, "key").toLowerCase().intern(), checkNotNull(value, "value").intern());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public boolean hasIgnoreCase(@Nonnull String key, @Nonnull String value) {
|
||||
value = checkNotNull(value, "value").intern();
|
||||
Collection<String> values = map.get(checkNotNull(key, "key").toLowerCase().intern());
|
||||
|
||||
if (values == null || values.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (String val : values) {
|
||||
if (val.equalsIgnoreCase(value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof ContextSet)) return false;
|
||||
final ContextSet other = (ContextSet) o;
|
||||
|
||||
// saves on copying the multimap
|
||||
final Multimap<String, String> otherContexts;
|
||||
|
||||
if (other instanceof MutableContextSet) {
|
||||
return other.equals(this);
|
||||
otherContexts = ((MutableContextSet) other).backing();
|
||||
} else {
|
||||
otherContexts = other.toMultimap();
|
||||
}
|
||||
|
||||
final Multimap<String, String> thisContexts = this.toMultimap();
|
||||
final Multimap<String, String> otherContexts = other.toMultimap();
|
||||
return thisContexts.equals(otherContexts);
|
||||
return this.map.equals(otherContexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -272,4 +242,107 @@ public final class ImmutableContextSet implements ContextSet {
|
||||
public String toString() {
|
||||
return "ImmutableContextSet(contexts=" + this.map + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder for {@link ImmutableContextSet}
|
||||
*/
|
||||
public static final class Builder {
|
||||
private final ImmutableSetMultimap.Builder<String, String> builder = ImmutableSetMultimap.builder();
|
||||
|
||||
private Builder() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new key value pair to the set
|
||||
*
|
||||
* @param key the key to add
|
||||
* @param value the value to add
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
@Nonnull
|
||||
public Builder add(@Nonnull String key, @Nonnull String value) {
|
||||
builder.put(sanitizeKey(key), sanitizeValue(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new key value pair to the set
|
||||
*
|
||||
* @param entry the entry to add
|
||||
* @throws NullPointerException if the entry is null
|
||||
*/
|
||||
@Nonnull
|
||||
public Builder add(@Nonnull Map.Entry<String, String> entry) {
|
||||
checkNotNull(entry, "entry");
|
||||
add(entry.getKey(), entry.getValue());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an iterable containing contexts to the set
|
||||
*
|
||||
* @param iterable an iterable of key value context pairs
|
||||
* @throws NullPointerException if iterable is null
|
||||
*/
|
||||
@Nonnull
|
||||
public Builder addAll(@Nonnull Iterable<? extends Map.Entry<String, String>> iterable) {
|
||||
for (Map.Entry<String, String> e : checkNotNull(iterable, "iterable")) {
|
||||
add(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the entry set of a map to the set
|
||||
*
|
||||
* @param map the map to add from
|
||||
* @throws NullPointerException if the map is null
|
||||
*/
|
||||
@Nonnull
|
||||
public Builder addAll(@Nonnull Map<String, String> map) {
|
||||
addAll(checkNotNull(map, "map").entrySet());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the entries of a multimap to the set
|
||||
*
|
||||
* @param multimap the multimap to add from
|
||||
* @throws NullPointerException if the map is null
|
||||
* @since 3.4
|
||||
*/
|
||||
@Nonnull
|
||||
public Builder addAll(@Nonnull Multimap<String, String> multimap) {
|
||||
addAll(checkNotNull(multimap, "multimap").entries());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds of of the values in another ContextSet to this set
|
||||
*
|
||||
* @param contextSet the set to add from
|
||||
* @throws NullPointerException if the contextSet is null
|
||||
*/
|
||||
@Nonnull
|
||||
public Builder addAll(@Nonnull ContextSet contextSet) {
|
||||
checkNotNull(contextSet, "contextSet");
|
||||
if (contextSet instanceof MutableContextSet) {
|
||||
MutableContextSet other = ((MutableContextSet) contextSet);
|
||||
builder.putAll(other.backing());
|
||||
} else if (contextSet instanceof ImmutableContextSet) {
|
||||
ImmutableContextSet other = ((ImmutableContextSet) contextSet);
|
||||
builder.putAll(other.backing());
|
||||
} else {
|
||||
addAll(contextSet.toMultimap());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ImmutableContextSet build() {
|
||||
return new ImmutableContextSet(builder.build());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
*
|
||||
* @since 2.16
|
||||
*/
|
||||
public final class MutableContextSet implements ContextSet {
|
||||
public final class MutableContextSet extends AbstractContextSet implements ContextSet {
|
||||
|
||||
/**
|
||||
* Make a singleton MutableContextSet from a context pair
|
||||
@ -86,7 +86,7 @@ public final class MutableContextSet implements ContextSet {
|
||||
checkNotNull(value1, "value1");
|
||||
checkNotNull(key2, "key2");
|
||||
checkNotNull(value2, "value2");
|
||||
MutableContextSet set = MutableContextSet.create();
|
||||
MutableContextSet set = create();
|
||||
set.add(key1, value1);
|
||||
set.add(key2, value2);
|
||||
return set;
|
||||
@ -102,7 +102,7 @@ public final class MutableContextSet implements ContextSet {
|
||||
@Nonnull
|
||||
public static MutableContextSet fromEntries(@Nonnull Iterable<? extends Map.Entry<String, String>> iterable) {
|
||||
checkNotNull(iterable, "iterable");
|
||||
MutableContextSet set = MutableContextSet.create();
|
||||
MutableContextSet set = create();
|
||||
set.addAll(iterable);
|
||||
return set;
|
||||
}
|
||||
@ -117,7 +117,7 @@ public final class MutableContextSet implements ContextSet {
|
||||
@Nonnull
|
||||
public static MutableContextSet fromMap(@Nonnull Map<String, String> map) {
|
||||
checkNotNull(map, "map");
|
||||
MutableContextSet set = MutableContextSet.create();
|
||||
MutableContextSet set = create();
|
||||
set.addAll(map);
|
||||
return set;
|
||||
}
|
||||
@ -132,7 +132,7 @@ public final class MutableContextSet implements ContextSet {
|
||||
@Nonnull
|
||||
public static MutableContextSet fromMultimap(@Nonnull Multimap<String, String> multimap) {
|
||||
checkNotNull(multimap, "multimap");
|
||||
MutableContextSet set = MutableContextSet.create();
|
||||
MutableContextSet set = create();
|
||||
set.addAll(multimap);
|
||||
return set;
|
||||
}
|
||||
@ -148,8 +148,8 @@ public final class MutableContextSet implements ContextSet {
|
||||
@Nonnull
|
||||
public static MutableContextSet fromSet(@Nonnull ContextSet contextSet) {
|
||||
Preconditions.checkNotNull(contextSet, "contextSet");
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.addAll(contextSet.toSet());
|
||||
MutableContextSet set = create();
|
||||
set.addAll(contextSet);
|
||||
return set;
|
||||
}
|
||||
|
||||
@ -173,6 +173,11 @@ public final class MutableContextSet implements ContextSet {
|
||||
this.map = Multimaps.synchronizedSetMultimap(HashMultimap.create(other.map));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Multimap<String, String> backing() {
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImmutable() {
|
||||
return false;
|
||||
@ -181,6 +186,9 @@ public final class MutableContextSet implements ContextSet {
|
||||
@Nonnull
|
||||
@Override
|
||||
public ImmutableContextSet makeImmutable() {
|
||||
if (map.isEmpty()) {
|
||||
return ImmutableContextSet.empty();
|
||||
}
|
||||
return new ImmutableContextSet(ImmutableSetMultimap.copyOf(map));
|
||||
}
|
||||
|
||||
@ -204,7 +212,6 @@ public final class MutableContextSet implements ContextSet {
|
||||
for (Map.Entry<String, String> e : map.entries()) {
|
||||
m.put(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
return m.build();
|
||||
}
|
||||
|
||||
@ -214,53 +221,6 @@ public final class MutableContextSet implements ContextSet {
|
||||
return ImmutableSetMultimap.copyOf(map);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public boolean containsKey(@Nonnull String key) {
|
||||
return map.containsKey(checkNotNull(key, "key").toLowerCase().intern());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Set<String> getValues(@Nonnull String key) {
|
||||
Collection<String> values = map.get(checkNotNull(key, "key").toLowerCase().intern());
|
||||
return values != null ? ImmutableSet.copyOf(values) : ImmutableSet.of();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public boolean has(@Nonnull String key, @Nonnull String value) {
|
||||
return map.containsEntry(checkNotNull(key, "key").toLowerCase().intern(), checkNotNull(value, "value").intern());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public boolean hasIgnoreCase(@Nonnull String key, @Nonnull String value) {
|
||||
value = checkNotNull(value, "value").intern();
|
||||
Collection<String> values = map.get(checkNotNull(key, "key").toLowerCase().intern());
|
||||
|
||||
if (values == null || values.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (String val : values) {
|
||||
if (val.equalsIgnoreCase(value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new key value pair to the set
|
||||
*
|
||||
@ -269,7 +229,7 @@ public final class MutableContextSet implements ContextSet {
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
public void add(@Nonnull String key, @Nonnull String value) {
|
||||
map.put(checkNotNull(key, "key").toLowerCase().intern(), checkNotNull(value, "value").intern());
|
||||
map.put(sanitizeKey(key), sanitizeValue(value));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -327,6 +287,9 @@ public final class MutableContextSet implements ContextSet {
|
||||
if (contextSet instanceof MutableContextSet) {
|
||||
MutableContextSet other = ((MutableContextSet) contextSet);
|
||||
this.map.putAll(other.map);
|
||||
} else if (contextSet instanceof ImmutableContextSet) {
|
||||
ImmutableContextSet other = ((ImmutableContextSet) contextSet);
|
||||
this.map.putAll(other.backing());
|
||||
} else {
|
||||
addAll(contextSet.toMultimap());
|
||||
}
|
||||
@ -340,11 +303,7 @@ public final class MutableContextSet implements ContextSet {
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
public void remove(@Nonnull String key, @Nonnull String value) {
|
||||
String k = checkNotNull(key, "key").toLowerCase().intern();
|
||||
String v = checkNotNull(value, "value").intern();
|
||||
|
||||
//noinspection StringEquality
|
||||
map.entries().removeIf(entry -> entry.getKey() == k && entry.getValue() == v);
|
||||
map.remove(sanitizeKey(key), sanitizeValue(value));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -355,11 +314,11 @@ public final class MutableContextSet implements ContextSet {
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
public void removeIgnoreCase(@Nonnull String key, @Nonnull String value) {
|
||||
String k = checkNotNull(key, "key").toLowerCase().intern();
|
||||
String v = checkNotNull(value, "value").intern();
|
||||
|
||||
//noinspection StringEquality
|
||||
map.entries().removeIf(e -> e.getKey() == k && e.getValue().equalsIgnoreCase(v));
|
||||
String v = sanitizeValue(value);
|
||||
Collection<String> strings = map.asMap().get(sanitizeKey(key));
|
||||
if (strings != null) {
|
||||
strings.removeIf(e -> e.equalsIgnoreCase(v));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -369,7 +328,7 @@ public final class MutableContextSet implements ContextSet {
|
||||
* @throws NullPointerException if the key is null
|
||||
*/
|
||||
public void removeAll(@Nonnull String key) {
|
||||
map.removeAll(checkNotNull(key, "key").toLowerCase());
|
||||
map.removeAll(sanitizeKey(key));
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user