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.util.Change; 021import io.leangen.geantyref.TypeToken; 022import org.immutables.value.Value; 023 024import java.util.Set; 025import java.util.concurrent.CompletableFuture; 026import java.util.function.Consumer; 027import java.util.function.UnaryOperator; 028 029/** 030 * A reference to a specific subject. 031 * 032 * @param <I> identifier type 033 * @since 2.0.0 034 */ 035@Value.Immutable(builder = false) 036public interface SubjectRef<I> { 037 TypeToken<SubjectRef<?>> TYPE = new TypeToken<SubjectRef<?>>() {}; 038 039 /** 040 * Create a new subject reference. 041 * 042 * @param type the subject type's collection 043 * @param identifier the subject's identifier 044 * @param <I> the identifier type 045 * @return a new subject reference 046 * @since 2.0.0 047 */ 048 static <I> SubjectRef<I> subject(final SubjectTypeCollection<I> type, final I identifier) { 049 return new SubjectRefImpl<>(type.type(), identifier); 050 } 051 052 /** 053 * Create a new subject reference. 054 * 055 * @param type the subject's type 056 * @param identifier the subject's identifier 057 * @param <I> the identifier type 058 * @return a new subject reference 059 * @since 2.0.0 060 */ 061 static <I> SubjectRef<I> subject(final SubjectType<I> type, final I identifier) { 062 return new SubjectRefImpl<>(type, identifier); 063 } 064 065 /** 066 * Return a sanitized subject reference that can safely be used as a map key. 067 * 068 * @param existing the existing reference 069 * @param <I> the identifier type 070 * @return a sanitized reference 071 * @since 2.0.0 072 */ 073 static <I> SubjectRef<I> mapKeySafe(final SubjectRef<I> existing) { 074 return SubjectRefImpl.copyOf(existing); 075 } 076 077 /** 078 * The subject's type. 079 * 080 * @return the type referred to. 081 * @since 2.0.0 082 */ 083 @Value.Parameter 084 SubjectType<I> type(); 085 086 /** 087 * An identifier. 088 * 089 * @return the subject identifier 090 * @since 2.0.0 091 */ 092 @Value.Parameter 093 I identifier(); 094 095 /** 096 * Compute the serialized form of the identifier. 097 * 098 * @return the canonical serialized form of the subject identifier 099 */ 100 default String serializedIdentifier() { 101 return this.type().serializeIdentifier(this.identifier()); 102 } 103 104 /** 105 * A resolved reference to a subject's data in a specific collection. 106 * 107 * @param <I> identifier type 108 * @since 2.0.0 109 */ 110 interface ToData<I> extends SubjectRef<I> { 111 /** 112 * Get the current subject data. 113 * 114 * @return The current data 115 * @since 2.0.0 116 */ 117 ImmutableSubjectData get(); 118 119 /** 120 * Update the contained data based on the result of a function. 121 * 122 * @param modifierFunc The function that will be called to update the data 123 * @return A future completing when data updates have been written to the data store 124 * @since 2.0.0 125 */ 126 CompletableFuture<Change<ImmutableSubjectData>> update(UnaryOperator<ImmutableSubjectData> modifierFunc); 127 128 /** 129 * Update a single segment of the contained data based on the provided operator. 130 * 131 * @param contexts the contexts to update in 132 * @param modifierFunc the function that will be called to update the data 133 * @return A future completing when data updates have been written to the data store 134 * @since 2.0.0 135 */ 136 default CompletableFuture<Change<ImmutableSubjectData>> update(final Set<ContextValue<?>> contexts, UnaryOperator<Segment> modifierFunc) { 137 return this.update(data -> data.withSegment(contexts, modifierFunc)); 138 } 139 140 /** 141 * Get whether or not this reference will hold strong references to stored listeners. 142 * If the return value is false, registering a listener object with this reference will 143 * not prevent it from being garbage collected, so the listener must be held somewhere 144 * else for it to continue being called. 145 * 146 * @return Whether or not listeners are held strongly. 147 * @since 2.0.0 148 */ 149 boolean holdsListenersStrongly(); 150 151 /** 152 * Register a listener to be called when an update is performed. 153 * 154 * @param listener The listener to register 155 * @since 2.0.0 156 */ 157 void onUpdate(Consumer<ImmutableSubjectData> listener); 158 159 /** 160 * Confirm whether or not the subject data referenced is actually registered. 161 * 162 * @return a future completing with registration state 163 * @since 2.0.0 164 */ 165 CompletableFuture<Boolean> isRegistered(); 166 167 /** 168 * Remove the subject data referenced. 169 * 170 * @return A future completing with the previous data for this subject. 171 * @see SubjectDataCache#remove(Object) 172 * @since 2.0.0 173 */ 174 CompletableFuture<ImmutableSubjectData> remove(); 175 } 176}