Skip to content

Commit b73a202

Browse files
committed
Subject state information methods & bounded ReplaySubject termination
fix
1 parent c49704b commit b73a202

13 files changed

+1042
-15
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: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,4 +140,61 @@ public void onNext(T v) {
140140
public boolean hasObservers() {
141141
return state.observers().length > 0;
142142
}
143+
/**
144+
* Check if the Subject has a value.
145+
* <p>Use the {@link #getValue()} method to retrieve such a value.
146+
* <p>Note that unless {@link #hasCompleted()} or {@link #hasThrowable()} returns true, the value
147+
* retrieved by {@code getValue()} may get outdated.
148+
* @return true if and only if the subject has some value but not an error
149+
*/
150+
public boolean hasValue() {
151+
Object v = lastValue;
152+
Object o = state.get();
153+
return !nl.isError(o) && nl.isNext(v);
154+
}
155+
/**
156+
* Check if the Subject has terminated with an exception.
157+
* @return true if the subject has received a throwable through {@code onError}.
158+
*/
159+
public boolean hasThrowable() {
160+
Object o = state.get();
161+
return nl.isError(o);
162+
}
163+
/**
164+
* Check if the Subject has terminated normally.
165+
* @return true if the subject completed normally via {@code onCompleted()}
166+
*/
167+
public boolean hasCompleted() {
168+
Object o = state.get();
169+
return o != null && !nl.isError(o);
170+
}
171+
/**
172+
* Returns the current value of the Subject if there is such a value and
173+
* the subject hasn't terminated with an exception.
174+
* <p>The can return {@code null} for various reasons. Use {@link #hasValue()}, {@link #hasThrowable()}
175+
* and {@link #hasCompleted()} to determine if such {@code null} is a valid value, there was an
176+
* exception or the Subject terminated without receiving any value.
177+
* @return the current value or {@code null} if the Subject doesn't have a value,
178+
* has terminated with an exception or has an actual {@code null} as a value.
179+
*/
180+
public T getValue() {
181+
Object v = lastValue;
182+
Object o = state.get();
183+
if (!nl.isError(o) && nl.isNext(v)) {
184+
return nl.getValue(v);
185+
}
186+
return null;
187+
}
188+
/**
189+
* Returns the Throwable that terminated the Subject.
190+
* @return the Throwable that terminated the Subject or {@code null} if the
191+
* subject hasn't terminated yet or it terminated normally.
192+
*/
193+
public Throwable getThrowable() {
194+
Object o = state.get();
195+
if (nl.isError(o)) {
196+
return nl.getError(o);
197+
}
198+
return null;
199+
}
143200
}

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

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,4 +176,59 @@ public void onNext(T v) {
176176
public boolean hasObservers() {
177177
return state.observers().length > 0;
178178
}
179+
/**
180+
* Check if the Subject has a value.
181+
* <p>Use the {@link #getValue()} method to retrieve such a value.
182+
* <p>Note that unless {@link #hasCompleted()} or {@link #hasThrowable()} returns true, the value
183+
* retrieved by {@code getValue()} may get outdated.
184+
* @return true if and only if the subject has some value and hasn't terminated yet.
185+
*/
186+
public boolean hasValue() {
187+
Object o = state.get();
188+
return nl.isNext(o);
189+
}
190+
/**
191+
* Check if the Subject has terminated with an exception.
192+
* @return true if the subject has received a throwable through {@code onError}.
193+
*/
194+
public boolean hasThrowable() {
195+
Object o = state.get();
196+
return nl.isError(o);
197+
}
198+
/**
199+
* Check if the Subject has terminated normally.
200+
* @return true if the subject completed normally via {@code onCompleted()}
201+
*/
202+
public boolean hasCompleted() {
203+
Object o = state.get();
204+
return nl.isCompleted(o);
205+
}
206+
/**
207+
* Returns the current value of the Subject if there is such a value and
208+
* the subject hasn't terminated yet.
209+
* <p>The can return {@code null} for various reasons. Use {@link #hasValue()}, {@link #hasThrowable()}
210+
* and {@link #hasCompleted()} to determine if such {@code null} is a valid value, there was an
211+
* exception or the Subject terminated (with or without receiving any value).
212+
* @return the current value or {@code null} if the Subject doesn't have a value,
213+
* has terminated or has an actual {@code null} as a valid value.
214+
*/
215+
public T getValue() {
216+
Object o = state.get();
217+
if (nl.isNext(o)) {
218+
return nl.getValue(o);
219+
}
220+
return null;
221+
}
222+
/**
223+
* Returns the Throwable that terminated the Subject.
224+
* @return the Throwable that terminated the Subject or {@code null} if the
225+
* subject hasn't terminated yet or it terminated normally.
226+
*/
227+
public Throwable getThrowable() {
228+
Object o = state.get();
229+
if (nl.isError(o)) {
230+
return nl.getError(o);
231+
}
232+
return null;
233+
}
179234
}

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,33 @@ public void onNext(T v) {
126126
public boolean hasObservers() {
127127
return state.observers().length > 0;
128128
}
129+
130+
/**
131+
* Check if the Subject has terminated with an exception.
132+
* @return true if the subject has received a throwable through {@code onError}.
133+
*/
134+
public boolean hasThrowable() {
135+
Object o = state.get();
136+
return nl.isError(o);
137+
}
138+
/**
139+
* Check if the Subject has terminated normally.
140+
* @return true if the subject completed normally via {@code onCompleted}
141+
*/
142+
public boolean hasCompleted() {
143+
Object o = state.get();
144+
return o != null && !nl.isError(o);
145+
}
146+
/**
147+
* Returns the Throwable that terminated the Subject.
148+
* @return the Throwable that terminated the Subject or {@code null} if the
149+
* subject hasn't terminated yet or it terminated normally.
150+
*/
151+
public Throwable getThrowable() {
152+
Object o = state.get();
153+
if (nl.isError(o)) {
154+
return nl.getError(o);
155+
}
156+
return null;
157+
}
129158
}

0 commit comments

Comments
 (0)