1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.jelly.tags.fmt;
17
18 import org.apache.commons.jelly.JellyContext;
19 import org.apache.commons.jelly.JellyTagException;
20 import org.apache.commons.jelly.XMLOutput;
21 import org.apache.commons.jelly.Tag;
22 import org.apache.commons.jelly.TagSupport;
23 import org.apache.commons.jelly.expression.Expression;
24 import java.util.Locale;
25
26 /***
27 * Support for tag handlers for <setLocale>, the locale setting
28 * tag in JSTL.
29 * @author <a href="mailto:willievu@yahoo.com">Willie Vu</a>
30 * @version 1.2
31 *
32 * @task decide how to implement setResponseLocale
33 */
34 public class SetLocaleTag extends TagSupport {
35
36 private static final char HYPHEN = '-';
37 private static final char UNDERSCORE = '_';
38
39 private Expression value;
40
41 private Expression variant;
42
43 private String scope;
44
45 /*** Creates a new instance of SetLocaleTag */
46 public SetLocaleTag() {
47 }
48
49 /***
50 * Evaluates this tag after all the tags properties have been initialized.
51 *
52 */
53 public void doTag(XMLOutput output) throws JellyTagException {
54 Locale locale = null;
55
56 Object valueInput = null;
57 if (this.value != null) {
58 valueInput = this.value.evaluate(context);
59 }
60 Object variantInput = null;
61 if (this.variant != null) {
62 variantInput = this.variant.evaluate(context);
63 }
64
65 if (valueInput == null) {
66 locale = Locale.getDefault();
67 } else if (valueInput instanceof String) {
68 if (((String) valueInput).trim().equals("")) {
69 locale = Locale.getDefault();
70 } else {
71 locale = parseLocale((String) valueInput, (String) variantInput);
72 }
73 } else {
74 locale = (Locale) valueInput;
75 }
76
77 if (scope != null) {
78 context.setVariable(Config.FMT_LOCALE, scope, locale);
79 }
80 else {
81 context.setVariable(Config.FMT_LOCALE, locale);
82 }
83
84 }
85
86 public void setValue(Expression value) {
87 this.value = value;
88 }
89
90 public void setVariant(Expression variant) {
91 this.variant = variant;
92 }
93
94 public void setScope(String scope) {
95 this.scope = scope;
96 }
97
98 //**********************************************************************
99 // Public utility methods
100
101 /**
102 * See parseLocale(String, String) for details.
103 */
104 public static Locale parseLocale(String locale) {
105 return parseLocale(locale, null);
106 }
107
108 /***
109 * Parses the given locale string into its language and (optionally)
110 * country components, and returns the corresponding
111 * <tt>java.util.Locale</tt> object.
112 *
113 * If the given locale string is null or empty, the runtime's default
114 * locale is returned.
115 *
116 * @param locale the locale string to parse
117 * @param variant the variant
118 *
119 * @return <tt>java.util.Locale</tt> object corresponding to the given
120 * locale string, or the runtime's default locale if the locale string is
121 * null or empty
122 *
123 * @throws IllegalArgumentException if the given locale does not have a
124 * language component or has an empty country component
125 */
126 public static Locale parseLocale(String locale, String variant) {
127
128 Locale ret = null;
129 String language = locale;
130 String country = null;
131 int index = -1;
132
133 if (((index = locale.indexOf(HYPHEN)) > -1)
134 || ((index = locale.indexOf(UNDERSCORE)) > -1)) {
135 language = locale.substring(0, index);
136 country = locale.substring(index+1);
137 }
138
139 if ((language == null) || (language.length() == 0)) {
140 throw new IllegalArgumentException("Missing language");
141 }
142
143 if (country == null) {
144 if (variant != null)
145 ret = new Locale(language, "", variant);
146 else
147 ret = new Locale(language, "");
148 } else if (country.length() > 0) {
149 if (variant != null)
150 ret = new Locale(language, country, variant);
151 else
152 ret = new Locale(language, country);
153 } else {
154 throw new IllegalArgumentException("Missing country");
155 }
156
157 return ret;
158 }
159
160 /***
161 * Returns the locale specified by the named scoped attribute or context
162 * configuration parameter.
163 *
164 * <p> The named scoped attribute is searched in the page, request,
165 * session (if valid), and application scope(s) (in this order). If no such
166 * attribute exists in any of the scopes, the locale is taken from the
167 * named context configuration parameter.
168 *
169 * @param jc the page in which to search for the named scoped
170 * attribute or context configuration parameter
171 * @param name the name of the scoped attribute or context configuration
172 * parameter
173 *
174 * @return the locale specified by the named scoped attribute or context
175 * configuration parameter, or <tt>null</tt> if no scoped attribute or
176 * configuration parameter with the given name exists
177 */
178 static Locale getLocale(JellyContext jc, String name) {
179 Locale loc = null;
180
181 Object obj = jc.getVariable(name);
182 if (obj != null) {
183 if (obj instanceof Locale) {
184 loc = (Locale) obj;
185 } else {
186 loc = parseLocale((String) obj);
187 }
188 }
189
190 return loc;
191 }
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208 static Locale getFormattingLocale(JellyContext jc,
209 Tag fromTag,
210 boolean format,
211 Locale[] avail) {
212
213 LocalizationContext locCtxt = null;
214
215
216 Tag parent = findAncestorWithClass(fromTag, BundleTag.class);
217 if (parent != null) {
218
219
220
221
222 locCtxt = ((BundleTag) parent).getLocalizationContext();
223 if (locCtxt.getLocale() != null) {
224 if (format) {
225
226 }
227 return locCtxt.getLocale();
228 }
229 }
230
231
232 if ((locCtxt = BundleTag.getLocalizationContext(jc)) != null) {
233 if (locCtxt.getLocale() != null) {
234 if (format) {
235
236 }
237 return locCtxt.getLocale();
238 }
239 }
240
241
242
243
244
245
246 Locale match = null;
247 Locale pref = getLocale(jc, Config.FMT_LOCALE);
248 if (pref != null) {
249
250 match = findFormattingMatch(pref, avail);
251 }
252 if (match == null) {
253
254 pref = getLocale(jc, Config.FMT_FALLBACK_LOCALE);
255 if (pref != null) {
256 match = findFormattingMatch(pref, avail);
257 }
258 }
259 if (format && (match != null)) {
260
261 }
262
263 return match;
264 }
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282 private static Locale findFormattingMatch(Locale pref, Locale[] avail) {
283 Locale match = null;
284
285 for (int i=0; i<avail.length; i++) {
286 if (pref.equals(avail[i])) {
287
288 match = avail[i];
289 break;
290 } else {
291 if (pref.getLanguage().equals(avail[i].getLanguage())
292 && ("".equals(avail[i].getCountry()))) {
293
294 if (match == null) {
295 match = avail[i];
296 }
297 }
298 }
299 }
300
301 return match;
302 }
303 }