/**
* 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.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.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.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;
import com.alipay.zdal.rule.ruleengine.util.RuleUtils;
/**
* һ�����ݿ�ij���
*
*
*/
public class Database extends ListSharedElement implements TablePropertiesSetter {
protected static final Logger log = Logger.getLogger(Database.class);
// implements TableContainer,TableListResultRuleContainer
private String dataSourceKey;
/**
* ������
*/
private String logicTableName;
/**
* ����List������initʱ���ruleChain
*/
private List<ListAbstractResultRule> tableRuleList;
/**
* 1�Զ�ָ��������Entry
*/
private OneToManyEntry oneToManyEntry;
private TableMapProvider tableMapProvider;
/**
* @see com.alipay.zdal.rule.ruleengine.entities.abstractentities.ListSharedElement#init()
* ������Ҫ���ȳ�ʼ������subTable��Ȼ���������Ӧ�Ķ�����
*/
public void init() {
initTableRuleChain();
initLogicTableName();
initTableMapProvider();
initDefaultListResultStragety();
// �����tableRuleProvider ��ô��ʼ���ӱ�tableMapProvier��transmit����������ʱ��������
if (tableMapProvider != null) {
Map<String, SharedElement> beConstructedMap = getTableMapByTableMapProvider();
putAutoConstructedMapIntoCurrentTagMap(beConstructedMap);
}
super.init();
}
private void initDefaultListResultStragety() {
if (defaultListResultStragety == null) {
defaultListResultStragety = oneToManyEntry.getDefaultListResultStragety();
}
}
/**
* ��������ķ���
* 1. �����Database����û�й��ȶ�Ӧ�Ŀ�û�зֱ����,
* ������Ȼ�й����ǵ�ǰ��sql������û��ƥ�䵽��Щ�������������������
* a ���Database����ֻ��һ������ô����Ĭ�Ϲ���Ϊ�ζ�Ӧ��ȡ���ñ����������Ҫ�����ڵ��⣨��,�ࣩ�������ࣩ�� ���������¡�
* b ���Database�ж������ôӦ��ʹ��Ĭ��ѡ����ԣ�DEFAULT_LIST_RESULT_STRAGETY�������������������ΪDEFAULT_LIST_RESULT_STRAGETY.NONE�Ƚϰ�ȫ;
*
* 2. ��������˹���
* 2.1�����˹���Database��û�д��ݶ�λ����databaseʱ�����õ�����->��㼯�ϵ�map.��ô��ʾǰ�����ݺ͵�ǰ�����أ�ֱ��ʹ�õ�ǰ����+sql��ƥ���ֵ���ɡ�
* 2.2�������˶�λ����databaseʱ������->���ļ���
* 2.2.1�����ݵ���㼯���е�key�����˴�sql�л�ȡ��key����ô��ʾdatabase��table�������ǻ������Ӱ��ġ�
* ���ʱ������ʹ��database�д���� ����->�������㡣
* 2.2.2�����ݵ���㼯���е�key��������sql�л�ȡ��key,��ô��ʾdatabase��table֮���������
* ��ֱ��ʹ��table�����ݽ��м��㡣
*
* @param targetDB
* Ŀ����������������ڱ���װ
* @param sourceTrace
* �������ǰ���ݿ��Դ�����١�
* @param map
* ��������Ӧ�������ġ�
*/
public void calculateTable(TargetDB targetDB, Field sourceTrace,
Map<RuleChain, CalculationContextInternal> map) {
CalculationContextInternal calculationContext = map.get(this.listResultRule);
Set<String> resultSet = null;
if (calculationContext == null) {
// ��ʾû��ָ����������ǰ����Ϊnull��û��ƥ�䵽���ݣ���Ĭ��
if (subSharedElement != null && subSharedElement.size() == 1) {
// 1��
resultSet = builSingleTable();
} else {
//2)
resultSet = buildDefaultTable();
}
} else if (sourceTrace == null || sourceTrace.sourceKeys.isEmpty()) {
//2.1��Database��û�д��ݶ�λ����databaseʱ�����õ�����->��㼯�ϵ�map
ListAbstractResultRule rule = calculationContext.ruleChain
.getRuleByIndex(calculationContext.index);
Map<String, Set<Object>> argsFromSQL = getEnumeratedSqlArgsMap(calculationContext, rule);
resultSet = rule.evalWithoutSourceTrace(argsFromSQL, null, null);
} else {
//2.2�������˶�λ����databaseʱ������->���ļ���
ListAbstractResultRule rule = calculationContext.ruleChain
.getRuleByIndex(calculationContext.index);
Map<String, Set<Object>> argsFromSQL = getEnumeratedSqlArgsMap(calculationContext, rule);
//�й�ϵ������Ӧ�����ȡ�putAll���ô����sourceKeys���Ա�database��Ч����㼯������ȫ��sql��Ϣ�ļ�����
Map<String/* ���� */, Set<Object>/* �õ��ý�������ֵ�� */> sourceKeys = sourceTrace.sourceKeys;
for (Entry<String, Set<Object>> entry : sourceKeys.entrySet()) {
if (argsFromSQL.containsKey(entry.getKey())) {
argsFromSQL.put(entry.getKey(), entry.getValue());
if (log.isDebugEnabled()) {
log.debug("put entry: " + entry + " to args");
}
}
// else{
// //�ӷֿ���������û�зֱ�����Ҫ�����ݵ�ʱ���Ž�ȥ
// }
}
resultSet = rule.evalWithoutSourceTrace(argsFromSQL, sourceTrace.mappingTargetColumn,
sourceTrace.mappingKeys);
}
buildTableNameSet(targetDB, resultSet);
}
private void buildTableNameSet(TargetDB targetDB, Set<String> resultSet) {
for (String key : resultSet) {
Table table = (Table) subSharedElement.get(key);
if (table == null) {
throw new IllegalArgumentException("cant find table by target index :" + key
+ " current sub tables is " + subSharedElement);
}
targetDB.addOneTable(table.getTableName());
}
}
private Map<String, Set<Object>> getEnumeratedSqlArgsMap(
CalculationContextInternal calculationContext,
ListAbstractResultRule rule) {
if (rule == null) {
throw new IllegalStateException("should not be here");
}
//ǿת ��Ҫ�õ�����ķ���
Map<String, Set<Object>> argsFromSQL = RuleUtils.getSamplingField(
calculationContext.sqlArgs, rule.getParameters());
return argsFromSQL;
}
private Set<String> buildDefaultTable() {
Set<String> resultMap;
resultMap = new HashSet<String>();
for (String defaultIndex : defaultListResult) {
resultMap.add(defaultIndex);
}
return resultMap;
}
private Set<String> builSingleTable() {
Set<String> resultMap = new HashSet<String>(1);
for (String key : subSharedElement.keySet()) {
resultMap.add(key);
}
return resultMap;
}
/**
* �����ǰ�ڵ�û��tableMapProvider����ôʹ��1�Զำ����tableMapProvider.
*/
void initTableMapProvider() {
if (this.tableMapProvider == null) {
this.tableMapProvider = oneToManyEntry.getTableMapProvider();
}
}
/**
* �����ǰ�ڵ�û��logicTableName,��ôʹ��1�Զำ���logictable.
*/
void initLogicTableName() {
String logicTable = oneToManyEntry.getLogicTableName();
if (logicTableName == null || logicTableName.length() == 0) {
this.logicTableName = logicTable;
}
}
/**
* ��ʼ��tableRuleChain,�����ǰ�ڵ��ListRule��Ϊ��,RuleChainΪ����ʹ��listRule�½�һ��ruleChain.
* ���listRuleΪ�գ�RuleChainҲΪ�գ���ôʹ��1�Զำ���ruleChain. ���ruleChain��Ϊ�գ����ʼ��֮
*/
void initTableRuleChain() {
RuleChain ruleChain = oneToManyEntry.getTableRuleChain();
// ���tableRuleList ��Ϊ�գ�����ruleChain == �ա���tableRuleList
//������ʵ��
if (this.tableRuleList != null) {
if (listResultRule != null) {
throw new IllegalArgumentException("��tableRuleList����ָ����ruleChain");
} else {
listResultRule = OneToManyEntry.getRuleChain(tableRuleList);
}
}
//�����ʵ��δָ������ǰdatabase���������ʹ�ô��ݺ�Ĺ���
if (listResultRule == null) {
listResultRule = ruleChain;
}
//��ǰdatabase�Ѿ��й��������£���ʼ����ǰ������Ϊrulechain�����ظ���ʼ��������ֻ���ʼ��һ�Ρ�
if (ruleChain != null) {
listResultRule.init();
} else {
log.warn("rule chain size is 0");
}
}
protected Map<String, SharedElement> getTableMapByTableMapProvider() {
TableMapProvider provider = getTableMapProvider();
provider.setParentID(this.getId());
provider.setLogicTable(getLogicTableName());
Map<String, SharedElement> beConstructedMap = provider.getTablesMap();
return beConstructedMap;
}
/**
* �����ñ�ݷ������ɵ���Ԫ��map���õ���ǰ�ڵ����Ԫ��map�����С�
*
* �����ǰ�ӽڵ����Ԫ��map����Ϊ����ֱ������
*
* �����ǰ�ӽڵ㲻Ϊ��,���ʾҵ��ͨ��spring�ķ�ʽset��һ�����е�map����
*
* ���map�����ȼ�Ҫ���Զ����ɵ�map�����ȼ�Ҫ�ߡ�
*
* @param beingConstructedMap
*/
protected void putAutoConstructedMapIntoCurrentTagMap(
Map<String, SharedElement> beingConstructedMap) {
if (this.subSharedElement == null) {
subSharedElement = beingConstructedMap;
} else {
if (beingConstructedMap != null) {
// ���Զ����table��ͬʱ����ͳһ������ô�����ϲ����Զ������ͨ��ͳһ����
beingConstructedMap.putAll(subSharedElement);
subSharedElement = beingConstructedMap;
}
// else
// û���Զ����ɹ���ֻ���Զ��������ôʲô���鶼����
}
}
/**
* 1��databse��Ӧһ��tables
*
* @param tables
*/
public void setTables(Map<String, SharedElement> tablesMap) {
super.subSharedElement = tablesMap;
}
@SuppressWarnings("unchecked")
public Map<String, SharedElement> getTables() {
return (Map<String, SharedElement>) super.subSharedElement;
}
private Map<String, SharedElement> getTablesMapByStringList(List<String> tablesString) {
List<Table> tables = null;
tables = new ArrayList<Table>(tablesString.size());
for (String tabName : tablesString) {
Table tab = new Table();
tab.setTableName(tabName);
tables.add(tab);
}
Map<String, SharedElement> returnMap = RuleUtils
.getSharedElemenetMapBySharedElementList(tables);
return returnMap;
}
/**
* ����ҵ��ֱ��ͨ��string->string�ķ�ʽ��ָ������
*
* @param tablesMapString
*/
protected void setTablesMapString(Map<String/* ���index */, String/* ���ʵ�ʱ��� */> tablesMapString) {
Map<String, SharedElement> beingConstructedMap = new HashMap<String, SharedElement>(
tablesMapString.size());
for (Entry<String, String> entry : tablesMapString.entrySet()) {
Table table = new Table();
table.setTableName(entry.getValue());
beingConstructedMap.put(entry.getKey(), table);
}
putAutoConstructedMapIntoCurrentTagMap(beingConstructedMap);
}
@SuppressWarnings("unchecked")
public void setTablesMapSimple(Object obj) {
if (obj instanceof Map) {
setTablesMapString((Map<String/* ���index */, String/* ���ʵ�ʱ��� */>) obj);
} else if (obj instanceof List) {
setTablesList((List) obj);
}
}
/**
* ����ҵ��ʹ��table1,table2,table3�ķ�ʽ��ָ��������key=�����±ꡣ ͬʱҲ����ҵ��ʹ��list.add("table1");
* list.add("table2");... �ķ�ʽ��ָ����Key=�����±�
*
* @param tablesString
*/
protected void setTablesList(List<String> tablesString) {
// û����tablesStringlist��not null��飬��Ϊ����spring
if (tablesString.size() == 1) {
String[] tokens = tablesString.get(0).split(",");
tablesString = new ArrayList<String>();
tablesString.addAll(Arrays.asList(tokens));
putAutoConstructedMapIntoCurrentTagMap(getTablesMapByStringList(tablesString));
} else {
putAutoConstructedMapIntoCurrentTagMap(getTablesMapByStringList(tablesString));
}
}
public String getDataSourceKey() {
return dataSourceKey;
}
public void setDataSourceKey(String dataSourceKey) {
this.dataSourceKey = dataSourceKey;
}
@Override
public String toString() {
return "Database [dataSourceKey=" + dataSourceKey + ", defaultListResult="
+ defaultListResult + ", defaultListResultStragety=" + defaultListResultStragety
+ ", listResultRule=" + listResultRule + ", subSharedElement=" + subSharedElement
+ "]";
}
public void setLogicTableName(String logicTable) {
this.logicTableName = logicTable;
}
public void setTableMapProvider(TableMapProvider tableMapProvider) {
this.tableMapProvider = tableMapProvider;
}
public void setTableRule(List<ListAbstractResultRule> tableRule) {
this.tableRuleList = tableRule;
}
public String getLogicTableName() {
return logicTableName;
}
public TableMapProvider getTableMapProvider() {
return tableMapProvider;
}
public RuleChain getRuleChain() {
return super.listResultRule;
}
public void setTableRuleChain(RuleChain ruleChain) {
super.listResultRule = ruleChain;
}
public void put(OneToManyEntry oneToManyEntry) {
this.oneToManyEntry = oneToManyEntry;
}
}