/* * Copyright 2014 mango.jfaster.org * * The Mango Project licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package org.jfaster.mango.operator.generator; import org.jfaster.mango.annotation.DatabaseShardingBy; import org.jfaster.mango.annotation.Sharding; import org.jfaster.mango.annotation.ShardingBy; import org.jfaster.mango.binding.BindingParameter; import org.jfaster.mango.binding.BindingParameterInvoker; import org.jfaster.mango.binding.ParameterContext; import org.jfaster.mango.datasource.DataSourceFactoryGroup; import org.jfaster.mango.datasource.DataSourceType; import org.jfaster.mango.descriptor.ParameterDescriptor; import org.jfaster.mango.exception.DescriptionException; import org.jfaster.mango.exception.IncorrectParameterTypeException; import org.jfaster.mango.sharding.DatabaseShardingStrategy; import org.jfaster.mango.sharding.NotUseDatabaseShardingStrategy; import org.jfaster.mango.sharding.NotUseShardingStrategy; import org.jfaster.mango.util.reflect.Reflection; import org.jfaster.mango.util.reflect.TypeToken; import org.jfaster.mango.util.reflect.TypeWrapper; import javax.annotation.Nullable; import java.lang.reflect.Type; /** * @author ash */ public class DataSourceGeneratorFactory { private final DataSourceFactoryGroup dataSourceFactoryGroup; public DataSourceGeneratorFactory(DataSourceFactoryGroup dataSourceFactoryGroup) { this.dataSourceFactoryGroup = dataSourceFactoryGroup; } public DataSourceGenerator getDataSourceGenerator( DataSourceType dataSourceType, @Nullable Sharding shardingAnno, String dataSourceFactoryName, ParameterContext context) { DatabaseShardingStrategy strategy = getDatabaseShardingStrategy(shardingAnno); TypeToken<?> strategyToken = null; if (strategy != null) { strategyToken = TypeToken.of(strategy.getClass()).resolveFatherClass(DatabaseShardingStrategy.class); } int shardingParameterNum = 0; String shardingParameterName = null; String shardingParameterProperty = null; for (ParameterDescriptor pd : context.getParameterDescriptors()) { DatabaseShardingBy databaseShardingByAnno = pd.getAnnotation(DatabaseShardingBy.class); if (databaseShardingByAnno != null) { shardingParameterName = context.getParameterNameByPosition(pd.getPosition()); shardingParameterProperty = databaseShardingByAnno.value(); shardingParameterNum++; continue; // 有了@DatabaseShardingBy,则忽略@ShardingBy } ShardingBy shardingByAnno = pd.getAnnotation(ShardingBy.class); if (shardingByAnno != null) { shardingParameterName = context.getParameterNameByPosition(pd.getPosition()); shardingParameterProperty = shardingByAnno.value(); shardingParameterNum++; } } DataSourceGenerator dataSourceGenerator; if (strategy != null) { if (shardingParameterNum == 1) { BindingParameterInvoker shardingParameterInvoker = context.getBindingParameterInvoker(BindingParameter.create(shardingParameterName, shardingParameterProperty, null)); Type shardingParameterType = shardingParameterInvoker.getTargetType(); TypeWrapper tw = new TypeWrapper(shardingParameterType); Class<?> mappedClass = tw.getMappedClass(); if (mappedClass == null || tw.isIterable()) { throw new IncorrectParameterTypeException("the type of parameter Modified @DatabaseShardingBy is error, " + "type is " + shardingParameterType + ", " + "please note that @ShardingBy = @TableShardingBy + @DatabaseShardingBy"); } TypeToken<?> shardToken = TypeToken.of(shardingParameterType); if (!strategyToken.isAssignableFrom(shardToken.wrap())) { throw new ClassCastException("DatabaseShardingStrategy[" + strategy.getClass() + "]'s " + "generic type[" + strategyToken.getType() + "] must be assignable from " + "the type of parameter Modified @DatabaseShardingBy [" + shardToken.getType() + "], " + "please note that @ShardingBy = @TableShardingBy + @DatabaseShardingBy"); } dataSourceGenerator = new ShardedDataSourceGenerator(dataSourceFactoryGroup, dataSourceType, shardingParameterInvoker, strategy); } else { throw new DescriptionException("if @Sharding.databaseShardingStrategy is defined, " + "need one and only one @DatabaseShardingBy on method's parameter but found " + shardingParameterNum + ", " + "please note that @ShardingBy = @TableShardingBy + @DatabaseShardingBy"); } } else { dataSourceGenerator = new SimpleDataSourceGenerator(dataSourceFactoryGroup, dataSourceType, dataSourceFactoryName); } return dataSourceGenerator; } @Nullable private DatabaseShardingStrategy getDatabaseShardingStrategy(@Nullable Sharding shardingAnno) { if (shardingAnno == null) { return null; } Class<? extends DatabaseShardingStrategy> strategyClass = shardingAnno.databaseShardingStrategy(); if (!strategyClass.equals(NotUseDatabaseShardingStrategy.class)) { DatabaseShardingStrategy strategy = Reflection.instantiateClass(strategyClass); return strategy; } strategyClass = shardingAnno.shardingStrategy(); if (!strategyClass.equals(NotUseShardingStrategy.class)) { DatabaseShardingStrategy strategy = Reflection.instantiateClass(strategyClass); return strategy; } return null; } }