package com.algocrafts.selenium; import java.util.Objects; import java.util.function.Function; import java.util.function.Predicate; public interface Locator<T1, T2> extends Function<T1, T2> { /** * locate the result on the search context. * * @param where the search context * @return located result */ T2 locate(T1 where); /** * Returns a composed function that first applies the {@code before} * function to its input, and then applies this function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param <V> the type of input to the {@code before} function, and to the * composed function * @param before the function to apply before this function is applied * @return a composed function that first applies the {@code before} * function and then applies this function * @throws NullPointerException if before is null * * @see #andThen(Function) */ default <V> Locator<V, T2> compose(Function<? super V, ? extends T1> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } /** * Returns a composed function that first applies this function to * its input, and then applies the {@code after} function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param after the function to locate after this function is applied * @return a composed function that first applies this function and then * applies the {@code after} function * @throws NullPointerException if after is null * @see #compose(Function) */ default <V> Locator<T1, V> andThen(Locator<? super T2, ? extends V> after) { Objects.requireNonNull(after); return (T1 t) -> after.locate(locate(t)); } /** * Returns a composed predicate that represents a short-circuiting logical * AND of this predicate and a locator. When evaluating the composed * predicate, locating the element first and test the element with the Predicate. * <p> * <p>Any exceptions thrown during evaluation of either predicate are relayed * to the caller; if evaluation of this predicate throws an exception, the * {@code other} predicate will not be evaluated. * * @param other a predicate that will be tested with this after locating * element using this locator * @return a predicate that represents the {@code other} predicate for * the element located by this * @throws NullPointerException if other is null */ default Predicate<T1> and(Predicate<T2> other) { Objects.requireNonNull(other); return (T1 t) -> other.test(locate(t)); } /** * Applies this function to the given argument by calling * the locate method of this locator. * * @param t the function argument * @return the function result */ @Override default T2 apply(T1 t) { return locate(t); } }