PageRenderTime 177ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/java/com/taobao/itest/tb/tddl/RuleCalUtil.java

https://github.com/qz267/automanx-api
Java | 464 lines | 357 code | 29 blank | 78 comment | 68 complexity | a666b4bc717eabc10e37e37b1593b903 MD5 | raw file
  1. package com.taobao.itest.tb.tddl;
  2. import java.lang.reflect.Field;
  3. import java.util.Arrays;
  4. import java.util.Calendar;
  5. import java.util.Collection;
  6. import java.util.Date;
  7. import java.util.HashMap;
  8. import java.util.Iterator;
  9. import java.util.List;
  10. import java.util.Map;
  11. import java.util.Set;
  12. import javax.script.ScriptEngine;
  13. import javax.script.ScriptEngineManager;
  14. import org.apache.poi.hssf.usermodel.HSSFCell;
  15. import org.apache.poi.hssf.usermodel.HSSFCellStyle;
  16. import org.apache.poi.hssf.usermodel.HSSFDataFormat;
  17. import org.apache.poi.hssf.usermodel.HSSFDateUtil;
  18. import org.apache.poi.hssf.usermodel.HSSFRow;
  19. import org.apache.poi.hssf.usermodel.HSSFSheet;
  20. import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  21. import org.apache.poi.ss.usermodel.Cell;
  22. /**
  23. * shard rule calculate util, if there have excel need to be shard, the
  24. * <method>calDataSet()</method> method can shard the data into right
  25. * dataSources and tables by the specified rules
  26. *
  27. * @author junliang
  28. */
  29. public class RuleCalUtil {
  30. private static final String LONE_VALUE = ".longValue()";
  31. private static final String HASH_CODE = ".hashCode()";
  32. private static Date _now = new Date();
  33. public static Map<String, HSSFWorkbook> calDataSet(AppRule rootRule,
  34. HSSFWorkbook sourceSet, Date now) {
  35. Map<String, HSSFWorkbook> result = new HashMap<String, HSSFWorkbook>();
  36. if (now != null) {
  37. _now = now;
  38. }
  39. /**
  40. * 1.循环rootRule.rootMap,主备库配置,每个元素对应一份sourceSet;
  41. * 2.循环ShardRule.tableRules,对每个表的数据进行分库,分表运算
  42. * a.根据tableRule.dbIndexes和tableRule.tbSuffix初始化result Map
  43. * b.根据tableRule.dbRules对sourceSet中的数据进行分库运算(先判断不分库的情况),运算结果存储在tempSet中
  44. * c.根据tableRule.tbRules对tempSet中的数据进行分表运算(先判断不分表的情况),运算结果存储在result中
  45. */
  46. Map<String, ShardRule> rootMap = rootRule.getRootMap();
  47. for (ShardRule shardRule : rootMap.values()) {
  48. Map<String, TableRule> tableRules = shardRule.getTableRules();
  49. int sNum = sourceSet.getNumberOfSheets();
  50. for (int i = 0; i < sNum; i++) {
  51. HSSFSheet sheet = sourceSet.getSheetAt(i);
  52. if (sheet.getPhysicalNumberOfRows() < 1) {// this sheet has no
  53. // data, ignore it
  54. continue;
  55. }
  56. String sheetName = sourceSet.getSheetName(i);
  57. TableRule tableRule = tableRules.get(sheetName);
  58. if (tableRule == null) {
  59. throw new RuntimeException(
  60. "there has no rule for table ["
  61. + sheetName
  62. + "], the rule config only for these tables \n"
  63. + tableRules.keySet()
  64. + ",\n please check your rule configuration or data preparation!");
  65. }
  66. if (tableRule.getLogicTableName() == null) {
  67. if (tableRule.isUniqueTB()
  68. && tableRule.getUniqueTB() != null
  69. && !"".equals(tableRule.getUniqueTB())) {
  70. tableRule.setLogicTableName(tableRule.getUniqueTB());
  71. } else {
  72. tableRule.setLogicTableName(sheetName);
  73. }
  74. }
  75. dealSheetData(result, tableRule, sheet);
  76. }
  77. }
  78. return result;
  79. }
  80. private static void dealSheetData(Map<String, HSSFWorkbook> result,
  81. TableRule tableRule, HSSFSheet sheet) {
  82. HSSFRow fieldNames = sheet.getRow(0);
  83. String targetDsName = null;
  84. String targetTbName = null;
  85. int rowNum = sheet.getPhysicalNumberOfRows();
  86. for (int i = 1; i < rowNum; i++) {
  87. HSSFRow data = sheet.getRow(i);
  88. if (tableRule.isUniqueDB()) {
  89. targetDsName = tableRule.getUniqueDB();
  90. } else {
  91. String dbRule = decideRule(tableRule.getDbRules(), fieldNames,
  92. data);
  93. int dbIndex = calRule(dbRule, fieldNames, data);
  94. targetDsName = tableRule.getDbIndexes()[dbIndex];
  95. }
  96. if (tableRule.isUniqueTB()) {
  97. targetTbName = tableRule.getUniqueTB();
  98. } else {
  99. String tbRule = decideRule(tableRule.getTbRules(), fieldNames,
  100. data);
  101. int tbIndex = calRule(tbRule, fieldNames, data);
  102. Map<String, List<String>> dbTableMap = tableRule
  103. .getDbTableNames();
  104. targetTbName = dbTableMap.get(targetDsName).get(tbIndex);
  105. }
  106. HSSFWorkbook workbook = result.get(targetDsName);
  107. if (workbook == null) {
  108. workbook = new HSSFWorkbook();
  109. }
  110. addRow2Workbook(workbook, targetTbName, fieldNames, data);
  111. result.put(targetDsName, workbook);
  112. }
  113. }
  114. private static String decideRule(String[] rules, HSSFRow fieldNames,
  115. HSSFRow data) {
  116. Map<String, Integer> fieldMap = converFieldName2Map(fieldNames);
  117. if (rules.length == 1) {// 只有一条,直接返回
  118. return rules[0];
  119. }
  120. for (String rule : rules) {// 有多条,返回rules中下标最小且变量数据都存在的规则
  121. Map<String, String[]> varMap = getVariableMap(rule);
  122. if (varMap.size() == 0) {// 规则中没有变量,直接返回
  123. return rule;
  124. }
  125. Collection<String[]> values = varMap.values();
  126. boolean flag = false;// 是否有在数据中找不到的变量
  127. for (String[] value : values) {
  128. String fieldName = value[0];
  129. Integer index = fieldMap.get(fieldName);
  130. if (index == null) {
  131. flag = true;
  132. break;
  133. }
  134. HSSFCell cell = data.getCell(index);
  135. if (cell == null || cell.toString() == null
  136. || "".equals(cell.toString())) {
  137. flag = true;
  138. break;
  139. }
  140. }
  141. if (!flag) {
  142. return rule;
  143. }
  144. }
  145. throw new RuntimeException(
  146. "rule config or data prepare is invalid:rules="
  147. + Arrays.toString(rules) + " data="
  148. + convertRow2String(data));
  149. }
  150. private static String convertRow2String(HSSFRow row) {
  151. StringBuilder sb = new StringBuilder("{");
  152. Iterator<Cell> it = row.cellIterator();
  153. while (it.hasNext()) {
  154. sb.append(it.next().toString()).append(", ");
  155. }
  156. sb.append("}");
  157. return sb.toString().replaceFirst(", }", "}");
  158. }
  159. /**
  160. * 运算规则就是普通的数学表达式,运算优先级仅可用"()"指示,规则中可以包含具体的数值也可以包含一个或多个变量,
  161. * 规则中仅支持三种类型的变量:String,Long和Date,对应这三类变量有如下强制规则</br> <li>
  162. * String的表达式为:[#field_name#.hashCode()]</li> <li>
  163. * Long的表达式为:[#field_name#.longValue()]</li> <li>
  164. * Date的表达式为:[#field_name#.DAY_OF_WEEK],其中DAY_OF_WEEK可以替换成任意</br>
  165. * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  166. * java.util.Calendar类中支持java.util.Calendar.get(int field)方法的字段名</li>
  167. * </br></br> 规则表达式示例:</br>
  168. * ([#field_name1#.hashCode()]+[#field_name1#.longValue()])%4/2 </br></br>
  169. *
  170. * @param rule
  171. * 规则表达式
  172. * @param fieldNames
  173. * excel中表示字段名的HSSFRow对象
  174. * @param data
  175. * excel中的一行数据,data中的元素与fieldNames中的元素顺序一一对应
  176. * @return 根据规则和变量值计算出的int值,如果实际计算出的值包含小数位,返回舍弃小数位后的int值
  177. */
  178. private static int calRule(String rule, HSSFRow fieldNames, HSSFRow data) {
  179. String mathExp = replaceVariable(rule, fieldNames, data);
  180. Double result = (Double) calMathExp(mathExp);
  181. return result.intValue();
  182. }
  183. private static Object calMathExp(String expression) {
  184. Object result = null;
  185. try {
  186. ScriptEngineManager sem = new ScriptEngineManager();
  187. ScriptEngine se = sem.getEngineByExtension("js");
  188. result = se.eval(expression);
  189. } catch (Exception e) {
  190. throw new RuntimeException("cal math expression failed: "
  191. + expression);
  192. }
  193. return result;
  194. }
  195. private static String replaceVariable(String rule, HSSFRow fieldNames,
  196. HSSFRow data) {
  197. Map<String, String[]> variables = getVariableMap(rule);
  198. Map<String, Long> varValues = getVariableValue(variables, fieldNames,
  199. data);
  200. Set<String> keySet = varValues.keySet();
  201. for (String key : keySet) {
  202. String regex = key.replaceAll("[\\[\\]]", "");
  203. rule = rule.replaceAll(regex, varValues.get(key).toString());
  204. }
  205. rule = rule.replaceAll("[\\[\\]]", "").replaceAll("\\(\\)", "");
  206. return rule;
  207. }
  208. // return as: Map<"[#field_name#.hashCode()]", {"field_name",
  209. // ".hashCode()"}>
  210. private static Map<String, String[]> getVariableMap(String rule) {
  211. Map<String, String[]> map = new HashMap<String, String[]>();
  212. String temp = new String(rule.replaceAll(" ", ""));
  213. while (temp.indexOf("[") != -1) {
  214. String key = temp.substring(temp.indexOf("["),
  215. temp.indexOf("]") + 1).trim();
  216. String fieldName = key
  217. .substring(key.indexOf("#") + 1, key.lastIndexOf("#"))
  218. .trim().toUpperCase();
  219. String operation = key
  220. .substring(key.indexOf("."), key.indexOf("]")).trim();
  221. String[] value = { fieldName, operation };
  222. map.put(key, value);
  223. temp = temp.replaceAll(key.substring(1, key.length() - 1), "")
  224. .replaceAll("\\[\\(\\)\\]", "").replaceAll("\\[\\]", "");
  225. }
  226. return map;
  227. }
  228. /**
  229. * @param variables
  230. * : Map<"[#field_name#.hashCode()]", {"field_name",
  231. * ".hashCode()"}>
  232. * @return Map<"[#field_name#.hashCode()]", 123>
  233. */
  234. private static Map<String, Long> getVariableValue(
  235. Map<String, String[]> variables, HSSFRow fieldNames, HSSFRow data) {
  236. Map<String, Long> map = new HashMap<String, Long>();
  237. Map<String, Integer> fieldIndex = converFieldName2Map(fieldNames);
  238. Set<java.util.Map.Entry<String, String[]>> entries = variables
  239. .entrySet();
  240. for (java.util.Map.Entry<String, String[]> entry : entries) {
  241. String[] value = entry.getValue();
  242. String fieldName = value[0];
  243. String operation = value[1];
  244. Integer index = fieldIndex.get(fieldName);
  245. if (index == null) {
  246. throw new RuntimeException(
  247. "there has no Field named ["
  248. + fieldName
  249. + "] in the fields:\n "
  250. + fieldIndex.keySet()
  251. + ",\n please check your rule configuration or data preparation!");
  252. }
  253. if (LONE_VALUE.equals(operation)) {
  254. HSSFCell datacell = data.getCell(index);
  255. long rtValue = 0;
  256. if (datacell.getCellType() == HSSFCell.CELL_TYPE_NUMERIC) {
  257. rtValue = (long) datacell.getNumericCellValue();
  258. } else {
  259. rtValue = Long.valueOf(datacell.getRichStringCellValue()
  260. .getString().trim());
  261. }
  262. map.put(entry.getKey(), rtValue);
  263. } else if (HASH_CODE.equals(operation)) {
  264. long rtValue = data.getCell(index).getRichStringCellValue()
  265. .getString().hashCode();
  266. map.put(entry.getKey(), Math.abs(rtValue));
  267. } else {// can only be date operation
  268. Map<String, Date> replacements = getSysdateReplacement();
  269. Date date = replacements.get(data.getCell(index).toString());
  270. if (date == null) {
  271. date = data.getCell(index).getDateCellValue();
  272. }
  273. Calendar c = Calendar.getInstance();
  274. c.setTime(date);
  275. try {
  276. if (operation.startsWith(".")) {
  277. operation = operation.substring(1, operation.length());
  278. }
  279. Field cField = c.getClass().getField(operation);
  280. long rtValue = c.get(cField.getInt(cField));
  281. map.put(entry.getKey(), rtValue);
  282. } catch (SecurityException e) {
  283. e.printStackTrace();
  284. } catch (NoSuchFieldException e) {
  285. e.printStackTrace();
  286. } catch (IllegalArgumentException e) {
  287. e.printStackTrace();
  288. } catch (IllegalAccessException e) {
  289. e.printStackTrace();
  290. }
  291. }
  292. }
  293. return map;
  294. }
  295. private static Map<String, Integer> converFieldName2Map(HSSFRow fieldNames) {
  296. Map<String, Integer> map = new HashMap<String, Integer>();
  297. Iterator<Cell> it = fieldNames.cellIterator();
  298. Integer index = 0;
  299. while (it.hasNext()) {
  300. Cell cell = it.next();
  301. String cellValue = cell.getRichStringCellValue().getString().trim()
  302. .toUpperCase();
  303. map.put(cellValue, index);
  304. index++;
  305. }
  306. return map;
  307. }
  308. private static Map<String, Date> getSysdateReplacement() {
  309. Map<String, Date> replacement = new HashMap<String, Date>();
  310. replacement.put("sysdate", _now);
  311. long day = 3600 * 24 * 1000;
  312. for (int i = 1; i < 32; i++) {
  313. replacement.put("sysdate+" + i, new Date(_now.getTime() + i * day));
  314. replacement.put("sysdate-" + i, new Date(_now.getTime() - i * day));
  315. }
  316. return replacement;
  317. }
  318. private static void addRow2Workbook(HSSFWorkbook workbook,
  319. String sheetName, HSSFRow fieldNames, HSSFRow data) {
  320. HSSFSheet sheet = workbook.getSheet(sheetName);
  321. if (sheet == null) {
  322. sheet = workbook.createSheet(sheetName);
  323. addRow2Sheet(workbook, sheet, fieldNames);
  324. }
  325. addRow2Sheet(workbook, sheet, data);
  326. }
  327. private static void addRow2Sheet(HSSFWorkbook workbook, HSSFSheet sheet,
  328. HSSFRow row) {
  329. int lastRowNum = sheet.getLastRowNum();
  330. int newRowNum = lastRowNum + 1;
  331. if (lastRowNum == 0 && sheet.getPhysicalNumberOfRows() == 0) {
  332. newRowNum = 0;
  333. }
  334. HSSFRow targetRow = sheet.createRow(newRowNum);
  335. Iterator<Cell> it = row.cellIterator();
  336. while (it.hasNext()) {
  337. Cell sourceCell = it.next();
  338. HSSFCell targetCell = targetRow.createCell(sourceCell
  339. .getColumnIndex());
  340. // targetCell.setCellStyle(sourceCell.getCellStyle());
  341. if (sourceCell.getCellComment() != null) {
  342. targetCell.setCellComment(sourceCell.getCellComment());
  343. }
  344. int cType = sourceCell.getCellType();
  345. targetCell.setCellType(cType);
  346. switch (cType) {
  347. case HSSFCell.CELL_TYPE_BOOLEAN:
  348. targetCell.setCellValue(sourceCell.getBooleanCellValue());
  349. break;
  350. case HSSFCell.CELL_TYPE_ERROR:
  351. targetCell.setCellErrorValue(sourceCell.getErrorCellValue());
  352. break;
  353. case HSSFCell.CELL_TYPE_FORMULA:
  354. targetCell.setCellFormula(parseFormula(sourceCell
  355. .getCellFormula()));
  356. break;
  357. case HSSFCell.CELL_TYPE_NUMERIC:
  358. if (HSSFDateUtil.isCellDateFormatted(sourceCell)) {
  359. targetCell.setCellValue(sourceCell.getDateCellValue());
  360. HSSFCellStyle cellStyle = workbook.createCellStyle();
  361. HSSFDataFormat format = workbook.createDataFormat();
  362. cellStyle.setDataFormat(format
  363. .getFormat("yyyy-mm-dd hh:mm:ss"));
  364. targetCell.setCellStyle(cellStyle);
  365. } else {
  366. targetCell.setCellValue(sourceCell.getNumericCellValue());
  367. HSSFCellStyle cellStyle = workbook.createCellStyle();
  368. HSSFDataFormat format = workbook.createDataFormat();
  369. cellStyle.setDataFormat(format.getFormat(sourceCell
  370. .getCellStyle().getDataFormatString()));
  371. targetCell.setCellStyle(cellStyle);
  372. }
  373. break;
  374. case HSSFCell.CELL_TYPE_STRING:
  375. targetCell.setCellValue(sourceCell.getRichStringCellValue());
  376. break;
  377. }
  378. }
  379. }
  380. private static String parseFormula(String pPOIFormula) {
  381. final String cstReplaceString = "ATTR(semiVolatile)"; //$NON-NLS-1$
  382. StringBuffer result = null;
  383. int index;
  384. result = new StringBuffer();
  385. index = pPOIFormula.indexOf(cstReplaceString);
  386. if (index >= 0) {
  387. result.append(pPOIFormula.substring(0, index));
  388. result.append(pPOIFormula.substring(index
  389. + cstReplaceString.length()));
  390. } else {
  391. result.append(pPOIFormula);
  392. }
  393. return result.toString();
  394. }
  395. public static void main(String[] args) {
  396. // System.out.println(((Double)calMathExp("7<<1")).intValue());
  397. // Calendar c = Calendar.getInstance();
  398. // Field field;
  399. // try {
  400. // field = c.getClass().getField("DAY_OF_WEEK");
  401. // System.out.println(field.getInt(field));
  402. // System.out.println(c.get(field.getInt(field)));
  403. // } catch (SecurityException e1) {
  404. // e1.printStackTrace();
  405. // } catch (NoSuchFieldException e1) {
  406. // e1.printStackTrace();
  407. // } catch (IllegalArgumentException e) {
  408. // e.printStackTrace();
  409. // } catch (IllegalAccessException e) {
  410. // e.printStackTrace();
  411. // }
  412. // HSSFWorkbook workbook = new HSSFWorkbook();
  413. // HSSFSheet sheet = workbook.createSheet();
  414. // HSSFRow row = sheet.createRow(0);
  415. // HSSFCell cell = row.createCell(0);
  416. // cell.setCellValue(new Date());
  417. // System.out.println(cell.getCellType());
  418. // System.out.println("cell="+cell.toString());
  419. // Iterator<Cell> it = row.cellIterator();
  420. // while(it.hasNext()){
  421. // System.out.println(it.next().toString());
  422. // }
  423. String key = "[#user_id#.DAYOFWEEK][]";
  424. // String rule = "[#user_id#.DAYOFWEEK]%3()-(3*2)";
  425. // String regex = key.replaceAll("[\\[\\]]", "");
  426. // System.out.println(regex);
  427. // rule = rule.replaceAll(regex, "333");
  428. // System.out.println(rule);
  429. // rule = rule.replaceAll("[\\[\\]]", "").replaceAll("\\(\\)",
  430. // "");//.replaceAll("[\\()]", "");
  431. // System.out.println(rule);
  432. System.out.println(key.substring(1, key.length() - 1));
  433. System.out.println(key.replaceAll("\\[\\]", ""));
  434. }
  435. }