001/**
002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (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 io.jboot.db;
017
018import com.jfinal.plugin.activerecord.Model;
019import io.jboot.db.annotation.Table;
020import io.jboot.db.datasource.DataSourceConfig;
021import io.jboot.db.model.JbootModelConfig;
022import io.jboot.utils.AnnotationUtil;
023import io.jboot.utils.ArrayUtil;
024import io.jboot.utils.ClassScanner;
025import io.jboot.utils.StrUtil;
026
027import java.util.*;
028
029/**
030 * @author Michael Yang 杨福海 (fuhai999@gmail.com)
031 * @version V1.0
032 */
033public class TableInfoManager {
034
035    private List<TableInfo> allTableInfos;
036
037
038    private static TableInfoManager instance = new TableInfoManager();
039
040    public static TableInfoManager me() {
041        return instance;
042    }
043
044
045    /**
046     * 初始化该数据下的 tableInfos 对象,其用来存储该数据源下有哪些表
047     *
048     * @param dataSourceConfig
049     */
050    public void initConfigMappingTables(DataSourceConfig dataSourceConfig) {
051
052        // 该数据源下配置的所有表
053        Set<String> configTables = StrUtil.isNotBlank(dataSourceConfig.getTable())
054                ? StrUtil.splitToSetByComma(dataSourceConfig.getTable())
055                : null;
056
057        // 该数据源下排除的所有表
058        Set<String> configExTables = StrUtil.isNotBlank(dataSourceConfig.getExTable())
059                ? StrUtil.splitToSetByComma(dataSourceConfig.getExTable())
060                : null;
061
062        // 所有的表信息
063        List<TableInfo> allTableInfos = getAllTableInfos();
064
065
066        for (TableInfo tableInfo : allTableInfos) {
067
068            // 排除配置 jboot.datasource.extable 包含了这个表
069            if (configExTables != null && configExTables.contains(tableInfo.getTableName())) {
070                continue;
071            }
072
073            if (configTables != null && configTables.contains(tableInfo.getTableName())) {
074                dataSourceConfig.addTableInfo(tableInfo, true);
075            }
076
077            if (tableInfo.getDatasourceNames().contains(dataSourceConfig.getName())) {
078                dataSourceConfig.addTableInfo(tableInfo, true);
079            }
080
081            // 排除所有表,但允许当前数据源自己指定的表,指定的表不被排除
082            if (configExTables != null && configExTables.contains("*")) {
083                continue;
084            }
085
086            // 注解 @Table(datasource="xxxx") 指定了数据源,而且当前数据源未匹配
087            if (tableInfo.getDatasourceNames().size() > 0) {
088                continue;
089            }
090
091            // 如果当前的数据源已经配置了绑定的表,且未当前表未命中,不让其他表添加到当前数据源
092            if (configTables != null && configTables.size() > 0) {
093                continue;
094            }
095
096            dataSourceConfig.addTableInfo(tableInfo, false);
097        }
098
099    }
100
101    private List<TableInfo> getAllTableInfos() {
102        if (allTableInfos == null) {
103            allTableInfos = new ArrayList<>();
104            initTableInfos(allTableInfos);
105        }
106        return allTableInfos;
107    }
108
109
110    private void initTableInfos(List<TableInfo> tableInfoList) {
111        List<Class<Model>> modelClassList = ClassScanner.scanSubClass(Model.class);
112        if (ArrayUtil.isNullOrEmpty(modelClassList)) {
113            return;
114        }
115
116        String scanPackage = JbootModelConfig.getConfig().getScanPackage();
117        String unscanPackage = JbootModelConfig.getConfig().getUnscanPackage();
118
119        for (Class<Model> clazz : modelClassList) {
120            Table tb = clazz.getAnnotation(Table.class);
121            if (tb == null) {
122                continue;
123            }
124
125            if (StrUtil.isNotBlank(scanPackage)
126                    && clazz.getName().startsWith(scanPackage.trim())) {
127                addTable(tableInfoList, clazz, tb);
128                continue;
129            }
130
131
132            if (StrUtil.isNotBlank(unscanPackage)
133                    && ("*".equals(unscanPackage.trim()) || clazz.getName().startsWith(unscanPackage.trim()))) {
134                continue;
135            }
136
137            addTable(tableInfoList, clazz, tb);
138        }
139
140    }
141
142    private void addTable(List<TableInfo> tableInfoList, Class<Model> modelClass, Table tb) {
143        TableInfo tableInfo = new TableInfo();
144        tableInfo.setModelClass(modelClass);
145        tableInfo.setPrimaryKey(AnnotationUtil.get(tb.primaryKey()));
146        tableInfo.setTableName(AnnotationUtil.get(tb.tableName()));
147        tableInfo.setDatasource(AnnotationUtil.get(tb.datasource()));
148
149        tableInfoList.add(tableInfo);
150    }
151}