001/** 002 * Copyright 2010-2014 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.common.util.spring.event; 017 018import static com.google.common.base.Preconditions.checkArgument; 019import static com.google.common.base.Preconditions.checkNotNull; 020 021import org.kuali.common.util.execute.Executable; 022import org.kuali.common.util.log.LoggerUtils; 023import org.slf4j.Logger; 024import org.springframework.context.ApplicationEvent; 025import org.springframework.context.event.SmartApplicationListener; 026 027/** 028 * <p> 029 * Associate an executable with a Spring framework application event. 030 * </p> 031 * 032 * <p> 033 * If the application event gets fired {@code onApplicationEvent} invokes the executable. 034 * </p> 035 */ 036public final class ExecutableApplicationEventListener<T extends ApplicationEvent> implements SmartApplicationListener { 037 038 private static final Logger logger = LoggerUtils.make(); 039 040 private final Executable executable; 041 private final int order; 042 private final Class<T> supportedEventType; 043 044 @Override 045 public void onApplicationEvent(ApplicationEvent event) { 046 checkEvent(event); 047 logger.info("Received event: [{}]", event.getClass().getCanonicalName()); 048 executable.execute(); 049 } 050 051 @Override 052 public int getOrder() { 053 return order; 054 } 055 056 @Override 057 public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) { 058 return supportedEventType == eventType; 059 } 060 061 @Override 062 public boolean supportsSourceType(Class<?> sourceType) { 063 return true; 064 } 065 066 private void checkEvent(ApplicationEvent event) { 067 boolean expression = supportedEventType == event.getClass(); 068 String errorMessage = "[%s] is the only supported event type. Events of type [%s] should not be getting passed to this listener"; 069 Object[] args = { supportedEventType.getCanonicalName(), event.getClass().getCanonicalName() }; 070 checkArgument(expression, errorMessage, args); 071 } 072 073 private ExecutableApplicationEventListener(Builder<T> builder) { 074 this.executable = builder.executable; 075 this.order = builder.order; 076 this.supportedEventType = builder.supportedEventType; 077 } 078 079 public static <T extends ApplicationEvent> Builder<T> builder(Executable executable, Class<T> supportedEventType) { 080 return new Builder<T>(executable, supportedEventType); 081 } 082 083 public static class Builder<T extends ApplicationEvent> { 084 085 // Required 086 private final Executable executable; 087 private final Class<T> supportedEventType; 088 089 // Optional 090 private int order = 0; // Lower values mean higher priority, higher values mean lower priority 091 092 public Builder(Executable executable, Class<T> supportedEventType) { 093 this.executable = executable; 094 this.supportedEventType = supportedEventType; 095 } 096 097 public ExecutableApplicationEventListener<T> build() { 098 ExecutableApplicationEventListener<T> instance = new ExecutableApplicationEventListener<T>(this); 099 validate(instance); 100 return instance; 101 } 102 103 private void validate(ExecutableApplicationEventListener<T> instance) { 104 checkNotNull(instance.getExecutable(), "'executable' cannot be null"); 105 checkNotNull(instance.getSupportedEventType(), "'supportedEventType' cannot be null"); 106 } 107 108 public Builder<T> order(int order) { 109 this.order = order; 110 return this; 111 } 112 113 public int getOrder() { 114 return order; 115 } 116 117 public void setOrder(int order) { 118 this.order = order; 119 } 120 121 public Executable getExecutable() { 122 return executable; 123 } 124 } 125 126 public Executable getExecutable() { 127 return executable; 128 } 129 130 public Class<T> getSupportedEventType() { 131 return supportedEventType; 132 } 133 134}