/**
* Alipay.com Inc.
* Copyright (c) 2004-2012 All Rights Reserved.
*/
package com.alipay.zdal.rule.bean;
import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import com.alipay.zdal.common.util.TableSuffixTypeEnum;
import com.alipay.zdal.rule.config.beans.Preffix;
import com.alipay.zdal.rule.ruleengine.entities.abstractentities.SharedElement;
/**
* �����û����õ�һ��groove�ű�����һ��List<string> ֱ��ƴ��һ��map����
*
*
*/
public class GroovyTableDatabaseMapProvider extends SimpleTableMapProvider {
private static final Logger log = Logger
.getLogger(GroovyTableDatabaseMapProvider.class);
private List<String> tableNames;
/**
* ���ݿ�ĸ���
*/
private int dbNumber;
private String expression; // groovy script
private Binding binding = new Binding();
private GroovyShell shell = new GroovyShell(binding);
/**
* ����ǰ� Ϊ��ʱ��Ĭ��ʹ�������� logicTable
*/
private Preffix tbPreffix;
/**
* ������
*/
private String logicTable;
private static Map<String, Object> tbSuffixRuleResult = new HashMap<String, Object>();
/**
* �ֱ����������
*/
private String tbType;
private DBAndNumberRelation dbAndNumberRelation = null;
private static class DBAndNumberRelation {
private final int[] dbNumber;
private final int[] tbNumber;
private final int[] dbNumberEnds;
private final int[] tbNumberEnds;
public DBAndNumberRelation(int[] dbNumber, int[] tbNumber) {
this.dbNumber = dbNumber;
this.tbNumber = tbNumber;
this.dbNumberEnds = genDBNumberEnds(dbNumber);
this.tbNumberEnds = genTbNumberEnds(dbNumber, tbNumber);
}
/**
* ��ȡ�������
*
* @param dbNumber
* @return
*/
private int[] genDBNumberEnds(int[] dbNumber) {
if (dbNumber == null) {
return null;
}
int[] dbNumberEnds = new int[dbNumber.length];
int sum = 0;
for (int i = 0; i < dbNumber.length; i++) {
sum += dbNumber[i];
dbNumberEnds[i] = sum;
}
return dbNumberEnds;
}
/**
* ��ȡ�������
*
* @param dbNumber
* @param tbNumber
* @return
*/
private int[] genTbNumberEnds(int[] dbNumber, int[] tbNumber) {
if (dbNumber == null) {
return null;
}
int[] tbNumberEnds = new int[dbNumber.length];
int sum = 0;
for (int i = 0; i < dbNumber.length; i++) {
sum += dbNumber[i] * tbNumber[i];
tbNumberEnds[i] = sum;
}
return tbNumberEnds;
}
}
/**
* ����Ӧ����д��groovy�ű����õ�һ����������table��list
*
* @param expression
* @return tables list
* @throws Exception
*/
@SuppressWarnings("unchecked")
protected List<String> getTableNames(String tableFactory, String expression)
throws IllegalArgumentException {
if (expression == null || expression.equals("")) {
throw new IllegalArgumentException("groovy script is null or empty!");
}
long time1 = System.currentTimeMillis();
// Object value = shell.evaluate(expression);
Object value = tbSuffixRuleResult.get(expression);
if (value == null) {
value = shell.evaluate(expression);
tbSuffixRuleResult.put(expression, value);
}
long time2 = System.currentTimeMillis();
if (log.isDebugEnabled()) {
log.debug("tbsuffix shell use time:" + (time2 - time1) + ",expression=" + expression);
}
/*
* ���ݽű����ɵĺ�������ǰ����������յ�ʵ�ʱ����б�
*/
if (value instanceof List) {
List<String> tableNameList = (List<String>) value;
List<String> finalList = new ArrayList<String>(tableNameList.size());
// ÿ�����������еı�
if (TableSuffixTypeEnum.groovyTableList.getValue().equals(this.tbType)) {
String temp = this.getPadding();
for (String tname : tableNameList) {
finalList.add(new StringBuilder(tableFactory).append(temp).append(tname)
.toString());
}
} else if (TableSuffixTypeEnum.groovyThroughAllDBTableList.getValue().equals(
this.tbType)) {
// �������ڸ÷ֿ�ı�ĺ�
int multiple = Integer.valueOf(super.getParentID());
int tableNumberForEachDB = tableNameList.size() / dbNumber;
int begin = multiple * tableNumberForEachDB;
int end = begin + tableNumberForEachDB;
String temp = this.getPadding();
for (int i = begin; i < end; i++) {
String tname = tableNameList.get(i);
finalList.add(new StringBuilder(tableFactory).append(temp).append(tname)
.toString());
}
} else if (TableSuffixTypeEnum.groovyAdjustTableList.getValue().equals(this.tbType)) {
// check һ��
if (this.dbAndNumberRelation.tbNumberEnds[this.dbAndNumberRelation.tbNumber.length - 1] != tableNameList
.size()
|| this.dbAndNumberRelation.dbNumberEnds[this.dbAndNumberRelation.dbNumber.length - 1] != this.dbNumber) {
throw new IllegalArgumentException(
"The size is different, error. tableNameList.size=" + tableNameList.size()
+ ",dbNumber=" + this.dbNumber);
}
int dbId = Integer.valueOf(super.getParentID());
int number = 0;
for (int i = 0; i < this.dbAndNumberRelation.dbNumberEnds.length; i++) {
if (dbId < (this.dbAndNumberRelation.dbNumberEnds)[i]) {
number = i;
break;
}
}
int begin = 0;
if (number > 0) {
for (int j = 0; j < number; j++) {
begin = begin + this.dbAndNumberRelation.dbNumber[j]
* this.dbAndNumberRelation.tbNumber[j];
}
begin = begin + (dbId - this.dbAndNumberRelation.dbNumberEnds[number - 1])
* this.dbAndNumberRelation.tbNumber[number];
} else {
begin = dbId * this.dbAndNumberRelation.tbNumber[0];
}
int end = begin + this.dbAndNumberRelation.tbNumber[number];
String temp = this.getPadding();
for (int i = begin; i < end; i++) {
String tname = tableNameList.get(i);
finalList.add(new StringBuilder(tableFactory).append(temp).append(tname)
.toString());
}
}
if (log.isDebugEnabled()) {
log.debug("dbId=" + super.getParentID() + ",tableNameList=" + finalList);
}
/*
* //���ָ��ÿ���ֱ��ֱ�ĸ���Ϊ-1��˵��ÿ���ⶼ�dz�ʼ�����еı� if
* (super.doesNotSetTablesNumberForEachDatabases()) { String temp =
* this.getPadding(); for (String tname : tableNameList) {
* finalList.add(new
* StringBuilder(tableFactory).append(temp).append(tname)
* .toString()); } } else { //�������ڸ÷ֿ�ı�ĺ� int multiple =
* Integer.valueOf(super.getParentID()); int tableNumberForEachDB =
* tableNameList.size() / dbNumber; int begin = multiple *
* tableNumberForEachDB; int end = begin + tableNumberForEachDB;
* String temp = this.getPadding(); for (int i = begin; i < end;
* i++) { String tname = tableNameList.get(i); finalList.add(new
* StringBuilder(tableFactory).append(temp).append(tname)
* .toString()); } }
*/
return finalList;
} else {
throw new IllegalArgumentException("ִ�нű��õ��˴��������!����");
}
}
/**
* ���������е�groovy�ű�������һ��table map
*
* @return Map<String, SharedElement>
*/
public Map<String, SharedElement> getTablesMap() {
if (getTbPreffix() != null) {
setTableFactor(getTbPreffix().getTbPreffix());
} else if (getTableFactor() == null && getLogicTable() != null) {
setTableFactor(logicTable);
}
if (getTableFactor() == null) {
throw new IllegalArgumentException("û�б�����������");
}
try {
this.tableNames = getTableNames(getTableFactor(), getExpression());
} catch (Exception e) {
log.error("���ܵõ�tablesNames ,ֱ�ӷ���null. ", e);
return null;
}
List<Table> tables = null;
tables = new ArrayList<Table>(tableNames.size());
for (String tableName : tableNames) {
Table tab = new Table();
tab.setTableName(tableName);
if (log.isDebugEnabled()) {
log.debug("Groovy table databases provide : get table names from groovy script "
+ tableName);
}
tables.add(tab);
}
Map<String, SharedElement> returnMap = getSharedElemenetMapBySharedElementList(tables);
return returnMap;
}
public Map<String, SharedElement> getSharedElemenetMapBySharedElementList(
List<? extends SharedElement> sharedElementList) {
Map<String, SharedElement> returnMap = new HashMap<String, SharedElement>();
if (sharedElementList != null) {
for (SharedElement sharedElement : sharedElementList) {
Table t = (Table) sharedElement;
String key = t.getTableName().substring(
getTableFactor().length() + this.getPadding().length());
// String key =
// t.getTableName().substring(getTableFactor().length());
returnMap.put(key, sharedElement);
}
}
return returnMap;
}
@Override
protected List<String> getSuffixList(int from, int to, int width, int step, String tableFactor,
String padding) {
return null;
}
public List<String> getTableNames() {
return tableNames;
}
public void setTableNames(List<String> tableNames) {
this.tableNames = tableNames;
}
public String getExpression() {
return expression;
}
public void setExpression(String expression) {
// �������������ķ�ʽ�����������
if (TableSuffixTypeEnum.groovyAdjustTableList.getValue().equals(this.tbType)) {
String temp[] = expression.split(":");
// �ж��Ƿ����[20_10,200_1]��ʽ
if (!temp[0].startsWith("[") || !temp[0].endsWith("]")) {
throw new IllegalArgumentException("The tbsuffix of groovyAjustTableList error!");
}
// ȥ��[]
String part = temp[0].substring(1, temp[0].length() - 1);
String[] part2 = part.split(",");
int[] dbNumber = new int[part2.length];
int[] tbNumber = new int[part2.length];
for (int i = 0; i < part2.length; i++) {
String temp2[] = part2[i].split("_");
if (temp2.length != 2) {
throw new IllegalArgumentException("The db_table number relation error! it is "
+ part);
}
dbNumber[i] = Integer.parseInt(temp2[0].trim());
tbNumber[i] = Integer.parseInt(temp2[1].trim());
}
this.setDbAndNumberRelation(new DBAndNumberRelation(dbNumber, tbNumber));
expression = temp[1].trim();
}
this.expression = expression;
}
public String getLogicTable() {
return logicTable;
}
public void setLogicTable(String logicTable) {
this.logicTable = logicTable;
}
public Preffix getTbPreffix() {
return tbPreffix;
}
public void setTbPreffix(Preffix tbPreffix) {
this.tbPreffix = tbPreffix;
}
/**
* Setter method for property <tt>dbNumber</tt>.
*
* @param dbNumber
* value to be assigned to property dbNumber
*/
public void setDbNumber(int dbNumber) {
this.dbNumber = dbNumber;
}
/**
* Getter method for property <tt>dbNumber</tt>.
*
* @return property value of dbNumber
*/
public int getDbNumber() {
return dbNumber;
}
public String getTbType() {
return tbType;
}
public void setTbType(String tbType) {
this.tbType = tbType;
}
/**
* Setter method for property <tt>dbAndNumberRelation</tt>.
*
* @param dbAndNumberRelation
* value to be assigned to property dbAndNumberRelation
*/
public void setDbAndNumberRelation(DBAndNumberRelation dbAndNumberRelation) {
this.dbAndNumberRelation = dbAndNumberRelation;
}
/**
* Getter method for property <tt>dbAndNumberRelation</tt>.
*
* @return property value of dbAndNumberRelation
*/
public DBAndNumberRelation getDbAndNumberRelation() {
return dbAndNumberRelation;
}
}