diff options
Diffstat (limited to 'bundles/org.eclipse.equinox.log.stream/osgi/src/org/osgi/util/pushstream/PushEvent.java')
-rw-r--r-- | bundles/org.eclipse.equinox.log.stream/osgi/src/org/osgi/util/pushstream/PushEvent.java | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.log.stream/osgi/src/org/osgi/util/pushstream/PushEvent.java b/bundles/org.eclipse.equinox.log.stream/osgi/src/org/osgi/util/pushstream/PushEvent.java new file mode 100644 index 000000000..028f0a392 --- /dev/null +++ b/bundles/org.eclipse.equinox.log.stream/osgi/src/org/osgi/util/pushstream/PushEvent.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) OSGi Alliance (2015, 2016). All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.osgi.util.pushstream; + +import static org.osgi.util.pushstream.PushEvent.EventType.*; + +/** + * A PushEvent is an immutable object that is transferred through a + * communication channel to push information to a downstream consumer. The event + * has three different types: + * <ul> + * <li>{@link EventType#DATA} – Provides access to a typed data element in the + * stream. + * <li>{@link EventType#CLOSE} – The stream is closed. After receiving this + * event, no more events will follow. + * <li>{@link EventType#ERROR} – The stream ran into an unrecoverable problem + * and is sending the reason downstream. The stream is closed and no more events + * will follow after this event. + * </ul> + * + * @param <T> The payload type of the event. + * @Immutable + */ +public abstract class PushEvent<T> { + + /** + * The type of a {@link PushEvent}. + */ + public static enum EventType { + /** + * A data event forming part of the stream + */ + DATA, + /** + * An error event that indicates streaming has failed and that no more + * events will arrive + */ + ERROR, + /** + * An event that indicates that the stream has terminated normally + */ + CLOSE + } + + /** + * Package private default constructor. + */ + PushEvent() {} + + /** + * Get the type of this event. + * + * @return The type of this event. + */ + public abstract EventType getType(); + + /** + * Return the data for this event. + * + * @return The data payload. + * @throws IllegalStateException if this event is not a + * {@link EventType#DATA} event. + */ + public T getData() throws IllegalStateException { + throw new IllegalStateException( + "Not a DATA event, the event type is " + getType()); + } + + /** + * Return the error that terminated the stream. + * + * @return The error that terminated the stream. + * @throws IllegalStateException if this event is not an + * {@link EventType#ERROR} event. + */ + public Exception getFailure() throws IllegalStateException { + throw new IllegalStateException( + "Not an ERROR event, the event type is " + getType()); + } + + /** + * Answer if no more events will follow after this event. + * + * @return {@code false} if this is a data event, otherwise {@code true}. + */ + public boolean isTerminal() { + return true; + } + + /** + * Create a new data event. + * + * @param <T> The payload type. + * @param payload The payload. + * @return A new data event wrapping the specified payload. + */ + public static <T> PushEvent<T> data(T payload) { + return new DataEvent<T>(payload); + } + + /** + * Create a new error event. + * + * @param <T> The payload type. + * @param e The error. + * @return A new error event with the specified error. + */ + public static <T> PushEvent<T> error(Exception e) { + return new ErrorEvent<T>(e); + } + + /** + * Create a new close event. + * + * @param <T> The payload type. + * @return A new close event. + */ + public static <T> PushEvent<T> close() { + return new CloseEvent<T>(); + } + + /** + * Convenience to cast a close/error event to another payload type. Since + * the payload type is not needed for these events this is harmless. This + * therefore allows you to forward the close/error event downstream without + * creating anew event. + * + * @param <X> The new payload type. + * @return The current error or close event mapped to a new payload type. + * @throws IllegalStateException if the event is a {@link EventType#DATA} + * event. + */ + public <X> PushEvent<X> nodata() throws IllegalStateException { + @SuppressWarnings("unchecked") + PushEvent<X> result = (PushEvent<X>) this; + return result; + } + + static final class DataEvent<T> extends PushEvent<T> { + private final T data; + + DataEvent(T data) { + this.data = data; + } + + @Override + public T getData() throws IllegalStateException { + return data; + } + + @Override + public EventType getType() { + return DATA; + } + + @Override + public boolean isTerminal() { + return false; + } + + @Override + public <X> PushEvent<X> nodata() throws IllegalStateException { + throw new IllegalStateException("This event is a DATA event"); + } + } + + static final class ErrorEvent<T> extends PushEvent<T> { + private final Exception error; + + ErrorEvent(Exception error) { + this.error = error; + } + + @Override + public Exception getFailure() { + return error; + } + + @Override + public EventType getType() { + return ERROR; + } + } + + static final class CloseEvent<T> extends PushEvent<T> { + @Override + public EventType getType() { + return CLOSE; + } + } +} |