package com.jty.wsxt.infrastructure;


import java.util.ArrayList;
import java.util.List;

/**
 * 领域事件发布者
 *
 * @author manjiajie
 * @since 2019-6-10 21:03:55
 */
public class DomainEventPublisher {

    private static final ThreadLocal<List> subscribers=new ThreadLocal<>();

    private static final ThreadLocal<Boolean> publishing=
            new ThreadLocal<Boolean>(){
                protected Boolean initialValue(){
                    return Boolean.FALSE;
                }
            };

    public static DomainEventPublisher instance(){
        return new DomainEventPublisher();
    }

    public DomainEventPublisher(){
        super();
    }

    public <T> void publish(final T domainEvent){
        if(publishing.get()){
            return;
        }
        try{
            publishing.set(Boolean.TRUE);
            List<DomainEventSubscriber<T>> registeredSubscribers=subscribers.get();
            if(registeredSubscribers!=null){
                Class<?> eventType=domainEvent.getClass();
                for(DomainEventSubscriber<T> subscriber:registeredSubscribers){
                    Class<?> subscribedTo=subscriber.subscribedToEventType();
                    if(subscribedTo==eventType||subscribedTo== DomainEvent.class){
                        subscriber.handleEvent(domainEvent);
                    }
                }
            }
        }finally {
            publishing.set(Boolean.FALSE);
        }
    }
    public DomainEventPublisher reset(){
        if(!publishing.get()){
            subscribers.set(null);
        }
        return this;
    }

    public <T> void subscriber(DomainEventSubscriber<T> subscriber){
        if(publishing.get()){
            return;
        }
        List<DomainEventSubscriber<T>> registeredSubscribers=subscribers.get();
        if(registeredSubscribers==null){
            registeredSubscribers=new ArrayList<>();
            subscribers.set(registeredSubscribers);
        }
        registeredSubscribers.add(subscriber);
    }

}