001/* 002 * JDrupes Builder 003 * Copyright (C) 2025 Michael N. Lipp 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <https://www.gnu.org/licenses/>. 017 */ 018 019package org.jdrupes.builder.core; 020 021import java.util.Map; 022import java.util.concurrent.ConcurrentHashMap; 023import java.util.function.Function; 024import org.jdrupes.builder.api.Resource; 025import org.jdrupes.builder.api.ResourceProvider; 026import org.jdrupes.builder.api.ResourceRequest; 027 028/// An implementation of a cache for [FutureStream]s. 029/// 030public class FutureStreamCache { 031 032 private final Map<Key<? extends Resource>, 033 FutureStream<? extends Resource>> cache = new ConcurrentHashMap<>(); 034 035 /// Provided resources are identified by the [ResourceProvider] 036 /// and the requested [Resource]. 037 /// 038 /// @param <T> the generic type 039 /// @param provider the provider 040 /// @param requested the requested resources 041 /// 042 public record Key<T extends Resource>(ResourceProvider provider, 043 ResourceRequest<T> requested) { 044 } 045 046 /// Instantiates a new future stream cache. 047 /// 048 /* default */ FutureStreamCache() { 049 // Make javadoc happy 050 } 051 052 /// Compute if absent. 053 /// 054 /// @param <T> the generic type 055 /// @param key the key 056 /// @param supplier the supplier 057 /// @return the future stream 058 /// 059 @SuppressWarnings("unchecked") 060 public <T extends Resource> FutureStream<T> computeIfAbsent(Key<T> key, 061 Function<Key<T>, FutureStream<T>> supplier) { 062 // This is actually type-safe, because the methods for entering 063 // key value pairs allow only values typed according to the casts 064 return (FutureStream<T>) cache.computeIfAbsent(key, 065 (Function<Key<? extends Resource>, 066 FutureStream<? extends Resource>>) (Object) supplier); 067 } 068 069}