1 package com.github.mygreen.cellformatter.lang;
2
3 import java.io.IOException;
4 import java.io.InputStreamReader;
5 import java.util.ArrayList;
6 import java.util.Collections;
7 import java.util.Enumeration;
8 import java.util.List;
9 import java.util.Locale;
10 import java.util.Map;
11 import java.util.Properties;
12 import java.util.ResourceBundle;
13 import java.util.concurrent.ConcurrentHashMap;
14
15
16
17
18
19
20
21
22
23
24 public class MessageResolver {
25
26
27
28
29
30 private final String resourceName;
31
32
33
34
35 private final boolean allowedNoDefault;
36
37
38
39
40 private final boolean appendUserResource;
41
42
43
44
45 private MessageResource defaultResource;
46
47
48
49
50
51 private Map<Locale, MessageResource> resources;
52
53
54
55
56
57 public MessageResolver(final String resourceName) {
58 this(resourceName, false, false);
59
60 }
61
62
63
64
65
66
67
68
69 public MessageResolver(final String resourceName, final boolean allowedNoDefault, final boolean appendUserResouce) {
70 this.resourceName = resourceName;
71 this.allowedNoDefault = allowedNoDefault;
72 this.appendUserResource = appendUserResouce;
73 this.defaultResource = loadDefaultResource(allowedNoDefault, appendUserResouce);
74 this.resources = new ConcurrentHashMap<>();
75 }
76
77 private String getPropertyPath() {
78
79 final String baseName = getResourceName().replaceAll("\\.", "/");
80 String path = new StringBuilder()
81 .append("/")
82 .append(baseName)
83 .append(".properties")
84 .toString();
85
86 return path;
87 }
88
89 private String[] getPropertyPath(final Locale locale) {
90
91 final List<String> list = new ArrayList<>();
92
93 final String baseName = getResourceName().replaceAll("\\.", "/");
94 if(Utils.isNotEmpty(locale.getLanguage())) {
95 String path = new StringBuilder()
96 .append("/")
97 .append(baseName)
98 .append("_").append(locale.getLanguage())
99 .append(".properties")
100 .toString();
101 list.add(path);
102 }
103
104 if(Utils.isNotEmpty(locale.getLanguage()) && Utils.isNotEmpty(locale.getCountry())) {
105 String path = new StringBuilder()
106 .append("/")
107 .append(baseName)
108 .append("_").append(locale.getLanguage())
109 .append("_").append(locale.getCountry())
110 .append(".properties")
111 .toString();
112 list.add(path);
113 }
114
115 Collections.reverse(list);
116
117 return list.toArray(new String[list.size()]);
118 }
119
120
121
122
123
124
125
126
127
128 private MessageResource loadDefaultResource(final boolean allowedNoDefault, final boolean appendUserResource) {
129
130 final String path = getPropertyPath();
131 Properties props = new Properties();
132 try {
133 props.load(new InputStreamReader(MessageResolver.class.getResourceAsStream(path), "UTF-8"));
134 } catch (NullPointerException | IOException e) {
135 if(allowedNoDefault) {
136 return MessageResource.NULL_OBJECT;
137 } else {
138 throw new RuntimeException("fail default properties. :" + path, e);
139 }
140 }
141
142 final MessageResourceg/MessageResource.html#MessageResource">MessageResource resource = new MessageResource();
143
144 final Enumeration<?> keys = props.propertyNames();
145 while(keys.hasMoreElements()) {
146 String key = (String) keys.nextElement();
147 String value = props.getProperty(key);
148 resource.addMessage(key, value);
149 }
150
151
152 if(appendUserResource) {
153 resource.addMessage(loadUserResource(path));
154 }
155
156 return resource;
157
158 }
159
160
161
162
163
164
165
166 MessageResource loadResource(final Locale locale) {
167
168 if(locale == null) {
169 return defaultResource;
170 }
171
172 if(resources.containsKey(locale)) {
173 return resources.get(locale);
174 }
175
176 MessageResource localeResource = null;
177 synchronized (resources) {
178 for(String path : getPropertyPath(locale)) {
179
180 try {
181 final Properties props = new Properties();
182 props.load(new InputStreamReader(MessageResolver.class.getResourceAsStream(path), "UTF-8"));
183
184 localeResource = new MessageResource();
185
186 final Enumeration<?> keys = props.propertyNames();
187 while(keys.hasMoreElements()) {
188 String key = (String) keys.nextElement();
189 String value = props.getProperty(key);
190 localeResource.addMessage(key, value);
191 }
192
193
194 if(appendUserResource) {
195 localeResource.addMessage(loadUserResource(path));
196 }
197
198 break;
199
200 } catch(NullPointerException | IOException e) {
201 continue;
202 }
203
204 }
205
206 if(localeResource == null) {
207
208 localeResource = defaultResource;
209 }
210
211 resources.put(locale, localeResource);
212 }
213
214 return localeResource;
215
216 }
217
218
219
220
221
222
223 private MessageResource loadUserResource(final String basePath) {
224
225
226 final int index = basePath.lastIndexOf("/");
227 if(index <= 0) {
228 return MessageResource.NULL_OBJECT;
229 }
230
231 final String userPropertyPath = "/" + basePath.substring(index+1);
232 try {
233 Properties props = new Properties();
234 props.load(new InputStreamReader(MessageResolver.class.getResourceAsStream(userPropertyPath), "UTF-8"));
235
236 final MessageResourceg/MessageResource.html#MessageResource">MessageResource resource = new MessageResource();
237 final Enumeration<?> keys = props.propertyNames();
238 while(keys.hasMoreElements()) {
239 String key = (String) keys.nextElement();
240 String value = props.getProperty(key);
241 resource.addMessage(key, value);
242 }
243
244 return resource;
245
246 } catch(NullPointerException | IOException e) {
247 return MessageResource.NULL_OBJECT;
248 }
249
250 }
251
252
253
254
255
256 public String getResourceName() {
257 return resourceName;
258 }
259
260
261
262
263
264 public boolean isAllowedNoDefault() {
265 return allowedNoDefault;
266 }
267
268
269
270
271
272
273 public String getMessage(final String key) {
274 return defaultResource.getMessage(key);
275 }
276
277
278
279
280
281
282
283
284 public String getMessage(final MSLocale locale, final String key) {
285 if(locale == null) {
286 return loadResource(null).getMessage(key);
287
288 } else {
289 return loadResource(locale.getLocale()).getMessage(key);
290 }
291 }
292
293
294
295
296
297
298
299
300 public String getMessage(final MSLocale locale, final String key, final String defaultValue) {
301 String message = getMessage(locale, key);
302 return message == null ? defaultValue : message;
303 }
304
305
306
307
308
309
310
311
312 public String getMessage(final Locale locale, final String key) {
313 return loadResource(locale).getMessage(key);
314 }
315
316
317
318
319
320
321
322
323 public String getMessage(final Locale locale, final String key, final String defaultValue) {
324 String message = getMessage(locale, key);
325 return message == null ? defaultValue : message;
326 }
327
328
329
330
331
332
333
334
335
336
337
338 public String getMessage(final MSLocale formatLocale, Locale runtimeLocale, final String key) {
339
340 if(formatLocale != null) {
341 return getMessage(formatLocale, key);
342 } else {
343 return getMessage(runtimeLocale, key);
344 }
345
346 }
347
348
349
350
351
352
353
354
355
356
357
358
359 public String getMessage(final MSLocale formatLocale, Locale runtimeLocale, final String key, final String defaultValue) {
360
361 if(formatLocale != null) {
362 return getMessage(formatLocale, key, defaultValue);
363 } else {
364 return getMessage(runtimeLocale, key, defaultValue);
365 }
366
367 }
368
369
370 }