package io.cattle.platform.eventing.annotation;
import io.cattle.platform.eventing.EventListener;
import io.cattle.platform.eventing.EventService;
import io.cattle.platform.eventing.util.EventUtils;
import io.cattle.platform.json.JsonMapper;
import io.cattle.platform.lock.LockManager;
import io.cattle.platform.util.type.InitializationTask;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
public class AnnotatedListenerRegistration implements InitializationTask {
List<AnnotatedEventListener> listeners;
EventService eventService;
JsonMapper jsonMapper;
LockManager lockManager;
@Override
public void start() {
for (AnnotatedEventListener listener : listeners) {
register(listener);
}
}
protected void register(AnnotatedEventListener listener) {
Map<String, EventListener> listeners = parseListener(listener);
for (Map.Entry<String, EventListener> entry : listeners.entrySet()) {
String eventName = entry.getKey();
EventListener annotatedListener = entry.getValue();
eventService.subscribe(eventName, annotatedListener);
}
}
protected List<String> getEventNames(EventHandler handler, AnnotatedEventListener listener, Method method) {
Class<? extends EventNameProvider> supplierClass = handler.nameProvider();
if (supplierClass == EventNameProvider.class) {
return Arrays.asList(EventUtils.getEventNameNonProvided(handler, listener, method));
} else {
EventNameProvider supplier = null;
try {
supplier = supplierClass.newInstance();
} catch (InstantiationException e) {
throw new IllegalArgumentException("Failed to instantiate [" + supplierClass + "]", e);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("Failed to instantiate [" + supplierClass + "]", e);
}
return supplier.events(handler, listener, method);
}
}
protected Map<String, EventListener> parseListener(AnnotatedEventListener listener) {
Map<String, EventListener> result = new LinkedHashMap<String, EventListener>();
for (Class<?> clz : getClasses(listener.getClass())) {
for (Method m : clz.getMethods()) {
EventHandler h = m.getAnnotation(EventHandler.class);
if (h == null) {
continue;
}
for (String eventName : getEventNames(h, listener, m)) {
result.put(eventName, new MethodInvokingListener(lockManager, jsonMapper, h, m, listener));
}
}
}
return result;
}
protected List<Class<?>> getClasses(Class<?> clz) {
List<Class<?>> result = new ArrayList<Class<?>>();
if (clz == null || clz.getPackage().getName().startsWith("java.lang")) {
return result;
}
result.add(clz);
for (Class<?> iface : clz.getInterfaces()) {
result.addAll(getClasses(iface));
}
result.addAll(getClasses(clz.getSuperclass()));
return result;
}
public List<AnnotatedEventListener> getListeners() {
return listeners;
}
@Inject
public void setListeners(List<AnnotatedEventListener> listeners) {
this.listeners = listeners;
}
public EventService getEventService() {
return eventService;
}
@Inject
public void setEventService(EventService eventService) {
this.eventService = eventService;
}
public JsonMapper getJsonMapper() {
return jsonMapper;
}
@Inject
public void setJsonMapper(JsonMapper jsonMapper) {
this.jsonMapper = jsonMapper;
}
public LockManager getLockManager() {
return lockManager;
}
@Inject
public void setLockManager(LockManager lockManager) {
this.lockManager = lockManager;
}
}