001/*
002 * JGrapes Event Driven Framework
003 * Copyright (C) 2017-2018 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.Collections;
022import java.util.Map;
023import java.util.Optional;
024import java.util.ServiceLoader;
025
026/**
027 * A general purpose factory interface for components.
028 * 
029 * In some use cases, components may not be known at compile-time, but
030 * only made available at run-time. The usual pattern for this is to lookup
031 * a factory service using the {@link ServiceLoader} and create the
032 * components using the factory (or factories) found.
033 * 
034 * Because JGrapes components interact with their environment only
035 * through events, they do not provide special APIs and it is possible
036 * to define this generic factory service interface.
037 * Of course, lookup by the {@link ServiceLoader} will usually be done
038 * using a derived interface (or base class) that represents the special
039 * kind of components required and allows an invocation
040 * of {@link ServiceLoader#load(Class)} that returns a "filtered"
041 * set of factories.
042 */
043public interface ComponentFactory {
044
045    /**
046     * Returns the type of the components created by this factory.
047     * 
048     * @return the component type
049     */
050    Class<? extends ComponentType> componentType();
051
052    /**
053     * Creates a new component with its channel set to
054     * itself.
055     * 
056     * @return the component
057     */
058    default ComponentType create() {
059        return create(Channel.SELF);
060    }
061
062    /**
063     * Creates a new component with its channel set to the given 
064     * channel.
065     * 
066     * @param componentChannel the channel that the component's 
067     * handlers listen on by default and that 
068     * {@link Manager#fire(Event, Channel...)} sends the event to
069     * @return the component
070     */
071    default ComponentType create(Channel componentChannel) {
072        return create(componentChannel, Collections.emptyMap()).get();
073    }
074
075    /**
076     * Creates a new component with its channel set to the given 
077     * channel using the given additional properties. If the requested
078     * properties or combination of properties cannot be provided by
079     * the component, the factory may return an empty {@link Optional}. 
080     * 
081     * @param componentChannel the channel that the component's 
082     * handlers listen on by default and that 
083     * {@link Manager#fire(Event, Channel...)} sends the event to 
084     * @param properties additional properties for the creation of the
085     * component
086     * @return the component
087     */
088    Optional<ComponentType> create(
089            Channel componentChannel, Map<Object, Object> properties);
090}