Skip to content

Commit

Permalink
#19 Use valid flag from PropertyValue to determine OptionalProperty b…
Browse files Browse the repository at this point in the history
…ehavior
  • Loading branch information
ljacqu committed Aug 15, 2019
1 parent 08f0efb commit 1084f43
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 22 deletions.
41 changes: 31 additions & 10 deletions src/main/java/ch/jalu/configme/properties/OptionalProperty.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ch.jalu.configme.properties;

import ch.jalu.configme.configurationdata.PropertyValue;
import ch.jalu.configme.resource.PropertyReader;

import java.util.Optional;
Expand All @@ -10,32 +11,52 @@
* Wraps another property with an {@link Optional}: if a property is not present in the property resource,
* {@link Optional#empty} is returned.
*/
public class OptionalProperty<T> extends BaseProperty<Optional<T>> {
public class OptionalProperty<T> implements Property<Optional<T>> {

private final Property<T> baseProperty;
private final Optional<T> defaultValue;

public OptionalProperty(Property<T> baseProperty) {
super(baseProperty.getPath(), Optional.empty());
this.baseProperty = baseProperty;
this.defaultValue = Optional.empty();
}

public OptionalProperty(Property<T> baseProperty, T defaultValue) {
super(baseProperty.getPath(), Optional.of(defaultValue));
this.baseProperty = baseProperty;
this.defaultValue = Optional.of(defaultValue);
}

@Override
protected Optional<T> getFromReader(PropertyReader reader) {
return isBasePropertyPresent(reader)
? Optional.ofNullable(baseProperty.determineValue(reader).getValue())
public String getPath() {
return baseProperty.getPath();
}

@Override
public PropertyValue<Optional<T>> determineValue(PropertyReader reader) {
PropertyValue<T> basePropertyValue = baseProperty.determineValue(reader);
Optional<T> value = basePropertyValue.isValidInResource()
? Optional.ofNullable(basePropertyValue.getValue())
: Optional.empty();

// Propagate the false "valid" property if the reader has a value at the base property's path
// and the base property says it's invalid -> triggers a rewrite to get rid of the invalid value.
boolean isWrongInResource = !basePropertyValue.isValidInResource() && reader.contains(baseProperty.getPath());
return isWrongInResource
? PropertyValue.withValueRequiringRewrite(value)
: PropertyValue.withValidValue(value);
}

protected boolean isBasePropertyPresent(PropertyReader reader) {
if (baseProperty instanceof BaseProperty<?>) {
return ((BaseProperty<?>) baseProperty).getFromReader(reader) != null;
@Override
public Optional<T> getDefaultValue() {
return defaultValue;
}

@Override
public boolean isValidValue(Optional<T> value) {
if (value == null) {
return false;
}
return reader.contains(baseProperty.getPath());
return value.map(baseProperty::isValidValue).orElse(true);
}

@Override
Expand Down
80 changes: 68 additions & 12 deletions src/test/java/ch/jalu/configme/properties/OptionalPropertyTest.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
package ch.jalu.configme.properties;

import ch.jalu.configme.configurationdata.PropertyValue;
import ch.jalu.configme.resource.PropertyReader;
import ch.jalu.configme.samples.TestEnum;
import org.junit.Before;
import org.junit.Test;

import java.util.Optional;

import static ch.jalu.configme.TestUtils.isErrorValueOf;
import static ch.jalu.configme.TestUtils.isValidValueOf;
import static java.util.Optional.of;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.only;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

/**
Expand Down Expand Up @@ -39,14 +47,14 @@ public void shouldReturnPresentValues() {
OptionalProperty<TestEnum> enumProp = new OptionalProperty<>(new EnumProperty<>(TestEnum.class, "enum.path.test", TestEnum.SECOND));

// when
Optional<Boolean> boolResult = booleanProp.getFromReader(reader);
Optional<Integer> intResult = intProp.getFromReader(reader);
Optional<TestEnum> enumResult = enumProp.getFromReader(reader);
PropertyValue<Optional<Boolean>> boolResult = booleanProp.determineValue(reader);
PropertyValue<Optional<Integer>> intResult = intProp.determineValue(reader);
PropertyValue<Optional<TestEnum>> enumResult = enumProp.determineValue(reader);

// then
assertThat(boolResult, equalTo(of(true)));
assertThat(intResult, equalTo(of(27)));
assertThat(enumResult, equalTo(of(TestEnum.FOURTH)));
assertThat(boolResult, isValidValueOf(of(true)));
assertThat(intResult, isValidValueOf(of(27)));
assertThat(enumResult, isValidValueOf(of(TestEnum.FOURTH)));
}

@Test
Expand All @@ -57,14 +65,14 @@ public void shouldReturnEmptyOptional() {
OptionalProperty<TestEnum> enumProp = new OptionalProperty<>(new EnumProperty<>(TestEnum.class, "enum.path.wrong", TestEnum.SECOND));

// when
Optional<Boolean> boolResult = booleanProp.getFromReader(reader);
Optional<Integer> intResult = intProp.getFromReader(reader);
Optional<TestEnum> enumResult = enumProp.getFromReader(reader);
PropertyValue<Optional<Boolean>> boolResult = booleanProp.determineValue(reader);
PropertyValue<Optional<Integer>> intResult = intProp.determineValue(reader);
PropertyValue<Optional<TestEnum>> enumResult = enumProp.determineValue(reader);

// then
assertThat(boolResult, equalTo(Optional.empty()));
assertThat(intResult, equalTo(Optional.empty()));
assertThat(enumResult, equalTo(Optional.empty()));
assertThat(boolResult, isValidValueOf(Optional.empty()));
assertThat(intResult, isValidValueOf(Optional.empty()));
assertThat(enumResult, isValidValueOf(Optional.empty()));
}

@Test
Expand All @@ -78,4 +86,52 @@ public void shouldAllowToDefineDefaultValue() {
// then
assertThat(defaultValue, equalTo(Optional.of(42)));
}

@Test
public void shouldReturnValueWithInvalidFlagIfReturnedFromReader() {
// given
StringProperty baseProperty = spy(new StringProperty("the.path", "DEFAULT"));
doReturn(PropertyValue.withValueRequiringRewrite("this should be discarded")).when(baseProperty).determineValue(reader);
given(reader.contains("the.path")).willReturn(true);
OptionalProperty<String> optionalProperty = new OptionalProperty<>(baseProperty);

// when
PropertyValue<Optional<String>> value = optionalProperty.determineValue(reader);

// then
assertThat(value, isErrorValueOf(Optional.empty()));
}

@Test
public void shouldDelegateToBasePropertyAndHaveEmptyOptionalAsDefault() {
// given
StringProperty baseProperty = new StringProperty("some.path", "Def");
OptionalProperty<String> property = new OptionalProperty<>(baseProperty);

// when
Optional<String> defaultValue = property.getDefaultValue();
String path = property.getPath();

// then
assertThat(defaultValue, equalTo(Optional.empty()));
assertThat(path, equalTo("some.path"));
}

@Test
public void shouldValidateWithBasePropertyNullSafe() {
// given
StringProperty baseProperty = spy(new StringProperty("some.path", "Def"));
OptionalProperty<String> property = new OptionalProperty<>(baseProperty);

// when
boolean isEmptyValid = property.isValidValue(Optional.empty());
boolean isValueValid = property.isValidValue(Optional.of("foo"));
boolean isNullValid = property.isValidValue(null);

// then
assertThat(isEmptyValid, equalTo(true));
assertThat(isValueValid, equalTo(true));
assertThat(isNullValid, equalTo(false));
verify(baseProperty, only()).isValidValue("foo");
}
}

0 comments on commit 1084f43

Please sign in to comment.