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