OSDN Git Service

modify whitespaces.
[mikutoga/TogaGem.git] / src / main / java / jp / sfjp / mikutoga / corelib / I18nText.java
1 /*
2  * internationalization text
3  *
4  * License : The MIT License
5  * Copyright(c) 2010 MikuToga Partners
6  */
7
8 package jp.sfjp.mikutoga.corelib;
9
10 import java.util.ArrayList;
11 import java.util.HashMap;
12 import java.util.List;
13 import java.util.Locale;
14 import java.util.Map;
15 import java.util.Set;
16
17 /**
18  * 多言語のバリアントを持つ文字列情報。
19  * 言語はISO639言語コードで区別される。
20  * <ul>
21  * <li>プライマリ:識別子にはこちらを使う。
22  * 基本はMMD発祥の地に敬意を表して日本語。
23  * <li>グローバル:基本は英語。UCS Basic-Latinオンリーの貧弱な言語環境でも
24  * 読める文字列が望ましい。
25  * <li>その他:必要に応じて好きな言語を。
26  * </ul>
27  */
28 public class I18nText implements CharSequence {
29
30     /** プライマリ言語のロケール。 */
31     public static final Locale LOCALE_PRIMARY = Locale.JAPANESE;
32     /** プライマリ言語のISO639言語コード。 */
33     public static final String CODE639_PRIMARY =
34             LOCALE_PRIMARY.getLanguage();
35
36     /** グローバル言語のロケール。 */
37     public static final Locale LOCALE_GLOBAL = Locale.ENGLISH;
38     /** グローバル言語のISO639言語コード。 */
39     public static final String CODE639_GLOBAL =
40             LOCALE_GLOBAL.getLanguage();
41
42     static{
43         assert "ja".equals(CODE639_PRIMARY);
44         assert "en".equals(CODE639_GLOBAL);
45     }
46
47
48     /**
49      * キーはISO639、値は多言語テキスト。
50      */
51     private final Map<String, String> nameMap =
52             new HashMap<String, String>();
53
54
55     /**
56      * コンストラクタ。
57      */
58     public I18nText(){
59         super();
60         return;
61     }
62
63     /**
64      * プライマリ文字列の登録。
65      * @param seq プライマリ文字列。nullの場合は削除動作
66      */
67     public void setPrimaryText(CharSequence seq){
68         setI18nText(CODE639_PRIMARY, seq);
69         return;
70     }
71
72     /**
73      * グローバル文字列の登録。
74      * @param seq グローバル文字列。nullの場合は削除動作
75      */
76     public void setGlobalText(CharSequence seq){
77         setI18nText(CODE639_GLOBAL, seq);
78         return;
79     }
80
81     /**
82      * 任意のロケールに関連付けられた文字列の登録。
83      * @param locale ロケール
84      * @param seq 文字列。nullの場合は削除動作
85      * @throws NullPointerException ロケール引数がnull
86      */
87     public void setI18nText(Locale locale, CharSequence seq)
88             throws NullPointerException{
89         String code639 = locale.getLanguage();
90         setI18nText(code639, seq);
91         return;
92     }
93
94     /**
95      * 任意の言語コードに関連付けられた文字列の登録。
96      * @param code639 ISO639言語コード
97      * @param seq 文字列。nullの場合は削除動作
98      * @throws NullPointerException 言語コードがnull
99      */
100     public void setI18nText(String code639, CharSequence seq)
101             throws NullPointerException{
102         if(code639 == null) throw new NullPointerException();
103
104         if(seq != null){
105             String text = seq.toString();
106             this.nameMap.put(code639, text);
107         }else{
108             this.nameMap.remove(code639);
109         }
110
111         return;
112     }
113
114     /**
115      * プライマリ文字列を返す。
116      * @return 文字列。見つからなければnullを返す。
117      */
118     public String getPrimaryText(){
119         String result = getI18nText(CODE639_PRIMARY);
120         return result;
121     }
122
123     /**
124      * グローバル文字列を返す。
125      * @return 文字列。見つからなければnullを返す。
126      */
127     public String getGlobalText(){
128         String result = getI18nText(CODE639_GLOBAL);
129         return result;
130     }
131
132     /**
133      * ロケールに応じた文字列を返す。
134      * @param locale ロケール
135      * @return 文字列。見つからなければnullを返す。
136      * @throws NullPointerException 引数がnull
137      */
138     public String getI18nText(Locale locale) throws NullPointerException{
139         String code639 = locale.getLanguage();
140         String result = getI18nText(code639);
141         return result;
142     }
143
144     /**
145      * 言語コードに応じた文字列を返す。
146      * @param code639 ISO639言語コード
147      * @return 文字列。見つからなければnullを返す。
148      * @throws NullPointerException 引数がnull
149      */
150     public String getI18nText(String code639) throws NullPointerException{
151         if(code639 == null) throw new NullPointerException();
152         String result = this.nameMap.get(code639);
153         return result;
154     }
155
156     /**
157      * プライマリ文字列を返す。
158      *
159      * <p>見つからなければグローバル文字列を返す。
160      * それでも見つからなければ長さ0の空文字列を返す。
161      *
162      * <p>※決してnullは返さない。
163      *
164      * @return 文字列
165      */
166     public String getText(){
167         String result;
168
169         result = getPrimaryText();
170
171         if(result == null){
172             result = getGlobalText();
173         }
174
175         if(result == null){
176             result = "";
177         }
178
179         return result;
180     }
181
182     /**
183      * 実行環境のデフォルトロケールに応じた文字列を返す。
184      *
185      * <p>見つからなければグローバル文字列、プライマリ文字列の順に返す。
186      * それでも見つからなければ適当な言語コードの文字列を返す。
187      * それでも見つからなければ長さ0の空文字列を返す。
188      *
189      * <p>デフォルトロケールの確認はその都度行われる。
190      *
191      * <p>※決してnullは返さない。
192      *
193      * @return 文字列
194      */
195     public String getLocalizedText(){
196         Locale locale = Locale.getDefault();
197         String langCode = locale.getLanguage();
198
199         String result;
200
201         result = this.nameMap.get(langCode);
202
203         if(result == null){
204             result = this.nameMap.get(CODE639_GLOBAL);
205         }
206
207         if(result == null){
208             result = this.nameMap.get(CODE639_PRIMARY);
209         }
210
211         if(result == null){
212             Set<String> langSet = this.nameMap.keySet();
213             for(String lang : langSet){
214                 result = this.nameMap.get(lang);
215                 if(result != null) break;
216             }
217         }
218
219         if(result == null){
220             result = "";
221         }
222
223         return result;
224     }
225
226     /**
227      * 全言語の文字列を削除する。
228      */
229     public void clearI18nText(){
230         this.nameMap.clear();
231         return;
232     }
233
234     /**
235      * 登録済みの全ISO639言語コードリストを返す。
236      * 優先度はプライマリ、グローバル、その他の順。
237      * @return 全ISO639言語コード
238      */
239     public List<String> lang639CodeList(){
240         Set<String> set = this.nameMap.keySet();
241         List<String> result = new ArrayList<String>(set.size());
242
243         for(String lang : set){
244             if(lang.equals(CODE639_PRIMARY)) result.add(lang);
245         }
246
247         for(String lang : set){
248             if(lang.equals(CODE639_GLOBAL)) result.add(lang);
249         }
250
251         for(String lang : set){
252             if(lang.equals(CODE639_PRIMARY)) continue;
253             if(lang.equals(CODE639_GLOBAL)) continue;
254             result.add(lang);
255         }
256
257         return result;
258     }
259
260     /**
261      * プライマリ文字列が登録されているか判定する。
262      * @return 登録されていればtrue
263      */
264     public boolean hasPrimaryText(){
265         boolean result = this.nameMap.containsKey(CODE639_PRIMARY);
266         return result;
267     }
268
269     /**
270      * グローバル文字列が登録されているか判定する。
271      * @return 登録されていればtrue
272      */
273     public boolean hasGlobalText(){
274         boolean result = this.nameMap.containsKey(CODE639_GLOBAL);
275         return result;
276     }
277
278     /**
279      * {@inheritDoc}
280      * {@link #getText()}仕様に準ずる。
281      * @param index {@inheritDoc}
282      * @return {@inheritDoc}
283      */
284     @Override
285     public char charAt(int index){
286         String text = getText();
287         char result = text.charAt(index);
288         return result;
289     }
290
291     /**
292      * {@inheritDoc}
293      * {@link #getText()}仕様に準ずる。
294      * @return {@inheritDoc}
295      */
296     @Override
297     public int length(){
298         String text = getText();
299         int result = text.length();
300         return result;
301     }
302
303     /**
304      * {@inheritDoc}
305      * {@link #getText()}仕様に準ずる。
306      * @param start {@inheritDoc}
307      * @param end {@inheritDoc}
308      * @return {@inheritDoc}
309      */
310     @Override
311     public CharSequence subSequence(int start, int end){
312         String text = getText();
313         CharSequence result = text.subSequence(start, end);
314         return result;
315     }
316
317     /**
318      * {@inheritDoc}
319      * {@link #getText()}仕様に準ずる。
320      * @return {@inheritDoc}
321      */
322     @Override
323     public String toString(){
324         return getText();
325     }
326
327 }