/**
* Alipay.com Inc.
* Copyright (c) 2004-2012 All Rights Reserved.
*/
package com.alipay.zdal.rule.bean;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.apache.log4j.Logger;
import com.alipay.zdal.common.DBType;
import com.alipay.zdal.rule.LogicTableRule;
import com.alipay.zdal.rule.ruleengine.entities.abstractentities.ListSharedElement;
import com.alipay.zdal.rule.ruleengine.entities.abstractentities.OneToManyEntry;
import com.alipay.zdal.rule.ruleengine.entities.abstractentities.RuleChain;
import com.alipay.zdal.rule.ruleengine.entities.abstractentities.SharedElement;
import com.alipay.zdal.rule.ruleengine.entities.abstractentities.TablePropertiesSetter;
import com.alipay.zdal.rule.ruleengine.entities.convientobjectmaker.DatabaseMapProvider;
import com.alipay.zdal.rule.ruleengine.entities.convientobjectmaker.TableMapProvider;
import com.alipay.zdal.rule.ruleengine.entities.inputvalue.CalculationContextInternal;
import com.alipay.zdal.rule.ruleengine.entities.retvalue.TargetDB;
import com.alipay.zdal.rule.ruleengine.rule.Field;
import com.alipay.zdal.rule.ruleengine.rule.ListAbstractResultRule;
/**
* һ�������
*
* û�в��������Ȼ����map��Ӧ����Ӧ�����ݿ�ȥ��ԭ�������� 1.����ֱ����ͷֿ�����ȫ��ͬ��������簴��idȡģ+gmtʱ��� 2.ȫ��full
* scan��ѯ��ʱ�������ѡ�����п��ܵı�Ȼ����map��Ӧ�����ݿ����ʱ�Ķ�Ӧ������ 3.����ҵ���������ñ��ڱ����ĸ�ʽ��
*
*
*
*
*/
public class LogicTable extends ListSharedElement implements Cloneable, LogicTableRule,
TablePropertiesSetter {
private static final Logger log = Logger.getLogger(LogicTable.class);
private OneToManyEntry oneToManyEntry = new OneToManyEntry();
/**
* ͨ����������databaseMap
*/
private DatabaseMapProvider databaseMapProvider = null;
/**
* ��type
*/
private DBType dbType = DBType.MYSQL;
/**
* ���������
*/
private boolean allowReverseOutput;
/**
* Ψһ���������ȼ��ġ����ȼ��ߵģ�����List��ǰ�� ÿ�������Ψһ����֧�ֶ�����������������ĸ�����ǣ�����������������Ŀǰ�����Ƕ��Ψһ��
* ����List�е�ÿ��Set����ֻ����һ��Ԫ�ء���ÿ������һ��Ψһ��
*
* ��һ��SQL����ʱ�������ȼ�������list����һ����sql�ж������ļ������ӦΨһ����������Ϊ�������Ψһ����������
*/
private List<String> uniqueKeys;
/**
* �����ǰû����Ըñ���Զ���⣬��ô�������ɳ����Ŀ�ֱ��ָ����subSharedElement���á�
* �����ǰ�Ѿ������Զ���⣬��ô���Զ�����������ӵ����ɳ���Map��(���key��ͬ ���Զ����database����Ḳ���Զ����ɳ����Ķ���)
*
* ��һ���������Ҫ���ǣ�Ҳ����˵��������������Զ�����database����
* ����ȫ��database������Ȼϣ��ȫ��database�����Զ����ӹ���(�������壬�α�д�ӹ����أ���
* ����һ���������ȫ�ֶ���Ҳ���Ӷ���ϣ��������Ӷ�����ôȫ��ƴװ����mapʧЧ��
* �������ֱ��ɾ��ȫ��ƴװdatabaseMap��provider����ͺ��ˡ�
*
* @param generatedDatabaseMap
* @return
*/
@SuppressWarnings("unchecked")
protected Map<String, Database> buildSubSharedMap(Map<String, Database> generatedDatabaseMap) {
if (this.subSharedElement == null || this.subSharedElement.size() == 0) {
// �����ǰû���Զ���ı������ֱ��ʹ�����ɺ��map
if (log.isDebugEnabled()) {
log
.debug("subShared element is null ,use sharedElement generated by database shared element map provider.");
}
return generatedDatabaseMap;
} else {
if (log.isDebugEnabled()) {
log
.debug("subSharedElement is not null,putAll current subSharedElement to generated sharedElement");
}
Map<String, Database> beAppendMap = (Map<String, Database>) subSharedElement;
generatedDatabaseMap.putAll(beAppendMap);
}
if (log.isDebugEnabled()) {
log.debug("sub shared element is " + generatedDatabaseMap);
}
return generatedDatabaseMap;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public DatabaseMapProvider getDatabaseMapProvider() {
return databaseMapProvider;
}
public Set<RuleChain> getRuleChainSet() {
return ruleChainSet;
}
/**
* @see com.alipay.zdal.rule.ruleengine.entities.abstractentities.ListSharedElement#init()
*/
public void init() {
// ��ʼ�����ݿ�ڵ�
initDatabaseByDatabaseMapProvider();
//�ж�subSharedElement ���벻Ϊ��
if (subSharedElement == null || subSharedElement.isEmpty()) {
throw new IllegalArgumentException("���ٱ���ָ��һ����");
}
oneToManyEntry.init();
//��oneToManyEntry �ŵ�����dataSource����ȥ����ʵsubSharedElement һ��ʼ��ŵ���<string,database>
for (Entry<String, ? extends SharedElement> sharedElement : subSharedElement.entrySet()) {
sharedElement.getValue().put(oneToManyEntry);
}
// ��ʼ������
super.init();
registeRule(ruleChainSet);
if (log.isDebugEnabled()) {
log.debug("rule chain set [" + ruleChainSet + "] inited;");
}
}
protected void initDatabaseByDatabaseMapProvider() {
if (databaseMapProvider != null) {
Map<String, Database> generatedDatabaseMap = databaseMapProvider.getDatabaseMap();
if (generatedDatabaseMap != null) {
subSharedElement = buildSubSharedMap(generatedDatabaseMap);
}
}
}
/**
* ֵ̽����
*/
private Set<RuleChain> ruleChainSet = new HashSet<RuleChain>();
public void setDatabase(Map<String, SharedElement> databasesMap) {
if (databasesMap != null) {
super.subSharedElement = databasesMap;
}
}
public void setDatabaseMapProvider(DatabaseMapProvider databaseMapProvider) {
this.databaseMapProvider = databaseMapProvider;
}
public void setDatabaseRule(List<ListAbstractResultRule> databaseRule) {
RuleChainImp ruleChainImp = new RuleChainImp();
ruleChainImp.setListResultRule(databaseRule);
ruleChainImp.setDatabaseRuleChain(true);
ruleChainImp.init();
this.listResultRule = ruleChainImp;
}
/**
* ����ȫ��ȫ��
*
* @return ��null ������Դ�����
*
*/
@SuppressWarnings("unchecked")
public List<TargetDB> getAllTargetDBList() {
List<TargetDB> targetDatabases = new ArrayList<TargetDB>();
Map<String, Database> beingSelectedDatabases = (Map<String, Database>) getSubSharedElements();
for (Database database : beingSelectedDatabases.values()) {
TargetDB db = new TargetDB();
db.setDbIndex(database.getDataSourceKey());
Set<String> tempTableNameSet = new HashSet<String>();
Map<String, SharedElement> tablesMap = database.getTables();
Collection<? extends SharedElement> tableSharedElement = tablesMap.values();
for (SharedElement shearedElement : tableSharedElement) {
Table table = (Table) shearedElement;
tempTableNameSet.add(table.getTableName());
}
db.setTableNames(tempTableNameSet);
targetDatabases.add(db);
}
return targetDatabases;
}
// public DBType getDBType() {
// return dbType;
// }
public void setDBType(DBType dbType) {
this.dbType = dbType;
}
public boolean isAllowReverseOutput() {
return this.allowReverseOutput;
}
public void setAllowReverseOutput(boolean allowReverseOutput) {
this.allowReverseOutput = allowReverseOutput;
}
public List<String> getUniqueColumns() {
return uniqueKeys;
}
public List<String> getUniqueKeys() {
return uniqueKeys;
}
public void setUniqueKeys(List<String> uniqueKeys) {
this.uniqueKeys = uniqueKeys;
}
/**
* ���ⲿ���õĽӿڡ�
* ���ڷ��طֿ�ֱ�Ľ��
*
* �����LogicTable����û�й��ȶ�Ӧ��logicTableû�зֿ����,
* ������Ȼ�й����ǵ�ǰ��sql������û��ƥ�䵽��Щ�������������������
* a ���logicTale����ֻ��һ���⣬��ô����Ĭ�Ϲ���Ϊ�ζ�Ӧ��ȡ���ÿ⡣���������Ҫ�����ڵ��⣨��,�ࣩ�������ࣩ�� ���������¡�
* b ���logicTale�ж���⣬��ôӦ��ʹ�� ��ѡ����ԣ�DEFAULT_LIST_RESULT_STRAGETY�������������������ΪDEFAULT_LIST_RESULT_STRAGETY.NONE�Ƚϰ�ȫ;
* ��������˹���ֱ��ʹ�ù�����м��㡣
*/
public List<TargetDB> calculate(Map<RuleChain, CalculationContextInternal> map) {
CalculationContextInternal calculationContext = map.get(this.listResultRule);
Map<String/* �����ֵ */, Field> resultmap = null;
if (calculationContext == null) {
//����Ϊ�գ����߹���δƥ�䵽
if (subSharedElement != null && subSharedElement.size() == 1) {
// 1���ڹ���δƥ�䵽����sharedElementΨһ������£�Ĭ�ϵ�ѡ��Ψһ��sharedElement.
//��ʱ���������ΪNONE��Ҳ��ѡ��Ψһ�ģ�����ʹ��Ĭ�Ϲ���
resultmap = buildSingleDatabase();
} else {
//2)����Ϊ�գ�����δƥ�䵽������Ĭ���ӿⲻΪΨһ��һ��������£�ʹ��Ĭ�Ϲ���
resultmap = buildDefaultDatabaseMap();
}
} else {
//3��
ListAbstractResultRule rule = calculationContext.ruleChain
.getRuleByIndex(calculationContext.index);
resultmap = rule.eval(calculationContext.sqlArgs);
}
List<TargetDB> targetDBList = buildTargetDBList(map, resultmap);
return targetDBList;
}
final Map<String, Field> buildDefaultDatabaseMap() {
Map<String, Field> resultmap;
resultmap = new HashMap<String, Field>(defaultListResult.size());
for (String defaultIndex : defaultListResult) {
resultmap.put(defaultIndex, Field.EMPTY_FIELD);
}
return resultmap;
}
final List<TargetDB> buildTargetDBList(Map<RuleChain, CalculationContextInternal> map,
Map<String, Field> resultmap) {
List<TargetDB> targetDBList = new ArrayList<TargetDB>();//�������б�
for (Entry<String, Field> entry : resultmap.entrySet()) {
Database database = (Database) subSharedElement.get(entry.getKey());
if (database == null) {
throw new IllegalArgumentException("���ܸ���key: " + entry.getKey()
+ "ȡ����Ӧ�ı�������ǰ�ӹ��������б���Ϊ:" + subSharedElement);
} else {
//��ӱ���
TargetDB targetDB = new TargetDB();
String dbKey = database.getDataSourceKey();
if (dbKey == null) {
throw new IllegalArgumentException("database����������Դkey id");
}
targetDB.setDbIndex(dbKey);
database.calculateTable(targetDB, entry.getValue(), map);
targetDBList.add(targetDB);
}
}
return targetDBList;
}
final Map<String, Field> buildSingleDatabase() {
Map<String, Field> resultmap;
resultmap = new HashMap<String, Field>(1);
for (String key : subSharedElement.keySet()) {
resultmap.put(key, Field.EMPTY_FIELD);
}
return resultmap;
}
public void setLogicTableName(String logicTable) {
oneToManyEntry.setLogicTableName(logicTable);
}
public String getLogicTableName() {
return oneToManyEntry.getLogicTableName();
}
public void setTableRuleChain(RuleChain ruleChain) {
oneToManyEntry.setTableRuleChain(ruleChain);
}
public void setTableMapProvider(TableMapProvider tableMapProvider) {
oneToManyEntry.setTableMapProvider(tableMapProvider);
}
public TableMapProvider getTableMapProvider() {
return oneToManyEntry.getTableMapProvider();
}
@Override
public String toString() {
return "LogicTable [allowReverseOutput=" + allowReverseOutput + ", databaseMapProvider="
+ databaseMapProvider + ", dbType=" + dbType + ", uniqueKeys=" + uniqueKeys
+ ", defaultListResult=" + defaultListResult + ", defaultListResultStragety="
+ defaultListResultStragety + ", listResultRule=" + listResultRule
+ ", subSharedElement=" + subSharedElement + "]";
}
public void setDefaultListResultStragety(DEFAULT_LIST_RESULT_STRAGETY defaultListResultStragety) {
// �����˸����ͬ��������
super.setDefaultListResultStragety(defaultListResultStragety);
oneToManyEntry.setDefaultListResultStragety(defaultListResultStragety);
}
public void setTableRule(List<ListAbstractResultRule> tableRule) {
oneToManyEntry.setTableRule(tableRule);
}
public List<ListAbstractResultRule> getTableRule() {
return oneToManyEntry.getTableRule();
}
}