001/* 002 * JGrapes Event Driven Framework 003 * Copyright (C) 2016-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.lang.reflect.Method; 022import java.util.Iterator; 023import java.util.List; 024import java.util.concurrent.ExecutorService; 025import java.util.stream.Stream; 026import org.jgrapes.core.events.Start; 027 028/** 029 * The interface that provides the methods for manipulating the 030 * component and the component's hierarchy and for firing events. 031 * Every component has access to a manager implementation that 032 * manages the component. 033 * 034 * The `Manager` for a component that extends from 035 * {@link Component} is provided by the base class itself. 036 * Components that only implement the {@link ComponentType} interface 037 * get their `Manager` assigned to their annotated 038 * attribute when they are attached to the component tree. 039 * 040 * @see ComponentType 041 */ 042public interface Manager extends Iterable<ComponentType> { 043 044 /** 045 * Sets the (optional) name of the component. 046 * 047 * @param name the name to set 048 * @return the component (for comfortable chaining) 049 */ 050 ComponentType setName(String name); 051 052 /** 053 * Returns the (optional) name of the component. 054 */ 055 String name(); 056 057 /** 058 * Returns the path of the component. The path is the concatenation 059 * of a slash ('/') and the component's name for all components 060 * from the root component to this component. If a component 061 * doesn't have a name set, the simple name of its class 062 * (see {@link Class#getSimpleName()}) is used instead. 063 */ 064 String componentPath(); 065 066 /** 067 * Detaches the component managed by this manager (with its children, 068 * if any) from the component tree that it currently belongs to. 069 * <P> 070 * This method results in a <code>IllegalStateException</code> if 071 * called on a tree before a {@link org.jgrapes.core.events.Start} 072 * event has been fired on 073 * it. The Reason for this restriction is that distributing 074 * buffered events between the two separated trees cannot easily be 075 * defined in an intuitive way. 076 * 077 * @return the component (for comfortable chaining) 078 * @throws IllegalStateException if invoked before a <code>Start</code> 079 * event 080 */ 081 ComponentType detach(); 082 083 /** 084 * Attaches the given component node (or complete tree) as a child 085 * to the component managed by this manager. The node or tree may not 086 * have been started. 087 * 088 * If a component (or component tree) is attached to an already 089 * started tree, a {@link Start} event is automatically fired 090 * with the list of components from the attached subtree as 091 * channels. This guarantees that every component gets a 092 * {@link Start} event once. For efficiency, it is therefore 093 * preferable to build a subtree first and attach it, instead 094 * of attaching the nodes to the existing tree one by one. 095 * 096 * @param <T> the component node's type 097 * @param child the component to add 098 * @return the added component (for comfortable chaining) 099 */ 100 <T extends ComponentType> T attach(T child); 101 102 /** 103 * Returns the component managed by this manager. 104 * 105 * @return the component 106 */ 107 ComponentType component(); 108 109 /** 110 * Returns the child components of the component managed by 111 * this manager as unmodifiable list. 112 * 113 * @return the child components 114 */ 115 List<ComponentType> children(); 116 117 /** 118 * Returns the parent of the component managed by this manager. 119 * 120 * @return the parent component or <code>null</code> if the 121 * component is not registered with another component 122 */ 123 ComponentType parent(); 124 125 /** 126 * Returns the root of the tree the component 127 * managed by this manager belongs to. 128 * 129 * @return the root 130 */ 131 ComponentType root(); 132 133 /** 134 * Returns the channel of the component managed by this manager. 135 * 136 * @return the channel that the component's 137 * handlers listen on by default and that 138 * {@link Manager#fire(Event, Channel...)} sends the event to 139 */ 140 Channel channel(); 141 142 /** 143 * Fires the given event on the given channel. If no channels are 144 * specified as parameters, the event is fired on the event's 145 * channel (see {@link Event#channels()}). If the event doesn't 146 * specify channels either, the event is fired on the 147 * channel of the component managed by this manager 148 * (see {@link #channel()}). 149 * <P> 150 * If an event is fired inside an event handler, it is added to the 151 * {@link EventPipeline} that has invoked the handler. If an event is fired 152 * by some other thread (not associated with a pipeline), a new pipeline 153 * is created for handling the event (and any events triggered by it). 154 * 155 * @param <T> the result type of the event 156 * @param event the event to fire 157 * @param channels the channels to fire the event on 158 * @return the event (for easy chaining) 159 */ 160 <T> Event<T> fire(Event<T> event, Channel... channels); 161 162 /** 163 * Adds a handler for the given method with the given scope 164 * and priority. 165 * 166 * This method is usually not invoked directly. Rather, a {@link 167 * org.jgrapes.core.annotation.HandlerDefinition.Evaluator} provides 168 * `add(...)` methods that evaluate the required `method` and 169 * `scope` arguments from easier to provide arguments and then 170 * call this method. 171 * 172 * @param method the method to invoke 173 * @param scope the handler scope to be used for matching events 174 * @param priority the priority of the handler 175 * @see org.jgrapes.core.annotation.Handler.Evaluator#add 176 */ 177 void addHandler(Method method, HandlerScope scope, int priority); 178 179 /** 180 * Returns the pipeline used when firing an event. 181 * 182 * @return the event pipeline 183 * @see #fire(Event, Channel...) 184 */ 185 EventPipeline activeEventPipeline(); 186 187 /** 188 * Return a new {@link EventPipeline} that processes the added events 189 * using a thread from a thread pool. 190 * 191 * @return the pipeline 192 */ 193 EventPipeline newEventPipeline(); 194 195 /** 196 * Return a new {@link EventPipeline} that processes the added events 197 * using threads from the given executor service. 198 * 199 * @param executorService the executor service 200 * @return the pipeline 201 */ 202 EventPipeline newEventPipeline(ExecutorService executorService); 203 204 /** 205 * Register the managed component as a running generator. 206 */ 207 void registerAsGenerator(); 208 209 /** 210 * Unregister the managed component as a running generator. 211 */ 212 void unregisterAsGenerator(); 213 214 /** 215 * Returns an iterator that visits the components of the 216 * component subtree that has this node as root. 217 * 218 * @return the iterator 219 */ 220 @Override 221 Iterator<ComponentType> iterator(); 222 223 /** 224 * Returns the components visited when traversing the 225 * tree that starts with this component. 226 * 227 * @return the stream 228 */ 229 @SuppressWarnings("PMD.DataflowAnomalyAnalysis") 230 default Stream<ComponentType> stream() { 231 Stream.Builder<ComponentType> res = Stream.builder(); 232 for (ComponentType c : this) { 233 res.accept(c); 234 } 235 return res.build(); 236 } 237}