001/** 002 * Copyright (c) 2025-2026, Michael Yang 杨福海 (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.gnu.org/licenses/lgpl-3.0.txt 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package dev.tinyflow.core.chain; 017 018import dev.tinyflow.core.chain.listener.ChainErrorListener; 019import dev.tinyflow.core.chain.listener.ChainEventListener; 020import dev.tinyflow.core.chain.listener.ChainOutputListener; 021import dev.tinyflow.core.chain.listener.NodeErrorListener; 022import dev.tinyflow.core.util.MapUtil; 023import org.slf4j.Logger; 024import org.slf4j.LoggerFactory; 025 026import java.util.List; 027import java.util.Map; 028import java.util.concurrent.ConcurrentHashMap; 029import java.util.concurrent.CopyOnWriteArrayList; 030 031public class EventManager { 032 033 private static final Logger log = LoggerFactory.getLogger(EventManager.class); 034 035 protected final Map<Class<?>, List<ChainEventListener>> eventListeners = new ConcurrentHashMap<>(); 036 protected final List<ChainOutputListener> outputListeners = new CopyOnWriteArrayList<>(); 037 protected final List<ChainErrorListener> chainErrorListeners = new CopyOnWriteArrayList<>(); 038 protected final List<NodeErrorListener> nodeErrorListeners = new CopyOnWriteArrayList<>(); 039 protected final Map<String, Object> otherListeners = new ConcurrentHashMap<>(); 040 041 /** 042 * ---------- 通用事件监听器 ---------- 043 */ 044 public void addEventListener(Class<? extends Event> eventClass, ChainEventListener listener) { 045 MapUtil.computeIfAbsent(eventListeners, eventClass, k -> { 046 CopyOnWriteArrayList<ChainEventListener> objects = new CopyOnWriteArrayList<>(); 047 objects.add(listener); 048 return objects; 049 }); 050 } 051 052 public void addEventListener(ChainEventListener listener) { 053 addEventListener(Event.class, listener); 054 } 055 056 public void removeEventListener(Class<? extends Event> eventClass, ChainEventListener listener) { 057 List<ChainEventListener> list = eventListeners.get(eventClass); 058 if (list != null) list.remove(listener); 059 } 060 061 public void removeEventListener(ChainEventListener listener) { 062 for (List<ChainEventListener> list : eventListeners.values()) { 063 list.remove(listener); 064 } 065 } 066 067 public void notifyEvent(Event event, Chain chain) { 068 for (Map.Entry<Class<?>, List<ChainEventListener>> entry : eventListeners.entrySet()) { 069 if (entry.getKey().isInstance(event)) { 070 for (ChainEventListener listener : entry.getValue()) { 071 try { 072 listener.onEvent(event, chain); 073 } catch (Exception e) { 074 log.error("Error in event listener: {}", e, e); 075 } 076 } 077 } 078 } 079 } 080 081 /** 082 * ---------- Output Listener ---------- 083 */ 084 public void addOutputListener(ChainOutputListener listener) { 085 outputListeners.add(listener); 086 } 087 088 public void removeOutputListener(ChainOutputListener listener) { 089 outputListeners.remove(listener); 090 } 091 092 public void notifyOutput(Chain chain, Node node, Object response) { 093 for (ChainOutputListener listener : outputListeners) { 094 try { 095 listener.onOutput(chain, node, response); 096 } catch (Exception e) { 097 log.error("Error in output listener: {}", e.toString(), e); 098 } 099 } 100 } 101 102 /** 103 * ---------- Chain Error Listener ---------- 104 */ 105 public void addChainErrorListener(ChainErrorListener listener) { 106 chainErrorListeners.add(listener); 107 } 108 109 public void removeChainErrorListener(ChainErrorListener listener) { 110 chainErrorListeners.remove(listener); 111 } 112 113 public void notifyChainError(Throwable error, Chain chain) { 114 for (ChainErrorListener listener : chainErrorListeners) { 115 try { 116 listener.onError(error, chain); 117 } catch (Exception e) { 118 log.error("Error in chain error listener: {}", e, e); 119 } 120 } 121 } 122 123 /** 124 * ---------- Node Error Listener ---------- 125 */ 126 public void addNodeErrorListener(NodeErrorListener listener) { 127 nodeErrorListeners.add(listener); 128 } 129 130 public void removeNodeErrorListener(NodeErrorListener listener) { 131 nodeErrorListeners.remove(listener); 132 } 133 134 public void notifyNodeError(Throwable error, Node node, Map<String, Object> result, Chain chain) { 135 for (NodeErrorListener listener : nodeErrorListeners) { 136 try { 137 listener.onError(error, node, result, chain); 138 } catch (Exception e) { 139 log.error("Error in node error listener: {}", e.toString(), e); 140 } 141 } 142 } 143 144 public void addOtherListener(String key, Object listener) { 145 otherListeners.put(key, listener); 146 } 147 148 public void removeOtherListener(String key) { 149 otherListeners.remove(key); 150 } 151 152 public <T> T getOtherListener(String key) { 153 //noinspection unchecked 154 return (T) otherListeners.get(key); 155 } 156}