From fd090a371e71a7d2dd3384b75a027c2aa0dcca00 Mon Sep 17 00:00:00 2001 From: aromaa Date: Sun, 20 Sep 2026 17:55:55 +0300 Subject: [PATCH 1/4] Introduce CompositeValue --- .../api/block/BlockSnapshot.java | 4 +- .../block/entity/BlockEntityArchetype.java | 4 +- .../api/data/CopyableDataHolder.java | 4 +- .../spongepowered/api/data/DataHolder.java | 56 ++-- .../api/data/DataHolderBuilder.java | 28 +- .../api/data/DataManipulator.java | 86 +++--- .../spongepowered/api/data/DataProvider.java | 37 +-- .../api/data/DataRegistration.java | 26 +- .../api/data/DataTransactionResult.java | 258 +++++++++--------- .../api/data/DirectionRelativeDataHolder.java | 26 +- .../data/DirectionRelativeDataProvider.java | 10 +- .../data/ImmutableDataProviderBuilder.java | 10 +- .../java/org/spongepowered/api/data/Key.java | 38 ++- .../java/org/spongepowered/api/data/Keys.java | 5 + .../api/data/MutableDataProviderBuilder.java | 3 +- .../api/data/persistence/DataStore.java | 20 +- .../api/data/persistence/DataView.java | 6 +- .../api/data/value/CompositeValue.java | 217 +++++++++++++++ .../data/value/CopyableValueContainer.java | 2 +- .../api/data/value/ElementMergeFunction.java | 50 ++++ .../api/data/value/MergeFunction.java | 26 +- .../spongepowered/api/data/value/Value.java | 101 +++---- .../api/data/value/ValueContainer.java | 72 ++--- .../api/data/value/ValueLike.java | 116 ++++++++ .../org/spongepowered/api/entity/Entity.java | 1 + .../api/entity/living/golem/CopperGolem.java | 5 +- .../api/entity/living/player/User.java | 1 + .../api/item/inventory/Inventory.java | 6 +- .../inventory/ItemStackBuilderPopulators.java | 21 +- .../api/item/inventory/ItemStackLike.java | 4 +- .../volume/game/LocationBaseDataHolder.java | 131 ++++----- 31 files changed, 893 insertions(+), 481 deletions(-) create mode 100644 src/main/java/org/spongepowered/api/data/value/CompositeValue.java create mode 100644 src/main/java/org/spongepowered/api/data/value/ElementMergeFunction.java create mode 100644 src/main/java/org/spongepowered/api/data/value/ValueLike.java diff --git a/src/main/java/org/spongepowered/api/block/BlockSnapshot.java b/src/main/java/org/spongepowered/api/block/BlockSnapshot.java index 58cb6143191..36928ad66d9 100644 --- a/src/main/java/org/spongepowered/api/block/BlockSnapshot.java +++ b/src/main/java/org/spongepowered/api/block/BlockSnapshot.java @@ -30,7 +30,7 @@ import org.spongepowered.api.data.SerializableDataHolderBuilder; import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.world.BlockChangeFlag; import org.spongepowered.api.world.LocatableSnapshot; import org.spongepowered.api.world.schematic.Schematic; @@ -157,7 +157,7 @@ interface Builder extends SerializableDataHolderBuilder.ImmutableThis method should be called before calling {@link #add(Value)} or + *

This method should be called before calling {@link #add(ValueLike)} or * any variant thereof.

* * @param blockState The BlockState diff --git a/src/main/java/org/spongepowered/api/block/entity/BlockEntityArchetype.java b/src/main/java/org/spongepowered/api/block/entity/BlockEntityArchetype.java index 31af5ca5ade..4b7f1e8db82 100644 --- a/src/main/java/org/spongepowered/api/block/entity/BlockEntityArchetype.java +++ b/src/main/java/org/spongepowered/api/block/entity/BlockEntityArchetype.java @@ -33,7 +33,7 @@ import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.data.persistence.DataView; import org.spongepowered.api.data.persistence.InvalidDataException; -import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.world.Archetype; import org.spongepowered.api.world.server.ServerLocation; @@ -149,7 +149,7 @@ default Builder blockEntity(Supplier type) { *
  • {@link #state(BlockState)}
  • *
  • {@link #blockEntity(BlockEntityType)}
  • *
  • {@link #blockEntityData(DataView)}
  • - *
  • {@link #add(Value)}
  • + *
  • {@link #add(ValueLike)}
  • *
  • {@link #add(Key, Object)}
  • *
  • {@link #add(DataManipulator)}
  • * diff --git a/src/main/java/org/spongepowered/api/data/CopyableDataHolder.java b/src/main/java/org/spongepowered/api/data/CopyableDataHolder.java index b7e93f10245..d9edd8d8d0c 100644 --- a/src/main/java/org/spongepowered/api/data/CopyableDataHolder.java +++ b/src/main/java/org/spongepowered/api/data/CopyableDataHolder.java @@ -24,7 +24,7 @@ */ package org.spongepowered.api.data; -import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.data.value.ValueLike; /** * Represents a {@link DataHolder} that can be copied. @@ -33,7 +33,7 @@ public interface CopyableDataHolder extends DataHolder { /** * Creates a clone copy of this {@link CopyableDataHolder} as a new - * {@link CopyableDataHolder} such that all the {@link Value}s are + * {@link CopyableDataHolder} such that all the {@link ValueLike}s are * safely duplicated to the new instance. It is not guaranteed that * the returning container is of the same type as this container. * diff --git a/src/main/java/org/spongepowered/api/data/DataHolder.java b/src/main/java/org/spongepowered/api/data/DataHolder.java index 948bddede6e..78017085f3e 100644 --- a/src/main/java/org/spongepowered/api/data/DataHolder.java +++ b/src/main/java/org/spongepowered/api/data/DataHolder.java @@ -25,10 +25,12 @@ package org.spongepowered.api.data; import org.spongepowered.api.data.value.CollectionValue; +import org.spongepowered.api.data.value.CompositeValue; 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.data.value.ValueLike; import org.spongepowered.api.util.annotation.DoNotStore; import java.util.Collection; @@ -102,7 +104,13 @@ default DataTransactionResult transform(Supplier The type of value * @return The transaction result */ - DataTransactionResult offer(Key> key, E value); + default DataTransactionResult offer(Key> key, E value) { + return this.offer(Value.immutableOf(key, value)); + } + + default DataTransactionResult offer(Key> key, K valueKey, E value) { + return this.offer(CompositeValue.immutableChildOf(key, valueKey, value)); + } /** * Offers the given {@code value} as defined by the provided {@link Key} @@ -135,15 +143,15 @@ default DataTransactionResult offer(Supplier value); + DataTransactionResult offer(ValueLike value); DataTransactionResult offerSingle(Key> key, E element); @@ -238,7 +246,7 @@ default DataTransactionResult tryOffer(Supplier DataTransactionResult tryOffer(Supplier DataTransactionResult tryOffer(Value value) throws IllegalArgumentException { - final DataTransactionResult result = this.offer(value.key(), value.get()); + default DataTransactionResult tryOffer(ValueLike value) throws IllegalArgumentException { + final DataTransactionResult result = this.offer(value); if (!result.isSuccessful()) { throw new IllegalArgumentException("Failed offer transaction!"); } @@ -257,7 +265,7 @@ default DataTransactionResult tryOffer(Value value) throws IllegalArgumen } /** - * Attempts to remove the provided {@link Value}. All values that were + * Attempts to remove the provided {@link ValueLike}. All values that were * successfully removed will be provided in * {@link DataTransactionResult#replacedData()}. If the data can not be * removed, the result will be an expected @@ -266,7 +274,7 @@ default DataTransactionResult tryOffer(Value value) throws IllegalArgumen * @param value The value to remove * @return The transaction result */ - default DataTransactionResult remove(Value value) { + default DataTransactionResult remove(ValueLike value) { return this.remove(value.key()); } @@ -282,6 +290,8 @@ default DataTransactionResult remove(Value value) { */ DataTransactionResult remove(Key key); + DataTransactionResult remove(Key> key, K valueKey); + /** * Attempts to remove the data associated with the provided {@link Key}. * All values that were successfully removed will be provided in @@ -309,9 +319,9 @@ default DataTransactionResult remove(Supplier> key) { DataTransactionResult undo(DataTransactionResult result); /** - * Performs an absolute copy of all {@link org.spongepowered.api.data.value.Value.Mutable}s and + * Performs an absolute copy of all {@link org.spongepowered.api.data.value.ValueLike.Mutable}s and * {@link ValueContainer}s to this {@link Mutable} such that - * any overlapping {@link org.spongepowered.api.data.value.Value.Mutable}s are offered for replacement. The + * any overlapping {@link org.spongepowered.api.data.value.ValueLike.Mutable}s are offered for replacement. The * result is provided as a {@link DataTransactionResult}. * * @param that The other {@link Mutable} to copy values from @@ -322,9 +332,9 @@ default DataTransactionResult copyFrom(ValueContainer that) { } /** - * Performs an absolute copy of all {@link org.spongepowered.api.data.value.Value.Mutable}s and + * Performs an absolute copy of all {@link org.spongepowered.api.data.value.ValueLike.Mutable}s and * {@link ValueContainer}s to this {@link Mutable} such that - * any overlapping {@link org.spongepowered.api.data.value.Value.Mutable}s are offered for replacement. The + * any overlapping {@link org.spongepowered.api.data.value.ValueLike.Mutable}s are offered for replacement. The * result is provided as a {@link DataTransactionResult}. * * @param that The other {@link Mutable} to copy values from @@ -376,7 +386,13 @@ default Optional transform(Supplier>> ke * @param The type of value * @return The new immutable value store */ - Optional with(Key> key, E value); + default Optional with(Key> key, E value) { + return this.with(Value.immutableOf(key, value)); + } + + default Optional with(Key> key, K valueKey, E value) { + return this.with(CompositeValue.immutableChildOf(key, valueKey, value)); + } /** * Creates a new {@link Immutable} with the provided @@ -400,17 +416,17 @@ default Optional with(Supplier>> key, E * @param value The value to set * @return The new immutable value store */ - Optional with(Value value); + Optional with(ValueLike value); /** * Creates a new {@link Immutable} without the key of the provided - * {@link Value}. If the key is supported by this value store, + * {@link ValueLike}. If the key is supported by this value store, * the returned value store will be present. * * @param value The value * @return The new immutable value store */ - default Optional without(Value value) { + default Optional without(ValueLike value) { return this.without(value.key()); } @@ -424,6 +440,8 @@ default Optional without(Value value) { */ Optional without(Key key); + Optional without(Key> key, K valueKey); + /** * Creates a new {@link Immutable} without the provided {@link Key}. If the * key is supported by this value store, the returned value store will @@ -437,7 +455,7 @@ default Optional without(Supplier> key) { } /** - * Attempts to merge the {@link org.spongepowered.api.data.value.Value.Immutable}s from this + * Attempts to merge the {@link org.spongepowered.api.data.value.ValueLike.Immutable}s from this * {@link Immutable} and the given {@link Immutable} to * produce a new instance of the merged result. * @@ -449,7 +467,7 @@ default I mergeWith(I that) { } /** - * Attempts to merge the {@link org.spongepowered.api.data.value.Value.Immutable}s from this + * Attempts to merge the {@link org.spongepowered.api.data.value.ValueLike.Immutable}s from this * {@link Immutable} and the given {@link Immutable} to * produce a new instance of the merged result. Any overlapping * {@link ValueContainer}s are merged through the {@link MergeFunction}. diff --git a/src/main/java/org/spongepowered/api/data/DataHolderBuilder.java b/src/main/java/org/spongepowered/api/data/DataHolderBuilder.java index 8f0213adcf0..73ac8786ab7 100644 --- a/src/main/java/org/spongepowered/api/data/DataHolderBuilder.java +++ b/src/main/java/org/spongepowered/api/data/DataHolderBuilder.java @@ -25,6 +25,7 @@ package org.spongepowered.api.data; import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.util.Builder; import org.spongepowered.api.util.CopyableBuilder; @@ -33,35 +34,32 @@ public interface DataHolderBuilder> extends Builder, CopyableBuilder { /** - * Adds the given {@link Value} to the builder. The - * {@link Value} is copied when the {@link DataHolder} + * Adds the given {@link ValueLike} to the builder. The + * {@link ValueLike} is copied when the {@link DataHolder} * is created. * * @param value The value to add * @return This builder, for chaining */ - @SuppressWarnings({"unchecked", "rawtypes"}) - default B add(Value value) { - return (B) this.add((Key) value.key(), value.get()); - } + B add(ValueLike value); /** - * Adds all the {@link Value}s to the builder. The - * {@link Value}s are copied when the {@link DataHolder} + * Adds all the {@link ValueLike}s to the builder. The + * {@link ValueLike}s are copied when the {@link DataHolder} * is created. * * @param values The values to add * @return This builder, for chaining */ @SuppressWarnings("unchecked") - default B add(Iterable> values) { + default B add(Iterable> values) { values.forEach(this::add); return (B) this; } /** - * Adds all the {@link Value}s from the {@link DataManipulator} - * to the builder. The {@link Value}s are copied when the + * Adds all the {@link ValueLike}s from the {@link DataManipulator} + * to the builder. The {@link ValueLike}s are copied when the * {@link DataHolder} is created. * * @param manipulator The manipulator to add @@ -72,8 +70,8 @@ default B add(DataManipulator manipulator) { } /** - * Adds all the {@link Value}s from the {@link DataHolder} - * to the builder. The {@link Value}s are copied when the + * Adds all the {@link ValueLike}s from the {@link DataHolder} + * to the builder. The {@link ValueLike}s are copied when the * {@link DataHolder} is created. * * @param dataHolder The data holder to add data from @@ -91,7 +89,9 @@ default B addFrom(DataHolder dataHolder) { * @param The type of the value * @return This builder, for chaining */ - B add(Key> key, V value); + default B add(Key> key, V value) { + return this.add(Value.immutableOf(key, value)); + } /** * Adds the given {@link Key} with the given value. diff --git a/src/main/java/org/spongepowered/api/data/DataManipulator.java b/src/main/java/org/spongepowered/api/data/DataManipulator.java index e70aba2b527..c06c6b5f958 100644 --- a/src/main/java/org/spongepowered/api/data/DataManipulator.java +++ b/src/main/java/org/spongepowered/api/data/DataManipulator.java @@ -29,6 +29,7 @@ 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.data.value.ValueLike; import org.spongepowered.api.entity.Entity; import org.spongepowered.api.world.World; import org.spongepowered.eventgen.annotations.TransformWith; @@ -56,21 +57,21 @@ public interface DataManipulator extends CopyableValueContainer { /** * Creates a {@link Immutable} view directly based on the - * {@link Value}s. No unnecessary copies of the {@link Value}s + * {@link ValueLike}s. No unnecessary copies of the {@link ValueLike}s * will be created. * * @param values The values * @return The immutable data manipulator view */ - static Immutable immutableOf(final Iterable> values) { + static Immutable immutableOf(final Iterable> values) { return Sponge.game().factoryProvider().provide(Immutable.Factory.class).of(values); } /** * Creates an {@link Immutable} view directly based on the - * {@link Value}s provided by the given {@link ValueContainer}, + * {@link ValueLike}s provided by the given {@link ValueContainer}, * such that all {@link ValueContainer#getValues()} will be - * converted via {@link Value#asImmutable()} and constructed + * converted via {@link ValueLike#asImmutable()} and constructed * into an {@link Immutable}. * * @param valueContainer The value container to populate values from @@ -102,21 +103,21 @@ static Mutable mutableOf() { /** * Creates a new {@link DataManipulator} with the provided * {@link Iterable Values} such that the resulting {@link Mutable} will - * contain all said {@link Value values}. The returned + * contain all said {@link ValueLike values}. The returned * {@link DataManipulator manipulator} is still {@link Mutable mutable}. * * @param values The values to populate the mutable container * @return The mutable manipulator containing all values */ - static Mutable mutableOf(final Iterable> values) { + static Mutable mutableOf(final Iterable> values) { return Sponge.game().factoryProvider().provide(Mutable.Factory.class).of(values); } /** - * Creates a new {@link DataManipulator} with all {@link Value values} + * Creates a new {@link DataManipulator} with all {@link ValueLike values} * retrievable through the given {@link ValueContainer} by * {@link ValueContainer#getValues()} with the connotation that all - * {@link Value}s are provided, even those that are not persisted or + * {@link ValueLike}s are provided, even those that are not persisted or * registered through a {@link DataRegistration}. * * @param valueContainer The value container providing all values @@ -144,7 +145,7 @@ static Mutable mutableOf(final ValueContainer valueContainer) { /** * Gets a {@link Mutable} copy of this * {@link DataManipulator} such that all backed - * {@link Value}s are copied into their {@link org.spongepowered.api.data.value.Value.Mutable} + * {@link ValueLike}s are copied into their {@link org.spongepowered.api.data.value.ValueLike.Mutable} * counterparts. Any changes to this {@link DataManipulator} will * NOT be reflected on the returned {@link Mutable} and vice versa. * @@ -158,8 +159,8 @@ static Mutable mutableOf(final ValueContainer valueContainer) { /** * Gets an {@link Immutable} copy of this - * {@link DataManipulator} such that all backed {@link org.spongepowered.api.data.value.Value.Mutable}s are copied - * into {@link org.spongepowered.api.data.value.Value.Immutable} counterparts. Any changes to this + * {@link DataManipulator} such that all backed {@link org.spongepowered.api.data.value.ValueLike.Mutable}s are copied + * into {@link org.spongepowered.api.data.value.ValueLike.Immutable} counterparts. Any changes to this * {@link DataManipulator} will NOT be reflected on the returned * {@link Immutable} and vice versa. * @@ -171,13 +172,13 @@ static Mutable mutableOf(final ValueContainer valueContainer) { /** * Represents an immutable {@link DataManipulator}. Immutable meaning that * the contained {@link #getValues() values} are all likewise - * {@link org.spongepowered.api.data.value.Value.Immutable}, and as such, + * {@link org.spongepowered.api.data.value.ValueLike.Immutable}, and as such, * cannot be changed themselves, nor can the manipulator be modified to add - * or remove values. All methods such as {@link #with(Value)} return new + * or remove values. All methods such as {@link #with(ValueLike)} return new * instances. It is guaranteed to be thread safe to access values from this * container, and seeing as it does not change, can be passed around as a * pseudo cache for templating. It is important to note that there is no - * guarantee on the validity of the stored {@link Value}s that their own data + * guarantee on the validity of the stored {@link ValueLike}s that their own data * does not "expire", cases may include outdated references of * {@link Entity entities} or {@link World worlds} that no longer serve valid * purposes. @@ -222,15 +223,15 @@ default Immutable without(final Key key) { /** * Creates a new {@link Immutable} with the provided - * {@link Value} provided that the {@link Value} is supported by + * {@link ValueLike} provided that the {@link ValueLike} is supported by * this {@link Immutable}. * * @param The type of value * @param value The value to set * @return The new immutable data manipulator */ - default Immutable with(final Value value) { - return this.with(value.key(), value.get()); + default Immutable with(final ValueLike value) { + return this.asMutable().set(value).asImmutable(); } /** @@ -262,23 +263,23 @@ interface Factory { /** * Creates an {@link Immutable} view directly based on the - * {@link Value}s provided by the given {@link Iterable}, + * {@link ValueLike}s provided by the given {@link Iterable}, * such that all {@link Iterable#forEach(Consumer)} will be - * converted via {@link Value#asImmutable()} and constructed + * converted via {@link ValueLike#asImmutable()} and constructed * into an {@link Immutable}. * * @see DataManipulator#immutableOf(Iterable) * @param values The value container to populate values from * @return The immutable manipulator */ - Immutable of(Iterable> values); + Immutable of(Iterable> values); /** * Creates an {@link Immutable} view directly based on the - * {@link Value}s provided by the given {@link ValueContainer}, + * {@link ValueLike}s provided by the given {@link ValueContainer}, * such that all {@link ValueContainer#getValues()} will be - * converted via {@link Value#asImmutable()} and constructed + * converted via {@link ValueLike#asImmutable()} and constructed * into an {@link Immutable}. * * @see DataManipulator#immutableOf(ValueContainer) @@ -445,9 +446,9 @@ default Mutable copyFrom(final ValueContainer valueContainer) { /** * Sets the supported {@link Key}'s value such that the value is set on * this {@link Mutable} without having to directly set the - * {@link org.spongepowered.api.data.value.Value.Mutable} and {@link #set(Value)} afterwards. The requirement + * {@link org.spongepowered.api.data.value.ValueLike.Mutable} and {@link #set(ValueLike)} afterwards. The requirement * for this to succeed is that the {@link Key} must be checked that it is - * supported via {@link #supports(Value)} or {@link #supports(Key)} + * supported via {@link #supports(ValueLike)} or {@link #supports(Key)} * otherwise an {@link IllegalArgumentException} may be thrown. For * fluency, after setting, this {@link Mutable} is returned. * @@ -456,7 +457,9 @@ default Mutable copyFrom(final ValueContainer valueContainer) { * @param The type of value * @return This manipulator, for chaining */ - Mutable set(Key> key, E value); + default Mutable set(Key> key, E value) { + return this.set(Value.immutableOf(key, value)); + } default > Mutable set(final Supplier> key, final E value) { return this.set(key.get(), value); @@ -468,9 +471,9 @@ default > Mutable set(final Supplier> key, final Su } /** - * Sets the supported {@link Value} onto this {@link Mutable}. - * The requirement for this to succeed is that the {@link Value} is - * checked for support via {@link #supports(Value)} or + * Sets the supported {@link ValueLike} onto this {@link Mutable}. + * The requirement for this to succeed is that the {@link ValueLike} is + * checked for support via {@link #supports(ValueLike)} or * {@link #supports(Key)} otherwise an {@link IllegalArgumentException} * may be thrown. For fluency, after setting, this {@link Mutable} * is returned. @@ -478,15 +481,12 @@ default > Mutable set(final Supplier> key, final Su * @param value The actual value to set * @return This manipulator, for chaining */ - @SuppressWarnings("unchecked") - default Mutable set(final Value value) { - return this.set((Key>) value.key(), value.get()); - } + Mutable set(final ValueLike value); /** - * Sets the supported {@link Value}s onto this {@link Mutable}. - * The requirement for this to succeed is that the {@link Value} is - * checked for support via {@link #supports(Value)} or + * Sets the supported {@link ValueLike}s onto this {@link Mutable}. + * The requirement for this to succeed is that the {@link ValueLike} is + * checked for support via {@link #supports(ValueLike)} or * {@link #supports(Key)} otherwise an {@link IllegalArgumentException} * may be thrown. For fluency, after setting, this {@link Mutable} * is returned. @@ -494,17 +494,17 @@ default Mutable set(final Value value) { * @param values The actual values to set * @return This manipulator, for chaining */ - default Mutable set(final Value... values) { - for (final Value value : Objects.requireNonNull(values)) { + default Mutable set(final ValueLike... values) { + for (final ValueLike value : Objects.requireNonNull(values)) { this.set(Objects.requireNonNull(value, "A null value was provided!")); } return this; } /** - * Sets the supported {@link Value}s onto this {@link Mutable}. - * The requirement for this to succeed is that the {@link Value} is - * checked for support via {@link #supports(Value)} or + * Sets the supported {@link ValueLike}s onto this {@link Mutable}. + * The requirement for this to succeed is that the {@link ValueLike} is + * checked for support via {@link #supports(ValueLike)} or * {@link #supports(Key)} otherwise an {@link IllegalArgumentException} * may be thrown. For fluency, after setting, this {@link Mutable} * is returned. @@ -512,8 +512,8 @@ default Mutable set(final Value... values) { * @param values The actual values to set * @return This manipulator, for chaining */ - default Mutable set(final Iterable> values) { - for (final Value value : Objects.requireNonNull(values)) { + default Mutable set(final Iterable> values) { + for (final ValueLike value : Objects.requireNonNull(values)) { this.set(Objects.requireNonNull(value, "A null value was provided!")); } return this; @@ -564,7 +564,7 @@ interface Factory { * @param values the values to populate * @return The new manipulator with the provided values */ - Mutable of(Iterable> values); + Mutable of(Iterable> values); /** * Creates a new manipulator with all the possible values diff --git a/src/main/java/org/spongepowered/api/data/DataProvider.java b/src/main/java/org/spongepowered/api/data/DataProvider.java index bbe62b5fe54..b17fa51bb02 100644 --- a/src/main/java/org/spongepowered/api/data/DataProvider.java +++ b/src/main/java/org/spongepowered/api/data/DataProvider.java @@ -25,17 +25,20 @@ package org.spongepowered.api.data; import io.leangen.geantyref.TypeToken; +import org.checkerframework.checker.units.qual.K; import org.spongepowered.api.Server; import org.spongepowered.api.Sponge; +import org.spongepowered.api.data.value.CompositeValue; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.data.value.ValueContainer; +import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.event.data.ChangeDataHolderEvent; import java.lang.reflect.Type; import java.util.Optional; @SuppressWarnings("unchecked") -public interface DataProvider, E> { +public interface DataProvider, E> { /** * Constructs a new {@link MutableDataProviderBuilder}. @@ -72,7 +75,7 @@ static , E> ImmutableDataProviderBuilde *

    A list of methods that are constrained by this check are: *

      *
    • - {@link #get(DataHolder)}
    • - *
    • - {@link #offer(DataHolder.Mutable, Object)}
    • + *
    • - {@link #offerValue(DataHolder.Mutable, ValueLike)}
    • *
    • - {@link #remove(DataHolder.Mutable)}
    • *
    * Conceptually, an immutable {@link DataHolder} will be ignorant of @@ -97,10 +100,12 @@ static , E> ImmutableDataProviderBuilde * @param dataHolder The data holder * @return The value, if it's supported and exists */ - Optional get(DataHolder dataHolder); + default Optional get(DataHolder dataHolder) { + return this.value(dataHolder).map(ValueLike::get); + } /** - * Gets a constructed {@link Value} for the provided {@link DataHolder}. + * Gets a constructed {@link ValueLike} 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}. @@ -112,9 +117,7 @@ static , E> ImmutableDataProviderBuilde * @param dataHolder The data holder to get the constructed value from * @return The value */ - default Optional value(DataHolder dataHolder) { - return this.get(dataHolder).map(element -> Value.genericMutableOf(this.key(), element)); - } + Optional value(DataHolder dataHolder); /** * Gets whether this value provider is supported by the given {@link ValueContainer}. @@ -130,23 +133,15 @@ default boolean isSupported(final TypeToken dataHolder) { boolean isSupported(Type dataHolder); - DataTransactionResult offer(DataHolder.Mutable dataHolder, E element); - - default DataTransactionResult offerValue(DataHolder.Mutable dataHolder, V value) { - return this.offer(dataHolder, value.get()); - } + DataTransactionResult offerValue(DataHolder.Mutable dataHolder, V value); DataTransactionResult remove(DataHolder.Mutable dataHolder); - > Optional with(I immutable, E element); - - default > Optional withValue(I immutable, V value) { - return this.with(immutable, value.get()); - } + > Optional withValue(I immutable, V value); /** * Gets a {@link DataHolder.Immutable} without - * a {@link Value} with the target {@link Key}, if successful. + * a {@link ValueLike} with the target {@link Key}, if successful. * * @param immutable The immutable value store * @param The type of the immutable value store @@ -154,4 +149,10 @@ default > Optional withValue(I immutable, V */ > Optional without(I immutable); + interface Composite, E> extends DataProvider { + + DataTransactionResult remove(DataHolder.Mutable dataHolder, K valueKey); + + , K> Optional without(I immutable, K valueKey); + } } diff --git a/src/main/java/org/spongepowered/api/data/DataRegistration.java b/src/main/java/org/spongepowered/api/data/DataRegistration.java index 9f46cfbe5ed..9d0b63ec79a 100644 --- a/src/main/java/org/spongepowered/api/data/DataRegistration.java +++ b/src/main/java/org/spongepowered/api/data/DataRegistration.java @@ -28,8 +28,8 @@ import org.spongepowered.api.Sponge; import org.spongepowered.api.data.persistence.DataQuery; import org.spongepowered.api.data.persistence.DataStore; -import org.spongepowered.api.data.value.Value; import org.spongepowered.api.data.value.ValueContainer; +import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.plugin.PluginContainer; import java.util.Collection; @@ -37,7 +37,7 @@ /** * An optional registration of {@link Key keys} to associate a semi-persistent - * state of their associated {@link Value values} that can be stored, retrieved, + * state of their associated {@link ValueLike values} that can be stored, retrieved, * persisted, and/or associated with {@link DataHolder DataHolders}. A * registration identifies the given {@link #keys() Keys} are provided by an * implementation for specific {@link DataHolder DataHolders} that may support @@ -46,9 +46,9 @@ * by the implementation of the API, whether they are usable through * {@link DataProvider DataProviders} or {@link DataStore DataStores}. * - *

    If dynamic or persistent retention of the {@link Value Values} by + *

    If dynamic or persistent retention of the {@link ValueLike Values} by * {@link Key keys} is not desired, a registration is optional. This would mean - * that any submitted {@link Value}s of a {@link Key} without an associated + * that any submitted {@link ValueLike}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 @@ -69,7 +69,7 @@ static Builder builder() { /** * Gets the {@link DataProvider} for the given {@link Key} to potentially - * get or offer {@link Value}s from any {@link ValueContainer} provided + * get or offer {@link ValueLike}s from any {@link ValueContainer} provided * that the container is supported by the {@code DataProvider}. If the * {@code key} is not actually registered with this {@link DataRegistration}, * an {@link UnregisteredKeyException} is thrown. If there is no @@ -83,7 +83,7 @@ static Builder builder() { * @throws UnregisteredKeyException If the key is not registered in this * registration */ - , E> Collection> providersFor(Key key) throws UnregisteredKeyException; + , E> Collection> providersFor(Key key) throws UnregisteredKeyException; /** * Gets the appropriate {@link DataStore} for the context of the @@ -134,7 +134,7 @@ static Builder builder() { * @return The built data registration */ @SafeVarargs - static > DataRegistration of(final Key key, final Class dataHolder, final Class... dataHolders) { + static > DataRegistration of(final Key key, final Class dataHolder, final Class... dataHolders) { final DataStore dataStore = DataStore.of(key, DataQuery.of(key.key().namespace(), key.key().value()), dataHolder, dataHolders); return DataRegistration.builder().dataKey(key).store(dataStore).build(); } @@ -149,11 +149,11 @@ interface Builder extends org.spongepowered.api.util.BuilderNote that by supplying a {@link DataProvider}, the {@link Value + *

    Note that by supplying a {@link DataProvider}, the {@link ValueLike * Values} with the provider's {@link Key} will NOT be * passed to any potentially registered {@link DataStore DataStores} for * serialization. A {@link Key} that has a {@link DataProvider} will @@ -186,7 +186,7 @@ interface Builder extends org.spongepowered.api.util.Builder value) { + public static DataTransactionResult successResult(final ValueLike.Immutable value) { return DataTransactionResult.builder().success(value).result(Type.SUCCESS).build(); } /** * Creates a new {@link DataTransactionResult} with the provided - * {@link Value.Immutable} being the successful addition. The result type is - * still {@link Type#SUCCESS}. If a {@link Value.Mutable} is - * necessary, use {@link Value.Mutable}#asImmutable()} to use this method. A + * {@link ValueLike.Immutable} being the successful addition. The result type is + * still {@link Type#SUCCESS}. If a {@link ValueLike.Mutable} is + * necessary, use {@link ValueLike.Mutable}#asImmutable()} to use this method. A * {@link DataTransactionResult} is always immutable once created, and any - * {@link Value}s should be provided as {@link Value.Immutable}s or - * transformed into {@link Value.Immutable}s. + * {@link ValueLike}s should be provided as {@link ValueLike.Immutable}s or + * transformed into {@link ValueLike.Immutable}s. * * @param successful The successfully added immutable value * @param replaced The replaced value * @return The new data transaction result */ - public static DataTransactionResult successReplaceResult(final Value.Immutable successful, final Value.Immutable replaced) { + public static DataTransactionResult successReplaceResult(final ValueLike.Immutable successful, final ValueLike.Immutable replaced) { return DataTransactionResult.builder().result(Type.SUCCESS).success(successful).replace(replaced).build(); } /** * Creates a new {@link DataTransactionResult} with the provided - * {@link Value.Immutable}s being the successful additions and - * the provided {@link Value.Immutable}s that were replaced. The result type - * is still {@link Type#SUCCESS}. If a {@link Value.Mutable} - * is necessary, use {@link Value.Mutable}#asImmutable()} to use this method. A + * {@link ValueLike.Immutable}s being the successful additions and + * the provided {@link ValueLike.Immutable}s that were replaced. The result type + * is still {@link Type#SUCCESS}. If a {@link ValueLike.Mutable} + * is necessary, use {@link ValueLike.Mutable}#asImmutable()} to use this method. A * {@link DataTransactionResult} is always immutable once created, and any - * {@link Value}s should be provided as {@link Value.Immutable}s or - * transformed into {@link Value.Immutable}s. + * {@link ValueLike}s should be provided as {@link ValueLike.Immutable}s or + * transformed into {@link ValueLike.Immutable}s. * * @param successful The successfully added immutable values * @param replaced The successfully replaced immutable values * @return The new data transaction result */ - public static DataTransactionResult successReplaceResult(final Collection> successful, final Collection> replaced) { + public static DataTransactionResult successReplaceResult(final Collection> successful, final Collection> replaced) { return DataTransactionResult.builder().success(successful).replace(replaced).result(Type.SUCCESS).build(); } /** * Creates a {@link DataTransactionResult} with the provided - * {@link Value.Immutable}s being successfully removed. The result type is - * still {@link Type#SUCCESS}. If a {@link Value.Mutable} is necessary, use - * {@link Value.Mutable}#asImmutable()} to use this method. A {@link DataTransactionResult} - * is always immutable once created, and any {@link Value}s should be provided - * as {@link Value.Immutable}s or transformed into {@link Value.Immutable}s. + * {@link ValueLike.Immutable}s being successfully removed. The result type is + * still {@link Type#SUCCESS}. If a {@link ValueLike.Mutable} is necessary, use + * {@link ValueLike.Mutable}#asImmutable()} to use this method. A {@link DataTransactionResult} + * is always immutable once created, and any {@link ValueLike}s should be provided + * as {@link ValueLike.Immutable}s or transformed into {@link ValueLike.Immutable}s. * * @param removed The successfully removed values * @return The new data transaction result */ - public static DataTransactionResult successRemove(final Collection> removed) { + public static DataTransactionResult successRemove(final Collection> removed) { return DataTransactionResult.builder().replace(removed).result(Type.SUCCESS).build(); } /** * Creates a {@link DataTransactionResult} with the provided - * {@link Value.Immutable} being successfully removed. The result type is - * still {@link Type#SUCCESS}. If a {@link Value.Mutable} is necessary, use - * {@link Value.Mutable}#asImmutable()} to use this method. A + * {@link ValueLike.Immutable} being successfully removed. The result type is + * still {@link Type#SUCCESS}. If a {@link ValueLike.Mutable} is necessary, use + * {@link ValueLike.Mutable}#asImmutable()} to use this method. A * {@link DataTransactionResult} is always immutable once created, and a - * {@link Value} should be provided as an {@link Value.Immutable} or - * transformed into an {@link Value.Immutable}. + * {@link ValueLike} should be provided as an {@link ValueLike.Immutable} or + * transformed into an {@link ValueLike.Immutable}. * * @param removed The successfully removed value * @return The new data transaction result */ - public static DataTransactionResult successRemove(final Value.Immutable removed) { + public static DataTransactionResult successRemove(final ValueLike.Immutable removed) { return DataTransactionResult.builder().replace(removed).result(Type.SUCCESS).build(); } /** * Creates a new {@link DataTransactionResult} that ends in failure. The - * provided {@link Value.Immutable} is considered "rejected" and was not + * provided {@link ValueLike.Immutable} is considered "rejected" and was not * successfully added. * * @param value The value that was rejected * @return The new data transaction result */ - public static DataTransactionResult failResult(final Value.Immutable value) { + public static DataTransactionResult failResult(final ValueLike.Immutable value) { return DataTransactionResult.builder().reject(value).result(Type.FAILURE).build(); } /** * Creates a new {@link DataTransactionResult} that ends in failure. The - * provided {@link Value.Immutable}s are considered "rejected" and were not + * provided {@link ValueLike.Immutable}s are considered "rejected" and were not * successfully added. * * @param values The values that were rejected * @return The new data transaction result */ - public static DataTransactionResult failResult(final Iterable> values) { + public static DataTransactionResult failResult(final Iterable> values) { return DataTransactionResult.builder().reject(values).result(Type.FAILURE).build(); } @@ -226,13 +226,13 @@ public static DataTransactionResult failNoData() { /** * Creates a new {@link DataTransactionResult} that ends in failure. The - * provided {@link Value.Immutable} is considered "incompatible" and was not + * provided {@link ValueLike.Immutable} is considered "incompatible" and was not * successfully added. * * @param value The value that was incompatible or errored * @return The new data transaction result */ - public static DataTransactionResult errorResult(final Value.Immutable value) { + public static DataTransactionResult errorResult(final ValueLike.Immutable value) { return DataTransactionResult.builder().result(Type.ERROR).reject(value).build(); } @@ -244,8 +244,8 @@ public enum Type { /** * The actual result of the operation is undefined, this probably * indicates that something went wrong with the operation that the - * {@link Value} couldn't handle or didn't expect. The - * state of the {@link Value} is undefined. + * {@link ValueLike} couldn't handle or didn't expect. The + * state of the {@link ValueLike} is undefined. */ UNDEFINED, @@ -255,33 +255,33 @@ public enum Type { SUCCESS, /** - * The {@link Value} operation failed for an - * expected reason (such as the {@link Value} being + * The {@link ValueLike} operation failed for an + * expected reason (such as the {@link ValueLike} being * incompatible with the {@link DataHolder}. The condition of the - * {@link Value} is unchanged. + * {@link ValueLike} is unchanged. */ FAILURE, /** - * The {@link Value} operation failed because an + * The {@link ValueLike} operation failed because an * unexpected condition occurred. The state of the - * {@link Value} is undefined. + * {@link ValueLike} is undefined. */ ERROR, /** * An operation was cancelled by a third party (eg. a - * {@link Value} event was cancelled). The condition of the - * {@link Value} is unchanged. + * {@link ValueLike} event was cancelled). The condition of the + * {@link ValueLike} is unchanged. */ CANCELLED, ; } final Type type; - private final List> rejected; - private final List> replaced; - private final List> success; + private final List> rejected; + private final List> replaced; + private final List> success; DataTransactionResult(final Builder builder) { this.type = builder.resultType; @@ -322,17 +322,17 @@ public boolean isSuccessful() { } /** - * If any {@link Value}s applied onto a {@link DataHolder} were + * If any {@link ValueLike}s applied onto a {@link DataHolder} were * successful, they'll be stored in the given list. * * @return An immutable list of the values successfully offered */ - public List> successfulData() { + public List> successfulData() { return this.success; } /** - * Gets the successfully applied {@link Value} based on the provided {@link Key}. + * Gets the successfully applied {@link ValueLike} based on the provided {@link Key}. * * @param key The key * @param The data type @@ -340,28 +340,28 @@ public List> successfulData() { * @return The value, if available */ @SuppressWarnings("unchecked") - public > Optional> successfulValue(final Key key) { - for (final Value.Immutable value : this.successfulData()) { + public > Optional> successfulValue(final Key key) { + for (final ValueLike.Immutable value : this.successfulData()) { if (value.key() == key) { - return Optional.of((Value.Immutable) value); + return Optional.of((ValueLike.Immutable) value); } } return Optional.empty(); } /** - * If {@link Value.Mutable}s were supplied to the operation, this - * collection will return any {@link Value.Immutable}s which were rejected + * If {@link ValueLike.Mutable}s were supplied to the operation, this + * collection will return any {@link ValueLike.Immutable}s which were rejected * by the target {@link DataHolder}. * * @return Any data that was rejected from the operation */ - public List> rejectedData() { + public List> rejectedData() { return this.rejected; } /** - * Gets the rejected {@link Value} based on the provided {@link Key}. + * Gets the rejected {@link ValueLike} based on the provided {@link Key}. * * @param key The key * @param The data type @@ -369,27 +369,27 @@ public List> rejectedData() { * @return The value, if available */ @SuppressWarnings("unchecked") - public > Optional> rejectedValue(final Key key) { - for (final Value.Immutable value : this.rejectedData()) { + public > Optional> rejectedValue(final Key key) { + for (final ValueLike.Immutable value : this.rejectedData()) { if (value.key() == key) { - return Optional.of((Value.Immutable) value); + return Optional.of((ValueLike.Immutable) value); } } return Optional.empty(); } /** - * If the operation replaced any {@link Value.Mutable}s, this returns a collection - * of the replaced {@link Value.Immutable}s. + * If the operation replaced any {@link ValueLike.Mutable}s, this returns a collection + * of the replaced {@link ValueLike.Immutable}s. * * @return Any data that was replaced */ - public List> replacedData() { + public List> replacedData() { return this.replaced; } /** - * Gets the replaced {@link Value} based on the provided {@link Key}. + * Gets the replaced {@link ValueLike} based on the provided {@link Key}. * * @param key The key * @param The data type @@ -397,10 +397,10 @@ public List> replacedData() { * @return The value, if available */ @SuppressWarnings("unchecked") - public > Optional> replacedValue(final Key key) { - for (final Value.Immutable value : this.replacedData()) { + public > Optional> replacedValue(final Key key) { + for (final ValueLike.Immutable value : this.replacedData()) { if (value.key() == key) { - return Optional.of((Value.Immutable) value); + return Optional.of((ValueLike.Immutable) value); } } return Optional.empty(); @@ -413,7 +413,7 @@ public > Optional> replacedValue(final * * @param consumer The consumer to call */ - public void ifSuccessful(final Consumer>> consumer) { + public void ifSuccessful(final Consumer>> consumer) { if (this.isSuccessful()) { consumer.accept(this.success); } @@ -471,9 +471,9 @@ public int hashCode() { */ public static final class Builder implements org.spongepowered.api.util.Builder, CopyableBuilder { - @MonotonicNonNull List> rejected; - @MonotonicNonNull List> replaced; - @MonotonicNonNull List> successful; + @MonotonicNonNull List> rejected; + @MonotonicNonNull List> replaced; + @MonotonicNonNull List> successful; @MonotonicNonNull Type resultType; Builder() { @@ -493,14 +493,14 @@ public Builder result(final Type type) { } /** - * Adds the provided {@link Value.Immutable} to the {@link List} of - * "replaced" {@link Value.Immutable}s. The replaced values are always + * Adds the provided {@link ValueLike.Immutable} to the {@link List} of + * "replaced" {@link ValueLike.Immutable}s. The replaced values are always * copied for every {@link DataTransactionResult} for referencing. * * @param value The value to replace * @return This builder, for chaining */ - public Builder replace(final Value.Immutable value) { + public Builder replace(final ValueLike.Immutable value) { if (this.replaced == null) { this.replaced = new ArrayList<>(); } @@ -509,29 +509,29 @@ public Builder replace(final Value.Immutable value) { } /** - * Adds the provided {@link Value.Immutable}s to the {@link List} of - * "replaced" {@link Value.Immutable}s. The replaced values are always + * Adds the provided {@link ValueLike.Immutable}s to the {@link List} of + * "replaced" {@link ValueLike.Immutable}s. The replaced values are always * copied for every {@link DataTransactionResult} for referencing. * * @param values The values to replace * @return This builder, for chaining */ - public Builder replace(final Iterable> values) { - for (final Value.Immutable value : values) { + public Builder replace(final Iterable> values) { + for (final ValueLike.Immutable value : values) { this.replace(Objects.requireNonNull(value)); } return this; } /** - * Adds the provided {@link Value.Immutable} to the {@link List} of - * "rejected" {@link Value.Immutable}s. The rejected values are always + * Adds the provided {@link ValueLike.Immutable} to the {@link List} of + * "rejected" {@link ValueLike.Immutable}s. The rejected values are always * copied for every {@link DataTransactionResult} for referencing. * * @param value The values to reject * @return This builder, for chaining */ - public Builder reject(final Value.Immutable value) { + public Builder reject(final ValueLike.Immutable value) { if (this.rejected == null) { this.rejected = new ArrayList<>(); } @@ -540,29 +540,29 @@ public Builder reject(final Value.Immutable value) { } /** - * Adds the provided {@link Value.Immutable}s to the {@link List} of - * "rejected" {@link Value.Immutable}s. The rejected values are always + * Adds the provided {@link ValueLike.Immutable}s to the {@link List} of + * "rejected" {@link ValueLike.Immutable}s. The rejected values are always * copied for every {@link DataTransactionResult} for referencing. * * @param values The values to reject * @return This builder, for chaining */ - public Builder reject(final Iterable> values) { - for (final Value.Immutable value : values) { + public Builder reject(final Iterable> values) { + for (final ValueLike.Immutable value : values) { this.reject(Objects.requireNonNull(value)); } return this; } /** - * Adds the provided {@link Value.Immutable} to the {@link List} of - * "successful" {@link Value.Immutable}s. The successful values are always + * Adds the provided {@link ValueLike.Immutable} to the {@link List} of + * "successful" {@link ValueLike.Immutable}s. The successful values are always * copied for every {@link DataTransactionResult} for referencing. * * @param value The value that was successfully provided * @return This builder, for chaining */ - public Builder success(final Value.Immutable value) { + public Builder success(final ValueLike.Immutable value) { if (this.successful == null) { this.successful = new ArrayList<>(); } @@ -571,15 +571,15 @@ public Builder success(final Value.Immutable value) { } /** - * Adds the provided {@link Value.Immutable}s to the {@link List} of - * "successful" {@link Value.Immutable}s. The rejected values are always + * Adds the provided {@link ValueLike.Immutable}s to the {@link List} of + * "successful" {@link ValueLike.Immutable}s. The rejected values are always * copied for every {@link DataTransactionResult} for referencing. * * @param values The values that were successfully provided * @return This builder, for chaining */ - public Builder success(final Iterable> values) { - for (final Value.Immutable value : values) { + public Builder success(final Iterable> values) { + for (final ValueLike.Immutable value : values) { this.success(Objects.requireNonNull(value)); } return this; @@ -588,10 +588,10 @@ public Builder success(final Iterable> values) { /** * Combines the currently building {@link DataTransactionResult} with the * one provided. Usually, this means that there is some merging of the - * {@link Value.Immutable}s based on {@link Key}. If this builder already - * has an {@link Value.Immutable} as being successfully offered, and the + * {@link ValueLike.Immutable}s based on {@link Key}. If this builder already + * has an {@link ValueLike.Immutable} as being successfully offered, and the * provided result shows the same key as being rejected, the rejected - * {@link Value.Immutable} will remain in the final result. + * {@link ValueLike.Immutable} will remain in the final result. * * @param result The result to merge * @return This builder, for chaining @@ -605,26 +605,26 @@ public Builder absorbResult(final DataTransactionResult result) { this.resultType = result.type(); } } - final List> newSuccessful = new ArrayList<>(); - final List> newReplaced = new ArrayList<>(); - final List> newRejected = new ArrayList<>(); + final List> newSuccessful = new ArrayList<>(); + final List> newReplaced = new ArrayList<>(); + final List> newRejected = new ArrayList<>(); // Now let's handle the successful data if (this.successful != null) { dance: - for (final Value.Immutable value : this.successful) { - for (final Value.Immutable rejected : result.rejectedData()) { + for (final ValueLike.Immutable value : this.successful) { + for (final ValueLike.Immutable rejected : result.rejectedData()) { if (value.key().equals(rejected.key())) { newRejected.add(rejected); continue dance; } } - for (final Value.Immutable replaced : result.replacedData()) { + for (final ValueLike.Immutable replaced : result.replacedData()) { if (value.key().equals(replaced.key())) { newReplaced.add(value); continue dance; } } - for (final Value.Immutable successful : result.successfulData()) { + for (final ValueLike.Immutable successful : result.successfulData()) { if (value.key().equals(successful.key())) { newSuccessful.add(successful); continue dance; @@ -635,20 +635,20 @@ public Builder absorbResult(final DataTransactionResult result) { } if (this.replaced != null) { dance: - for (final Value.Immutable value : this.replaced) { - for (final Value.Immutable rejected : result.rejectedData()) { + for (final ValueLike.Immutable value : this.replaced) { + for (final ValueLike.Immutable rejected : result.rejectedData()) { if (value.key().equals(rejected.key())) { newRejected.add(rejected); continue dance; } } - for (final Value.Immutable replaced : result.replacedData()) { + for (final ValueLike.Immutable replaced : result.replacedData()) { if (value.key().equals(replaced.key())) { newReplaced.add(value); continue dance; } } - for (final Value.Immutable successful : result.successfulData()) { + for (final ValueLike.Immutable successful : result.successfulData()) { if (value.key().equals(successful.key())) { newSuccessful.add(successful); continue dance; @@ -659,20 +659,20 @@ public Builder absorbResult(final DataTransactionResult result) { } if (this.rejected != null) { dance: - for (final Value.Immutable value : this.rejected) { - for (final Value.Immutable rejected : result.rejectedData()) { + for (final ValueLike.Immutable value : this.rejected) { + for (final ValueLike.Immutable rejected : result.rejectedData()) { if (value.key().equals(rejected.key())) { newRejected.add(rejected); continue dance; } } - for (final Value.Immutable replaced : result.replacedData()) { + for (final ValueLike.Immutable replaced : result.replacedData()) { if (value.key().equals(replaced.key())) { newReplaced.add(value); continue dance; } } - for (final Value.Immutable successful : result.successfulData()) { + for (final ValueLike.Immutable successful : result.successfulData()) { if (value.key().equals(successful.key())) { newSuccessful.add(successful); continue dance; @@ -682,18 +682,18 @@ public Builder absorbResult(final DataTransactionResult result) { } } dance: - for (final Value.Immutable value : result.successfulData()) { - for (final Value.Immutable rejected : newRejected) { + for (final ValueLike.Immutable value : result.successfulData()) { + for (final ValueLike.Immutable rejected : newRejected) { if (value.key().equals(rejected.key())) { continue dance; } } - for (final Value.Immutable replaced : newReplaced) { + for (final ValueLike.Immutable replaced : newReplaced) { if (value.key().equals(replaced.key())) { continue dance; } } - for (final Value.Immutable successful : newSuccessful) { + for (final ValueLike.Immutable successful : newSuccessful) { if (value.key().equals(successful.key())) { continue dance; } @@ -701,18 +701,18 @@ public Builder absorbResult(final DataTransactionResult result) { newSuccessful.add(value); } dance: - for (final Value.Immutable value : result.rejectedData()) { - for (final Value.Immutable rejected : newRejected) { + for (final ValueLike.Immutable value : result.rejectedData()) { + for (final ValueLike.Immutable rejected : newRejected) { if (value.key().equals(rejected.key())) { continue dance; } } - for (final Value.Immutable replaced : newReplaced) { + for (final ValueLike.Immutable replaced : newReplaced) { if (value.key().equals(replaced.key())) { continue dance; } } - for (final Value.Immutable successful : newSuccessful) { + for (final ValueLike.Immutable successful : newSuccessful) { if (value.key().equals(successful.key())) { continue dance; } @@ -720,18 +720,18 @@ public Builder absorbResult(final DataTransactionResult result) { newRejected.add(value); } dance: - for (final Value.Immutable value : result.replacedData()) { - for (final Value.Immutable rejected : newRejected) { + for (final ValueLike.Immutable value : result.replacedData()) { + for (final ValueLike.Immutable rejected : newRejected) { if (value.key().equals(rejected.key())) { continue dance; } } - for (final Value.Immutable replaced : newReplaced) { + for (final ValueLike.Immutable replaced : newReplaced) { if (value.key().equals(replaced.key())) { continue dance; } } - for (final Value.Immutable successful : newSuccessful) { + for (final ValueLike.Immutable successful : newSuccessful) { if (value.key().equals(successful.key())) { continue dance; } @@ -746,9 +746,9 @@ public Builder absorbResult(final DataTransactionResult result) { /** * Builds a new {@link DataTransactionResult} with the providing - * {@link List}s of {@link Value.Immutable}s that are successfully - * offered, {@link Value.Immutable}s that were replaced, and - * {@link Value.Immutable}s that were rejected. + * {@link List}s of {@link ValueLike.Immutable}s that are successfully + * offered, {@link ValueLike.Immutable}s that were replaced, and + * {@link ValueLike.Immutable}s that were rejected. * * @return The newly created transaction result */ diff --git a/src/main/java/org/spongepowered/api/data/DirectionRelativeDataHolder.java b/src/main/java/org/spongepowered/api/data/DirectionRelativeDataHolder.java index d18cd8ed13c..7f020f3f86a 100644 --- a/src/main/java/org/spongepowered/api/data/DirectionRelativeDataHolder.java +++ b/src/main/java/org/spongepowered/api/data/DirectionRelativeDataHolder.java @@ -24,7 +24,7 @@ */ package org.spongepowered.api.data; -import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.util.Direction; import java.util.Optional; @@ -35,61 +35,61 @@ public interface DirectionRelativeDataHolder extends DataHolder { /** - * Attempts to get the underlying value backed by a {@link Value} + * Attempts to get the underlying value backed by a {@link ValueLike} * linked to the provided {@link Key} and {@link Direction}. If the * {@link Key} is not supported, {@link Optional#empty()} is returned. * It is important to check for support of a {@link Key} by either - * calling {@link #supports(Value)} or {@link #supports(Key)}. + * calling {@link #supports(ValueLike)} or {@link #supports(Key)}. * * @param direction The direction * @param key The key to retrieve the value for * @param The type of value * @return The value, if available */ - Optional get(Direction direction, Key> key); + Optional get(Direction direction, Key> key); /** - * Attempts to get the underlying int value backed by a {@link Value} + * Attempts to get the underlying int value backed by a {@link ValueLike} * linked to the provided {@link Key} and {@link Direction}. If the * {@link Key} is not supported, {@link Optional#empty()} is returned. * It is important to check for support of a {@link Key} by either - * calling {@link #supports(Value)} or {@link #supports(Key)}. + * calling {@link #supports(ValueLike)} or {@link #supports(Key)}. * * @param direction The direction * @param key The key to retrieve the value for * @return The value, if available */ - default OptionalInt getInt(Direction direction, Key> key) { + default OptionalInt getInt(Direction direction, Key> key) { return this.get(direction, key).map(OptionalInt::of).orElse(OptionalInt.empty()); } /** - * Attempts to get the underlying double value backed by a {@link Value} + * Attempts to get the underlying double value backed by a {@link ValueLike} * linked to the provided {@link Key} and {@link Direction}. If the * {@link Key} is not supported, {@link Optional#empty()} is returned. * It is important to check for support of a {@link Key} by either - * calling {@link #supports(Value)} or {@link #supports(Key)}. + * calling {@link #supports(ValueLike)} or {@link #supports(Key)}. * * @param direction The direction * @param key The key to retrieve the value for * @return The value, if available */ - default OptionalDouble getDouble(Direction direction, Key> key) { + default OptionalDouble getDouble(Direction direction, Key> key) { return this.get(direction, key).map(OptionalDouble::of).orElse(OptionalDouble.empty()); } /** - * Attempts to get the underlying long value backed by a {@link Value} + * Attempts to get the underlying long value backed by a {@link ValueLike} * linked to the provided {@link Key} and {@link Direction}. If the * {@link Key} is not supported, {@link Optional#empty()} is returned. * It is important to check for support of a {@link Key} by either - * calling {@link #supports(Value)} or {@link #supports(Key)}. + * calling {@link #supports(ValueLike)} or {@link #supports(Key)}. * * @param direction The direction * @param key The key to retrieve the value for * @return The value, if available */ - default OptionalLong getLong(Direction direction, Key> key) { + default OptionalLong getLong(Direction direction, Key> key) { return this.get(direction, key).map(OptionalLong::of).orElse(OptionalLong.empty()); } diff --git a/src/main/java/org/spongepowered/api/data/DirectionRelativeDataProvider.java b/src/main/java/org/spongepowered/api/data/DirectionRelativeDataProvider.java index b8049f78faa..61a599d3094 100644 --- a/src/main/java/org/spongepowered/api/data/DirectionRelativeDataProvider.java +++ b/src/main/java/org/spongepowered/api/data/DirectionRelativeDataProvider.java @@ -24,13 +24,13 @@ */ package org.spongepowered.api.data; -import org.spongepowered.api.data.value.Value; import org.spongepowered.api.data.value.ValueContainer; +import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.util.Direction; import java.util.Optional; -public interface DirectionRelativeDataProvider, E> extends DataProvider { +public interface DirectionRelativeDataProvider, E> extends DataProvider { @Override default Optional get(DataHolder dataHolder) { @@ -63,7 +63,7 @@ default boolean isSupported(DataHolder dataHolder) { Optional get(DataHolder dataHolder, Direction direction); /** - * Gets a constructed {@link Value} for the provided {@link DataHolder}. + * Gets a constructed {@link ValueLike} 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}. @@ -76,9 +76,7 @@ default boolean isSupported(DataHolder dataHolder) { * @param direction The related relative direction to the data provider * @return The value */ - default Optional value(DataHolder dataHolder, Direction direction) { - return this.get(dataHolder, direction).map(element -> Value.genericMutableOf(this.key(), element)); - } + Optional value(DataHolder dataHolder, Direction direction); /** * Gets whether this value provider is supported by the given {@link ValueContainer}. diff --git a/src/main/java/org/spongepowered/api/data/ImmutableDataProviderBuilder.java b/src/main/java/org/spongepowered/api/data/ImmutableDataProviderBuilder.java index ca32d472ae4..22e3a1fec57 100644 --- a/src/main/java/org/spongepowered/api/data/ImmutableDataProviderBuilder.java +++ b/src/main/java/org/spongepowered/api/data/ImmutableDataProviderBuilder.java @@ -25,16 +25,16 @@ package org.spongepowered.api.data; import io.leangen.geantyref.TypeToken; -import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.util.Builder; import java.util.function.BiFunction; import java.util.function.Function; -public interface ImmutableDataProviderBuilder, E> extends - Builder, E>, ImmutableDataProviderBuilder> { +public interface ImmutableDataProviderBuilder, E> extends + Builder, E>, ImmutableDataProviderBuilder> { - , NE> ImmutableDataProviderBuilder key(Key key); + , NE> ImmutableDataProviderBuilder key(Key key); ImmutableDataProviderBuilder dataHolder(TypeToken holder); @@ -47,5 +47,5 @@ public interface ImmutableDataProviderBuilder supports(final Function supports); @Override - DataProvider, E> build(); + DataProvider, E> build(); } diff --git a/src/main/java/org/spongepowered/api/data/Key.java b/src/main/java/org/spongepowered/api/data/Key.java index c1b74343784..9ec49ded9f9 100644 --- a/src/main/java/org/spongepowered/api/data/Key.java +++ b/src/main/java/org/spongepowered/api/data/Key.java @@ -28,11 +28,13 @@ import org.spongepowered.api.ResourceKey; import org.spongepowered.api.ResourceKeyed; import org.spongepowered.api.Sponge; +import org.spongepowered.api.data.value.CompositeValue; import org.spongepowered.api.data.value.ListValue; import org.spongepowered.api.data.value.MapValue; import org.spongepowered.api.data.value.SetValue; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.data.value.ValueContainer; +import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.data.value.WeightedCollectionValue; import org.spongepowered.api.event.EventListener; import org.spongepowered.api.event.data.ChangeDataHolderEvent; @@ -70,7 +72,7 @@ * @param The type of {@link Value} */ @CatalogedBy(Keys.class) -public interface Key> extends ResourceKeyed { +public interface Key> extends ResourceKeyed { /** * Creates a {@link Key.Builder} which allows creation of a {@link Key} @@ -181,7 +183,7 @@ static Key> fromMap(final ResourceKey resourceKey, final C */ void registerEvent(PluginContainer plugin, Class holderFilter, EventListener listener); - interface Builder> extends ResourceKeyedBuilder, Builder> { + interface Builder> extends ResourceKeyedBuilder, Builder> { /** * Starter method for the builder, to be used immediately after @@ -345,6 +347,38 @@ interface Builder> extends ResourceKeyedBuilder, Bu */ Builder, WeightedCollectionValue> weightedCollectionElementType(TypeToken type); + /** + * 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}. + * + *

    This overload is provided for simple cases where a plain + * {@link CompositeValue} is used.

    + * + * @param keyType The key type + * @param elementType The element type + * @param The element type of the Key's key type + * @param The element type of the Key's element type + * @return This builder, generified + */ + Builder> compositeValueElementType(Class keyType, Class elementType); + + /** + * 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}. + * + *

    This overload is provided for simple cases where a plain + * {@link CompositeValue} is used.

    + * + * @param keyType The key type + * @param elementType The element type + * @param The element type of the Key's key type + * @param The element type of the Key's element type + * @return This builder, generified + */ + Builder> compositeValueElementType(TypeToken keyType, TypeToken elementType); + /** * Sets the {@link Comparator} that can be used to compare * the elements. diff --git a/src/main/java/org/spongepowered/api/data/Keys.java b/src/main/java/org/spongepowered/api/data/Keys.java index f67f4e5334a..aa1914c46f6 100644 --- a/src/main/java/org/spongepowered/api/data/Keys.java +++ b/src/main/java/org/spongepowered/api/data/Keys.java @@ -108,6 +108,7 @@ import org.spongepowered.api.data.type.WireAttachmentType; import org.spongepowered.api.data.type.WolfSoundVariant; import org.spongepowered.api.data.type.WolfVariant; +import org.spongepowered.api.data.value.CompositeValue; import org.spongepowered.api.data.value.ListValue; import org.spongepowered.api.data.value.MapValue; import org.spongepowered.api.data.value.SetValue; @@ -3836,6 +3837,10 @@ private static Key> weightedKey(final ResourceKey return Key.builder().key(resourceKey).weightedCollectionElementType(elementType).build(); } + private static Key> compositeKey(final ResourceKey resourceKey, final Class keyType, final Class elementType) { + return Key.builder().key(resourceKey).compositeValueElementType(keyType, elementType).build(); + } + private Keys() { } } diff --git a/src/main/java/org/spongepowered/api/data/MutableDataProviderBuilder.java b/src/main/java/org/spongepowered/api/data/MutableDataProviderBuilder.java index 8bd2dff0535..1125183d37e 100644 --- a/src/main/java/org/spongepowered/api/data/MutableDataProviderBuilder.java +++ b/src/main/java/org/spongepowered/api/data/MutableDataProviderBuilder.java @@ -26,6 +26,7 @@ import io.leangen.geantyref.TypeToken; import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.util.Builder; import java.util.function.BiConsumer; @@ -34,7 +35,7 @@ import java.util.function.Function; import java.util.function.Supplier; -public interface MutableDataProviderBuilder, E> extends +public interface MutableDataProviderBuilder, E> extends Builder, MutableDataProviderBuilder> { , NE> MutableDataProviderBuilder key(Key key); diff --git a/src/main/java/org/spongepowered/api/data/persistence/DataStore.java b/src/main/java/org/spongepowered/api/data/persistence/DataStore.java index b8ee17c0c16..ff543f242e7 100644 --- a/src/main/java/org/spongepowered/api/data/persistence/DataStore.java +++ b/src/main/java/org/spongepowered/api/data/persistence/DataStore.java @@ -30,7 +30,7 @@ import org.spongepowered.api.data.DataHolder; import org.spongepowered.api.data.DataManipulator; import org.spongepowered.api.data.Key; -import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.util.ResettableBuilder; import java.lang.reflect.Type; @@ -63,23 +63,23 @@ public interface DataStore { DataView serialize(DataManipulator dataManipulator, DataView view); /** - * Serializes the passed in {@link Value values} to the {@link DataView view}. + * Serializes the passed in {@link ValueLike values} to the {@link DataView view}. * * @param values The values to serialize * @param view The view * @return The view, for chaining */ - default DataView serialize(Iterable> values, DataView view) { + default DataView serialize(Iterable> values, DataView view) { return this.serialize(DataManipulator.immutableOf(values), view); } /** - * Serializes the {@link Value}s. + * Serializes the {@link ValueLike}s. * * @param values The value container * @return This view, for chaining */ - default DataView serialize(Iterable> values) { + default DataView serialize(Iterable> values) { return this.serialize(DataManipulator.immutableOf(values)); } @@ -131,7 +131,7 @@ default DataManipulator.Mutable deserialize(DataView view) { */ @SafeVarargs @SuppressWarnings("unchecked") - static > DataStore of(final Key key, final DataQuery dataQuery, final TypeToken typeToken, final TypeToken... typeTokens) { + static > DataStore of(final Key key, final DataQuery dataQuery, final TypeToken typeToken, final TypeToken... typeTokens) { return DataStore.builder().pluginData(key.key()).holder(typeToken).holder(typeTokens).key(key, dataQuery).build(); } @@ -150,7 +150,7 @@ static > DataStore of(final Key key, final DataQuery da */ @SafeVarargs @SuppressWarnings("unchecked") - static > DataStore of(final Key key, final DataQuery dataQuery, final Class type, final Class... types) { + static > DataStore of(final Key key, final DataQuery dataQuery, final Class type, final Class... types) { return DataStore.builder().pluginData(key.key()).holder(type).holder(types).key(key, dataQuery).build(); } @@ -253,7 +253,7 @@ interface SerializersStep extends HolderStep, ResettableBuilder> Builder.EndStep key(final Key key, final String... dataQueries) { + default > Builder.EndStep key(final Key key, final String... dataQueries) { if (dataQueries.length == 0) { throw new IllegalArgumentException("dataQueries cannot be empty"); } @@ -268,7 +268,7 @@ default > Builder.EndStep key(final Key key, final Stri * * @return this builder for chaining */ - > Builder.EndStep key(final Key key, final DataQuery dataQuery); + > Builder.EndStep key(final Key key, final DataQuery dataQuery); /** * Adds the serializers for the given key. @@ -279,7 +279,7 @@ default > Builder.EndStep key(final Key key, final Stri * * @return this builder for chaining */ - > Builder.EndStep key(Key key, BiConsumer serializer, Function> deserializer); + > Builder.EndStep key(Key key, BiConsumer serializer, Function> deserializer); } interface EndStep extends SerializersStep, ResettableBuilder { diff --git a/src/main/java/org/spongepowered/api/data/persistence/DataView.java b/src/main/java/org/spongepowered/api/data/persistence/DataView.java index f2afc82e83a..58d1169111a 100644 --- a/src/main/java/org/spongepowered/api/data/persistence/DataView.java +++ b/src/main/java/org/spongepowered/api/data/persistence/DataView.java @@ -28,7 +28,7 @@ import org.spongepowered.api.Sponge; import org.spongepowered.api.data.DataManager; import org.spongepowered.api.data.Key; -import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.registry.RegistryType; @@ -875,7 +875,7 @@ default Optional> getRegistryValueList(final DataQuery path, final R * @param The value type * @return The key, if available */ - > Optional> getDataKey(DataQuery path); + > Optional> getDataKey(DataQuery path); /** * Gets the {@link List} of {@link Key values} by path, if available. @@ -883,7 +883,7 @@ default Optional> getRegistryValueList(final DataQuery path, final R * @param path The path of the value to get * @return The list of keys, if available */ - Optional>>> getDataKeyList(DataQuery path); + Optional>>> getDataKeyList(DataQuery path); /** * Copies this {@link DataView} and all of it's contents into a new diff --git a/src/main/java/org/spongepowered/api/data/value/CompositeValue.java b/src/main/java/org/spongepowered/api/data/value/CompositeValue.java new file mode 100644 index 00000000000..333dda797a1 --- /dev/null +++ b/src/main/java/org/spongepowered/api/data/value/CompositeValue.java @@ -0,0 +1,217 @@ +/* + * This file is part of SpongeAPI, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * 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.value; + +import org.spongepowered.api.Sponge; +import org.spongepowered.api.data.Key; + +import java.util.Collection; +import java.util.function.Function; + +public interface CompositeValue extends ValueLike { + + @Override + Key> key(); + + static CompositeValue.Parent.Mutable mutableOf(Key> key, ElementMergeFunction.Defaulted mergeFunction, Collection> children) { + return Sponge.game().factoryProvider().provide(CompositeValue.Factory.class).mutableOf(key, mergeFunction, children); + } + + static CompositeValue.Parent.Immutable immutableOf(Key> key, ElementMergeFunction.Defaulted mergeFunction, Collection> children) { + return Sponge.game().factoryProvider().provide(CompositeValue.Factory.class).immutableOf(key, mergeFunction, children); + } + + static Child.Mutable mutableChildOf(Key> key, K valueKey, E value) { + return Sponge.game().factoryProvider().provide(CompositeValue.Factory.class).mutableChildOf(key, valueKey, value); + } + + static Child.Immutable immutableChildOf(Key> key, K valueKey, E value) { + return Sponge.game().factoryProvider().provide(CompositeValue.Factory.class).immutableChildOf(key, valueKey, value); + } + + @Override + CompositeValue.Mutable asMutable(); + + @Override + CompositeValue.Mutable asMutableCopy(); + + @Override + CompositeValue.Immutable asImmutable(); + + interface Parent extends CompositeValue { + + Collection> children(); + + @Override + Parent.Mutable asMutable(); + + @Override + Parent.Mutable asMutableCopy(); + + @Override + Parent.Immutable asImmutable(); + + interface Mutable extends Parent, CompositeValue.Mutable { + + @Override + Collection> children(); + + Parent.Mutable set(K key, E value); + + @Override + Parent.Immutable asImmutable(); + + @Override + default Parent.Mutable asMutable() { + return this; + } + + @Override + default Parent.Mutable asMutableCopy() { + return this.copy(); + } + + @Override + Parent.Mutable copy(); + } + + interface Immutable extends Parent, CompositeValue.Immutable { + + @Override + Collection> children(); + + Parent.Immutable with(K key, E value); + + @Override + Parent.Mutable asMutable(); + + @Override + default Parent.Mutable asMutableCopy() { + return this.asMutable(); + } + + @Override + default Parent.Immutable asImmutable() { + return this; + } + } + } + + interface Child extends CompositeValue { + + K valueKey(); + + @Override + Child.Mutable asMutable(); + + @Override + Child.Mutable asMutableCopy(); + + @Override + Child.Immutable asImmutable(); + + interface Mutable extends Child, CompositeValue.Mutable { + + Child.Mutable set(E value); + + Child.Mutable transform(Function function); + + @Override + Child.Immutable asImmutable(); + + @Override + default Child.Mutable asMutable() { + return this; + } + + @Override + default Child.Mutable asMutableCopy() { + return this.copy(); + } + + @Override + Child.Mutable copy(); + } + + interface Immutable extends Child, CompositeValue.Immutable { + + Child.Immutable with(E value); + + Child.Immutable transform(Function function); + + @Override + Child.Mutable asMutable(); + + @Override + default Child.Mutable asMutableCopy() { + return this.asMutable(); + } + + @Override + default Child.Immutable asImmutable() { + return this; + } + } + } + + interface Mutable extends CompositeValue, ValueLike.Mutable { + + @Override + CompositeValue.Mutable asMutable(); + + @Override + CompositeValue.Mutable asMutableCopy(); + + @Override + CompositeValue.Immutable asImmutable(); + } + + interface Immutable extends CompositeValue, ValueLike.Immutable { + + @Override + CompositeValue.Mutable asMutable(); + + @Override + default CompositeValue.Mutable asMutableCopy() { + return this.asMutable(); + } + + @Override + default CompositeValue.Immutable asImmutable() { + return this; + } + } + + interface Factory { + + CompositeValue.Parent.Mutable mutableOf(Key> key, ElementMergeFunction.Defaulted mergeFunction, Collection> children); + + CompositeValue.Parent.Immutable immutableOf(Key> key, ElementMergeFunction.Defaulted mergeFunction, Collection> children); + + CompositeValue.Child.Mutable mutableChildOf(Key> key, K valueKey, E value); + + CompositeValue.Child.Immutable immutableChildOf(Key> key, K valueKey, E value); + } +} diff --git a/src/main/java/org/spongepowered/api/data/value/CopyableValueContainer.java b/src/main/java/org/spongepowered/api/data/value/CopyableValueContainer.java index 535e459eeab..2240edfa05e 100644 --- a/src/main/java/org/spongepowered/api/data/value/CopyableValueContainer.java +++ b/src/main/java/org/spongepowered/api/data/value/CopyableValueContainer.java @@ -31,7 +31,7 @@ public interface CopyableValueContainer extends ValueContainer { /** * Creates a clone copy of this {@link CopyableValueContainer} as a new - * {@link CopyableValueContainer} such that all the {@link Value}s are + * {@link CopyableValueContainer} such that all the {@link ValueLike}s are * safely duplicated to the new instance. It is not guaranteed that * the returning container is of the same type as this container. * diff --git a/src/main/java/org/spongepowered/api/data/value/ElementMergeFunction.java b/src/main/java/org/spongepowered/api/data/value/ElementMergeFunction.java new file mode 100644 index 00000000000..04d9a018130 --- /dev/null +++ b/src/main/java/org/spongepowered/api/data/value/ElementMergeFunction.java @@ -0,0 +1,50 @@ +/* + * This file is part of SpongeAPI, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * 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.value; + +import org.checkerframework.checker.nullness.qual.Nullable; + +@FunctionalInterface +public interface ElementMergeFunction { + + E merge(@Nullable E original, @Nullable E replacement); + + default > E merge(@Nullable V original, @Nullable V replacement) { + return this.merge(original != null ? original.get() : null, replacement != null ? replacement.get() : null); + } + + default > E merge(E original, Iterable replacement) { + E merged = original; + for (V value : replacement) { + merged = this.merge(merged, value.get()); + } + return merged; + } + + interface Defaulted extends ElementMergeFunction { + + > E merge(Iterable replacement); + } +} diff --git a/src/main/java/org/spongepowered/api/data/value/MergeFunction.java b/src/main/java/org/spongepowered/api/data/value/MergeFunction.java index 85d010fb2f5..18053bb3102 100644 --- a/src/main/java/org/spongepowered/api/data/value/MergeFunction.java +++ b/src/main/java/org/spongepowered/api/data/value/MergeFunction.java @@ -31,7 +31,7 @@ /** * Represents a unique form of {@link Function} that attempts to merge - * two separate {@link Value}s into a singular {@link Value}. + * two separate {@link ValueLike}s into a singular {@link ValueLike}. * A merge function is similar to a {@link Function} such that it can be reused * for multiple purposes and should be "stateless" on its own. */ @@ -39,9 +39,9 @@ public interface MergeFunction { /** - * Performs a merge of a type of {@link Value} such that a merge has been - * performed and the resulting merged {@link Value} is returned. It is - * suffice to say that only one of the {@link Value}s may be {@code null}, + * Performs a merge of a type of {@link ValueLike} such that a merge has been + * performed and the resulting merged {@link ValueLike} is returned. It is + * suffice to say that only one of the {@link ValueLike}s may be {@code null}, * such that
     {@code
          * if (original == null) {
          *     return checkNotNull(replacement);
    @@ -54,18 +54,18 @@ public interface MergeFunction {
          * It can be therefor discerned that both values are passed in as copies
          * and therefor either one can be modified and returned.
          *
    -     * @param original The original {@link Value} from the value store
    +     * @param original The original {@link ValueLike} from the value store
          * @param replacement The replacing value container
    -     * @param  The type of {@link Value} being passed in
    -     * @param  The type of {@code value} for the {@link Value}
    -     * @return The "merged" {@link Value}
    +     * @param  The type of {@link ValueLike} being passed in
    +     * @param  The type of {@code value} for the {@link ValueLike}
    +     * @return The "merged" {@link ValueLike}
          */
    -    , E> V merge(@Nullable V original, @Nullable V replacement);
    +    , E> V merge(@Nullable V original, @Nullable V replacement);
     
         /**
          * Creates a new {@link MergeFunction} chaining this current merge function
          * with the provided merge function. The order of the merge is this
    -     * performs {@link #merge(Value, Value)} then, the
    +     * performs {@link #merge(ValueLike, ValueLike)} then, the
          * provided {@link MergeFunction} merges the returned merged
          * {@link ValueContainer} and the {@code replacement}. This can be used to
          * apply a custom merge strategy after a pre-defined {@link MergeFunction}
    @@ -78,7 +78,7 @@ default MergeFunction andThen(final MergeFunction that) {
             final MergeFunction self = this;
             return new MergeFunction() {
                 @Override
    -            public , E> V merge(@Nullable V original, @Nullable V replacement) {
    +            public , E> V merge(@Nullable V original, @Nullable V replacement) {
                     return that.merge(self.merge(original, replacement), replacement);
                 }
             };
    @@ -90,7 +90,7 @@ public , E> V merge(@Nullable V original, @Nullable V replace
          */
         MergeFunction REPLACEMENT_PREFERRED = new MergeFunction() {
             @Override
    -        public , E> V merge(@Nullable V original, @Nullable V replacement) {
    +        public , E> V merge(@Nullable V original, @Nullable V replacement) {
                 return replacement == null ? Objects.requireNonNull(original, "Original and replacement cannot be null!") : replacement;
             }
         };
    @@ -101,7 +101,7 @@ public , E> V merge(@Nullable V original, @Nullable V replace
          */
         MergeFunction ORIGINAL_PREFERRED = new MergeFunction() {
             @Override
    -        public , E> V merge(@Nullable V original, @Nullable V replacement) {
    +        public , E> V merge(@Nullable V original, @Nullable V replacement) {
                 return original == null ? Objects.requireNonNull(replacement, "Replacement and original cannot be null!") : original;
             }
         };
    diff --git a/src/main/java/org/spongepowered/api/data/value/Value.java b/src/main/java/org/spongepowered/api/data/value/Value.java
    index 1f1c163e96f..e642b8c067d 100644
    --- a/src/main/java/org/spongepowered/api/data/value/Value.java
    +++ b/src/main/java/org/spongepowered/api/data/value/Value.java
    @@ -60,7 +60,7 @@
      *
      * @param  The type of element wrapped by this value
      */
    -public interface Value {
    +public interface Value extends ValueLike {
     
         /**
          * Constructs a mutable {@link Value} of the appropriate type based
    @@ -358,57 +358,30 @@ static , E> V genericImmutableOf(Key key, E element) {
             return Sponge.game().factoryProvider().provide(Factory.class).immutableOf(key, element);
         }
     
    -    /**
    -     * Gets the held value.
    -     *
    -     * @return The held value
    -     */
    -    E get();
    -
         /**
          * Gets the key for this {@link Value}.
          *
          * @return The key for this value
          */
    +    @Override
         Key> key();
     
    -    /**
    -     * Retrieves a mutable form of this value. Due to the vague nature of the
    -     * value itself, some cases can already provide a {@link Mutable} instance
    -     * where this would simply return itself. In other cases, where the retrieved
    -     * value is an {@link Immutable} instance, a new mutable value is created
    -     * with the same key and values.
    -     *
    -     * @return A mutable value
    -     */
    +    @Override
         Mutable asMutable();
     
    -    /**
    -     * Retrieves a copy in the mutable form of this value. The new is created
    -     * with the same key and values.
    -     *
    -     * @return A mutable value
    -     */
    +    @Override
         Mutable asMutableCopy();
     
    -    /**
    -     * Retrieves an immutable form of this value. Due to the vague nature of the
    -     * value itself, some cases can already provide a {@link Immutable} instance
    -     * where this would simply return itself. In other cases, where the retrieved
    -     * value is a {@link Mutable} instance, a new immutable value is created
    -     * with the same key and values.
    -     *
    -     * @return An immutable value
    -     */
    +    @Override
         Immutable asImmutable();
     
         /**
          * Represents a type of {@link Value} that is mutable. Simply put, the
    -     * underlying value can always be changed without creating a new {@link Mutable}.
    +     * underlying value can always be changed without creating a new {@link Value.Mutable}.
          *
          * @param  The type of element
          */
    -    interface Mutable extends Value {
    +    interface Mutable extends Value, ValueLike.Mutable {
     
             /**
              * Sets the underlying value to the provided {@code value}.
    @@ -416,7 +389,7 @@ interface Mutable extends Value {
              * @param value The value to set
              * @return The owning {@link ValueContainer}
              */
    -        Mutable set(E value);
    +        Value.Mutable set(E value);
     
             /**
              * Attempts to transform the underlying value based on the provided
    @@ -426,74 +399,68 @@ interface Mutable extends Value {
              * @param function The function to apply on the existing value
              * @return The owning {@link ValueContainer}
              */
    -        Mutable transform(Function function);
    +        Value.Mutable transform(Function function);
     
             /**
    -         * Gets the {@link Immutable} version of this {@link Mutable} such that
    -         * all data is duplicated across to the new {@link Immutable}. Note
    -         * that once created, the {@link Immutable} is not going to change.
    +         * Gets the {@link Value.Immutable} version of this {@link Value.Mutable} such that
    +         * all data is duplicated across to the new {@link Value.Immutable}. Note
    +         * that once created, the {@link Value.Immutable} is not going to change.
              *
    -         * @return A new {@link Immutable} instance
    +         * @return A new {@link Value.Immutable} instance
              */
             @Override
    -        Immutable asImmutable();
    +        Value.Immutable asImmutable();
     
             @Override
    -        default Mutable asMutable() {
    +        default Value.Mutable asMutable() {
                 return this;
             }
     
             @Override
    -        default Mutable asMutableCopy() {
    +        default Value.Mutable asMutableCopy() {
                 return this.copy();
             }
     
    -        /**
    -         * Makes an independent copy of this {@link Mutable} with the same initial
    -         * data. Both this value and the new value will refer to the same object
    -         * initially.
    -         *
    -         * @return A new copy of this {@link Mutable}
    -         */
    -        Mutable copy();
    +        @Override
    +        Value.Mutable copy();
     
         }
     
         /**
          * Represents an immutable representation of a {@link Value} where any
          * modifications of the underlying value result in a new instance of an
    -     * {@link Immutable} and/or the {@link ValueContainer} if the
    +     * {@link Value.Immutable} and/or the {@link ValueContainer} if the
          * {@link ValueContainer} too is immutable.
          *
          * 

    The basis for immutability is that once created, the value can not be * changed for any reason. Change requires a new instance to be created. As the - * {@link Immutable} always has a {@link ValueContainer}, it is + * {@link Value.Immutable} always has a {@link ValueContainer}, it is * recommended that the owning {@link ValueContainer} too is immutable, unless - * the {@link Immutable} is being passed around for data processing. The - * underlying value of an {@link Immutable} may be itself mutable, however - * utilizing any provided methods by any of the {@link Immutable} classes + * the {@link Value.Immutable} is being passed around for data processing. The + * underlying value of an {@link Value.Immutable} may be itself mutable, however + * utilizing any provided methods by any of the {@link Value.Immutable} classes * is recommended.

    * * @param The type of value */ - interface Immutable extends Value { + interface Immutable extends Value, ValueLike.Immutable { /** - * Creates a new {@link Immutable} with the given E typed + * Creates a new {@link Value.Immutable} with the given E typed * value, such that if the owning {@link ValueContainer} is immutable, the * {@link ValueContainer} too is recreated as a new instance with the new - * {@link Immutable}. + * {@link Value.Immutable}. * * @param value The value to replace * @return The owning {@link ValueContainer}, a new instance if it too is * immutable */ - Immutable with(E value); + Value.Immutable with(E value); /** - * Retrieves the underlying value for this {@link Immutable} and + * Retrieves the underlying value for this {@link Value.Immutable} and * applies the given {@link Function} onto that value, after which, the - * product is sent to a new {@link Immutable} replacing this one. + * product is sent to a new {@link Value.Immutable} replacing this one. * *

    If the {@link ValueContainer} too is immutable, a new instance of * the {@link ValueContainer} may be created. If the {@link ValueContainer} @@ -504,23 +471,23 @@ interface Immutable extends Value { * @return The owning {@link ValueContainer}, a new instance if it too is * immutable */ - Immutable transform(Function function); + Value.Immutable transform(Function function); /** - * Creates a mutable {@link Mutable} for this {@link Immutable}. + * Creates a mutable {@link Value.Mutable} for this {@link Value.Immutable}. * * @return A mutable value */ @Override - Mutable asMutable(); + Value.Mutable asMutable(); @Override - default Mutable asMutableCopy() { + default Value.Mutable asMutableCopy() { return this.asMutable(); } @Override - default Immutable asImmutable() { + default Value.Immutable asImmutable() { return this; } diff --git a/src/main/java/org/spongepowered/api/data/value/ValueContainer.java b/src/main/java/org/spongepowered/api/data/value/ValueContainer.java index 883d72b7b30..5876f2721de 100644 --- a/src/main/java/org/spongepowered/api/data/value/ValueContainer.java +++ b/src/main/java/org/spongepowered/api/data/value/ValueContainer.java @@ -39,13 +39,13 @@ import java.util.stream.Stream; /** - * A value holder is a holder of a particular set of {@link Value}s. While + * A value holder is a holder of a particular set of {@link ValueLike}s. While * there exists a {@link DataHolder} and {@link DataManipulator}, * the emphasis of {@link ValueContainer} is that it only contains "data". It * is not known whether a {@code ValueHolder} is mutable or immutable. * *

    Being that a {@code ValueHolder} is literally a container of - * {@link Value}s, it itself does not contain the underlying values of + * {@link ValueLike}s, it itself does not contain the underlying values of * data. A {@link ValueContainer} may not always be parented by another * {@link ValueContainer}, such as the case for {@link DataManipulator}s and * {@link org.spongepowered.api.data.DataHolder.Mutable}s, it is recommended to knowingly understand the @@ -54,62 +54,62 @@ public interface ValueContainer { /** - * Attempts to get the underlying value backed by a {@link Value} + * Attempts to get the underlying value backed by a {@link ValueLike} * linked to the provided {@link Key}. If the {@link Key} is not * supported, {@link Optional#empty()} is returned. It is important * to check for support of a {@link Key} by either calling - * {@link #supports(Value)} or {@link #supports(Key)}. + * {@link #supports(ValueLike)} or {@link #supports(Key)}. * * @param key The key to retrieve the value for * @param The type of value * @return The value, if available */ - Optional get(Key> key); + Optional get(Key> key); /** - * Attempts to get the underlying int value backed by a {@link Value} + * Attempts to get the underlying int value backed by a {@link ValueLike} * linked to the provided {@link Key}. If the {@link Key} is not * supported, {@link Optional#empty()} is returned. It is important * to check for support of a {@link Key} by either calling - * {@link #supports(Value)} or {@link #supports(Key)}. + * {@link #supports(ValueLike)} or {@link #supports(Key)}. * * @param key The key to retrieve the value for * @return The value, if available */ - default OptionalInt getInt(final Key> key) { + default OptionalInt getInt(final Key> key) { return this.get(key).map(OptionalInt::of).orElseGet(OptionalInt::empty); } /** - * Attempts to get the underlying double value backed by a {@link Value} + * Attempts to get the underlying double value backed by a {@link ValueLike} * linked to the provided {@link Key}. If the {@link Key} is not * supported, {@link Optional#empty()} is returned. It is important * to check for support of a {@link Key} by either calling - * {@link #supports(Value)} or {@link #supports(Key)}. + * {@link #supports(ValueLike)} or {@link #supports(Key)}. * * @param key The key to retrieve the value for * @return The value, if available */ - default OptionalDouble getDouble(final Key> key) { + default OptionalDouble getDouble(final Key> key) { return this.get(key).map(OptionalDouble::of).orElseGet(OptionalDouble::empty); } /** - * Attempts to get the underlying long value backed by a {@link Value} + * Attempts to get the underlying long value backed by a {@link ValueLike} * linked to the provided {@link Key}. If the {@link Key} is not * supported, {@link Optional#empty()} is returned. It is important * to check for support of a {@link Key} by either calling - * {@link #supports(Value)} or {@link #supports(Key)}. + * {@link #supports(ValueLike)} or {@link #supports(Key)}. * * @param key The key to retrieve the value for * @return The value, if available */ - default OptionalLong getLong(final Key> key) { + default OptionalLong getLong(final Key> key) { return this.get(key).map(OptionalLong::of).orElseGet(OptionalLong::empty); } /** - * Attempts to get the underlying value backed by a {@link Value} + * Attempts to get the underlying value backed by a {@link ValueLike} * linked to the provided {@link Key}. * *

    If the {@link Key} is not supported or @@ -120,21 +120,21 @@ default OptionalLong getLong(final Key> key) { * @return The value * @throws NoSuchElementException If the value is not supported or present */ - default E require(final Key> key) { + default E require(final Key> key) { return this.get(key).orElseThrow(() -> new NoSuchElementException(String.format( "Could not retrieve value for key '%s'", key.toString()))); } /** * Attempts to get the underlying value if available and supported. If the - * {@link Value} is not supported whatsoever by this + * {@link ValueLike} is not supported whatsoever by this * {@link ValueContainer}, an exception is thrown. * - * @param key The {@link Key} backing the {@link Value} + * @param key The {@link Key} backing the {@link ValueLike} * @param The type of value * @return The value, or null if not set */ - default @Nullable E getOrNull(final Key> key) { + default @Nullable E getOrNull(final Key> key) { final Optional value = this.get(key); if (value.isPresent()) { return value.get(); @@ -148,29 +148,29 @@ default E require(final Key> key) { /** * Attempts to get the underlying value if available. If the value is not * set, the given {@code defaultValue} is returned, if the - * {@link Value} is even supported. + * {@link ValueLike} is even supported. * - * @param key The key backing the {@link Value} + * @param key The key backing the {@link ValueLike} * @param defaultValue The value to default to if not set * @param The type of value * @return The value, or default if not set */ - default E getOrElse(final Key> key, E defaultValue) { + default E getOrElse(final Key> key, E defaultValue) { return this.get(key).orElse(Objects.requireNonNull(defaultValue, "defaultValue")); } /** - * Gets the {@link Value} for the given {@link Key}. + * Gets the {@link ValueLike} for the given {@link Key}. * - * @param key The key linked to the {@link Value} + * @param key The key linked to the {@link ValueLike} * @param The type of the return type * @param The type of value * @return The value, if available */ - > Optional getValue(Key key); + > Optional getValue(Key key); /** - * Attempts to get the underlying value backed by a {@link Value} + * Attempts to get the underlying value backed by a {@link ValueLike} * linked to the provided {@link Key}. * *

    If the {@link Key} is not supported or @@ -182,7 +182,7 @@ default E getOrElse(final Key> key, E defaultValue) { * @return The value * @throws NoSuchElementException If the value is not supported or present */ - default > V requireValue(final Key key) { + default > V requireValue(final Key key) { return this.getValue(key).orElseThrow(() -> new NoSuchElementException(String.format( "Could not retrieve value for key '%s'", key.toString()))); } @@ -197,19 +197,19 @@ default > V requireValue(final Key key) { boolean supports(Key key); /** - * Checks if the provided {@link Value} is supported. + * Checks if the provided {@link ValueLike} is supported. * * @param value The base value to check * @return True if the base value is supported */ - default boolean supports(final Value value) { + default boolean supports(final ValueLike value) { return this.supports(value.key()); } /** * Gets all applicable {@link Key}s for this {@link ValueContainer}. * Changes can not be made to the set to alter the {@link ValueContainer}, - * nor can the {@link Value}s be changed with the provided + * nor can the {@link ValueLike}s be changed with the provided * {@link Set}. * * @return An immutable set of known {@link Key}s @@ -226,24 +226,24 @@ default Stream> streamKeys() { } /** - * Gets all applicable {@link Value}s associated with this + * Gets all applicable {@link ValueLike}s associated with this * {@link ValueContainer}. As the data backed by the values are copied, - * any modifications to the {@link Value}s will not be reflected onto + * any modifications to the {@link ValueLike}s will not be reflected onto * this {@link ValueContainer}. * * @return An immutable set of copied values */ - Set> getValues(); + Set> getValues(); /** - * Gets all applicable {@link Value}s associated with this + * Gets all applicable {@link ValueLike}s associated with this * {@link ValueContainer}. As the data backed by the values are copied, - * any modifications to the {@link Value}s will not be reflected onto + * any modifications to the {@link ValueLike}s will not be reflected onto * this {@link ValueContainer}. * * @return A stream of copied values */ - default Stream> streamValues() { + default Stream> streamValues() { return this.getValues().stream(); } } diff --git a/src/main/java/org/spongepowered/api/data/value/ValueLike.java b/src/main/java/org/spongepowered/api/data/value/ValueLike.java new file mode 100644 index 00000000000..b59282d5601 --- /dev/null +++ b/src/main/java/org/spongepowered/api/data/value/ValueLike.java @@ -0,0 +1,116 @@ +/* + * This file is part of SpongeAPI, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * 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.value; + +import org.spongepowered.api.data.Key; + + +public interface ValueLike { + + /** + * Gets the key for this {@link ValueLike}. + * + * @return The key for this value + */ + Key> key(); + + /** + * Gets the held value. + * + * @return The held value + */ + E get(); + + /** + * Retrieves a mutable form of this value. Due to the vague nature of the + * value itself, some cases can already provide a {@link Mutable} instance + * where this would simply return itself. In other cases, where the retrieved + * value is an {@link Immutable} instance, a new mutable value is created + * with the same key and values. + * + * @return A mutable value + */ + Mutable asMutable(); + + /** + * Retrieves a copy in the mutable form of this value. The new is created + * with the same key and values. + * + * @return A mutable value + */ + Mutable asMutableCopy(); + + /** + * Retrieves an immutable form of this value. Due to the vague nature of the + * value itself, some cases can already provide a {@link Immutable} instance + * where this would simply return itself. In other cases, where the retrieved + * value is a {@link Mutable} instance, a new immutable value is created + * with the same key and values. + * + * @return An immutable value + */ + Immutable asImmutable(); + + interface Mutable extends ValueLike { + + @Override + Immutable asImmutable(); + + @Override + default Mutable asMutable() { + return this; + } + + @Override + default Mutable asMutableCopy() { + return this.copy(); + } + + /** + * Makes an independent copy of this {@link Mutable} with the same initial + * data. Both this value and the new value will refer to the same object + * initially. + * + * @return A new copy of this {@link Mutable} + */ + Mutable copy(); + } + + interface Immutable extends ValueLike { + + @Override + Mutable asMutable(); + + @Override + default Mutable asMutableCopy() { + return this.asMutable(); + } + + @Override + default Immutable asImmutable() { + return this; + } + } +} diff --git a/src/main/java/org/spongepowered/api/entity/Entity.java b/src/main/java/org/spongepowered/api/entity/Entity.java index c7d629d77ff..d6d8a472d1f 100644 --- a/src/main/java/org/spongepowered/api/entity/Entity.java +++ b/src/main/java/org/spongepowered/api/entity/Entity.java @@ -33,6 +33,7 @@ import org.spongepowered.api.data.value.ListValue; import org.spongepowered.api.data.value.SetValue; import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.effect.VanishState; import org.spongepowered.api.event.cause.entity.damage.source.DamageSource; import org.spongepowered.api.projectile.source.EntityProjectileSource; diff --git a/src/main/java/org/spongepowered/api/entity/living/golem/CopperGolem.java b/src/main/java/org/spongepowered/api/entity/living/golem/CopperGolem.java index 77624fa8937..71e70e7dd66 100644 --- a/src/main/java/org/spongepowered/api/entity/living/golem/CopperGolem.java +++ b/src/main/java/org/spongepowered/api/entity/living/golem/CopperGolem.java @@ -27,6 +27,7 @@ import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.CopperOxidation; import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.data.value.ValueLike; public interface CopperGolem extends Golem { @@ -34,7 +35,7 @@ public interface CopperGolem extends Golem { * Gets the {@link Value.Mutable} value of the current {@link CopperOxidation} state * for this golem. * - * @return The mutable value, to set it back, use {@link #offer(Value)} + * @return The mutable value, to set it back, use {@link #offer(ValueLike)} * @see Oxidation */ default Value.Mutable oxidation() { @@ -44,7 +45,7 @@ default Value.Mutable oxidation() { /** * Gets the {@link Value.Mutable} value of the current waxed state. * - * @return The mutable value, to set it back, use {@link #offer(Value)} + * @return The mutable value, to set it back, use {@link #offer(ValueLike)} * @see Waxing */ default Value.Mutable waxed() { diff --git a/src/main/java/org/spongepowered/api/entity/living/player/User.java b/src/main/java/org/spongepowered/api/entity/living/player/User.java index 50a704fc43c..6102a99a03d 100644 --- a/src/main/java/org/spongepowered/api/entity/living/player/User.java +++ b/src/main/java/org/spongepowered/api/entity/living/player/User.java @@ -31,6 +31,7 @@ import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.MapValue; import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.effect.VanishState; import org.spongepowered.api.entity.Entity; import org.spongepowered.api.entity.Tamer; diff --git a/src/main/java/org/spongepowered/api/item/inventory/Inventory.java b/src/main/java/org/spongepowered/api/item/inventory/Inventory.java index e74de518aa8..1ad442671f6 100644 --- a/src/main/java/org/spongepowered/api/item/inventory/Inventory.java +++ b/src/main/java/org/spongepowered/api/item/inventory/Inventory.java @@ -28,8 +28,8 @@ import org.spongepowered.api.data.Key; import org.spongepowered.api.data.KeyValueMatcher; import org.spongepowered.api.data.Keys; -import org.spongepowered.api.data.value.Value; import org.spongepowered.api.data.value.ValueContainer; +import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.item.ItemType; import org.spongepowered.api.item.inventory.query.Query; @@ -303,7 +303,7 @@ static Builder builder() { * * @return The key value, if available */ - Optional get(Inventory child, Key> key); + Optional get(Inventory child, Key> key); /** * Gets a key defined directly on this Inventory if one is defined. @@ -318,7 +318,7 @@ static Builder builder() { * @return The key value, if available */ @Override - Optional get(Key> key); + Optional get(Key> key); /** * Query this inventory with given {@link Query} diff --git a/src/main/java/org/spongepowered/api/item/inventory/ItemStackBuilderPopulators.java b/src/main/java/org/spongepowered/api/item/inventory/ItemStackBuilderPopulators.java index c0740d655e1..66d731b63da 100644 --- a/src/main/java/org/spongepowered/api/item/inventory/ItemStackBuilderPopulators.java +++ b/src/main/java/org/spongepowered/api/item/inventory/ItemStackBuilderPopulators.java @@ -33,6 +33,7 @@ import org.spongepowered.api.data.value.ListValue; import org.spongepowered.api.data.value.SetValue; import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.item.ItemType; import org.spongepowered.api.item.enchantment.Enchantment; import org.spongepowered.api.item.enchantment.EnchantmentType; @@ -440,7 +441,7 @@ private static BiConsumer setValue(final Key BiConsumer setValue(final Key The type of value * @return The new biconsumer to apply to an itemstack builder */ - public static > BiConsumer value(final V value) { + public static > BiConsumer value(final V value) { return (builder, random) -> { final ItemStack itemStack = builder.build(); final DataTransactionResult dataTransactionResult = itemStack.offer(value); @@ -460,14 +461,14 @@ public static > BiConsumer valu /** * Creates a new {@link BiConsumer} that applies a random selection of the - * provided {@link Value}s. + * provided {@link ValueLike}s. * * @param values The iterable collection of values to choose from * @param The type of element * @param The type of value * @return The new biconsumer to apply to an itemstack builder */ - public static > BiConsumer values(final Iterable values) { + public static > BiConsumer values(final Iterable values) { final WeightedTable tableEntries = new WeightedTable<>(1); for (final V value : values) { tableEntries.add(Objects.requireNonNull(value, "Value cannot be null!"), 1); @@ -484,7 +485,7 @@ public static > BiConsumer valu /** * Creates a new {@link BiConsumer} that provides a {@link VariableAmount} - * of {@link Value}s from the provided pool. Note that no + * of {@link ValueLike}s from the provided pool. Note that no * validation can be performed, however the builder will ignore unsupported * data. * @@ -492,11 +493,11 @@ public static > BiConsumer valu * @param rolls The variable amount of manipulators to apply * @return The new biconsumer to apply to an itemstack builder */ - public static BiConsumer values(final Collection> manipulators, final VariableAmount rolls) { + public static BiConsumer values(final Collection> manipulators, final VariableAmount rolls) { Objects.requireNonNull(manipulators, "Manipulators cannot be null!"); Objects.requireNonNull(rolls, "VariableAmount cannot be null!"); - final List> copied = List.copyOf(manipulators); - final WeightedTable> table = new WeightedTable<>(); + final List> copied = List.copyOf(manipulators); + final WeightedTable> table = new WeightedTable<>(); table.setRolls(rolls); copied.forEach(manipulator1 -> table.add(manipulator1, 1)); return ItemStackBuilderPopulators.values(table); @@ -504,14 +505,14 @@ public static BiConsumer values(final Collection values(final WeightedTable> weightedTable) { + public static BiConsumer values(final WeightedTable> weightedTable) { Objects.requireNonNull(weightedTable, "WeightedTable cannot be null!"); return (builder, random) -> weightedTable.get(random).forEach(builder::add); } diff --git a/src/main/java/org/spongepowered/api/item/inventory/ItemStackLike.java b/src/main/java/org/spongepowered/api/item/inventory/ItemStackLike.java index e425fe1f103..2777cd99f66 100644 --- a/src/main/java/org/spongepowered/api/item/inventory/ItemStackLike.java +++ b/src/main/java/org/spongepowered/api/item/inventory/ItemStackLike.java @@ -30,8 +30,8 @@ import org.spongepowered.api.data.Key; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.SerializableDataHolder; -import org.spongepowered.api.data.value.Value; import org.spongepowered.api.data.value.ValueContainer; +import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.entity.attribute.AttributeModifier; import org.spongepowered.api.entity.attribute.type.AttributeType; import org.spongepowered.api.item.ItemType; @@ -160,7 +160,7 @@ default Collection attributeModifiers(Supplier The type of element of data * @return The data, if available */ - default Optional get(final Vector3i position, final Key> key) { + default Optional get(final Vector3i position, final Key> key) { return this.get(position.x(), position.y(), position.z(), key); } @@ -77,7 +78,7 @@ default Optional get(final Vector3i position, final Key The type of element of data * @return The data, if available */ - default Optional get(final Vector3i position, final DefaultedRegistryReference>> key) { + default Optional get(final Vector3i position, final DefaultedRegistryReference>> key) { return this.get(position.x(), position.y(), position.z(), key.get()); } @@ -92,7 +93,7 @@ default Optional get(final Vector3i position, final DefaultedRegistryRefe * @param The type of element of data * @return The data, if available */ - Optional get(int x, int y, int z, Key> key); + Optional get(int x, int y, int z, Key> key); /** * Gets the value of data that is keyed to the provided {@link Key} at the @@ -105,7 +106,7 @@ default Optional get(final Vector3i position, final DefaultedRegistryRefe * @param The type of element of data * @return The data, if available */ - default Optional get(final int x, final int y, final int z, final DefaultedRegistryReference>> key) { + default Optional get(final int x, final int y, final int z, final DefaultedRegistryReference>> key) { return this.get(x, y, z, key.get()); } @@ -117,7 +118,7 @@ default Optional get(final int x, final int y, final int z, final Default * @param key The key to the data * @return The data, if available */ - default OptionalInt getInt(final Vector3i position, final Key> key) { + default OptionalInt getInt(final Vector3i position, final Key> key) { return this.getInt(position.x(), position.y(), position.z(), key); } @@ -129,7 +130,7 @@ default OptionalInt getInt(final Vector3i position, final Key>> key) { + default OptionalInt getInt(final Vector3i position, final DefaultedRegistryReference>> key) { return this.getInt(position.x(), position.y(), position.z(), key.get()); } @@ -143,7 +144,7 @@ default OptionalInt getInt(final Vector3i position, final DefaultedRegistryRefer * @param key The key to the data * @return The data, if available */ - default OptionalInt getInt(final int x, final int y, final int z, final Key> key) { + default OptionalInt getInt(final int x, final int y, final int z, final Key> key) { return this.get(x, y, z, key).map(OptionalInt::of).orElseGet(OptionalInt::empty); } @@ -157,7 +158,7 @@ default OptionalInt getInt(final int x, final int y, final int z, final Key>> key) { + default OptionalInt getInt(final int x, final int y, final int z, final DefaultedRegistryReference>> key) { return this.get(x, y, z, key.get()).map(OptionalInt::of).orElseGet(OptionalInt::empty); } @@ -169,7 +170,7 @@ default OptionalInt getInt(final int x, final int y, final int z, final Defaulte * @param key The key to the data * @return The data, if available */ - default OptionalDouble getDouble(final Vector3i position, final Key> key) { + default OptionalDouble getDouble(final Vector3i position, final Key> key) { return this.getDouble(position.x(), position.y(), position.z(), key); } @@ -181,7 +182,7 @@ default OptionalDouble getDouble(final Vector3i position, final Key>> key) { + default OptionalDouble getDouble(final Vector3i position, final DefaultedRegistryReference>> key) { return this.getDouble(position.x(), position.y(), position.z(), key.get()); } @@ -195,7 +196,7 @@ default OptionalDouble getDouble(final Vector3i position, final DefaultedRegistr * @param key The key to the data * @return The data, if available */ - default OptionalDouble getDouble(final int x, final int y, final int z, final Key> key) { + default OptionalDouble getDouble(final int x, final int y, final int z, final Key> key) { return this.get(x, y, z, key).map(OptionalDouble::of).orElseGet(OptionalDouble::empty); } @@ -209,7 +210,7 @@ default OptionalDouble getDouble(final int x, final int y, final int z, final Ke * @param key The key to the data * @return The data, if available */ - default OptionalDouble getDouble(final int x, final int y, final int z, final DefaultedRegistryReference>> key) { + default OptionalDouble getDouble(final int x, final int y, final int z, final DefaultedRegistryReference>> key) { return this.get(x, y, z, key).map(OptionalDouble::of).orElseGet(OptionalDouble::empty); } @@ -221,7 +222,7 @@ default OptionalDouble getDouble(final int x, final int y, final int z, final De * @param key The key to the data * @return The data, if available */ - default OptionalLong getLong(final Vector3i position, final Key> key) { + default OptionalLong getLong(final Vector3i position, final Key> key) { return this.getLong(position.x(), position.y(), position.z(), key); } @@ -233,7 +234,7 @@ default OptionalLong getLong(final Vector3i position, final Key>> key) { + default OptionalLong getLong(final Vector3i position, final DefaultedRegistryReference>> key) { return this.getLong(position.x(), position.y(), position.z(), key.get()); } @@ -247,7 +248,7 @@ default OptionalLong getLong(final Vector3i position, final DefaultedRegistryRef * @param key The key to the data * @return The data, if available */ - default OptionalLong getLong(final int x, final int y, final int z, final Key> key) { + default OptionalLong getLong(final int x, final int y, final int z, final Key> key) { return this.get(x, y, z, key).map(OptionalLong::of).orElseGet(OptionalLong::empty); } @@ -261,12 +262,12 @@ default OptionalLong getLong(final int x, final int y, final int z, final Key>> key) { + default OptionalLong getLong(final int x, final int y, final int z, final DefaultedRegistryReference>> key) { return this.get(x, y, z, key).map(OptionalLong::of).orElseGet(OptionalLong::empty); } /** - * Attempts to get the underlying value backed by a {@link Value} + * Attempts to get the underlying value backed by a {@link ValueLike} * linked to the provided {@link Key}. * *

    If the {@link Key} is not supported or @@ -278,12 +279,12 @@ default OptionalLong getLong(final int x, final int y, final int z, final Defaul * @return The value * @throws NoSuchElementException If the value is not supported or present */ - default E require(final Vector3i position, final Key> key) { + default E require(final Vector3i position, final Key> key) { return this.require(position.x(), position.y(), position.z(), key); } /** - * Attempts to get the underlying value backed by a {@link Value} + * Attempts to get the underlying value backed by a {@link ValueLike} * linked to the provided {@link Key}. * *

    If the {@link Key} is not supported or @@ -295,12 +296,12 @@ default E require(final Vector3i position, final Key> key * @return The value * @throws NoSuchElementException If the value is not supported or present */ - default E require(final Vector3i position, final DefaultedRegistryReference>> key) { + default E require(final Vector3i position, final DefaultedRegistryReference>> key) { return this.require(position.x(), position.y(), position.z(), key.get()); } /** - * Attempts to get the underlying value backed by a {@link Value} + * Attempts to get the underlying value backed by a {@link ValueLike} * linked to the provided {@link Key}. * *

    If the {@link Key} is not supported or @@ -314,7 +315,7 @@ default E require(final Vector3i position, final DefaultedRegistryReference< * @return The value * @throws NoSuchElementException If the value is not supported or present */ - default E require(final int x, final int y, final int z, final Key> key) { + default E require(final int x, final int y, final int z, final Key> key) { final Optional optional = this.get(x, y, z, key); if (optional.isPresent()) { return optional.get(); @@ -323,7 +324,7 @@ default E require(final int x, final int y, final int z, final KeyIf the {@link Key} is not supported or @@ -337,7 +338,7 @@ default E require(final int x, final int y, final int z, final Key E require(final int x, final int y, final int z, final DefaultedRegistryReference>> key) { + default E require(final int x, final int y, final int z, final DefaultedRegistryReference>> key) { final Optional optional = this.get(x, y, z, key.get()); if (optional.isPresent()) { return optional.get(); @@ -355,7 +356,7 @@ default E require(final int x, final int y, final int z, final DefaultedRegi * @param The type of element of data * @return The data or null */ - default @Nullable E orNull(final Vector3i position, final Key> key) { + default @Nullable E orNull(final Vector3i position, final Key> key) { return this.get(position.x(), position.y(), position.z(), key).orElse(null); } @@ -369,7 +370,7 @@ default E require(final int x, final int y, final int z, final DefaultedRegi * @param The type of element of data * @return The data or null */ - default @Nullable E orNull(final Vector3i position, final DefaultedRegistryReference>> key) { + default @Nullable E orNull(final Vector3i position, final DefaultedRegistryReference>> key) { return this.get(position.x(), position.y(), position.z(), key.get()).orElse(null); } @@ -385,7 +386,7 @@ default E require(final int x, final int y, final int z, final DefaultedRegi * @param The type of element of data * @return The data or null */ - default @Nullable E orNull(final int x, final int y, final int z, final Key> key) { + default @Nullable E orNull(final int x, final int y, final int z, final Key> key) { return this.get(x, y, z, key).orElse(null); } @@ -401,7 +402,7 @@ default E require(final int x, final int y, final int z, final DefaultedRegi * @param The type of element of data * @return The data or null */ - default @Nullable E orNull(final int x, final int y, final int z, final DefaultedRegistryReference>> key) { + default @Nullable E orNull(final int x, final int y, final int z, final DefaultedRegistryReference>> key) { return this.get(x, y, z, key.get()).orElse(null); } @@ -416,7 +417,7 @@ default E require(final int x, final int y, final int z, final DefaultedRegi * @param The type of element of data * @return The data or null */ - default E orElse(final Vector3i position, final Key> key, final E defaultValue) { + default E orElse(final Vector3i position, final Key> key, final E defaultValue) { return this.get(position.x(), position.y(), position.z(), key).orElse(Objects.requireNonNull(defaultValue)); } @@ -431,7 +432,7 @@ default E orElse(final Vector3i position, final Key> key, * @param The type of element of data * @return The data or null */ - default E orElse(final Vector3i position, final DefaultedRegistryReference>> key, final E defaultValue) { + default E orElse(final Vector3i position, final DefaultedRegistryReference>> key, final E defaultValue) { return this.get(position.x(), position.y(), position.z(), key.get()).orElse(Objects.requireNonNull(defaultValue)); } @@ -448,7 +449,7 @@ default E orElse(final Vector3i position, final DefaultedRegistryReference The type of element of data * @return The data or null */ - default E orElse(final int x, final int y, final int z, final Key> key, final E defaultValue) { + default E orElse(final int x, final int y, final int z, final Key> key, final E defaultValue) { return this.get(x, y, z, key).orElse(Objects.requireNonNull(defaultValue)); } @@ -465,7 +466,7 @@ default E orElse(final int x, final int y, final int z, final Key The type of element of data * @return The data or null */ - default E orElse(final int x, final int y, final int z, final DefaultedRegistryReference>> key, final E defaultValue) { + default E orElse(final int x, final int y, final int z, final DefaultedRegistryReference>> key, final E defaultValue) { return this.get(x, y, z, key.get()).orElse(Objects.requireNonNull(defaultValue)); } @@ -481,7 +482,7 @@ default E orElse(final int x, final int y, final int z, final DefaultedRegis * @param The type of element of data * @return The data or null */ - default E orElse(final Vector3i position, final Key> key, final Supplier defaultValue) { + default E orElse(final Vector3i position, final Key> key, final Supplier defaultValue) { return this.get(position.x(), position.y(), position.z(), key).orElseGet(Objects.requireNonNull(defaultValue)); } @@ -496,7 +497,7 @@ default E orElse(final Vector3i position, final Key> key, * @param The type of element of data * @return The data or null */ - default E orElse(final Vector3i position, final DefaultedRegistryReference>> key, final Supplier defaultValue) { + default E orElse(final Vector3i position, final DefaultedRegistryReference>> key, final Supplier defaultValue) { return this.get(position.x(), position.y(), position.z(), key.get()).orElseGet(Objects.requireNonNull(defaultValue)); } @@ -513,7 +514,7 @@ default E orElse(final Vector3i position, final DefaultedRegistryReference The type of element of data * @return The data or null */ - default E orElse(final int x, final int y, final int z, final Key> key, final Supplier defaultValue) { + default E orElse(final int x, final int y, final int z, final Key> key, final Supplier defaultValue) { return this.get(x, y, z, key).orElseGet(Objects.requireNonNull(defaultValue)); } @@ -530,7 +531,7 @@ default E orElse(final int x, final int y, final int z, final Key The type of element of data * @return The data or null */ - default E orElse(final int x, final int y, final int z, final DefaultedRegistryReference>> key, final Supplier defaultValue) { + default E orElse(final int x, final int y, final int z, final DefaultedRegistryReference>> key, final Supplier defaultValue) { return this.get(x, y, z, key.get()).orElseGet(Objects.requireNonNull(defaultValue)); } @@ -545,7 +546,7 @@ default E orElse(final int x, final int y, final int z, final DefaultedRegis * @param The type of value * @return The base value, if available */ - default > Optional getValue(final Vector3i position, final Key key) { + default > Optional getValue(final Vector3i position, final Key key) { return this.getValue(position.x(), position.y(), position.z(), key); } @@ -560,7 +561,7 @@ default > Optional getValue(final Vector3i position, fi * @param The type of value * @return The base value, if available */ - default > Optional getValue(final Vector3i position, final Supplier> key) { + default > Optional getValue(final Vector3i position, final Supplier> key) { return this.getValue(position.x(), position.y(), position.z(), key.get()); } @@ -576,7 +577,7 @@ default > Optional getValue(final Vector3i position, fi * @param The type of value * @return The base value, if available */ - > Optional getValue(int x, int y, int z, Key key); + > Optional getValue(int x, int y, int z, Key key); /** * Gets the value of data that is keyed to the provided {@link Key} at the @@ -590,7 +591,7 @@ default > Optional getValue(final Vector3i position, fi * @param The type of value * @return The base value, if available */ - default > Optional getValue(final int x, final int y, final int z, final DefaultedRegistryReference> key) { + default > Optional getValue(final int x, final int y, final int z, final DefaultedRegistryReference> key) { return this.getValue(x, y, z, key.get()); } @@ -645,19 +646,19 @@ default boolean supports(final int x, final int y, final int z, final Supplier value) { + default boolean supports(final Vector3i position, final ValueLike value) { return this.supports(position.x(), position.y(), position.z(), value.key()); } /** - * Checks if the provided {@link Value} is supported by the block at the + * Checks if the provided {@link ValueLike} is supported by the block at the * provided location. * * @param x The X coordinate @@ -666,7 +667,7 @@ default boolean supports(final Vector3i position, final Value value) { * @param value The value of data * @return True if the block supports the data */ - default boolean supports(final int x, final int y, final int z, final Value value) { + default boolean supports(final int x, final int y, final int z, final ValueLike value) { return this.supports(x, y, z, value.key()); } @@ -693,18 +694,18 @@ default Set> keys(final Vector3i position) { Set> keys(int x, int y, int z); /** - * Gets an immutable {@link Set} of {@link org.spongepowered.api.data.value.Value.Immutable}s for the block at + * Gets an immutable {@link Set} of {@link org.spongepowered.api.data.value.ValueLike.Immutable}s for the block at * the given location. * * @param position The position of the block * @return The immutable set of values for the block */ - default Set> getValues(final Vector3i position) { + default Set> getValues(final Vector3i position) { return this.getValues(position.x(), position.y(), position.z()); } /** - * Gets an immutable {@link Set} of {@link org.spongepowered.api.data.value.Value.Immutable}s for the block at + * Gets an immutable {@link Set} of {@link org.spongepowered.api.data.value.ValueLike.Immutable}s for the block at * the given location. * * @param x The X position @@ -712,7 +713,7 @@ default Set> getValues(final Vector3i position) { * @param z The Z position * @return The immutable set of values for the block */ - Set> getValues(int x, int y, int z); + Set> getValues(int x, int y, int z); interface Mutable extends LocationBaseDataHolder { @@ -846,7 +847,9 @@ default DataTransactionResult offer(final Vector3i position, final Defaulted * @param The type of data being offered * @return The transaction result */ - DataTransactionResult offer(int x, int y, int z, Key> key, E value); + default DataTransactionResult offer(int x, int y, int z, Key> key, E value) { + return this.offer(x, y, z, Value.immutableOf(key, value)); + } /** * Offers the given E value that is keyed by the provided @@ -870,7 +873,7 @@ default DataTransactionResult offer(final int x, final int y, final int z, f } /** - * Offers the given {@link Value} to the block at the given position. + * Offers the given {@link ValueLike} to the block at the given position. * *

    If any data is rejected or existing data is replaced, the * {@link DataTransactionResult} will retain the rejected and replaced @@ -881,12 +884,12 @@ default DataTransactionResult offer(final int x, final int y, final int z, f * @param The type of the element wrapped by the value * @return The transaction result */ - default DataTransactionResult offer(final Vector3i position, final Value value) { - return this.offer(position.x(), position.y(), position.z(), value.key(), value.get()); + default DataTransactionResult offer(final Vector3i position, final ValueLike value) { + return this.offer(position.x(), position.y(), position.z(), value); } /** - * Offers the given {@link Value} to the block at the given position. + * Offers the given {@link ValueLike} to the block at the given position. * *

    If any data is rejected or existing data is replaced, the * {@link DataTransactionResult} will retain the rejected and replaced @@ -899,9 +902,7 @@ default DataTransactionResult offer(final Vector3i position, final Value * @param The type of the element wrapped by the value * @return The transaction result */ - default DataTransactionResult offer(final int x, final int y, final int z, final Value value) { - return this.offer(x, y, z, value.key(), value.get()); - } + DataTransactionResult offer(final int x, final int y, final int z, final ValueLike value); /** * Attempts to remove the data associated with the provided {@link Key} from @@ -955,8 +956,8 @@ default DataTransactionResult remove(final int x, final int y, final int z, fina /** * Attempts to undo a {@link DataTransactionResult}. Specifically, all - * {@link org.spongepowered.api.data.value.Value.Immutable}s that were successfully added are removed, and all - * replaced {@link org.spongepowered.api.data.value.Value.Immutable}s are offered. + * {@link org.spongepowered.api.data.value.ValueLike.Immutable}s that were successfully added are removed, and all + * replaced {@link org.spongepowered.api.data.value.ValueLike.Immutable}s are offered. * * @param position The position of the block * @param result The transaction result to undo @@ -968,8 +969,8 @@ default DataTransactionResult undo(final Vector3i position, final DataTransactio /** * Attempts to undo a {@link DataTransactionResult}. Specifically, all - * {@link org.spongepowered.api.data.value.Value.Immutable}s that were successfully added are removed, and all - * replaced {@link org.spongepowered.api.data.value.Value.Immutable}s are offered. + * {@link org.spongepowered.api.data.value.ValueLike.Immutable}s that were successfully added are removed, and all + * replaced {@link org.spongepowered.api.data.value.ValueLike.Immutable}s are offered. * * @param x The X position * @param y The Y position @@ -1018,7 +1019,7 @@ default DataTransactionResult copyFrom(final Vector3i positionTo, final Vector3i } /** - * Attempts to copy all {@link org.spongepowered.api.data.value.Value.Immutable}s from the provided block to + * Attempts to copy all {@link org.spongepowered.api.data.value.ValueLike.Immutable}s from the provided block to * provided block to the provided block position. * * @param xTo The X position of the block to copy data to @@ -1034,7 +1035,7 @@ default DataTransactionResult copyFrom(final int xTo, final int yTo, final int z } /** - * Attempts to copy all {@link org.spongepowered.api.data.value.Value.Immutable}s from the provided block to + * Attempts to copy all {@link org.spongepowered.api.data.value.ValueLike.Immutable}s from the provided block to * provided block to the provided block position. Any conflicting data is * handled through the provided {@link MergeFunction}. * @@ -1048,7 +1049,7 @@ default DataTransactionResult copyFrom(final Vector3i to, final ValueContainer f } /** - * Attempts to copy all {@link org.spongepowered.api.data.value.Value.Immutable}s from the provided block to + * Attempts to copy all {@link org.spongepowered.api.data.value.ValueLike.Immutable}s from the provided block to * provided block to the provided block position. Any conflicting data is * handled through the provided {@link MergeFunction}. * @@ -1062,7 +1063,7 @@ default DataTransactionResult copyFrom(final Vector3i to, final ValueContainer f DataTransactionResult copyFrom(int xTo, int yTo, int zTo, ValueContainer from, MergeFunction function); /** - * Attempts to copy all {@link org.spongepowered.api.data.value.Value.Immutable}s from the provided block to + * Attempts to copy all {@link org.spongepowered.api.data.value.ValueLike.Immutable}s from the provided block to * provided block to the provided block position. Any conflicting data is * handled through the provided {@link MergeFunction}. * @@ -1077,7 +1078,7 @@ default DataTransactionResult copyFrom(final Vector3i positionTo, final Vector3i } /** - * Attempts to copy all {@link org.spongepowered.api.data.value.Value.Immutable}s from the provided block to + * Attempts to copy all {@link org.spongepowered.api.data.value.ValueLike.Immutable}s from the provided block to * provided block to the provided block position. Any conflicting data is * handled through the provided {@link MergeFunction}. * From 15e23e8359957aea2244e7e9b9a74cd3fb289532 Mon Sep 17 00:00:00 2001 From: aromaa Date: Sun, 20 Sep 2026 18:11:31 +0300 Subject: [PATCH 2/4] Revert DataProvider builders back to Value --- .../api/data/ImmutableDataProviderBuilder.java | 10 +++++----- .../api/data/MutableDataProviderBuilder.java | 3 +-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/spongepowered/api/data/ImmutableDataProviderBuilder.java b/src/main/java/org/spongepowered/api/data/ImmutableDataProviderBuilder.java index 22e3a1fec57..ca32d472ae4 100644 --- a/src/main/java/org/spongepowered/api/data/ImmutableDataProviderBuilder.java +++ b/src/main/java/org/spongepowered/api/data/ImmutableDataProviderBuilder.java @@ -25,16 +25,16 @@ package org.spongepowered.api.data; import io.leangen.geantyref.TypeToken; -import org.spongepowered.api.data.value.ValueLike; +import org.spongepowered.api.data.value.Value; import org.spongepowered.api.util.Builder; import java.util.function.BiFunction; import java.util.function.Function; -public interface ImmutableDataProviderBuilder, E> extends - Builder, E>, ImmutableDataProviderBuilder> { +public interface ImmutableDataProviderBuilder, E> extends + Builder, E>, ImmutableDataProviderBuilder> { - , NE> ImmutableDataProviderBuilder key(Key key); + , NE> ImmutableDataProviderBuilder key(Key key); ImmutableDataProviderBuilder dataHolder(TypeToken holder); @@ -47,5 +47,5 @@ public interface ImmutableDataProviderBuilder supports(final Function supports); @Override - DataProvider, E> build(); + DataProvider, E> build(); } diff --git a/src/main/java/org/spongepowered/api/data/MutableDataProviderBuilder.java b/src/main/java/org/spongepowered/api/data/MutableDataProviderBuilder.java index 1125183d37e..8bd2dff0535 100644 --- a/src/main/java/org/spongepowered/api/data/MutableDataProviderBuilder.java +++ b/src/main/java/org/spongepowered/api/data/MutableDataProviderBuilder.java @@ -26,7 +26,6 @@ import io.leangen.geantyref.TypeToken; import org.spongepowered.api.data.value.Value; -import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.util.Builder; import java.util.function.BiConsumer; @@ -35,7 +34,7 @@ import java.util.function.Function; import java.util.function.Supplier; -public interface MutableDataProviderBuilder, E> extends +public interface MutableDataProviderBuilder, E> extends Builder, MutableDataProviderBuilder> { , NE> MutableDataProviderBuilder key(Key key); From 5acfdc2c69bff08ef2cec901eac458cd1e1a9136 Mon Sep 17 00:00:00 2001 From: aromaa Date: Sun, 20 Sep 2026 18:14:11 +0300 Subject: [PATCH 3/4] Fix checkstyle --- .../api/data/value/CompositeValue.java | 24 +++++++++---------- .../org/spongepowered/api/entity/Entity.java | 1 - .../api/entity/living/player/User.java | 1 - 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/spongepowered/api/data/value/CompositeValue.java b/src/main/java/org/spongepowered/api/data/value/CompositeValue.java index 333dda797a1..60645eb85d5 100644 --- a/src/main/java/org/spongepowered/api/data/value/CompositeValue.java +++ b/src/main/java/org/spongepowered/api/data/value/CompositeValue.java @@ -52,26 +52,26 @@ static Child.Immutable immutableChildOf(Key asMutable(); + CompositeValue.Mutable asMutable(); @Override - CompositeValue.Mutable asMutableCopy(); + CompositeValue.Mutable asMutableCopy(); @Override - CompositeValue.Immutable asImmutable(); + CompositeValue.Immutable asImmutable(); interface Parent extends CompositeValue { Collection> children(); @Override - Parent.Mutable asMutable(); + Parent.Mutable asMutable(); @Override - Parent.Mutable asMutableCopy(); + Parent.Mutable asMutableCopy(); @Override - Parent.Immutable asImmutable(); + Parent.Immutable asImmutable(); interface Mutable extends Parent, CompositeValue.Mutable { @@ -124,13 +124,13 @@ interface Child extends CompositeValue { K valueKey(); @Override - Child.Mutable asMutable(); + Child.Mutable asMutable(); @Override - Child.Mutable asMutableCopy(); + Child.Mutable asMutableCopy(); @Override - Child.Immutable asImmutable(); + Child.Immutable asImmutable(); interface Mutable extends Child, CompositeValue.Mutable { @@ -179,13 +179,13 @@ default Child.Immutable asImmutable() { interface Mutable extends CompositeValue, ValueLike.Mutable { @Override - CompositeValue.Mutable asMutable(); + CompositeValue.Mutable asMutable(); @Override - CompositeValue.Mutable asMutableCopy(); + CompositeValue.Mutable asMutableCopy(); @Override - CompositeValue.Immutable asImmutable(); + CompositeValue.Immutable asImmutable(); } interface Immutable extends CompositeValue, ValueLike.Immutable { diff --git a/src/main/java/org/spongepowered/api/entity/Entity.java b/src/main/java/org/spongepowered/api/entity/Entity.java index d6d8a472d1f..c7d629d77ff 100644 --- a/src/main/java/org/spongepowered/api/entity/Entity.java +++ b/src/main/java/org/spongepowered/api/entity/Entity.java @@ -33,7 +33,6 @@ import org.spongepowered.api.data.value.ListValue; import org.spongepowered.api.data.value.SetValue; import org.spongepowered.api.data.value.Value; -import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.effect.VanishState; import org.spongepowered.api.event.cause.entity.damage.source.DamageSource; import org.spongepowered.api.projectile.source.EntityProjectileSource; diff --git a/src/main/java/org/spongepowered/api/entity/living/player/User.java b/src/main/java/org/spongepowered/api/entity/living/player/User.java index 6102a99a03d..50a704fc43c 100644 --- a/src/main/java/org/spongepowered/api/entity/living/player/User.java +++ b/src/main/java/org/spongepowered/api/entity/living/player/User.java @@ -31,7 +31,6 @@ import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.MapValue; import org.spongepowered.api.data.value.Value; -import org.spongepowered.api.data.value.ValueLike; import org.spongepowered.api.effect.VanishState; import org.spongepowered.api.entity.Entity; import org.spongepowered.api.entity.Tamer; From f24c1057596871aaa01c8acfd6ece02966566317 Mon Sep 17 00:00:00 2001 From: aromaa Date: Sat, 3 Oct 2026 02:17:26 +0300 Subject: [PATCH 4/4] Add CompositeKey --- .../spongepowered/api/data/CompositeKey.java | 46 ++++++++++++++++ .../spongepowered/api/data/DataHolder.java | 12 +++-- .../spongepowered/api/data/DataProvider.java | 53 ++++++++++++------- .../data/DirectionRelativeDataProvider.java | 20 +++---- .../java/org/spongepowered/api/data/Key.java | 38 ++++++------- .../api/data/value/CompositeValue.java | 41 +++++++++----- 6 files changed, 145 insertions(+), 65 deletions(-) create mode 100644 src/main/java/org/spongepowered/api/data/CompositeKey.java diff --git a/src/main/java/org/spongepowered/api/data/CompositeKey.java b/src/main/java/org/spongepowered/api/data/CompositeKey.java new file mode 100644 index 00000000000..8115c6222ba --- /dev/null +++ b/src/main/java/org/spongepowered/api/data/CompositeKey.java @@ -0,0 +1,46 @@ +/* + * This file is part of SpongeAPI, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * 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.spongepowered.api.data.value.CompositeValue; + +public interface CompositeKey> extends Key { + + @Override + CompositeKey> root(); + + Parent> parent(); + + Child> child(K valueKey); + + interface Parent> extends CompositeKey { + + } + + interface Child> extends CompositeKey { + + K valueKey(); + } +} diff --git a/src/main/java/org/spongepowered/api/data/DataHolder.java b/src/main/java/org/spongepowered/api/data/DataHolder.java index 78017085f3e..09c3856a9a5 100644 --- a/src/main/java/org/spongepowered/api/data/DataHolder.java +++ b/src/main/java/org/spongepowered/api/data/DataHolder.java @@ -108,7 +108,7 @@ default DataTransactionResult offer(Key> key, E value) { return this.offer(Value.immutableOf(key, value)); } - default DataTransactionResult offer(Key> key, K valueKey, E value) { + default DataTransactionResult offer(CompositeKey> key, K valueKey, E value) { return this.offer(CompositeValue.immutableChildOf(key, valueKey, value)); } @@ -290,7 +290,9 @@ default DataTransactionResult remove(ValueLike value) { */ DataTransactionResult remove(Key key); - DataTransactionResult remove(Key> key, K valueKey); + default DataTransactionResult remove(CompositeKey> key, K valueKey) { + return this.remove(key.child(valueKey)); + } /** * Attempts to remove the data associated with the provided {@link Key}. @@ -390,7 +392,7 @@ default Optional with(Key> key, E value) { return this.with(Value.immutableOf(key, value)); } - default Optional with(Key> key, K valueKey, E value) { + default Optional with(CompositeKey> key, K valueKey, E value) { return this.with(CompositeValue.immutableChildOf(key, valueKey, value)); } @@ -440,7 +442,9 @@ default Optional without(ValueLike value) { */ Optional without(Key key); - Optional without(Key> key, K valueKey); + default Optional without(CompositeKey> key, K valueKey) { + return this.without(key.child(valueKey)); + } /** * Creates a new {@link Immutable} without the provided {@link Key}. If the diff --git a/src/main/java/org/spongepowered/api/data/DataProvider.java b/src/main/java/org/spongepowered/api/data/DataProvider.java index b17fa51bb02..b4c19cfee31 100644 --- a/src/main/java/org/spongepowered/api/data/DataProvider.java +++ b/src/main/java/org/spongepowered/api/data/DataProvider.java @@ -25,10 +25,8 @@ package org.spongepowered.api.data; import io.leangen.geantyref.TypeToken; -import org.checkerframework.checker.units.qual.K; import org.spongepowered.api.Server; import org.spongepowered.api.Sponge; -import org.spongepowered.api.data.value.CompositeValue; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.data.value.ValueContainer; import org.spongepowered.api.data.value.ValueLike; @@ -63,7 +61,7 @@ static , E> ImmutableDataProviderBuilde * * @return The key */ - Key key(); + Key> key(); /** * Gets whether this provider will allow asynchronous access for retrieving @@ -74,9 +72,9 @@ static , E> ImmutableDataProviderBuilde * *

    A list of methods that are constrained by this check are: *

      - *
    • - {@link #get(DataHolder)}
    • + *
    • - {@link #get(DataHolder, Key)}
    • *
    • - {@link #offerValue(DataHolder.Mutable, ValueLike)}
    • - *
    • - {@link #remove(DataHolder.Mutable)}
    • + *
    • - {@link #remove(DataHolder.Mutable, Key)}
    • *
    * Conceptually, an immutable {@link DataHolder} will be ignorant of * asynchronous access, however, some cases may exist where attempting to @@ -100,13 +98,17 @@ static , E> ImmutableDataProviderBuilde * @param dataHolder The data holder * @return The value, if it's supported and exists */ + default Optional get(DataHolder dataHolder, Key key) { + return this.value(dataHolder, key).map(ValueLike::get); + } + default Optional get(DataHolder dataHolder) { - return this.value(dataHolder).map(ValueLike::get); + return this.get(dataHolder, this.key()); } /** * Gets a constructed {@link ValueLike} for the provided {@link DataHolder}. - * Much like {@link #get(DataHolder)}, this is generally considered the + * Much like {@link #get(DataHolder, Key)}, 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 @@ -117,7 +119,11 @@ default Optional get(DataHolder dataHolder) { * @param dataHolder The data holder to get the constructed value from * @return The value */ - Optional value(DataHolder dataHolder); + Optional value(DataHolder dataHolder, Key key); + + default Optional value(DataHolder dataHolder) { + return this.value(dataHolder, this.key()); + } /** * Gets whether this value provider is supported by the given {@link ValueContainer}. @@ -125,17 +131,29 @@ default Optional get(DataHolder dataHolder) { * @param dataHolder The data holder * @return Whether it's supported */ - boolean isSupported(DataHolder dataHolder); + boolean isSupported(DataHolder dataHolder, Key key); + + default boolean isSupported(DataHolder dataHolder) { + return this.isSupported(dataHolder, this.key()); + } - default boolean isSupported(final TypeToken dataHolder) { - return this.isSupported(dataHolder.getType()); + default boolean isSupported(final TypeToken dataHolder, Key key) { + return this.isSupported(dataHolder.getType(), key); } - boolean isSupported(Type dataHolder); + boolean isSupported(Type dataHolder, Key key); + + default boolean isSupported(Type dataHolder) { + return this.isSupported(dataHolder, this.key()); + } DataTransactionResult offerValue(DataHolder.Mutable dataHolder, V value); - DataTransactionResult remove(DataHolder.Mutable dataHolder); + DataTransactionResult remove(DataHolder.Mutable dataHolder, Key key); + + default DataTransactionResult remove(DataHolder.Mutable dataHolder) { + return this.remove(dataHolder, this.key()); + } > Optional withValue(I immutable, V value); @@ -147,12 +165,9 @@ default boolean isSupported(final TypeToken dataHolder) { * @param The type of the immutable value store * @return The new value store, if successful */ - > Optional without(I immutable); - - interface Composite, E> extends DataProvider { - - DataTransactionResult remove(DataHolder.Mutable dataHolder, K valueKey); + > Optional without(I immutable, Key key); - , K> Optional without(I immutable, K valueKey); + default > Optional without(I immutable) { + return this.without(immutable, this.key()); } } diff --git a/src/main/java/org/spongepowered/api/data/DirectionRelativeDataProvider.java b/src/main/java/org/spongepowered/api/data/DirectionRelativeDataProvider.java index 61a599d3094..f476db03779 100644 --- a/src/main/java/org/spongepowered/api/data/DirectionRelativeDataProvider.java +++ b/src/main/java/org/spongepowered/api/data/DirectionRelativeDataProvider.java @@ -33,18 +33,18 @@ public interface DirectionRelativeDataProvider, E> extends DataProvider { @Override - default Optional get(DataHolder dataHolder) { - return this.get(dataHolder, Direction.NONE); + default Optional get(DataHolder dataHolder, Key key) { + return this.get(dataHolder, key, Direction.NONE); } @Override - default Optional value(DataHolder dataHolder) { - return this.value(dataHolder, Direction.NONE); + default Optional value(DataHolder dataHolder, Key key) { + return this.value(dataHolder, key, Direction.NONE); } @Override - default boolean isSupported(DataHolder dataHolder) { - return this.isSupported(dataHolder, Direction.NONE); + default boolean isSupported(DataHolder dataHolder, Key key) { + return this.isSupported(dataHolder, key, Direction.NONE); } /** @@ -60,11 +60,11 @@ default boolean isSupported(DataHolder dataHolder) { * @param direction The related relative direction to the data provider * @return The value, if it's supported and exists */ - Optional get(DataHolder dataHolder, Direction direction); + Optional get(DataHolder dataHolder, Key key, Direction direction); /** * Gets a constructed {@link ValueLike} for the provided {@link DataHolder}. - * Much like {@link #get(DataHolder)}, this is generally considered the + * Much like {@link #get(DataHolder, Key)}, 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 @@ -76,7 +76,7 @@ default boolean isSupported(DataHolder dataHolder) { * @param direction The related relative direction to the data provider * @return The value */ - Optional value(DataHolder dataHolder, Direction direction); + Optional value(DataHolder dataHolder, Key key, Direction direction); /** * Gets whether this value provider is supported by the given {@link ValueContainer}. @@ -85,5 +85,5 @@ default boolean isSupported(DataHolder dataHolder) { * @param direction The related relative direction to the data provider * @return Whether it's supported */ - boolean isSupported(DataHolder dataHolder, Direction direction); + boolean isSupported(DataHolder dataHolder, Key key, Direction direction); } diff --git a/src/main/java/org/spongepowered/api/data/Key.java b/src/main/java/org/spongepowered/api/data/Key.java index 9ec49ded9f9..b9438443a02 100644 --- a/src/main/java/org/spongepowered/api/data/Key.java +++ b/src/main/java/org/spongepowered/api/data/Key.java @@ -86,7 +86,7 @@ public interface Key> extends ResourceKeyed { * @return The key builder */ @SuppressWarnings("unchecked") - static Builder builder() { + static Builder builder() { return Sponge.game().builderProvider().provide(Builder.class); } @@ -134,6 +134,8 @@ static Key> fromMap(final ResourceKey resourceKey, final C .build(); } + Key> root(); + /** * Gets the type of the {@link Value} this {@link Key} is representing. * @@ -183,7 +185,7 @@ static Key> fromMap(final ResourceKey resourceKey, final C */ void registerEvent(PluginContainer plugin, Class holderFilter, EventListener listener); - interface Builder> extends ResourceKeyedBuilder, Builder> { + interface Builder, E, V extends ValueLike> extends ResourceKeyedBuilder> { /** * Starter method for the builder, to be used immediately after @@ -201,7 +203,7 @@ interface Builder> extends ResourceKeyedBuilder * @param The base value type of the key * @return This builder, generified */ - > Builder type(TypeToken token); + > Builder, T, B> type(TypeToken token); /** * Starter method for the builder, to be used immediately after @@ -215,7 +217,7 @@ interface Builder> extends ResourceKeyedBuilder * @param The element type of the Key * @return This builder, generified */ - Builder> elementType(Class type); + Builder>, T, Value> elementType(Class type); /** * Starter method for the builder, to be used immediately after @@ -229,7 +231,7 @@ interface Builder> extends ResourceKeyedBuilder * @param The element type of the Key * @return This builder, generified */ - Builder> elementType(TypeToken type); + Builder>, T, Value> elementType(TypeToken type); /** * Starter method for the builder, to be used immediately after @@ -243,7 +245,7 @@ interface Builder> extends ResourceKeyedBuilder * @param The element type of the Key * @return This builder, generified */ - Builder, ListValue> listElementType(Class type); + Builder>, List, ListValue> listElementType(Class type); /** * Starter method for the builder, to be used immediately after @@ -257,7 +259,7 @@ interface Builder> extends ResourceKeyedBuilder * @param The element type of the Key * @return This builder, generified */ - Builder, ListValue> listElementType(TypeToken type); + Builder>, List, ListValue> listElementType(TypeToken type); /** * Starter method for the builder, to be used immediately after @@ -271,7 +273,7 @@ interface Builder> extends ResourceKeyedBuilder * @param The element type of the Key * @return This builder, generified */ - Builder, SetValue> setElementType(Class type); + Builder>, Set, SetValue> setElementType(Class type); /** * Starter method for the builder, to be used immediately after @@ -285,7 +287,7 @@ interface Builder> extends ResourceKeyedBuilder * @param The element type of the Key * @return This builder, generified */ - Builder, SetValue> setElementType(TypeToken type); + Builder>, Set, SetValue> setElementType(TypeToken type); /** * Starter method for the builder, to be used immediately after @@ -301,7 +303,7 @@ interface Builder> extends ResourceKeyedBuilder * @param The element type of the Key's value type * @return This builder, generified */ - Builder, MapValue> mapElementType(Class keyType, Class valueType); + Builder>, Map, MapValue> mapElementType(Class keyType, Class valueType); /** * Starter method for the builder, to be used immediately after @@ -317,7 +319,7 @@ interface Builder> extends ResourceKeyedBuilder * @param The element type of the Key's value type * @return This builder, generified */ - Builder, MapValue> mapElementType(TypeToken keyType, TypeToken valueType); + Builder>, Map, MapValue> mapElementType(TypeToken keyType, TypeToken valueType); /** * Starter method for the builder, to be used immediately after @@ -331,7 +333,7 @@ interface Builder> extends ResourceKeyedBuilder * @param The element type of the Key * @return This builder, generified */ - Builder, WeightedCollectionValue> weightedCollectionElementType(Class type); + Builder>, WeightedTable, WeightedCollectionValue> weightedCollectionElementType(Class type); /** * Starter method for the builder, to be used immediately after @@ -345,7 +347,7 @@ interface Builder> extends ResourceKeyedBuilder * @param The element type of the Key * @return This builder, generified */ - Builder, WeightedCollectionValue> weightedCollectionElementType(TypeToken type); + Builder>, WeightedTable, WeightedCollectionValue> weightedCollectionElementType(TypeToken type); /** * Starter method for the builder, to be used immediately after @@ -361,7 +363,7 @@ interface Builder> extends ResourceKeyedBuilder * @param The element type of the Key's element type * @return This builder, generified */ - Builder> compositeValueElementType(Class keyType, Class elementType); + Builder>, E, CompositeValue> compositeValueElementType(Class keyType, Class elementType); /** * Starter method for the builder, to be used immediately after @@ -377,7 +379,7 @@ interface Builder> extends ResourceKeyedBuilder * @param The element type of the Key's element type * @return This builder, generified */ - Builder> compositeValueElementType(TypeToken keyType, TypeToken elementType); + Builder>, E, CompositeValue> compositeValueElementType(TypeToken keyType, TypeToken elementType); /** * Sets the {@link Comparator} that can be used to compare @@ -389,7 +391,7 @@ interface Builder> extends ResourceKeyedBuilder * @param comparator The comparator * @return This builder, for chaining */ - Builder comparator(Comparator comparator); + Builder comparator(Comparator comparator); /** * Sets the includes tester {@link BiPredicate}. This predicate should @@ -402,7 +404,7 @@ interface Builder> extends ResourceKeyedBuilder * @see KeyValueMatcher.Operator#INCLUDES * @see KeyValueMatcher.Operator#EXCLUDES */ - Builder includesTester(BiPredicate predicate); + Builder includesTester(BiPredicate predicate); /** * Builds the {@link Key}. @@ -412,7 +414,7 @@ interface Builder> extends ResourceKeyedBuilder * {@link #type(TypeToken)}. */ @Override - Key build(); + K build(); } } diff --git a/src/main/java/org/spongepowered/api/data/value/CompositeValue.java b/src/main/java/org/spongepowered/api/data/value/CompositeValue.java index 60645eb85d5..aaec64389c9 100644 --- a/src/main/java/org/spongepowered/api/data/value/CompositeValue.java +++ b/src/main/java/org/spongepowered/api/data/value/CompositeValue.java @@ -25,7 +25,7 @@ package org.spongepowered.api.data.value; import org.spongepowered.api.Sponge; -import org.spongepowered.api.data.Key; +import org.spongepowered.api.data.CompositeKey; import java.util.Collection; import java.util.function.Function; @@ -33,21 +33,21 @@ public interface CompositeValue extends ValueLike { @Override - Key> key(); + CompositeKey> key(); - static CompositeValue.Parent.Mutable mutableOf(Key> key, ElementMergeFunction.Defaulted mergeFunction, Collection> children) { + static CompositeValue.Parent.Mutable mutableOf(CompositeKey> key, ElementMergeFunction.Defaulted mergeFunction, Collection> children) { return Sponge.game().factoryProvider().provide(CompositeValue.Factory.class).mutableOf(key, mergeFunction, children); } - static CompositeValue.Parent.Immutable immutableOf(Key> key, ElementMergeFunction.Defaulted mergeFunction, Collection> children) { + static CompositeValue.Parent.Immutable immutableOf(CompositeKey> key, ElementMergeFunction.Defaulted mergeFunction, Collection> children) { return Sponge.game().factoryProvider().provide(CompositeValue.Factory.class).immutableOf(key, mergeFunction, children); } - static Child.Mutable mutableChildOf(Key> key, K valueKey, E value) { + static Child.Mutable mutableChildOf(CompositeKey> key, K valueKey, E value) { return Sponge.game().factoryProvider().provide(CompositeValue.Factory.class).mutableChildOf(key, valueKey, value); } - static Child.Immutable immutableChildOf(Key> key, K valueKey, E value) { + static Child.Immutable immutableChildOf(CompositeKey> key, K valueKey, E value) { return Sponge.game().factoryProvider().provide(CompositeValue.Factory.class).immutableChildOf(key, valueKey, value); } @@ -62,6 +62,9 @@ static Child.Immutable immutableChildOf(Key extends CompositeValue { + @Override + CompositeKey.Parent> key(); + Collection> children(); @Override @@ -121,7 +124,8 @@ default Parent.Immutable asImmutable() { interface Child extends CompositeValue { - K valueKey(); + @Override + CompositeKey.Child> key(); @Override Child.Mutable asMutable(); @@ -179,13 +183,20 @@ default Child.Immutable asImmutable() { interface Mutable extends CompositeValue, ValueLike.Mutable { @Override - CompositeValue.Mutable asMutable(); + CompositeValue.Immutable asImmutable(); @Override - CompositeValue.Mutable asMutableCopy(); + default CompositeValue.Mutable asMutable() { + return this; + } @Override - CompositeValue.Immutable asImmutable(); + default CompositeValue.Mutable asMutableCopy() { + return this.copy(); + } + + @Override + CompositeValue.Mutable copy(); } interface Immutable extends CompositeValue, ValueLike.Immutable { @@ -206,12 +217,14 @@ default CompositeValue.Immutable asImmutable() { interface Factory { - CompositeValue.Parent.Mutable mutableOf(Key> key, ElementMergeFunction.Defaulted mergeFunction, Collection> children); + CompositeValue.Immutable of(CompositeKey> key, E value); + + CompositeValue.Parent.Mutable mutableOf(CompositeKey> key, ElementMergeFunction.Defaulted mergeFunction, Collection> children); - CompositeValue.Parent.Immutable immutableOf(Key> key, ElementMergeFunction.Defaulted mergeFunction, Collection> children); + CompositeValue.Parent.Immutable immutableOf(CompositeKey> key, ElementMergeFunction.Defaulted mergeFunction, Collection> children); - CompositeValue.Child.Mutable mutableChildOf(Key> key, K valueKey, E value); + CompositeValue.Child.Mutable mutableChildOf(CompositeKey> key, K valueKey, E value); - CompositeValue.Child.Immutable immutableChildOf(Key> key, K valueKey, E value); + CompositeValue.Child.Immutable immutableChildOf(CompositeKey> key, K valueKey, E value); } }