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.datasource;
017
018import java.lang.reflect.Method;
019import java.util.function.Supplier;
020
021/**
022 * @author michael
023 */
024public class DataSourceKey {
025
026    /**
027     * 通过注解设置的 key
028     */
029    private static ThreadLocal<String> annotationKeyThreadLocal = new ThreadLocal<>();
030
031    /**
032     * 通过手动编码指定的 key
033     */
034    private static ThreadLocal<String> manualKeyThreadLocal = new ThreadLocal<>();
035
036    private DataSourceKey() {
037    }
038
039    public static void use(String dataSourceKey) {
040        manualKeyThreadLocal.set(dataSourceKey.trim());
041    }
042
043    public static void useWithAnnotation(String dataSourceKey) {
044        annotationKeyThreadLocal.set(dataSourceKey.trim());
045    }
046
047    public static <T> T use(String dataSourceKey, Supplier<T> supplier) {
048        String prevKey = manualKeyThreadLocal.get();
049        try {
050            manualKeyThreadLocal.set(dataSourceKey);
051            return supplier.get();
052        } finally {
053            if (prevKey != null) {
054                manualKeyThreadLocal.set(prevKey);
055            } else {
056                clear();
057            }
058        }
059    }
060
061    public static void use(String dataSourceKey, Runnable runnable) {
062        String prevKey = manualKeyThreadLocal.get();
063        try {
064            manualKeyThreadLocal.set(dataSourceKey);
065            runnable.run();
066        } finally {
067            if (prevKey != null) {
068                manualKeyThreadLocal.set(prevKey);
069            } else {
070                clear();
071            }
072        }
073    }
074
075    public static void clear() {
076        annotationKeyThreadLocal.remove();
077        manualKeyThreadLocal.remove();
078    }
079
080    public static String getByAnnotation() {
081        return annotationKeyThreadLocal.get();
082    }
083
084    public static String getByManual() {
085        return manualKeyThreadLocal.get();
086    }
087
088    public static String get() {
089        String key = manualKeyThreadLocal.get();
090        return key != null ? key : annotationKeyThreadLocal.get();
091    }
092
093    public static void setAnnotationKeyThreadLocal(ThreadLocal<String> annotationKeyThreadLocal) {
094        DataSourceKey.annotationKeyThreadLocal = annotationKeyThreadLocal;
095    }
096
097    public static void setManualKeyThreadLocal(ThreadLocal<String> manualKeyThreadLocal) {
098        DataSourceKey.manualKeyThreadLocal = manualKeyThreadLocal;
099    }
100
101    public static String getShardingDsKey(String dataSource, Object mapper, Method method, Object[] args) {
102        String shardingDsKey = DataSourceManager.getShardingDsKey(dataSource, mapper, method, args);
103        return shardingDsKey != null ? shardingDsKey : dataSource;
104    }
105}