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}