mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-28 03:48:01 +01:00
#933: Define native persistent data types for lists
By: Bjarne Koll <lynxplay101@gmail.com>
This commit is contained in:
parent
b48b712546
commit
cfcc75669d
@ -0,0 +1,22 @@
|
||||
package org.bukkit.persistence;
|
||||
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* The list persistent data represents a data type that is capable of storing a
|
||||
* list of other data types in a {@link PersistentDataContainer}.
|
||||
*
|
||||
* @param <P> the primitive type of the list element.
|
||||
* @param <C> the complex type of the list elements.
|
||||
*/
|
||||
public interface ListPersistentDataType<P, C> extends PersistentDataType<List<P>, List<C>> {
|
||||
|
||||
/**
|
||||
* Provides the persistent data type of the elements found in the list.
|
||||
*
|
||||
* @return the persistent data type.
|
||||
*/
|
||||
@NotNull
|
||||
PersistentDataType<P, C> elementType();
|
||||
}
|
@ -0,0 +1,229 @@
|
||||
package org.bukkit.persistence;
|
||||
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.Lists;
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A provider for list persistent data types that represent the known primitive
|
||||
* types exposed by {@link PersistentDataType}.
|
||||
*/
|
||||
public final class ListPersistentDataTypeProvider {
|
||||
|
||||
private static final ListPersistentDataType<Byte, Byte> BYTE = new ListPersistentDataTypeImpl<>(PersistentDataType.BYTE);
|
||||
private static final ListPersistentDataType<Short, Short> SHORT = new ListPersistentDataTypeImpl<>(PersistentDataType.SHORT);
|
||||
private static final ListPersistentDataType<Integer, Integer> INTEGER = new ListPersistentDataTypeImpl<>(PersistentDataType.INTEGER);
|
||||
private static final ListPersistentDataType<Long, Long> LONG = new ListPersistentDataTypeImpl<>(PersistentDataType.LONG);
|
||||
private static final ListPersistentDataType<Float, Float> FLOAT = new ListPersistentDataTypeImpl<>(PersistentDataType.FLOAT);
|
||||
private static final ListPersistentDataType<Double, Double> DOUBLE = new ListPersistentDataTypeImpl<>(PersistentDataType.DOUBLE);
|
||||
private static final ListPersistentDataType<Byte, Boolean> BOOLEAN = new ListPersistentDataTypeImpl<>(PersistentDataType.BOOLEAN);
|
||||
private static final ListPersistentDataType<String, String> STRING = new ListPersistentDataTypeImpl<>(PersistentDataType.STRING);
|
||||
private static final ListPersistentDataType<byte[], byte[]> BYTE_ARRAY = new ListPersistentDataTypeImpl<>(PersistentDataType.BYTE_ARRAY);
|
||||
private static final ListPersistentDataType<int[], int[]> INTEGER_ARRAY = new ListPersistentDataTypeImpl<>(PersistentDataType.INTEGER_ARRAY);
|
||||
private static final ListPersistentDataType<long[], long[]> LONG_ARRAY = new ListPersistentDataTypeImpl<>(PersistentDataType.LONG_ARRAY);
|
||||
private static final ListPersistentDataType<PersistentDataContainer, PersistentDataContainer> DATA_CONTAINER = new ListPersistentDataTypeImpl<>(
|
||||
PersistentDataType.TAG_CONTAINER
|
||||
);
|
||||
|
||||
ListPersistentDataTypeProvider() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a shared {@link ListPersistentDataType} that is capable of
|
||||
* storing lists of bytes.
|
||||
*
|
||||
* @return the persistent data type.
|
||||
*/
|
||||
@NotNull
|
||||
public ListPersistentDataType<Byte, Byte> bytes() {
|
||||
return BYTE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a shared {@link ListPersistentDataType} that is capable of
|
||||
* storing lists of shorts.
|
||||
*
|
||||
* @return the persistent data type.
|
||||
*/
|
||||
@NotNull
|
||||
public ListPersistentDataType<Short, Short> shorts() {
|
||||
return SHORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a shared {@link ListPersistentDataType} that is capable of
|
||||
* storing lists of integers.
|
||||
*
|
||||
* @return the persistent data type.
|
||||
*/
|
||||
@NotNull
|
||||
public ListPersistentDataType<Integer, Integer> integers() {
|
||||
return INTEGER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a shared {@link ListPersistentDataType} that is capable of
|
||||
* storing lists of longs.
|
||||
*
|
||||
* @return the persistent data type.
|
||||
*/
|
||||
@NotNull
|
||||
public ListPersistentDataType<Long, Long> longs() {
|
||||
return LONG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a shared {@link ListPersistentDataType} that is capable of
|
||||
* storing lists of floats.
|
||||
*
|
||||
* @return the persistent data type.
|
||||
*/
|
||||
@NotNull
|
||||
public ListPersistentDataType<Float, Float> floats() {
|
||||
return FLOAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a shared {@link ListPersistentDataType} that is capable of
|
||||
* storing lists of doubles.
|
||||
*
|
||||
* @return the persistent data type.
|
||||
*/
|
||||
@NotNull
|
||||
public ListPersistentDataType<Double, Double> doubles() {
|
||||
return DOUBLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a shared {@link ListPersistentDataType} that is capable of
|
||||
* storing lists of booleans.
|
||||
*
|
||||
* @return the persistent data type.
|
||||
*/
|
||||
@NotNull
|
||||
public ListPersistentDataType<Byte, Boolean> booleans() {
|
||||
return BOOLEAN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a shared {@link ListPersistentDataType} that is capable of
|
||||
* storing lists of strings.
|
||||
*
|
||||
* @return the persistent data type.
|
||||
*/
|
||||
@NotNull
|
||||
public ListPersistentDataType<String, String> strings() {
|
||||
return STRING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a shared {@link ListPersistentDataType} that is capable of
|
||||
* storing lists of byte arrays.
|
||||
*
|
||||
* @return the persistent data type.
|
||||
*/
|
||||
@NotNull
|
||||
public ListPersistentDataType<byte[], byte[]> byteArrays() {
|
||||
return BYTE_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a shared {@link ListPersistentDataType} that is capable of
|
||||
* storing lists of int arrays.
|
||||
*
|
||||
* @return the persistent data type.
|
||||
*/
|
||||
@NotNull
|
||||
public ListPersistentDataType<int[], int[]> integerArrays() {
|
||||
return INTEGER_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a shared {@link ListPersistentDataType} that is capable of
|
||||
* storing lists of long arrays.
|
||||
*
|
||||
* @return the persistent data type.
|
||||
*/
|
||||
@NotNull
|
||||
public ListPersistentDataType<long[], long[]> longArrays() {
|
||||
return LONG_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a shared {@link ListPersistentDataType} that is capable of
|
||||
* persistent data containers..
|
||||
*
|
||||
* @return the persistent data type.
|
||||
*/
|
||||
@NotNull
|
||||
public ListPersistentDataType<PersistentDataContainer, PersistentDataContainer> dataContainers() {
|
||||
return DATA_CONTAINER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new list persistent data type given any persistent data type
|
||||
* for its elements.
|
||||
*
|
||||
* @param elementType the persistent data type that is capable of
|
||||
* writing/reading the elements of the list.
|
||||
* @param <P> the generic type of the primitives stored in the list.
|
||||
* @param <C> the generic type of the complex values yielded back by the
|
||||
* persistent data types.
|
||||
* @return the created list persistent data type.
|
||||
*/
|
||||
@NotNull
|
||||
public <P, C> ListPersistentDataType<P, C> listTypeFrom(@NotNull final PersistentDataType<P, C> elementType) {
|
||||
return new ListPersistentDataTypeImpl<>(elementType);
|
||||
}
|
||||
|
||||
/**
|
||||
* A private implementation of the {@link ListPersistentDataType} that uses
|
||||
* {@link Collections2} for conversion from/to the primitive list.
|
||||
*
|
||||
* @param <P> the generic type of the primitives stored in the list.
|
||||
* @param <C> the generic type of the complex values yielded back by the
|
||||
* persistent data types.
|
||||
*/
|
||||
private static final class ListPersistentDataTypeImpl<P, C> implements ListPersistentDataType<P, C> {
|
||||
|
||||
@NotNull
|
||||
private final PersistentDataType<P, C> innerType;
|
||||
|
||||
private ListPersistentDataTypeImpl(@NotNull final PersistentDataType<P, C> innerType) {
|
||||
this.innerType = innerType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<List<P>> getPrimitiveType() {
|
||||
return (Class<List<P>>) (Object) List.class;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<List<C>> getComplexType() {
|
||||
return (Class<List<C>>) (Object) List.class;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<P> toPrimitive(@NotNull final List<C> complex, @NotNull final PersistentDataAdapterContext context) {
|
||||
return Lists.transform(complex, s -> innerType.toPrimitive(s, context));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<C> fromPrimitive(@NotNull final List<P> primitive, @NotNull final PersistentDataAdapterContext context) {
|
||||
return Lists.transform(primitive, s -> innerType.fromPrimitive(s, context));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PersistentDataType<P, C> elementType() {
|
||||
return this.innerType;
|
||||
}
|
||||
}
|
||||
}
|
@ -22,8 +22,8 @@ public interface PersistentDataContainer {
|
||||
* @param key the key this value will be stored under
|
||||
* @param type the type this tag uses
|
||||
* @param value the value to store in the tag
|
||||
* @param <T> the generic java type of the tag value
|
||||
* @param <Z> the generic type of the object to store
|
||||
* @param <P> the generic java type of the tag value
|
||||
* @param <C> the generic type of the object to store
|
||||
*
|
||||
* @throws IllegalArgumentException if the key is null
|
||||
* @throws IllegalArgumentException if the type is null
|
||||
@ -32,7 +32,7 @@ public interface PersistentDataContainer {
|
||||
* @throws IllegalArgumentException if no suitable adapter was found for
|
||||
* the {@link PersistentDataType#getPrimitiveType()}
|
||||
*/
|
||||
<T, Z> void set(@NotNull NamespacedKey key, @NotNull PersistentDataType<T, Z> type, @NotNull Z value);
|
||||
<P, C> void set(@NotNull NamespacedKey key, @NotNull PersistentDataType<P, C> type, @NotNull C value);
|
||||
|
||||
/**
|
||||
* Returns if the persistent metadata provider has metadata registered
|
||||
@ -54,8 +54,8 @@ public interface PersistentDataContainer {
|
||||
*
|
||||
* @param key the key the value is stored under
|
||||
* @param type the type the primative stored value has to match
|
||||
* @param <T> the generic type of the stored primitive
|
||||
* @param <Z> the generic type of the eventually created complex object
|
||||
* @param <P> the generic type of the stored primitive
|
||||
* @param <C> the generic type of the eventually created complex object
|
||||
*
|
||||
* @return if a value with the provided key and type exists
|
||||
*
|
||||
@ -63,7 +63,7 @@ public interface PersistentDataContainer {
|
||||
* @throws IllegalArgumentException if the type to cast the found object to is
|
||||
* null
|
||||
*/
|
||||
<T, Z> boolean has(@NotNull NamespacedKey key, @NotNull PersistentDataType<T, Z> type);
|
||||
<P, C> boolean has(@NotNull NamespacedKey key, @NotNull PersistentDataType<P, C> type);
|
||||
|
||||
/**
|
||||
* Returns if the persistent metadata provider has metadata registered matching
|
||||
@ -90,8 +90,8 @@ public interface PersistentDataContainer {
|
||||
*
|
||||
* @param key the key to look up in the custom tag map
|
||||
* @param type the type the value must have and will be casted to
|
||||
* @param <T> the generic type of the stored primitive
|
||||
* @param <Z> the generic type of the eventually created complex object
|
||||
* @param <P> the generic type of the stored primitive
|
||||
* @param <C> the generic type of the eventually created complex object
|
||||
*
|
||||
* @return the value or {@code null} if no value was mapped under the given
|
||||
* value
|
||||
@ -106,7 +106,7 @@ public interface PersistentDataContainer {
|
||||
* PersistentDataType#getPrimitiveType()}
|
||||
*/
|
||||
@Nullable
|
||||
<T, Z> Z get(@NotNull NamespacedKey key, @NotNull PersistentDataType<T, Z> type);
|
||||
<P, C> C get(@NotNull NamespacedKey key, @NotNull PersistentDataType<P, C> type);
|
||||
|
||||
/**
|
||||
* Returns the metadata value that is stored on the
|
||||
@ -117,8 +117,8 @@ public interface PersistentDataContainer {
|
||||
* @param type the type the value must have and will be casted to
|
||||
* @param defaultValue the default value to return if no value was found for
|
||||
* the provided key
|
||||
* @param <T> the generic type of the stored primitive
|
||||
* @param <Z> the generic type of the eventually created complex object
|
||||
* @param <P> the generic type of the stored primitive
|
||||
* @param <C> the generic type of the eventually created complex object
|
||||
*
|
||||
* @return the value or the default value if no value was mapped under the
|
||||
* given key
|
||||
@ -132,7 +132,7 @@ public interface PersistentDataContainer {
|
||||
* the {@link PersistentDataType#getPrimitiveType()}
|
||||
*/
|
||||
@NotNull
|
||||
<T, Z> Z getOrDefault(@NotNull NamespacedKey key, @NotNull PersistentDataType<T, Z> type, @NotNull Z defaultValue);
|
||||
<P, C> C getOrDefault(@NotNull NamespacedKey key, @NotNull PersistentDataType<P, C> type, @NotNull C defaultValue);
|
||||
|
||||
/**
|
||||
* Get the set of keys present on this {@link PersistentDataContainer}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.bukkit.persistence;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@ -13,17 +14,17 @@ import org.jetbrains.annotations.NotNull;
|
||||
* {@code
|
||||
* public class UUIDTagType implements PersistentDataType<byte[], UUID> {
|
||||
*
|
||||
* {@literal @Override}
|
||||
* @Override
|
||||
* public Class<byte[]> getPrimitiveType() {
|
||||
* return byte[].class;
|
||||
* }
|
||||
*
|
||||
* {@literal @Override}
|
||||
* @Override
|
||||
* public Class<UUID> getComplexType() {
|
||||
* return UUID.class;
|
||||
* }
|
||||
*
|
||||
* {@literal @Override}
|
||||
* @Override
|
||||
* public byte[] toPrimitive(UUID complex, PersistentDataAdapterContext context) {
|
||||
* ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
|
||||
* bb.putLong(complex.getMostSignificantBits());
|
||||
@ -31,19 +32,24 @@ import org.jetbrains.annotations.NotNull;
|
||||
* return bb.array();
|
||||
* }
|
||||
*
|
||||
* {@literal @Override}
|
||||
* @Override
|
||||
* public UUID fromPrimitive(byte[] primitive, PersistentDataAdapterContext context) {
|
||||
* ByteBuffer bb = ByteBuffer.wrap(primitive);
|
||||
* long firstLong = bb.getLong();
|
||||
* long secondLong = bb.getLong();
|
||||
* return new UUID(firstLong, secondLong);
|
||||
* }
|
||||
* }}</pre>
|
||||
* }
|
||||
*}</pre>
|
||||
*
|
||||
* @param <T> the primary object type that is stored in the given tag
|
||||
* @param <Z> the retrieved object type when applying this tag type
|
||||
* Any plugin owned implementation of this interface is required to define one
|
||||
* of the existing primitive types found in this interface. Notably
|
||||
* {@link #BOOLEAN} is not a primitive type but a convenience type.
|
||||
*
|
||||
* @param <P> the primary object type that is stored in the given tag
|
||||
* @param <C> the retrieved object type when applying this tag type
|
||||
*/
|
||||
public interface PersistentDataType<T, Z> {
|
||||
public interface PersistentDataType<P, C> {
|
||||
|
||||
/*
|
||||
The primitive one value types.
|
||||
@ -80,6 +86,10 @@ public interface PersistentDataType<T, Z> {
|
||||
/*
|
||||
Complex Arrays.
|
||||
*/
|
||||
/**
|
||||
* @deprecated Use {@link #LIST}'s {@link ListPersistentDataTypeProvider#dataContainers()} instead.
|
||||
*/
|
||||
@ApiStatus.Obsolete
|
||||
PersistentDataType<PersistentDataContainer[], PersistentDataContainer[]> TAG_CONTAINER_ARRAY = new PrimitivePersistentDataType<>(PersistentDataContainer[].class);
|
||||
|
||||
/*
|
||||
@ -87,13 +97,29 @@ public interface PersistentDataType<T, Z> {
|
||||
*/
|
||||
PersistentDataType<PersistentDataContainer, PersistentDataContainer> TAG_CONTAINER = new PrimitivePersistentDataType<>(PersistentDataContainer.class);
|
||||
|
||||
/**
|
||||
* A data type provider type that itself cannot be used as a
|
||||
* {@link PersistentDataType}.
|
||||
*
|
||||
* {@link ListPersistentDataTypeProvider} exposes shared persistent data
|
||||
* types for storing lists of other data types, however.
|
||||
* <p>
|
||||
* Its existence in the {@link PersistentDataType} interface does not permit
|
||||
* {@link java.util.List} as a primitive type in combination with a plain
|
||||
* {@link PersistentDataType}. {@link java.util.List}s are only valid
|
||||
* primitive types when used via a {@link ListPersistentDataType}.
|
||||
*
|
||||
* @see ListPersistentDataTypeProvider
|
||||
*/
|
||||
ListPersistentDataTypeProvider LIST = new ListPersistentDataTypeProvider();
|
||||
|
||||
/**
|
||||
* Returns the primitive data type of this tag.
|
||||
*
|
||||
* @return the class
|
||||
*/
|
||||
@NotNull
|
||||
Class<T> getPrimitiveType();
|
||||
Class<P> getPrimitiveType();
|
||||
|
||||
/**
|
||||
* Returns the complex object type the primitive value resembles.
|
||||
@ -101,7 +127,7 @@ public interface PersistentDataType<T, Z> {
|
||||
* @return the class type
|
||||
*/
|
||||
@NotNull
|
||||
Class<Z> getComplexType();
|
||||
Class<C> getComplexType();
|
||||
|
||||
/**
|
||||
* Returns the primitive data that resembles the complex object passed to
|
||||
@ -112,7 +138,7 @@ public interface PersistentDataType<T, Z> {
|
||||
* @return the primitive value
|
||||
*/
|
||||
@NotNull
|
||||
T toPrimitive(@NotNull Z complex, @NotNull PersistentDataAdapterContext context);
|
||||
P toPrimitive(@NotNull C complex, @NotNull PersistentDataAdapterContext context);
|
||||
|
||||
/**
|
||||
* Creates a complex object based of the passed primitive value
|
||||
@ -122,7 +148,7 @@ public interface PersistentDataType<T, Z> {
|
||||
* @return the complex object instance
|
||||
*/
|
||||
@NotNull
|
||||
Z fromPrimitive(@NotNull T primitive, @NotNull PersistentDataAdapterContext context);
|
||||
C fromPrimitive(@NotNull P primitive, @NotNull PersistentDataAdapterContext context);
|
||||
|
||||
/**
|
||||
* A default implementation that simply exists to pass on the retrieved or
|
||||
@ -131,37 +157,37 @@ public interface PersistentDataType<T, Z> {
|
||||
* This implementation does not add any kind of logic, but is used to
|
||||
* provide default implementations for the primitive types.
|
||||
*
|
||||
* @param <T> the generic type of the primitive objects
|
||||
* @param <P> the generic type of the primitive objects
|
||||
*/
|
||||
class PrimitivePersistentDataType<T> implements PersistentDataType<T, T> {
|
||||
class PrimitivePersistentDataType<P> implements PersistentDataType<P, P> {
|
||||
|
||||
private final Class<T> primitiveType;
|
||||
private final Class<P> primitiveType;
|
||||
|
||||
PrimitivePersistentDataType(@NotNull Class<T> primitiveType) {
|
||||
PrimitivePersistentDataType(@NotNull Class<P> primitiveType) {
|
||||
this.primitiveType = primitiveType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Class<T> getPrimitiveType() {
|
||||
public Class<P> getPrimitiveType() {
|
||||
return primitiveType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Class<T> getComplexType() {
|
||||
public Class<P> getComplexType() {
|
||||
return primitiveType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public T toPrimitive(@NotNull T complex, @NotNull PersistentDataAdapterContext context) {
|
||||
public P toPrimitive(@NotNull P complex, @NotNull PersistentDataAdapterContext context) {
|
||||
return complex;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public T fromPrimitive(@NotNull T primitive, @NotNull PersistentDataAdapterContext context) {
|
||||
public P fromPrimitive(@NotNull P primitive, @NotNull PersistentDataAdapterContext context) {
|
||||
return primitive;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user