001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- 002 * 003 * Copyright © 2024–2025 microBean™. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 006 * the License. You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 011 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 012 * specific language governing permissions and limitations under the License. 013 */ 014package org.microbean.bean; 015 016import java.util.List; 017import java.util.Objects; 018 019import java.util.concurrent.ConcurrentHashMap; 020 021import java.util.function.BiFunction; 022import java.util.function.Function; 023 024/** 025 * A {@linkplain FunctionalInterface functional interface} whose implementations can <dfn>reduce</dfn> an unspecified 026 * notional collection of elements to a single element according to some <em>criteria</em>. 027 * 028 * <p>This interface is related to, but should not be confused with, the {@link Reducer} interface, implementations of 029 * which can be used to build {@link Reducible} instances.</p> 030 * 031 * @param <C> the type of criteria 032 * 033 * @param <T> the element type 034 * 035 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a> 036 * 037 * @see #reduce(Object) 038 * 039 * @see Reducer 040 * 041 * @deprecated This interface is not really needed and is tentatively deprecated. 042 */ 043@Deprecated(since = "0.0.18") 044@FunctionalInterface 045public interface Reducible<C, T> { 046 047 048 /* 049 * Instance methods. 050 */ 051 052 053 /** 054 * Given a criteria object, which may be {@code null}, returns an object that represents the <em>reduction</em> of a 055 * notional collection of objects. 056 * 057 * <p>Most {@link Reducible} implementations will return determinate values from invocations of this method, but there 058 * is no requirement to do so.</p> 059 * 060 * @param criteria the criteria; may be {@code null} to indicate no criteria 061 * 062 * @return a single object, or {@code null} 063 * 064 * @exception ReductionException if reduction could not occur or if an error occurs 065 */ 066 public T reduce(final C criteria); 067 068 069 /* 070 * Static methods. 071 */ 072 073 074 /** 075 * Calls the {@link #of(Selectable, Reducer, BiFunction)} method with the supplied {@code selectable}, the supplied {@code r}, and a reference to the {@link Reducer#fail(List, Object)} method, 076 * and returns the result. 077 * 078 * @param <C> the criteria type 079 * 080 * @param <E> the element type 081 * 082 * @param selectable a {@link Selectable}; must not be {@code null} 083 * 084 * @param r a {@link Reducer}; must not be {@code null} 085 * 086 * @return a {@link Reducible}; never {@code null} 087 * 088 * @exception NullPointerException if {@code selectable} or {@code r} is {@code null} 089 * 090 * @see #of(Selectable, Reducer, BiFunction) 091 * 092 * @see Reducer#fail(List, Object) 093 */ 094 public static <C, E> Reducible<C, E> of(final Selectable<C, E> selectable, 095 final Reducer<C, E> r) { 096 return of(selectable, r, Reducer::fail); 097 } 098 099 /** 100 * Returns a {@link Reducible} implementation that uses the supplied {@link Reducer} for its reduction operations. 101 * 102 * @param <C> the criteria type 103 * 104 * @param <E> the element type 105 * 106 * @param selectable a {@link Selectable}; must not be {@code null} 107 * 108 * @param r a {@link Reducer}; must not be {@code null} 109 * 110 * @param failureHandler a {@link BiFunction} serving as the supplied {@link Reducer}'s <dfn>failure handler</dfn>; 111 * must not be {@code null} 112 * 113 * @return a {@link Reducible}; never {@code null} 114 * 115 * @exception NullPointerException if any argument is {@code null} 116 * 117 * @see Reducer 118 */ 119 public static <C, E> Reducible<C, E> of(final Selectable<C, E> selectable, 120 final Reducer<C, E> r, 121 final BiFunction<? super List<? extends E>, ? super C, ? extends E> failureHandler) { 122 Objects.requireNonNull(selectable, "selectable"); 123 Objects.requireNonNull(r, "r"); 124 final BiFunction<? super List<? extends E>, ? super C, ? extends E> fh = Objects.requireNonNull(failureHandler, "failureHandler"); 125 return c -> r.reduce(selectable.select(c), c, fh); 126 } 127 128 /** 129 * Calls the {@link #ofCaching(Selectable, Reducer, BiFunction)} method with the supplied {@code selectable}, the 130 * supplied {@code r}, the supplied {@code failureHandler}, and a reference to the {@link Reducer#fail(List, Object)} 131 * method, and returns its result. 132 * 133 * @param <C> the criteria type 134 * 135 * @param <E> the element type 136 * 137 * @param selectable a {@link Selectable}; must not be {@code null} 138 * 139 * @param r a {@link Reducer}; must not be {@code null} 140 * 141 * @return a {@link Reducible}; never {@code null} 142 * 143 * @exception NullPointerException if any argument is {@code null} 144 * 145 * @see #ofCaching(Selectable, Reducer, BiFunction) 146 */ 147 public static <C, E> Reducible<C, E> ofCaching(final Selectable<C, E> selectable, final Reducer<C, E> r) { 148 return ofCaching(selectable, r, Reducer::fail); 149 } 150 151 /** 152 * Calls the {@link #ofCaching(Selectable, Reducer, BiFunction, BiFunction)} method with the supplied {@code 153 * selectable}, the supplied {@code r}, the supplied {@code fh}, and a reference to the {@link 154 * ConcurrentHashMap#computeIfAbsent(Object, java.util.function.Function) computeIfAbsent(Object, Function)} method of 155 * a new {@link ConcurrentHashMap}, and returns its result. 156 * 157 * @param <C> the criteria type 158 * 159 * @param <E> the element type 160 * 161 * @param selectable a {@link Selectable}; must not be {@code null} 162 * 163 * @param r a {@link Reducer}; must not be {@code null} 164 * 165 * @param fh a {@link BiFunction} serving as the supplied {@link Reducer}'s <dfn>failure handler</dfn>; 166 * must not be {@code null} 167 * 168 * @return a {@link Reducible}; never {@code null} 169 * 170 * @exception NullPointerException if any argument is {@code null} 171 * 172 * @see #ofCaching(Selectable, Reducer, BiFunction, BiFunction) 173 */ 174 public static <C, E> Reducible<C, E> ofCaching(final Selectable<C, E> selectable, 175 final Reducer<C, E> r, 176 final BiFunction<? super List<? extends E>, ? super C, ? extends E> fh) { 177 return ofCaching(selectable, r, fh, new ConcurrentHashMap<C, E>()::computeIfAbsent); 178 } 179 180 /** 181 * Returns a {@link Reducible} implementation that uses the supplied {@link Reducer} for its reduction operations and 182 * the supplied {@code computeIfAbsent} {@link BiFunction} for its caching implementation. 183 * 184 * @param <C> the criteria type 185 * 186 * @param <E> the element type 187 * 188 * @param selectable a {@link Selectable}; must not be {@code null} 189 * 190 * @param r a {@link Reducer}; must not be {@code null} 191 * 192 * @param fh a {@link BiFunction} serving as the supplied {@link Reducer}'s <dfn>failure handler</dfn>; must not be 193 * {@code null} 194 * 195 * @param cache a {@link BiFunction} with the same semantics as the {@link 196 * java.util.Map#computeIfAbsent(Object, java.util.function.Function)} method; must not be {@code null} 197 * 198 * @return a {@link Reducible}; never {@code null} 199 * 200 * @exception NullPointerException if any argument is {@code null} 201 * 202 * @see #of(Selectable, Reducer, BiFunction) 203 * 204 * @see java.util.Map#computeIfAbsent(Object, java.util.function.Function) 205 */ 206 public static <C, E> Reducible<C, E> ofCaching(final Selectable<C, E> selectable, 207 final Reducer<C, E> r, 208 final BiFunction<? super List<? extends E>, ? super C, ? extends E> fh, 209 final BiFunction<? super C, Function<C, E>, ? extends E> cache) { 210 Objects.requireNonNull(cache, "cache"); 211 final Reducible<C, E> reducible = of(selectable, r, fh); 212 return c -> cache.apply(c, reducible::reduce); 213 } 214 215}