Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
terrymanu committed Apr 6, 2016
1 parent 69121ed commit ebaf67a
Show file tree
Hide file tree
Showing 76 changed files with 522 additions and 495 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,30 @@
import com.dangdang.ddframe.rdb.sharding.config.common.api.config.ShardingRuleConfig;
import com.dangdang.ddframe.rdb.sharding.config.common.api.config.StrategyConfig;
import com.dangdang.ddframe.rdb.sharding.config.common.api.config.TableRuleConfig;
import com.dangdang.ddframe.rdb.sharding.config.common.internal.ConfigUtil;
import com.dangdang.ddframe.rdb.sharding.config.common.internal.algorithm.ClosureDatabaseShardingAlgorithm;
import com.dangdang.ddframe.rdb.sharding.config.common.internal.algorithm.ClosureTableShardingAlgorithm;
import com.dangdang.ddframe.rdb.sharding.config.common.internal.parser.InlineParser;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.MapUtils;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
* 分片规则构建器.
*
* @author gaohongtao
*/
@AllArgsConstructor
public class ShardingRuleBuilder {

private final String logRoot;
Expand All @@ -65,21 +68,11 @@ public class ShardingRuleBuilder {
private final ShardingRuleConfig shardingRuleConfig;

public ShardingRuleBuilder(final ShardingRuleConfig shardingRuleConfig) {
logRoot = "default";
externalDataSourceMap = new HashMap<>();
this.shardingRuleConfig = shardingRuleConfig;
this("default", shardingRuleConfig);
}

public ShardingRuleBuilder(final String logRoot, final ShardingRuleConfig shardingRuleConfig) {
this.logRoot = logRoot;
externalDataSourceMap = new HashMap<>();
this.shardingRuleConfig = shardingRuleConfig;
}

public ShardingRuleBuilder(final String logRoot, final Map<String, DataSource> externalDataSourceMap, final ShardingRuleConfig shardingRuleConfig) {
this.logRoot = logRoot;
this.externalDataSourceMap = externalDataSourceMap;
this.shardingRuleConfig = shardingRuleConfig;
this(logRoot, Collections.<String, DataSource> emptyMap(), shardingRuleConfig);
}

/**
Expand All @@ -89,8 +82,8 @@ public ShardingRuleBuilder(final String logRoot, final Map<String, DataSource> e
*/
public ShardingRule build() {
DataSourceRule dataSourceRule = buildDataSourceRule();
Collection<TableRule> tableRules = buildTableRule(dataSourceRule);
return new ShardingRule(dataSourceRule, tableRules, buildBindingTableRule(tableRules),
Collection<TableRule> tableRules = buildTableRules(dataSourceRule);
return new ShardingRule(dataSourceRule, tableRules, buildBindingTableRules(tableRules),
buildShardingStrategy(shardingRuleConfig.getDefaultDatabaseStrategy(), DatabaseShardingStrategy.class),
buildShardingStrategy(shardingRuleConfig.getDefaultTableStrategy(), TableShardingStrategy.class));
}
Expand All @@ -100,20 +93,21 @@ private DataSourceRule buildDataSourceRule() {
return !shardingRuleConfig.getDataSource().isEmpty() ? new DataSourceRule(shardingRuleConfig.getDataSource()) : new DataSourceRule(externalDataSourceMap);
}

private Collection<TableRule> buildTableRule(final DataSourceRule dataSourceRule) {
private Collection<TableRule> buildTableRules(final DataSourceRule dataSourceRule) {
Collection<TableRule> result = new ArrayList<>(shardingRuleConfig.getTables().size());
for (Map.Entry<String, TableRuleConfig> each : shardingRuleConfig.getTables().entrySet()) {
result.add(new TableRule(each.getKey(), ConfigUtil.transformCommaStringToList(each.getValue().getActualTables()), dataSourceRule,
for (Entry<String, TableRuleConfig> each : shardingRuleConfig.getTables().entrySet()) {
result.add(new TableRule(each.getKey(), new InlineParser(each.getValue().getActualTables()).evaluate(), dataSourceRule,
buildShardingStrategy(each.getValue().getDatabaseStrategy(), DatabaseShardingStrategy.class),
buildShardingStrategy(each.getValue().getTableStrategy(), TableShardingStrategy.class)));
}
return result;
}

private Collection<BindingTableRule> buildBindingTableRule(final Collection<TableRule> tableRules) {
private Collection<BindingTableRule> buildBindingTableRules(final Collection<TableRule> tableRules) {
Collection<BindingTableRule> result = new ArrayList<>(shardingRuleConfig.getBindingTables().size());
for (BindingTableRuleConfig each : shardingRuleConfig.getBindingTables()) {
result.add(new BindingTableRule(Lists.transform(ConfigUtil.transformCommaStringToList(each.getTableNames()), new Function<String, TableRule>() {
result.add(new BindingTableRule(Lists.transform(new InlineParser(each.getTableNames()).split(), new Function<String, TableRule>() {

@Override
public TableRule apply(final String input) {
return findTableRuleByLogicTableName(tableRules, input);
Expand All @@ -139,36 +133,34 @@ private <T extends ShardingStrategy> T buildShardingStrategy(final StrategyConfi
Preconditions.checkArgument(Strings.isNullOrEmpty(config.getAlgorithmExpression()) && !Strings.isNullOrEmpty(config.getAlgorithmClassName())
|| !Strings.isNullOrEmpty(config.getAlgorithmExpression()) && Strings.isNullOrEmpty(config.getAlgorithmClassName()));
Preconditions.checkState(returnClass.isAssignableFrom(DatabaseShardingStrategy.class) || returnClass.isAssignableFrom(TableShardingStrategy.class), "Sharding-JDBC: returnClass is illegal");
List<String> shardingColumns = ConfigUtil.transformCommaStringToList(config.getShardingColumns());
if (!Strings.isNullOrEmpty(config.getAlgorithmClassName())) {
return buildClassNameAlgorithmShardingStrategy(shardingColumns, config.getAlgorithmClassName(), returnClass);
} else {
return buildExpressionAlgorithmShardingStrategy(shardingColumns, config.getAlgorithmExpression(), returnClass);
List<String> shardingColumns = new InlineParser(config.getShardingColumns()).split();
if (Strings.isNullOrEmpty(config.getAlgorithmClassName())) {
return buildShardingAlgorithmExpression(shardingColumns, config.getAlgorithmExpression(), returnClass);
}
return buildShardingAlgorithmClassName(shardingColumns, config.getAlgorithmClassName(), returnClass);
}

@SuppressWarnings("unchecked")
private <T extends ShardingStrategy> T buildShardingAlgorithmExpression(final List<String> shardingColumns, final String algorithmExpression, final Class<T> returnClass) {
return returnClass.isAssignableFrom(DatabaseShardingStrategy.class) ? (T) new DatabaseShardingStrategy(shardingColumns, new ClosureDatabaseShardingAlgorithm(algorithmExpression, logRoot))
: (T) new TableShardingStrategy(shardingColumns, new ClosureTableShardingAlgorithm(algorithmExpression, logRoot));
}

@SuppressWarnings("unchecked")
private <T extends ShardingStrategy> T buildClassNameAlgorithmShardingStrategy(final List<String> shardingColumns, final String algorithmClassName, final Class<T> returnClass) {
private <T extends ShardingStrategy> T buildShardingAlgorithmClassName(final List<String> shardingColumns, final String algorithmClassName, final Class<T> returnClass) {
ShardingAlgorithm shardingAlgorithm;
try {
shardingAlgorithm = (ShardingAlgorithm) Class.forName(algorithmClassName).newInstance();
} catch (final InstantiationException | IllegalAccessException | ClassNotFoundException e) {
throw new IllegalArgumentException(e);
} catch (final InstantiationException | IllegalAccessException | ClassNotFoundException ex) {
throw new IllegalArgumentException(ex);
}
Preconditions.checkState(shardingAlgorithm instanceof SingleKeyShardingAlgorithm || shardingAlgorithm instanceof MultipleKeysShardingAlgorithm, "Sharding-JDBC: algorithmClassName is illegal");
if (shardingAlgorithm instanceof SingleKeyShardingAlgorithm) {
Preconditions.checkArgument(shardingColumns.size() == 1, "Sharding-JDBC: SingleKeyShardingAlgorithm must match only ONE shading column");
Preconditions.checkArgument(1 == shardingColumns.size(), "Sharding-JDBC: SingleKeyShardingAlgorithm must have only ONE sharding column");
return returnClass.isAssignableFrom(DatabaseShardingStrategy.class) ? (T) new DatabaseShardingStrategy(shardingColumns.get(0), (SingleKeyDatabaseShardingAlgorithm<?>) shardingAlgorithm)
: (T) new TableShardingStrategy(shardingColumns.get(0), (SingleKeyTableShardingAlgorithm<?>) shardingAlgorithm);
} else {
return returnClass.isAssignableFrom(DatabaseShardingStrategy.class) ? (T) new DatabaseShardingStrategy(shardingColumns, (MultipleKeysDatabaseShardingAlgorithm) shardingAlgorithm)
: (T) new TableShardingStrategy(shardingColumns, (MultipleKeysTableShardingAlgorithm) shardingAlgorithm);
}
}

@SuppressWarnings("unchecked")
private <T extends ShardingStrategy> T buildExpressionAlgorithmShardingStrategy(final List<String> shardingColumns, final String algorithmExpression, final Class<T> returnClass) {
return returnClass.isAssignableFrom(DatabaseShardingStrategy.class) ? (T) new DatabaseShardingStrategy(shardingColumns, new ClosureDatabaseShardingAlgorithm(algorithmExpression, logRoot))
: (T) new TableShardingStrategy(shardingColumns, new ClosureTableShardingAlgorithm(algorithmExpression, logRoot));
return returnClass.isAssignableFrom(DatabaseShardingStrategy.class) ? (T) new DatabaseShardingStrategy(shardingColumns, (MultipleKeysDatabaseShardingAlgorithm) shardingAlgorithm)
: (T) new TableShardingStrategy(shardingColumns, (MultipleKeysTableShardingAlgorithm) shardingAlgorithm);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
*/
public class ClosureDatabaseShardingAlgorithm extends ClosureShardingAlgorithm implements MultipleKeysDatabaseShardingAlgorithm {

public ClosureDatabaseShardingAlgorithm(final String scriptText, final String logRoot) {
super(scriptText, logRoot);
public ClosureDatabaseShardingAlgorithm(final String expression, final String logRoot) {
super(expression, logRoot);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@

package com.dangdang.ddframe.rdb.sharding.config.common.internal.algorithm;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.common.MultipleKeysShardingAlgorithm;
import com.google.common.base.Joiner;
Expand All @@ -35,55 +29,61 @@
import groovy.util.Expando;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
* 基于闭包的数据源划分算法.
*
* @author gaohongtao
*/
public class ClosureShardingAlgorithm implements MultipleKeysShardingAlgorithm {

private final Closure<String> closure;
private final Closure<?> closureTemplate;

@SuppressWarnings(value = "unchecked")
public ClosureShardingAlgorithm(final String scriptText, final String logRoot) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(scriptText));
public ClosureShardingAlgorithm(final String expression, final String logRoot) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(expression));
Preconditions.checkArgument(!Strings.isNullOrEmpty(logRoot));
Binding binding = new Binding();
binding.setVariable("log", LoggerFactory.getLogger(Joiner.on(".").join("com.dangdang.ddframe.rdb.sharding.configFile", logRoot.trim())));
closure = (Closure) new GroovyShell(binding).evaluate(Joiner.on("").join("{it -> \"", scriptText.trim(), "\"}"));
closureTemplate = (Closure) new GroovyShell(binding).evaluate(Joiner.on("").join("{it -> \"", expression.trim(), "\"}"));
}

@Override
public Collection<String> doSharding(final Collection<String> availableTargetNames, final Collection<ShardingValue<?>> shardingValues) {
List<Set<Comparable>> parametersDim = new ArrayList<>();
List<String> columnNameList = new ArrayList<>(shardingValues.size());
List<Set<Comparable>> valuesDim = new ArrayList<>();
List<String> columnNames = new ArrayList<>(shardingValues.size());
for (ShardingValue<?> each : shardingValues) {
columnNameList.add(each.getColumnName());
columnNames.add(each.getColumnName());
switch (each.getType()) {
case SINGLE:
parametersDim.add(Sets.newHashSet((Comparable) each.getValue()));
valuesDim.add(Sets.newHashSet((Comparable) each.getValue()));
break;
case LIST:
parametersDim.add(Sets.<Comparable>newHashSet(each.getValues()));
valuesDim.add(Sets.<Comparable>newHashSet(each.getValues()));
break;
case RANGE:
throw new UnsupportedOperationException("Config file does not support BETWEEN, please use Java API Config");
throw new UnsupportedOperationException("Inline expression does not support BETWEEN, please use Java API Config");
default:
throw new UnsupportedOperationException();
throw new UnsupportedOperationException(each.getType().name());
}
}
List<String> result = new ArrayList<>();
Set<String> availableTargetNameSet = new HashSet<>(availableTargetNames);
for (List<Comparable> each : Sets.cartesianProduct(parametersDim)) {
Closure<String> newClosure = closure.rehydrate(new Expando(), null, null);
newClosure.setResolveStrategy(Closure.DELEGATE_ONLY);
newClosure.setProperty("log", closure.getProperty("log"));
for (int i = 0; i < each.size(); i++) {
newClosure.setProperty(columnNameList.get(i), new ShardingValueWrapper(each.get(i)));
}
Object algorithmResult = newClosure.call();
Preconditions.checkState(availableTargetNameSet.contains(algorithmResult.toString()));
result.add(algorithmResult.toString());
Set<List<Comparable>> cartesianValues = Sets.cartesianProduct(valuesDim);
List<String> result = new ArrayList<>(cartesianValues.size());
for (List<Comparable> each : cartesianValues) {
result.add(cloneClosure(columnNames, each).call().toString());
}
return result;
}

private Closure<?> cloneClosure(final List<String> columnNames, final List<Comparable> values) {
Closure<?> result = closureTemplate.rehydrate(new Expando(), null, null);
result.setResolveStrategy(Closure.DELEGATE_ONLY);
result.setProperty("log", closureTemplate.getProperty("log"));
for (int i = 0; i < values.size(); i++) {
result.setProperty(columnNames.get(i), new ShardingValueWrapper(values.get(i)));
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
*/
public class ClosureTableShardingAlgorithm extends ClosureShardingAlgorithm implements MultipleKeysTableShardingAlgorithm {

public ClosureTableShardingAlgorithm(final String scriptText, final String logRoot) {
super(scriptText, logRoot);
public ClosureTableShardingAlgorithm(final String expression, final String logRoot) {
super(expression, logRoot);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,28 @@

package com.dangdang.ddframe.rdb.sharding.config.common.internal.algorithm;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import lombok.RequiredArgsConstructor;

/**
* 进入闭包的值进行包装,提供类型转换方法.
* 将进入闭包的值提供类型转换方法.
*
* @author gaohongtao
*/
@RequiredArgsConstructor
public class ShardingValueWrapper {

//value 可能的取值类型有 Number, java.sql.Date, String
private final Comparable value;
private final Comparable<?> value;

public ShardingValueWrapper(final Comparable<?> value) {
Preconditions.checkArgument(value instanceof Number || value instanceof Date || value instanceof String,
String.format("Value must be type of Number, Data or String, your value type is '%s'", value.getClass().getName()));
this.value = value;
}

/**
* 获取long值.
Expand All @@ -58,13 +61,11 @@ public double doubleValue() {
private Number numberValue() {
if (value instanceof Number) {
return (Number) value;
} else if (value instanceof Date) {
}
if (value instanceof Date) {
return ((Date) value).getTime();
} else if (value instanceof String) {
return new BigDecimal((String) value);
} else {
throw new UnsupportedOperationException();
}
return new BigDecimal(value.toString());
}

/**
Expand All @@ -77,16 +78,20 @@ private Number numberValue() {
public Date dateValue(final String format) throws ParseException {
if (value instanceof Number) {
return new Date(((Number) value).longValue());
} else if (value instanceof Date) {
}
if (value instanceof Date) {
return (Date) value;
} else if (value instanceof String) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(format));
return new SimpleDateFormat(format).parse((String) value);
} else {
throw new UnsupportedOperationException();
}
Preconditions.checkArgument(!Strings.isNullOrEmpty(format));
return new SimpleDateFormat(format).parse(value.toString());
}

/**
* 将字符串转换为时间.
*
* @return 时间类型的值
* @throws ParseException
*/
public Date dateValue() throws ParseException {
return dateValue(null);
}
Expand All @@ -100,15 +105,15 @@ public Date dateValue() throws ParseException {
public String toString(final String format) {
if (value instanceof Date) {
return new SimpleDateFormat(format).format(((Date) value).getTime());
} else if (value instanceof Number) {
}
if (value instanceof Number) {
return new SimpleDateFormat(format).format(((Number) value).longValue());
} else {
return toString();
}
return toString();
}

@Override
public String toString() {
return value.toString();
}

}
Loading

0 comments on commit ebaf67a

Please sign in to comment.