Add API methods to load users/groups/tracks and return a future encapsulating the resultant object instead of a success flag

This commit is contained in:
Luck 2018-01-30 15:55:36 +00:00
parent 7f7116e1c7
commit fe200ca1ec
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
19 changed files with 837 additions and 297 deletions

View File

@ -25,6 +25,10 @@
package me.lucko.luckperms.api; 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.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
@ -38,13 +42,15 @@ import javax.annotation.Nullable;
/** /**
* A means of loading and saving permission data to/from the backend. * A means of loading and saving permission data to/from the backend.
* *
* <p>All blocking methods return {@link CompletableFuture}s, which will be populated with the result once the data has been * <p>All blocking methods return {@link CompletableFuture}s, which will be
* loaded/saved asynchronously. Care should be taken when using such methods to ensure that the main server thread is not * populated with the result once the data has been loaded/saved asynchronously.
* blocked.</p> * Care should be taken when using such methods to ensure that the main server
* thread is not blocked.</p>
* *
* <p>Methods such as {@link CompletableFuture#get()} and equivalent should <strong>not</strong> be called on the main * <p>Methods such as {@link CompletableFuture#get()} and equivalent should
* server thread. If you need to use the result of these operations on the main server thread, register a * <strong>not</strong> be called on the main server thread. If you need to use
* callback using {@link CompletableFuture#thenAcceptAsync(Consumer, Executor)} and {@link #getSyncExecutor()}.</p> * the result of these operations on the main server thread, register a
* callback using {@link CompletableFuture#thenAcceptAsync(Consumer, Executor)}.</p>
* *
* @since 2.14 * @since 2.14
*/ */
@ -58,42 +64,6 @@ public interface Storage {
@Nonnull @Nonnull
String getName(); 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<Boolean> logAction(@Nonnull LogEntry entry);
/** /**
* Loads and returns the entire log from storage * Loads and returns the entire log from storage
* *
@ -102,40 +72,6 @@ public interface Storage {
@Nonnull @Nonnull
CompletableFuture<Log> getLog(); CompletableFuture<Log> 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<Boolean> 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<Boolean> 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<Boolean> saveUser(@Nonnull User user);
/** /**
* Gets a set all "unique" user UUIDs. * Gets a set all "unique" user UUIDs.
* *
@ -157,58 +93,6 @@ public interface Storage {
@Nonnull @Nonnull
CompletableFuture<List<HeldPermission<UUID>>> getUsersWithPermission(@Nonnull String permission); CompletableFuture<List<HeldPermission<UUID>>> 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<Boolean> 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<Boolean> loadGroup(@Nonnull String name);
/**
* Loads all groups from the storage into memory
*
* @return true if the operation completed successfully.
*/
@Nonnull
CompletableFuture<Boolean> 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<Boolean> 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<Boolean> deleteGroup(@Nonnull Group group);
/** /**
* Searches for a list of groups with a given permission. * Searches for a list of groups with a given permission.
* *
@ -220,58 +104,6 @@ public interface Storage {
@Nonnull @Nonnull
CompletableFuture<List<HeldPermission<String>>> getGroupsWithPermission(@Nonnull String permission); CompletableFuture<List<HeldPermission<String>>> 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<Boolean> 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<Boolean> loadTrack(@Nonnull String name);
/**
* Loads all tracks from the storage into memory
*
* @return true if the operation completed successfully.
*/
@Nonnull
CompletableFuture<Boolean> 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<Boolean> 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<Boolean> deleteTrack(@Nonnull Track track);
/** /**
* Saves UUID caching data to the global cache * Saves UUID caching data to the global cache
* *
@ -306,4 +138,221 @@ public interface Storage {
@Nonnull @Nonnull
CompletableFuture<String> getName(@Nonnull UUID uuid); CompletableFuture<String> 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.
*
* <p>This method is deprecated as plugins should create and use their own
* executor instances.</p>
*
* @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.
*
* <p>This method is deprecated as plugins should create and use their own
* executor instances.</p>
*
* @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<Boolean> 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<Boolean> 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<Boolean> loadUser(@Nonnull UUID uuid) {
return loadUser(uuid, null);
}
/**
* Saves a user object back to storage.
*
* <p>You should call this after you make any changes to a user.</p>
*
* @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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> loadAllGroups();
/**
* Saves a group back to storage.
*
* <p>You should call this after you make any changes to a group.</p>
*
* @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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> deleteTrack(@Nonnull Track track);
} }

View File

@ -26,9 +26,11 @@
package me.lucko.luckperms.api.manager; package me.lucko.luckperms.api.manager;
import me.lucko.luckperms.api.Group; import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.Storage;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -41,7 +43,103 @@ import javax.annotation.Nullable;
public interface GroupManager { 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.
*
* <p>If a group by the same name already exists, it will be loaded.</p>
*
* <p>This method is effectively the same as
* {@link Storage#createAndLoadGroup(String)}, however, the Future returns
* the resultant group instance instead of a boolean flag.</p>
*
* <p>Unlike the method in {@link Storage}, when a group cannot be loaded,
* the future will be {@link CompletableFuture completed exceptionally}.</p>
*
* @param name the name of the group
* @return the resultant group
* @throws NullPointerException if the name is null
* @since 4.1
*/
@Nonnull
CompletableFuture<Group> createAndLoadGroup(@Nonnull String name);
/**
* Loads a group from the plugin's storage provider into memory.
*
* <p>Returns an {@link Optional#empty() empty optional} if the group does
* not exist.</p>
*
* <p>This method is effectively the same as
* {@link Storage#loadGroup(String)}, however, the Future returns
* the resultant group instance instead of a boolean flag.</p>
*
* <p>Unlike the method in {@link Storage}, when a group cannot be loaded,
* the future will be {@link CompletableFuture completed exceptionally}.</p>
*
* @param name the name of the group
* @return the resultant group
* @throws NullPointerException if the name is null
* @since 4.1
*/
@Nonnull
CompletableFuture<Optional<Group>> loadGroup(@Nonnull String name);
/**
* Saves a group's data back to the plugin's storage provider.
*
* <p>You should call this after you make any changes to a group.</p>
*
* <p>This method is effectively the same as {@link Storage#saveGroup(Group)},
* however, the Future returns void instead of a boolean flag.</p>
*
* <p>Unlike the method in {@link Storage}, when a group cannot be saved,
* the future will be {@link CompletableFuture completed exceptionally}.</p>
*
* @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<Void> saveGroup(@Nonnull Group group);
/**
* Permanently deletes a group from the plugin's storage provider.
*
* <p>This method is effectively the same as {@link Storage#deleteGroup(Group)},
* however, the Future returns void instead of a boolean flag.</p>
*
* <p>Unlike the method in {@link Storage}, when a group cannot be deleted,
* the future will be {@link CompletableFuture completed exceptionally}.</p>
*
*
* @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<Void> deleteGroup(@Nonnull Group group);
/**
* Loads all groups into memory.
*
* <p>This method is effectively the same as {@link Storage#loadAllTracks()},
* however, the Future returns void instead of a boolean flag.</p>
*
* <p>Unlike the method in {@link Storage}, when a group cannot be loaded,
* the future will be {@link CompletableFuture completed exceptionally}.</p>
*
* @return a future to encapsulate the operation.
* @since 4.1
*/
@Nonnull
CompletableFuture<Void> loadAllGroups();
/**
* Gets a loaded group.
* *
* @param name the name of the group to get * @param name the name of the group to get
* @return a {@link Group} object, if one matching the name exists, or null if not * @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); Group getGroup(@Nonnull String name);
/** /**
* Gets a wrapped group object from the group storage. * Gets a loaded group.
* *
* <p>This method does not return null, unlike {@link #getGroup}</p> * <p>This method does not return null, unlike {@link #getGroup}</p>
* *

View File

@ -25,10 +25,12 @@
package me.lucko.luckperms.api.manager; package me.lucko.luckperms.api.manager;
import me.lucko.luckperms.api.Storage;
import me.lucko.luckperms.api.Track; import me.lucko.luckperms.api.Track;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -41,7 +43,103 @@ import javax.annotation.Nullable;
public interface TrackManager { 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.
*
* <p>If a track by the same name already exists, it will be loaded.</p>
*
* <p>This method is effectively the same as
* {@link Storage#createAndLoadTrack(String)}, however, the Future returns
* the resultant track instance instead of a boolean flag.</p>
*
* <p>Unlike the method in {@link Storage}, when a track cannot be loaded,
* the future will be {@link CompletableFuture completed exceptionally}.</p>
*
* @param name the name of the track
* @return the resultant track
* @throws NullPointerException if the name is null
* @since 4.1
*/
@Nonnull
CompletableFuture<Track> createAndLoadTrack(@Nonnull String name);
/**
* Loads a track from the plugin's storage provider into memory.
*
* <p>Returns an {@link Optional#empty() empty optional} if the track does
* not exist.</p>
*
* <p>This method is effectively the same as
* {@link Storage#loadTrack(String)}, however, the Future returns
* the resultant track instance instead of a boolean flag.</p>
*
* <p>Unlike the method in {@link Storage}, when a track cannot be loaded,
* the future will be {@link CompletableFuture completed exceptionally}.</p>
*
* @param name the name of the track
* @return the resultant track
* @throws NullPointerException if the name is null
* @since 4.1
*/
@Nonnull
CompletableFuture<Optional<Track>> loadTrack(@Nonnull String name);
/**
* Saves a track's data back to the plugin's storage provider.
*
* <p>You should call this after you make any changes to a track.</p>
*
* <p>This method is effectively the same as {@link Storage#saveTrack(Track)},
* however, the Future returns void instead of a boolean flag.</p>
*
* <p>Unlike the method in {@link Storage}, when a track cannot be saved,
* the future will be {@link CompletableFuture completed exceptionally}.</p>
*
* @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<Void> saveTrack(@Nonnull Track track);
/**
* Permanently deletes a track from the plugin's storage provider.
*
* <p>This method is effectively the same as {@link Storage#deleteTrack(Track)},
* however, the Future returns void instead of a boolean flag.</p>
*
* <p>Unlike the method in {@link Storage}, when a track cannot be deleted,
* the future will be {@link CompletableFuture completed exceptionally}.</p>
*
*
* @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<Void> deleteTrack(@Nonnull Track track);
/**
* Loads all tracks into memory.
*
* <p>This method is effectively the same as {@link Storage#loadAllTracks()},
* however, the Future returns void instead of a boolean flag.</p>
*
* <p>Unlike the method in {@link Storage}, when a track cannot be loaded,
* the future will be {@link CompletableFuture completed exceptionally}.</p>
*
* @return a future to encapsulate the operation.
* @since 4.1
*/
@Nonnull
CompletableFuture<Void> loadAllTracks();
/**
* Gets a loaded track.
* *
* @param name the name of the track to get * @param name the name of the track to get
* @return a {@link Track} object, if one matching the name exists, or null if not * @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); Track getTrack(@Nonnull String name);
/** /**
* Gets a wrapped track object from the track storage. * Gets a loaded track.
* *
* <p>This method does not return null, unlike {@link #getTrack}</p> * <p>This method does not return null, unlike {@link #getTrack}</p>
* *

View File

@ -25,11 +25,13 @@
package me.lucko.luckperms.api.manager; package me.lucko.luckperms.api.manager;
import me.lucko.luckperms.api.Storage;
import me.lucko.luckperms.api.User; import me.lucko.luckperms.api.User;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -37,12 +39,74 @@ import javax.annotation.Nullable;
/** /**
* Represents the object responsible for managing {@link User} instances. * Represents the object responsible for managing {@link User} instances.
* *
* <p>Note that User instances are automatically loaded for online players.
* It's likely that offline players will not have an instance pre-loaded.</p>
*
* @since 4.0 * @since 4.0
*/ */
public interface UserManager { public interface UserManager {
/** /**
* Gets a wrapped user object from the user storage * Loads a user from the plugin's storage provider into memory.
*
* <p>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.</p>
*
* <p>Unlike the method in {@link Storage}, when a user cannot be loaded,
* the future will be {@link CompletableFuture completed exceptionally}.</p>
*
* @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<User> loadUser(@Nonnull UUID uuid, @Nullable String username);
/**
* Loads a user from the plugin's storage provider into memory.
*
* <p>This method is effectively the same as {@link Storage#loadUser(UUID)},
* however, the Future returns the resultant user instance instead of a
* boolean flag.</p>
*
* <p>Unlike the method in {@link Storage}, when a user cannot be loaded,
* the future will be {@link CompletableFuture completed exceptionally}.</p>
*
* @param uuid the uuid of the user
* @return the resultant user
* @throws NullPointerException if the uuid is null
* @since 4.1
*/
@Nonnull
default CompletableFuture<User> loadUser(@Nonnull UUID uuid) {
return loadUser(uuid, null);
}
/**
* Saves a user's data back to the plugin's storage provider.
*
* <p>You should call this after you make any changes to a user.</p>
*
* <p>This method is effectively the same as {@link Storage#saveUser(User)},
* however, the Future returns void instead of a boolean flag.</p>
*
* <p>Unlike the method in {@link Storage}, when a user cannot be saved,
* the future will be {@link CompletableFuture completed exceptionally}.</p>
*
* @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<Void> saveUser(@Nonnull User user);
/**
* Gets a loaded user.
* *
* @param uuid the uuid of the user to get * @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 * @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); 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 * @param uuid the uuid of the user to get
* @return an optional {@link User} object * @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 * @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 * @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); 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 * @param name the username of the user to get
* @return an optional {@link User} object * @return an optional {@link User} object

View File

@ -32,6 +32,10 @@ import me.lucko.luckperms.common.storage.DataConstraints;
public final class ApiUtils { public final class ApiUtils {
public static String checkUsername(String s) { public static String checkUsername(String s) {
if (s == null) {
return null;
}
Preconditions.checkArgument( Preconditions.checkArgument(
DataConstraints.PLAYER_USERNAME_TEST.test(s), 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 _'." "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) { public static String checkName(String s) {
if (s == null) {
return null;
}
Preconditions.checkArgument( Preconditions.checkArgument(
DataConstraints.GROUP_NAME_TEST.test(s), 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'." "Invalid name entry '" + s + "'. Names must be less than 37 chars and only contain 'a-z A-Z 1-9'."

View File

@ -78,9 +78,9 @@ public class LuckPermsApiProvider implements LuckPermsApi {
this.plugin = plugin; this.plugin = plugin;
this.platformInfo = new ApiPlatformInfo(plugin); this.platformInfo = new ApiPlatformInfo(plugin);
this.userManager = new ApiUserManager(plugin.getUserManager()); this.userManager = new ApiUserManager(plugin, plugin.getUserManager());
this.groupManager = new ApiGroupManager(plugin.getGroupManager()); this.groupManager = new ApiGroupManager(plugin, plugin.getGroupManager());
this.trackManager = new ApiTrackManager(plugin.getTrackManager()); this.trackManager = new ApiTrackManager(plugin, plugin.getTrackManager());
this.actionLogger = new ApiActionLogger(plugin); this.actionLogger = new ApiActionLogger(plugin);
this.contextManager = new ApiContextManager(plugin, plugin.getContextManager()); this.contextManager = new ApiContextManager(plugin, plugin.getContextManager());
this.metaStackFactory = new ApiMetaStackFactory(plugin); this.metaStackFactory = new ApiMetaStackFactory(plugin);

View File

@ -0,0 +1,41 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.manager;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
public abstract class ApiAbstractManager<I, E, H> {
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);
}

View File

@ -28,10 +28,10 @@ package me.lucko.luckperms.common.api.delegates.manager;
import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.User; import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.context.ContextCalculator; 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.ImmutableContextSet;
import me.lucko.luckperms.api.context.StaticContextCalculator; import me.lucko.luckperms.api.context.StaticContextCalculator;
import me.lucko.luckperms.common.api.delegates.model.ApiUser; import me.lucko.luckperms.common.api.delegates.model.ApiUser;
import me.lucko.luckperms.common.contexts.ContextManager;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import java.util.Objects; import java.util.Objects;
@ -40,11 +40,11 @@ import java.util.Optional;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class ApiContextManager implements ContextManager { public class ApiContextManager implements me.lucko.luckperms.api.context.ContextManager {
private final LuckPermsPlugin plugin; 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.plugin = plugin;
this.handle = handle; this.handle = handle;
} }

View File

@ -25,33 +25,87 @@
package me.lucko.luckperms.common.api.delegates.manager; package me.lucko.luckperms.common.api.delegates.manager;
import me.lucko.luckperms.api.Group; import me.lucko.luckperms.api.event.cause.CreationCause;
import me.lucko.luckperms.api.manager.GroupManager; 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.Objects;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class ApiGroupManager implements GroupManager { public class ApiGroupManager extends ApiAbstractManager<Group, me.lucko.luckperms.api.Group, GroupManager<?>> implements me.lucko.luckperms.api.manager.GroupManager {
private final me.lucko.luckperms.common.managers.group.GroupManager<?> handle; public ApiGroupManager(LuckPermsPlugin plugin, GroupManager<?> handle) {
super(plugin, handle);
public ApiGroupManager(me.lucko.luckperms.common.managers.group.GroupManager<?> handle) {
this.handle = handle;
} }
@Override @Override
public Group getGroup(@Nonnull String name) { protected me.lucko.luckperms.api.Group getDelegateFor(me.lucko.luckperms.common.model.Group internal) {
Objects.requireNonNull(name, "name"); if (internal == null) {
me.lucko.luckperms.common.model.Group group = this.handle.getIfLoaded(name); return null;
return group == null ? null : group.getApiDelegate(); }
return internal.getApiDelegate();
} }
@Nonnull @Nonnull
@Override @Override
public Set<Group> getLoadedGroups() { public CompletableFuture<me.lucko.luckperms.api.Group> createAndLoadGroup(@Nonnull String name) {
return this.handle.getAll().values().stream().map(me.lucko.luckperms.common.model.Group::getApiDelegate).collect(Collectors.toSet()); name = ApiUtils.checkName(Objects.requireNonNull(name, "name"));
return this.plugin.getStorage().noBuffer().createAndLoadGroup(name, CreationCause.API)
.thenApply(this::getDelegateFor);
}
@Nonnull
@Override
public CompletableFuture<Optional<me.lucko.luckperms.api.Group>> 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<Void> 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<Void> 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<Void> 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<me.lucko.luckperms.api.Group> getLoadedGroups() {
return this.handle.getAll().values().stream()
.map(this::getDelegateFor)
.collect(ImmutableCollectors.toSet());
} }
@Override @Override

View File

@ -25,33 +25,83 @@
package me.lucko.luckperms.common.api.delegates.manager; package me.lucko.luckperms.common.api.delegates.manager;
import me.lucko.luckperms.api.Track; import me.lucko.luckperms.api.event.cause.CreationCause;
import me.lucko.luckperms.api.manager.TrackManager; 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.Objects;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class ApiTrackManager implements TrackManager { public class ApiTrackManager extends ApiAbstractManager<Track, me.lucko.luckperms.api.Track, TrackManager<?>> implements me.lucko.luckperms.api.manager.TrackManager {
private final me.lucko.luckperms.common.managers.track.TrackManager<?> handle; public ApiTrackManager(LuckPermsPlugin plugin, TrackManager<?> handle) {
super(plugin, handle);
public ApiTrackManager(me.lucko.luckperms.common.managers.track.TrackManager<?> handle) {
this.handle = handle;
} }
@Override @Override
public Track getTrack(@Nonnull String name) { protected me.lucko.luckperms.api.Track getDelegateFor(Track internal) {
Objects.requireNonNull(name, "name"); if (internal == null) {
me.lucko.luckperms.common.model.Track track = this.handle.getIfLoaded(name); return null;
return track == null ? null : track.getApiDelegate(); }
return internal.getApiDelegate();
} }
@Nonnull @Nonnull
@Override @Override
public Set<Track> getLoadedTracks() { public CompletableFuture<me.lucko.luckperms.api.Track> createAndLoadTrack(@Nonnull String name) {
return this.handle.getAll().values().stream().map(me.lucko.luckperms.common.model.Track::getApiDelegate).collect(Collectors.toSet()); name = ApiUtils.checkName(Objects.requireNonNull(name, "name"));
return this.plugin.getStorage().noBuffer().createAndLoadTrack(name, CreationCause.API)
.thenApply(this::getDelegateFor);
}
@Nonnull
@Override
public CompletableFuture<Optional<me.lucko.luckperms.api.Track>> 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<Void> 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<Void> 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<Void> 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<me.lucko.luckperms.api.Track> getLoadedTracks() {
return this.handle.getAll().values().stream()
.map(this::getDelegateFor)
.collect(ImmutableCollectors.toSet());
} }
@Override @Override

View File

@ -25,43 +25,74 @@
package me.lucko.luckperms.common.api.delegates.manager; package me.lucko.luckperms.common.api.delegates.manager;
import me.lucko.luckperms.api.User; import me.lucko.luckperms.common.api.ApiUtils;
import me.lucko.luckperms.api.manager.UserManager;
import me.lucko.luckperms.common.api.delegates.model.ApiUser; 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.references.UserIdentifier;
import me.lucko.luckperms.common.utils.ImmutableCollectors;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class ApiUserManager implements UserManager { public class ApiUserManager extends ApiAbstractManager<User, me.lucko.luckperms.api.User, UserManager<?>> implements me.lucko.luckperms.api.manager.UserManager {
private final me.lucko.luckperms.common.managers.user.UserManager<?> handle; public ApiUserManager(LuckPermsPlugin plugin, UserManager<?> handle) {
super(plugin, handle);
public ApiUserManager(me.lucko.luckperms.common.managers.user.UserManager<?> handle) {
this.handle = handle;
} }
@Override @Override
public User getUser(@Nonnull UUID uuid) { protected me.lucko.luckperms.api.User getDelegateFor(User internal) {
Objects.requireNonNull(uuid, "uuid"); if (internal == null) {
me.lucko.luckperms.common.model.User user = this.handle.getIfLoaded(uuid); return null;
return user == null ? null : new ApiUser(user);
} }
return new ApiUser(internal);
@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);
} }
@Nonnull @Nonnull
@Override @Override
public Set<User> getLoadedUsers() { public CompletableFuture<me.lucko.luckperms.api.User> loadUser(@Nonnull UUID uuid, @Nullable String username) {
return this.handle.getAll().values().stream().map(ApiUser::new).collect(Collectors.toSet()); 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<Void> 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<me.lucko.luckperms.api.User> getLoadedUsers() {
return this.handle.getAll().values().stream()
.map(this::getDelegateFor)
.collect(ImmutableCollectors.toSet());
} }
@Override @Override
@ -71,7 +102,7 @@ public class ApiUserManager implements UserManager {
} }
@Override @Override
public void cleanupUser(@Nonnull User user) { public void cleanupUser(@Nonnull me.lucko.luckperms.api.User user) {
Objects.requireNonNull(user, "user"); Objects.requireNonNull(user, "user");
this.handle.getHouseKeeper().clearApiUsage(ApiUser.cast(user).getUuid()); this.handle.getHouseKeeper().clearApiUsage(ApiUser.cast(user).getUuid());
} }

View File

@ -52,7 +52,7 @@ public class ApiActionLogger implements ActionLogger {
@Nonnull @Nonnull
@Override @Override
public CompletableFuture<Log> getLog() { public CompletableFuture<Log> 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 @Nonnull

View File

@ -27,30 +27,30 @@ package me.lucko.luckperms.common.api.delegates.model;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.caching.GroupData; import me.lucko.luckperms.api.caching.GroupData;
import me.lucko.luckperms.common.model.Group;
import java.util.Objects; import java.util.Objects;
import java.util.OptionalInt; import java.util.OptionalInt;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public final class ApiGroup extends ApiPermissionHolder implements Group { public final class ApiGroup extends ApiPermissionHolder implements me.lucko.luckperms.api.Group {
public static me.lucko.luckperms.common.model.Group cast(Group group) { public static Group cast(me.lucko.luckperms.api.Group group) {
Objects.requireNonNull(group, "group"); Objects.requireNonNull(group, "group");
Preconditions.checkState(group instanceof ApiGroup, "Illegal instance " + group.getClass() + " cannot be handled by this implementation."); Preconditions.checkState(group instanceof ApiGroup, "Illegal instance " + group.getClass() + " cannot be handled by this implementation.");
return ((ApiGroup) group).getHandle(); 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); super(handle);
this.handle = handle; this.handle = handle;
} }
@Override @Override
me.lucko.luckperms.common.model.Group getHandle() { Group getHandle() {
return this.handle; return this.handle;
} }

View File

@ -25,8 +25,9 @@
package me.lucko.luckperms.common.api.delegates.model; package me.lucko.luckperms.common.api.delegates.model;
import me.lucko.luckperms.api.Log;
import me.lucko.luckperms.api.LogEntry; import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.common.actionlog.Log;
import java.util.Objects; import java.util.Objects;
import java.util.SortedMap; import java.util.SortedMap;
@ -38,11 +39,11 @@ import javax.annotation.Nonnull;
import static me.lucko.luckperms.common.api.ApiUtils.checkName; import static me.lucko.luckperms.common.api.ApiUtils.checkName;
@SuppressWarnings("unchecked") @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 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; this.handle = handle;
} }

View File

@ -35,13 +35,13 @@ import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.DataMutateResult;
import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.PermissionHolder;
import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.caching.CachedData; import me.lucko.luckperms.api.caching.CachedData;
import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.NodeMapType; 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.model.User;
import me.lucko.luckperms.common.node.MetaType; import me.lucko.luckperms.common.node.MetaType;
import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.common.utils.ImmutableCollectors;
@ -56,14 +56,14 @@ import java.util.function.Predicate;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class ApiPermissionHolder implements PermissionHolder { public class ApiPermissionHolder implements me.lucko.luckperms.api.PermissionHolder {
private final me.lucko.luckperms.common.model.PermissionHolder handle; private final PermissionHolder handle;
ApiPermissionHolder(me.lucko.luckperms.common.model.PermissionHolder handle) { ApiPermissionHolder(PermissionHolder handle) {
this.handle = Objects.requireNonNull(handle, "handle"); this.handle = Objects.requireNonNull(handle, "handle");
} }
me.lucko.luckperms.common.model.PermissionHolder getHandle() { PermissionHolder getHandle() {
return this.handle; return this.handle;
} }

View File

@ -29,13 +29,13 @@ import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.HeldPermission; import me.lucko.luckperms.api.HeldPermission;
import me.lucko.luckperms.api.Log; import me.lucko.luckperms.api.Log;
import me.lucko.luckperms.api.LogEntry; import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.Storage;
import me.lucko.luckperms.api.Track; import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.User; import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.event.cause.CreationCause; import me.lucko.luckperms.api.event.cause.CreationCause;
import me.lucko.luckperms.api.event.cause.DeletionCause; import me.lucko.luckperms.api.event.cause.DeletionCause;
import me.lucko.luckperms.common.node.NodeFactory; import me.lucko.luckperms.common.node.NodeFactory;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.Storage;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -44,17 +44,34 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.function.Function;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import static me.lucko.luckperms.common.api.ApiUtils.checkName; import static me.lucko.luckperms.common.api.ApiUtils.checkName;
import static me.lucko.luckperms.common.api.ApiUtils.checkUsername; import static me.lucko.luckperms.common.api.ApiUtils.checkUsername;
public class ApiStorage implements Storage { public class ApiStorage implements me.lucko.luckperms.api.Storage {
private final LuckPermsPlugin plugin; private static final Function<Throwable, Boolean> CONSUME_EXCEPTION = throwable -> {
private final me.lucko.luckperms.common.storage.Storage handle; throwable.printStackTrace();
return false;
};
public ApiStorage(LuckPermsPlugin plugin, me.lucko.luckperms.common.storage.Storage handle) { private static Function<Throwable, Boolean> consumeExceptionToFalse() {
return CONSUME_EXCEPTION;
}
private static <T> Function<Throwable, T> consumeExceptionToNull() {
return throwable -> {
throwable.printStackTrace();
return null;
};
}
private final LuckPermsPlugin plugin;
private final Storage handle;
public ApiStorage(LuckPermsPlugin plugin, Storage handle) {
this.plugin = plugin; this.plugin = plugin;
this.handle = handle; this.handle = handle;
} }
@ -86,72 +103,87 @@ public class ApiStorage implements Storage {
@Override @Override
public CompletableFuture<Boolean> logAction(@Nonnull LogEntry entry) { public CompletableFuture<Boolean> logAction(@Nonnull LogEntry entry) {
Objects.requireNonNull(entry, "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 @Nonnull
@Override @Override
public CompletableFuture<Log> getLog() { public CompletableFuture<Log> getLog() {
return this.handle.noBuffer().getLog().thenApply(log -> log == null ? null : new ApiLog(log)); return this.handle.noBuffer().getLog().<Log>thenApply(ApiLog::new).exceptionally(consumeExceptionToNull());
} }
@Nonnull @Nonnull
@Override @Override
public CompletableFuture<Boolean> loadUser(@Nonnull UUID uuid, String username) { public CompletableFuture<Boolean> loadUser(@Nonnull UUID uuid, String username) {
Objects.requireNonNull(uuid, "uuid"); Objects.requireNonNull(uuid, "uuid");
username = checkUsername(username);
if (this.plugin.getUserManager().getIfLoaded(uuid) == null) { if (this.plugin.getUserManager().getIfLoaded(uuid) == null) {
this.plugin.getUserManager().getHouseKeeper().registerApiUsage(uuid); 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 @Nonnull
@Override @Override
public CompletableFuture<Boolean> saveUser(@Nonnull User user) { public CompletableFuture<Boolean> saveUser(@Nonnull User user) {
Objects.requireNonNull(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 @Nonnull
@Override @Override
public CompletableFuture<Set<UUID>> getUniqueUsers() { public CompletableFuture<Set<UUID>> getUniqueUsers() {
return this.handle.noBuffer().getUniqueUsers(); return this.handle.noBuffer().getUniqueUsers().exceptionally(consumeExceptionToNull());
} }
@Nonnull @Nonnull
@Override @Override
public CompletableFuture<List<HeldPermission<UUID>>> getUsersWithPermission(@Nonnull String permission) { public CompletableFuture<List<HeldPermission<UUID>>> getUsersWithPermission(@Nonnull String permission) {
Objects.requireNonNull(permission, "permission"); Objects.requireNonNull(permission, "permission");
return this.handle.noBuffer().getUsersWithPermission(permission); return this.handle.noBuffer().getUsersWithPermission(permission).exceptionally(consumeExceptionToNull());
} }
@Nonnull @Nonnull
@Override @Override
public CompletableFuture<Boolean> createAndLoadGroup(@Nonnull String name) { public CompletableFuture<Boolean> createAndLoadGroup(@Nonnull String name) {
Objects.requireNonNull(name, "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 @Nonnull
@Override @Override
public CompletableFuture<Boolean> loadGroup(@Nonnull String name) { public CompletableFuture<Boolean> loadGroup(@Nonnull String name) {
Objects.requireNonNull(name, "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 @Nonnull
@Override @Override
public CompletableFuture<Boolean> loadAllGroups() { public CompletableFuture<Boolean> loadAllGroups() {
return this.handle.noBuffer().loadAllGroups().thenApply(x -> true); return this.handle.noBuffer().loadAllGroups()
.thenApply(r -> true)
.exceptionally(consumeExceptionToFalse());
} }
@Nonnull @Nonnull
@Override @Override
public CompletableFuture<Boolean> saveGroup(@Nonnull Group group) { public CompletableFuture<Boolean> saveGroup(@Nonnull Group group) {
Objects.requireNonNull(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 @Nonnull
@ -161,48 +193,60 @@ public class ApiStorage implements Storage {
if (group.getName().equalsIgnoreCase(NodeFactory.DEFAULT_GROUP_NAME)) { if (group.getName().equalsIgnoreCase(NodeFactory.DEFAULT_GROUP_NAME)) {
throw new IllegalArgumentException("Cannot delete the default group."); 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 @Nonnull
@Override @Override
public CompletableFuture<List<HeldPermission<String>>> getGroupsWithPermission(@Nonnull String permission) { public CompletableFuture<List<HeldPermission<String>>> getGroupsWithPermission(@Nonnull String permission) {
Objects.requireNonNull(permission, "permission"); Objects.requireNonNull(permission, "permission");
return this.handle.noBuffer().getGroupsWithPermission(permission); return this.handle.noBuffer().getGroupsWithPermission(permission).exceptionally(consumeExceptionToNull());
} }
@Nonnull @Nonnull
@Override @Override
public CompletableFuture<Boolean> createAndLoadTrack(@Nonnull String name) { public CompletableFuture<Boolean> createAndLoadTrack(@Nonnull String name) {
Objects.requireNonNull(name, "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 @Nonnull
@Override @Override
public CompletableFuture<Boolean> loadTrack(@Nonnull String name) { public CompletableFuture<Boolean> loadTrack(@Nonnull String name) {
Objects.requireNonNull(name, "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 @Nonnull
@Override @Override
public CompletableFuture<Boolean> loadAllTracks() { public CompletableFuture<Boolean> loadAllTracks() {
return this.handle.noBuffer().loadAllTracks().thenApply(x -> true); return this.handle.noBuffer().loadAllTracks()
.thenApply(r -> true)
.exceptionally(consumeExceptionToFalse());
} }
@Nonnull @Nonnull
@Override @Override
public CompletableFuture<Boolean> saveTrack(@Nonnull Track track) { public CompletableFuture<Boolean> saveTrack(@Nonnull Track track) {
Objects.requireNonNull(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 @Nonnull
@Override @Override
public CompletableFuture<Boolean> deleteTrack(@Nonnull Track track) { public CompletableFuture<Boolean> deleteTrack(@Nonnull Track track) {
Objects.requireNonNull(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 @Nonnull
@ -210,7 +254,9 @@ public class ApiStorage implements Storage {
public CompletableFuture<Boolean> saveUUIDData(@Nonnull String username, @Nonnull UUID uuid) { public CompletableFuture<Boolean> saveUUIDData(@Nonnull String username, @Nonnull UUID uuid) {
Objects.requireNonNull(username, "username"); Objects.requireNonNull(username, "username");
Objects.requireNonNull(uuid, "uuid"); 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 @Nonnull

View File

@ -29,27 +29,27 @@ import com.google.common.base.Preconditions;
import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.DataMutateResult;
import me.lucko.luckperms.api.Group; 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.List;
import java.util.Objects; import java.util.Objects;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public final class ApiTrack implements Track { public final class ApiTrack implements me.lucko.luckperms.api.Track {
public static me.lucko.luckperms.common.model.Track cast(Track track) { public static Track cast(me.lucko.luckperms.api.Track track) {
Objects.requireNonNull(track, "track"); Objects.requireNonNull(track, "track");
Preconditions.checkState(track instanceof ApiTrack, "Illegal instance " + track.getClass() + " cannot be handled by this implementation."); Preconditions.checkState(track instanceof ApiTrack, "Illegal instance " + track.getClass() + " cannot be handled by this implementation.");
return ((ApiTrack) track).getHandle(); 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; this.handle = handle;
} }
me.lucko.luckperms.common.model.Track getHandle() { Track getHandle() {
return this.handle; return this.handle;
} }

View File

@ -28,8 +28,8 @@ package me.lucko.luckperms.common.api.delegates.model;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.DataMutateResult;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.caching.UserData; import me.lucko.luckperms.api.caching.UserData;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.node.NodeFactory; import me.lucko.luckperms.common.node.NodeFactory;
import java.util.Objects; import java.util.Objects;
@ -37,21 +37,21 @@ import java.util.UUID;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public final class ApiUser extends ApiPermissionHolder implements User { public final class ApiUser extends ApiPermissionHolder implements me.lucko.luckperms.api.User {
public static me.lucko.luckperms.common.model.User cast(User u) { 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."); Preconditions.checkState(u instanceof ApiUser, "Illegal instance " + u.getClass() + " cannot be handled by this implementation.");
return ((ApiUser) u).getHandle(); 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); super(handle);
this.handle = handle; this.handle = handle;
} }
@Override @Override
me.lucko.luckperms.common.model.User getHandle() { User getHandle() {
return this.handle; return this.handle;
} }

View File

@ -77,8 +77,8 @@ public class LuckPermsEventBus implements EventBus {
} }
@Nonnull @Nonnull
@SuppressWarnings("unchecked")
@Override @Override
@SuppressWarnings("unchecked")
public <T extends LuckPermsEvent> Set<EventHandler<T>> getHandlers(@Nonnull Class<T> eventClass) { public <T extends LuckPermsEvent> Set<EventHandler<T>> getHandlers(@Nonnull Class<T> eventClass) {
Set<LuckPermsEventHandler<?>> handlers = this.handlerMap.get(eventClass); Set<LuckPermsEventHandler<?>> handlers = this.handlerMap.get(eventClass);
if (handlers == null) { if (handlers == null) {