/** * PermissionsEx * Copyright (C) zml and PermissionsEx contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ninja.leaping.permissionsex.backend; import ninja.leaping.configurate.ConfigurationNode; import ninja.leaping.permissionsex.PermissionsEx; import ninja.leaping.permissionsex.data.Caching; import ninja.leaping.permissionsex.data.ContextInheritance; import ninja.leaping.permissionsex.data.ImmutableSubjectData; import ninja.leaping.permissionsex.exception.PermissionsException; import ninja.leaping.permissionsex.exception.PermissionsLoadingException; import ninja.leaping.permissionsex.rank.RankLadder; import ninja.leaping.permissionsex.util.Util; import javax.annotation.Nullable; import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.function.Function; import static ninja.leaping.permissionsex.util.Translations.t; /** * Data type abstraction for permissions data */ public interface DataStore { /** * Activate this data store from the required data * @throws PermissionsLoadingException If the backing data cannot be loaded */ void initialize(PermissionsEx core) throws PermissionsLoadingException; /** * Free any resources this backend may be using */ void close(); /** * Loads the data at the specified type and identifier. Implementations of this method do not need to perform any caching. * * @param type The type of subject to get * @param identifier The subject's identifier * @param listener The update listener for this subject * @return The relevant subject data */ CompletableFuture<ImmutableSubjectData> getData(String type, String identifier, @Nullable Caching<ImmutableSubjectData> listener); /** * Sets the data at the specified type and identifier. * * @param type The type of subject data is being fetched for * @param identifier The identifier of the subject data is being fetched for * @param data The data to commit to this backend. This being null deletes any data for the given identifier * @return A future that can be used to listen for completion of writing the changed data */ CompletableFuture<ImmutableSubjectData> setData(String type, String identifier, @Nullable ImmutableSubjectData data); default CompletableFuture<Void> moveData(String oldType, String oldIdentifier, String newType, String newIdentifier) { return isRegistered(oldType, oldIdentifier).thenCombine(isRegistered(newType, newIdentifier), (oldRegistered, newRegistered) -> { if (oldRegistered && !newRegistered) { return getData(oldType, oldIdentifier, null) .thenCompose(oldData -> setData(newType, newIdentifier, oldData)) .thenCompose(newData -> setData(oldType, oldIdentifier, null)) .thenApply(inp -> (Void) null); } else { return Util.<Void>failedFuture(new PermissionsException(t("Destination subject already existed or target subject did not!"))); } }).thenCompose(future -> future); } /** * Return if the given subject has any data stored in this backend. * * @param type The subject's type * @param identifier The subject's identifier * @return whether any data is stored */ CompletableFuture<Boolean> isRegistered(String type, String identifier); /** * Get all data for subjects of the specified type. This {@link Iterable} may be filled asynchronously * @param type The type to get all data for * @return An iterable providing data */ Iterable<Map.Entry<String, ImmutableSubjectData>> getAll(String type); /** * Get all subject identifiers for subjects of the given type. * * @param type The type of subject to get identifiers for * @return The registered identifiers of subjects of type {@code type} */ Set<String> getAllIdentifiers(String type); /** * Return all subject types that contain data * * @return The registered subject types */ Set<String> getRegisteredTypes(); /** * Returns all subjects present in this data store * * @return An iterable containing all subjects */ String serialize(ConfigurationNode node) throws PermissionsLoadingException; /** * Returns all subjects present in this data store * * @return An iterable containing all subjects */ Iterable<Map.Entry<Map.Entry<String,String>,ImmutableSubjectData>> getAll(); /** * Perform a bulk operation on this data store. While this operation is in progress, all writes must be suppressed * (meaning changes must be cached in memory until the operation is complete). * * Bulk operations may be executed asynchronously. * * @param function The function to call containing the operation. */ <T> CompletableFuture<T> performBulkOperation(Function<DataStore, T> function); /** * Get all rank ladders. * * @return The names of all rank ladders */ Iterable<String> getAllRankLadders(); /** * Get a specific rank ladder, with a possible update listener. * * @param ladder The ladder to get. Case-insensitive * @param listener The listener to track possible updates * @return the ladder */ CompletableFuture<RankLadder> getRankLadder(String ladder, @Nullable Caching<RankLadder> listener); /** * Whether a rank ladder by the given name is present. * * @param ladder The ladder to check. Case-insensitive * @return Whether a ladder by the provided name exists */ CompletableFuture<Boolean> hasRankLadder(String ladder); /** * Set the rank ladder at the given identifier. * * @param identifier The name of the ladder. Case-insensitive for overwriting existing ladders * @param ladder The ladder to update * @return a future tracking the status of this operation */ CompletableFuture<RankLadder> setRankLadder(String identifier, @Nullable RankLadder ladder); /** * Get context inheritance information * @param inheritance The listener to notify about changes * @return A future that will supply context inheritance */ CompletableFuture<ContextInheritance> getContextInheritance(Caching<ContextInheritance> inheritance); CompletableFuture<ContextInheritance> setContextInheritance(ContextInheritance inheritance); }