Skip to content

Commit

Permalink
Create CollectionProperty parent type
Browse files Browse the repository at this point in the history
  • Loading branch information
ljacqu committed Oct 13, 2024
1 parent d7803f6 commit a38aec6
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 60 deletions.
71 changes: 71 additions & 0 deletions src/main/java/ch/jalu/configme/properties/CollectionProperty.java
Original file line number Diff line number Diff line change
@@ -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 <E> the type of the entries in the collection
* @param <C> the concrete collection type
* @see ListProperty
* @see SetProperty
*/
public class CollectionProperty<E, C extends Collection<E>> extends TypeBasedProperty<C> {

/**
* 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<C> 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 <E> the type of the entries in the collection
* @param <C> the concrete collection type
* @return a new collection property
*/
public static <E, C extends Collection<E>> @NotNull Property<C> of(@NotNull String path,
@NotNull PropertyType<E> entryType,
@NotNull Collector<E, ?, C> collector,
@NotNull C defaultValue) {
CollectionPropertyType<E, C> 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 <E> the type of the entries in the collection
* @param <C> the concrete collection type
* @return a new collection property
*/
@SafeVarargs
public static <E, C extends Collection<E>> @NotNull Property<C> of(@NotNull String path,
@NotNull PropertyType<E> entryType,
@NotNull Collector<E, ?, C> collector,
E @NotNull ... defaultValueEntries) {
CollectionPropertyType<E, C> collectionPropertyType = CollectionPropertyType.of(entryType, collector);
C defaultValue = Arrays.stream(defaultValueEntries).collect(collector);
return new CollectionProperty<>(path, collectionPropertyType, defaultValue);
}
}
16 changes: 8 additions & 8 deletions src/main/java/ch/jalu/configme/properties/EnumSetProperty.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 <E> the enum type
*/
public class EnumSetProperty<E extends Enum<E>> extends SetProperty<E> {
public class EnumSetProperty<E extends Enum<E>> extends CollectionProperty<E, EnumSet<E>> {

public EnumSetProperty(@NotNull String path, @NotNull Class<E> enumClass, @NotNull EnumSet<E> defaultValue) {
super(new EnumSetPropertyType(enumClass), path, defaultValue);
super(path, new EnumSetPropertyType<>(enumClass), defaultValue);
}

public EnumSetProperty(@NotNull String path, @NotNull Class<E> enumClass, @NotNull E @NotNull... defaultValue) {
super(new EnumSetPropertyType(enumClass), path, newEnumSet(enumClass, defaultValue));
@SafeVarargs
public EnumSetProperty(@NotNull String path, @NotNull Class<E> enumClass, @NotNull E @NotNull ... defaultValue) {
super(path, new EnumSetPropertyType<>(enumClass), newEnumSet(enumClass, defaultValue));
}

private static <E extends Enum<E>> @NotNull Set<E> newEnumSet(@NotNull Class<E> enumClass,
E @NotNull [] defaultValue) {
private static <E extends Enum<E>> @NotNull EnumSet<E> newEnumSet(@NotNull Class<E> enumClass,
E @NotNull [] defaultValue) {
EnumSet<E> enumSet = EnumSet.noneOf(enumClass);
enumSet.addAll(Arrays.asList(defaultValue));
return enumSet;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*
* @param <E> the type of the elements in the list
*/
public class ListProperty<E> extends TypeBasedProperty<List<E>> {
public class ListProperty<E> extends CollectionProperty<E, List<E>> {

/**
* Constructor.
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/ch/jalu/configme/properties/SetProperty.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*
* @param <E> the type of the elements in the set
*/
public class SetProperty<E> extends TypeBasedProperty<Set<E>> {
public class SetProperty<E> extends CollectionProperty<E, Set<E>> {

/**
* Constructor.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class StringSetProperty extends SetProperty<String> {
* @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);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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<Double, TreeSet<Double>> treeSetType =
CollectionPropertyType.of(NumberType.DOUBLE, Collectors.toCollection(TreeSet::new));
Property<TreeSet<Double>> sortedValuesProperty =
new CollectionProperty<>("values", treeSetType, new TreeSet<>());
given(reader.getObject("values")).willReturn(Arrays.asList(16, 9, 4));

// when
PropertyValue<TreeSet<Double>> 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<Vector<Double>> 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<Vector<Double>> 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<List<Long>> property1 = CollectionProperty.of("p1", NumberType.LONG, Collectors.toList());
Property<List<Long>> 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<List<Long>> value1 = property1.determineValue(reader);
PropertyValue<List<Long>> 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)));
}
}
18 changes: 7 additions & 11 deletions src/test/java/ch/jalu/configme/properties/EnumSetPropertyTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand All @@ -27,13 +27,11 @@ class EnumSetPropertyTest {
void shouldReturnEnumSetDefaultValue() {
// given
EnumSet<TestEnum> set = EnumSet.of(TestEnum.ENTRY_A);
EnumSetProperty<TestEnum> property =
new EnumSetProperty<>("enum.path", TestEnum.class, set);
given(reader.getObject(property.getPath()))
.willReturn(null);
EnumSetProperty<TestEnum> property = new EnumSetProperty<>("enum.path", TestEnum.class, set);
given(reader.getObject(property.getPath())).willReturn(null);

// when
PropertyValue<Set<TestEnum>> result = property.determineValue(reader);
PropertyValue<EnumSet<TestEnum>> result = property.determineValue(reader);

// then
assertThat(result, isErrorValueOf(EnumSet.of(TestEnum.ENTRY_A)));
Expand All @@ -43,15 +41,13 @@ void shouldReturnEnumSetDefaultValue() {
void shouldReturnEnumSetDefaultValueFromArray() {
// given
EnumSetProperty<TestEnum> 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<Set<TestEnum>> result = property.determineValue(reader);
EnumSet<TestEnum> 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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,17 @@
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;

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;
Expand All @@ -48,9 +39,9 @@ void copyConfigFile() {
void shouldLoadAndExportProperly() throws IOException {
// given
PropertyResource resource = new YamlFileResource(configFile);
Property<Set<TestEnum>> setProperty = new EnumSetProperty("sample.ratio.fields", Collections.emptySet());
EnumSetProperty<TestEnum> 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);
Expand All @@ -67,29 +58,4 @@ void shouldLoadAndExportProperly() throws IOException {
" - SECOND",
" - THIRD"));
}

private static final class EnumSetProperty extends BaseProperty<Set<TestEnum>> {

EnumSetProperty(String path, Set<TestEnum> defaultValue) {
super(path, defaultValue);
}

@Override
protected Set<TestEnum> 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<String> toExportValue(@NotNull Set<TestEnum> value) {
return value.stream()
.map(Enum::name)
.collect(Collectors.toCollection(LinkedHashSet::new));
}
}
}

0 comments on commit a38aec6

Please sign in to comment.