1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package ch.elca.el4j.services.i18n;
18
19 import java.io.IOException;
20 import java.io.InputStreamReader;
21 import java.io.Reader;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.Locale;
26 import java.util.Map;
27
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30 import org.springframework.context.MessageSource;
31 import org.springframework.context.MessageSourceResolvable;
32 import org.springframework.context.NoSuchMessageException;
33 import org.springframework.core.io.ClassPathResource;
34 import org.springframework.core.io.Resource;
35 import org.springframework.util.StringUtils;
36
37 import ch.elca.el4j.util.codingsupport.Reject;
38
39
40
41
42
43
44
45
46 public class RewritingMessageSource implements MessageSource {
47
48 protected String[] m_basenames;
49
50
51 protected MessageRewriter.Rule[] m_additionalRules;
52
53
54 protected Map<Locale, MessageRewriter> m_rewriters
55 = new HashMap<Locale, MessageRewriter>();
56
57
58 protected static final Logger s_logger
59 = LoggerFactory.getLogger(RewritingMessageSource.class);
60
61
62
63
64
65 public void setBasenames(String... basenames) {
66 m_basenames = basenames;
67 }
68
69
70
71
72 public void setAdditionalRules(MessageRewriter.Rule... rules) {
73 m_additionalRules = rules;
74 }
75
76
77
78
79
80
81
82
83 protected String assembleFileName(String... parts) {
84 StringBuilder r = new StringBuilder();
85 for (String p : parts) {
86 if (StringUtils.hasText(p)) {
87 r.append(p).append('_');
88 }
89 }
90 return r.substring(0, r.length() - 1);
91 }
92
93
94
95
96
97
98
99
100 protected MessageRewriter createRewriter(Locale loc) {
101 ArrayList<Reader> ruleSources = new ArrayList<Reader>();
102 for (String bn : m_basenames) {
103 String filename = assembleFileName(
104 bn,
105 loc.getLanguage(),
106 loc.getCountry(),
107 loc.getVariant()
108 );
109
110 String fn = filename;
111 do {
112 Resource r = new ClassPathResource(
113 fn.replace('.', '/') + ".properties"
114 );
115 try {
116 Reader reader = new InputStreamReader(r.getInputStream());
117 if (s_logger.isDebugEnabled()) {
118 s_logger.debug("found: " + r);
119 }
120 ruleSources.add(reader);
121 } catch (IOException e) {
122
123 }
124
125 int i = fn.lastIndexOf('_');
126 if (i == -1) { break; }
127 fn = fn.substring(0, i);
128 } while (true);
129 }
130 Collections.reverse(ruleSources);
131 MessageRewriter rewriter = new MessageRewriter(ruleSources);
132 rewriter.add(m_additionalRules);
133 return rewriter;
134 }
135
136
137
138
139
140
141
142
143 private MessageRewriter getRewriter(Locale loc) {
144 MessageRewriter r = m_rewriters.get(loc);
145 if (r == null) {
146 r = createRewriter(loc);
147 m_rewriters.put(loc, r);
148 }
149 return r;
150 }
151
152
153 public String getMessage(MessageSourceResolvable resolvable, Locale locale)
154 throws NoSuchMessageException {
155
156 NoSuchMessageException ex = null;
157 for (String key : resolvable.getCodes()) {
158 try {
159 return getMessage(key, resolvable.getArguments(), locale);
160 } catch (NoSuchMessageException e) {
161 s_logger.info(e.toString());
162 if (ex == null) {
163 ex = e;
164 }
165 }
166 }
167 Reject.ifNull(
168 ex, "a non-empty list of codes is required to resolve a message"
169 );
170 if (resolvable.getDefaultMessage() != null) {
171 return resolvable.getDefaultMessage();
172 } else {
173 throw ex;
174 }
175 }
176
177
178 public String getMessage(String code, Object[] args, Locale locale)
179 throws NoSuchMessageException {
180
181
182
183
184
185
186 Object[] resolvedArgs;
187 if (args == null) {
188 resolvedArgs = null;
189 } else {
190 resolvedArgs = new Object[args.length];
191 for (int i = 0; i < args.length; i++) {
192 if (args[i] instanceof MessageSourceResolvable) {
193 resolvedArgs[i] = getMessage(
194 (MessageSourceResolvable) args[i], locale);
195 } else {
196 resolvedArgs[i] = args[i];
197 }
198 }
199 }
200
201 return getRewriter(locale).resolve(code, resolvedArgs);
202 }
203
204
205 public String getMessage(String code, Object[] args,
206 String defaultMessage, Locale locale) {
207
208 try {
209 return getMessage(code, args, locale);
210 } catch (NoSuchMessageException e) {
211 return defaultMessage;
212 }
213 }
214 }