Skip to content

#443 Create CollectionProperty parent type #453

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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));
}
}
}