001/*
002 * JGrapes Event Driven Framework
003 * Copyright (C) 2017-2026 Michael N. Lipp
004 * 
005 * This program is free software; you can redistribute it and/or modify it 
006 * under the terms of the GNU Affero General Public License as published by 
007 * the Free Software Foundation; either version 3 of the License, or 
008 * (at your option) any later version.
009 * 
010 * This program is distributed in the hope that it will be useful, but 
011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
013 * for more details.
014 * 
015 * You should have received a copy of the GNU Affero General Public License along 
016 * with this program; if not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jgrapes.core;
020
021import java.util.Arrays;
022import java.util.Collections;
023import java.util.List;
024import java.util.Map;
025import java.util.ServiceLoader;
026import java.util.function.Function;
027
028/**
029 * A component that collects all component factory services of 
030 * a given type and uses each to create one or more components
031 * that are then attached to the component collector instance.
032 * 
033 * Effectively, the component collector leverages the 
034 * mechanism provided by the service loader to determine
035 * the component tree that is built eventually at 
036 * "link time".
037 * 
038 * @deprecated This class has been moved to 
039 * {@link org.jgrapes.util.ComponentCollector}.
040 * 
041 * @param <F> the component factory type
042 */
043@Deprecated(since = "1.3")
044public class ComponentCollector<F extends ComponentFactory>
045        extends Component {
046
047    private static final List<Map<Object, Object>> SINGLE_DEFAULT
048        = Arrays.asList(Collections.emptyMap());
049
050    /**
051     * Creates a new collector that collects the factories of the given 
052     * type and uses each to create one or more instances with this 
053     * component's (the component collector's) channel. 
054     * 
055     * Before instances are created, the `matcher` function is 
056     * invoked with the name of the class of the component
057     * to be created as argument. The list of maps returned is
058     * used to create components, passing each element in the list
059     * as parameter to {@link ComponentFactory#create(Channel, Map)}.
060     * 
061     * @param factoryClass the factory class
062     * @param componentChannel this component's channel
063     * @param matcher the matcher function
064     */
065    @Deprecated
066    @SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
067    public ComponentCollector(
068            Class<F> factoryClass, Channel componentChannel,
069            Function<String, List<Map<Object, Object>>> matcher) {
070        super(componentChannel);
071        ServiceLoader<F> serviceLoader = ServiceLoader.load(factoryClass);
072        for (F factory : serviceLoader) {
073            List<Map<Object, Object>> configs = matcher.apply(
074                factory.componentType().getName());
075            for (Map<Object, Object> config : configs) {
076                factory.create(channel(), config).ifPresent(this::attach);
077            }
078        }
079    }
080
081    /**
082     * Utility constructor that uses each factory to create a single
083     * instance, using an empty map as properties.
084     * 
085     * @param factoryClass the factory class
086     * @param componentChannel this component's channel
087     */
088    @Deprecated
089    public ComponentCollector(
090            Class<F> factoryClass, Channel componentChannel) {
091        this(factoryClass, componentChannel, type -> SINGLE_DEFAULT);
092    }
093}