GuavaのEventBusにStickyEvent機能を追加します(全面的なテストは行われていませんので、参照は慎重にしてください)


import com.google.common.collect.Multimap
import com.google.common.eventbus.EventBus as GuavaEventBus

import java.util.concurrent.ConcurrentHashMap
static { // Version 0.3
    def stickyMaps = new WeakHashMap<Object, Map<Class, Object>>()
    def getStickyEvents = { GuavaEventBus bus ->
        def events = stickyMaps.get(bus)
        if (!events) {
            synchronized (stickyMaps) {
                events = stickyMaps.get(bus)
                if (!events) {
                    events = new ConcurrentHashMap<Class, Object>()
                    stickyMaps.put(bus, events)
                }
            }
        }
        return events
    }
    GuavaEventBus.metaClass.registerSticky = { object ->
        def thisBus = delegate
        Multimap<Class, ?> methodsInListener = thisBus.finder.findAllSubscribers(object)
        thisBus.subscribersByTypeLock.writeLock().lock()
        try {
            thisBus.subscribersByType.putAll(methodsInListener)
            // dispatch sticky events
            methodsInListener.entries().each { e1 ->
                Class eventType = e1.key
                def wrapper = e1.value
                def stickyEvents = getStickyEvents(thisBus as GuavaEventBus)
                stickyEvents.entrySet().each { entry ->
                    Class candidateEventType = entry.key

                    if (eventType.isAssignableFrom(candidateEventType)) {
                        def stickyEvent = entry.getValue()
//                            println("sticky Dispatch $candidateEventType   Want: $eventType  $wrapper $stickyEvent")
                        thisBus.enqueueEvent(stickyEvent, wrapper)
                    }
                }
            }
            thisBus.dispatchQueuedEvents()
        } finally {
            thisBus.subscribersByTypeLock.writeLock().unlock()
        }
    }
    GuavaEventBus.metaClass.postSticky = { event ->
        def stickyEvents = getStickyEvents(delegate as GuavaEventBus)
        synchronized (stickyEvents) {
            stickyEvents.put(event.class, event)
        }
        delegate.post(event)
    }
    GuavaEventBus.metaClass.getStickyEvent = { Class eventType ->
        def stickyEvents = getStickyEvents(delegate as GuavaEventBus)
        synchronized (stickyEvents) {
            return eventType.cast(stickyEvents.get(eventType))
        }
    }
    GuavaEventBus.metaClass.removeStickyEvent = { Class eventType ->
        def stickyEvents = getStickyEvents(delegate as GuavaEventBus)
        synchronized (stickyEvents) {
            return eventType.cast(stickyEvents.remove(eventType))
        }
    }
    GuavaEventBus.metaClass.removeStickyEvent = { Object event ->
        def stickyEvents = getStickyEvents(delegate as GuavaEventBus)
        synchronized (stickyEvents) {
            def eventType = event.getClass()
            def existingEvent = stickyEvents.get(eventType)
            if (event == existingEvent) {
                stickyEvents.remove(eventType)
                return true
            } else {
                return false
            }
        }
    }
    GuavaEventBus.metaClass.removeAllStickyEvents = {
        def stickyEvents = getStickyEvents(delegate as GuavaEventBus)
        synchronized (stickyEvents) {
            stickyEvents.clear()
        }
    }
}