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.datastore; 018 019import ca.stellardrift.permissionsex.context.ContextInheritance; 020import ca.stellardrift.permissionsex.subject.ImmutableSubjectData; 021import ca.stellardrift.permissionsex.rank.RankLadder; 022import ca.stellardrift.permissionsex.subject.SubjectRef; 023import ca.stellardrift.permissionsex.subject.SubjectType; 024import org.checkerframework.checker.nullness.qual.Nullable; 025import org.spongepowered.configurate.util.UnmodifiableCollections; 026 027import java.util.Map; 028import java.util.Set; 029import java.util.concurrent.CompletableFuture; 030import java.util.function.Consumer; 031import java.util.function.Function; 032import java.util.stream.Stream; 033 034 035/** 036 * Data type abstraction for permissions data. 037 * 038 * <p>This is the low-level interface used by the engine for querying data. It should perform 039 * minimal caching, but is responsible for update notifications.</p> 040 * 041 * @since 2.0.0 042 */ 043public interface DataStore { 044 045 /** 046 * Get the identifier that refers to this instance of the data store uniquely. 047 * 048 * <p>This is generally user-defined in the configuration.</p> 049 * 050 * @return The name of the current data store instance. 051 * @since 2.0.0 052 */ 053 String name(); 054 055 /** 056 * Get whether or not this is this data store's first run. 057 * 058 * <p>If this is the first run for a data store, PermissionsEx will try to populate 059 * it with default data.</p> 060 * 061 * @return if this is the first run 062 * @since 2.0.0 063 */ 064 boolean firstRun(); 065 066 /** 067 * Free any resources this data store may be using. 068 * 069 * @since 2.0.0 070 */ 071 void close(); 072 073 /** 074 * Loads the data at the specified type and identifier. 075 * 076 * <p>Implementations of this method do not need to perform any caching.</p> 077 * 078 * @param type The type of subject to get 079 * @param identifier The subject's identifier 080 * @param listener The update listener for this subject 081 * @return The relevant subject data 082 * @since 2.0.0 083 */ 084 CompletableFuture<ImmutableSubjectData> getData(String type, String identifier, @Nullable Consumer<ImmutableSubjectData> listener); 085 086 /** 087 * Loads the data at the specified type and identifier. 088 * 089 * <p>Implementations of this method do not need to perform any caching.</p> 090 * 091 * @param subject The identity of the subject data is being set for 092 * @param listener The update listener for this subject 093 * @return The relevant subject data 094 * @since 2.0.0 095 */ 096 default CompletableFuture<ImmutableSubjectData> getData(final SubjectRef<?> subject, final @Nullable Consumer<ImmutableSubjectData> listener) { 097 return getData(subject.type().name(), subject.serializedIdentifier(), listener); 098 } 099 100 /** 101 * Sets the data at the specified type and identifier. 102 * 103 * @param type The type of subject data is being fetched for 104 * @param identifier The identifier of the subject data is being fetched for 105 * @param data The data to commit to this backend. This being null deletes any data for the given identifier 106 * @return A future that can be used to listen for completion of writing the changed data 107 * @since 2.0.0 108 */ 109 CompletableFuture<ImmutableSubjectData> setData(String type, String identifier, @Nullable ImmutableSubjectData data); 110 /** 111 * Sets the data at the specified type and identifier. 112 * 113 * @param subject The identity of the subject data is being set for 114 * @param data The data to commit to this backend. This being null deletes any data for the given subject 115 * @return A future that can be used to listen for completion of writing the changed data 116 * @since 2.0.0 117 */ 118 default CompletableFuture<ImmutableSubjectData> setData(final SubjectRef<?> subject, final @Nullable ImmutableSubjectData data) { 119 return setData(subject.type().name(), subject.serializedIdentifier(), data); 120 } 121 122 /** 123 * Move data from one subject to another 124 * 125 * @param oldType The old subject's type 126 * @param oldIdentifier The old subject's identifier 127 * @param newType The new subject's type 128 * @param newIdentifier The new subject's identifier 129 * @return A future that will complete when the move is complete 130 * @since 2.0.0 131 */ 132 CompletableFuture<Void> moveData(String oldType, String oldIdentifier, String newType, String newIdentifier); 133 134 /** 135 * Move data from one subject to another 136 * 137 * @param from the old subject 138 * @param to the new subject 139 * @return A future that will complete when the move is complete 140 * @since 2.0.0 141 */ 142 default CompletableFuture<Void> moveData(final SubjectRef<?> from, final SubjectRef<?> to) { 143 return moveData(from.type().name(), from.serializedIdentifier(), to.type().name(), to.serializedIdentifier()); 144 } 145 146 /** 147 * Return if the given subject has any data stored in this store. 148 * 149 * @param type The subject's type 150 * @param identifier The subject's identifier 151 * @return whether any data is stored 152 * @since 2.0.0 153 */ 154 CompletableFuture<Boolean> isRegistered(String type, String identifier); 155 156 /** 157 * Return if the given subject has any data stored in this store. 158 * 159 * @param subject the subject to check 160 * @return whether any data is stored 161 * @since 2.0.0 162 */ 163 default CompletableFuture<Boolean> isRegistered(final SubjectRef<?> subject) { 164 return isRegistered(subject.type().name(), subject.serializedIdentifier()); 165 } 166 167 /** 168 * Get all data for subjects of the specified type. This {@link Stream} may be filled asynchronously 169 * @param type The type to get all data for 170 * @return An iterable providing data 171 * @since 2.0.0 172 */ 173 Stream<Map.Entry<String, ImmutableSubjectData>> getAll(String type); 174 175 /** 176 * Get all data for subjects of the specified type. This {@link Stream} may be filled asynchronously. 177 * 178 * @param type The type to get all data for 179 * @return An iterable providing data 180 * @since 2.0.0 181 */ 182 default <I> Stream<Map.Entry<I, ImmutableSubjectData>> getAll(final SubjectType<I> type) { 183 return this.getAll(type.name()) 184 .map(entry -> UnmodifiableCollections.immutableMapEntry(type.parseIdentifier(entry.getKey()), entry.getValue())); 185 186 } 187 188 /** 189 * Get all subject identifiers for subjects of the given type. 190 * 191 * @param type The type of subject to get identifiers for 192 * @return The registered identifiers of subjects of type {@code type} 193 * @since 2.0.0 194 */ 195 Stream<String> getAllIdentifiers(String type); 196 197 /** 198 * Return all subject types that contain data 199 * 200 * @return The registered subject types 201 * @since 2.0.0 202 */ 203 Set<String> getRegisteredTypes(); 204 205 /** 206 * Enumerate all contexts defined within this data store 207 * 208 * @return The contexts available within this data store 209 * @since 2.0.0 210 */ 211 CompletableFuture<Set<String>> getDefinedContextKeys(); 212 213 /** 214 * Returns all subjects present in this data store 215 * 216 * @return An iterable containing all subjects 217 * @since 2.0.0 218 */ 219 Stream<Map.Entry<SubjectRef<?>, ImmutableSubjectData>> getAll(); 220 221 /** 222 * Perform a bulk operation on this data store. While this operation is in progress, all writes must be suppressed 223 * (meaning changes must be cached in memory until the operation is complete). 224 * 225 * Bulk operations may be executed asynchronously. 226 * 227 * @param <T> return value type 228 * @param function The function to call containing the operation. 229 * @return a future completing with the result of the operation or an error 230 * @since 2.0.0 231 */ 232 <T> CompletableFuture<T> performBulkOperation(Function<DataStore, T> function); 233 234 /** 235 * Get all rank ladders. 236 * 237 * @return The names of all rank ladders 238 * @since 2.0.0 239 */ 240 Stream<String> getAllRankLadders(); 241 242 /** 243 * Get a specific rank ladder, with a possible update listener. 244 * 245 * @param ladder The ladder to get. Case-insensitive 246 * @param listener The listener to track possible updates 247 * @return the ladder 248 * @since 2.0.0 249 */ 250 CompletableFuture<RankLadder> getRankLadder(String ladder, @Nullable Consumer<RankLadder> listener); 251 252 /** 253 * Whether a rank ladder by the given name is present. 254 * 255 * @param ladder The ladder to check. Case-insensitive 256 * @return Whether a ladder by the provided name exists 257 * @since 2.0.0 258 */ 259 CompletableFuture<Boolean> hasRankLadder(String ladder); 260 261 /** 262 * Set the rank ladder at the given identifier. 263 * 264 * @param identifier The name of the ladder. Case-insensitive for overwriting existing ladders 265 * @param ladder The ladder to update 266 * @return a future tracking the status of this operation 267 * @since 2.0.0 268 */ 269 CompletableFuture<RankLadder> setRankLadder(String identifier, @Nullable RankLadder ladder); 270 271 /** 272 * Get context inheritance information. 273 * 274 * @param inheritance The listener to notify about changes 275 * @return A future that will supply context inheritance 276 * @since 2.0.0 277 */ 278 CompletableFuture<ContextInheritance> getContextInheritance(@Nullable Consumer<ContextInheritance> inheritance); 279 280 /** 281 * Uppdate the stored context inheritance information. 282 * 283 * @param inheritance inheritance to apply 284 * @return a future completing with the previous inheritance data 285 * @since 2.0.0 286 */ 287 CompletableFuture<ContextInheritance> setContextInheritance(ContextInheritance inheritance); 288} 289