001/* Copyright 2011-2012 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 Future<?> futureReply; 044 private List<Object> values; 045 private Object value; 046 private int receivers; 047 private boolean futureReplyLoaded = false; 048 private Closure onError = null; 049 050 public void setOnError(Closure onError) { 051 this.onError = onError; 052 } 053 054 public Closure getOnError() { 055 return onError; 056 } 057 058 public EventReply(Object val, int receivers) { 059 this.receivers = receivers; 060 initValues(val); 061 } 062 063 @SuppressWarnings("unchecked") 064 protected void initValues(Object val) { 065 this.values = new ArrayList<Object>(); 066 067 if (receivers > 1 && val instanceof Collection) { 068 this.values.addAll((Collection) val); 069 this.value = values.get(0); 070 } else if(receivers != 0 || val != null) { 071 this.value = val; 072 this.values.add(this.value); 073 } 074 this.futureReplyLoaded = true; 075 } 076 077 public EventReply(Future<?> future, int receivers) { 078 this.receivers = receivers; 079 this.futureReply = future; 080 } 081 082 protected void addValue(Object v) { 083 values.add(v); 084 } 085 086 public List<Object> getValues() throws Throwable { 087 if (!futureReplyLoaded) { 088 get(); 089 } 090 throwError(); 091 return values; 092 } 093 094 public Object getValue() throws Throwable{ 095 if (!futureReplyLoaded) { 096 get(); 097 } 098 throwError(); 099 return value; 100 } 101 102 public boolean cancel(){ 103 return cancel(true); 104 } 105 106 public boolean cancel(boolean b) { 107 return futureReply == null || futureReply.cancel(b); 108 } 109 110 public boolean isCancelled() { 111 return futureReply != null && futureReply.isCancelled(); 112 } 113 114 public boolean isDone() { 115 return futureReply == null || futureReply.isDone(); 116 } 117 118 public boolean isSuccess() { 119 return isDone() && !hasErrors(); 120 } 121 122 public List<Throwable> getErrors() { 123 List<Throwable> ex = new ArrayList<Throwable>(); 124 if (values != null) { 125 for (Object v : values) { 126 if (v != null && Throwable.class.isAssignableFrom(v.getClass())) { 127 ex.add((Throwable) v); 128 } 129 } 130 } 131 132 return ex; 133 } 134 135 public boolean hasErrors() { 136 for (Object v : values) { 137 if (v != null && Throwable.class.isAssignableFrom(v.getClass())) { 138 return true; 139 } 140 } 141 return false; 142 } 143 144 public void throwError() throws Throwable{ 145 if(hasErrors()){ 146 if(onError != null){ 147 onError.call(this); 148 }else{ 149 throw new EventException(getErrors().get(0)); 150 } 151 } 152 } 153 154 public int size() throws Throwable { 155 get(); 156 throwError(); 157 return receivers; 158 } 159 160 protected void setReceivers(int receivers) { 161 this.receivers = receivers; 162 } 163 164 public EventReply waitFor() throws Throwable { 165 get(); 166 throwError(); 167 return this; 168 } 169 170 public EventReply waitFor(long l) throws Throwable { 171 get(l, TimeUnit.MILLISECONDS); 172 throwError(); 173 return this; 174 } 175 176 public Object get() throws InterruptedException, ExecutionException { 177 Object val = futureReply == null ? value : futureReply.get(); 178 if (!futureReplyLoaded) { 179 initValues(val); 180 } 181 return val; 182 } 183 184 public Object get(long l, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException { 185 Object val = futureReply == null ? value : futureReply.get(l, timeUnit); 186 if (!futureReplyLoaded) { 187 initValues(val); 188 } 189 return val; 190 } 191 192}