package com.taobao.tddl.rule.utils; import java.util.Calendar; import com.taobao.tddl.common.utils.TStringUtil; import com.taobao.tddl.rule.model.AdvancedParameter; import com.taobao.tddl.rule.model.AdvancedParameter.AtomIncreaseType; import com.taobao.tddl.rule.model.AdvancedParameter.Range; import com.taobao.tddl.rule.model.DateEnumerationParameter; /** * {@linkplain AdvancedParameter}解析器 * * @author jianghang 2013-10-29 下午5:18:27 * @since 5.0.0 */ public class AdvancedParameterParser { public static final String PARAM_SEGMENT_SPLITOR = ","; public static final char NEED_APPEAR_SYMBOL = '?'; public static final String INCREASE_TYPE_SPLITOR = "_"; public static final String RANGE_SEGMENT_SPLITOR = "|"; public static final String RANGE_SEGMENT_START_END_SPLITOR = "_"; /** * @param paramToken 定义变量的分表片段,形式类似 #gmt_create?,1_month,-12_12# * #id,1_number,1024# #name,1_string,a_z# #id,1_number,0_1024|1m_1g# * @param completeConfig 如果为true,那么paramToken必须满足逗号分隔的3段形式 * 如果为false,那么paramToken可以只配置分表或者分表键 2.3.x-2.4.3的老规则配置该参数为false * 2.4.4后支持的新规则配置该参数为true; */ public static AdvancedParameter getAdvancedParamByParamTokenNew(String paramToken, boolean completeConfig) { String key; boolean[] needAppear = new boolean[1]; AtomIncreaseType atomicIncreateType = null; Comparable<?> atomicIncreateValue = null; Range[] rangeObjectArray = null; Integer cumulativeTimes = null; String[] paramTokens = TStringUtil.split(paramToken, PARAM_SEGMENT_SPLITOR); switch (paramTokens.length) { case 1: if (completeConfig) { throw new IllegalArgumentException("规则必须配置完全,格式如下:#id,1_number,1024#"); } key = parseKeyPart(paramTokens[0], needAppear); break; case 2: // 若只有两个,自增类型默认为number,自增值默认为1; 其他同case 3 key = parseKeyPart(paramTokens[0], needAppear); atomicIncreateType = AtomIncreaseType.NUMBER; atomicIncreateValue = 1; try { rangeObjectArray = parseRangeArray(paramTokens[1]); cumulativeTimes = getCumulativeTimes(rangeObjectArray[0]); } catch (NumberFormatException e) { throw new IllegalArgumentException("输入的参数不为Integer类型,参数为:" + paramToken, e); } catch (Exception e) { throw new IllegalArgumentException(e); } break; case 3: key = parseKeyPart(paramTokens[0], needAppear); try { atomicIncreateType = getIncreaseType(paramTokens[1]); atomicIncreateValue = getAtomicIncreaseValue(paramTokens[1], atomicIncreateType); rangeObjectArray = parseRangeArray(paramTokens[2]); // 长度为三必定有范围定义,否则直接抛错 // 如果范围有多段("|"分割),那么以第一段的跨度为标准 cumulativeTimes = getCumulativeTimes(rangeObjectArray[0]); } catch (NumberFormatException e) { throw new IllegalArgumentException("输入的参数不为Integer类型,参数为:" + paramToken, e); } catch (Exception e) { throw new IllegalArgumentException(e); } break; default: throw new IllegalArgumentException("错误的参数个数,必须为1个或者3个,3个的时候为允许使用" + "枚举时的数据"); } return new AdvancedParameter(key, atomicIncreateValue, cumulativeTimes, needAppear[0], atomicIncreateType, rangeObjectArray); } /** * ColumnName?表示可选 * * @param keyPart 不可能传入null */ private static String parseKeyPart(String keyPart, boolean[] needAppear) { String key; keyPart = keyPart.trim(); int endIndex = keyPart.length() - 1; if (keyPart.charAt(endIndex) == NEED_APPEAR_SYMBOL) { needAppear[0] = true; key = keyPart.substring(0, endIndex); } else { needAppear[0] = false; key = keyPart; } return key; } private static AtomIncreaseType getIncreaseType(String paramTokenStr) { String[] increase = TStringUtil.split(paramTokenStr.trim(), INCREASE_TYPE_SPLITOR); if (increase.length == 1) { return AtomIncreaseType.NUMBER; } else if (increase.length == 2) { return AtomIncreaseType.valueOf(increase[1].toUpperCase()); } else { throw new IllegalArgumentException("自增配置定义错误:" + paramTokenStr); } } private static Comparable<?> getAtomicIncreaseValue(String paramTokenStr, AtomIncreaseType type) { String[] increase = TStringUtil.split(paramTokenStr.trim(), INCREASE_TYPE_SPLITOR); // 如果长度为1,那么默认为数字类型 if (increase.length == 1) { return Integer.valueOf(increase[0]); } else if (increase.length == 2) { switch (type) { case NUMBER: return Integer.valueOf(increase[0]); case DATE: return new DateEnumerationParameter(Integer.valueOf(increase[0]), Calendar.DATE); case MONTH: return new DateEnumerationParameter(Integer.valueOf(increase[0]), Calendar.MONTH); case YEAR: return new DateEnumerationParameter(Integer.valueOf(increase[0]), Calendar.YEAR); case HOUR: return new DateEnumerationParameter(Integer.valueOf(increase[0]), Calendar.HOUR_OF_DAY); default: throw new IllegalArgumentException("不支持的自增类型:" + type); } } else { throw new IllegalArgumentException("自增配置定义错误:" + paramTokenStr); } } private static Range[] parseRangeArray(String paramTokenStr) { String[] ranges = TStringUtil.split(paramTokenStr, RANGE_SEGMENT_SPLITOR); Range[] rangeObjArray = new Range[ranges.length]; for (int i = 0; i < ranges.length; i++) { String range = ranges[i].trim(); String[] startEnd = TStringUtil.split(range, RANGE_SEGMENT_START_END_SPLITOR); if (startEnd.length == 1) { if (i == 0) { rangeObjArray[i] = new Range(Integer.valueOf(0), Integer.valueOf(startEnd[0])); } else { rangeObjArray[i] = new Range(fromReadableInt(startEnd[0]), fromReadableInt(startEnd[0])); } } else if (startEnd.length == 2) { rangeObjArray[i] = new Range(fromReadableInt(startEnd[0]), fromReadableInt(startEnd[1])); } else { throw new IllegalArgumentException("范围定义错误," + paramTokenStr); } } return rangeObjArray; } /** * 1m = 1,000,000; 2M = 2,000,000 1g = 1,000,000,000 3G = 3,000,000,000 */ private static int fromReadableInt(String readableInt) { char c = readableInt.charAt(readableInt.length() - 1); if (c == 'm' || c == 'M') { return Integer.valueOf(readableInt.substring(0, readableInt.length() - 1)) * 1000000; } else if (c == 'g' || c == 'G') { return Integer.valueOf(readableInt.substring(0, readableInt.length() - 1)) * 1000000000; } else { return Integer.valueOf(readableInt); } } private static Integer getCumulativeTimes(Range ro) { return ro.end - ro.start; } }