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