View Javadoc

1   /*
2    * @(#) $Id: UnicodeCorrector.java,v 1.1.2.1 2005/01/18 07:20:36 otsuka Exp $
3    * $Revision: 1.1.2.1 $
4    * Copyright (c) 2000 Shin Kinoshita All Rights Reserved.
5    */
6   package com.ozacc.mail.fetch.impl.sk_jp.io;
7   
8   import java.io.UnsupportedEncodingException;
9   import java.util.HashMap;
10  import java.util.Map;
11  
12  /***
13   * UnicodeCorrector.
14   * <p>
15   * CorrectOutputStreamWriterで用いられる文字列バッファ補正クラスです。<br>
16   * 出力エンコーディングによって補正すべき文字コードが異なるので、
17   * 実際の補正処理はサブクラスで行います。<br>
18   *
19   * 対応しているのは以下のコンバータ名です。
20   * </p>
21   * <UL>
22   * <LI>ISO2022JP
23   * <LI>ISO-2022-JP
24   * <LI>EUC-JP
25   * <LI>EUCJIS
26   * <LI>SJIS
27   * <LI>Shift_JIS
28   * <LI>MS932
29   * <LI>Windows-31J
30   * </UL>
31   * @author Shin
32   * @version $Revision: 1.1.2.1 $ $Date: 2005/01/18 07:20:36 $
33   */
34  public abstract class UnicodeCorrector {
35      private static final Map correctorMap = new HashMap();
36      static {
37          // x-sjis-cp932等でおかしく変換されたUnicodeを他のエンコーディングで
38          // 出力する場合です
39          correctorMap.put("iso2022jp", FromCP932Corrector.class);
40          correctorMap.put("iso-2022-jp", FromCP932Corrector.class);
41          correctorMap.put("euc-jp", FromCP932Corrector.class);
42          correctorMap.put("eucjis", FromCP932Corrector.class);
43          // 同じ"SJIS"でもSunとMS-VMでは異なります。
44          // Sun-JDK1.1はSJISはx-sjis-jdk-1.1.7で、MS-VMはx-sjis-cp932です。
45          // しかし、MS-JDK中のクラスライブラリだけはx-sjis-jdk-1.1.7相当になるので
46          // 困ったものです。(ファイル書き出し等のときのみおかしくなる)
47          // これはWindowsネイティブな変換表で生成されたUnicodeを
48          // x-sjis-jdk-1.1.7で出力するためのものです。
49          correctorMap.put("sjis", FromCP932Corrector.class);
50          correctorMap.put("shift_jis", FromCP932Corrector.class);
51          // MS-VMでファイル出力を行う場合に限り、こちらでなければなりません。
52          //      correctorMap.put("sjis", ToCP932Corrector.class);
53          // JDK1.2からはWindowsのデフォルトが"MS932"(x-sjis-cp932相当)となりました。
54          // これで、他のエンコーディングで変換された(正しい)Unicodeが"ms932"
55          // での出力時におかしくなってしまいます。
56          // これを補正します。
57          correctorMap.put("ms932", ToCP932Corrector.class);
58          correctorMap.put("windows-31j", ToCP932Corrector.class);
59      }
60  
61      /***
62       * Create an UnicodeCorrector that uses
63       * the named character encoding.
64       * @param  enc  Name of the encoding to be used
65       * @exception  UnsupportedEncodingException
66       *             If the named encoding is not supported
67       */
68      public static UnicodeCorrector getInstance(String enc)
69              throws UnsupportedEncodingException {
70          Class correctorClass = (Class)correctorMap.get(enc.toLowerCase());
71          if (correctorClass == null) {
72              throw new UnsupportedEncodingException(enc);
73          }
74          try {
75              return (UnicodeCorrector)correctorClass.newInstance();
76          } catch (Exception e) {
77              throw new UnsupportedEncodingException(
78                      correctorClass + " cannot get newInstance.\n" + e);
79          }
80      }
81  
82      /***
83       * Unicode文字配列の補正を行います。
84       * <p>
85       * 特定の文字を特定エンコーディングで出力しようとした際の
86       * sun.ioコンバータでは正常に変換できない部分を補正します。
87       * </p>
88       * @param  cbuf  Buffer of characters
89       * @param  off   Offset from which to start writing characters
90       * @param  len   Number of characters to write
91       * @return Result that corrected.
92       *         Note:Return array is different from <code>cbuf</code>
93       *              in case of different result size.
94       */
95      public char[] correct(char cbuf[], int off, int len) {
96          StringBuffer buf = new StringBuffer();
97          for (int i = off; i < len; i++) {
98              buf.append(correct(cbuf[i]));
99          }
100         return new String(buf).toCharArray();
101     }
102 
103     public String correct(String s) {
104         StringBuffer buf = new StringBuffer();
105         for (int i = 0; i < s.length(); i++) {
106             buf.append(correct(s.charAt(i)));
107         }
108         return new String(buf);
109     }
110 
111     // 性能的にこれをabstractにするのはためらったが・・・
112     public abstract char correct(char c);
113 
114     /***
115      * 新しいUnicodeCorrectorを追加します。
116      * <p>
117      * このソースコードを変えずに、動的に新たな出力エンコーディングに
118      * 対応したUnicodeCorrectorを登録したい場合に用います。
119      * </p>
120      * @param enc 対応するエンコーディング名
121      * @param correctorClass UnicodeCorrectorサブクラスのClassオブジェクト
122      */
123     public static void addCorrector(String enc, Class correctorClass) {
124         if (!correctorClass.isInstance(UnicodeCorrector.class)) {
125             throw new IllegalArgumentException(
126                     "Corrector is not UnicodeCorrector type.");
127         }
128         correctorMap.put(enc, correctorClass);
129     }
130 }