/** * Load data via the proxy, and pump the records into the store * * @throws Exception */ public ObservableFuture<Void> load() throws Exception { if (lastLoadingFuture != null) { // cancel the old ones. lastLoadingFuture.cancel(); lastProxyLoadingFuture.cancel(); } // this might take a long time. // unfortunately i can't sync during it. // but this means that after a LOAD operation is requested, // any adds that someone does will be overridden by the proxy.load() return value. // note: unfortunately this is synchronous. lastProxyLoadingFuture = proxy.load(); lastLoadingFuture = new DefaultObservableFuture<Void>(this); // listen for completion of this future. lastProxyLoadingFuture.addObserver(onLoadCompleteCallback); // this whitespace might be all it takes to miss a callback, so we have to listen first, check // second. if (handleImmediatelyDone(lastProxyLoadingFuture, lastLoadingFuture)) { lastProxyLoadingFuture.removeObserver(onLoadCompleteCallback); } return lastLoadingFuture; }
/** * This future is the future of the proxy * * @param internal * @param external * @throws Exception * @return if it was done or not */ private synchronized boolean handleImmediatelyDone( ObservableFuture<D> internal, MutableObservableFuture<Void> external) throws Exception { // if it's already done, we need to do some work. if (internal.isDone()) { if (internal.isSuccess()) { // already done! shit! we missed it! parseAndLoad(internal.getResult()); external.setSuccess(null); } else if (internal.isCancelled()) { // cascade the cancellation external.cancel(); } else { // must be in error? external.setFailure(internal.getCause()); } return true; } return false; }