Skip to content

Commit ccada81

Browse files
committed
Merge pull request #2470 from akarnokd/SubjectAdditionalMethods
Subject state information methods & bounded ReplaySubject termination
2 parents 0da0d44 + 9544c6a commit ccada81

12 files changed

+1065
-14
lines changed

src/main/java/rx/internal/operators/NotificationLite.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,23 @@ public boolean isError(Object n) {
176176
return n instanceof OnErrorSentinel;
177177
}
178178

179+
/**
180+
* Indicates whether or not the lite notification represents a wrapped {@code null} {@code onNext} event.
181+
* @param n the lite notification
182+
* @return {@code true} if {@code n} represents a wrapped {@code null} {@code onNext} event, {@code false} otherwise
183+
*/
184+
public boolean isNull(Object n) {
185+
return n == ON_NEXT_NULL_SENTINEL;
186+
}
187+
188+
/**
189+
* Indicates whether or not the lite notification represents an {@code onNext} event.
190+
* @param n the lite notification
191+
* @return {@code true} if {@code n} represents an {@code onNext} event, {@code false} otherwise
192+
*/
193+
public boolean isNext(Object n) {
194+
return n != null && !isError(n) && !isCompleted(n);
195+
}
179196
/**
180197
* Indicates which variety a particular lite notification is. If you need something more complex than
181198
* simply calling the right method on an {@link Observer} then you can use this method to get the

src/main/java/rx/subjects/AsyncSubject.java

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.List;
2020

2121
import rx.Observer;
22+
import rx.annotations.Experimental;
2223
import rx.exceptions.CompositeException;
2324
import rx.exceptions.Exceptions;
2425
import rx.functions.Action1;
@@ -140,4 +141,66 @@ public void onNext(T v) {
140141
public boolean hasObservers() {
141142
return state.observers().length > 0;
142143
}
144+
/**
145+
* Check if the Subject has a value.
146+
* <p>Use the {@link #getValue()} method to retrieve such a value.
147+
* <p>Note that unless {@link #hasCompleted()} or {@link #hasThrowable()} returns true, the value
148+
* retrieved by {@code getValue()} may get outdated.
149+
* @return true if and only if the subject has some value but not an error
150+
*/
151+
@Experimental
152+
public boolean hasValue() {
153+
Object v = lastValue;
154+
Object o = state.get();
155+
return !nl.isError(o) && nl.isNext(v);
156+
}
157+
/**
158+
* Check if the Subject has terminated with an exception.
159+
* @return true if the subject has received a throwable through {@code onError}.
160+
*/
161+
@Experimental
162+
public boolean hasThrowable() {
163+
Object o = state.get();
164+
return nl.isError(o);
165+
}
166+
/**
167+
* Check if the Subject has terminated normally.
168+
* @return true if the subject completed normally via {@code onCompleted()}
169+
*/
170+
@Experimental
171+
public boolean hasCompleted() {
172+
Object o = state.get();
173+
return o != null && !nl.isError(o);
174+
}
175+
/**
176+
* Returns the current value of the Subject if there is such a value and
177+
* the subject hasn't terminated with an exception.
178+
* <p>The can return {@code null} for various reasons. Use {@link #hasValue()}, {@link #hasThrowable()}
179+
* and {@link #hasCompleted()} to determine if such {@code null} is a valid value, there was an
180+
* exception or the Subject terminated without receiving any value.
181+
* @return the current value or {@code null} if the Subject doesn't have a value,
182+
* has terminated with an exception or has an actual {@code null} as a value.
183+
*/
184+
@Experimental
185+
public T getValue() {
186+
Object v = lastValue;
187+
Object o = state.get();
188+
if (!nl.isError(o) && nl.isNext(v)) {
189+
return nl.getValue(v);
190+
}
191+
return null;
192+
}
193+
/**
194+
* Returns the Throwable that terminated the Subject.
195+
* @return the Throwable that terminated the Subject or {@code null} if the
196+
* subject hasn't terminated yet or it terminated normally.
197+
*/
198+
@Experimental
199+
public Throwable getThrowable() {
200+
Object o = state.get();
201+
if (nl.isError(o)) {
202+
return nl.getError(o);
203+
}
204+
return null;
205+
}
143206
}

