/* * WBI Indicator Explorer * * Copyright 2015 Sebastian Nogara <snogaraleal@gmail.com> * * This file is part of WBI. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package rpc.client; import java.util.ArrayList; import java.util.List; import rpc.shared.data.Type; /** * RPC request. * * <ol> * <li>Create a {@code ClientRequest} with a remote class and method</li> * <li>Specify method arguments with {@link #setArguments(Object...)}</li> * <li>Set the expected return type with {@link #setExpected(Type)}</li> * <li>Attach listeners with {@link #addListener(Listener)}</li> * <li>Send the request with {@link #send()} or {@link #send(Client)}</li> * </ol> * * The request can be cancelled with {@link #cancel()} or * {@link #cancel(Client)}. * * @param <T> Expected return type. */ public class ClientRequest<T> { /** * Global request listener. * * Useful for debugging, general information or global loading UI * indicators. */ public static interface GlobalListener { /** * Handle sent {@link ClientRequest}. * * @param clientRequest {@code ClientRequest}. */ void onSend(ClientRequest<?> clientRequest); /** * Handle completed {@link ClientRequest}. * * @param clientRequest {@code ClientRequest}. */ void onFinish(ClientRequest<?> clientRequest); } /** * Registered {@link GlobalListener}. */ private static List<GlobalListener> globalListeners = new ArrayList<GlobalListener>(); /** * Register {@link GlobalListener}. * * @param listener Listener to register. */ public static void addGlobalListener(GlobalListener listener) { globalListeners.add(listener); } /** * Unregister {@link GlobalListener}. * * @param listener Listener to unregister. */ public static void removeGlobalListener(GlobalListener listener) { globalListeners.remove(listener); } /** * Error during request. */ @SuppressWarnings("serial") public static class Error extends Exception { /** * Initialize {@link Error}. * * @param caught {@code Throwable} to wrap. */ public Error(Throwable caught) { super(caught); } /** * Initialize {@link Error}. * * @param reason Error message. */ public Error(String reason) { super(reason); } } /** * Request listener. * * @param <T> */ public static interface Listener<T> { /** * Handle request result. * * @param object Returned result. */ void onSuccess(T object); /** * Handle request error. * * @param error Error. */ void onFailure(Error error); } private String className; private String methodName; private Object[] arguments; private Type expected; /** * Registered request listeners. */ private List<Listener<T>> listeners = new ArrayList<Listener<T>>(); /** * Initialize {@code ClientRequest}. * * @param className Remote service class. * @param methodName Method name. */ public ClientRequest(String className, String methodName) { this.className = className; this.methodName = methodName; } /** * Get remote service class name. * * @return Service class name. */ public String getClassName() { return className; } /** * Get remote service method name. * * @return Service method name. */ public String getMethodName() { return methodName; } /** * Set arguments for the remote method. * * @param arguments Arguments. * @return {@code ClientRequest}. */ public ClientRequest<T> setArguments(Object... arguments) { this.arguments = arguments; return this; } /** * Get arguments for remote method. * * @return Arguments. */ public Object[] getArguments() { return arguments; } /** * Set expected return type. * * @param expected Expected return type. * @return {@code ClientRequest}. */ public ClientRequest<T> setExpected(Type expected) { this.expected = expected; return this; } /** * Get expected return type. * * @return Expected return type. */ public Type getExpected() { return expected; } /** * Add request listener. * * @param listener Request listener. * @return {@code ClientRequest}. */ public ClientRequest<T> addListener(Listener<T> listener) { listeners.add(listener); return this; } /** * Send request using the specified {@link Client}. * * @param client {@code Client}. * @return {@code ClientRequest}. */ public ClientRequest<T> send(Client client) { for (GlobalListener listener : globalListeners) { listener.onSend(this); } client.send(this); return this; } /** * Send request using the default {@link Client}. * * @return {@code ClientRequest}. */ public ClientRequest<T> send() { return send(Client.get()); } /** * Cancel request using the specified {@link Client}. * * @param client {@code Client}. * @return {@code ClientRequest}. */ public ClientRequest<T> cancel(Client client) { client.cancel(this); return this; } /** * Cancel request using the default {@link Client}. * * @return {@code ClientRequest}. */ public ClientRequest<T> cancel() { return cancel(Client.get()); } /** * Inform that this {@code ClientRequest} is completed and the specified * object is the return value of the remote service method. * * @param object Returned object. */ public void finish(T object) { for (GlobalListener listener : globalListeners) { listener.onFinish(this); } for (Listener<T> listener : listeners) { listener.onSuccess(object); } } /** * Inform that this {@code ClientRequest} is completed and an error * occurred when processing the request remotely. * * @param error Remote error. */ public void finish(Error error) { for (GlobalListener listener : globalListeners) { listener.onFinish(this); } for (Listener<T> listener : listeners) { listener.onFailure(error); } } }