diff --git a/api/src/main/java/me/lucko/luckperms/api/Storage.java b/api/src/main/java/me/lucko/luckperms/api/Storage.java index bede6fbc..e05140a0 100644 --- a/api/src/main/java/me/lucko/luckperms/api/Storage.java +++ b/api/src/main/java/me/lucko/luckperms/api/Storage.java @@ -25,6 +25,10 @@ package me.lucko.luckperms.api; +import me.lucko.luckperms.api.manager.GroupManager; +import me.lucko.luckperms.api.manager.TrackManager; +import me.lucko.luckperms.api.manager.UserManager; + import java.util.List; import java.util.Set; import java.util.UUID; @@ -38,13 +42,15 @@ import javax.annotation.Nullable; /** * A means of loading and saving permission data to/from the backend. * - *

All blocking methods return {@link CompletableFuture}s, which will be populated with the result once the data has been - * loaded/saved asynchronously. Care should be taken when using such methods to ensure that the main server thread is not - * blocked.

+ *

All blocking methods return {@link CompletableFuture}s, which will be + * populated with the result once the data has been loaded/saved asynchronously. + * Care should be taken when using such methods to ensure that the main server + * thread is not blocked.

* - *

Methods such as {@link CompletableFuture#get()} and equivalent should not be called on the main - * server thread. If you need to use the result of these operations on the main server thread, register a - * callback using {@link CompletableFuture#thenAcceptAsync(Consumer, Executor)} and {@link #getSyncExecutor()}.

+ *

Methods such as {@link CompletableFuture#get()} and equivalent should + * not be called on the main server thread. If you need to use + * the result of these operations on the main server thread, register a + * callback using {@link CompletableFuture#thenAcceptAsync(Consumer, Executor)}.

* * @since 2.14 */ @@ -58,42 +64,6 @@ public interface Storage { @Nonnull String getName(); - /** - * Gets whether the storage instance is allowing logins on the platform. - * - * @return true if logins are enabled - */ - boolean isAcceptingLogins(); - - /** - * Returns an executor which will run all passed runnables on the main server thread. - * - * @return an executor instance - */ - @Nonnull - Executor getSyncExecutor(); - - /** - * Returns an executor which will run all passed runnables asynchronously using the platforms scheduler and thread - * pools. - * - * @return an executor instance - */ - @Nonnull - Executor getAsyncExecutor(); - - /** - * Saves an action to storage - * - * @param entry the log entry to be saved - * @return true if the operation completed successfully. - * @throws NullPointerException if entry is null - * @deprecated in favour of {@link ActionLogger#submit(LogEntry)}. - */ - @Nonnull - @Deprecated - CompletableFuture logAction(@Nonnull LogEntry entry); - /** * Loads and returns the entire log from storage * @@ -102,40 +72,6 @@ public interface Storage { @Nonnull CompletableFuture getLog(); - /** - * Loads a user's data from the main storage into the plugins local storage. - * - * @param uuid the uuid of the user to load - * @param username the users username, or null if it is not known. - * @return if the operation completed successfully - * @throws NullPointerException if uuid is null - */ - @Nonnull - CompletableFuture loadUser(@Nonnull UUID uuid, @Nullable String username); - - /** - * Loads a user's data from the main storage into the plugins local storage. - * - * @param uuid the uuid of the user to load - * @return if the operation completed successfully - * @throws NullPointerException if uuid is null - */ - @Nonnull - default CompletableFuture loadUser(@Nonnull UUID uuid) { - return loadUser(uuid, null); - } - - /** - * Saves a user object back to storage. You should call this after you make any changes to a user. - * - * @param user the user to save - * @return true if the operation completed successfully. - * @throws NullPointerException if user is null - * @throws IllegalStateException if the user instance was not obtained from LuckPerms. - */ - @Nonnull - CompletableFuture saveUser(@Nonnull User user); - /** * Gets a set all "unique" user UUIDs. * @@ -157,58 +93,6 @@ public interface Storage { @Nonnull CompletableFuture>> getUsersWithPermission(@Nonnull String permission); - /** - * Creates and loads a group into the plugins local storage - * - * @param name the name of the group - * @return true if the operation completed successfully - * @throws NullPointerException if name is null - * @throws IllegalArgumentException if the name is invalid - */ - @Nonnull - CompletableFuture createAndLoadGroup(@Nonnull String name); - - /** - * Loads a group into the plugins local storage. - * - * @param name the name of the group - * @return true if the operation completed successfully - * @throws NullPointerException if name is null - * @throws IllegalArgumentException if the name is invalid - */ - @Nonnull - CompletableFuture loadGroup(@Nonnull String name); - - /** - * Loads all groups from the storage into memory - * - * @return true if the operation completed successfully. - */ - @Nonnull - CompletableFuture loadAllGroups(); - - /** - * Saves a group back to storage. You should call this after you make any changes to a group. - * - * @param group the group to save - * @return true if the operation completed successfully. - * @throws NullPointerException if group is null - * @throws IllegalStateException if the group instance was not obtained from LuckPerms. - */ - @Nonnull - CompletableFuture saveGroup(@Nonnull Group group); - - /** - * Permanently deletes a group from storage. - * - * @param group the group to delete - * @return true if the operation completed successfully. - * @throws NullPointerException if group is null - * @throws IllegalStateException if the group instance was not obtained from LuckPerms. - */ - @Nonnull - CompletableFuture deleteGroup(@Nonnull Group group); - /** * Searches for a list of groups with a given permission. * @@ -220,58 +104,6 @@ public interface Storage { @Nonnull CompletableFuture>> getGroupsWithPermission(@Nonnull String permission); - /** - * Creates and loads a track into the plugins local storage - * - * @param name the name of the track - * @return true if the operation completed successfully - * @throws NullPointerException if name is null - * @throws IllegalArgumentException if the name is invalid - */ - @Nonnull - CompletableFuture createAndLoadTrack(@Nonnull String name); - - /** - * Loads a track into the plugins local storage. - * - * @param name the name of the track - * @return true if the operation completed successfully - * @throws NullPointerException if name is null - * @throws IllegalArgumentException if the name is invalid - */ - @Nonnull - CompletableFuture loadTrack(@Nonnull String name); - - /** - * Loads all tracks from the storage into memory - * - * @return true if the operation completed successfully. - */ - @Nonnull - CompletableFuture loadAllTracks(); - - /** - * Saves a track back to storage. You should call this after you make any changes to a track. - * - * @param track the track to save - * @return true if the operation completed successfully. - * @throws NullPointerException if track is null - * @throws IllegalStateException if the track instance was not obtained from LuckPerms. - */ - @Nonnull - CompletableFuture saveTrack(@Nonnull Track track); - - /** - * Permanently deletes a track from storage - * - * @param track the track to delete - * @return true if the operation completed successfully. - * @throws NullPointerException if track is null - * @throws IllegalStateException if the track instance was not obtained from LuckPerms. - */ - @Nonnull - CompletableFuture deleteTrack(@Nonnull Track track); - /** * Saves UUID caching data to the global cache * @@ -306,4 +138,221 @@ public interface Storage { @Nonnull CompletableFuture getName(@Nonnull UUID uuid); + /** + * Gets whether the storage instance is allowing logins on the platform. + * + * @return true if logins are enabled + * @deprecated as this method always returns true. + */ + @Deprecated + boolean isAcceptingLogins(); + + /** + * Returns an executor which will run all passed runnables on the + * main server thread. + * + *

This method is deprecated as plugins should create and use their own + * executor instances.

+ * + * @return an executor instance + * @deprecated as plugins should create their own executors + */ + @Nonnull + @Deprecated + Executor getSyncExecutor(); + + /** + * Returns an executor which will run all passed runnables asynchronously + * using the platforms scheduler and thread pools. + * + *

This method is deprecated as plugins should create and use their own + * executor instances.

+ * + * @return an executor instance + * @deprecated as plugins should create their own executors + */ + @Nonnull + @Deprecated + Executor getAsyncExecutor(); + + /** + * Saves an action to storage + * + * @param entry the log entry to be saved + * @return true if the operation completed successfully. + * @throws NullPointerException if entry is null + * @deprecated in favour of {@link ActionLogger#submit(LogEntry)}. + */ + @Nonnull + @Deprecated + CompletableFuture logAction(@Nonnull LogEntry entry); + + /** + * Loads a user's data from the main storage into the plugins local storage. + * + * @param uuid the uuid of the user to load + * @param username the users username, or null if it is not known. + * @return if the operation completed successfully + * @throws NullPointerException if uuid is null + * @deprecated in favour of {@link UserManager#loadUser(UUID, String)} + */ + @Nonnull + @Deprecated + CompletableFuture loadUser(@Nonnull UUID uuid, @Nullable String username); + + /** + * Loads a user's data from the main storage into the plugins local storage. + * + * @param uuid the uuid of the user to load + * @return if the operation completed successfully + * @throws NullPointerException if uuid is null + * @deprecated in favour of {@link UserManager#loadUser(UUID)} + */ + @Nonnull + @Deprecated + default CompletableFuture loadUser(@Nonnull UUID uuid) { + return loadUser(uuid, null); + } + + /** + * Saves a user object back to storage. + * + *

You should call this after you make any changes to a user.

+ * + * @param user the user to save + * @return true if the operation completed successfully. + * @throws NullPointerException if user is null + * @throws IllegalStateException if the user instance was not obtained from LuckPerms. + * @deprecated in favour of {@link UserManager#saveUser(User)} + */ + @Nonnull + @Deprecated + CompletableFuture saveUser(@Nonnull User user); + + /** + * Creates and loads a group into the plugins local storage + * + * @param name the name of the group + * @return true if the operation completed successfully + * @throws NullPointerException if name is null + * @throws IllegalArgumentException if the name is invalid + * @deprecated in favour of {@link GroupManager#createAndLoadGroup(String)} + */ + @Nonnull + @Deprecated + CompletableFuture createAndLoadGroup(@Nonnull String name); + + /** + * Loads a group into the plugins local storage. + * + * @param name the name of the group + * @return true if the operation completed successfully + * @throws NullPointerException if name is null + * @throws IllegalArgumentException if the name is invalid + * @deprecated in favour of {@link GroupManager#loadGroup(String)} + */ + @Nonnull + @Deprecated + CompletableFuture loadGroup(@Nonnull String name); + + /** + * Loads all groups from the storage into memory + * + * @return true if the operation completed successfully. + * @deprecated in favour of {@link GroupManager#loadAllGroups()} + */ + @Nonnull + @Deprecated + CompletableFuture loadAllGroups(); + + /** + * Saves a group back to storage. + * + *

You should call this after you make any changes to a group.

+ * + * @param group the group to save + * @return true if the operation completed successfully. + * @throws NullPointerException if group is null + * @throws IllegalStateException if the group instance was not obtained from LuckPerms. + * @deprecated in favour of {@link GroupManager#saveGroup(Group)} + */ + @Nonnull + @Deprecated + CompletableFuture saveGroup(@Nonnull Group group); + + /** + * Permanently deletes a group from storage. + * + * @param group the group to delete + * @return true if the operation completed successfully. + * @throws NullPointerException if group is null + * @throws IllegalStateException if the group instance was not obtained from LuckPerms. + * @deprecated in favour of {@link GroupManager#deleteGroup(Group)} + */ + @Nonnull + @Deprecated + CompletableFuture deleteGroup(@Nonnull Group group); + + /** + * Creates and loads a track into the plugins local storage + * + * @param name the name of the track + * @return true if the operation completed successfully + * @throws NullPointerException if name is null + * @throws IllegalArgumentException if the name is invalid + * @deprecated in favour of {@link TrackManager#createAndLoadTrack(String)} + */ + @Nonnull + @Deprecated + CompletableFuture createAndLoadTrack(@Nonnull String name); + + /** + * Loads a track into the plugins local storage. + * + * @param name the name of the track + * @return true if the operation completed successfully + * @throws NullPointerException if name is null + * @throws IllegalArgumentException if the name is invalid + * @deprecated in favour of {@link TrackManager#loadTrack(String)} + */ + @Nonnull + @Deprecated + CompletableFuture loadTrack(@Nonnull String name); + + /** + * Loads all tracks from the storage into memory + * + * @return true if the operation completed successfully. + * @deprecated in favour of {@link TrackManager#loadAllTracks()} + */ + @Nonnull + @Deprecated + CompletableFuture loadAllTracks(); + + /** + * Saves a track back to storage. You should call this after you make any changes to a track. + * + * @param track the track to save + * @return true if the operation completed successfully. + * @throws NullPointerException if track is null + * @throws IllegalStateException if the track instance was not obtained from LuckPerms. + * @deprecated in favour of {@link TrackManager#saveTrack(Track)} + */ + @Nonnull + @Deprecated + CompletableFuture saveTrack(@Nonnull Track track); + + /** + * Permanently deletes a track from storage + * + * @param track the track to delete + * @return true if the operation completed successfully. + * @throws NullPointerException if track is null + * @throws IllegalStateException if the track instance was not obtained from LuckPerms. + * @deprecated in favour of {@link TrackManager#deleteTrack(Track)} + */ + @Nonnull + @Deprecated + CompletableFuture deleteTrack(@Nonnull Track track); + } diff --git a/api/src/main/java/me/lucko/luckperms/api/manager/GroupManager.java b/api/src/main/java/me/lucko/luckperms/api/manager/GroupManager.java index 69b72a12..2f6f0e37 100644 --- a/api/src/main/java/me/lucko/luckperms/api/manager/GroupManager.java +++ b/api/src/main/java/me/lucko/luckperms/api/manager/GroupManager.java @@ -26,9 +26,11 @@ package me.lucko.luckperms.api.manager; import me.lucko.luckperms.api.Group; +import me.lucko.luckperms.api.Storage; import java.util.Optional; import java.util.Set; +import java.util.concurrent.CompletableFuture; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -41,7 +43,103 @@ import javax.annotation.Nullable; public interface GroupManager { /** - * Gets a wrapped group object from the group storage + * Creates a new group in the plugin's storage provider and then loads it + * into memory. + * + *

If a group by the same name already exists, it will be loaded.

+ * + *

This method is effectively the same as + * {@link Storage#createAndLoadGroup(String)}, however, the Future returns + * the resultant group instance instead of a boolean flag.

+ * + *

Unlike the method in {@link Storage}, when a group cannot be loaded, + * the future will be {@link CompletableFuture completed exceptionally}.

+ * + * @param name the name of the group + * @return the resultant group + * @throws NullPointerException if the name is null + * @since 4.1 + */ + @Nonnull + CompletableFuture createAndLoadGroup(@Nonnull String name); + + /** + * Loads a group from the plugin's storage provider into memory. + * + *

Returns an {@link Optional#empty() empty optional} if the group does + * not exist.

+ * + *

This method is effectively the same as + * {@link Storage#loadGroup(String)}, however, the Future returns + * the resultant group instance instead of a boolean flag.

+ * + *

Unlike the method in {@link Storage}, when a group cannot be loaded, + * the future will be {@link CompletableFuture completed exceptionally}.

+ * + * @param name the name of the group + * @return the resultant group + * @throws NullPointerException if the name is null + * @since 4.1 + */ + @Nonnull + CompletableFuture> loadGroup(@Nonnull String name); + + /** + * Saves a group's data back to the plugin's storage provider. + * + *

You should call this after you make any changes to a group.

+ * + *

This method is effectively the same as {@link Storage#saveGroup(Group)}, + * however, the Future returns void instead of a boolean flag.

+ * + *

Unlike the method in {@link Storage}, when a group cannot be saved, + * the future will be {@link CompletableFuture completed exceptionally}.

+ * + * @param group the group to save + * @return a future to encapsulate the operation. + * @throws NullPointerException if group is null + * @throws IllegalStateException if the group instance was not obtained from LuckPerms. + * @since 4.1 + */ + @Nonnull + CompletableFuture saveGroup(@Nonnull Group group); + + /** + * Permanently deletes a group from the plugin's storage provider. + * + *

This method is effectively the same as {@link Storage#deleteGroup(Group)}, + * however, the Future returns void instead of a boolean flag.

+ * + *

Unlike the method in {@link Storage}, when a group cannot be deleted, + * the future will be {@link CompletableFuture completed exceptionally}.

+ * + * + * @param group the group to delete + * @return a future to encapsulate the operation. + * @throws NullPointerException if group is null + * @throws IllegalStateException if the group instance was not obtained from LuckPerms. + * @since 4.1 + */ + @Nonnull + CompletableFuture deleteGroup(@Nonnull Group group); + + /** + * Loads all groups into memory. + * + *

This method is effectively the same as {@link Storage#loadAllTracks()}, + * however, the Future returns void instead of a boolean flag.

+ * + *

Unlike the method in {@link Storage}, when a group cannot be loaded, + * the future will be {@link CompletableFuture completed exceptionally}.

+ * + * @return a future to encapsulate the operation. + * @since 4.1 + */ + @Nonnull + CompletableFuture loadAllGroups(); + + /** + * Gets a loaded group. * * @param name the name of the group to get * @return a {@link Group} object, if one matching the name exists, or null if not @@ -51,7 +149,7 @@ public interface GroupManager { Group getGroup(@Nonnull String name); /** - * Gets a wrapped group object from the group storage. + * Gets a loaded group. * *

This method does not return null, unlike {@link #getGroup}

* diff --git a/api/src/main/java/me/lucko/luckperms/api/manager/TrackManager.java b/api/src/main/java/me/lucko/luckperms/api/manager/TrackManager.java index b31531b4..3a6491aa 100644 --- a/api/src/main/java/me/lucko/luckperms/api/manager/TrackManager.java +++ b/api/src/main/java/me/lucko/luckperms/api/manager/TrackManager.java @@ -25,10 +25,12 @@ package me.lucko.luckperms.api.manager; +import me.lucko.luckperms.api.Storage; import me.lucko.luckperms.api.Track; import java.util.Optional; import java.util.Set; +import java.util.concurrent.CompletableFuture; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -41,7 +43,103 @@ import javax.annotation.Nullable; public interface TrackManager { /** - * Gets a wrapped track object from the track storage + * Creates a new track in the plugin's storage provider and then loads it + * into memory. + * + *

If a track by the same name already exists, it will be loaded.

+ * + *

This method is effectively the same as + * {@link Storage#createAndLoadTrack(String)}, however, the Future returns + * the resultant track instance instead of a boolean flag.

+ * + *

Unlike the method in {@link Storage}, when a track cannot be loaded, + * the future will be {@link CompletableFuture completed exceptionally}.

+ * + * @param name the name of the track + * @return the resultant track + * @throws NullPointerException if the name is null + * @since 4.1 + */ + @Nonnull + CompletableFuture createAndLoadTrack(@Nonnull String name); + + /** + * Loads a track from the plugin's storage provider into memory. + * + *

Returns an {@link Optional#empty() empty optional} if the track does + * not exist.

+ * + *

This method is effectively the same as + * {@link Storage#loadTrack(String)}, however, the Future returns + * the resultant track instance instead of a boolean flag.

+ * + *

Unlike the method in {@link Storage}, when a track cannot be loaded, + * the future will be {@link CompletableFuture completed exceptionally}.

+ * + * @param name the name of the track + * @return the resultant track + * @throws NullPointerException if the name is null + * @since 4.1 + */ + @Nonnull + CompletableFuture> loadTrack(@Nonnull String name); + + /** + * Saves a track's data back to the plugin's storage provider. + * + *

You should call this after you make any changes to a track.

+ * + *

This method is effectively the same as {@link Storage#saveTrack(Track)}, + * however, the Future returns void instead of a boolean flag.

+ * + *

Unlike the method in {@link Storage}, when a track cannot be saved, + * the future will be {@link CompletableFuture completed exceptionally}.

+ * + * @param track the track to save + * @return a future to encapsulate the operation. + * @throws NullPointerException if track is null + * @throws IllegalStateException if the track instance was not obtained from LuckPerms. + * @since 4.1 + */ + @Nonnull + CompletableFuture saveTrack(@Nonnull Track track); + + /** + * Permanently deletes a track from the plugin's storage provider. + * + *

This method is effectively the same as {@link Storage#deleteTrack(Track)}, + * however, the Future returns void instead of a boolean flag.

+ * + *

Unlike the method in {@link Storage}, when a track cannot be deleted, + * the future will be {@link CompletableFuture completed exceptionally}.

+ * + * + * @param track the track to delete + * @return a future to encapsulate the operation. + * @throws NullPointerException if track is null + * @throws IllegalStateException if the track instance was not obtained from LuckPerms. + * @since 4.1 + */ + @Nonnull + CompletableFuture deleteTrack(@Nonnull Track track); + + /** + * Loads all tracks into memory. + * + *

This method is effectively the same as {@link Storage#loadAllTracks()}, + * however, the Future returns void instead of a boolean flag.

+ * + *

Unlike the method in {@link Storage}, when a track cannot be loaded, + * the future will be {@link CompletableFuture completed exceptionally}.

+ * + * @return a future to encapsulate the operation. + * @since 4.1 + */ + @Nonnull + CompletableFuture loadAllTracks(); + + /** + * Gets a loaded track. * * @param name the name of the track to get * @return a {@link Track} object, if one matching the name exists, or null if not @@ -51,7 +149,7 @@ public interface TrackManager { Track getTrack(@Nonnull String name); /** - * Gets a wrapped track object from the track storage. + * Gets a loaded track. * *

This method does not return null, unlike {@link #getTrack}

* diff --git a/api/src/main/java/me/lucko/luckperms/api/manager/UserManager.java b/api/src/main/java/me/lucko/luckperms/api/manager/UserManager.java index f292de61..188add7a 100644 --- a/api/src/main/java/me/lucko/luckperms/api/manager/UserManager.java +++ b/api/src/main/java/me/lucko/luckperms/api/manager/UserManager.java @@ -25,11 +25,13 @@ package me.lucko.luckperms.api.manager; +import me.lucko.luckperms.api.Storage; import me.lucko.luckperms.api.User; import java.util.Optional; import java.util.Set; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -37,12 +39,74 @@ import javax.annotation.Nullable; /** * Represents the object responsible for managing {@link User} instances. * + *

Note that User instances are automatically loaded for online players. + * It's likely that offline players will not have an instance pre-loaded.

+ * * @since 4.0 */ public interface UserManager { /** - * Gets a wrapped user object from the user storage + * Loads a user from the plugin's storage provider into memory. + * + *

This method is effectively the same as + * {@link Storage#loadUser(UUID, String)}, however, the Future returns the + * resultant user instance instead of a boolean flag.

+ * + *

Unlike the method in {@link Storage}, when a user cannot be loaded, + * the future will be {@link CompletableFuture completed exceptionally}.

+ * + * @param uuid the uuid of the user + * @param username the username, if known + * @return the resultant user + * @throws NullPointerException if the uuid is null + * @since 4.1 + */ + @Nonnull + CompletableFuture loadUser(@Nonnull UUID uuid, @Nullable String username); + + /** + * Loads a user from the plugin's storage provider into memory. + * + *

This method is effectively the same as {@link Storage#loadUser(UUID)}, + * however, the Future returns the resultant user instance instead of a + * boolean flag.

+ * + *

Unlike the method in {@link Storage}, when a user cannot be loaded, + * the future will be {@link CompletableFuture completed exceptionally}.

+ * + * @param uuid the uuid of the user + * @return the resultant user + * @throws NullPointerException if the uuid is null + * @since 4.1 + */ + @Nonnull + default CompletableFuture loadUser(@Nonnull UUID uuid) { + return loadUser(uuid, null); + } + + /** + * Saves a user's data back to the plugin's storage provider. + * + *

You should call this after you make any changes to a user.

+ * + *

This method is effectively the same as {@link Storage#saveUser(User)}, + * however, the Future returns void instead of a boolean flag.

+ * + *

Unlike the method in {@link Storage}, when a user cannot be saved, + * the future will be {@link CompletableFuture completed exceptionally}.

+ * + * @param user the user to save + * @return a future to encapsulate the operation. + * @throws NullPointerException if user is null + * @throws IllegalStateException if the user instance was not obtained from LuckPerms. + * @since 4.1 + */ + @Nonnull + CompletableFuture saveUser(@Nonnull User user); + + /** + * Gets a loaded user. * * @param uuid the uuid of the user to get * @return a {@link User} object, if one matching the uuid is loaded, or null if not @@ -52,7 +116,7 @@ public interface UserManager { User getUser(@Nonnull UUID uuid); /** - * Gets a wrapped user object from the user storage. + * Gets a loaded user. * * @param uuid the uuid of the user to get * @return an optional {@link User} object @@ -64,7 +128,7 @@ public interface UserManager { } /** - * Gets a wrapped user object from the user storage + * Gets a loaded user. * * @param name the username of the user to get * @return a {@link User} object, if one matching the uuid is loaded, or null if not @@ -74,7 +138,7 @@ public interface UserManager { User getUser(@Nonnull String name); /** - * Gets a wrapped user object from the user storage. + * Gets a loaded user. * * @param name the username of the user to get * @return an optional {@link User} object diff --git a/common/src/main/java/me/lucko/luckperms/common/api/ApiUtils.java b/common/src/main/java/me/lucko/luckperms/common/api/ApiUtils.java index 849e891a..67d80f57 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/ApiUtils.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/ApiUtils.java @@ -32,6 +32,10 @@ import me.lucko.luckperms.common.storage.DataConstraints; public final class ApiUtils { public static String checkUsername(String s) { + if (s == null) { + return null; + } + Preconditions.checkArgument( DataConstraints.PLAYER_USERNAME_TEST.test(s), "Invalid username entry '" + s + "'. Usernames must be less than 16 chars and only contain 'a-z A-Z 1-9 _'." @@ -40,6 +44,10 @@ public final class ApiUtils { } public static String checkName(String s) { + if (s == null) { + return null; + } + Preconditions.checkArgument( DataConstraints.GROUP_NAME_TEST.test(s), "Invalid name entry '" + s + "'. Names must be less than 37 chars and only contain 'a-z A-Z 1-9'." diff --git a/common/src/main/java/me/lucko/luckperms/common/api/LuckPermsApiProvider.java b/common/src/main/java/me/lucko/luckperms/common/api/LuckPermsApiProvider.java index d388f41b..1519b3e4 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/LuckPermsApiProvider.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/LuckPermsApiProvider.java @@ -78,9 +78,9 @@ public class LuckPermsApiProvider implements LuckPermsApi { this.plugin = plugin; this.platformInfo = new ApiPlatformInfo(plugin); - this.userManager = new ApiUserManager(plugin.getUserManager()); - this.groupManager = new ApiGroupManager(plugin.getGroupManager()); - this.trackManager = new ApiTrackManager(plugin.getTrackManager()); + this.userManager = new ApiUserManager(plugin, plugin.getUserManager()); + this.groupManager = new ApiGroupManager(plugin, plugin.getGroupManager()); + this.trackManager = new ApiTrackManager(plugin, plugin.getTrackManager()); this.actionLogger = new ApiActionLogger(plugin); this.contextManager = new ApiContextManager(plugin, plugin.getContextManager()); this.metaStackFactory = new ApiMetaStackFactory(plugin); diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiAbstractManager.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiAbstractManager.java new file mode 100644 index 00000000..09fa9b33 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiAbstractManager.java @@ -0,0 +1,41 @@ +/* + * 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.api.delegates.manager; + +import me.lucko.luckperms.common.plugin.LuckPermsPlugin; + +public abstract class ApiAbstractManager { + protected final LuckPermsPlugin plugin; + protected final H handle; + + protected ApiAbstractManager(LuckPermsPlugin plugin, H handle) { + this.plugin = plugin; + this.handle = handle; + } + + protected abstract E getDelegateFor(I internal); + +} diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiContextManager.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiContextManager.java index 39bf9a5f..ed434fb3 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiContextManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiContextManager.java @@ -28,10 +28,10 @@ package me.lucko.luckperms.common.api.delegates.manager; import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.User; import me.lucko.luckperms.api.context.ContextCalculator; -import me.lucko.luckperms.api.context.ContextManager; import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.context.StaticContextCalculator; import me.lucko.luckperms.common.api.delegates.model.ApiUser; +import me.lucko.luckperms.common.contexts.ContextManager; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import java.util.Objects; @@ -40,11 +40,11 @@ import java.util.Optional; import javax.annotation.Nonnull; @SuppressWarnings("unchecked") -public class ApiContextManager implements ContextManager { +public class ApiContextManager implements me.lucko.luckperms.api.context.ContextManager { private final LuckPermsPlugin plugin; - private final me.lucko.luckperms.common.contexts.ContextManager handle; + private final ContextManager handle; - public ApiContextManager(LuckPermsPlugin plugin, me.lucko.luckperms.common.contexts.ContextManager handle) { + public ApiContextManager(LuckPermsPlugin plugin, ContextManager handle) { this.plugin = plugin; this.handle = handle; } diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiGroupManager.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiGroupManager.java index 7c21f8a1..c56c4635 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiGroupManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiGroupManager.java @@ -25,33 +25,87 @@ package me.lucko.luckperms.common.api.delegates.manager; -import me.lucko.luckperms.api.Group; -import me.lucko.luckperms.api.manager.GroupManager; +import me.lucko.luckperms.api.event.cause.CreationCause; +import me.lucko.luckperms.api.event.cause.DeletionCause; +import me.lucko.luckperms.common.api.ApiUtils; +import me.lucko.luckperms.common.api.delegates.model.ApiGroup; +import me.lucko.luckperms.common.managers.group.GroupManager; +import me.lucko.luckperms.common.model.Group; +import me.lucko.luckperms.common.node.NodeFactory; +import me.lucko.luckperms.common.plugin.LuckPermsPlugin; +import me.lucko.luckperms.common.utils.ImmutableCollectors; import java.util.Objects; +import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; +import java.util.concurrent.CompletableFuture; import javax.annotation.Nonnull; -public class ApiGroupManager implements GroupManager { - private final me.lucko.luckperms.common.managers.group.GroupManager handle; - - public ApiGroupManager(me.lucko.luckperms.common.managers.group.GroupManager handle) { - this.handle = handle; +public class ApiGroupManager extends ApiAbstractManager> implements me.lucko.luckperms.api.manager.GroupManager { + public ApiGroupManager(LuckPermsPlugin plugin, GroupManager handle) { + super(plugin, handle); } @Override - public Group getGroup(@Nonnull String name) { - Objects.requireNonNull(name, "name"); - me.lucko.luckperms.common.model.Group group = this.handle.getIfLoaded(name); - return group == null ? null : group.getApiDelegate(); + protected me.lucko.luckperms.api.Group getDelegateFor(me.lucko.luckperms.common.model.Group internal) { + if (internal == null) { + return null; + } + + return internal.getApiDelegate(); } @Nonnull @Override - public Set getLoadedGroups() { - return this.handle.getAll().values().stream().map(me.lucko.luckperms.common.model.Group::getApiDelegate).collect(Collectors.toSet()); + public CompletableFuture createAndLoadGroup(@Nonnull String name) { + name = ApiUtils.checkName(Objects.requireNonNull(name, "name")); + return this.plugin.getStorage().noBuffer().createAndLoadGroup(name, CreationCause.API) + .thenApply(this::getDelegateFor); + } + + @Nonnull + @Override + public CompletableFuture> loadGroup(@Nonnull String name) { + name = ApiUtils.checkName(Objects.requireNonNull(name, "name")); + return this.plugin.getStorage().noBuffer().loadGroup(name).thenApply(opt -> opt.map(this::getDelegateFor)); + } + + @Nonnull + @Override + public CompletableFuture saveGroup(@Nonnull me.lucko.luckperms.api.Group group) { + Objects.requireNonNull(group, "group"); + return this.plugin.getStorage().noBuffer().saveGroup(ApiGroup.cast(group)); + } + + @Nonnull + @Override + public CompletableFuture deleteGroup(@Nonnull me.lucko.luckperms.api.Group group) { + Objects.requireNonNull(group, "group"); + if (group.getName().equalsIgnoreCase(NodeFactory.DEFAULT_GROUP_NAME)) { + throw new IllegalArgumentException("Cannot delete the default group."); + } + return this.plugin.getStorage().noBuffer().deleteGroup(ApiGroup.cast(group), DeletionCause.API); + } + + @Nonnull + @Override + public CompletableFuture loadAllGroups() { + return this.plugin.getStorage().noBuffer().loadAllGroups(); + } + + @Override + public me.lucko.luckperms.api.Group getGroup(@Nonnull String name) { + Objects.requireNonNull(name, "name"); + return getDelegateFor(this.handle.getIfLoaded(name)); + } + + @Nonnull + @Override + public Set getLoadedGroups() { + return this.handle.getAll().values().stream() + .map(this::getDelegateFor) + .collect(ImmutableCollectors.toSet()); } @Override diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiTrackManager.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiTrackManager.java index 3135f9e6..1441f1c1 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiTrackManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiTrackManager.java @@ -25,33 +25,83 @@ package me.lucko.luckperms.common.api.delegates.manager; -import me.lucko.luckperms.api.Track; -import me.lucko.luckperms.api.manager.TrackManager; +import me.lucko.luckperms.api.event.cause.CreationCause; +import me.lucko.luckperms.api.event.cause.DeletionCause; +import me.lucko.luckperms.common.api.ApiUtils; +import me.lucko.luckperms.common.api.delegates.model.ApiTrack; +import me.lucko.luckperms.common.managers.track.TrackManager; +import me.lucko.luckperms.common.model.Track; +import me.lucko.luckperms.common.plugin.LuckPermsPlugin; +import me.lucko.luckperms.common.utils.ImmutableCollectors; import java.util.Objects; +import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; +import java.util.concurrent.CompletableFuture; import javax.annotation.Nonnull; -public class ApiTrackManager implements TrackManager { - private final me.lucko.luckperms.common.managers.track.TrackManager handle; - - public ApiTrackManager(me.lucko.luckperms.common.managers.track.TrackManager handle) { - this.handle = handle; +public class ApiTrackManager extends ApiAbstractManager> implements me.lucko.luckperms.api.manager.TrackManager { + public ApiTrackManager(LuckPermsPlugin plugin, TrackManager handle) { + super(plugin, handle); } @Override - public Track getTrack(@Nonnull String name) { - Objects.requireNonNull(name, "name"); - me.lucko.luckperms.common.model.Track track = this.handle.getIfLoaded(name); - return track == null ? null : track.getApiDelegate(); + protected me.lucko.luckperms.api.Track getDelegateFor(Track internal) { + if (internal == null) { + return null; + } + + return internal.getApiDelegate(); } @Nonnull @Override - public Set getLoadedTracks() { - return this.handle.getAll().values().stream().map(me.lucko.luckperms.common.model.Track::getApiDelegate).collect(Collectors.toSet()); + public CompletableFuture createAndLoadTrack(@Nonnull String name) { + name = ApiUtils.checkName(Objects.requireNonNull(name, "name")); + return this.plugin.getStorage().noBuffer().createAndLoadTrack(name, CreationCause.API) + .thenApply(this::getDelegateFor); + } + + @Nonnull + @Override + public CompletableFuture> loadTrack(@Nonnull String name) { + name = ApiUtils.checkName(Objects.requireNonNull(name, "name")); + return this.plugin.getStorage().noBuffer().loadTrack(name).thenApply(opt -> opt.map(this::getDelegateFor)); + } + + @Nonnull + @Override + public CompletableFuture saveTrack(@Nonnull me.lucko.luckperms.api.Track track) { + Objects.requireNonNull(track, "track"); + return this.plugin.getStorage().noBuffer().saveTrack(ApiTrack.cast(track)); + } + + @Nonnull + @Override + public CompletableFuture deleteTrack(@Nonnull me.lucko.luckperms.api.Track track) { + Objects.requireNonNull(track, "track"); + return this.plugin.getStorage().noBuffer().deleteTrack(ApiTrack.cast(track), DeletionCause.API); + } + + @Nonnull + @Override + public CompletableFuture loadAllTracks() { + return this.plugin.getStorage().noBuffer().loadAllTracks(); + } + + @Override + public me.lucko.luckperms.api.Track getTrack(@Nonnull String name) { + Objects.requireNonNull(name, "name"); + return getDelegateFor(this.handle.getIfLoaded(name)); + } + + @Nonnull + @Override + public Set getLoadedTracks() { + return this.handle.getAll().values().stream() + .map(this::getDelegateFor) + .collect(ImmutableCollectors.toSet()); } @Override diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiUserManager.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiUserManager.java index 0bdd4154..7113ccf6 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiUserManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/manager/ApiUserManager.java @@ -25,43 +25,74 @@ package me.lucko.luckperms.common.api.delegates.manager; -import me.lucko.luckperms.api.User; -import me.lucko.luckperms.api.manager.UserManager; +import me.lucko.luckperms.common.api.ApiUtils; import me.lucko.luckperms.common.api.delegates.model.ApiUser; +import me.lucko.luckperms.common.managers.user.UserManager; +import me.lucko.luckperms.common.model.User; +import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.references.UserIdentifier; +import me.lucko.luckperms.common.utils.ImmutableCollectors; import java.util.Objects; import java.util.Set; import java.util.UUID; -import java.util.stream.Collectors; +import java.util.concurrent.CompletableFuture; import javax.annotation.Nonnull; +import javax.annotation.Nullable; -public class ApiUserManager implements UserManager { - private final me.lucko.luckperms.common.managers.user.UserManager handle; - - public ApiUserManager(me.lucko.luckperms.common.managers.user.UserManager handle) { - this.handle = handle; +public class ApiUserManager extends ApiAbstractManager> implements me.lucko.luckperms.api.manager.UserManager { + public ApiUserManager(LuckPermsPlugin plugin, UserManager handle) { + super(plugin, handle); } @Override - public User getUser(@Nonnull UUID uuid) { - Objects.requireNonNull(uuid, "uuid"); - me.lucko.luckperms.common.model.User user = this.handle.getIfLoaded(uuid); - return user == null ? null : new ApiUser(user); - } - - @Override - public User getUser(@Nonnull String name) { - Objects.requireNonNull(name, "name"); - me.lucko.luckperms.common.model.User user = this.handle.getByUsername(name); - return user == null ? null : new ApiUser(user); + protected me.lucko.luckperms.api.User getDelegateFor(User internal) { + if (internal == null) { + return null; + } + return new ApiUser(internal); } @Nonnull @Override - public Set getLoadedUsers() { - return this.handle.getAll().values().stream().map(ApiUser::new).collect(Collectors.toSet()); + public CompletableFuture loadUser(@Nonnull UUID uuid, @Nullable String username) { + Objects.requireNonNull(uuid, "uuid"); + ApiUtils.checkUsername(username); + + if (this.plugin.getUserManager().getIfLoaded(uuid) == null) { + this.plugin.getUserManager().getHouseKeeper().registerApiUsage(uuid); + } + + return this.plugin.getStorage().noBuffer().loadUser(uuid, username) + .thenApply(this::getDelegateFor); + } + + @Nonnull + @Override + public CompletableFuture saveUser(@Nonnull me.lucko.luckperms.api.User user) { + Objects.requireNonNull(user, "user"); + return this.plugin.getStorage().noBuffer().saveUser(ApiUser.cast(user)); + } + + @Override + public me.lucko.luckperms.api.User getUser(@Nonnull UUID uuid) { + Objects.requireNonNull(uuid, "uuid"); + return getDelegateFor(this.handle.getIfLoaded(uuid)); + } + + @Override + public me.lucko.luckperms.api.User getUser(@Nonnull String name) { + Objects.requireNonNull(name, "name"); + return getDelegateFor(this.handle.getByUsername(name)); + } + + @Nonnull + @Override + public Set getLoadedUsers() { + return this.handle.getAll().values().stream() + .map(this::getDelegateFor) + .collect(ImmutableCollectors.toSet()); } @Override @@ -71,7 +102,7 @@ public class ApiUserManager implements UserManager { } @Override - public void cleanupUser(@Nonnull User user) { + public void cleanupUser(@Nonnull me.lucko.luckperms.api.User user) { Objects.requireNonNull(user, "user"); this.handle.getHouseKeeper().clearApiUsage(ApiUser.cast(user).getUuid()); } diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/misc/ApiActionLogger.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/misc/ApiActionLogger.java index 42fce03e..865ba942 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/misc/ApiActionLogger.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/misc/ApiActionLogger.java @@ -52,7 +52,7 @@ public class ApiActionLogger implements ActionLogger { @Nonnull @Override public CompletableFuture getLog() { - return this.plugin.getStorage().noBuffer().getLog().thenApply(log -> log == null ? null : new ApiLog(log)); + return this.plugin.getStorage().noBuffer().getLog().thenApply(ApiLog::new); } @Nonnull diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiGroup.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiGroup.java index fb14953e..e2c4101e 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiGroup.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiGroup.java @@ -27,30 +27,30 @@ package me.lucko.luckperms.common.api.delegates.model; import com.google.common.base.Preconditions; -import me.lucko.luckperms.api.Group; import me.lucko.luckperms.api.caching.GroupData; +import me.lucko.luckperms.common.model.Group; import java.util.Objects; import java.util.OptionalInt; import javax.annotation.Nonnull; -public final class ApiGroup extends ApiPermissionHolder implements Group { - public static me.lucko.luckperms.common.model.Group cast(Group group) { +public final class ApiGroup extends ApiPermissionHolder implements me.lucko.luckperms.api.Group { + public static Group cast(me.lucko.luckperms.api.Group group) { Objects.requireNonNull(group, "group"); Preconditions.checkState(group instanceof ApiGroup, "Illegal instance " + group.getClass() + " cannot be handled by this implementation."); return ((ApiGroup) group).getHandle(); } - private final me.lucko.luckperms.common.model.Group handle; + private final Group handle; - public ApiGroup(me.lucko.luckperms.common.model.Group handle) { + public ApiGroup(Group handle) { super(handle); this.handle = handle; } @Override - me.lucko.luckperms.common.model.Group getHandle() { + Group getHandle() { return this.handle; } 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 99ceeec4..e42b169a 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,8 +25,9 @@ package me.lucko.luckperms.common.api.delegates.model; -import me.lucko.luckperms.api.Log; + import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.common.actionlog.Log; import java.util.Objects; import java.util.SortedMap; @@ -38,11 +39,11 @@ import javax.annotation.Nonnull; import static me.lucko.luckperms.common.api.ApiUtils.checkName; @SuppressWarnings("unchecked") -public class ApiLog implements Log { +public class ApiLog implements me.lucko.luckperms.api.Log { private static final int ENTRIES_PER_PAGE = 5; - private final me.lucko.luckperms.common.actionlog.Log handle; + private final Log handle; - public ApiLog(me.lucko.luckperms.common.actionlog.Log handle) { + public ApiLog(Log handle) { this.handle = handle; } diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiPermissionHolder.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiPermissionHolder.java index 652544c8..88e9ff22 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiPermissionHolder.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiPermissionHolder.java @@ -35,13 +35,13 @@ import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.PermissionHolder; import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.caching.CachedData; import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.NodeMapType; +import me.lucko.luckperms.common.model.PermissionHolder; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.node.MetaType; import me.lucko.luckperms.common.utils.ImmutableCollectors; @@ -56,14 +56,14 @@ import java.util.function.Predicate; import javax.annotation.Nonnull; -public class ApiPermissionHolder implements PermissionHolder { - private final me.lucko.luckperms.common.model.PermissionHolder handle; +public class ApiPermissionHolder implements me.lucko.luckperms.api.PermissionHolder { + private final PermissionHolder handle; - ApiPermissionHolder(me.lucko.luckperms.common.model.PermissionHolder handle) { + ApiPermissionHolder(PermissionHolder handle) { this.handle = Objects.requireNonNull(handle, "handle"); } - me.lucko.luckperms.common.model.PermissionHolder getHandle() { + PermissionHolder getHandle() { return this.handle; } diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiStorage.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiStorage.java index 9c63c997..9fc0893f 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiStorage.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiStorage.java @@ -29,13 +29,13 @@ import me.lucko.luckperms.api.Group; import me.lucko.luckperms.api.HeldPermission; import me.lucko.luckperms.api.Log; import me.lucko.luckperms.api.LogEntry; -import me.lucko.luckperms.api.Storage; import me.lucko.luckperms.api.Track; import me.lucko.luckperms.api.User; import me.lucko.luckperms.api.event.cause.CreationCause; import me.lucko.luckperms.api.event.cause.DeletionCause; import me.lucko.luckperms.common.node.NodeFactory; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; +import me.lucko.luckperms.common.storage.Storage; import java.util.List; import java.util.Objects; @@ -44,17 +44,34 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; +import java.util.function.Function; import javax.annotation.Nonnull; import static me.lucko.luckperms.common.api.ApiUtils.checkName; import static me.lucko.luckperms.common.api.ApiUtils.checkUsername; -public class ApiStorage implements Storage { - private final LuckPermsPlugin plugin; - private final me.lucko.luckperms.common.storage.Storage handle; +public class ApiStorage implements me.lucko.luckperms.api.Storage { + private static final Function CONSUME_EXCEPTION = throwable -> { + throwable.printStackTrace(); + return false; + }; + + private static Function consumeExceptionToFalse() { + return CONSUME_EXCEPTION; + } + + private static Function consumeExceptionToNull() { + return throwable -> { + throwable.printStackTrace(); + return null; + }; + } - public ApiStorage(LuckPermsPlugin plugin, me.lucko.luckperms.common.storage.Storage handle) { + private final LuckPermsPlugin plugin; + private final Storage handle; + + public ApiStorage(LuckPermsPlugin plugin, Storage handle) { this.plugin = plugin; this.handle = handle; } @@ -86,72 +103,87 @@ public class ApiStorage implements Storage { @Override public CompletableFuture logAction(@Nonnull LogEntry entry) { Objects.requireNonNull(entry, "entry"); - return this.handle.noBuffer().logAction(entry).thenApply(x -> true); + return this.handle.noBuffer().logAction(entry) + .thenApply(r -> true) + .exceptionally(consumeExceptionToFalse()); } @Nonnull @Override public CompletableFuture getLog() { - return this.handle.noBuffer().getLog().thenApply(log -> log == null ? null : new ApiLog(log)); + return this.handle.noBuffer().getLog().thenApply(ApiLog::new).exceptionally(consumeExceptionToNull()); } @Nonnull @Override public CompletableFuture loadUser(@Nonnull UUID uuid, String username) { Objects.requireNonNull(uuid, "uuid"); + username = checkUsername(username); if (this.plugin.getUserManager().getIfLoaded(uuid) == null) { this.plugin.getUserManager().getHouseKeeper().registerApiUsage(uuid); } - return this.handle.noBuffer().loadUser(uuid, username == null ? null : checkUsername(username)).thenApply(Objects::nonNull); + return this.handle.noBuffer().loadUser(uuid, username) + .thenApply(r -> true) + .exceptionally(consumeExceptionToFalse()); } @Nonnull @Override public CompletableFuture saveUser(@Nonnull User user) { Objects.requireNonNull(user, "user"); - return this.handle.noBuffer().saveUser(ApiUser.cast(user)).thenApply(x -> true); + return this.handle.noBuffer().saveUser(ApiUser.cast(user)) + .thenApply(r -> true) + .exceptionally(consumeExceptionToFalse()); } @Nonnull @Override public CompletableFuture> getUniqueUsers() { - return this.handle.noBuffer().getUniqueUsers(); + return this.handle.noBuffer().getUniqueUsers().exceptionally(consumeExceptionToNull()); } @Nonnull @Override public CompletableFuture>> getUsersWithPermission(@Nonnull String permission) { Objects.requireNonNull(permission, "permission"); - return this.handle.noBuffer().getUsersWithPermission(permission); + return this.handle.noBuffer().getUsersWithPermission(permission).exceptionally(consumeExceptionToNull()); } @Nonnull @Override public CompletableFuture createAndLoadGroup(@Nonnull String name) { Objects.requireNonNull(name, "name"); - return this.handle.noBuffer().createAndLoadGroup(checkName(name), CreationCause.API).thenApply(Objects::nonNull); + return this.handle.noBuffer().createAndLoadGroup(checkName(name), CreationCause.API) + .thenApply(r -> true) + .exceptionally(consumeExceptionToFalse()); } @Nonnull @Override public CompletableFuture loadGroup(@Nonnull String name) { Objects.requireNonNull(name, "name"); - return this.handle.noBuffer().loadGroup(checkName(name)).thenApply(Optional::isPresent); + return this.handle.noBuffer().loadGroup(checkName(name)) + .thenApply(Optional::isPresent) + .exceptionally(consumeExceptionToFalse()); } @Nonnull @Override public CompletableFuture loadAllGroups() { - return this.handle.noBuffer().loadAllGroups().thenApply(x -> true); + return this.handle.noBuffer().loadAllGroups() + .thenApply(r -> true) + .exceptionally(consumeExceptionToFalse()); } @Nonnull @Override public CompletableFuture saveGroup(@Nonnull Group group) { Objects.requireNonNull(group, "group"); - return this.handle.noBuffer().saveGroup(ApiGroup.cast(group)).thenApply(x -> true); + return this.handle.noBuffer().saveGroup(ApiGroup.cast(group)) + .thenApply(r -> true) + .exceptionally(consumeExceptionToFalse()); } @Nonnull @@ -161,48 +193,60 @@ public class ApiStorage implements Storage { if (group.getName().equalsIgnoreCase(NodeFactory.DEFAULT_GROUP_NAME)) { throw new IllegalArgumentException("Cannot delete the default group."); } - return this.handle.noBuffer().deleteGroup(ApiGroup.cast(group), DeletionCause.API).thenApply(x -> true); + return this.handle.noBuffer().deleteGroup(ApiGroup.cast(group), DeletionCause.API) + .thenApply(r -> true) + .exceptionally(consumeExceptionToFalse()); } @Nonnull @Override public CompletableFuture>> getGroupsWithPermission(@Nonnull String permission) { Objects.requireNonNull(permission, "permission"); - return this.handle.noBuffer().getGroupsWithPermission(permission); + return this.handle.noBuffer().getGroupsWithPermission(permission).exceptionally(consumeExceptionToNull()); } @Nonnull @Override public CompletableFuture createAndLoadTrack(@Nonnull String name) { Objects.requireNonNull(name, "name"); - return this.handle.noBuffer().createAndLoadTrack(checkName(name), CreationCause.API).thenApply(Objects::nonNull); + return this.handle.noBuffer().createAndLoadTrack(checkName(name), CreationCause.API) + .thenApply(r -> true) + .exceptionally(consumeExceptionToFalse()); } @Nonnull @Override public CompletableFuture loadTrack(@Nonnull String name) { Objects.requireNonNull(name, "name"); - return this.handle.noBuffer().loadTrack(checkName(name)).thenApply(Optional::isPresent); + return this.handle.noBuffer().loadTrack(checkName(name)) + .thenApply(Optional::isPresent) + .exceptionally(consumeExceptionToFalse()); } @Nonnull @Override public CompletableFuture loadAllTracks() { - return this.handle.noBuffer().loadAllTracks().thenApply(x -> true); + return this.handle.noBuffer().loadAllTracks() + .thenApply(r -> true) + .exceptionally(consumeExceptionToFalse()); } @Nonnull @Override public CompletableFuture saveTrack(@Nonnull Track track) { Objects.requireNonNull(track, "track"); - return this.handle.noBuffer().saveTrack(ApiTrack.cast(track)).thenApply(x -> true); + return this.handle.noBuffer().saveTrack(ApiTrack.cast(track)) + .thenApply(r -> true) + .exceptionally(consumeExceptionToFalse()); } @Nonnull @Override public CompletableFuture deleteTrack(@Nonnull Track track) { Objects.requireNonNull(track, "track"); - return this.handle.noBuffer().deleteTrack(ApiTrack.cast(track), DeletionCause.API).thenApply(x -> true); + return this.handle.noBuffer().deleteTrack(ApiTrack.cast(track), DeletionCause.API) + .thenApply(r -> true) + .exceptionally(consumeExceptionToFalse()); } @Nonnull @@ -210,7 +254,9 @@ public class ApiStorage implements Storage { public CompletableFuture saveUUIDData(@Nonnull String username, @Nonnull UUID uuid) { Objects.requireNonNull(username, "username"); Objects.requireNonNull(uuid, "uuid"); - return this.handle.noBuffer().saveUUIDData(uuid, checkUsername(username)).thenApply(x -> true); + return this.handle.noBuffer().saveUUIDData(uuid, checkUsername(username)) + .thenApply(r -> true) + .exceptionally(consumeExceptionToFalse()); } @Nonnull diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiTrack.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiTrack.java index 71fbb7c6..7d238e20 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiTrack.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiTrack.java @@ -29,27 +29,27 @@ import com.google.common.base.Preconditions; import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.Group; -import me.lucko.luckperms.api.Track; +import me.lucko.luckperms.common.model.Track; import java.util.List; import java.util.Objects; import javax.annotation.Nonnull; -public final class ApiTrack implements Track { - public static me.lucko.luckperms.common.model.Track cast(Track track) { +public final class ApiTrack implements me.lucko.luckperms.api.Track { + public static Track cast(me.lucko.luckperms.api.Track track) { Objects.requireNonNull(track, "track"); Preconditions.checkState(track instanceof ApiTrack, "Illegal instance " + track.getClass() + " cannot be handled by this implementation."); return ((ApiTrack) track).getHandle(); } - private final me.lucko.luckperms.common.model.Track handle; + private final Track handle; - public ApiTrack(me.lucko.luckperms.common.model.Track handle) { + public ApiTrack(Track handle) { this.handle = handle; } - me.lucko.luckperms.common.model.Track getHandle() { + Track getHandle() { return this.handle; } diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiUser.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiUser.java index 5641fdaf..4ddd992d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiUser.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/model/ApiUser.java @@ -28,8 +28,8 @@ package me.lucko.luckperms.common.api.delegates.model; import com.google.common.base.Preconditions; import me.lucko.luckperms.api.DataMutateResult; -import me.lucko.luckperms.api.User; import me.lucko.luckperms.api.caching.UserData; +import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.node.NodeFactory; import java.util.Objects; @@ -37,21 +37,21 @@ import java.util.UUID; import javax.annotation.Nonnull; -public final class ApiUser extends ApiPermissionHolder implements User { - public static me.lucko.luckperms.common.model.User cast(User u) { +public final class ApiUser extends ApiPermissionHolder implements me.lucko.luckperms.api.User { + public static User cast(me.lucko.luckperms.api.User u) { Preconditions.checkState(u instanceof ApiUser, "Illegal instance " + u.getClass() + " cannot be handled by this implementation."); return ((ApiUser) u).getHandle(); } - private final me.lucko.luckperms.common.model.User handle; + private final User handle; - public ApiUser(me.lucko.luckperms.common.model.User handle) { + public ApiUser(User handle) { super(handle); this.handle = handle; } @Override - me.lucko.luckperms.common.model.User getHandle() { + User getHandle() { return this.handle; } diff --git a/common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventBus.java b/common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventBus.java index a62bd8c5..9b363aa4 100644 --- a/common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventBus.java +++ b/common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventBus.java @@ -77,8 +77,8 @@ public class LuckPermsEventBus implements EventBus { } @Nonnull - @SuppressWarnings("unchecked") @Override + @SuppressWarnings("unchecked") public Set> getHandlers(@Nonnull Class eventClass) { Set> handlers = this.handlerMap.get(eventClass); if (handlers == null) {