001/*
002 * JDrupes Builder
003 * Copyright (C) 2026 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.api;
020
021import java.util.HashSet;
022import java.util.Set;
023import java.util.function.Consumer;
024import java.util.function.Predicate;
025import java.util.stream.Stream;
026
027/// Helper class for implementing [Project#from].
028///
029@Deprecated
030public class ProviderStream {
031    private final Project project;
032    private Predicate<ResourceProvider> filter = _ -> true;
033    private final Set<ResourceProvider> excluded = new HashSet<>();
034    private final Set<Class<? extends ResourceProvider>> excludedTypes
035        = new HashSet<>();
036    private Consumer<ResourceProvider> providerLog = _ -> {
037    };
038
039    /// Initializes a new provider stream.
040    ///
041    /// @param project the project
042    ///
043    public ProviderStream(Project project) {
044        this.project = project;
045    }
046
047    public ProviderStream filter(Predicate<ResourceProvider> filter) {
048        this.filter = filter;
049        return this;
050    }
051
052    /// Exclude the given provider when requesting resources.
053    ///
054    /// @param provider the provider
055    /// @return the from helper
056    ///
057    public ProviderStream without(ResourceProvider provider) {
058        excluded.add(provider);
059        return this;
060    }
061
062    /// Exclude providers of the given type when requesting resources.
063    ///
064    /// @param providerType the provider type
065    /// @return the from helper
066    ///
067    public ProviderStream
068            without(Class<? extends ResourceProvider> providerType) {
069        excludedTypes.add(providerType);
070        return this;
071    }
072
073    /// Register a callback for logging the providers used.
074    ///
075    /// @param providerLog the provider log
076    /// @return the from helper
077    ///
078    public ProviderStream log(Consumer<ResourceProvider> providerLog) {
079        this.providerLog = providerLog;
080        return this;
081    }
082
083    /// Returns the requested resources using the context and providers 
084    /// passed to the record's constructor.
085    ///
086    /// @param <T> the generic type
087    /// @param request the request
088    /// @return the stream
089    ///
090    public <T extends Resource> Stream<T> get(ResourceQuery<T> request) {
091        return project.providers(request.uses())
092            .filter(filter::test)
093            .filter(p -> !excluded.contains(p))
094            .filter(p -> excludedTypes.stream()
095                .filter(t -> t.isAssignableFrom(p.getClass())).findAny()
096                .isEmpty())
097            .peek(providerLog::accept)
098            .flatMap(provider -> project.context().get(provider, request));
099    }
100}