
net.yetamine.lang.functional.Choice Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of net.yetamine.lang Show documentation
Show all versions of net.yetamine.lang Show documentation
Small extensions for the core Java language libraries.
The newest version!
/*
* Copyright 2016 Yetamine
*
* Licensed 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 net.yetamine.lang.functional;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
import net.yetamine.lang.exceptions.ThrowingOperation;
/**
* An alternative to {@link Optional} for the cases when the value may be right
* or wrong, but the value itself might be used anyway, e.g., for logging. The
* the value is marked as either right or wrong and this mark is
* carried with the value, so that the consumer of the value can decide if and
* how the value could be used.
*
* @param
* the type of the contained value
*
* @deprecated Planned for removal. Alternative and more powerful options, e.g.,
* {@code net.yetamine.sova.Adaptation} are available.
*/
@Deprecated
public final class Choice implements Supplier {
/** Shared instance for right {@code null}. */
private static final Choice> RIGHT_NULL = new Choice<>(null, true);
/** Shared instance for wrong {@code null}. */
private static final Choice> WRONG_NULL = new Choice<>(null, false);
/** Stored value. */
private final T value;
/** Flag marking right or wrong. */
private final boolean right;
/**
* Creates a new instance.
*
* @param o
* the value to store
* @param t
* the flag marking right or wrong
*/
private Choice(T o, boolean t) {
value = o;
right = t;
}
/**
* Narrows a widened type performing a safe type cast (thanks to the safe
* covariant changes for immutable types).
*
* @param
* the type of the represented value
* @param instance
* the instance to narrow
*
* @return the narrowed instance
*/
@SuppressWarnings("unchecked")
public static Choice narrow(Choice extends T> instance) {
return (Choice) instance;
}
/**
* Returns a representation of the given value.
*
* @param
* the type of the value
* @param value
* the value to store
* @param right
* {@code true} when the value shall be considered right
* and {@code false} otherwise
*
* @return a representation of the given value
*/
public static Choice of(T value, boolean right) {
return right ? right(value) : wrong(value);
}
/**
* Returns the shared instance representing a {@code null} as right.
*
* @param
* the type of the value
*
* @return the shared instance representing a {@code null} as right
*/
@SuppressWarnings("unchecked")
public static Choice rightNull() {
return (Choice) RIGHT_NULL;
}
/**
* Returns the shared instance representing a {@code null} as wrong.
*
* @param
* the type of the value
*
* @return the shared instance representing a {@code null} as wrong
*/
@SuppressWarnings("unchecked")
public static Choice wrongNull() {
return (Choice) WRONG_NULL;
}
/**
* Returns an instance representing the value as right.
*
* @param
* the type of the value
* @param o
* the value to represent
*
* @return an instance representing the value as right
*/
public static Choice right(T o) {
return (o != null) ? new Choice<>(o, true) : rightNull();
}
/**
* Returns an instance representing the value as wrong.
*
* @param
* the type of the value
* @param o
* the value to represent
*
* @return an instance representing the value as wrong
*/
public static Choice wrong(T o) {
return (o != null) ? new Choice<>(o, false) : wrongNull();
}
/**
* Returns a new instance representing the given value in the way that the
* {@code null} value is considered wrong, while a non-{@code null}
* value is considered right.
*
* @param
* the type of the value
* @param o
* the value to represent
*
* @return the new instance
*/
public static Choice nonNull(T o) {
return (o != null) ? new Choice<>(o, true) : wrongNull();
}
/**
* Returns a new instance using the given {@link Optional} in the way that a
* present value is considered right, while an absent value maps to
* wrong {@code null}.
*
* @param
* the type of the value
* @param optional
* the container of the value to represent. It must not be
* {@code null}.
*
* @return the new instance
*/
public static Choice from(Optional extends T> optional) {
return Choice.narrow(optional.map(Choice::right).orElseGet(Choice::wrongNull));
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return String.format("%s[%s]", right ? "Choice.right" : "Choice.wrong", value);
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Choice>) {
final Choice> o = (Choice>) obj;
return Objects.equals(value, o.value) && (right == o.right);
}
return false;
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return Objects.hash(value, right);
}
/**
* Returns the value of this choice.
*
* @return the value of this choice
*
* @see java.util.function.Supplier#get()
*/
public T get() {
return value;
}
/**
* Returns the value of this choice if {@link #isRight()}.
*
* @return the value of this choice
*
* @throws NoSuchElementException
* if this choice {@link #isWrong()}
*/
public T require() {
if (isRight()) {
return value;
}
throw new NoSuchElementException();
}
/**
* Returns the value of this choice if {@link #isRight()}.
*
* @param
* the type of the exception to throw
* @param e
* the supplier of the exception to throw if {@link #isWrong()}.
* It must not be {@code null}.
*
* @return the value of this choice
*
* @throws X
* if this choice {@link #isWrong()}
*/
public T require(Supplier extends X> e) throws X {
if (isRight()) {
return value;
}
throw e.get();
}
/**
* Creates a stream of this instance as the only element of the stream.
*
* @return a stream of this instance
*/
public Stream> stream() {
return Stream.of(this);
}
/**
* Returns an {@link Optional} representing a non-{@code null} right
* value.
*
* @return an {@link Optional} with the non-{@code null} right value,
* otherwise {@link Optional#empty()}
*/
public Optional optional() {
return isRight() ? Optional.ofNullable(value) : Optional.empty();
}
/**
* Returns a right case of the represented value.
*
* @return a right case of the represented value
*/
public Choice right() {
return isRight() ? this : right(value);
}
/**
* Returns a wrong case of the represented value.
*
* @return a wrong case of the represented value
*/
public Choice wrong() {
return isWrong() ? this : wrong(value);
}
/**
* Returns an instance representing the same value, but right turned
* into wrong and vice versa.
*
* @return an swapped instance
*/
public Choice swap() {
return isRight() ? wrong(value) : right(value);
}
/**
* Tests if the value represented by this choice is considered right.
*
* @return {@code true} if the represented value is considered right
*/
public boolean isRight() {
return right;
}
/**
* Tests if the value represented by this choice is considered wrong.
*
* @return {@code false} if the represented value is considered wrong
*/
public boolean isWrong() {
return !isRight();
}
/**
* Passes the represented value to the given consumer if {@link #isRight()}
* returns {@code true}.
*
* @param consumer
* the consumer to accept the value. It must not be {@code null}.
*
* @return this instance
*/
public Choice ifRight(Consumer super T> consumer) {
if (isRight()) {
consumer.accept(value);
}
return this;
}
/**
* Runs the given action if {@link #isRight()} returns {@code false}.
*
* @param consumer
* the consumer to accept the value. It must not be {@code null}.
*
* @return this instance
*/
public Choice ifWrong(Consumer super T> consumer) {
if (isWrong()) {
consumer.accept(value);
}
return this;
}
/**
* Maps the represented value if right, keeping the wrong value untouched.
*
* @param mapping
* the function to map the represented value when
* {@link #isRight()}. It must not be {@code null}.
*
* @return a new instance representing the mapped value
*/
public Choice mapRight(Function super T, ? extends T> mapping) {
return isRight() ? right(mapping.apply(value)) : this;
}
/**
* Maps the represented value if wrong, keeping the right value untouched.
*
* @param mapping
* the function to map the represented value when
* {@link #isWrong()}. It must not be {@code null}.
*
* @return a new instance representing the mapped value
*/
public Choice mapWrong(Function super T, ? extends T> mapping) {
return isRight() ? this : wrong(mapping.apply(value));
}
/**
* Maps the represented value.
*
* @param
* the type of the new value
* @param whenRight
* the function to map the represented value when
* {@link #isRight()}. It must not be {@code null}.
* @param whenWrong
* the function to map the represented value when
* {@link #isWrong()}. It must not be {@code null}.
*
* @return a new instance representing the mapped value
*/
public Choice map(Function super T, ? extends V> whenRight, Function super T, ? extends V> whenWrong) {
return isRight() ? right(whenRight.apply(value)) : wrong(whenWrong.apply(value));
}
/**
* Maps this instance.
*
* @param
* the type of the new represented value
* @param mapping
* the mapping function. It must not be {@code null} and it
* should not return {@code null}.
*
* @return the result of the mapping function
*/
public Choice map(Function super Choice, Choice> mapping) {
return mapping.apply(this);
}
/**
* Applies either action depending on {@link #isRight()} result.
*
* @param whenRight
* the consumer to accept the represented value if
* {@link #isRight()}. It must not be {@code null}.
* @param whenWrong
* the consumer to accept the represented value if
* {@link #isWrong()}. It must not be {@code null}.
*
* @return this instance
*/
public Choice use(Consumer super T> whenRight, Consumer super T> whenWrong) {
if (isRight()) {
whenRight.accept(value);
} else {
whenWrong.accept(value);
}
return this;
}
/**
* Applies the given action regardless of the actual right or
* wrong case.
*
* @param consumer
* the consumer to accept the represented value. It must not be
* {@code null}.
*
* @return this instance
*/
public Choice use(Consumer super T> consumer) {
consumer.accept(value);
return this;
}
/**
* Maps the represented value and returns it using the appropriate mapping
* function for the actual right or wrong case.
*
* @param
* the type of the new value
* @param whenRight
* the function to map the represented value when
* {@link #isRight()}. It must not be {@code null}.
* @param whenWrong
* the function to map the represented value when
* {@link #isWrong()}. It must not be {@code null}.
*
* @return the mapped value
*/
public V reconcile(Function super T, ? extends V> whenRight, Function super T, ? extends V> whenWrong) {
return isRight() ? whenRight.apply(value) : whenWrong.apply(value);
}
/**
* Maps the represented value and returns it using the given function
* regardless of the actual right or wrong case.
*
* @param
* the type of the new value
* @param function
* the function to map the represented value. It must not be
* {@code null}.
*
* @return the mapped value
*/
public V reconcile(Function super T, ? extends V> function) {
return function.apply(value);
}
/**
* Maps the represented value and returns it using the appropriate mapping
* function for the actual right or wrong case.
*
* @param
* the type of the new value
* @param
* the type of the exception that might be thrown
* @param whenRight
* the function to map the represented value when
* {@link #isRight()}. It must not be {@code null}.
* @param whenWrong
* the function to map the represented value when
* {@link #isWrong()}. It must not be {@code null}.
*
* @return the mapped value
*
* @throws X
* if an operation fails
*/
public V resolve(ThrowingOperation super T, ? extends V, ? extends X> whenRight, ThrowingOperation super T, ? extends V, ? extends X> whenWrong) throws X {
return isRight() ? whenRight.execute(value) : whenWrong.execute(value);
}
/**
* Maps the represented value and returns it using the given function
* regardless of the actual right or wrong case.
*
* @param
* the type of the new value
* @param
* the type of the exception that might be thrown
* @param function
* the function to map the represented value. It must not be
* {@code null}.
*
* @return the mapped value
*
* @throws X
* if an operation fails
*/
public V resolve(ThrowingOperation super T, ? extends V, ? extends X> function) throws X {
return function.execute(value);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy