| /* |
| * Copyright 2011 Google 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.google.web.bindery.requestfactory.shared; |
| |
| import com.google.web.bindery.event.shared.UmbrellaException; |
| |
| import java.util.ArrayList; |
| import java.util.LinkedHashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| import javax.validation.ConstraintViolation; |
| |
| /** |
| * A FanoutReceiver will forward its callbacks to zero or more other Receivers. |
| * Any exceptions thrown by the queued Receivers will be re-thrown as an |
| * {@link UmbrellaException} after all Receivers have been invoked. |
| * |
| * @param <T> the type of data being received |
| */ |
| public class FanoutReceiver<T> extends Receiver<T> { |
| private List<Receiver<? super T>> toCall; |
| private Set<Throwable> toThrow; |
| |
| /** |
| * Register a receiver to be called by the fanout. |
| * |
| * @throws IllegalArgumentException if {@code receiver} is {@code null} |
| */ |
| public void add(Receiver<? super T> receiver) { |
| if (receiver == null) { |
| throw new IllegalArgumentException(); |
| } |
| if (toCall == null) { |
| toCall = new ArrayList<Receiver<? super T>>(); |
| } |
| toCall.add(receiver); |
| } |
| |
| @Override |
| public void onConstraintViolation(Set<ConstraintViolation<?>> violations) { |
| try { |
| if (toCall != null) { |
| for (Receiver<? super T> r : toCall) { |
| try { |
| r.onConstraintViolation(violations); |
| } catch (Throwable t) { |
| onUncaughtThrowable(t); |
| } |
| } |
| } |
| } finally { |
| finish(); |
| } |
| } |
| |
| @Override |
| public void onFailure(ServerFailure error) { |
| try { |
| if (toCall != null) { |
| for (Receiver<? super T> r : toCall) { |
| try { |
| r.onFailure(error); |
| } catch (Throwable t) { |
| onUncaughtThrowable(t); |
| } |
| } |
| } |
| } finally { |
| finish(); |
| } |
| } |
| |
| @Override |
| public void onSuccess(T response) { |
| try { |
| if (toCall != null) { |
| for (Receiver<? super T> r : toCall) { |
| try { |
| r.onSuccess(response); |
| } catch (Throwable t) { |
| onUncaughtThrowable(t); |
| } |
| } |
| } |
| } finally { |
| finish(); |
| } |
| } |
| |
| @Deprecated |
| @Override |
| public void onViolation(Set<Violation> errors) { |
| try { |
| if (toCall != null) { |
| for (Receiver<? super T> r : toCall) { |
| try { |
| r.onViolation(errors); |
| } catch (Throwable t) { |
| onUncaughtThrowable(t); |
| } |
| } |
| } |
| } finally { |
| finish(); |
| } |
| } |
| |
| /** |
| * Called after all Receivers have been executed. |
| */ |
| protected void finish() { |
| if (toThrow != null) { |
| // Reset if the user wants to re-fire the Request |
| Set<Throwable> causes = toThrow; |
| toThrow = null; |
| throw new UmbrellaException(causes); |
| } |
| } |
| |
| /** |
| * Subclasses may override this method to alter how the FanoutReceiver |
| * collects exceptions that escape from the queued Receivers. |
| */ |
| protected void onUncaughtThrowable(Throwable t) { |
| if (toThrow == null) { |
| toThrow = new LinkedHashSet<Throwable>(); |
| } |
| toThrow.add(t); |
| } |
| } |