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.subject;
018
019import ca.stellardrift.permissionsex.context.ContextValue;
020import ca.stellardrift.permissionsex.logging.PermissionCheckNotifier;
021import ca.stellardrift.permissionsex.util.NodeTree;
022import org.checkerframework.checker.nullness.qual.Nullable;
023import org.spongepowered.configurate.ConfigurationNode;
024
025import java.util.List;
026import java.util.Map;
027import java.util.Optional;
028import java.util.Set;
029import java.util.concurrent.CompletableFuture;
030import java.util.function.Consumer;
031
032public interface CalculatedSubject {
033    /**
034     * Get the identifier for this subject, as a map entry where the key is the identifier for this
035     * subject's type and the value is the specific identifier for this subject.
036     *
037     * @return The identifier
038     */
039    SubjectRef<?> identifier();
040
041    /**
042     * Get the subject type holding this calculated subject.
043     *
044     * @return The subject type
045     */
046    SubjectTypeCollection<?> containingType();
047
048    /**
049     * Get the permissions tree in this subject's active contexts.
050     *
051     * @return A node tree with the calculated permissions
052     */
053    default NodeTree permissions() {
054        return permissions(activeContexts());
055    }
056
057    /**
058     * Get the permissions tree for a certain set of contexts.
059     *
060     * @param contexts The contexts to get permissions in
061     * @return A node tree with the calculated permissions
062     */
063    NodeTree permissions(Set<ContextValue<?>> contexts);
064
065    /**
066     * Get all options for this subject's active contexts. Options are plain strings and therefore
067     * do not have wildcard handling.
068     *
069     * @return A map of option keys to values
070     */
071    default Map<String, String> options() {
072        return options(activeContexts());
073    }
074
075    /**
076     * Get all options for a certain set of contexts. Options are plain strings and therefore do not
077     * have wildcard handling.
078     *
079     * @param contexts The contexts to query
080     * @return A map of option keys to values
081     */
082    Map<String, String> options(Set<ContextValue<?>> contexts);
083
084    /**
085     * Get a list of all parents inheriting from this subject in the active contexts.
086     *
087     * @return The list of parents that apply to this subject
088     */
089    default List<SubjectRef<?>> parents() {
090        return parents(activeContexts());
091    }
092
093    /**
094     * Get a list of all parents inheriting from this subject.
095     *
096     * @param contexts The contexts to check
097     * @return The list of parents that apply to this subject
098     */
099    List<SubjectRef<?>> parents(Set<ContextValue<?>> contexts);
100
101    Set<ContextValue<?>> activeContexts();
102
103    CompletableFuture<Set<ContextValue<?>>> usedContextValues();
104
105    /**
106     * Query a specific permission in this subject's active contexts
107     * This method takes into account context and wildcard inheritance calculations for any permission.
108     *
109     * <p>Any checks made through this method will be logged by the {@link PermissionCheckNotifier}
110     * registered with the PEX engine.</p>
111     *
112     * @param permission The permission to query
113     * @return The permission value. &lt;0 evaluates to false, 0 is undefined, and &gt;0 evaluates to true.
114     */
115    default int permission(final String permission) {
116        return permission(activeContexts(), permission);
117    }
118
119    /**
120     * Query a specific permission in a certain set of contexts.
121     * This method takes into account context and wildcard inheritance calculations for any permission.
122     *
123     * <p>Any checks made through this method will be logged by the {@link PermissionCheckNotifier}
124     * registered with the PEX engine.</p>
125     *
126     * @param contexts The contexts to check in
127     * @param permission The permission to query
128     * @return The permission value. &lt;0 evaluates to false, 0 is undefined, and &gt;0 evaluates to true.
129     */
130    int permission(Set<ContextValue<?>> contexts, String permission);
131
132    /**
133     * Query whether this subject has a specific permission in this subject's active contexts
134     * This method takes into account context and wildcard inheritance calculations for any permission.
135     *
136     * <p>Any checks made through this method will be logged by the {@link PermissionCheckNotifier}
137     * registered with the PEX engine.</p>
138     *
139     * @param permission The permission to query
140     * @return Whether the subject has a true permissions value
141     */
142    default boolean hasPermission(final String permission) {
143        return hasPermission(activeContexts(), permission);
144    }
145
146    /**
147     * Query whether this subject has a specific permission in the provided contexts
148     * This method takes into account context and wildcard inheritance calculations for any permission.
149     *
150     * <p>Any checks made through this method will be logged by the {@link PermissionCheckNotifier}
151     * registered with the PEX engine.</p>
152     *
153     * @param contexts The contexts to query this permission in
154     * @param permission The permission to query
155     * @return Whether the subject has a true permissions value
156     */
157    boolean hasPermission(Set<ContextValue<?>> contexts, String permission);
158
159    /**
160     * Get an option that may be present for a certain subject in the subject's active contexts
161     *
162     * <p>Any checks made through this method will be logged by the {@link PermissionCheckNotifier}
163     * registered with the PEX engine.</p>
164     *
165     * @param option The option to query
166     * @return The option, if set
167     */
168    default Optional<String> option(final String option) {
169        return option(activeContexts(), option);
170    }
171
172    /**
173     * Get an option that may be present for a certain subject
174     *
175     * <p>Any checks made through this method will be logged by the {@link PermissionCheckNotifier}
176     * registered with the PEX engine.</p>
177     *
178     * @param contexts The contexts to check in
179     * @param option The option to query
180     * @return The option, if set
181     */
182    Optional<String> option(Set<ContextValue<?>> contexts, String option);
183
184    /**
185     * Get an option from this subject. The value will be returned as a {@link ConfigurationNode} to
186     * allow easily accessing its data.
187     *
188     * <p>Any checks made through this method will be logged by the {@link PermissionCheckNotifier}
189     * registered with the PEX engine.</p>
190     *
191     * @param option The option to query
192     * @return The option, if set
193     */
194    default ConfigurationNode optionNode(final String option) {
195        return optionNode(activeContexts(), option);
196    }
197
198    /**
199     * Get an option from this subject. The value will be returned as a ConfigurationNode to allow easily accessing its data.
200     *
201     * Any checks made through this method will be logged by the {@link PermissionCheckNotifier}
202     * registered with the PEX engine.
203     *
204     * @param contexts The contexts to check in
205     * @param option The option to query
206     * @return The option, if set
207     */
208    ConfigurationNode optionNode(Set<ContextValue<?>> contexts, String option);
209
210    /**
211     * Access this subject's persistent data.
212     *
213     * @return A reference to the persistent data of this subject
214     */
215    SubjectRef.ToData<?> data();
216
217    /**
218     * Access this subject's transient data.
219     *
220     * @return A reference to the transient data of this subject
221     */
222    SubjectRef.ToData<?> transientData();
223
224    /**
225     * Get a native object associated with this subject.
226     *
227     * <p>This object is provided by the {@link SubjectType} responsible for this
228     * subject's type.</p>
229     *
230     * @return a native object
231     */
232    @Nullable Object associatedObject();
233
234    /**
235     * Register a listener that will receive updates to this subject.
236     *
237     * A reference to the listener will be held, so when updates are no longer needed the listener should be unregistered
238     *
239     * @param listener The listener
240     */
241    void registerListener(Consumer<CalculatedSubject> listener);
242
243    void unregisterListener(Consumer<CalculatedSubject> listener);
244}