001/*
002 *  Copyright (c) 2023-2026, Agents-Flex (fuhai999@gmail.com).
003 *  <p>
004 *  Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
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 */
016
017package com.agentsflex.core.model.chat;
018
019import java.util.ArrayList;
020import java.util.Collections;
021import java.util.List;
022
023/**
024 * 全局聊天拦截器管理器。
025 * <p>
026 * 该类提供静态方法,用于注册和管理应用于所有 {@link BaseChatModel} 实例的全局拦截器。
027 * 全局拦截器会在实例级拦截器之前执行,适用于统一的日志、安全、监控等横切关注点。
028 * <p>
029 * <strong>使用建议</strong>:
030 * <ul>
031 *   <li>在应用启动阶段(如 Spring 的 {@code @PostConstruct} 或 main 方法)注册全局拦截器</li>
032 *   <li>避免在运行时动态修改,以确保线程安全和行为一致性</li>
033 * </ul>
034 */
035public final class GlobalChatInterceptors {
036
037    /**
038     * 全局拦截器列表,使用 synchronized 保证线程安全
039     */
040    private static final List<ChatInterceptor> GLOBAL_INTERCEPTORS = new ArrayList<>();
041
042    /**
043     * 私有构造函数,防止实例化
044     */
045    private GlobalChatInterceptors() {
046        // 工具类,禁止实例化
047    }
048
049    /**
050     * 注册一个全局拦截器。
051     * <p>
052     * 该拦截器将应用于所有后续创建的 {@link BaseChatModel} 实例。
053     *
054     * @param interceptor 要注册的拦截器,不能为 null
055     * @throws IllegalArgumentException 如果 interceptor 为 null
056     */
057    public static synchronized void addInterceptor(ChatInterceptor interceptor) {
058        if (interceptor == null) {
059            throw new IllegalArgumentException("ChatInterceptor must not be null");
060        }
061        GLOBAL_INTERCEPTORS.add(interceptor);
062    }
063
064    /**
065     * 批量注册多个全局拦截器。
066     * <p>
067     * 拦截器将按列表顺序添加,并在执行时按相同顺序调用。
068     *
069     * @param interceptors 拦截器列表,不能为 null;列表中元素不能为 null
070     * @throws IllegalArgumentException 如果 interceptors 为 null 或包含 null 元素
071     */
072    public static synchronized void addInterceptors(List<ChatInterceptor> interceptors) {
073        if (interceptors == null) {
074            throw new IllegalArgumentException("Interceptor list must not be null");
075        }
076        for (ChatInterceptor interceptor : interceptors) {
077            if (interceptor == null) {
078                throw new IllegalArgumentException("Interceptor list must not contain null elements");
079            }
080        }
081        GLOBAL_INTERCEPTORS.addAll(interceptors);
082    }
083
084    /**
085     * 获取当前注册的全局拦截器列表的不可变视图。
086     * <p>
087     * 该方法供 {@link BaseChatModel} 内部使用,返回值不应被外部修改。
088     *
089     * @return 不可变的全局拦截器列表
090     */
091    public static List<ChatInterceptor> getInterceptors() {
092        return Collections.unmodifiableList(GLOBAL_INTERCEPTORS);
093    }
094
095    /**
096     * 清空所有全局拦截器。
097     * <p>
098     * <strong>仅用于测试环境</strong>,生产环境应避免调用。
099     */
100    public static synchronized void clear() {
101        GLOBAL_INTERCEPTORS.clear();
102    }
103
104    /**
105     * 获取当前全局拦截器的数量。
106     * <p>
107     * 用于诊断或监控。
108     *
109     * @return 拦截器数量
110     */
111    public static synchronized int size() {
112        return GLOBAL_INTERCEPTORS.size();
113    }
114}