@@ -0,0 +1,2313 @@
+package com.github.blackrush.acara;%0A%0Aimport com.google.common.collect.ImmutableList;%0Aimport com.google.common.collect.ImmutableSet;%0A%0Aimport java.util.Map;%0Aimport java.util.Set;%0Aimport java.util.concurrent.ConcurrentHashMap;%0Aimport java.util.function.BiConsumer;%0Aimport java.util.function.BinaryOperator;%0Aimport java.util.function.Function;%0Aimport java.util.function.Supplier;%0Aimport java.util.stream.Collector;%0Aimport java.util.stream.Stream;%0A%0A/**%0A * %7B@code ClassListenerMetadataLookup%7D lookup %7B@link com.github.blackrush.acara.ListenerMetadata%7D by listener's %7B@link java.lang.Class%7D%0A * It also provide cache the result.%0A */%0Apublic abstract class ClassListenerMetadataLookup implements ListenerMetadataLookup %7B%0A%0A    private final Map%3CClass%3C?%3E, ImmutableList%3CListenerMetadata%3E%3E cache%0A            = new ConcurrentHashMap%3C%3E();%0A%0A    protected abstract Stream%3CListenerMetadata%3E lookupClass(Class%3C?%3E klass);%0A%0A    @Override%0A    public final Stream%3CListenerMetadata%3E lookup(Object listener) %7B%0A        return cache.computeIfAbsent(listener.getClass(), this::compute).stream();%0A    %7D%0A%0A    private ImmutableList%3CListenerMetadata%3E compute(Class%3C?%3E klass) %7B%0A        return lookupClass(klass).collect(collector());%0A    %7D%0A%0A    private static final Collector%3CObject, ImmutableList.Builder%3CObject%3E, ImmutableList%3CObject%3E%3E COLLECTOR%0A            = new Collector%3CObject, ImmutableList.Builder%3CObject%3E, ImmutableList%3CObject%3E%3E() %7B%0A        @Override%0A        public Supplier%3CImmutableList.Builder%3CObject%3E%3E supplier() %7B%0A            return ImmutableList::builder;%0A        %7D%0A%0A        @Override%0A        public BiConsumer%3CImmutableList.Builder%3CObject%3E, Object%3E accumulator() %7B%0A            return ImmutableList.Builder::add;%0A        %7D%0A%0A        @Override%0A        public BinaryOperator%3CImmutableList.Builder%3CObject%3E%3E combiner() %7B%0A            return (a, b) -%3E %7B a.addAll(b.build()); return a; %7D;%0A        %7D%0A%0A        @Override%0A        public Function%3CImmutableList.Builder%3CObject%3E, ImmutableList%3CObject%3E%3E finisher() %7B%0A            return ImmutableList.Builder::build;%0A        %7D%0A%0A        @Override%0A        public Set%3CCharacteristics%3E characteristics() %7B%0A            return ImmutableSet.of();%0A        %7D%0A    %7D;%0A%0A    @SuppressWarnings(%22unchecked%22)%0A    private static %3CT%3E Collector%3CT, ?, ImmutableList%3CT%3E%3E collector() %7B return (Collector) COLLECTOR; %7D%0A%7D%0A

create ClassListenerMetadataLookup