/**
* Copyright 2008 - 2015 The Loon Game Engine Authors
*
* 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.
*
* @project loon
* @author cping
* @email:javachenpeng@yahoo.com
* @version 0.5
*/
package loon.utils.reply;
public class GoFuture<T> {
protected final VarView<Try<T>> _result;
protected VarView<Boolean> _isComplete;
public static <T> GoFuture<T> success (T value) {
return result(Try.success(value));
}
public static GoFuture<Void> success () {
return success(null);
}
public static <T> GoFuture<T> failure (Throwable cause) {
return result(Try.<T>failure(cause));
}
public static <T> GoFuture<T> result (Try<T> result) {
return new GoFuture<T>(Var.create(result));
}
public GoFuture<T> onSuccess (final ActView.Listener<? super T> slot) {
Try<T> result = _result.get();
if (result == null) _result.connect(new ActView.Listener<Try<T>>() {
public void onEmit (Try<T> result) {
if (result.isSuccess()) slot.onEmit(result.get());
}
});
else if (result.isSuccess()) slot.onEmit(result.get());
return this;
}
public GoFuture<T> onFailure (final ActView.Listener<? super Throwable> slot) {
Try<T> result = _result.get();
if (result == null) _result.connect(new ActView.Listener<Try<T>>() {
public void onEmit (Try<T> result) {
if (result.isFailure()) slot.onEmit(result.getFailure());
}
});
else if (result.isFailure()) slot.onEmit(result.getFailure());
return this;
}
public GoFuture<T> onComplete (final ActView.Listener<? super Try<T>> slot) {
Try<T> result = _result.get();
if (result == null) {
_result.connect(slot);
}
else slot.onEmit(result);
return this;
}
public VarView<Boolean> isComplete () {
if (_isComplete == null){
_isComplete = _result.map(Functions.NON_NULL);
}
return _isComplete;
}
public boolean isCompleteNow () {
return _result.get() != null;
}
public GoFuture<T> bindComplete (ActView.Listener<Boolean> slot) {
isComplete().connectNotify(slot);
return this;
}
public <R> GoFuture<R> map (final Function<? super T, R> func) {
return new GoFuture<R>(_result.map(new Function<Try<T>,Try<R>>() {
public Try<R> apply (Try<T> result) {
return result == null ? null : result.map(func);
}
}));
}
public <R> GoFuture<R> flatMap (final Function<? super T, GoFuture<R>> func) {
final Var<Try<R>> mapped = Var.create(null);
_result.connectNotify(new ActView.Listener<Try<T>>() {
public void onEmit (Try<T> result) {
if (result == null){
return;
}
if (result.isFailure()) {
mapped.update(Try.<R>failure(result.getFailure()));
}
else{
func.apply(result.get()).onComplete(mapped.port());
}
}
});
return new GoFuture<R>(mapped);
}
public Try<T> result () {
return _result.get();
}
protected GoFuture (VarView<Try<T>> result) {
_result = result;
}
}