src/main/java/rx/subjects/BehaviorSubject.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.List;
2121

2222
import rx.Observer;
23+
import rx.annotations.Experimental;
2324
import rx.exceptions.CompositeException;
2425
import rx.exceptions.Exceptions;
2526
import rx.functions.Action1;
@@ -176,4 +177,64 @@ public void onNext(T v) {
176177
public boolean hasObservers() {
177178
return state.observers().length > 0;
178179
}
180+
/**
181+
* Check if the Subject has a value.
182+
* <p>Use the {@link #getValue()} method to retrieve such a value.
183+
* <p>Note that unless {@link #hasCompleted()} or {@link #hasThrowable()} returns true, the value
184+
* retrieved by {@code getValue()} may get outdated.
185+
* @return true if and only if the subject has some value and hasn't terminated yet.
186+
*/
187+
@Experimental
188+
public boolean hasValue() {
189+
Object o = state.get();
190+
return nl.isNext(o);
191+
}
192+
/**
193+
* Check if the Subject has terminated with an exception.
194+
* @return true if the subject has received a throwable through {@code onError}.
195+
*/
196+
@Experimental
197+
public boolean hasThrowable() {
198+
Object o = state.get();
199+
return nl.isError(o);
200+
}
201+
/**
202+
* Check if the Subject has terminated normally.
203+
* @return true if the subject completed normally via {@code onCompleted()}
204+
*/
205+
@Experimental
206+
public boolean hasCompleted() {
207+
Object o = state.get();
208+
return nl.isCompleted(o);
209+
}
210+
/**
211+
* Returns the current value of the Subject if there is such a value and
212+
* the subject hasn't terminated yet.
213+
* <p>The can return {@code null} for various reasons. Use {@link #hasValue()}, {@link #hasThrowable()}
214+
* and {@link #hasCompleted()} to determine if such {@code null} is a valid value, there was an
215+
* exception or the Subject terminated (with or without receiving any value).
216+
* @return the current value or {@code null} if the Subject doesn't have a value,
217+
* has terminated or has an actual {@code null} as a valid value.
218+
*/
219+
@Experimental
220+
public T getValue() {
221+
Object o = state.get();
222+
if (nl.isNext(o)) {
223+
return nl.getValue(o);
224+
}
225+
return null;
226+
}
227+
/**
228+
* Returns the Throwable that terminated the Subject.
229+
* @return the Throwable that terminated the Subject or {@code null} if the
230+
* subject hasn't terminated yet or it terminated normally.
231+
*/
232+
@Experimental
233+
public Throwable getThrowable() {
234+
Object o = state.get();
235+
if (nl.isError(o)) {
236+
return nl.getError(o);
237+
}
238+
return null;
239+
}
179240
}

src/main/java/rx/subjects/PublishSubject.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.List;
2020

2121
import rx.Observer;
22+
import rx.annotations.Experimental;
2223
import rx.exceptions.CompositeException;
2324
import rx.exceptions.Exceptions;
2425
import rx.functions.Action1;
@@ -126,4 +127,36 @@ public void onNext(T v) {
126127
public boolean hasObservers() {
127128
return state.observers().length > 0;
128129
}
130+
131+
/**
132+
* Check if the Subject has terminated with an exception.
133+
* @return true if the subject has received a throwable through {@code onError}.
134+
*/
135+
@Experimental
136+
public boolean hasThrowable() {
137+
Object o = state.get();
138+
return nl.isError(o);
139+
}
140+
/**
141+
* Check if the Subject has terminated normally.
142+
* @return true if the subject completed normally via {@code onCompleted}
143+
*/
144+
@Experimental
145+
public boolean hasCompleted() {
146+
Object o = state.get();
147+
return o != null && !nl.isError(o);
148+
}
149+
/**
150+
* Returns the Throwable that terminated the Subject.
151+
* @return the Throwable that terminated the Subject or {@code null} if the
152+
* subject hasn't terminated yet or it terminated normally.
153+
*/
154+
@Experimental
155+
public Throwable getThrowable() {
156+
Object o = state.get();
157+
if (nl.isError(o)) {
158+
return nl.getError(o);
159+
}
160+
return null;
161+
}
129162
}

0 commit comments

Comments
 (0)