CharReplacer.java
package com.github.mygreen.supercsv.cellprocessor.conversion;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.github.mygreen.supercsv.util.ArgUtils;
import com.github.mygreen.supercsv.util.Utils;
/**
* 文字を置換するクラス
*
* @version 2.0.1
* @since 2.0
* @author T.TSUCHIE
*
*/
public class CharReplacer {
/** 置換元が1文字の場合 */
private final Map<Character, String> singles = new HashMap<>();
/** 置換元が2文字以上の文字の場合 */
private final List<MultiChar> multi = new ArrayList<>();
/**
* 置換元の文字が2文字以上の場合
*
*/
private static class MultiChar {
private final String word;
private final String replacement;
private MultiChar(final String word, final String replacement) {
this.word = word;
this.replacement = replacement;
}
}
/**
* 置換対象の文字を登録する。
* @param word 置換対象の文字
* @param replacement 置換後の文字
* @throws IllegalArgumentException word is empty.
* @throws NullPointerException replacement is null.
*/
public void register(final String word, final String replacement) {
ArgUtils.notEmpty(word, "word");
ArgUtils.notNull(replacement, "replacement");
if(word.length() == 1) {
singles.computeIfAbsent(word.charAt(0), key -> replacement);
} else {
multi.add(new MultiChar(word, replacement));
}
}
/**
* 登録後に置換文字の整理を行うため、必ず実行すること。
*/
public void ready() {
// 複数の文字の場合、重複を排除する。
final Set<String> duplicatedWords = new HashSet<>();
final List<MultiChar> newMulti = new ArrayList<>();
for(MultiChar word : multi) {
if(duplicatedWords.contains(word.word)) {
continue;
}
duplicatedWords.add(word.word);
newMulti.add(word);
}
// 複数の文字の場合、文字長が長い順に並び替える。
Collections.sort(newMulti, new Comparator<MultiChar>() {
@Override
public int compare(final MultiChar o1, final MultiChar o2) {
final int length1 = o1.word.length();
final int length2 = o2.word.length();
if(length1 < length2) {
return 1;
} else if(length1 > length2) {
return -1;
} else {
return o1.word.compareTo(o2.word);
}
}
});
multi.clear();
multi.addAll(newMulti);
}
/**
* 登録された文字を元に置換する。
* @param text 置換対象の文字
* @return 置換した文字。置換対象の文字がnullまたは空文字の場合、置換しない。
*/
public String replace(final String text) {
if(Utils.isEmpty(text)) {
return text;
}
final int length = text.length();
StringBuilder replaced = new StringBuilder();
int index = 0;
while(index < length) {
int multiIndex = replaceMulti(text, index, replaced);
if(multiIndex > index) {
index = multiIndex;
continue;
}
int singleIndex = replaceSingle(text, index, replaced);
if(singleIndex > index) {
index = singleIndex;
continue;
}
// 置換できるものがない場合
replaced.append(text.charAt(index));
index++;
}
return replaced.toString();
}
private int replaceSingle(final String source, final int index, final StringBuilder replaced) {
final char c = source.charAt(index);
if(singles.containsKey(c)) {
replaced.append(singles.get(c));
return index + 1;
}
return index;
}
private int replaceMulti(final String source, final int index, final StringBuilder replaced) {
for(MultiChar word : multi) {
if(source.indexOf(word.word, index) == index) {
replaced.append(word.replacement);
return index + word.word.length();
}
}
return index;
}
}