![JAR search and dependency download from the Maven repository](/logo.png)
org.microbean.bean.Selectable Maven / Gradle / Ivy
Show all versions of microbean-bean Show documentation
/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
*
* Copyright © 2024 microBean™.
*
* 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 org.microbean.bean;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
/**
* A notional list of elements from which sublists may be selected according to some criteria.
*
* @param the type of criteria
*
* @param the type of the elements
*
* @author Laird Nelson
*/
@FunctionalInterface
public interface Selectable {
/**
* Selects and returns an immutable {@link List} representing a sublist of this {@link Selectable}'s
* elements, as mediated by the supplied criteria.
*
* Implementations of this method must be idempotent and must return a determinate value.
*
* Implementations of this method must not return {@code null}.
*
* Implementations of this method should not call {@link #list()}, since that method is typically implemented in
* terms of this one.
*
* @param criteria the criteria to use; may be {@code null}
*
* @return an immutable sublist of this {@link Selectable}'s elements; never {@code null}
*
* @see #list()
*/
// Filters this thing according to the supplied criteria, producing a List.
// List not Stream to permit caching
// List not Collection so equals() is well-defined
// List is unmodifiable and is always valid for the supplied criteria (unenforceable)
// C and not Predicate because equality semantics for Predicate are not well-defined (caching again)
public List select(final C criteria);
/**
* Returns an immutable {@link List} of all of this {@link Selectable}'s elements.
*
* Implementations of this method must be idempotent and must return a determinate value.
*
* Implementations of this method must not return {@code null}.
*
* The default implementation of this method calls the {@link #select(Object)} method with {@code null} as the sole
* argument.
*
* @return an immutable {@link List} of all of this {@link Selectable}'s elements; never {@code null}
*
* @see #select(Object)
*/
public default List list() {
return this.select(null);
}
/*
* Static methods.
*/
/**
* Returns a {@link Selectable} using the supplied {@link Collection} as its elements, and the supplied {@link
* BiFunction} as its selector function.
*
* There is no guarantee that this method will return new {@link Selectable} instances.
*
* The {@link Selectable} instances returned by this method may or may not cache their selections.
*
* The selector function must select a sublist from the supplied {@link Collection} as mediated by the supplied
* criteria. The selector function must additionally be idempotent and must produce a determinate value when given the
* same arguments.
*
* No validation of these semantics of the selector function is performed.
*
* @param the type of criteria
*
* @param the type of the elements
*
* @param collection a {@link Collection} of elements from which sublists may be selected; must not be {@code null}
*
* @param f the selector function; must not be {@code null}
*
* @return a {@link Selectable}; never {@code null}
*
* @exception NullPointerException if either {@code collection} or {@code f} is {@code null}
*/
@SuppressWarnings("unchecked")
public static Selectable of(final Collection extends E> collection, final BiFunction super E, ? super C, ? extends Boolean> f) {
Objects.requireNonNull(f, "f");
return collection.isEmpty() ? of() : c -> (List)collection.stream()
.filter(e -> f.apply(e, c))
.toList();
}
/**
* Returns a {@link Selectable} whose {@link #select(Object)} method always returns an {@linkplain List#of() empty
* {@code List}}.
*
* @param the type of criteria
*
* @param the type of the elements
*
* @return a {@link Selectable} whose {@link #select(Object)} method always returns an {@linkplain List#of() empty
* {@code List}}; never {@code null}
*/
public static Selectable of() {
return c -> List.of();
}
/**
* Returns a {@link Selectable} using the supplied {@link Collection} as its elements, and the supplied {@link
* BiFunction} as its selector function.
*
* There is no guarantee that this method will return new {@link Selectable} instances.
*
* The {@link Selectable} instances returned by this method will cache their selections.
*
* The selector function must select a sublist from the supplied {@link Collection} as mediated by the supplied
* criteria. The selector function must additionally be idempotent and must produce a determinate value when given the
* same arguments.
*
* No validation of these semantics of the selector function is performed.
*
* @param the type of criteria
*
* @param the type of the elements
*
* @param collection a {@link Collection} of elements from which sublists may be selected; must not be {@code null}
*
* @param f the selector function; must not be {@code null}
*
* @return a {@link Selectable}; never {@code null}
*
* @exception NullPointerException if either {@code collection} or {@code f} is {@code null}
*/
@SuppressWarnings("unchecked")
public static Selectable ofCaching(final Collection extends E> collection, final BiFunction super E, ? super C, ? extends Boolean> f) {
Objects.requireNonNull(f, "f");
if (collection.isEmpty()) {
return c -> List.of();
}
final Map> m = new ConcurrentHashMap<>();
return c ->
(List)m.computeIfAbsent(c, fc -> collection.stream()
.filter(e -> f.apply(e, fc))
.toList());
}
}