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.util.concurrent.Callable;
022import java.util.concurrent.ExecutorService;
023import java.util.concurrent.Future;
024import org.jgrapes.core.Components.IdInfoProvider;
025
026/**
027 * An interface that describes a queue of events that are sent to the components
028 * of the associated tree. Any events fired by the components while handling
029 * an event from the pipeline are added at the end of the pipeline.
030 * 
031 * An event pipeline is run by a single thread from an executor service. 
032 * Adding several events to the same pipeline therefore ensures that they 
033 * are executed in sequence.
034 */
035public interface EventPipeline extends IdInfoProvider {
036
037    /**
038     * Add an event to be sent to components listening for such events on
039     * the given channels to the end of the queue. If no channels are
040     * specified as parameters, the event is fired on the event's 
041     * channel (see {@link Event#channels()}). If the event doesn't
042     * specify channels either, the channel depends on how the
043     * event pipeline was obtained. Event pipelines obtained from a
044     * component's manager use the component's channel as fall back.
045     * 
046     * @param <T> the event's type
047     * @param event the event to process
048     * @param channels the channels that the event was fired on
049     * @return the event (for easy chaining)
050     */
051    <T extends Event<?>> T fire(T event, Channel... channels);
052
053    /**
054     * Allow only the given source pipeline to fire events on this
055     * pipeline.
056     * 
057     * This feature can be used to ensure the proper usage of event
058     * pipelines. Assume that a handler invoked from event pipeline
059     * *S* produces several related output events and fires them
060     * using another event pipeline *O*. In this case, it is important
061     * that the proper sequence is not disturbed. By restricting
062     * the source pipeline of *O* to *S*, it becomes impossible
063     * for other threads than the one that runs the event pipeline
064     * *S* to fire events that are to be processed by *O*.
065     * 
066     * Events from other threads than the one that runs *O*
067     * are ignored and an error is logged with the core package
068     * logger with ".fireRestriction" appended.
069     *
070     * @param sourcePipeline the source pipeline or `null` to
071     * revoke the restriction
072     * @return the event pipeline
073     */
074    EventPipeline restrictEventSource(EventPipeline sourcePipeline);
075
076    /**
077     * Overrides any restriction set by 
078     * {@link #restrictEventSource(EventPipeline)} for the next 
079     * {@link #fire(Event, Channel...)} invocation from the calling thread.
080     * 
081     * The typical use case is a protocol handling component
082     * (see the JGrapes I/O package) . After a connection and an 
083     * associated IOSubchannel have been established, the response 
084     * pipeline is usually only used by the downstream component,
085     * which may restrict the source for events on that pipeline.
086     * 
087     * Sometimes, however, the protocol handling component must insert
088     * events with out-of-band (control) information in the stream
089     * of events that form the regular I/O data. This method allows
090     * the protocol component to do this, even if a restriction
091     * applies to the response pipeline. 
092     *
093     * @return the event pipeline
094     */
095    EventPipeline overrideRestriction();
096
097    /**
098     * Adds an action to be executed to the event pipeline. 
099     * Execution of the action is synchronized with the events
100     * on this pipeline. It will be executed after any events
101     * already fired and before any event fired subsequently.
102     * 
103     * This is a short-cut for firing a special kind of event 
104     * and defining a handler for only this kind of event.
105     * Submitting a callable instead of firing an event and defining
106     * a handler should only be done when no use case is imaginable
107     * in which such an event could be intercepted by other 
108     * components or could trigger some action.
109     *
110     * @param <V> the value type
111     * @param name the name of the action; used in the event debug log 
112     * @param action the action to execute
113     * @return the future
114     */
115    <V> Future<V> submit(String name, Callable<V> action);
116
117    /**
118     * Like {@link #submit(String, Callable)} but without specifying a
119     * name for the event debug log.
120     * 
121     * @param action the action to execute
122     */
123    default <V> Future<V> submit(Callable<V> action) {
124        return submit(null, action);
125    }
126
127    /**
128     * Adds an action to be executed to the event pipeline. 
129     * Execution of the action is synchronized with the events
130     * on this pipeline. It will be executed after any events
131     * already fired and before any event fired subsequently.
132     * 
133     * This is a short-cut for firing a special kind of event 
134     * and defining a handler for only this kind of event.
135     * Submitting a runnable instead of firing an event and defining
136     * a handler should only be done when no use case is imaginable
137     * in which such an event could be intercepted by other 
138     * components or could trigger some action.
139     *
140     * @param name the name of the action; used in the event debug log 
141     * @param action the action to execute
142     */
143    void submit(String name, Runnable action);
144
145    /**
146     * Like {@link #submit(String, Callable)} but without specifiying
147     * a name for the event debug log.
148     * 
149     * @param action the action to execute
150     */
151    default void submit(Runnable action) {
152        submit(null, action);
153    }
154
155    /**
156     * All pipelines use the same id scope to make them uniquely identifiable
157     * by their number.
158     */
159    @Override
160    default Class<?> idScope() {
161        return EventPipeline.class;
162    }
163
164    /**
165     * Returns the executor service used by this event pipeline to
166     * obtain its thread. If a component needs to create a thread for its
167     * own use, it should obtain it from the component's event pipeline's
168     * executor service in order to conform with standard resource
169     * management.
170     * 
171     * @return the executor service
172     */
173    ExecutorService executorService();
174
175    /**
176     * Waits until this pipeline is empty. 
177     *
178     * @throws InterruptedException
179     */
180    void awaitExhaustion() throws InterruptedException;
181}