/**
* Alipay.com Inc.
* Copyright (c) 2004-2012 All Rights Reserved.
*/
package com.alipay.zdal.rule.bean;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.log4j.Logger;
import com.alipay.zdal.rule.groovy.GroovyListRuleEngine;
import com.alipay.zdal.rule.ruleengine.entities.abstractentities.RuleChain;
import com.alipay.zdal.rule.ruleengine.entities.convientobjectmaker.DefaultTableMapProvider;
import com.alipay.zdal.rule.ruleengine.util.RuleUtils;
/**
* ���������ʵ��������Ĺ���ļ��ϣ��ὫһЩ����������ƽ��
*
* ������Ժ�������ʱ����ʹ�õ�����ʱ���ݣ�Ȼ��������С�
*
*
*/
public class SimpleLogicTable extends LogicTable {
private static final Logger log = Logger
.getLogger(SimpleLogicTable.class);
String databases;
/**
* �ֿ��
*/
String shardingKey;
List<Object> tableRuleStringList;
List<Object> databaseRuleStringList;
boolean isSimpleTableMapPropertiesChanged;
/**
* Simple logic table���ڲ�����,���ڼ�¼��Ҫ���ݸ�����ı�������Ϣ��
*
*TODO: ��֪��Ϊʲô֧������ͬ־���������ȥ���ˡ���
*/
private SimpleTableMapProvider simpleTableMapProvider = new SimpleTableMapProvider();
SimpleListDatabaseMapProvider simpleDatabaseMapProvider = new SimpleListDatabaseMapProvider();
/**
* �Ƿ�ʹ���Զ����ɹ���һ����˵�ò���
* ֻ��Ϊ��ǿ�Ƹ�ҵ��һ����ʹ���Զ������ѡ��Ա���ʱ֮�衣
*/
boolean useAutoGeneratingRule = true;
/**
* ���ֿ���ͷֱ����ָ��������£�
* �Զ��������й���ֻҪ�ֿ���ͷֱ����һ��ָ���ˡ���ô����Ҫ�Զ����ɹ���
*
* �Զ����ɹ���Ḳ�������Ѿ����ڵĹ���
*
*
* @return �Ƿ����ʹ���Զ���������
*/
protected boolean canUseAutoGenerationRule() {
if (!useAutoGeneratingRule) {
return false;
}
if (shardingKey == null) {
return false;
}
return true;
}
protected void valid(int databasesSize, int tableSizeForEachDatabase) {
if (databasesSize == 0 || tableSizeForEachDatabase == 0) {
//�ֿ���ͷֱ��Ϊ0�����������ڷֿ��ֱ�û��ָ�������ʱ���Dz���Ҫƴ�ӵ�
return;
}
int dividend = 0;
int divisor = 0;
if (databasesSize > tableSizeForEachDatabase) {
dividend = databasesSize;
divisor = tableSizeForEachDatabase;
} else {
dividend = tableSizeForEachDatabase;
divisor = databasesSize;
}
if (dividend % divisor != 0) {
throw new IllegalArgumentException("�ֱ���������Ƿֿ�����ı���," + "�ֿ���:" + databasesSize + "�ֱ���:"
+ tableSizeForEachDatabase);
}
}
static class TableAGRuleHandler extends DatabaseAndTableAGRuleHandler implements
AutoGenerationRuleHandler {
@Override
public String getTableRule(String tableShardingKey, int databaseSize,
int tableSizeForEachDatabase) {
StringBuilder sb = new StringBuilder();
sb.append("#").append(tableShardingKey).append("#");
if (tableSizeForEachDatabase != 0) {
sb.append(" % ").append(tableSizeForEachDatabase);
}
return sb.toString();
}
public String getDatabaseRule(String databaseShardingKey, int tablesSize,
int tableSizeForEachDatabase) {
return null;
}
}
static class DatabaseAGRuleHandler extends DatabaseAndTableAGRuleHandler implements
AutoGenerationRuleHandler {
@Override
public String getTableRule(String tableShardingKey, int databaseSize,
int tableSizeForEachDatabase) {
return null;
}
@Override
public String getDatabaseRule(String databaseShardingKey, int databaseSize,
int tableSizeForEachDatabase) {
StringBuilder sb = new StringBuilder();
sb.append("#").append(databaseShardingKey).append("#");
if (databaseSize != 0) {
sb.append(" % ").append(databaseSize);
}
sb.append("");
return sb.toString();
}
}
static class NoneAGRuleHandler implements AutoGenerationRuleHandler {
public String getDatabaseRule(String databaseShardingKey, int tablesSize,
int tableSizeForEachDatabase) {
return null;
}
public String getTableRule(String tableShardingKey, int tablesSize,
int tableSizeForEachDatabase) {
return null;
}
}
static class DatabaseAndTableAGRuleHandler implements AutoGenerationRuleHandler {
public String getDatabaseRule(String databaseShardingKey, int databaseSize,
int tableSizeForEachDatabase) {
int tablesSize = databaseSize * tableSizeForEachDatabase;
StringBuilder sb = new StringBuilder();
sb.append("(#").append(databaseShardingKey).append("#");
if (tablesSize != 0) {
sb.append(" % ").append(tablesSize);
}
sb.append(")");
if (tableSizeForEachDatabase != 0) {
sb.append(".intdiv(").append(tableSizeForEachDatabase).append(")");
}
return sb.toString();
}
public String getTableRule(String tableShardingKey, int databaseSize,
int tableSizeForEachDatabase) {
int tablesSize = databaseSize * tableSizeForEachDatabase;
StringBuilder sb = new StringBuilder();
sb.append("(#").append(tableShardingKey).append("#");
if (tablesSize != 0) {
sb.append(" % ").append(tablesSize);
}
sb.append(")");
if (tableSizeForEachDatabase != 0) {
sb.append(" % ").append(tableSizeForEachDatabase);
}
return sb.toString();
}
}
static interface AutoGenerationRuleHandler {
/**
* ��ȡ�ֱ����
* @param tableShardingKey �ֱ��
* @param tablesSize ����ܸ���
* @param tableSizeForEachDatabase ÿ����ı�ĸ���
* @return
*/
String getTableRule(String tableShardingKey, int tablesSize, int tableSizeForEachDatabase);
/**��ȡ�ֿ����
*
* @param tableShardingKey �ֱ��
* @param tablesSize ����ܸ���
* @param tableSizeForEachDatabase ÿ����ı�ĸ���
*
* @return
*/
String getDatabaseRule(String databaseShardingKey, int tablesSize,
int tableSizeForEachDatabase);
}
AutoGenerationRuleHandler decideAutoGenerationRuleHandler(int databaseSize,
int tableSizeForEachDatabase) {
if (databaseSize <= 0 || tableSizeForEachDatabase <= 0) {
throw new IllegalArgumentException("������Ҫһ����,һ�ű�");
}
if (databaseSize == 1) {
if (tableSizeForEachDatabase == 1) {
//���ⵥ����
return new NoneAGRuleHandler();
} else {
//��������
return new TableAGRuleHandler();
}
} else {
if (tableSizeForEachDatabase == 1) {
//��ⵥ��
return new DatabaseAGRuleHandler();
} else {
//�����
return new DatabaseAndTableAGRuleHandler();
}
}
}
/**
* �Զ����ɹ���
*
* ��ָ����һ��databaseKey��tableKey��ʱ����
*
* �Զ�����һ������
*
* Ȼ�����û��ͨ���ⲿ��ָ��String����Ļ����ͻ�ʹ�õ�ǰ����������ⲿ����
*
* ������ⲿָ���Ĺ�����ôʹ���ⲿ����
*
* ���ȼ���͵�һ�ֹ�����������
*/
protected void processAutoGenerationRule() {
if (!canUseAutoGenerationRule()) {
return;
}
int databaseSize = simpleDatabaseMapProvider.getDatasourceKeys().size();
int tablesNumberForEachDatabases = getTablesNumberForEachDatabases();
valid(databaseSize, tablesNumberForEachDatabases);
//���п���ܱ����
AutoGenerationRuleHandler agrHandler = decideAutoGenerationRuleHandler(databaseSize,
tablesNumberForEachDatabases);
String dbRule = agrHandler.getDatabaseRule(shardingKey, databaseSize,
tablesNumberForEachDatabases);
//ֻ�е�databaseRuleStringListΪnull������²���Ĭ�Ϲ����滻֮��
if (dbRule != null && this.databaseRuleStringList == null) {
this.databaseRuleStringList = new ArrayList<Object>(1);
if (log.isDebugEnabled()) {
log.debug("auto generation rule for database: " + dbRule);
}
databaseRuleStringList.add(dbRule);
}
String tableRule = agrHandler.getTableRule(shardingKey, databaseSize,
tablesNumberForEachDatabases);
if (tableRule != null) {
this.tableRuleStringList = new ArrayList<Object>(1);
if (log.isDebugEnabled()) {
log.debug("auto generation rule for database: " + tableRule);
}
tableRuleStringList.add(tableRule);
}
}
protected int getTablesNumberForEachDatabases() {
int tablesNumberForEachDatabases = simpleTableMapProvider.getTablesNumberForEachDatabases();
if (tablesNumberForEachDatabases == SimpleTableMapProvider.DEFAULT_TABLES_NUM_FOR_EACH_DB) {
//���ÿ�����ڱ��������Ĭ��ֵ����ôӦ����to-from+1��ô���ű�
tablesNumberForEachDatabases = simpleTableMapProvider.getTo()
- simpleTableMapProvider.getFrom() + 1;
}
return tablesNumberForEachDatabases;
}
@Override
public void init() {
boolean isDatabase = true;
//��ע�����ﲻҪ����ߵ���ʼ��˳��
if (superClassDatabaseProviderIsNull()) {
setSimpleDatabaseMapToSuperLogicTable();
}
if (superClassTableMapProviderIsNull()) {
if (isSimpleTableMapPropertiesChanged)
setTableMapProvider(this.simpleTableMapProvider);
}
processAutoGenerationRule();
if (superClassDatabaseRuleIsNull()) {
RuleChain rc = RuleUtils.getRuleChainByRuleStringList(databaseRuleStringList,
GroovyListRuleEngine.class, isDatabase);
super.listResultRule = rc;
}
if (transmitterTableRuleIsNull()) {
RuleChain rc = RuleUtils.getRuleChainByRuleStringList(tableRuleStringList,
GroovyListRuleEngine.class, !isDatabase);
setTableRuleChain(rc);
}
super.init();
}
private boolean transmitterTableRuleIsNull() {
return getTableRule() == null || getTableRule().isEmpty();
}
private boolean superClassDatabaseRuleIsNull() {
return listResultRule == null;
}
private boolean superClassTableMapProviderIsNull() {
return getTableMapProvider() == null
|| getTableMapProvider() instanceof DefaultTableMapProvider;
}
protected void setSimpleDatabaseMapToSuperLogicTable() {
if (databases == null) {
return;
}
String[] databasesTokens = databases.split(",");
simpleDatabaseMapProvider.setDatasourceKeys(Arrays.asList(databasesTokens));
setDatabaseMapProvider(simpleDatabaseMapProvider);
}
private boolean superClassDatabaseProviderIsNull() {
return getDatabaseMapProvider() == null;
}
/**
* ��{@linkplain setLogicTableName}����һ��
* @param logicTable
*/
public void setLogicTable(String logicTable) {
setLogicTableName(logicTable);
}
public void setPadding(String padding) {
isSimpleTableMapPropertiesChanged = true;
simpleTableMapProvider.setPadding(padding);
}
public void setParentID(String parentID) {
isSimpleTableMapPropertiesChanged = true;
simpleTableMapProvider.setParentID(parentID);
}
public void setStep(int step) {
isSimpleTableMapPropertiesChanged = true;
simpleTableMapProvider.setStep(step);
}
/**
* ��{@linkplain setLogicTableName}����һ��
* @param tableFactor
*/
public void setTableFactor(String tableFactor) {
setLogicTableName(tableFactor);
}
public void setTablesNumberForEachDatabases(int tablesNumberForEachDatabases) {
isSimpleTableMapPropertiesChanged = true;
simpleTableMapProvider.setTablesNumberForEachDatabases(tablesNumberForEachDatabases);
}
public void setFrom(int from) {
isSimpleTableMapPropertiesChanged = true;
simpleTableMapProvider.setFrom(from);
}
public void setTo(int to) {
isSimpleTableMapPropertiesChanged = true;
simpleTableMapProvider.setTo(to);
}
public void setType(String type) {
isSimpleTableMapPropertiesChanged = true;
simpleTableMapProvider.setType(type);
}
public void setWidth(int width) {
isSimpleTableMapPropertiesChanged = true;
simpleTableMapProvider.setWidth(width);
}
public String getDatabases() {
return databases;
}
public void setDatabases(String databases) {
this.databases = databases;
}
public List<Object> getTableRuleStringList() {
return tableRuleStringList;
}
public void setTableRuleStringList(List<Object> tableRuleStringList) {
this.tableRuleStringList = tableRuleStringList;
}
public List<Object> getDatabaseRuleStringList() {
return databaseRuleStringList;
}
public void setDatabaseRuleStringList(List<Object> databaseRuleStringList) {
this.databaseRuleStringList = databaseRuleStringList;
}
public boolean isUseAutoGeneratingRule() {
return useAutoGeneratingRule;
}
public void setUseAutoGeneratingRule(boolean useAutoGeneratingRule) {
this.useAutoGeneratingRule = useAutoGeneratingRule;
}
public String getShardingKey() {
return shardingKey;
}
public void setShardingKey(String shardingKey) {
this.shardingKey = shardingKey;
}
public void setSimpleTableMapProvider(SimpleTableMapProvider simpleTableMapProvider) {
this.simpleTableMapProvider = simpleTableMapProvider;
}
@Override
public String toString() {
return "SimpleLogicTable [databaseRuleStringList=" + databaseRuleStringList
+ ", databases=" + databases + ", isSimpleTableMapPropertiesChanged="
+ isSimpleTableMapPropertiesChanged + ", shardingKey=" + shardingKey
+ ", simpleDatabaseMapProvider=" + simpleDatabaseMapProvider
+ ", simpleTableMapProvider=" + simpleTableMapProvider + ", tableRuleStringList="
+ tableRuleStringList + ", useAutoGeneratingRule=" + useAutoGeneratingRule
+ ", defaultListResult=" + defaultListResult + ", defaultListResultStragety="
+ defaultListResultStragety + ", listResultRule=" + listResultRule
+ ", subSharedElement=" + subSharedElement + "]";
}
}