001/* Copyright 2011-2013 the original author or authors: 002 * 003 * Marc Palmer (marc@grailsrocks.com) 004 * Stéphane Maldini (smaldini@vmware.com) 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.grails.plugin.platform.events; 019 020import grails.events.EventException; 021import groovy.lang.Closure; 022 023import java.io.Serializable; 024import java.util.ArrayList; 025import java.util.Collection; 026import java.util.List; 027import java.util.concurrent.ExecutionException; 028import java.util.concurrent.Future; 029import java.util.concurrent.TimeUnit; 030import java.util.concurrent.TimeoutException; 031 032/** 033 * @author Stephane Maldini <smaldini@vmware.com> 034 * @version 1.0 035 * @file 036 * @date 30/12/11 037 * @section DESCRIPTION 038 * <p/> 039 * [Does stuff] 040 */ 041public class EventReply implements Serializable, Future<Object> { 042 043 private static final long serialVersionUID = 1; 044 045 private Future<?> futureReply; 046 private List<Object> values; 047 private Object value; 048 private int receivers; 049 private boolean futureReplyLoaded = false; 050 @SuppressWarnings("rawtypes") private Closure onError; 051 052 @SuppressWarnings("rawtypes") 053 public void setOnError(Closure onError) { 054 this.onError = onError; 055 } 056 057 @SuppressWarnings("rawtypes") 058 public Closure getOnError() { 059 return onError; 060 } 061 062 public EventReply(Object val, int receivers) { 063 this.receivers = receivers; 064 initValues(val); 065 } 066 067 protected void initValues(Object val) { 068 this.values = new ArrayList<Object>(); 069 070 if (receivers > 1 && val instanceof Collection) { 071 this.values.addAll((Collection<?>) val); 072 this.value = values.get(0); 073 } else if(receivers != 0 || val != null) { 074 this.value = val; 075 this.values.add(this.value); 076 } 077 this.futureReplyLoaded = true; 078 } 079 080 public EventReply(Future<?> future, int receivers) { 081 this.receivers = receivers; 082 this.futureReply = future; 083 } 084 085 protected void addValue(Object v) { 086 values.add(v); 087 } 088 089 public List<Object> getValues() throws Throwable { 090 if (!futureReplyLoaded) { 091 get(); 092 } 093 throwError(); 094 return values; 095 } 096 097 public Object getValue() throws Throwable{ 098 if (!futureReplyLoaded) { 099 get(); 100 } 101 throwError(); 102 return value; 103 } 104 105 public boolean cancel(){ 106 return cancel(true); 107 } 108 109 public boolean cancel(boolean b) { 110 return futureReply == null || futureReply.cancel(b); 111 } 112 113 public boolean isCancelled() { 114 return futureReply != null && futureReply.isCancelled(); 115 } 116 117 public boolean isDone() { 118 return futureReply == null || futureReply.isDone(); 119 } 120 121 public boolean isSuccess() { 122 return isDone() && !hasErrors(); 123 } 124 125 public List<Throwable> getErrors() { 126 List<Throwable> ex = new ArrayList<Throwable>(); 127 if (values != null) { 128 for (Object v : values) { 129 if (v != null && Throwable.class.isAssignableFrom(v.getClass())) { 130 ex.add((Throwable) v); 131 } 132 } 133 } 134 135 return ex; 136 } 137 138 public boolean hasErrors() { 139 for (Object v : values) { 140 if (v != null && Throwable.class.isAssignableFrom(v.getClass())) { 141 return true; 142 } 143 } 144 return false; 145 } 146 147 public void throwError() throws Throwable{ 148 if(hasErrors()){ 149 if(onError != null){ 150 onError.call(this); 151 }else{ 152 throw new EventException(getErrors().get(0)); 153 } 154 } 155 } 156 157 public int size() throws Throwable { 158 get(); 159 throwError(); 160 return receivers; 161 } 162 163 protected void setReceivers(int receivers) { 164 this.receivers = receivers; 165 } 166 167 public EventReply waitFor() throws Throwable { 168 get(); 169 throwError(); 170 return this; 171 } 172 173 public EventReply waitFor(long l) throws Throwable { 174 get(l, TimeUnit.MILLISECONDS); 175 throwError(); 176 return this; 177 } 178 179 public Object get() throws InterruptedException, ExecutionException { 180 Object val = futureReply == null ? value : futureReply.get(); 181 if (!futureReplyLoaded) { 182 initValues(val); 183 } 184 return val; 185 } 186 187 public Object get(long l, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException { 188 Object val = futureReply == null ? value : futureReply.get(l, timeUnit); 189 if (!futureReplyLoaded) { 190 initValues(val); 191 } 192 return val; 193 } 194 195}