From a38aec687730348abc4b73392a06fdd0f14a51dc Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sun, 13 Oct 2024 11:12:41 +0200 Subject: [PATCH] Create CollectionProperty parent type --- .../properties/CollectionProperty.java | 71 ++++++++++++++ .../configme/properties/EnumSetProperty.java | 16 ++-- .../configme/properties/ListProperty.java | 2 +- .../jalu/configme/properties/SetProperty.java | 2 +- .../properties/StringSetProperty.java | 2 +- .../properties/CollectionPropertyTest.java | 96 +++++++++++++++++++ .../properties/EnumSetPropertyTest.java | 18 ++-- .../resource/YamlSetPropertyExportTest.java | 42 +------- 8 files changed, 189 insertions(+), 60 deletions(-) create mode 100644 src/main/java/ch/jalu/configme/properties/CollectionProperty.java create mode 100644 src/test/java/ch/jalu/configme/properties/CollectionPropertyTest.java diff --git a/src/main/java/ch/jalu/configme/properties/CollectionProperty.java b/src/main/java/ch/jalu/configme/properties/CollectionProperty.java new file mode 100644 index 00000000..308acb1e --- /dev/null +++ b/src/main/java/ch/jalu/configme/properties/CollectionProperty.java @@ -0,0 +1,71 @@ +package ch.jalu.configme.properties; + +import ch.jalu.configme.properties.types.CollectionPropertyType; +import ch.jalu.configme.properties.types.PropertyType; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.Collection; +import java.util.stream.Collector; + +/** + * General {@link Collection} property. Used as common parent type for all collection properties. + * + * @param the type of the entries in the collection + * @param the concrete collection type + * @see ListProperty + * @see SetProperty + */ +public class CollectionProperty> extends TypeBasedProperty { + + /** + * Constructor. + * + * @param path the path of the property + * @param collectionType the property type + * @param defaultValue the default value of the property + */ + public CollectionProperty(@NotNull String path, @NotNull PropertyType collectionType, @NotNull C defaultValue) { + super(path, collectionType, defaultValue); + } + + /** + * Constructs a new collection property based on the given entry type and collector. + * + * @param path the path of the property + * @param entryType the collection type + * @param collector the collection type + * @param defaultValue the default value + * @param the type of the entries in the collection + * @param the concrete collection type + * @return a new collection property + */ + public static > @NotNull Property of(@NotNull String path, + @NotNull PropertyType entryType, + @NotNull Collector collector, + @NotNull C defaultValue) { + CollectionPropertyType collectionPropertyType = CollectionPropertyType.of(entryType, collector); + return new CollectionProperty<>(path, collectionPropertyType, defaultValue); + } + + /** + * Constructs a new collection property based on the given entry type and collector. + * + * @param path the path of the property + * @param entryType the collection type + * @param collector the collection type + * @param defaultValueEntries the entries that make up the default value + * @param the type of the entries in the collection + * @param the concrete collection type + * @return a new collection property + */ + @SafeVarargs + public static > @NotNull Property of(@NotNull String path, + @NotNull PropertyType entryType, + @NotNull Collector collector, + E @NotNull ... defaultValueEntries) { + CollectionPropertyType collectionPropertyType = CollectionPropertyType.of(entryType, collector); + C defaultValue = Arrays.stream(defaultValueEntries).collect(collector); + return new CollectionProperty<>(path, collectionPropertyType, defaultValue); + } +} diff --git a/src/main/java/ch/jalu/configme/properties/EnumSetProperty.java b/src/main/java/ch/jalu/configme/properties/EnumSetProperty.java index 9cc01c3e..42977619 100644 --- a/src/main/java/ch/jalu/configme/properties/EnumSetProperty.java +++ b/src/main/java/ch/jalu/configme/properties/EnumSetProperty.java @@ -5,25 +5,25 @@ import java.util.Arrays; import java.util.EnumSet; -import java.util.Set; /** - * EnumSet property. + * EnumSet property. The property's values are mutable and in declaration order of the enum. * * @param the enum type */ -public class EnumSetProperty> extends SetProperty { +public class EnumSetProperty> extends CollectionProperty> { public EnumSetProperty(@NotNull String path, @NotNull Class enumClass, @NotNull EnumSet defaultValue) { - super(new EnumSetPropertyType(enumClass), path, defaultValue); + super(path, new EnumSetPropertyType<>(enumClass), defaultValue); } - public EnumSetProperty(@NotNull String path, @NotNull Class enumClass, @NotNull E @NotNull... defaultValue) { - super(new EnumSetPropertyType(enumClass), path, newEnumSet(enumClass, defaultValue)); + @SafeVarargs + public EnumSetProperty(@NotNull String path, @NotNull Class enumClass, @NotNull E @NotNull ... defaultValue) { + super(path, new EnumSetPropertyType<>(enumClass), newEnumSet(enumClass, defaultValue)); } - private static > @NotNull Set newEnumSet(@NotNull Class enumClass, - E @NotNull [] defaultValue) { + private static > @NotNull EnumSet newEnumSet(@NotNull Class enumClass, + E @NotNull [] defaultValue) { EnumSet enumSet = EnumSet.noneOf(enumClass); enumSet.addAll(Arrays.asList(defaultValue)); return enumSet; diff --git a/src/main/java/ch/jalu/configme/properties/ListProperty.java b/src/main/java/ch/jalu/configme/properties/ListProperty.java index 2a8a78d4..d0c2b6fb 100644 --- a/src/main/java/ch/jalu/configme/properties/ListProperty.java +++ b/src/main/java/ch/jalu/configme/properties/ListProperty.java @@ -13,7 +13,7 @@ * * @param the type of the elements in the list */ -public class ListProperty extends TypeBasedProperty> { +public class ListProperty extends CollectionProperty> { /** * Constructor. diff --git a/src/main/java/ch/jalu/configme/properties/SetProperty.java b/src/main/java/ch/jalu/configme/properties/SetProperty.java index b99863bf..c8ab507f 100644 --- a/src/main/java/ch/jalu/configme/properties/SetProperty.java +++ b/src/main/java/ch/jalu/configme/properties/SetProperty.java @@ -17,7 +17,7 @@ * * @param the type of the elements in the set */ -public class SetProperty extends TypeBasedProperty> { +public class SetProperty extends CollectionProperty> { /** * Constructor. diff --git a/src/main/java/ch/jalu/configme/properties/StringSetProperty.java b/src/main/java/ch/jalu/configme/properties/StringSetProperty.java index 13733a24..5e2195a7 100644 --- a/src/main/java/ch/jalu/configme/properties/StringSetProperty.java +++ b/src/main/java/ch/jalu/configme/properties/StringSetProperty.java @@ -17,7 +17,7 @@ public class StringSetProperty extends SetProperty { * @param path the path of the property * @param defaultValue the values that make up the entries of the default set */ - public StringSetProperty(@NotNull String path, @NotNull String @NotNull... defaultValue) { + public StringSetProperty(@NotNull String path, @NotNull String @NotNull ... defaultValue) { super(path, StringType.STRING, defaultValue); } diff --git a/src/test/java/ch/jalu/configme/properties/CollectionPropertyTest.java b/src/test/java/ch/jalu/configme/properties/CollectionPropertyTest.java new file mode 100644 index 00000000..71e459eb --- /dev/null +++ b/src/test/java/ch/jalu/configme/properties/CollectionPropertyTest.java @@ -0,0 +1,96 @@ +package ch.jalu.configme.properties; + +import ch.jalu.configme.properties.convertresult.PropertyValue; +import ch.jalu.configme.properties.types.CollectionPropertyType; +import ch.jalu.configme.properties.types.NumberType; +import ch.jalu.configme.resource.PropertyReader; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.TreeSet; +import java.util.Vector; +import java.util.stream.Collectors; + +import static ch.jalu.configme.TestUtils.isErrorValueOf; +import static ch.jalu.configme.TestUtils.isValidValueOf; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.instanceOf; +import static org.mockito.BDDMockito.given; + +/** + * Test for {@link CollectionProperty}. + */ +@ExtendWith(MockitoExtension.class) +class CollectionPropertyTest { + + @Mock + private PropertyReader reader; + + @Test + void shouldUseGivenPropertyType() { + // given + CollectionPropertyType> treeSetType = + CollectionPropertyType.of(NumberType.DOUBLE, Collectors.toCollection(TreeSet::new)); + Property> sortedValuesProperty = + new CollectionProperty<>("values", treeSetType, new TreeSet<>()); + given(reader.getObject("values")).willReturn(Arrays.asList(16, 9, 4)); + + // when + PropertyValue> value = sortedValuesProperty.determineValue(reader); + + // then + assertThat(value.isValidInResource(), equalTo(true)); + assertThat(value.getValue(), instanceOf(TreeSet.class)); + assertThat(value.getValue(), contains(4.0, 9.0, 16.0)); + } + + @Test + void shouldCreatePropertyWithEntryTypeAndCollector() { + // given + Property> valuesProperty = CollectionProperty.of( + "values", + NumberType.DOUBLE, + Collectors.toCollection(Vector::new), + new Vector<>(Arrays.asList(3.0, 4.0))); + given(reader.getObject("values")).willReturn(Arrays.asList(1.0, 2.5, 4.0)); + + // when + PropertyValue> value = valuesProperty.determineValue(reader); + + // then + assertThat(valuesProperty.getPath(), equalTo("values")); + assertThat(valuesProperty.getDefaultValue(), instanceOf(Vector.class)); + assertThat(valuesProperty.getDefaultValue(), contains(3.0, 4.0)); + + assertThat(value.isValidInResource(), equalTo(true)); + assertThat(value.getValue(), instanceOf(Vector.class)); + assertThat(value.getValue(), contains(1.0, 2.5, 4.0)); + } + + @Test + void shouldCreatePropertyWithEntryTypeAndCollectorAndVarargsDefaultValue() { + // given + Property> property1 = CollectionProperty.of("p1", NumberType.LONG, Collectors.toList()); + Property> property2 = CollectionProperty.of("p2", NumberType.LONG, Collectors.toList(), 4L, 6L); + given(reader.getObject("p1")).willReturn("invalid"); + given(reader.getObject("p2")).willReturn(Arrays.asList("1", "2")); + + // when + PropertyValue> value1 = property1.determineValue(reader); + PropertyValue> value2 = property2.determineValue(reader); + + // then + assertThat(property1.getDefaultValue(), empty()); + assertThat(property2.getDefaultValue(), contains(4L, 6L)); + assertThat(value1, isErrorValueOf(Collections.emptyList())); // default value + assertThat(value2, isValidValueOf(Arrays.asList(1L, 2L))); + } +} diff --git a/src/test/java/ch/jalu/configme/properties/EnumSetPropertyTest.java b/src/test/java/ch/jalu/configme/properties/EnumSetPropertyTest.java index fab85e72..cebdbd27 100644 --- a/src/test/java/ch/jalu/configme/properties/EnumSetPropertyTest.java +++ b/src/test/java/ch/jalu/configme/properties/EnumSetPropertyTest.java @@ -8,10 +8,10 @@ import org.mockito.junit.jupiter.MockitoExtension; import java.util.EnumSet; -import java.util.Set; import static ch.jalu.configme.TestUtils.isErrorValueOf; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; import static org.mockito.BDDMockito.given; /** @@ -27,13 +27,11 @@ class EnumSetPropertyTest { void shouldReturnEnumSetDefaultValue() { // given EnumSet set = EnumSet.of(TestEnum.ENTRY_A); - EnumSetProperty property = - new EnumSetProperty<>("enum.path", TestEnum.class, set); - given(reader.getObject(property.getPath())) - .willReturn(null); + EnumSetProperty property = new EnumSetProperty<>("enum.path", TestEnum.class, set); + given(reader.getObject(property.getPath())).willReturn(null); // when - PropertyValue> result = property.determineValue(reader); + PropertyValue> result = property.determineValue(reader); // then assertThat(result, isErrorValueOf(EnumSet.of(TestEnum.ENTRY_A))); @@ -43,15 +41,13 @@ void shouldReturnEnumSetDefaultValue() { void shouldReturnEnumSetDefaultValueFromArray() { // given EnumSetProperty property = - new EnumSetProperty<>("enum.path", TestEnum.class, new TestEnum[]{TestEnum.ENTRY_B, TestEnum.ENTRY_C}); - given(reader.getObject(property.getPath())) - .willReturn(null); + new EnumSetProperty<>("enum.path", TestEnum.class, TestEnum.ENTRY_B, TestEnum.ENTRY_C); // when - PropertyValue> result = property.determineValue(reader); + EnumSet defaultValue = property.getDefaultValue(); // then - assertThat(result, isErrorValueOf(EnumSet.of(TestEnum.ENTRY_B, TestEnum.ENTRY_C))); + assertThat(defaultValue, contains(TestEnum.ENTRY_B, TestEnum.ENTRY_C)); } private enum TestEnum { diff --git a/src/test/java/ch/jalu/configme/resource/YamlSetPropertyExportTest.java b/src/test/java/ch/jalu/configme/resource/YamlSetPropertyExportTest.java index 4fc5473d..505cba7f 100644 --- a/src/test/java/ch/jalu/configme/resource/YamlSetPropertyExportTest.java +++ b/src/test/java/ch/jalu/configme/resource/YamlSetPropertyExportTest.java @@ -3,11 +3,8 @@ import ch.jalu.configme.TestUtils; import ch.jalu.configme.configurationdata.ConfigurationData; import ch.jalu.configme.configurationdata.ConfigurationDataBuilder; -import ch.jalu.configme.properties.BaseProperty; -import ch.jalu.configme.properties.Property; -import ch.jalu.configme.properties.convertresult.ConvertErrorRecorder; +import ch.jalu.configme.properties.EnumSetProperty; import ch.jalu.configme.samples.TestEnum; -import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -15,14 +12,8 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; +import java.util.EnumSet; -import static ch.jalu.configme.TestUtils.transform; import static java.util.Collections.singletonList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; @@ -48,9 +39,9 @@ void copyConfigFile() { void shouldLoadAndExportProperly() throws IOException { // given PropertyResource resource = new YamlFileResource(configFile); - Property> setProperty = new EnumSetProperty("sample.ratio.fields", Collections.emptySet()); + EnumSetProperty setProperty = new EnumSetProperty<>("sample.ratio.fields", TestEnum.class); ConfigurationData configurationData = ConfigurationDataBuilder.createConfiguration(singletonList(setProperty)); - configurationData.setValue(setProperty, new LinkedHashSet<>(Arrays.asList(TestEnum.FIRST, TestEnum.SECOND, TestEnum.THIRD))); + configurationData.setValue(setProperty, EnumSet.of(TestEnum.FIRST, TestEnum.SECOND, TestEnum.THIRD)); // when resource.exportProperties(configurationData); @@ -67,29 +58,4 @@ void shouldLoadAndExportProperly() throws IOException { " - SECOND", " - THIRD")); } - - private static final class EnumSetProperty extends BaseProperty> { - - EnumSetProperty(String path, Set defaultValue) { - super(path, defaultValue); - } - - @Override - protected Set getFromReader(@NotNull PropertyReader reader, - @NotNull ConvertErrorRecorder errorRecorder) { - List list = reader.getList(getPath()); - if (list == null) { - return null; - } - return new LinkedHashSet<>( - transform(list, v -> TestEnum.valueOf(v.toString()))); - } - - @Override - public Set toExportValue(@NotNull Set value) { - return value.stream() - .map(Enum::name) - .collect(Collectors.toCollection(LinkedHashSet::new)); - } - } }