Add DataTypeFilter

This commit is contained in:
Luck 2020-06-12 23:14:33 +01:00
parent 6fa690a49d
commit df324de9ec
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
6 changed files with 280 additions and 8 deletions

View File

@ -48,6 +48,8 @@ import java.util.function.Consumer;
* it is possible that more {@link DataType}s may be added in the future. * it is possible that more {@link DataType}s may be added in the future.
* Ideally the {@link Comparator} implementations should be able to handle these * Ideally the {@link Comparator} implementations should be able to handle these
* smoothly.</p> * smoothly.</p>
*
* @see DataQueryOrderFunction
*/ */
public enum DataQueryOrder implements Comparator<DataType> { public enum DataQueryOrder implements Comparator<DataType> {

View File

@ -44,6 +44,18 @@ public interface DataQueryOrderFunction {
*/ */
OptionKey<DataQueryOrderFunction> KEY = OptionKey.of("dataqueryorderfunction", DataQueryOrderFunction.class); OptionKey<DataQueryOrderFunction> KEY = OptionKey.of("dataqueryorderfunction", DataQueryOrderFunction.class);
/**
* Creates a {@link DataQueryOrderFunction} that always returns the given
* {@code comparator}.
*
* @param comparator the comparator
* @return the data query order function
* @since 5.2
*/
static DataQueryOrderFunction always(Comparator<DataType> comparator) {
return id -> comparator;
}
/** /**
* Gets the {@link DataQueryOrder} comparator for the given * Gets the {@link DataQueryOrder} comparator for the given
* {@link PermissionHolder.Identifier holder identifier}. * {@link PermissionHolder.Identifier holder identifier}.

View File

@ -0,0 +1,110 @@
/*
* 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.query.dataorder;
import net.luckperms.api.model.data.DataType;
import net.luckperms.api.query.QueryOptions;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
/**
* Represents which different {@link DataType}s are used for a query.
*
* <p>The {@link DataTypeFilter} enum simply represents some default
* implementations of the {@link Predicate} required by {@link QueryOptions}
* and the {@link #values(Predicate)} method.</p>
*
* <p>Users are free to implement their own predicate. However, be aware that
* it is possible that more {@link DataType}s may be added in the future.
* Ideally the {@link Predicate} implementations should be able to handle these
* smoothly.</p>
*
* @see DataTypeFilterFunction
* @since 5.2
*/
public enum DataTypeFilter implements Predicate<DataType> {
/**
* A data type filter indicating that all {@link DataType}s should be used.
*/
ALL {
@Override
public boolean test(DataType dataType) {
return true;
}
},
/**
* A data type filter indicating that only {@link DataType#NORMAL} should be used.
*/
NORMAL_ONLY {
@Override
public boolean test(DataType dataType) {
return dataType == DataType.NORMAL;
}
},
/**
* A data type filter indicating that only {@link DataType#TRANSIENT} should be used.
*/
TRANSIENT_ONLY {
@Override
public boolean test(DataType dataType) {
return dataType == DataType.TRANSIENT;
}
};
private static final List<DataType> ALL_LIST = Collections.unmodifiableList(Arrays.asList(DataType.NORMAL, DataType.TRANSIENT));
private static final List<DataType> NORMAL_ONLY_LIST = Collections.unmodifiableList(Collections.singletonList(DataType.NORMAL));
private static final List<DataType> TRANSIENT_ONLY_LIST = Collections.unmodifiableList(Collections.singletonList(DataType.TRANSIENT));
/**
* Gets a {@link List} of all {@link DataType}s, filtered by the {@code predicate}.
*
* @param predicate the predicate to filter with
* @return the list of data types
*/
public static @NonNull List<DataType> values(@NonNull Predicate<? super DataType> predicate) {
boolean normal = predicate.test(DataType.NORMAL);
boolean trans = predicate.test(DataType.TRANSIENT);
if (normal && trans) {
return ALL_LIST;
} else if (normal) {
return NORMAL_ONLY_LIST;
} else if (trans) {
return TRANSIENT_ONLY_LIST;
} else {
return Collections.emptyList();
}
}
}

View File

@ -0,0 +1,69 @@
/*
* 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.query.dataorder;
import net.luckperms.api.model.PermissionHolder;
import net.luckperms.api.model.data.DataType;
import net.luckperms.api.query.OptionKey;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.function.Predicate;
/**
* A function that generates a {@link DataTypeFilter} predicate for
* {@link PermissionHolder}s as required during inheritance.
*
* @since 5.2
*/
public interface DataTypeFilterFunction {
/**
* The {@link OptionKey} for {@link DataTypeFilterFunction}.
*/
OptionKey<DataTypeFilterFunction> KEY = OptionKey.of("datatypefilterfunction", DataTypeFilterFunction.class);
/**
* Creates a {@link DataTypeFilterFunction} that always returns the given
* {@code predicate}.
*
* @param predicate the predicate
* @return the data type filter function
*/
static DataTypeFilterFunction always(Predicate<DataType> predicate) {
return id -> predicate;
}
/**
* Gets the {@link DataTypeFilter} predicate for the given
* {@link PermissionHolder.Identifier holder identifier}.
*
* @param holderIdentifier the holder identifier
* @return the predicate to use
*/
@NonNull Predicate<DataType> getTypeFilter(PermissionHolder.@NonNull Identifier holderIdentifier);
}

View File

@ -36,6 +36,7 @@ import me.lucko.luckperms.common.inheritance.InheritanceComparator;
import me.lucko.luckperms.common.inheritance.InheritanceGraph; import me.lucko.luckperms.common.inheritance.InheritanceGraph;
import me.lucko.luckperms.common.node.comparator.NodeWithContextComparator; import me.lucko.luckperms.common.node.comparator.NodeWithContextComparator;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; 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.ContextSet;
import net.luckperms.api.context.ImmutableContextSet; import net.luckperms.api.context.ImmutableContextSet;
@ -48,8 +49,6 @@ import net.luckperms.api.node.NodeType;
import net.luckperms.api.node.types.InheritanceNode; import net.luckperms.api.node.types.InheritanceNode;
import net.luckperms.api.query.Flag; import net.luckperms.api.query.Flag;
import net.luckperms.api.query.QueryOptions; import net.luckperms.api.query.QueryOptions;
import net.luckperms.api.query.dataorder.DataQueryOrder;
import net.luckperms.api.query.dataorder.DataQueryOrderFunction;
import net.luckperms.api.util.Tristate; import net.luckperms.api.util.Tristate;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@ -262,12 +261,8 @@ public abstract class PermissionHolder {
invalidateCache(); invalidateCache();
} }
private List<DataType> queryOrder(QueryOptions queryOptions) { private DataType[] queryOrder(QueryOptions queryOptions) {
Comparator<DataType> comparator = queryOptions.option(DataQueryOrderFunction.KEY) return DataSelector.select(queryOptions, getIdentifier());
.map(func -> func.getOrderComparator(getIdentifier()))
.orElse(DataQueryOrder.TRANSIENT_FIRST);
return DataQueryOrder.order(comparator);
} }
public List<Node> getOwnNodes(QueryOptions queryOptions) { public List<Node> getOwnNodes(QueryOptions queryOptions) {

View File

@ -0,0 +1,84 @@
/*
* 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.query;
import net.luckperms.api.model.PermissionHolder;
import net.luckperms.api.model.data.DataType;
import net.luckperms.api.query.QueryOptions;
import net.luckperms.api.query.dataorder.DataQueryOrder;
import net.luckperms.api.query.dataorder.DataQueryOrderFunction;
import net.luckperms.api.query.dataorder.DataTypeFilter;
import net.luckperms.api.query.dataorder.DataTypeFilterFunction;
import java.util.Comparator;
import java.util.function.Predicate;
public final class DataSelector {
private DataSelector() {}
// These arrays are only ever exposed internally - we ensure they don't get modified
private static final DataType[] TRANSIENT_NORMAL = new DataType[]{DataType.TRANSIENT, DataType.NORMAL};
private static final DataType[] NORMAL_TRANSIENT = new DataType[]{DataType.NORMAL, DataType.TRANSIENT};
private static final DataType[] NORMAL = new DataType[]{DataType.NORMAL};
private static final DataType[] TRANSIENT = new DataType[]{DataType.TRANSIENT};
private static final DataType[] NONE = new DataType[0];
public static DataType[] select(QueryOptions queryOptions, PermissionHolder.Identifier identifier) {
final DataQueryOrderFunction orderFunc = queryOptions.option(DataQueryOrderFunction.KEY).orElse(null);
final DataTypeFilterFunction filterFunc = queryOptions.option(DataTypeFilterFunction.KEY).orElse(null);
if (orderFunc == null && filterFunc == null) {
return TRANSIENT_NORMAL;
}
Predicate<DataType> predicate = filterFunc != null ? filterFunc.getTypeFilter(identifier) : DataTypeFilter.ALL;
boolean normal = predicate.test(DataType.NORMAL);
boolean trans = predicate.test(DataType.TRANSIENT);
// if both are included - we need to consult the order comparator
if (normal && trans) {
Comparator<DataType> comparator = orderFunc != null ? orderFunc.getOrderComparator(identifier) : DataQueryOrder.TRANSIENT_FIRST;
int compare = comparator.compare(DataType.TRANSIENT, DataType.NORMAL);
if (compare == 0) {
throw new IllegalStateException("Comparator " + comparator + " does not define an order between DataType.NORMAL and DataType.TRANSIENT!");
}
return compare > 0 ? TRANSIENT_NORMAL : NORMAL_TRANSIENT;
}
// otherwise, no need to worry about order
if (normal) {
return NORMAL;
} else if (trans) {
return TRANSIENT;
} else {
return NONE;
}
}
}