package com.maxifier.guice.events; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.util.List; class HandlerAnnotation { private final List<EventMatcher> matchers; private final List<EventClassMatcher> classMatchers; private final Class<? extends EventMatcher> ownMatcher; public HandlerAnnotation(List<EventMatcher> matchers, List<EventClassMatcher> classMatchers, Class<? extends EventMatcher> ownMatcher) { this.matchers = matchers; this.classMatchers = classMatchers; this.ownMatcher = ownMatcher; } public void append(Annotation a, List<EventMatcher> matchers, List<EventClassMatcher> classMatchers) { if (this.matchers != null) { matchers.addAll(this.matchers); classMatchers.addAll(this.classMatchers); EventMatcher m = createMatcher(ownMatcher, a); if (ownMatcher != null) { if (EventClassMatcher.class.isAssignableFrom(ownMatcher)) { classMatchers.add((EventClassMatcher) m); } else { matchers.add(m); } } } } @SuppressWarnings({"unchecked"}) private static <T extends EventMatcher, A extends Annotation> T createMatcher(Class<T> cls, A a) { Constructor<T> found = null; for (Constructor<?> constructor : cls.getConstructors()) { MatcherConstructor mc = constructor.getAnnotation(MatcherConstructor.class); if (mc != null) { if (found != null) { throw new RuntimeException("More than one constructor of " + cls + " has @MatcherConstructor"); } found = (Constructor<T>) constructor; } } Class<?>[] pt = found.getParameterTypes(); if (pt.length > 1) { throw new RuntimeException("Matcher constructor should have one or no arguments, but " + found + " requires " + pt.length); } Class<? extends Annotation> ac = a.annotationType(); if (!pt[0].isAssignableFrom(ac)) { throw new RuntimeException("Matcher " + cls + " could not be bound to " + ac + " cause it doesn't have constructor that takes such annotations"); } found.setAccessible(true); try { if (pt.length == 0) { return found.newInstance(); } else { return found.newInstance(a); } } catch (Exception e) { throw new RuntimeException(e); } } }