All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.spongepowered.api.service.permission.SubjectCollection Maven / Gradle / Ivy

There is a newer version: 9.0.0
Show newest version
/*
 * This file is part of SpongeAPI, licensed under the MIT License (MIT).
 *
 * Copyright (c) SpongePowered 
 * 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 org.spongepowered.api.service.permission;

import org.spongepowered.api.event.Cause;
import org.spongepowered.api.service.context.Context;

import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * An object which manages subjects of a certain type (user, group, etc).
 *
 * 

A distinction is made between subjects which exist and are loaded, and * subjects which exist but are not currently loaded into memory. The methods to * "load" data return {@link CompletableFuture}s, and will load the data into * memory if it isn't already loaded. The methods to "get" data return * {@link Optional}s, which will only be filled if the data is currently * loaded.

* *

Note: the default subject must already be cached when the subject * collection is fetched.

* *

When Subjects are loaded, it may not be necessary to load data about all * parent subjects immediately, however, lookups should still honour inheritance * rules.

*/ public interface SubjectCollection { /** * Return the identifier for this collection. * * @return The identifier */ String identifier(); /** * Returns a predicate which determines whether or not a given identifier is * valid for a subject held by this collection. * *

It is expected that the {@link PermissionService#SUBJECTS_USER} * collection should accept identifiers in UUID RFC4122 string format. (In * the format produced by {@link UUID#toString()}

* * @return The predicate */ Predicate identifierValidityPredicate(); /** * Loads and returns a subject with the given identifier. * *

The returned future will complete exceptionally if the subject with * the given identifier cannot be loaded.

* *

A {@link IllegalArgumentException} will be thrown directly by this * method if the identifier does not pass the identifier validity * predicate.

* * @param identifier The identifier. All identifiers are case-insensitive * @return A subject for the given identifier * @throws IllegalArgumentException If the subject identifier does not pass * the validity predicate for this * collection. */ CompletableFuture loadSubject(String identifier); /** * Returns a subject with the given identifier, if the subject is already * loaded within this collection. * *

It is important to note that a subject with the given identifier * may still exist, even if this method returns an empty * optional. Checking for the presence of a subject should be * done using {@link #hasSubject(String)}.

* *

If the subject identifier does not pass the validity predicate, this * method will return an empty optional, and not throw an exception.

* * @param identifier The identifier * @return A subject for the given identifier */ Optional subject(String identifier); /** * Returns whether a subject with the given identifier currently exists. * *

The return value of this function does not influence whether or * not the results from any subject lookups should be obtained. * * @param identifier The identifier of the subject * @return If the subject currently exists */ CompletableFuture hasSubject(String identifier); /** * Gets a map of subjects from the provided set of identifiers. * *

If any of the identifiers do not pass the collections * {@link #identifierValidityPredicate()}, a subject will not be returned * for that identifier.

* * @param identifiers A set of identifiers to get subjects for * @return a map of subjects corresponding to the identifiers passed */ CompletableFuture> loadSubjects(Iterable identifiers); /** * Returns an immutable copy of all subjects currently loaded in this * collection. * * @return A collection containing the subjects currently loaded into this * subject collection. */ Collection loadedSubjects(); /** * Gets a set of Subject identifiers being stored in the collection. This * method must return a complete list, including identifiers of subjects not * currently loaded. * *

The results of this method should not be passed directly to * {@link #loadSubjects(Iterable)}. Instead, each individual subject should be * loaded, processed, and then allowed to be unloaded using * {@link #suggestUnload(String)}.

* *

If you simply need to process each subject in the collection, you can * use {@link #applyToAll(Consumer)} and gather data.

* * @return A set containing the identifiers of every Subject in this * collection */ CompletableFuture> allIdentifiers(); /** * Creates a new subject reference to represent the expressed subject. * *

Note that instances of SubjectReference must be capable of resolving * the identifier to a Subject without being passed a reference to the * service.

* *

A {@link IllegalArgumentException} will be thrown directly by this * method if the identifier does not pass the identifier validity * predicate.

* * @param subjectIdentifier The identifier of the subject * @return A subject reference to represent the expressed subject * @throws IllegalArgumentException If the subject identifier does not pass * the validity predicate for this * collection. */ SubjectReference newSubjectReference(String subjectIdentifier); /** * Performs an action on each Subject in the collection. * *

Subjects are loaded, supplied to the consumer, and then allowed to be * uncached by the implementation.

* *

This should be used to apply bulk changes or gather data about all * Subjects in the collection. The provided consumer will be supplied * asynchronously. Acting upon a large collection may be particularly * resource intensive.

* *

Implementations may choose to load and process subjects in * parallel.

* * @param action The action to perform on each subject * @return A future which will complete when the operation has finished */ default CompletableFuture applyToAll(final Consumer action) { Objects.requireNonNull(action, "action"); return CompletableFuture.runAsync(() -> { final Set identifiers = this.allIdentifiers().join(); this.applyToAll(identifiers, action).join(); }); } /** * Performs an action on each Subject in the provided set. * *

Subjects are loaded, supplied to the consumer, and then allowed to be * uncached by the implementation.

* *

This should be used to apply bulk changes or gather data about all * Subjects in the collection. The provided consumer will be supplied * asynchronously. Acting upon a large collection may be particularly * resource intensive.

* *

Implementations may choose to load and process subjects in * parallel.

* * @param identifiers a set of identifiers to apply the action to * @param action The action to perform on each subject * @return A future which will complete when the operation has finished */ default CompletableFuture applyToAll(final Iterable identifiers, final Consumer action) { Objects.requireNonNull(action, "action"); Objects.requireNonNull(identifiers, "identifiers"); return CompletableFuture.runAsync(() -> { for (final String id : identifiers) { final Subject subject = this.loadSubject(id).join(); action.accept(subject); this.suggestUnload(subject.identifier()); } }); } /** * Return the identifiers of all known subjects with the given permission * set. * *

This method DOES NOT consider inheritance, and will * only query the data set to the subjects {@link Subject#subjectData()}. * Transient data is not considered.

* *

As no context is passed, it is up to the implementation to decide * which contexts to use. When available, it is likely that * {@link SubjectData#GLOBAL_CONTEXT} will be used.

*

Contexts will be extracted from the current cause for each lookup.

* * @param permission The permission to check * @return A reference to any subject known to have this permission * set, and the value this permission is set to */ CompletableFuture> allWithPermission(String permission); /** * Return the identifiers of all known subjects with the given permission * set. * *

This method DOES NOT consider inheritance, and will only query * the data set to the subjects {@link Subject#subjectData()}. Transient * data is not considered.

* * @param permission The permission to check * @param cause The cause to extract context information from * @return A reference to any subject known to have this permission * set, and the value this permission is set to */ CompletableFuture> allWithPermission(String permission, Cause cause); /** * Return all loaded subjects with the given permission set. * *

This method DOES NOT consider inheritance, and will only query * the data set to the subjects {@link Subject#subjectData()}. Transient * data is not considered.

* *

Contexts will be extracted from the current cause for each lookup.

* * @param permission The permission to check * @return A map containing any subject known to have this permission set, * and the value this permission is set to */ Map loadedWithPermission(String permission); /** * Return all loaded subjects with the given permission set. * *

This method DOES NOT consider inheritance, and will only query * the data set to the subjects {@link Subject#subjectData()}. Transient * data is not considered.

* * @param permission The permission to check * @param cause The cause to extract context information from * @return A map containing any subject known to have this permission set, * and the value this permission is set to */ Map loadedWithPermission(String permission, Cause cause); /** * Gets the subject holding data that is applied by default to all * subjects in this collection. * *

This subject is at the root of all inheritance trees for subjects in * this collection, but at a higher priority chan defaults expressed to * {@link PermissionService#defaults()}.

* *

Note: This data may be persisted, so plugins that add * permissions to this subject must take care to not override * permissions already set or modified.

* *

It is also recommended to use * {@link Subject#transientSubjectData()} where possible to avoid * persisting unnecessary data.

* *

Assigning default permissions should be used sparingly, and by * convention, only in situations where "default" game behaviour is restored * by granting a certain permission.

* * @return The subject holding defaults for this collection */ Subject defaults(); /** * Indicate that a certain subject may be unloaded by the implementation. * *

This is only a hint to the implementation, and does not guarantee that * the subject will be unloaded.

* * @param identifier The subject to be unloaded */ void suggestUnload(String identifier); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy