001/**
002 * Copyright (c) 2022-2023, Mybatis-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 */
016package com.mybatisflex.core;
017
018import com.mybatisflex.annotation.InsertListener;
019import com.mybatisflex.annotation.KeyType;
020import com.mybatisflex.annotation.SetListener;
021import com.mybatisflex.annotation.UpdateListener;
022import com.mybatisflex.core.dialect.DbType;
023import org.apache.ibatis.session.Configuration;
024import org.apache.ibatis.session.SqlSessionFactory;
025
026import java.util.*;
027import java.util.concurrent.ConcurrentHashMap;
028
029/**
030 * 全局配置文件
031 */
032public class FlexGlobalConfig {
033
034    /**
035     * 启动是否打印 banner 和 版本好
036     */
037    private boolean printBanner = true;
038
039    /**
040     * 默认使用 Mysql 数据库类型
041     */
042    private DbType dbType = DbType.MYSQL;
043
044    /**
045     * Mybatis 配置
046     */
047    private Configuration configuration;
048
049    /**
050     * 创建好的 sqlSessionFactory
051     */
052    private SqlSessionFactory sqlSessionFactory;
053
054    /**
055     * 全局的 ID 生成策略配置,当 @Id 未配置 或者 配置 KeyType 为 None 时
056     * 使用当前全局配置
057     */
058    private KeyConfig keyConfig;
059
060    /**
061     * entity 的监听器
062     */
063    private Map<Class<?>, SetListener> entitySetListeners = new ConcurrentHashMap<>();
064    private Map<Class<?>, UpdateListener> entityUpdateListeners = new ConcurrentHashMap<>();
065    private Map<Class<?>, InsertListener> entityInsertListeners = new ConcurrentHashMap<>();
066
067
068    /**
069     * 逻辑删除的相关配置
070     */
071    private Object normalValueOfLogicDelete = FlexConsts.LOGIC_DELETE_NORMAL;
072    private Object deletedValueOfLogicDelete = FlexConsts.LOGIC_DELETE_DELETED;
073
074    public boolean isPrintBanner() {
075        return printBanner;
076    }
077
078    public void setPrintBanner(boolean printBanner) {
079        this.printBanner = printBanner;
080    }
081
082    public DbType getDbType() {
083        return dbType;
084    }
085
086    public void setDbType(DbType dbType) {
087        this.dbType = dbType;
088    }
089
090    public Configuration getConfiguration() {
091        return configuration;
092    }
093
094    public void setConfiguration(Configuration configuration) {
095        this.configuration = configuration;
096    }
097
098    public SqlSessionFactory getSqlSessionFactory() {
099        return sqlSessionFactory;
100    }
101
102    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
103        this.sqlSessionFactory = sqlSessionFactory;
104    }
105
106    public KeyConfig getKeyConfig() {
107        return keyConfig;
108    }
109
110    public void setKeyConfig(KeyConfig keyConfig) {
111        this.keyConfig = keyConfig;
112    }
113
114    public Map<Class<?>, SetListener> getEntitySetListeners() {
115        return entitySetListeners;
116    }
117
118    public void setEntitySetListeners(Map<Class<?>, SetListener> entitySetListeners) {
119        this.entitySetListeners = entitySetListeners;
120    }
121
122    public Map<Class<?>, UpdateListener> getEntityUpdateListeners() {
123        return entityUpdateListeners;
124    }
125
126    public void setEntityUpdateListeners(Map<Class<?>, UpdateListener> entityUpdateListeners) {
127        this.entityUpdateListeners = entityUpdateListeners;
128    }
129
130    public Map<Class<?>, InsertListener> getEntityInsertListeners() {
131        return entityInsertListeners;
132    }
133
134    public void setEntityInsertListeners(Map<Class<?>, InsertListener> entityInsertListeners) {
135        this.entityInsertListeners = entityInsertListeners;
136    }
137
138    public void registerSetListener(SetListener listener, Class<?>... classes) {
139        for (Class<?> aClass : classes) {
140            entitySetListeners.put(aClass, listener);
141        }
142    }
143
144    public void registerUpdateListener(UpdateListener listener, Class<?>... classes) {
145        for (Class<?> aClass : classes) {
146            entityUpdateListeners.put(aClass, listener);
147        }
148    }
149
150    public void registerInsertListener(InsertListener listener, Class<?>... classes) {
151        for (Class<?> aClass : classes) {
152            entityInsertListeners.put(aClass, listener);
153        }
154    }
155
156    public SetListener getSetListener(Class<?> entityClass) {
157        return entitySetListeners.get(entityClass);
158    }
159
160    /**
161     * 获取支持该 {@code entityClass} 的set监听器
162     * <p>当registerClass是entityClass的本身或其超类时,则视为支持</p>
163     *
164     * @param entityClass 实体class
165     * @return UpdateListener
166     */
167    public List<SetListener> getSupportedSetListener(Class<?> entityClass, boolean interfaceOnly) {
168
169        Map<Class<?>, SetListener> map = new HashMap<>();
170        if (!interfaceOnly) {
171            doGetSupportedSetListener(entityClass, map);
172        }
173
174        while (entityClass.getSuperclass() != null) {
175            Class<?>[] interfaces = entityClass.getInterfaces();
176            for (Class<?> interfaceClass : interfaces) {
177                doGetSupportedSetListener(interfaceClass, map);
178            }
179            entityClass = entityClass.getSuperclass();
180        }
181
182        return new ArrayList<>(map.values());
183    }
184
185
186    private void doGetSupportedSetListener(Class<?> childClass, Map<Class<?>, SetListener> listeners) {
187        SetListener setListener = null;
188        while (setListener == null && childClass != null) {
189            setListener = entitySetListeners.get(childClass);
190            childClass = childClass.getSuperclass();
191        }
192
193        if (setListener != null) {
194            listeners.put(childClass, setListener);
195        }
196    }
197
198
199    public UpdateListener getUpdateListener(Class<?> entityClass) {
200        return entityUpdateListeners.get(entityClass);
201    }
202
203    /**
204     * 获取支持该 {@code entityClass} 的update监听器
205     * <p>当registerClass是entityClass的本身或其超类时,则视为支持</p>
206     *
207     * @param entityClass 实体class
208     * @return UpdateListener
209     */
210    public List<UpdateListener> getSupportedUpdateListener(Class<?> entityClass, boolean interfaceOnly) {
211
212        Map<Class<?>, UpdateListener> map = new HashMap<>();
213        if (!interfaceOnly) {
214            doGetSupportedUpdateListener(entityClass, map);
215        }
216
217        while (entityClass.getSuperclass() != null) {
218            Class<?>[] interfaces = entityClass.getInterfaces();
219            for (Class<?> interfaceClass : interfaces) {
220                doGetSupportedUpdateListener(interfaceClass, map);
221            }
222            entityClass = entityClass.getSuperclass();
223        }
224
225        return new ArrayList<>(map.values());
226    }
227
228
229    private void doGetSupportedUpdateListener(Class<?> childClass, Map<Class<?>, UpdateListener> listeners) {
230        UpdateListener updateListener = null;
231        while (updateListener == null && childClass != null) {
232            updateListener = entityUpdateListeners.get(childClass);
233            childClass = childClass.getSuperclass();
234        }
235
236        if (updateListener != null) {
237            listeners.put(childClass, updateListener);
238        }
239    }
240
241
242    public InsertListener getInsertListener(Class<?> entityClass) {
243        return entityInsertListeners.get(entityClass);
244    }
245
246    /**
247     * 获取支持该 {@code entityClass} 的insert监听器
248     * <p>当registerClass是entityClass的本身或其超类时,则视为支持</p>
249     *
250     * @param entityClass 实体class
251     * @return InsertListener
252     */
253    public List<InsertListener> getSupportedInsertListener(Class<?> entityClass, boolean interfaceOnly) {
254
255        Map<Class<?>, InsertListener> map = new HashMap<>();
256        if (!interfaceOnly) {
257            doGetSupportedInsertListener(entityClass, map);
258        }
259
260        while (entityClass.getSuperclass() != null) {
261            Class<?>[] interfaces = entityClass.getInterfaces();
262            for (Class<?> interfaceClass : interfaces) {
263                doGetSupportedInsertListener(interfaceClass, map);
264            }
265            entityClass = entityClass.getSuperclass();
266        }
267
268        return new ArrayList<>(map.values());
269    }
270
271
272    private void doGetSupportedInsertListener(Class<?> childClass, Map<Class<?>, InsertListener> listeners) {
273        InsertListener insertListener = null;
274        while (insertListener == null && childClass != null) {
275            insertListener = entityInsertListeners.get(childClass);
276            childClass = childClass.getSuperclass();
277        }
278
279        if (insertListener != null) {
280            listeners.put(childClass, insertListener);
281        }
282    }
283
284
285    public Object getNormalValueOfLogicDelete() {
286        return normalValueOfLogicDelete;
287    }
288
289    public void setNormalValueOfLogicDelete(Object normalValueOfLogicDelete) {
290        if (normalValueOfLogicDelete == null) {
291            throw new NullPointerException("normalValueOfLogicDelete can not be null.");
292        }
293        this.normalValueOfLogicDelete = normalValueOfLogicDelete;
294    }
295
296    public Object getDeletedValueOfLogicDelete() {
297        return deletedValueOfLogicDelete;
298    }
299
300    public void setDeletedValueOfLogicDelete(Object deletedValueOfLogicDelete) {
301        if (deletedValueOfLogicDelete == null) {
302            throw new NullPointerException("deletedValueOfLogicDelete can not be null.");
303        }
304        this.deletedValueOfLogicDelete = deletedValueOfLogicDelete;
305    }
306
307    public static ConcurrentHashMap<String, FlexGlobalConfig> getGlobalConfigs() {
308        return globalConfigs;
309    }
310
311    public static void setGlobalConfigs(ConcurrentHashMap<String, FlexGlobalConfig> globalConfigs) {
312        FlexGlobalConfig.globalConfigs = globalConfigs;
313    }
314
315
316    /**
317     * 对应的是 注解 {@link com.mybatisflex.annotation.Id} 的配置
318     */
319    public static class KeyConfig {
320        private KeyType keyType;
321        private String value;
322        private boolean before = true;
323
324        public KeyType getKeyType() {
325            return keyType;
326        }
327
328        public void setKeyType(KeyType keyType) {
329            this.keyType = keyType;
330        }
331
332        public String getValue() {
333            return value;
334        }
335
336        public void setValue(String value) {
337            this.value = value;
338        }
339
340        public boolean isBefore() {
341            return before;
342        }
343
344        public void setBefore(boolean before) {
345            this.before = before;
346        }
347    }
348
349
350    /////static factory methods/////
351    private static ConcurrentHashMap<String, FlexGlobalConfig> globalConfigs = new ConcurrentHashMap<>();
352    private static FlexGlobalConfig defaultConfig = new FlexGlobalConfig();
353
354    public static FlexGlobalConfig getDefaultConfig() {
355        return defaultConfig;
356    }
357
358    public static void setDefaultConfig(FlexGlobalConfig config) {
359        if (config == null) {
360            throw new NullPointerException("config must not be null.");
361        }
362        defaultConfig = config;
363    }
364
365    public static FlexGlobalConfig getConfig(Configuration configuration) {
366        return getConfig(configuration.getEnvironment().getId());
367    }
368
369    public static FlexGlobalConfig getConfig(String environmentId) {
370        return globalConfigs.get(environmentId);
371    }
372
373    public static synchronized void setConfig(String id, FlexGlobalConfig config) {
374        setConfig(id, config, true);
375    }
376
377    /**
378     * 设置全局配置
379     *
380     * @param id            环境id
381     * @param config        全局配置
382     * @param copyToDefault 自动指定默认全局配置(在多源时,方便由注解指定默认源)
383     */
384    public static synchronized void setConfig(String id, FlexGlobalConfig config, boolean copyToDefault) {
385        //first setConfig,copy the config to default
386        if (copyToDefault && globalConfigs.isEmpty()) {
387
388            defaultConfig.setSqlSessionFactory(config.sqlSessionFactory);
389            defaultConfig.setDbType(config.dbType);
390            defaultConfig.setConfiguration(config.configuration);
391
392            if (defaultConfig.getKeyConfig() == null
393                    && config.keyConfig != null) {
394                defaultConfig.setKeyConfig(config.keyConfig);
395            }
396
397            config = defaultConfig;
398        }
399
400        globalConfigs.put(id, config);
401    }
402}