All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.gravitee.common.event.impl.EventManagerImpl Maven / Gradle / Ivy

The newest version!
/*
 * Copyright © 2015 The Gravitee team (http://gravitee.io)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.gravitee.common.event.impl;

import io.gravitee.common.event.Event;
import io.gravitee.common.event.EventListener;
import io.gravitee.common.event.EventManager;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import lombok.extern.slf4j.Slf4j;

/**
 * @author David BRASSELY (brasseld at gmail.com)
 */
@Slf4j
public class EventManagerImpl implements EventManager {

    private final Map>, List>> listeners = new ConcurrentHashMap<>();

    public , S> void publishEvent(final T type, final S content) {
        this.publishEvent(new SimpleEvent<>(type, content));
    }

    public , S> void publishEvent(final Event event) {
        log.debug("Publish event {} - {}", event.type(), event.content());
        List> eventTypeListeners =
            this.listeners.get(new ComparableEventType<>((Class) event.type().getClass()));

        if (eventTypeListeners != null && !eventTypeListeners.isEmpty()) {
            eventTypeListeners
                .stream()
                .filter(wrapper -> wrapper.events().contains(event.type()))
                .forEach(wrapper -> ((EventListenerSubscription) wrapper).eventListener().onEvent(event));
        }
    }

    public > void subscribeForEvents(EventListener eventListener, T... eventTypes) {
        if (eventTypes.length > 0) {
            Class eventTypeClass = (Class) eventTypes[0].getClass();
            EnumSet eventTypesSet = EnumSet.of(eventTypes[0], eventTypes);
            addEventListener(eventListener, eventTypeClass, eventTypesSet);
        }
    }

    public > void subscribeForEvents(EventListener eventListener, Class eventTypeClass) {
        addEventListener(eventListener, eventTypeClass, EnumSet.allOf(eventTypeClass));
    }

    private > void addEventListener(
        final EventListener eventListener,
        final Class eventTypeClass,
        final Set eventTypes
    ) {
        log.debug("Register new listener {} for event type {}", eventListener.getClass().getSimpleName(), eventTypeClass);

        this.listeners.compute(
                new ComparableEventType<>(eventTypeClass),
                (k, v) -> {
                    if (v == null) {
                        v = new CopyOnWriteArrayList<>();
                    }
                    v.add(new EventListenerSubscription<>(eventListener, eventTypes));
                    return v;
                }
            );
    }

    @Override
    public > void unsubscribeForEvents(final EventListener eventListener, final Class eventTypesClass) {
        removeEventListener(eventListener, eventTypesClass, EnumSet.allOf(eventTypesClass));
    }

    @Override
    public > void unsubscribeForEvents(final EventListener eventListener, final T... eventTypes) {
        if (eventTypes.length > 0) {
            Class eventTypeClass = (Class) eventTypes[0].getClass();
            EnumSet eventTypesSet = EnumSet.of(eventTypes[0], eventTypes);
            removeEventListener(eventListener, eventTypeClass, eventTypesSet);
        }
    }

    private > void removeEventListener(
        final EventListener eventListener,
        final Class eventTypeClass,
        final Set eventTypes
    ) {
        log.debug("Unregister listener {} for event type {}", eventListener.getClass().getSimpleName(), eventTypeClass);

        this.listeners.computeIfPresent(
                new ComparableEventType<>(eventTypeClass),
                (k, v) -> {
                    Set> removedEventListener = new HashSet<>();
                    v
                        .stream()
                        .filter(eventListenerSubscription -> eventListenerSubscription.eventListener.equals(eventListener))
                        .forEach(eventListenerSubscription -> {
                            eventListenerSubscription.events.removeAll(eventTypes);
                            if (eventListenerSubscription.events.isEmpty()) {
                                removedEventListener.add(eventListenerSubscription);
                            }
                        });
                    for (EventListenerSubscription eventListenerSubscription : removedEventListener) {
                        v.remove(eventListenerSubscription);
                    }

                    if (v.isEmpty()) {
                        return null;
                    }
                    return v;
                }
            );
    }

    private record EventListenerSubscription, S>(EventListener eventListener, Set events) {}

    private record ComparableEventType>(Class wrappedClass) implements Comparable> {
        @Override
        public int compareTo(ComparableEventType o) {
            return wrappedClass.getCanonicalName().compareTo(o.wrappedClass.getCanonicalName());
        }

        @Override
        public boolean equals(Object o) {
            if (!(o instanceof ComparableEventType)) {
                return false;
            }

            return compareTo((ComparableEventType) o) == 0;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy