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 * 043 * @since 1.3 044 */ 045public interface ComponentFactory { 046 047 /** 048 * Assigns standard properties from the given properties to the 049 * component. 050 * 051 * Currently, the only standard property of a component is its name. 052 * 053 * @param component the component 054 * @param properties the properties 055 * @return the optional 056 */ 057 static ComponentType setStandardProperties( 058 ComponentType component, Map<?, ?> properties) { 059 if (properties.containsKey("name")) { 060 Components.manager(component) 061 .setName((String) properties.get("name")); 062 } 063 return component; 064 } 065 066 /** 067 * Returns the type of the components created by this factory. 068 * 069 * @return the component type 070 */ 071 Class<? extends ComponentType> componentType(); 072 073 /** 074 * Creates a new component with its channel set to 075 * itself. 076 * 077 * @return the component 078 */ 079 default ComponentType create() { 080 return create(Channel.SELF); 081 } 082 083 /** 084 * Creates a new component with its channel set to the given 085 * channel. 086 * 087 * @param componentChannel the channel that the component's 088 * handlers listen on by default and that 089 * {@link Manager#fire(Event, Channel...)} sends the event to 090 * @return the component 091 */ 092 default ComponentType create(Channel componentChannel) { 093 return create(componentChannel, Collections.emptyMap()).get(); 094 } 095 096 /** 097 * Creates a new component with its channel set to the given 098 * channel using the given additional properties. If the requested 099 * properties or combination of properties cannot be provided by 100 * the component, the factory may return an empty {@link Optional}. 101 * 102 * @param componentChannel the channel that the component's 103 * handlers listen on by default and that 104 * {@link Manager#fire(Event, Channel...)} sends the event to 105 * @param properties additional properties for the creation of the 106 * component 107 * @return the component 108 */ 109 Optional<ComponentType> create( 110 Channel componentChannel, Map<?, ?> properties); 111}