JAMES-1781 Adding support for PatchedValue PatchedValue have 3 states :
- KEEP : no modification will be taken - MODIFY : Set to non null value - REMOVE : Set property to Null Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/b7d41df7 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/b7d41df7 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/b7d41df7 Branch: refs/heads/master Commit: b7d41df7ead490ee344e2c765ac53a94270dfb06 Parents: a8fe12f Author: Benoit Tellier <[email protected]> Authored: Mon Jun 27 11:00:05 2016 +0700 Committer: Benoit Tellier <[email protected]> Committed: Thu Sep 29 12:48:14 2016 +0200 ---------------------------------------------------------------------- .../org/apache/james/util/PatchedValue.java | 125 +++++++++++ .../org/apache/james/util/PatchedValueTest.java | 220 +++++++++++++++++++ 2 files changed, 345 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/b7d41df7/server/container/util-java8/src/main/java/org/apache/james/util/PatchedValue.java ---------------------------------------------------------------------- diff --git a/server/container/util-java8/src/main/java/org/apache/james/util/PatchedValue.java b/server/container/util-java8/src/main/java/org/apache/james/util/PatchedValue.java new file mode 100644 index 0000000..438e27a --- /dev/null +++ b/server/container/util-java8/src/main/java/org/apache/james/util/PatchedValue.java @@ -0,0 +1,125 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.util; + +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Function; + +import com.google.common.base.Preconditions; + +public class PatchedValue<T> { + + private enum State { + KEEP, + REMOVE, + MODIFY + } + + public static <T> PatchedValue<T> modifyTo(T value) { + Preconditions.checkNotNull(value); + return new PatchedValue<>(value, State.MODIFY); + } + + public static <T> PatchedValue<T> ofNullable(T value) { + return ofOptional(Optional.ofNullable(value)); + } + + public static <T> PatchedValue<T> ofOptional(Optional<T> value) { + Preconditions.checkNotNull(value); + return value.map(PatchedValue::modifyTo) + .orElse(PatchedValue.remove()); + } + + public static <T> PatchedValue<T> remove() { + return new PatchedValue<>(null, State.REMOVE); + } + + public static <T> PatchedValue<T> keep() { + return new PatchedValue<>(null, State.KEEP); + } + + private final T value; + private final State state; + + private PatchedValue(T value, State state) { + this.value = value; + this.state = state; + } + + public boolean isRemoved() { + return state == State.REMOVE; + } + + public boolean isModified() { + return state == State.MODIFY; + } + + public boolean isKept() { + return state == State.KEEP; + } + + public <S> Optional<S> mapNotKeptToOptional(Function<Optional<T>, S> updateTransformation) { + if (isKept()) { + return Optional.empty(); + } + return Optional.of(updateTransformation.apply(Optional.ofNullable(value))); + } + + public T get() { + if (isModified()) { + return value; + } else { + throw new NoSuchElementException(); + } + } + + public Optional<T> notKeptOrElse(Optional<T> replacement) { + if (isKept()) { + return replacement; + } + return Optional.ofNullable(value); + } + + public Optional<T> toOptional() { + return Optional.ofNullable(value); + } + + public T getOrElse(T replacement) { + return toOptional().orElse(replacement); + } + + @Override + public boolean equals(Object o) { + if (o instanceof PatchedValue) { + PatchedValue<?> that = (PatchedValue<?>) o; + return Objects.equals(this.value, that.value) && + Objects.equals(this.state, that.state); + } else { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hash(value, state); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/b7d41df7/server/container/util-java8/src/test/java/org/apache/james/util/PatchedValueTest.java ---------------------------------------------------------------------- diff --git a/server/container/util-java8/src/test/java/org/apache/james/util/PatchedValueTest.java b/server/container/util-java8/src/test/java/org/apache/james/util/PatchedValueTest.java new file mode 100644 index 0000000..4929f6d --- /dev/null +++ b/server/container/util-java8/src/test/java/org/apache/james/util/PatchedValueTest.java @@ -0,0 +1,220 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy modifyTo the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.util; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.NoSuchElementException; +import java.util.Optional; + +import org.junit.Test; + +public class PatchedValueTest { + + public static final int REPLACEMENT_VALUE = 24; + public static final Optional<Integer> REPLACEMENT = Optional.of(REPLACEMENT_VALUE); + public static final int VALUE = 12; + public static final Optional<Integer> OPTIONAL_OF_VALUE = Optional.of(VALUE); + + @Test + public void keepShouldProduceKeptValues() { + assertThat(PatchedValue.<Integer>keep().isKept()).isTrue(); + } + + @Test + public void keepShouldThrowOnGet() { + assertThatThrownBy(() -> PatchedValue.<Integer>keep().get()).isInstanceOf(NoSuchElementException.class); + } + + @Test + public void keepShouldNotBeModified() { + assertThat(PatchedValue.<Integer>keep().isModified()).isFalse(); + } + + @Test + public void keepShouldNotBeRemoved() { + assertThat(PatchedValue.<Integer>keep().isRemoved()).isFalse(); + } + + @Test + public void removeShouldNotBeKept() { + assertThat(PatchedValue.<Integer>remove().isKept()).isFalse(); + } + + @Test + public void removeShouldBeRemoved() { + assertThat(PatchedValue.<Integer>remove().isRemoved()).isTrue(); + } + + @Test + public void removedShouldNotBeModified() { + assertThat(PatchedValue.<Integer>remove().isModified()).isFalse(); + } + + @Test + public void removeShouldThrowOnGet() { + assertThatThrownBy(() -> PatchedValue.<Integer>remove().get()).isInstanceOf(NoSuchElementException.class); + } + + @Test + public void ofNullableShouldBeEquivalentToRemoveWhenNullParameter() { + assertThat(PatchedValue.<Integer>ofNullable(null)).isEqualTo(PatchedValue.<Integer>remove()); + } + + @Test + public void ofNullableShouldBeEquivalentToModifyWhenNonNullParameter() { + assertThat(PatchedValue.ofNullable(VALUE)).isEqualTo(PatchedValue.modifyTo(VALUE)); + } + + @Test + public void modifyToShouldNotBeKept() { + assertThat(PatchedValue.modifyTo(VALUE).isKept()).isFalse(); + } + + @Test + public void modifyToShouldNotBeRemoved() { + assertThat(PatchedValue.modifyTo(VALUE).isRemoved()).isFalse(); + } + + @Test + public void modifyToShouldBeModified() { + assertThat(PatchedValue.modifyTo(VALUE).isModified()).isTrue(); + } + + @Test + public void modifyToShouldThrowOnNullValue() { + assertThatThrownBy(() -> PatchedValue.modifyTo(null)).isInstanceOf(NullPointerException.class); + } + + @Test + public void modifyToShouldBeRetrievedByGet() { + assertThat(PatchedValue.modifyTo(VALUE).get()).isEqualTo(VALUE); + } + + @Test + public void ofOptionalShouldThrowOnNullValue() { + assertThatThrownBy(() -> PatchedValue.ofOptional(null)).isInstanceOf(NullPointerException.class); + } + + @Test + public void ofOptionalShouldBeEquivalentToModifyToWhenPresent() { + assertThat(PatchedValue.ofOptional(OPTIONAL_OF_VALUE)).isEqualTo(PatchedValue.modifyTo(VALUE)); + } + + @Test + public void ofOptionalShouldBeEquivalentToRemoveWhenEmpty() { + assertThat(PatchedValue.ofOptional(Optional.empty())).isEqualTo(PatchedValue.remove()); + } + + @Test + public void notKeptOrElseShouldReturnElseWhenKept() { + assertThat(PatchedValue.<Integer>keep().notKeptOrElse(REPLACEMENT)).isEqualTo(REPLACEMENT); + } + + @Test + public void notKeptOrElseShouldReturnEmptyWhenRemoved() { + assertThat(PatchedValue.<Integer>remove().notKeptOrElse(REPLACEMENT)).isEqualTo(Optional.empty()); + } + + @Test + public void notKeptOrElseShouldReturnOptionalWhenModified() { + assertThat(PatchedValue.modifyTo(VALUE).notKeptOrElse(REPLACEMENT)).isEqualTo(OPTIONAL_OF_VALUE); + } + + @Test + public void toOptionalShouldReturnElseWhenKept() { + assertThat(PatchedValue.<Integer>keep().toOptional()).isEqualTo(Optional.empty()); + } + + @Test + public void toOptionalShouldReturnEmptyWhenRemoved() { + assertThat(PatchedValue.<Integer>remove().toOptional()).isEqualTo(Optional.empty()); + } + + @Test + public void toOptionalShouldReturnOptionalWhenModified() { + assertThat(PatchedValue.modifyTo(VALUE).toOptional()).isEqualTo(OPTIONAL_OF_VALUE); + } + + @Test + public void getOrElseShouldReturnReplacementWhenKept() { + assertThat(PatchedValue.<Integer>keep().getOrElse(REPLACEMENT_VALUE)).isEqualTo(REPLACEMENT_VALUE); + } + + @Test + public void getOrElseShouldReturnReplacementWhenRemoved() { + assertThat(PatchedValue.<Integer>remove().getOrElse(REPLACEMENT_VALUE)).isEqualTo(REPLACEMENT_VALUE); + } + + @Test + public void getOrElseShouldReturnValueWhenPresent() { + assertThat(PatchedValue.modifyTo(VALUE).getOrElse(REPLACEMENT_VALUE)).isEqualTo(VALUE); + } + + @Test + public void getOrElseShouldReturnNullWhenKeptAndNullSpecified() { + assertThat(PatchedValue.<Integer>keep().getOrElse(null)).isNull(); + } + + @Test + public void getOrElseShouldReturnNullWhenRemovedAndNullSpecified() { + assertThat(PatchedValue.<Integer>remove().getOrElse(null)).isNull(); + } + + @Test + public void getOrElseShouldReturnValueWhenPresentAndNullSpecified() { + assertThat(PatchedValue.modifyTo(VALUE).getOrElse(null)).isEqualTo(VALUE); + } + + @Test + public void mapNotKeptToValueShouldPreserveKept() { + assertThat( + PatchedValue.<Integer>keep() + .mapNotKeptToOptional(optional -> optional.map(i -> i + 1).orElse(REPLACEMENT_VALUE))) + .isEmpty(); + } + + @Test + public void mapNotKeptToValueShouldTransformOf() { + assertThat( + PatchedValue.modifyTo(VALUE) + .mapNotKeptToOptional(optional -> optional.map(i -> i + 1).orElse(REPLACEMENT_VALUE))) + .contains(VALUE + 1); + } + + @Test + public void mapNotKeptToValueShouldTransformRemoved() { + assertThat( + PatchedValue.<Integer>remove() + .mapNotKeptToOptional(optional -> optional.map(i -> i + 1).orElse(REPLACEMENT_VALUE))) + .contains(REPLACEMENT_VALUE); + } + + @Test + public void mapNotKeptToValueShouldThrowWhenNull() { + assertThatThrownBy( + () -> PatchedValue.modifyTo(12) + .mapNotKeptToOptional(any -> null) + .isPresent()) + .isInstanceOf(NullPointerException.class); + } + +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
