package logbook.data; import java.util.ArrayList; import java.util.EnumMap; import java.util.List; import java.util.Map; /** * イベントをリスナーに送信するクラスです * */ public final class EventSender { private final Map<DataType, List<EventListener>> listenerMap = new EnumMap<>(DataType.class); /** * リスナーを追加します * * @param listener */ public void addEventListener(EventListener listener) { DataType[] types = this.getTypes(listener); for (DataType key : types) { List<EventListener> listeners = this.listenerMap.get(key); if (listeners == null) { listeners = new ArrayList<>(); this.listenerMap.put(key, listeners); } synchronized (listeners) { listeners.add(listener); } } } /** * リスナーを除去します * * @param listener */ public void removeEventListener(EventListener listener) { DataType[] types = this.getTypes(listener); for (DataType key : types) { List<EventListener> listeners = this.listenerMap.get(key); if (listeners != null) { synchronized (listeners) { while (!listeners.remove(listener)) { } } } } } /** * イベントを送信します(同期) * * @param type * @param data */ public void syncSendEvent(DataType type, Data data) { List<EventListener> listeners = this.listenerMap.get(type); if (listeners != null) { synchronized (listeners) { for (EventListener listener : listeners) { listener.update(type, data); } } } } /** * リスナーのターゲット注釈からデータの種類を取得します * * @param listener * @return */ private DataType[] getTypes(EventListener listener) { EventTarget target = listener.getClass().getAnnotation(EventTarget.class); if (target == null) { throw new IllegalArgumentException("リスナーにEventTarget注釈がありません"); } return target.value(); } }