/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.citrus.util.regex;
import static com.alibaba.citrus.util.Assert.*;
import static com.alibaba.citrus.util.StringUtil.*;
/**
* 代表一个替换。替换字符串中的变量。通常变量以<code>'$'</code>开始,例如: <code>$1</code>,<code>$2</code>
* 等,但<code>Substitution</code>类可支持对多种不同前缀的变量进行替换。
*
* @author Michael Zhou
*/
public abstract class Substitution {
protected final String replacementPrefixes;
/** 创建一个替换,以<code>'$'</code>为变量前缀。 */
public Substitution() {
this("$");
}
/** 创建一个替换,以指定字符为变量前缀。 */
public Substitution(String replacementPrefixes) {
this.replacementPrefixes = assertNotNull(trimToNull(replacementPrefixes), "replacementPrefixes");
}
/** 替换字符串中的变量。 */
public final String substitute(String input) {
if (input == null) {
return null;
}
StringBuilder buf = new StringBuilder();
substitute(buf, input);
return buf.toString();
}
/** 替换字符串中的变量。 */
public final void substitute(StringBuilder buf, String input) {
int length = input.length();
int index;
for (int i = 0; i < length; ) {
char ch = input.charAt(i);
if (ch == '\\') {
i++;
if (i < length) {
buf.append(input.charAt(i++));
} else {
buf.append(ch);
}
} else if ((index = replacementPrefixes.indexOf(ch)) >= 0) {
i++;
int num = -1;
int numStartIndex = i; // 保存index
while (i < length) {
int digit = input.charAt(i) - '0';
if (digit < 0 || digit > 9) {
break;
}
i++;
if (num == -1) {
num = digit;
} else {
num = num * 10 + digit;
}
}
String groupValue;
if (num == -1) { // not a number
buf.append(ch);
} else if ((groupValue = group(index, num)) != null) {
buf.append(groupValue);
} else { // out of range
buf.append(ch);
buf.append(input, numStartIndex, i);
}
} else {
buf.append(ch);
i++;
}
}
}
/** 子类覆盖此方法,以提供指定类型、指定group序号的的replacement结果。 */
protected abstract String group(int index, int groupNumber);
}