OSDN Git Service

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