「Java 6 でIVSを比較すると何が起こるか」の記事の誤り(続編)

先日のエントリで「ざっとチェックした限りでは,それらにはまだIVSがらみの変更はないようだが,もし見落としがあれば教えて頂きたい」と書いておいたら,さっそく仕様書に記述はないが,Unicode DatabaseのDUCET(Default Unicode Collation Element Table)はすでに変更されていると指摘して頂いた.どうもありがとう.
DUCETをチェックしなかったのは,「Unicode Collation Algorithm」でjava.text.Collatorクラスとjava.text.RuleBasedCollatorクラスが引用されているように,Mark Davisjava.textパッケージの設計に直接関わっていて,Unicode Databaseがそのままjava.textパッケージに使われていると思っていたからだが,指摘されて実はjava.text.Collatorクラスの実装では,ロケールごとに照合規則を定義して,それをロードしていることを思い出した.
以下が現在のままでも正しく動くコードである.

import java.text.Collator;
import java.text.RuleBasedCollator;

public class VariationSelectorTest {
    public static void main(String[] args) throws Exception {
	String nonIvs = "与太郎";
	String ivs1 = "与\uDB40\uDD00太郎";
	String ivs2 = "与\uDB40\uDD02太郎";
	String nonIvsNext = "与那国";

	RuleBasedCollator c = new RuleBasedCollator(",\uDB40\uDD00 ,\uDB40\uDD02 " + ((RuleBasedCollator)Collator.getInstance()).getRules());
	c.setStrength(Collator.PRIMARY);

	System.out.println("Compare " + ivs1 + " with " + nonIvs + ": " +
			   c.compare("test", "test\t"));
	System.out.println("Compare " + ivs1 + " with " + nonIvs + ": " +
			   c.compare(ivs1, nonIvs));
	System.out.println("Compare " + ivs1 + " with " + ivs2 + ": " +
			   c.compare(ivs1, ivs2));
	System.out.println("Compare " + nonIvs + " with " + nonIvsNext + ": " +
			   c.compare(nonIvs, nonIvsNext));
	System.out.println("Compare " + nonIvsNext + " with " + ivs1 + ": " +
			   c.compare(nonIvsNext, ivs1));
    }
}

このコードのポイントは以下の通りだ.

  • setStrength()で照合の強さを指定している.
  • デフォルトの照合規則に,異体字選択子を無視する(このコードで対象とする最低限の)規則を追加している.

RuleBasedCollatorは正しく動作するが,デフォルトの照合規則に入っていないのが問題なので,それはバグレポートして修正要求するとよいだろう.
なお,面白いことにApache HarmonyのRuleBasedCollatorの実装のコメントには,「If a character is not located in the RuleBasedCollator, the default Unicode Collation Algorithm (UCA) rulebased table is automatically searched as a backup.」と書かれているので,こちらでは正しく動くかもしれない(未確認).
なお,Togetterでは,照合よりも正規化の話が進行していたのだが,現在の正規化方法ではまだ区別されてしまうという理解でよいのだろうか?(確かにテストコードは,そのように動くのだが…)