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}