Created
June 7, 2019 20:11
-
-
Save ItsDoot/dd52cee83675ccafc445cf2e0d76835a to your computer and use it in GitHub Desktop.
Asynchronous and Synchronous data access
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * This file is part of SpongeAPI, licensed under the MIT License (MIT). | |
| * | |
| * Copyright (c) SpongePowered <https://www.spongepowered.org> | |
| * 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.data; | |
| import org.checkerframework.checker.nullness.qual.NonNull; | |
| import org.spongepowered.api.data.persistence.DataSerializable; | |
| import org.spongepowered.api.data.persistence.DataView; | |
| import org.spongepowered.api.data.persistence.InvalidDataException; | |
| import org.spongepowered.api.data.property.PropertyHolder; | |
| import org.spongepowered.api.data.value.CollectionValue; | |
| import org.spongepowered.api.data.value.MapValue; | |
| import org.spongepowered.api.data.value.MergeFunction; | |
| import org.spongepowered.api.data.value.Value; | |
| import org.spongepowered.api.data.value.ValueContainer; | |
| import org.spongepowered.api.entity.EntityType; | |
| import org.spongepowered.api.item.ItemType; | |
| import java.util.Collection; | |
| import java.util.Map; | |
| import java.util.Optional; | |
| import java.util.concurrent.CompletableFuture; | |
| import java.util.function.Function; | |
| /** | |
| * A data holder object allows the access of additional data on the object | |
| * that is not simply expressed by its basic type. | |
| */ | |
| public interface DataHolder extends DataSerializable, PropertyHolder, ValueContainer { | |
| interface Mutable extends DataHolder { | |
| // ... | |
| /** | |
| * Offers the given {@code value} as defined by the provided {@link Key} | |
| * such that a {@link DataTransactionResult} is returned for any | |
| * successful, rejected, and replaced {@link Value}s from this | |
| * {@link Mutable}. | |
| * | |
| * @param key The key to the value to set | |
| * @param value The value to set | |
| * @param <E> The type of value | |
| * @return The transaction result | |
| */ | |
| <V extends Value<E>, E> DataTransactionResult offer(Key<V, DataProvider.Sync<V, E>> key, E value); | |
| /** | |
| * Offers the given {@code value} as defined by the provided {@link Key} | |
| * such that a {@link DataTransactionResult} is returned for any | |
| * successful, rejected, and replaced {@link Value}s from this | |
| * {@link Mutable}. | |
| * | |
| * @param key The key to the value to set | |
| * @param value The value to set | |
| * @param <E> The type of value | |
| * @return The transaction result | |
| */ | |
| <V extends Value<E>, E> CompletableFuture<DataTransactionResult> offerAsync(Key<V, DataProvider.Async<V, E>> key, E value); | |
| // ... | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * This file is part of SpongeAPI, licensed under the MIT License (MIT). | |
| * | |
| * Copyright (c) SpongePowered <https://www.spongepowered.org> | |
| * 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.data; | |
| import com.google.common.reflect.TypeToken; | |
| import org.spongepowered.api.Server; | |
| import org.spongepowered.api.data.value.Value; | |
| import org.spongepowered.api.event.data.ChangeDataHolderEvent; | |
| import java.util.Optional; | |
| import java.util.concurrent.CompletableFuture; | |
| public interface DataProvider<V extends Value<E>, E> { | |
| /** | |
| * Gets whether this provider will allow asynchronous access for retrieving | |
| * and storing value changes through the API and implementation. This is | |
| * usually sanity checked by the implementation through a simplified | |
| * {@link Server#onMainThread()} as a majority of datas are required to be | |
| * synchronous if the changes can end up throwing {@link ChangeDataHolderEvent}s. | |
| * | |
| * <p>A list of methods that are constrained by this check are: | |
| * <ul> | |
| * <li>- {@link #get(DataHolder)}</li> | |
| * <li>- {@link #offer(DataHolder.Mutable, Object)}</li> | |
| * <li>- {@link #remove(DataHolder.Mutable)}</li> | |
| * </ul> | |
| * Conceptually, an immutable {@link DataHolder} will be ignorant of | |
| * asynchronous access, however, some cases may exist where attempting to | |
| * create new immutable variants with different values can be still limited | |
| * by synchronous access. | |
| * </p> | |
| * | |
| * @param token The token of the {@link DataHolder} that is being requested | |
| * @return True if this provider allows asynchronous access | |
| */ | |
| boolean allowsAsynchronousAccess(TypeToken<? extends DataHolder> token); | |
| /** | |
| * Gets the {@link Key} this provider supports. | |
| * | |
| * @return The key | |
| */ | |
| Key<V, ? extends DataProvider<V, E>> getKey(); | |
| interface Sync<V extends Value<E>, E> extends DataProvider<V, E> { | |
| @Override | |
| Key<V, Sync<V, E>> getKey(); | |
| /** | |
| * Gets the elemental value from the provided {@link DataHolder}. This is | |
| * generally considered the underlying implementation access for any | |
| * {@link DataHolder#get(Key)} where the {@link Key} is registered with | |
| * this {@link DataProvider}. Nominally, this means the data is provided | |
| * outside traditional serialized data that is stored with the | |
| * {@link DataHolder}. It's possible that there may be changing return values | |
| * for even immutable types, since the provider is providing the data. | |
| * | |
| * @param container The dataholder | |
| * @return The value, if it's supported and exists | |
| */ | |
| Optional<E> get(DataHolder container); | |
| /** | |
| * Gets a constructed {@link Value} for the provided {@link DataHolder}. | |
| * Much like {@link #get(DataHolder)}, this is generally considered the | |
| * underlying implementation access for any {@link DataHolder#get(Key)} | |
| * where the {@link Key} is registered with this {@link DataProvider}. | |
| * Nominally, this means the data is provided outside traditional serialized | |
| * data that is stored with the {@link DataHolder}. It's possible that there | |
| * may be changing return values for even immutable types, since the | |
| * provider is providing the data. | |
| * | |
| * @param container The holder to get the constructed value from | |
| * @return The value | |
| */ | |
| default Optional<V> getValue(DataHolder container) { | |
| return get(container).map(element -> Value.mutableOf(getKey(), element)); | |
| } | |
| DataTransactionResult offer(DataHolder.Mutable container, E element); | |
| default DataTransactionResult offerValue(DataHolder.Mutable container, V value) { | |
| return offer(container, value.get()); | |
| } | |
| DataTransactionResult remove(DataHolder.Mutable container); | |
| <I extends DataHolder.Immutable<I>> Optional<I> with(I immutable, E element); | |
| default <I extends DataHolder.Immutable<I>> Optional<I> withValue(I immutable, V value) { | |
| return with(immutable, value.get()); | |
| } | |
| /** | |
| * Gets a {@link DataHolder.Immutable} without | |
| * a {@link Value} with the target {@link Key}, if successful. | |
| * | |
| * @param immutable The immutable value store | |
| * @param <I> The type of the immutable value store | |
| * @return The new value store, if successful | |
| */ | |
| <I extends DataHolder.Immutable<I>> Optional<I> without(I immutable); | |
| } | |
| interface Async<V extends Value<E>, E> extends DataProvider<V, E> { | |
| @Override | |
| Key<V, Async<V, E>> getKey(); | |
| /** | |
| * Gets the elemental value from the provided {@link DataHolder}. This is | |
| * generally considered the underlying implementation access for any | |
| * {@link DataHolder#get(Key)} where the {@link Key} is registered with | |
| * this {@link DataProvider}. Nominally, this means the data is provided | |
| * outside traditional serialized data that is stored with the | |
| * {@link DataHolder}. It's possible that there may be changing return values | |
| * for even immutable types, since the provider is providing the data. | |
| * | |
| * @param container The dataholder | |
| * @return The value, if it's supported and exists | |
| */ | |
| CompletableFuture<Optional<E>> get(DataHolder container); | |
| /** | |
| * Gets a constructed {@link Value} for the provided {@link DataHolder}. | |
| * Much like {@link #get(DataHolder)}, this is generally considered the | |
| * underlying implementation access for any {@link DataHolder#get(Key)} | |
| * where the {@link Key} is registered with this {@link DataProvider}. | |
| * Nominally, this means the data is provided outside traditional serialized | |
| * data that is stored with the {@link DataHolder}. It's possible that there | |
| * may be changing return values for even immutable types, since the | |
| * provider is providing the data. | |
| * | |
| * @param container The holder to get the constructed value from | |
| * @return The value | |
| */ | |
| default CompletableFuture<Optional<V>> getValue(DataHolder container) { | |
| return get(container).thenApply(value -> value.map(element -> Value.mutableOf(getKey(), element))); | |
| } | |
| CompletableFuture<DataTransactionResult> offer(DataHolder.Mutable container, E element); | |
| default CompletableFuture<DataTransactionResult> offerValue(DataHolder.Mutable container, V value) { | |
| return offer(container, value.get()); | |
| } | |
| CompletableFuture<DataTransactionResult> remove(DataHolder.Mutable container); | |
| <I extends DataHolder.Immutable<I>> CompletableFuture<Optional<I>> with(I immutable, E element); | |
| default <I extends DataHolder.Immutable<I>> CompletableFuture<Optional<I>> withValue(I immutable, V value) { | |
| return with(immutable, value.get()); | |
| } | |
| /** | |
| * Gets a {@link DataHolder.Immutable} without | |
| * a {@link Value} with the target {@link Key}, if successful. | |
| * | |
| * @param immutable The immutable value store | |
| * @param <I> The type of the immutable value store | |
| * @return The new value store, if successful | |
| */ | |
| <I extends DataHolder.Immutable<I>> CompletableFuture<Optional<I>> without(I immutable); | |
| } | |
| boolean isSupported(DataHolder container); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * This file is part of SpongeAPI, licensed under the MIT License (MIT). | |
| * | |
| * Copyright (c) SpongePowered <https://www.spongepowered.org> | |
| * 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.data; | |
| import com.google.common.reflect.TypeToken; | |
| import org.spongepowered.api.CatalogKey; | |
| import org.spongepowered.api.CatalogType; | |
| import org.spongepowered.api.Sponge; | |
| import org.spongepowered.api.data.value.BoundedValue; | |
| import org.spongepowered.api.data.value.Value; | |
| import org.spongepowered.api.data.value.ValueContainer; | |
| import org.spongepowered.api.event.EventListener; | |
| import org.spongepowered.api.event.data.ChangeDataHolderEvent; | |
| import org.spongepowered.api.util.CatalogBuilder; | |
| import org.spongepowered.api.util.TypeTokens; | |
| import org.spongepowered.api.util.annotation.CatalogedBy; | |
| import java.lang.reflect.Type; | |
| import java.util.Collection; | |
| import java.util.Comparator; | |
| import java.util.List; | |
| import java.util.Map; | |
| import java.util.function.Supplier; | |
| /** | |
| * Represents a key to an underlying {@link Value} such that the underlying | |
| * value can be retrieved from a {@link ValueContainer}. For the key to be used | |
| * through retrieval of {@link DataHolder}s, it's required to use a | |
| * {@link DataRegistration} if the data is needed to be serialized, or dynamically | |
| * provided for through external mechanisms, through {@link DataProvider}s. | |
| * | |
| * <p>If dynamic or persistent retention of the {@link Value Values} by | |
| * {@link Key keys} is not desired, a registration with {@link DataRegistration} | |
| * is optional. This would mean that any submitted {@link Value}s of a | |
| * {@link Key} without an associated {@link DataRegistration} will be only | |
| * stored on a | |
| * {@link org.spongepowered.api.data.DataHolder.Mutable mutable DataHolder} for | |
| * the duration that that holder exists. The value would not persist between | |
| * reloads, restarts, etc.</p> | |
| * | |
| * @param <V> The type of {@link Value} | |
| */ | |
| @CatalogedBy(Keys.class) | |
| public interface Key<V extends Value<?>, P extends DataProvider<V, ?>> extends CatalogType { | |
| /** | |
| * Creates a {@link Key.Builder} which allows creation of a {@link Key} | |
| * to later be registered for accessing values from | |
| * a {@link ValueContainer}. It is the default policy that a | |
| * custom created {@link Key} is <strong>NOT PERSISTENT</strong> by | |
| * Sponge. If custom keys for {@link DataHolder}s is desired to be | |
| * persisted, a {@link DataRegistration} is required. | |
| * | |
| * <p>Registration of a custom created {@link Key} is required through | |
| * {@link org.spongepowered.api.event.game.GameRegistryEvent.Register}, | |
| * though the creation is not restricted to any particular event. The | |
| * registration of a {@link DataRegistration} is done separately. | |
| * </p> | |
| * | |
| * @see DataRegistration | |
| * @return The key builder | |
| */ | |
| @SuppressWarnings("unchecked") | |
| static Builder<?, ?> builder() { | |
| return Sponge.getRegistry().createBuilder(Builder.class); | |
| } | |
| /** | |
| * Gets the class of the {@link Value} this {@link Key} is representing. | |
| * | |
| * @return The value class | |
| */ | |
| TypeToken<V> getValueToken(); | |
| /** | |
| * Gets the class of the element of the {@link Value} this {@link Key} | |
| * is representing. On occasion, if the element is a {@link Collection} type, | |
| * one can occasionally use {@link TypeToken#resolveType(Type)} with | |
| * {@link Class#getTypeParameters()} as the type parameter of a collection | |
| * is retrievable, such as the element type parameter for {@link List} or | |
| * {@link Map}. | |
| * | |
| * @return The element class | |
| */ | |
| TypeToken<?> getElementToken(); | |
| P getProvider(); | |
| /** | |
| * Register an event listener which listens to the value the key accesses | |
| * changing. | |
| * | |
| * @param holderFilter The data holder to filter with | |
| * @param listener The event listener | |
| * @param <E> The class type of the data holder | |
| */ | |
| <E extends DataHolder> void registerEvent(Class<E> holderFilter, EventListener<ChangeDataHolderEvent.ValueChange> listener); | |
| interface Builder<E, V extends Value<E>> extends CatalogBuilder<Key<V, ?>, Builder<E, V>> { | |
| /** | |
| * Starter method for the builder, to be used immediately after | |
| * {@link Key#builder()} is called. This defines the generics for the | |
| * builder itself to provide the properly generified {@link Key}. | |
| * | |
| * <p>Common {@link TypeToken TypeTokens} can be found in | |
| * {@link TypeTokens}. If a new TypeToken is to be created, it is | |
| * recommended to create an anonymous class instance of a token, | |
| * as recommended by Guava's wiki found | |
| * <a href="https://github.com/google/guava/wiki/ReflectionExplained#introduction">here</a>. | |
| * </p> | |
| * | |
| * <p>If the value type is a {@link BoundedValue} the | |
| * {@link #boundedType(TypeToken)} method should be used instead.</p> | |
| * | |
| * @param token The type token, preferably an anonymous | |
| * @param <T> The element type of the Key | |
| * @param <B> The base value type of the key | |
| * @return This builder, generified | |
| */ | |
| <T, B extends Value<T>> Builder<T, B> type(TypeToken<B> token); | |
| /** | |
| * Starter method for the bounded builder, to be used immediately after | |
| * {@link Key#builder()} is called. This defines the generics for the | |
| * builder itself to provide the properly generified {@link Key}. | |
| * | |
| * <p>Common {@link TypeToken TypeTokens} can be found in | |
| * {@link TypeTokens}. If a new TypeToken is to be created, it is | |
| * recommended to create an anonymous class instance of a token, | |
| * as recommended by Guava's wiki found | |
| * <a href="https://github.com/google/guava/wiki/ReflectionExplained#introduction">here</a>. | |
| * </p> | |
| * | |
| * @param token The type token, preferably an anonymous | |
| * @param <T> The element type of the Key | |
| * @param <B> The base value type of the key | |
| * @return This builder, generified | |
| */ | |
| <T, B extends BoundedValue<T>> BoundedBuilder<T, B> boundedType(TypeToken<B> token); | |
| @Override | |
| Builder<E, V> key(CatalogKey key); | |
| /** | |
| * Builds the {@link Key}. | |
| * | |
| * @return The built key | |
| * @throws IllegalStateException If not all required options were specified; | |
| * {@link #key(CatalogKey)} and {@link #type(TypeToken)}. | |
| */ | |
| @Override | |
| Key<V, ?> build(); | |
| interface BoundedBuilder<E, V extends BoundedValue<E>> extends Builder<E, V> { | |
| /** | |
| * Sets the default minimum element. | |
| * | |
| * <p>Setting the minimum value is required.</p> | |
| * | |
| * @param minValue The minimum value | |
| * @return This builder, for chaining | |
| */ | |
| BoundedBuilder<E, V> minValue(E minValue); | |
| /** | |
| * Sets the default minimum element supplier. | |
| * | |
| * <p>Use this method instead of {@link #minValue(Object)} if | |
| * the element type {@code E} isn't immutable.</p> | |
| * | |
| * <p>Setting the minimum value is required.</p> | |
| * | |
| * @param supplier The minimum value supplier | |
| * @return This builder, for chaining | |
| */ | |
| BoundedBuilder<E, V> minValueSupplier(Supplier<? extends E> supplier); | |
| /** | |
| * Sets the default maximum element. | |
| * | |
| * <p>Setting the maximum value is required.</p> | |
| * | |
| * @param minValue The minimum value | |
| * @return This builder, for chaining | |
| */ | |
| BoundedBuilder<E, V> maxValue(E minValue); | |
| /** | |
| * Sets the default maximum element supplier. | |
| * | |
| * <p>Use this method instead of {@link #maxValue(Object)} if | |
| * the element type {@code E} isn't immutable.</p> | |
| * | |
| * <p>Setting the maximum value is required.</p> | |
| * | |
| * @param supplier The maximum value supplier | |
| * @return This builder, for chaining | |
| */ | |
| BoundedBuilder<E, V> maxValueSupplier(Supplier<? extends E> supplier); | |
| /** | |
| * Sets the {@link Comparator} that can be used to compare | |
| * the elements. | |
| * | |
| * <p>Setting the comparator is a <strong>requirement</strong> | |
| * if the element type isn't {@link Comparable}.</p> | |
| * | |
| * @param comparator The comparator | |
| * @return This builder, for chaining | |
| */ | |
| BoundedBuilder<E, V> comparator(Comparator<? super E> comparator); | |
| @Override | |
| BoundedBuilder<E, V> key(CatalogKey key); | |
| /** | |
| * Builds the {@link Key}. | |
| * | |
| * @return The built key | |
| * @throws IllegalStateException If not all required options were specified; | |
| * {@link #key(CatalogKey)}, {@link #boundedType(TypeToken)}, | |
| * {@link #minValue(Object)}, {@link #maxValue(Object)} and | |
| * {@link #comparator(Comparator)} if needed. | |
| */ | |
| @Override | |
| Key<V, ?> build(); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment