
rx.subjects.Subject Maven / Gradle / Ivy
/**
* Copyright 2014 Netflix, Inc.
*
* 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 rx.subjects;
import rx.Observable;
import rx.Observer;
import rx.Subscriber;
import rx.annotations.Experimental;
/**
* Represents an object that is both an Observable and an Observer.
*/
public abstract class Subject extends Observable implements Observer {
protected Subject(OnSubscribe onSubscribe) {
super(onSubscribe);
}
/**
* Indicates whether the {@link Subject} has {@link Observer Observers} subscribed to it.
*
* @return true if there is at least one Observer subscribed to this Subject, false otherwise
*/
public abstract boolean hasObservers();
/**
* Wraps a {@link Subject} so that it is safe to call its various {@code on} methods from different threads.
*
* When you use an ordinary {@link Subject} as a {@link Subscriber}, you must take care not to call its
* {@link Subscriber#onNext} method (or its other {@code on} methods) from multiple threads, as this could
* lead to non-serialized calls, which violates
* the Observable contract and creates an
* ambiguity in the resulting Subject.
*
* To protect a {@code Subject} from this danger, you can convert it into a {@code SerializedSubject} with
* code like the following:
*
{@code
* mySafeSubject = myUnsafeSubject.toSerialized();
* }
*
* @return SerializedSubject wrapping the current Subject
*/
public final SerializedSubject toSerialized() {
if (getClass() == SerializedSubject.class) {
return (SerializedSubject)this;
}
return new SerializedSubject(this);
}
/**
* Check if the Subject has terminated with an exception.
* The operation is threadsafe.
*
* @return {@code true} if the subject has received a throwable through {@code onError}.
* @since (If this graduates from being an Experimental class method, replace this parenthetical with the release number)
* @deprecated this method will be moved to each Subject class individually in the next release
*/
@Experimental
@Deprecated
public boolean hasThrowable() {
throw new UnsupportedOperationException();
}
/**
* Check if the Subject has terminated normally.
*
The operation is threadsafe.
*
* @return {@code true} if the subject completed normally via {@code onCompleted}
* @since (If this graduates from being an Experimental class method, replace this parenthetical with the release number)
* @deprecated this method will be moved to each Subject class individually in the next release
*/
@Experimental
@Deprecated
public boolean hasCompleted() {
throw new UnsupportedOperationException();
}
/**
* Returns the Throwable that terminated the Subject.
*
The operation is threadsafe.
*
* @return the Throwable that terminated the Subject or {@code null} if the subject hasn't terminated yet or
* if it terminated normally.
* @since (If this graduates from being an Experimental class method, replace this parenthetical with the release number)
* @deprecated this method will be moved to each Subject class individually in the next release
*/
@Experimental
@Deprecated
public Throwable getThrowable() {
throw new UnsupportedOperationException();
}
/**
* Check if the Subject has any value.
*
Use the {@link #getValue()} method to retrieve such a value.
*
Note that unless {@link #hasCompleted()} or {@link #hasThrowable()} returns true, the value
* retrieved by {@code getValue()} may get outdated.
*
The operation is threadsafe.
*
* @return {@code true} if and only if the subject has some value but not an error
* @since (If this graduates from being an Experimental class method, replace this parenthetical with the release number)
* @deprecated this method will be moved to each Subject class individually in the next release
*/
@Experimental
@Deprecated
public boolean hasValue() {
throw new UnsupportedOperationException();
}
/**
* Returns the current or latest value of the Subject if there is such a value and
* the subject hasn't terminated with an exception.
*
The method can return {@code null} for various reasons. Use {@link #hasValue()}, {@link #hasThrowable()}
* and {@link #hasCompleted()} to determine if such {@code null} is a valid value, there was an
* exception or the Subject terminated without receiving any value.
*
The operation is threadsafe.
*
* @return the current value or {@code null} if the Subject doesn't have a value, has terminated with an
* exception or has an actual {@code null} as a value.
* @since (If this graduates from being an Experimental class method, replace this parenthetical with the release number)
* @deprecated this method will be moved to each Subject class individually in the next release
*/
@Experimental
@Deprecated
public T getValue() {
throw new UnsupportedOperationException();
}
/** An empty array to trigger getValues() to return a new array. */
private static final Object[] EMPTY_ARRAY = new Object[0];
/**
* Returns a snapshot of the currently buffered non-terminal events.
*
The operation is threadsafe.
*
* @return a snapshot of the currently buffered non-terminal events.
* @since (If this graduates from being an Experimental class method, replace this parenthetical with the release number)
* @deprecated this method will be moved to each Subject class individually in the next release
*/
@SuppressWarnings("unchecked")
@Experimental
@Deprecated
public Object[] getValues() {
T[] r = getValues((T[])EMPTY_ARRAY);
if (r == EMPTY_ARRAY) {
return new Object[0]; // don't leak the default empty array.
}
return r;
}
/**
* Returns a snapshot of the currently buffered non-terminal events into
* the provided {@code a} array or creates a new array if it has not enough capacity.
*
If the subject's values fit in the specified array with room to spare
* (i.e., the array has more elements than the list), the element in
* the array immediately following the end of the subject's values is set to
* {@code null}.
*
The operation is threadsafe.
*
* @param a the array to fill in
* @return the array {@code a} if it had enough capacity or a new array containing the available values
* @since (If this graduates from being an Experimental class method, replace this parenthetical with the release number)
* @deprecated this method will be moved to each Subject class individually in the next release
*/
@Experimental
@Deprecated
public T[] getValues(T[] a) {
throw new UnsupportedOperationException();
}
}