001/*
002 * PermissionsEx
003 * Copyright (C) zml and PermissionsEx contributors
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package ca.stellardrift.permissionsex;
018
019import ca.stellardrift.permissionsex.context.ContextDefinitionProvider;
020import ca.stellardrift.permissionsex.context.ContextInheritance;
021import ca.stellardrift.permissionsex.datastore.DataStore;
022import ca.stellardrift.permissionsex.rank.RankLadderCollection;
023import ca.stellardrift.permissionsex.subject.CalculatedSubject;
024import ca.stellardrift.permissionsex.subject.SubjectRef;
025import ca.stellardrift.permissionsex.subject.SubjectType;
026import ca.stellardrift.permissionsex.subject.SubjectTypeCollection;
027import org.checkerframework.checker.nullness.qual.Nullable;
028
029import java.util.Collection;
030import java.util.Set;
031import java.util.concurrent.CompletableFuture;
032import java.util.function.Consumer;
033import java.util.function.Function;
034import java.util.regex.Pattern;
035
036/**
037 * A PermissionsEx engine.
038 *
039 * @since 2.0.0
040 */
041public interface PermissionsEngine extends ContextDefinitionProvider {
042
043    /**
044     * Create a new builder for an engine.
045     *
046     * @return the engine builder
047     * @since 2.0.0
048     */
049    static PermissionsEngineBuilder<Void> builder() {
050        return EngineBuilderService.ACTIVE_BUILDER.newBuilder();
051    }
052
053    /**
054     * Create a new builder for an engine.
055     *
056     * @return the engine builder
057     * @since 2.0.0
058     */
059    static <C> PermissionsEngineBuilder<C> builder(final Class<C> configType) {
060        return EngineBuilderService.ACTIVE_BUILDER.newBuilder(configType);
061    }
062
063    // -- Internal subject types -- //
064
065    /**
066     * Subjects holding data that will be applied to every subject of a type.
067     *
068     * @return the {@code fallback} subject type
069     * @since 2.0.0
070     */
071    SubjectTypeCollection<SubjectType<?>> defaults();
072
073    /**
074     * Subjects holding data that will be applied to subjects of each type when no other data is available.
075     *
076     * @return the {@code fallback} subject type
077     * @since 2.0.0
078     */
079    SubjectTypeCollection<SubjectType<?>> fallbacks();
080
081    // -- Working with subject types -- //
082
083    /**
084     * Register subject types with the engine.
085     *
086     * @param types the types to register
087     * @since 2.0.0
088     */
089    void registerSubjectTypes(final SubjectType<?>... types);
090
091    /**
092     * Get a subject type by name.
093     *
094     * <p>If this subject type has not been seen before, it will be registered.</p>
095     *
096     * @param type the type identifier
097     * @return a subject type instance, never null
098     * @since 2.0.0
099     */
100    <I> SubjectTypeCollection<I> subjects(final SubjectType<I> type);
101
102    /**
103     * Resolve a subject from a reference.
104     *
105     * @param reference the subject reference to resolve
106     * @param <I> identifier type
107     * @return a future providing the resolved subject
108     * @since 2.0.0
109     */
110    default <I> CompletableFuture<CalculatedSubject> subject(final SubjectRef<I> reference) {
111        return this.subjects(reference.type()).get(reference.identifier());
112    }
113
114    /**
115     * Get subject types with actively stored data.
116     *
117     * @return an unmodifiable view of the actively loaded subject types
118     */
119    Collection<? extends SubjectTypeCollection<?>> loadedSubjectTypes();
120
121    /**
122     * Get all registered subject types
123     *
124     * @return a stream producing all subject types
125     * @since 2.0.0
126     */
127    Set<SubjectType<?>> knownSubjectTypes();
128
129    /**
130     * Get a cache for rank ladders known by the engine.
131     *
132     * <p>Rank ladders allow for promotion and demotion of a subject among a
133     * set of ranked parents.</p>
134     *
135     * @return the ladder cache
136     * @since 2.0.0
137     */
138    RankLadderCollection ladders();
139
140    /**
141     * Perform a low-level bulk operation.
142     *
143     * <p>This can be used for transforming subjects if the subject type definition changes, and
144     * any large data changes that require information that may no longer be valid with current
145     * subject type options.</p>
146     *
147     * <p>When possible, higher-level bulk query API (not yet written) should be used instead.</p>
148     *
149     * @param actor the action to perform
150     * @param <V> the result type
151     * @return a future completing with the result of the action
152     */
153    <V> CompletableFuture<V> doBulkOperation(final Function<DataStore, CompletableFuture<V>> actor);
154
155    /**
156     * Get the current context inheritance.
157     *
158     * <p>No update listener will be registered</p>
159     *
160     * @return a future providing the current context inheritance data
161     * @see #contextInheritance(Consumer) for more details on context inheritance
162     * @since 2.0.0
163     */
164    default CompletableFuture<ContextInheritance> contextInheritance() {
165        return this.contextInheritance((Consumer<ContextInheritance>) null);
166    }
167
168    /**
169     * Get context inheritance data.
170     *
171     * <p>The result of the future is immutable -- to take effect, the object returned by any
172     * update methods in {@link ContextInheritance} must be passed to {@link #contextInheritance(ContextInheritance)}.
173     *  It follows that anybody else's changes will not appear in the returned inheritance object -- so if updates are
174     *  desired providing a callback function is important.</p>
175     *
176     * @param listener A callback function that will be triggered whenever there is a change to the context inheritance
177     * @return A future providing the current context inheritance data
178     * @since 2.0.0
179     */
180    CompletableFuture<ContextInheritance> contextInheritance(final @Nullable Consumer<ContextInheritance> listener);
181
182    /**
183     * Update the context inheritance when values have been changed
184     *
185     * @param newInheritance The modified inheritance object
186     * @return A future containing the latest context inheritance object
187     * @since 2.0.0
188     */
189    CompletableFuture<ContextInheritance> contextInheritance(ContextInheritance newInheritance);
190
191    // -- Engine state -- //
192
193    /**
194     * Get whether or not debug mode is enabled.
195     *
196     * <p>When debug mode is enabled, all permission queries will be logged to the engine's
197     *    active logger.</p>
198     *
199     * @return the debug mode state
200     * @since 2.0.0
201     */
202    boolean debugMode();
203
204    /**
205     * Set the active debug mode state.
206     *
207     * @param enabled whether debug mode is enabled
208     * @since 2.0.0
209     * @see #debugMode() for information on the consequences of debug mode
210     */
211    default void debugMode(final boolean enabled) {
212        this.debugMode(enabled, null);
213    }
214
215    /**
216     * Set the active debug mode state, and a filter.
217     *
218     * @param enabled whether debug mode is enabled
219     * @param filter a filter for values (permissions, options, and subject names) that will be
220     *               logged by debug mode.
221     * @since 2.0.0
222     * @see #debugMode() for information on the consequences of debug mode
223     */
224    void debugMode(final boolean enabled, final @Nullable Pattern filter);
225
226}