可定製替換規則的文本替換器

可以根據需要改進:

1. 讓其不僅僅可以改SIM卡名稱,適用於普遍的替換。(考慮提取抽象類)

2. 使用Omission策略判斷可更多地使用正則表達式。(比如在判斷 “ sim ” 和 ”simple“上)

3. 有一些特殊例子符合Omission策略,而實際卻不能被忽略,這種情況應當能處理。(考慮修改Omission接口,增加一個會被優先處理的函數)

4. 改進效率,目前在太多的地方使用了String。


建議先閱讀 main(), 以便了解代碼功能。

package com.xxx.modify;

import java.util.ArrayList;
import java.util.List;

/**
 * To change the sim name to uim name.
 * 
 * @author [email protected]
 * 
 */
public final class SimNameModifer {

	// please make sure the length of 'SIM_STR' equals the length of 'UIM_STR'
	private static final String[] SIM_STR = { "sim", "Sim", "SIM" };
	private static final String[] UIM_STR = { "uim", "Uim", "UIM" };

	/**
	 * see main() in this class.
	 */
	public static CharSequence change1(CharSequence c) {
		return change2(c);
	}

	// TODO optimize: may use StringBuiler
	/**
	 * see main() in this class.
	 */
	public static String change2(CharSequence c) {
		if (c == null)
			return null;

		ArrayList<Omission> omits = new ArrayList<Omission>();
		omits.add(omitWord);

		String str = c.toString();
		for (int i = 0; i < SIM_STR.length; i++) {
			str = replace(str, SIM_STR[i], UIM_STR[i], omits);
		}

		return str;
	}

	// to omit the word include s1.
	// (e. s1 = "sim", the "simple" will be omit)
	private static Omission omitWord = new Omission() {
		@Override
		public boolean isOmit(String str, String s1, String s2, int from) {
			int i = str.indexOf(s1, from);
			if (i < 0)
				return false;

			int before = i - 1; // the index before the s1
			int after = i + s1.length();
			boolean haveBefore = before >= 0;
			boolean haveAfter = after < str.length();
			if (haveBefore && isLetter(str.charAt(before)))
				return true;
			if (haveAfter && isLetter(str.charAt(after)))
				return true;

			return false;
		}

		private boolean isLetter(Character c) {
			return c.toString().matches("[a-zA-Z]");
		}
	};

	// according to the 'omits' rule2, replace all s1 in str with s2.
	private static String replace(String str, String s1, String s2,
			List<Omission> omits) {
		// TODO check args and throw
		int i = -1;
		StringBuilder sb = new StringBuilder(str);
		NO_REPLACE: while ((i = sb.indexOf(s1, i + 1)) >= 0) {
			if (omits != null) {
				for (Omission o : omits) {
					if (o.isOmit(str, s1, s2, i)) {
						continue NO_REPLACE;
					}
				}
			}

			sb.replace(i, i + s1.length(), s2);
		}

		return sb.toString();
	}

	// all System.out.println(...equals(...)) are print "true"
	public static void main(String[] args) {
		String s1 = "uim card is Uim card is UIM card, not simple.";
		String s2 = "sim card is Sim card is SIM card, not simple.";
		String result = change2(s2);
		System.out.println(result);
		System.out.println(s1.equals(result));

		result = change2("dsim");
		System.out.println(result);
		System.out.println("dsim".equals(result));

		result = change2("simple");
		System.out.println(result);
		System.out.println("simple".equals(result));

		System.out.println("the uim card".equals(change1("the sim card")));
		System.out.println("uim".equals(change1("sim")));

		result = change2("sim卡");
		System.out.println(result);
		System.out.println("uim卡".equals(result));

		CharSequence csq1 = "the uim card";
		CharSequence csq2 = "the sim card";
		CharSequence re = change1(csq2);
		System.out.println(re);
		System.out.println(csq1.equals(re));

		System.out.println(null == change1(null));
	}
}

interface Omission {
	/**
	 * @param str
	 * @param s1
	 * @param s2
	 * @param from
	 * @return false: if want the 'str' to replace the 's1'(after index 'from')
	 *         with 's2'.
	 */
	public boolean isOmit(String str, String s1, String s2, int from);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章