diff --git a/api/src/main/java/me/lucko/luckperms/api/Log.java b/api/src/main/java/me/lucko/luckperms/api/Log.java index 2ae3f8d90..43a05121b 100644 --- a/api/src/main/java/me/lucko/luckperms/api/Log.java +++ b/api/src/main/java/me/lucko/luckperms/api/Log.java @@ -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 getContent(); /** - * Get the content of the log - * - * @return all content in this log - */ - @Nonnull - SortedSet 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 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 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 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 getContent(@Nonnull UUID actor); /** * Gets the log content for a given user @@ -119,27 +70,6 @@ public interface Log { @Nonnull SortedSet 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 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 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 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 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 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 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 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); - } diff --git a/common/src/main/java/me/lucko/luckperms/common/actionlog/Log.java b/common/src/main/java/me/lucko/luckperms/common/actionlog/Log.java index 3069c1597..dc1c18c0b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/actionlog/Log.java +++ b/common/src/main/java/me/lucko/luckperms/common/actionlog/Log.java @@ -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 getPage(Set 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 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 content; public Log(SortedSet content) { this.content = ImmutableSortedSet.copyOfSorted(content); } - public SortedSet getRecent() { + public SortedSet getContent() { return this.content; } - public SortedMap getRecent(int pageNo, int entriesPerPage) { - return getPage(this.content, pageNo, entriesPerPage); - } - - public int getRecentMaxPages(int entriesPerPage) { - return getMaxPages(this.content.size(), entriesPerPage); - } - - public SortedSet getRecent(UUID actor) { + public SortedSet getContent(UUID actor) { return this.content.stream() .filter(e -> e.getActor().equals(actor)) .collect(Collectors.toCollection(TreeSet::new)); } - public SortedMap 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 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 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 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 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 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 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 getSearch(String query) { return this.content.stream() .filter(e -> e.matchesSearch(query)) - .collect(Collectors.toCollection(TreeSet::new)); + .collect(ImmutableCollectors.toSortedSet(Comparator.naturalOrder())); } - public SortedMap 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 getContent() { - return this.content; - } - - @SuppressWarnings("WeakerAccess") public static class Builder { private final SortedSet content = new TreeSet<>(); diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiLog.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiLog.java index e42b169a1..75d599543 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiLog.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiLog.java @@ -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 getRecent() { - return (SortedSet) this.handle.getRecent(); - } - - @Nonnull - @Override - public SortedMap 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 getRecent(@Nonnull UUID actor) { + public SortedSet getContent(@Nonnull UUID actor) { Objects.requireNonNull(actor, "actor"); - return (SortedSet) this.handle.getRecent(actor); - } - - @Nonnull - @Override - public SortedMap 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 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 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 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 getTrackHistory(@Nonnull String name) { Objects.requireNonNull(name, "name"); return (SortedSet) this.handle.getTrackHistory(checkName(name)); } - - @Nonnull - @Override - public SortedMap 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 getSearch(@Nonnull String query) { - Objects.requireNonNull(query, "query"); - return (SortedSet) this.handle.getSearch(query); - } - - @Nonnull - @Override - public SortedMap 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); - } } diff --git a/common/src/main/java/me/lucko/luckperms/common/command/utils/ArgumentParser.java b/common/src/main/java/me/lucko/luckperms/common/command/utils/ArgumentParser.java index 5b2920cad..1247f2d5e 100644 --- a/common/src/main/java/me/lucko/luckperms/common/command/utils/ArgumentParser.java +++ b/common/src/main/java/me/lucko/luckperms/common/command/utils/ArgumentParser.java @@ -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 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 {} diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/log/LogGroupHistory.java b/common/src/main/java/me/lucko/luckperms/common/commands/log/LogGroupHistory.java index 331b7003b..b5a73bc7c 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/log/LogGroupHistory.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/log/LogGroupHistory.java @@ -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 { @Override public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Log log, List 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 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 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 { return CommandResult.INVALID_ARGS; } - SortedMap entries = log.getGroupHistory(page, group, ENTRIES_PER_PAGE); + SortedMap 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); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/log/LogRecent.java b/common/src/main/java/me/lucko/luckperms/common/commands/log/LogRecent.java index 8552d8d50..d6c52bb0c 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/log/LogRecent.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/log/LogRecent.java @@ -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 { public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Log log, List args, String label) { if (args.isEmpty()) { // No page or user - return showLog(log.getRecentMaxPages(ENTRIES_PER_PAGE), null, sender, log); + Paginated 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 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; - } - } 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; - } - } + return CommandResult.INVALID_ARGS; } - if (args.size() != 2) { - // Just user - return showLog(log.getRecentMaxPages(uuid, ENTRIES_PER_PAGE), uuid, sender, log); + Paginated 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 { - 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); - } + return showLog(content.getMaxPages(ENTRIES_PER_PAGE), true, sender, content); } } - 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 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 { return CommandResult.INVALID_ARGS; } - SortedMap entries = (filter != null) ? log.getRecent(page, filter, ENTRIES_PER_PAGE) : log.getRecent(page, ENTRIES_PER_PAGE); - if (filter != null) { + SortedMap entries = log.getPage(page, ENTRIES_PER_PAGE); + if (specificUser) { String name = entries.values().stream().findAny().get().getActorName(); if (name.contains("@")) { name = name.split("@")[0]; diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/log/LogSearch.java b/common/src/main/java/me/lucko/luckperms/common/commands/log/LogSearch.java index 411568c25..cb9760ef7 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/log/LogSearch.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/log/LogSearch.java @@ -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 { 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 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 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 { return CommandResult.INVALID_ARGS; } - SortedMap entries = log.getSearch(page, query, ENTRIES_PER_PAGE); + SortedMap entries = log.getPage(page, ENTRIES_PER_PAGE); Message.LOG_SEARCH_HEADER.send(sender, query, page, maxPage); long now = System.currentTimeMillis() / 1000L; diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/log/LogTrackHistory.java b/common/src/main/java/me/lucko/luckperms/common/commands/log/LogTrackHistory.java index 526bb1a78..49c0b2c82 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/log/LogTrackHistory.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/log/LogTrackHistory.java @@ -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 { @Override public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Log log, List 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 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 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 { return CommandResult.INVALID_ARGS; } - SortedMap entries = log.getTrackHistory(page, track, ENTRIES_PER_PAGE); + SortedMap 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); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/log/LogUserHistory.java b/common/src/main/java/me/lucko/luckperms/common/commands/log/LogUserHistory.java index 3442df45a..758e46199 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/log/LogUserHistory.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/log/LogUserHistory.java @@ -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 { @Override public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Log log, List 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; - } - } 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; - } - } + return CommandResult.INVALID_ARGS; } - if (page == Integer.MIN_VALUE) { - page = log.getUserHistoryMaxPages(uuid, ENTRIES_PER_PAGE); - } + Paginated content = new Paginated<>(log.getUserHistory(uuid)); - return showLog(page, uuid, sender, log); + 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, UUID user, Sender sender, Log log) { - int maxPage = log.getUserHistoryMaxPages(user, ENTRIES_PER_PAGE); + private static CommandResult showLog(int page, Sender sender, Paginated 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 { return CommandResult.INVALID_ARGS; } - SortedMap entries = log.getUserHistory(page, user, ENTRIES_PER_PAGE); + SortedMap 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); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/user/UserClone.java b/common/src/main/java/me/lucko/luckperms/common/commands/user/UserClone.java index e9f421c45..6737f8c18 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/user/UserClone.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/user/UserClone.java @@ -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,35 +56,9 @@ public class UserClone extends SubCommand { 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; - } - } + return CommandResult.INVALID_ARGS; } User otherUser = plugin.getStorage().loadUser(uuid, null).join(); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/user/UserMainCommand.java b/common/src/main/java/me/lucko/luckperms/common/commands/user/UserMainCommand.java index e517a2053..5f3d28c7f 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/user/UserMainCommand.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/user/UserMainCommand.java @@ -80,8 +80,7 @@ public class UserMainCommand extends MainCommand { ); } - @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 { } } + 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); } diff --git a/common/src/main/java/me/lucko/luckperms/common/contexts/ContextManager.java b/common/src/main/java/me/lucko/luckperms/common/contexts/ContextManager.java index 26f2b7655..6f5edd914 100644 --- a/common/src/main/java/me/lucko/luckperms/common/contexts/ContextManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/contexts/ContextManager.java @@ -259,7 +259,7 @@ public abstract class ContextManager { return formContexts(subject, accumulator.makeImmutable()); } - private Contexts calculateStatic() { + Contexts calculateStatic() { MutableContextSet accumulator = MutableContextSet.create(); for (StaticContextCalculator calculator : this.staticCalculators) { diff --git a/common/src/main/java/me/lucko/luckperms/common/utils/ImmutableCollectors.java b/common/src/main/java/me/lucko/luckperms/common/utils/ImmutableCollectors.java index 42e197667..5df1bc70d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/utils/ImmutableCollectors.java +++ b/common/src/main/java/me/lucko/luckperms/common/utils/ImmutableCollectors.java @@ -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 Collector> toSortedSet(Comparator comparator) { + return Collector.of( + () -> new ImmutableSortedSet.Builder(comparator), + ImmutableSortedSet.Builder::add, + (l, r) -> l.addAll(r.build()), + ImmutableSortedSet.Builder::build + ); + } + public static Collector, ImmutableMap> toMap(Function keyMapper, Function valueMapper) { return Collector.of( ImmutableMap.Builder::new, diff --git a/common/src/main/java/me/lucko/luckperms/common/utils/Paginated.java b/common/src/main/java/me/lucko/luckperms/common/utils/Paginated.java new file mode 100644 index 000000000..7348bc015 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/utils/Paginated.java @@ -0,0 +1,88 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * 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 the element type + */ +public class Paginated { + private final List content; + + public Paginated(Collection content) { + this.content = ImmutableList.copyOf(content); + } + + public Paginated(Stream content) { + this.content = content.collect(ImmutableCollectors.toList()); + } + + public List getContent() { + return this.content; + } + + public int getMaxPages(int entriesPerPage) { + return (int) Math.ceil((double) this.content.size() / (double) entriesPerPage); + } + + public SortedMap 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 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; + } + +}