/*
* Copyright 2014 ArcBees 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 com.gwtplatform.dispatch.rpc.client.interceptor;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.gwtplatform.dispatch.client.DelegatingDispatchRequest;
import com.gwtplatform.dispatch.client.ExecuteCommand;
import com.gwtplatform.dispatch.rpc.client.DispatchCall;
import com.gwtplatform.dispatch.rpc.client.RpcDispatchCallFactory;
import com.gwtplatform.dispatch.rpc.client.RpcDispatchExecuteCall;
import com.gwtplatform.dispatch.rpc.shared.Action;
import com.gwtplatform.dispatch.rpc.shared.Result;
import com.gwtplatform.dispatch.shared.DispatchRequest;
/**
* {@code AsyncCallback} implementation wrapping another {@link AsyncCallback} object used by a {@link
* com.gwtplatform.dispatch.client.interceptor.Interceptor Interceptor} implementations to delegate the execution
* result.
*
* @param <A> the {@link TypedAction} type.
* @param <R> the result type for this action.
*/
public class RpcInterceptedAsyncCallback<A extends Action<R>, R extends Result>
implements AsyncCallback<RpcInterceptor<?, ?>>, ExecuteCommand<A, AsyncCallback<R>> {
private final RpcDispatchCallFactory dispatchCallFactory;
private final DispatchCall<A, R> dispatchCall;
private final A action;
private final AsyncCallback<R> callback;
private final DelegatingDispatchRequest dispatchRequest;
public RpcInterceptedAsyncCallback(
RpcDispatchCallFactory dispatchCallFactory,
DispatchCall<A, R> dispatchCall,
A action,
AsyncCallback<R> callback,
DelegatingDispatchRequest dispatchRequest) {
this.dispatchCallFactory = dispatchCallFactory;
this.dispatchCall = dispatchCall;
this.action = action;
this.callback = callback;
this.dispatchRequest = dispatchRequest;
}
@Override
public DispatchRequest execute(A action, AsyncCallback<R> resultCallback) {
if (dispatchRequest.isPending()) {
RpcDispatchExecuteCall<A, R> newDispatchCall = dispatchCallFactory.create(action, resultCallback);
newDispatchCall.setIntercepted(true);
return newDispatchCall.execute();
} else {
return null;
}
}
@Override
public void onSuccess(RpcInterceptor<?, ?> result) {
handleSuccess(result);
}
@Override
public void onFailure(Throwable caught) {
handleFailure(caught);
}
protected void handleSuccess(RpcInterceptor<?, ?> interceptor) {
if (!interceptor.canExecute(action)) {
delegateFailure(interceptor);
} else if (getDispatchRequest().isPending()) {
delegateExecute((RpcInterceptor<A, R>) interceptor);
}
}
protected void handleFailure(Throwable caught) {
dispatchRequest.cancel();
dispatchCall.onExecuteFailure(caught, null);
}
protected void delegateFailure(RpcInterceptor<?, ?> interceptor) {
InterceptorMismatchException exception =
new InterceptorMismatchException(action.getClass(), interceptor.getActionType());
if (dispatchCall.shouldHandleFailure(exception)) {
handleFailure(exception);
}
}
@SuppressWarnings("unchecked")
protected void delegateExecute(RpcInterceptor<A, R> interceptor) {
dispatchRequest.setDelegate(interceptor.execute(action, callback, this));
}
protected DelegatingDispatchRequest getDispatchRequest() {
return dispatchRequest;
}
}