|
|
@@ -21,8 +21,7 @@ import java.util.function.Supplier;
|
|
|
* Class contains functional implementation of switch-case construct.
|
|
|
* Useful if we want to switch over values, which are not constant at compile-time.
|
|
|
*
|
|
|
- * @author mwx1031516 [mariusz.czarnowski@huawei.com]
|
|
|
- * @since 2021-03-14
|
|
|
+ * @author Ranides Atterwim {@literal <ranides@gmail.com>}
|
|
|
*/
|
|
|
@UtilityClass
|
|
|
public class Branch {
|
|
|
@@ -45,63 +44,304 @@ public class Branch {
|
|
|
.withParam(new TypeToken<Optional<?>>() {})
|
|
|
.function();
|
|
|
|
|
|
+ /**
|
|
|
+ * Creates new selector, which will return first non-null value.
|
|
|
+ *
|
|
|
+ * @return new selector
|
|
|
+ */
|
|
|
public static BranchSelector<Object> first() {
|
|
|
return new BranchChain<>(true, null);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Creates new selector, which stores specified input value, and examines all conditions declared
|
|
|
+ * in chain, to return result matching specified input.
|
|
|
+ *
|
|
|
+ * Effectively, it is more flexible, functional version of switch-case construct.
|
|
|
+ *
|
|
|
+ * @param value input
|
|
|
+ * @return new selector
|
|
|
+ */
|
|
|
public static BranchSelector<Object> first(Object value) {
|
|
|
return new BranchChain<>(true, value);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Creates new selector, which will return first non-null value.
|
|
|
+ * It checks if there is exactly one unambiguous non-null result
|
|
|
+ *
|
|
|
+ * @return new selector
|
|
|
+ */
|
|
|
public static BranchSelector<Object> single() {
|
|
|
return new BranchChain<>(false, null);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Creates new selector, which stores specified input value, and examines all conditions declared
|
|
|
+ * in chain, to return result matching specified input.
|
|
|
+ * It checks if there is exactly one unambiguous non-null result
|
|
|
+ *
|
|
|
+ * Effectively, it is more flexible, non-ambiguous, functional version of switch-case construct.
|
|
|
+ *
|
|
|
+ * @param value input
|
|
|
+ * @return new selector
|
|
|
+ */
|
|
|
public static BranchSelector<Object> single(Object value) {
|
|
|
return new BranchChain<>(false, value);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Branch selector, which allows you to declare switch-case construct by chaining conditions one by one.
|
|
|
+ * Every branch selector is initially constructed by one of factory methods, which defines basic contract.
|
|
|
+ * Then, you can add specific clauses into it, and finally query for result.
|
|
|
+ *
|
|
|
+ * Please note, that every clause can declare narrowed result type, although if you shouldn't abuse
|
|
|
+ * this functionality, because class cast exception will be thrown at the end. Ideally, you should use
|
|
|
+ * this functionality to define result type in first clause and then do not narrow it in next clauses.
|
|
|
+ *
|
|
|
+ * @param <F> type of result
|
|
|
+ */
|
|
|
public interface BranchSelector<F> {
|
|
|
+ /**
|
|
|
+ * Returns computed result as Optional, possibly empty if none condition is met.
|
|
|
+ *
|
|
|
+ * @return optional result
|
|
|
+ */
|
|
|
Optional<F> optional();
|
|
|
|
|
|
+ /**
|
|
|
+ * Returns computed result.
|
|
|
+ * If there is no result, it throws exception.
|
|
|
+ *
|
|
|
+ * @return result
|
|
|
+ * @throws NoSuchElementException if there is no result
|
|
|
+ */
|
|
|
F get();
|
|
|
|
|
|
+ /**
|
|
|
+ * Returns computed result.
|
|
|
+ * Returns default value, if there is no result.
|
|
|
+ *
|
|
|
+ * @param other default result
|
|
|
+ * @return result
|
|
|
+ */
|
|
|
F orElse(F other);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: return const value if input has specified type.
|
|
|
+ *
|
|
|
+ * @param type type of input
|
|
|
+ * @param result result
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> forType(Class<T> type, R result);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: return const value if input has specified type.
|
|
|
+ *
|
|
|
+ * @param type type of input
|
|
|
+ * @param result result
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> forType(IClass<T> type, R result);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: return const value if input has specified value.
|
|
|
+ *
|
|
|
+ * @param condition expected value
|
|
|
+ * @param result result
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> forValue(T condition, R result);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: return const value if input has specified value generated by supplier.
|
|
|
+ * Expected value is computed lazily.
|
|
|
+ *
|
|
|
+ * @param condition expected value
|
|
|
+ * @param result result
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> forExpression(Supplier<T> condition, R result);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: return const value if input has specified value.
|
|
|
+ *
|
|
|
+ * @param condition expected value
|
|
|
+ * @param result result
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> forOptional(Optional<T> condition, R result);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: return generated value if input has value generated by specified supplier.
|
|
|
+ * Result is computed lazily.
|
|
|
+ *
|
|
|
+ * @param condition expected value
|
|
|
+ * @param supplier result
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> forOptional(Supplier<Optional<T>> condition, R supplier);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: return generated value if input has specified type.
|
|
|
+ * Expected value is computed lazily.
|
|
|
+ * Result is computed lazily.
|
|
|
+ *
|
|
|
+ * @param type type
|
|
|
+ * @param supplier supplier
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> computeForType(Class<T> type, Supplier<R> supplier);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: return generated value if input has specified type.
|
|
|
+ * Result is computed lazily.
|
|
|
+ *
|
|
|
+ * @param type type
|
|
|
+ * @param supplier supplier
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> computeForType(IClass<T> type, Supplier<R> supplier);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: return generated value if input has specified value.
|
|
|
+ * Result is computed lazily.
|
|
|
+ *
|
|
|
+ * @param condition condition
|
|
|
+ * @param supplier supplier
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> computeForValue(T condition, Supplier<R> supplier);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: return generated value if input has the same value as generated by specified supplier.
|
|
|
+ * Expected value is computed lazily.
|
|
|
+ * Result is computed lazily.
|
|
|
+ *
|
|
|
+ * @param condition condition
|
|
|
+ * @param supplier supplier
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> computeForExpression(Supplier<T> condition, Supplier<R> supplier);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: return generated value if input has specified value.
|
|
|
+ * Result is computed lazily.
|
|
|
+ *
|
|
|
+ * @param condition condition
|
|
|
+ * @param supplier supplier
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> computeForOptional(Optional<T> condition, Supplier<R> supplier);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: return generated value if input has the same value as generated by specified supplier.
|
|
|
+ * Expected value is computed lazily.
|
|
|
+ * Result is computed lazily.
|
|
|
+ *
|
|
|
+ * @param condition condition
|
|
|
+ * @param supplier supplier
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> computeForOptional(Supplier<Optional<T>> condition, Supplier<R> supplier);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: map input into result if input has specified type
|
|
|
+ * Result is computed lazily.
|
|
|
+ *
|
|
|
+ * @param type type
|
|
|
+ * @param function function
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> mapType(Class<T> type, Function<T, R> function);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: map input into result if input has specified type
|
|
|
+ * Result is computed lazily.
|
|
|
+ *
|
|
|
+ * @param type type
|
|
|
+ * @param function function
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> mapType(IClass<T> type, Function<T, R> function);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: map input into result if input has specified value
|
|
|
+ * Result is computed lazily.
|
|
|
+ *
|
|
|
+ * @param condition condition
|
|
|
+ * @param function function
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> mapValue(T condition, Function<T, R> function);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: map input into result if input has the same value as generated by specified supplier.
|
|
|
+ * Expected value is computed lazily.
|
|
|
+ * Result is computed lazily.
|
|
|
+ *
|
|
|
+ * @param condition condition
|
|
|
+ * @param function function
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> mapExpression(Supplier<T> condition, Function<T, R> function);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: map input into result if input has specified value
|
|
|
+ * Result is computed lazily.
|
|
|
+ *
|
|
|
+ * @param condition condition
|
|
|
+ * @param function function
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> mapOptional(Optional<T> condition, Function<T, R> function);
|
|
|
|
|
|
+ /**
|
|
|
+ * BRANCH CLAUSE: map input into result if input has the same value as generated by specified supplier.
|
|
|
+ * Expected value is computed lazily.
|
|
|
+ * Result is computed lazily.
|
|
|
+ *
|
|
|
+ * @param condition condition
|
|
|
+ * @param function function
|
|
|
+ * @param <T> type of input
|
|
|
+ * @param <R> type of result, every clause can narrow it
|
|
|
+ * @return selector
|
|
|
+ */
|
|
|
<T, R extends F> BranchSelector<R> mapOptional(Supplier<Optional<T>> condition, Function<T, R> function);
|
|
|
}
|
|
|
|