Cleanup action log formatting and pagination

This is technically a breaking change to the API, but I'm fairly certain hardly anyone is using these methods (the pagination functionality in the API is pretty useless)

Can always add them back if it becomes an issue
This commit is contained in:
Luck 2018-06-18 16:08:18 +01:00
parent 957a918bd6
commit 2036127612
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
14 changed files with 215 additions and 517 deletions

View File

@ -25,7 +25,6 @@
package me.lucko.luckperms.api;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.UUID;
@ -46,69 +45,21 @@ import javax.annotation.concurrent.Immutable;
public interface Log {
/**
* Get the content of the log
* Gets the {@link LogEntry}s that make up this log.
*
* @return a {@link SortedSet} of all of the {@link LogEntry} objects in this {@link Log}
* @return the content
*/
@Nonnull
SortedSet<LogEntry> getContent();
/**
* Get the content of the log
*
* @return all content in this log
*/
@Nonnull
SortedSet<LogEntry> getRecent();
/**
* Gets the recent content separated by page
*
* @param pageNo the page number
* @return the page content
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getRecentMaxPages()}
*/
@Nonnull
SortedMap<Integer, LogEntry> getRecent(int pageNo);
/**
* Gets the max page number for the recent pages.
*
* @return the max page number allowed in the {@link #getRecent(int)} method
*/
int getRecentMaxPages();
/**
* Gets the recent content for a given actor
* Gets the entries in the log performed by the given actor.
*
* @param actor the uuid of the actor to filter by
* @return all content in this log where is actor = uuid
* @return the content for the given actor
*/
@Nonnull
SortedSet<LogEntry> getRecent(@Nonnull UUID actor);
/**
* Gets the recent content for a given actor, separated by page
*
* @param pageNo the page number
* @param actor the uuid of the actor to filter by
* @return the page content
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getRecentMaxPages(UUID)}
*/
@Nonnull
SortedMap<Integer, LogEntry> getRecent(int pageNo, @Nonnull UUID actor);
/**
* Gets the max page number for the recent pages.
*
* @param actor the actor to filter by
* @return the max page number allowed in the {@link #getRecent(int, UUID)} method
*/
int getRecentMaxPages(@Nonnull UUID actor);
SortedSet<LogEntry> getContent(@Nonnull UUID actor);
/**
* Gets the log content for a given user
@ -119,27 +70,6 @@ public interface Log {
@Nonnull
SortedSet<LogEntry> getUserHistory(@Nonnull UUID uuid);
/**
* Gets the log content for a given user, separated by page
*
* @param pageNo the page number
* @param uuid the uuid of the acted user to filter by
* @return the page content
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getUserHistoryMaxPages(UUID)}
*/
@Nonnull
SortedMap<Integer, LogEntry> getUserHistory(int pageNo, @Nonnull UUID uuid);
/**
* Gets the max page number for the user history pages.
*
* @param uuid the uuid to filter by
* @return the max page number allowed in the {@link #getUserHistory(int, UUID)} method
*/
int getUserHistoryMaxPages(@Nonnull UUID uuid);
/**
* Gets the log content for a given group
*
@ -149,27 +79,6 @@ public interface Log {
@Nonnull
SortedSet<LogEntry> getGroupHistory(@Nonnull String name);
/**
* Gets the log content for a given group, separated by page
*
* @param pageNo the page number
* @param name the name of the acted group to filter by
* @return the page content
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getGroupHistoryMaxPages(String)}
*/
@Nonnull
SortedMap<Integer, LogEntry> getGroupHistory(int pageNo, @Nonnull String name);
/**
* Gets the max page number for the group history pages.
*
* @param name the name to filter by
* @return the max page number allowed in the {@link #getGroupHistory(int, String)} method
*/
int getGroupHistoryMaxPages(@Nonnull String name);
/**
* Gets the log content for a given track
*
@ -179,54 +88,4 @@ public interface Log {
@Nonnull
SortedSet<LogEntry> getTrackHistory(@Nonnull String name);
/**
* Gets the log content for a given track, separated by page
*
* @param pageNo the page number
* @param name the name of the acted track to filter by
* @return the page content
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getTrackHistoryMaxPages(String)}
*/
@Nonnull
SortedMap<Integer, LogEntry> getTrackHistory(int pageNo, @Nonnull String name);
/**
* Gets the max page number for the track history pages.
*
* @param name the name to filter by
* @return the max page number allowed in the {@link #getTrackHistory(int, String)} method
*/
int getTrackHistoryMaxPages(@Nonnull String name);
/**
* Gets the log content for a given search query
*
* @param query the query to filter by
* @return all content in this log where the content matches query
*/
@Nonnull
SortedSet<LogEntry> getSearch(@Nonnull String query);
/**
* Gets the log content for a given search query, separated by page
*
* @param pageNo the page number
* @param query the query to filter by
* @return the page content
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getSearchMaxPages(String)}}
*/
@Nonnull
SortedMap<Integer, LogEntry> getSearch(int pageNo, @Nonnull String query);
/**
* Gets the max page number for the search query pages.
*
* @param query the query to filter by
* @return the max page number allowed in the {@link #getSearch(int, String)} method
*/
int getSearchMaxPages(@Nonnull String query);
}

View File

@ -28,11 +28,10 @@ package me.lucko.luckperms.common.actionlog;
import com.google.common.collect.ImmutableSortedSet;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.common.utils.ImmutableCollectors;
import java.util.Set;
import java.util.SortedMap;
import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.UUID;
import java.util.stream.Collectors;
@ -51,149 +50,49 @@ public class Log {
return empty;
}
private static SortedMap<Integer, ExtendedLogEntry> getPage(Set<ExtendedLogEntry> set, int pageNo, int entries) {
if (pageNo < 1) {
throw new IllegalArgumentException("pageNo cannot be less than 1: " + pageNo);
}
int minimumEntries = ((pageNo * entries) - entries) + 1;
if (set.size() < minimumEntries) {
throw new IllegalStateException("Log does not contain that many entries. " +
"Requested: " + minimumEntries + ", Log Count: " + set.size());
}
final SortedMap<Integer, ExtendedLogEntry> out = new TreeMap<>();
final int max = minimumEntries + entries - 1;
int index = 0;
for (ExtendedLogEntry e : set) {
index++;
if (index >= minimumEntries) {
out.put(index, e);
}
if (index == max) {
break;
}
}
return out;
}
private static int getMaxPages(int size, int entries) {
return (int) Math.ceil((double) size / (double) entries);
}
private final SortedSet<ExtendedLogEntry> content;
public Log(SortedSet<ExtendedLogEntry> content) {
this.content = ImmutableSortedSet.copyOfSorted(content);
}
public SortedSet<ExtendedLogEntry> getRecent() {
public SortedSet<ExtendedLogEntry> getContent() {
return this.content;
}
public SortedMap<Integer, ExtendedLogEntry> getRecent(int pageNo, int entriesPerPage) {
return getPage(this.content, pageNo, entriesPerPage);
}
public int getRecentMaxPages(int entriesPerPage) {
return getMaxPages(this.content.size(), entriesPerPage);
}
public SortedSet<ExtendedLogEntry> getRecent(UUID actor) {
public SortedSet<ExtendedLogEntry> getContent(UUID actor) {
return this.content.stream()
.filter(e -> e.getActor().equals(actor))
.collect(Collectors.toCollection(TreeSet::new));
}
public SortedMap<Integer, ExtendedLogEntry> getRecent(int pageNo, UUID actor, int entriesPerPage) {
return getPage(getRecent(actor), pageNo, entriesPerPage);
}
public int getRecentMaxPages(UUID actor, int entriesPerPage) {
return getMaxPages(this.content.stream()
.filter(e -> e.getActor().equals(actor))
.mapToInt(x -> 1).sum(), entriesPerPage);
}
public SortedSet<ExtendedLogEntry> getUserHistory(UUID uuid) {
return this.content.stream()
.filter(e -> e.getType() == LogEntry.Type.USER)
.filter(e -> e.getActed().isPresent())
.filter(e -> e.getActed().get().equals(uuid))
.collect(Collectors.toCollection(TreeSet::new));
}
public SortedMap<Integer, ExtendedLogEntry> getUserHistory(int pageNo, UUID uuid, int entriesPerPage) {
return getPage(getUserHistory(uuid), pageNo, entriesPerPage);
}
public int getUserHistoryMaxPages(UUID uuid, int entriesPerPage) {
return getMaxPages(this.content.stream()
.filter(e -> e.getType() == LogEntry.Type.USER)
.filter(e -> e.getActed().isPresent())
.filter(e -> e.getActed().get().equals(uuid))
.mapToInt(x -> 1).sum(), entriesPerPage);
.filter(e -> e.getActed().isPresent() && e.getActed().get().equals(uuid))
.collect(ImmutableCollectors.toSortedSet(Comparator.naturalOrder()));
}
public SortedSet<ExtendedLogEntry> getGroupHistory(String name) {
return this.content.stream()
.filter(e -> e.getType() == LogEntry.Type.GROUP)
.filter(e -> e.getActedName().equals(name))
.collect(Collectors.toCollection(TreeSet::new));
}
public SortedMap<Integer, ExtendedLogEntry> getGroupHistory(int pageNo, String name, int entriesPerPage) {
return getPage(getGroupHistory(name), pageNo, entriesPerPage);
}
public int getGroupHistoryMaxPages(String name, int entriesPerPage) {
return getMaxPages(this.content.stream()
.filter(e -> e.getType() == LogEntry.Type.GROUP)
.filter(e -> e.getActedName().equals(name))
.mapToInt(x -> 1).sum(), entriesPerPage);
.collect(ImmutableCollectors.toSortedSet(Comparator.naturalOrder()));
}
public SortedSet<ExtendedLogEntry> getTrackHistory(String name) {
return this.content.stream()
.filter(e -> e.getType() == LogEntry.Type.TRACK)
.filter(e -> e.getActedName().equals(name))
.collect(Collectors.toCollection(TreeSet::new));
}
public SortedMap<Integer, ExtendedLogEntry> getTrackHistory(int pageNo, String name, int entriesPerPage) {
return getPage(getTrackHistory(name), pageNo, entriesPerPage);
}
public int getTrackHistoryMaxPages(String name, int entriesPerPage) {
return getMaxPages(this.content.stream()
.filter(e -> e.getType() == LogEntry.Type.TRACK)
.filter(e -> e.getActedName().equals(name))
.mapToInt(x -> 1).sum(), entriesPerPage);
.collect(ImmutableCollectors.toSortedSet(Comparator.naturalOrder()));
}
public SortedSet<ExtendedLogEntry> getSearch(String query) {
return this.content.stream()
.filter(e -> e.matchesSearch(query))
.collect(Collectors.toCollection(TreeSet::new));
.collect(ImmutableCollectors.toSortedSet(Comparator.naturalOrder()));
}
public SortedMap<Integer, ExtendedLogEntry> getSearch(int pageNo, String query, int entriesPerPage) {
return getPage(getSearch(query), pageNo, entriesPerPage);
}
public int getSearchMaxPages(String query, int entriesPerPage) {
return getMaxPages(this.content.stream()
.filter(e -> e.matchesSearch(query))
.mapToInt(x -> 1).sum(), entriesPerPage);
}
public SortedSet<ExtendedLogEntry> getContent() {
return this.content;
}
@SuppressWarnings("WeakerAccess")
public static class Builder {
private final SortedSet<ExtendedLogEntry> content = new TreeSet<>();

View File

@ -25,12 +25,10 @@
package me.lucko.luckperms.common.api.delegates.model;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.common.actionlog.Log;
import java.util.Objects;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.UUID;
@ -40,7 +38,6 @@ import static me.lucko.luckperms.common.api.ApiUtils.checkName;
@SuppressWarnings("unchecked")
public class ApiLog implements me.lucko.luckperms.api.Log {
private static final int ENTRIES_PER_PAGE = 5;
private final Log handle;
public ApiLog(Log handle) {
@ -55,39 +52,9 @@ public class ApiLog implements me.lucko.luckperms.api.Log {
@Nonnull
@Override
public SortedSet<LogEntry> getRecent() {
return (SortedSet) this.handle.getRecent();
}
@Nonnull
@Override
public SortedMap<Integer, LogEntry> getRecent(int pageNo) {
return (SortedMap) this.handle.getRecent(pageNo, ENTRIES_PER_PAGE);
}
@Override
public int getRecentMaxPages() {
return this.handle.getRecentMaxPages(ENTRIES_PER_PAGE);
}
@Nonnull
@Override
public SortedSet<LogEntry> getRecent(@Nonnull UUID actor) {
public SortedSet<LogEntry> getContent(@Nonnull UUID actor) {
Objects.requireNonNull(actor, "actor");
return (SortedSet) this.handle.getRecent(actor);
}
@Nonnull
@Override
public SortedMap<Integer, LogEntry> getRecent(int pageNo, @Nonnull UUID actor) {
Objects.requireNonNull(actor, "actor");
return (SortedMap) this.handle.getRecent(pageNo, actor, ENTRIES_PER_PAGE);
}
@Override
public int getRecentMaxPages(@Nonnull UUID actor) {
Objects.requireNonNull(actor, "actor");
return this.handle.getRecentMaxPages(actor, ENTRIES_PER_PAGE);
return (SortedSet) this.handle.getContent(actor);
}
@Nonnull
@ -97,19 +64,6 @@ public class ApiLog implements me.lucko.luckperms.api.Log {
return (SortedSet) this.handle.getUserHistory(uuid);
}
@Nonnull
@Override
public SortedMap<Integer, LogEntry> getUserHistory(int pageNo, @Nonnull UUID uuid) {
Objects.requireNonNull(uuid, "uuid");
return (SortedMap) this.handle.getUserHistory(pageNo, uuid, ENTRIES_PER_PAGE);
}
@Override
public int getUserHistoryMaxPages(@Nonnull UUID uuid) {
Objects.requireNonNull(uuid, "uuid");
return this.handle.getUserHistoryMaxPages(uuid, ENTRIES_PER_PAGE);
}
@Nonnull
@Override
public SortedSet<LogEntry> getGroupHistory(@Nonnull String name) {
@ -117,56 +71,10 @@ public class ApiLog implements me.lucko.luckperms.api.Log {
return (SortedSet) this.handle.getGroupHistory(checkName(name));
}
@Nonnull
@Override
public SortedMap<Integer, LogEntry> getGroupHistory(int pageNo, @Nonnull String name) {
Objects.requireNonNull(name, "name");
return (SortedMap) this.handle.getGroupHistory(pageNo, checkName(name), ENTRIES_PER_PAGE);
}
@Override
public int getGroupHistoryMaxPages(@Nonnull String name) {
Objects.requireNonNull(name, "name");
return this.handle.getGroupHistoryMaxPages(checkName(name), ENTRIES_PER_PAGE);
}
@Nonnull
@Override
public SortedSet<LogEntry> getTrackHistory(@Nonnull String name) {
Objects.requireNonNull(name, "name");
return (SortedSet) this.handle.getTrackHistory(checkName(name));
}
@Nonnull
@Override
public SortedMap<Integer, LogEntry> getTrackHistory(int pageNo, @Nonnull String name) {
Objects.requireNonNull(name, "name");
return (SortedMap) this.handle.getTrackHistory(pageNo, checkName(name), ENTRIES_PER_PAGE);
}
@Override
public int getTrackHistoryMaxPages(@Nonnull String name) {
Objects.requireNonNull(name, "name");
return this.handle.getTrackHistoryMaxPages(checkName(name), ENTRIES_PER_PAGE);
}
@Nonnull
@Override
public SortedSet<LogEntry> getSearch(@Nonnull String query) {
Objects.requireNonNull(query, "query");
return (SortedSet) this.handle.getSearch(query);
}
@Nonnull
@Override
public SortedMap<Integer, LogEntry> getSearch(int pageNo, @Nonnull String query) {
Objects.requireNonNull(query, "query");
return (SortedMap) this.handle.getSearch(pageNo, query, ENTRIES_PER_PAGE);
}
@Override
public int getSearchMaxPages(@Nonnull String query) {
Objects.requireNonNull(query, "query");
return this.handle.getSearchMaxPages(query, ENTRIES_PER_PAGE);
}
}

View File

@ -29,14 +29,17 @@ import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.api.context.MutableContextSet;
import me.lucko.luckperms.common.command.abstraction.CommandException;
import me.lucko.luckperms.common.commands.user.UserMainCommand;
import me.lucko.luckperms.common.model.TemporaryModifier;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints;
import me.lucko.luckperms.common.utils.DateParser;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
/**
* Utility class to help process arguments, and throw checked exceptions if the arguments are invalid.
@ -252,6 +255,11 @@ public class ArgumentParser {
return contextSet.makeImmutable();
}
public static UUID parseUserTarget(int index, List<String> args, LuckPermsPlugin plugin, Sender sender) {
final String target = args.get(index);
return UserMainCommand.parseTargetUuid(target, plugin, sender);
}
public abstract static class ArgumentException extends CommandException {}
public static class DetailedUsageException extends ArgumentException {}
public static class InvalidServerWorldException extends ArgumentException {}

View File

@ -30,6 +30,7 @@ import me.lucko.luckperms.common.actionlog.Log;
import me.lucko.luckperms.common.command.CommandResult;
import me.lucko.luckperms.common.command.abstraction.SubCommand;
import me.lucko.luckperms.common.command.access.CommandPermission;
import me.lucko.luckperms.common.command.utils.ArgumentParser;
import me.lucko.luckperms.common.command.utils.TabCompletions;
import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.command.CommandSpec;
@ -38,6 +39,7 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints;
import me.lucko.luckperms.common.utils.DurationFormatter;
import me.lucko.luckperms.common.utils.Paginated;
import me.lucko.luckperms.common.utils.Predicates;
import java.util.List;
@ -54,24 +56,23 @@ public class LogGroupHistory extends SubCommand<Log> {
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Log log, List<String> args, String label) {
String group = args.get(0).toLowerCase();
int page = Integer.MIN_VALUE;
if (args.size() == 2) {
try {
page = Integer.parseInt(args.get(1));
} catch (NumberFormatException e) {
// invalid page
Message.LOG_INVALID_PAGE.send(sender);
return CommandResult.INVALID_ARGS;
}
}
if (!DataConstraints.GROUP_NAME_TEST.test(group)) {
Message.GROUP_INVALID_ENTRY.send(sender, group);
return CommandResult.INVALID_ARGS;
}
int maxPage = log.getGroupHistoryMaxPages(group, ENTRIES_PER_PAGE);
Paginated<ExtendedLogEntry> content = new Paginated<>(log.getGroupHistory(group));
int page = ArgumentParser.parseIntOrElse(1, args, Integer.MIN_VALUE);
if (page != Integer.MIN_VALUE) {
return showLog(page, sender, content);
} else {
return showLog(content.getMaxPages(ENTRIES_PER_PAGE), sender, content);
}
}
private static CommandResult showLog(int page, Sender sender, Paginated<ExtendedLogEntry> log) {
int maxPage = log.getMaxPages(ENTRIES_PER_PAGE);
if (maxPage == 0) {
Message.LOG_NO_ENTRIES.send(sender);
return CommandResult.STATE_ERROR;
@ -86,7 +87,7 @@ public class LogGroupHistory extends SubCommand<Log> {
return CommandResult.INVALID_ARGS;
}
SortedMap<Integer, ExtendedLogEntry> entries = log.getGroupHistory(page, group, ENTRIES_PER_PAGE);
SortedMap<Integer, ExtendedLogEntry> entries = log.getPage(page, ENTRIES_PER_PAGE);
String name = entries.values().stream().findAny().get().getActedName();
Message.LOG_HISTORY_GROUP_HEADER.send(sender, name, page, maxPage);

View File

@ -30,16 +30,15 @@ import me.lucko.luckperms.common.actionlog.Log;
import me.lucko.luckperms.common.command.CommandResult;
import me.lucko.luckperms.common.command.abstraction.SubCommand;
import me.lucko.luckperms.common.command.access.CommandPermission;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.command.utils.ArgumentParser;
import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints;
import me.lucko.luckperms.common.utils.DurationFormatter;
import me.lucko.luckperms.common.utils.Paginated;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.common.utils.Uuids;
import java.util.List;
import java.util.Map;
@ -57,67 +56,33 @@ public class LogRecent extends SubCommand<Log> {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Log log, List<String> args, String label) {
if (args.isEmpty()) {
// No page or user
return showLog(log.getRecentMaxPages(ENTRIES_PER_PAGE), null, sender, log);
Paginated<ExtendedLogEntry> content = new Paginated<>(log.getContent());
return showLog(content.getMaxPages(ENTRIES_PER_PAGE), false, sender, content);
}
if (args.size() == 1) {
// Page or user
try {
int p = Integer.parseInt(args.get(0));
// page
return showLog(p, null, sender, log);
} catch (NumberFormatException ignored) {
}
int page = ArgumentParser.parseIntOrElse(0, args, Integer.MIN_VALUE);
if (page != Integer.MIN_VALUE) {
Paginated<ExtendedLogEntry> content = new Paginated<>(log.getContent());
return showLog(page, false, sender, content);
}
// User and possibly page
final String target = args.get(0);
UUID uuid = Uuids.parseNullable(target);
UUID uuid = ArgumentParser.parseUserTarget(0, args, plugin, sender);
if (uuid == null) {
if (!plugin.getConfiguration().get(ConfigKeys.ALLOW_INVALID_USERNAMES)) {
if (!DataConstraints.PLAYER_USERNAME_TEST.test(target)) {
Message.USER_INVALID_ENTRY.send(sender, target);
return CommandResult.INVALID_ARGS;
}
Paginated<ExtendedLogEntry> content = new Paginated<>(log.getContent(uuid));
page = ArgumentParser.parseIntOrElse(1, args, Integer.MIN_VALUE);
if (page != Integer.MIN_VALUE) {
return showLog(page, true, sender, content);
} else {
if (!DataConstraints.PLAYER_USERNAME_TEST_LENIENT.test(target)) {
Message.USER_INVALID_ENTRY.send(sender, target);
return CommandResult.INVALID_ARGS;
return showLog(content.getMaxPages(ENTRIES_PER_PAGE), true, sender, content);
}
}
uuid = plugin.getStorage().getPlayerUuid(target.toLowerCase()).join();
if (uuid == null) {
if (!plugin.getConfiguration().get(ConfigKeys.USE_SERVER_UUID_CACHE)) {
Message.USER_NOT_FOUND.send(sender, target);
return CommandResult.INVALID_ARGS;
}
uuid = plugin.getBootstrap().lookupUuid(target).orElse(null);
if (uuid == null) {
Message.USER_NOT_FOUND.send(sender, target);
return CommandResult.INVALID_ARGS;
}
}
}
if (args.size() != 2) {
// Just user
return showLog(log.getRecentMaxPages(uuid, ENTRIES_PER_PAGE), uuid, sender, log);
} else {
try {
int p = Integer.parseInt(args.get(1));
// User and page
return showLog(p, uuid, sender, log);
} catch (NumberFormatException e) {
// Invalid page
return showLog(-1, null, sender, log);
}
}
}
private static CommandResult showLog(int page, UUID filter, Sender sender, Log log) {
int maxPage = (filter != null) ? log.getRecentMaxPages(filter, ENTRIES_PER_PAGE) : log.getRecentMaxPages(ENTRIES_PER_PAGE);
private static CommandResult showLog(int page, boolean specificUser, Sender sender, Paginated<ExtendedLogEntry> log) {
int maxPage = log.getMaxPages(ENTRIES_PER_PAGE);
if (maxPage == 0) {
Message.LOG_NO_ENTRIES.send(sender);
return CommandResult.STATE_ERROR;
@ -128,8 +93,8 @@ public class LogRecent extends SubCommand<Log> {
return CommandResult.INVALID_ARGS;
}
SortedMap<Integer, ExtendedLogEntry> entries = (filter != null) ? log.getRecent(page, filter, ENTRIES_PER_PAGE) : log.getRecent(page, ENTRIES_PER_PAGE);
if (filter != null) {
SortedMap<Integer, ExtendedLogEntry> entries = log.getPage(page, ENTRIES_PER_PAGE);
if (specificUser) {
String name = entries.values().stream().findAny().get().getActorName();
if (name.contains("@")) {
name = name.split("@")[0];

View File

@ -36,6 +36,7 @@ import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.utils.DurationFormatter;
import me.lucko.luckperms.common.utils.Paginated;
import me.lucko.luckperms.common.utils.Predicates;
import java.util.List;
@ -57,13 +58,23 @@ public class LogSearch extends SubCommand<Log> {
try {
page = Integer.parseInt(args.get(args.size() - 1));
args.remove(args.size() - 1);
} catch (NumberFormatException ignored) {
} catch (NumberFormatException e) {
// ignored
}
}
final String query = args.stream().collect(Collectors.joining(" "));
Paginated<ExtendedLogEntry> content = new Paginated<>(log.getSearch(query));
int maxPage = log.getSearchMaxPages(query, ENTRIES_PER_PAGE);
if (page != Integer.MIN_VALUE) {
return showLog(page, query, sender, content);
} else {
return showLog(content.getMaxPages(ENTRIES_PER_PAGE), query, sender, content);
}
}
private static CommandResult showLog(int page, String query, Sender sender, Paginated<ExtendedLogEntry> log) {
int maxPage = log.getMaxPages(ENTRIES_PER_PAGE);
if (maxPage == 0) {
Message.LOG_NO_ENTRIES.send(sender);
return CommandResult.STATE_ERROR;
@ -78,7 +89,7 @@ public class LogSearch extends SubCommand<Log> {
return CommandResult.INVALID_ARGS;
}
SortedMap<Integer, ExtendedLogEntry> entries = log.getSearch(page, query, ENTRIES_PER_PAGE);
SortedMap<Integer, ExtendedLogEntry> entries = log.getPage(page, ENTRIES_PER_PAGE);
Message.LOG_SEARCH_HEADER.send(sender, query, page, maxPage);
long now = System.currentTimeMillis() / 1000L;

View File

@ -30,6 +30,7 @@ import me.lucko.luckperms.common.actionlog.Log;
import me.lucko.luckperms.common.command.CommandResult;
import me.lucko.luckperms.common.command.abstraction.SubCommand;
import me.lucko.luckperms.common.command.access.CommandPermission;
import me.lucko.luckperms.common.command.utils.ArgumentParser;
import me.lucko.luckperms.common.command.utils.TabCompletions;
import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.command.CommandSpec;
@ -38,6 +39,7 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints;
import me.lucko.luckperms.common.utils.DurationFormatter;
import me.lucko.luckperms.common.utils.Paginated;
import me.lucko.luckperms.common.utils.Predicates;
import java.util.List;
@ -54,24 +56,23 @@ public class LogTrackHistory extends SubCommand<Log> {
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Log log, List<String> args, String label) {
String track = args.get(0).toLowerCase();
int page = Integer.MIN_VALUE;
if (args.size() == 2) {
try {
page = Integer.parseInt(args.get(1));
} catch (NumberFormatException e) {
// invalid page
Message.LOG_INVALID_PAGE.send(sender);
return CommandResult.INVALID_ARGS;
}
}
if (!DataConstraints.TRACK_NAME_TEST.test(track)) {
Message.TRACK_INVALID_ENTRY.send(sender, track);
return CommandResult.INVALID_ARGS;
}
int maxPage = log.getTrackHistoryMaxPages(track, ENTRIES_PER_PAGE);
Paginated<ExtendedLogEntry> content = new Paginated<>(log.getTrackHistory(track));
int page = ArgumentParser.parseIntOrElse(1, args, Integer.MIN_VALUE);
if (page != Integer.MIN_VALUE) {
return showLog(page, sender, content);
} else {
return showLog(content.getMaxPages(ENTRIES_PER_PAGE), sender, content);
}
}
private static CommandResult showLog(int page, Sender sender, Paginated<ExtendedLogEntry> log) {
int maxPage = log.getMaxPages(ENTRIES_PER_PAGE);
if (maxPage == 0) {
Message.LOG_NO_ENTRIES.send(sender);
return CommandResult.STATE_ERROR;
@ -86,7 +87,7 @@ public class LogTrackHistory extends SubCommand<Log> {
return CommandResult.INVALID_ARGS;
}
SortedMap<Integer, ExtendedLogEntry> entries = log.getTrackHistory(page, track, ENTRIES_PER_PAGE);
SortedMap<Integer, ExtendedLogEntry> entries = log.getPage(page, ENTRIES_PER_PAGE);
String name = entries.values().stream().findAny().get().getActedName();
Message.LOG_HISTORY_TRACK_HEADER.send(sender, name, page, maxPage);

View File

@ -30,16 +30,15 @@ import me.lucko.luckperms.common.actionlog.Log;
import me.lucko.luckperms.common.command.CommandResult;
import me.lucko.luckperms.common.command.abstraction.SubCommand;
import me.lucko.luckperms.common.command.access.CommandPermission;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.command.utils.ArgumentParser;
import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints;
import me.lucko.luckperms.common.utils.DurationFormatter;
import me.lucko.luckperms.common.utils.Paginated;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.common.utils.Uuids;
import java.util.List;
import java.util.Map;
@ -55,56 +54,23 @@ public class LogUserHistory extends SubCommand<Log> {
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Log log, List<String> args, String label) {
String target = args.get(0);
int page = Integer.MIN_VALUE;
if (args.size() == 2) {
try {
page = Integer.parseInt(args.get(1));
} catch (NumberFormatException e) {
// invalid page
return showLog(-1, null, sender, log);
}
}
UUID uuid = Uuids.parseNullable(target);
UUID uuid = ArgumentParser.parseUserTarget(0, args, plugin, sender);
if (uuid == null) {
if (!plugin.getConfiguration().get(ConfigKeys.ALLOW_INVALID_USERNAMES)) {
if (!DataConstraints.PLAYER_USERNAME_TEST.test(target)) {
Message.USER_INVALID_ENTRY.send(sender, target);
return CommandResult.INVALID_ARGS;
}
Paginated<ExtendedLogEntry> content = new Paginated<>(log.getUserHistory(uuid));
int page = ArgumentParser.parseIntOrElse(1, args, Integer.MIN_VALUE);
if (page != Integer.MIN_VALUE) {
return showLog(page, sender, content);
} else {
if (!DataConstraints.PLAYER_USERNAME_TEST_LENIENT.test(target)) {
Message.USER_INVALID_ENTRY.send(sender, target);
return CommandResult.INVALID_ARGS;
return showLog(content.getMaxPages(ENTRIES_PER_PAGE), sender, content);
}
}
uuid = plugin.getStorage().getPlayerUuid(target.toLowerCase()).join();
if (uuid == null) {
if (!plugin.getConfiguration().get(ConfigKeys.USE_SERVER_UUID_CACHE)) {
Message.USER_NOT_FOUND.send(sender, target);
return CommandResult.INVALID_ARGS;
}
uuid = plugin.getBootstrap().lookupUuid(target).orElse(null);
if (uuid == null) {
Message.USER_NOT_FOUND.send(sender, target);
return CommandResult.INVALID_ARGS;
}
}
}
if (page == Integer.MIN_VALUE) {
page = log.getUserHistoryMaxPages(uuid, ENTRIES_PER_PAGE);
}
return showLog(page, uuid, sender, log);
}
private static CommandResult showLog(int page, UUID user, Sender sender, Log log) {
int maxPage = log.getUserHistoryMaxPages(user, ENTRIES_PER_PAGE);
private static CommandResult showLog(int page, Sender sender, Paginated<ExtendedLogEntry> log) {
int maxPage = log.getMaxPages(ENTRIES_PER_PAGE);
if (maxPage == 0) {
Message.LOG_NO_ENTRIES.send(sender);
return CommandResult.STATE_ERROR;
@ -115,7 +81,7 @@ public class LogUserHistory extends SubCommand<Log> {
return CommandResult.INVALID_ARGS;
}
SortedMap<Integer, ExtendedLogEntry> entries = log.getUserHistory(page, user, ENTRIES_PER_PAGE);
SortedMap<Integer, ExtendedLogEntry> entries = log.getPage(page, ENTRIES_PER_PAGE);
String name = entries.values().stream().findAny().get().getActedName();
Message.LOG_HISTORY_USER_HEADER.send(sender, name, page, maxPage);

View File

@ -30,8 +30,8 @@ import me.lucko.luckperms.common.command.CommandResult;
import me.lucko.luckperms.common.command.abstraction.SubCommand;
import me.lucko.luckperms.common.command.access.ArgumentPermissions;
import me.lucko.luckperms.common.command.access.CommandPermission;
import me.lucko.luckperms.common.command.utils.ArgumentParser;
import me.lucko.luckperms.common.command.utils.StorageAssistant;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message;
@ -39,9 +39,7 @@ import me.lucko.luckperms.common.model.NodeMapType;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.common.utils.Uuids;
import java.util.List;
import java.util.UUID;
@ -58,36 +56,10 @@ public class UserClone extends SubCommand<User> {
return CommandResult.NO_PERMISSION;
}
String target = args.get(0);
UUID uuid = Uuids.parseNullable(target);
UUID uuid = ArgumentParser.parseUserTarget(0, args, plugin, sender);
if (uuid == null) {
if (!plugin.getConfiguration().get(ConfigKeys.ALLOW_INVALID_USERNAMES)) {
if (!DataConstraints.PLAYER_USERNAME_TEST.test(target)) {
Message.USER_INVALID_ENTRY.send(sender, target);
return CommandResult.INVALID_ARGS;
}
} else {
if (!DataConstraints.PLAYER_USERNAME_TEST_LENIENT.test(target)) {
Message.USER_INVALID_ENTRY.send(sender, target);
return CommandResult.INVALID_ARGS;
}
}
uuid = plugin.getStorage().getPlayerUuid(target.toLowerCase()).join();
if (uuid == null) {
if (!plugin.getConfiguration().get(ConfigKeys.USE_SERVER_UUID_CACHE)) {
Message.USER_NOT_FOUND.send(sender, target);
return CommandResult.INVALID_ARGS;
}
uuid = plugin.getBootstrap().lookupUuid(target).orElse(null);
if (uuid == null) {
Message.USER_NOT_FOUND.send(sender, target);
return CommandResult.INVALID_ARGS;
}
}
}
User otherUser = plugin.getStorage().loadUser(uuid, null).join();
if (otherUser == null) {

View File

@ -80,8 +80,7 @@ public class UserMainCommand extends MainCommand<User, UserIdentifier> {
);
}
@Override
protected UserIdentifier parseTarget(String target, LuckPermsPlugin plugin, Sender sender) {
public static UUID parseTargetUuid(String target, LuckPermsPlugin plugin, Sender sender) {
UUID uuid = Uuids.parseNullable(target);
if (uuid == null) {
if (!plugin.getConfiguration().get(ConfigKeys.ALLOW_INVALID_USERNAMES)) {
@ -111,6 +110,16 @@ public class UserMainCommand extends MainCommand<User, UserIdentifier> {
}
}
return uuid;
}
@Override
protected UserIdentifier parseTarget(String target, LuckPermsPlugin plugin, Sender sender) {
UUID uuid = parseTargetUuid(target, plugin, sender);
if (uuid == null) {
return null;
}
String name = plugin.getStorage().getPlayerName(uuid).join();
return UserIdentifier.of(uuid, name);
}

View File

@ -259,7 +259,7 @@ public abstract class ContextManager<T> {
return formContexts(subject, accumulator.makeImmutable());
}
private Contexts calculateStatic() {
Contexts calculateStatic() {
MutableContextSet accumulator = MutableContextSet.create();
for (StaticContextCalculator calculator : this.staticCalculators) {

View File

@ -28,7 +28,9 @@ package me.lucko.luckperms.common.utils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.function.Function;
@ -70,6 +72,15 @@ public final class ImmutableCollectors {
);
}
public static <E> Collector<E, ?, ImmutableSortedSet<E>> toSortedSet(Comparator<? super E> comparator) {
return Collector.of(
() -> new ImmutableSortedSet.Builder<E>(comparator),
ImmutableSortedSet.Builder::add,
(l, r) -> l.addAll(r.build()),
ImmutableSortedSet.Builder::build
);
}
public static <T, K, V> Collector<T, ImmutableMap.Builder<K, V>, ImmutableMap<K, V>> toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends V> valueMapper) {
return Collector.of(
ImmutableMap.Builder<K, V>::new,

View File

@ -0,0 +1,88 @@
/*
* 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.utils;
import com.google.common.collect.ImmutableList;
import java.util.Collection;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.stream.Stream;
/**
* A simple pagination utility
*
* @param <T> the element type
*/
public class Paginated<T> {
private final List<T> content;
public Paginated(Collection<T> content) {
this.content = ImmutableList.copyOf(content);
}
public Paginated(Stream<T> content) {
this.content = content.collect(ImmutableCollectors.toList());
}
public List<T> getContent() {
return this.content;
}
public int getMaxPages(int entriesPerPage) {
return (int) Math.ceil((double) this.content.size() / (double) entriesPerPage);
}
public SortedMap<Integer, T> getPage(int pageNo, int entries) {
if (pageNo < 1) {
throw new IllegalArgumentException("pageNo cannot be less than 1: " + pageNo);
}
int minimumEntries = ((pageNo * entries) - entries) + 1;
if (this.content.size() < minimumEntries) {
throw new IllegalStateException("Content does not contain that many elements. " +
"Requested: " + minimumEntries + ", Size: " + this.content.size());
}
final SortedMap<Integer, T> out = new TreeMap<>();
final int max = minimumEntries + entries - 1;
int index = 0;
for (T e : this.content) {
index++;
if (index >= minimumEntries) {
out.put(index, e);
}
if (index == max) {
break;
}
}
return out;
}
}