001 /*
002 * Copyright 2008-2017 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.codehaus.griffon.runtime.core.resources;
017
018 import griffon.core.CallableWithArgs;
019 import griffon.core.resources.NoSuchResourceException;
020 import griffon.core.resources.ResourceResolver;
021
022 import javax.annotation.Nonnull;
023 import javax.annotation.Nullable;
024 import java.beans.PropertyEditor;
025 import java.text.MessageFormat;
026 import java.util.List;
027 import java.util.Locale;
028 import java.util.Map;
029 import java.util.MissingResourceException;
030
031 import static griffon.core.editors.PropertyEditorResolver.findEditor;
032 import static griffon.util.GriffonNameUtils.requireNonBlank;
033 import static java.util.Objects.requireNonNull;
034
035 /**
036 * @author Andres Almiray
037 * @since 2.0.0
038 */
039 public abstract class AbstractResourceResolver implements ResourceResolver {
040 protected static final String ERROR_KEY_BLANK = "Argument 'key' must not be blank";
041 protected static final String ERROR_LOCALE_NULL = "Argument 'locale' must not be null";
042 protected static final String ERROR_ARGS_NULL = "Argument 'args' must not be null";
043 protected static final String ERROR_RESOURCE_NULL = "Argument 'resource' must not be null";
044
045 protected static final Object[] EMPTY_OBJECT_ARGS = new Object[0];
046
047 @Nonnull
048 @Override
049 public Object resolveResource(@Nonnull String key) throws NoSuchResourceException {
050 return resolveResource(key, EMPTY_OBJECT_ARGS, Locale.getDefault());
051 }
052
053 @Nonnull
054 @Override
055 public Object resolveResource(@Nonnull String key, @Nonnull Locale locale) throws NoSuchResourceException {
056 return resolveResource(key, EMPTY_OBJECT_ARGS, locale);
057 }
058
059 @Nonnull
060 @Override
061 public Object resolveResource(@Nonnull String key, @Nonnull Object[] args) throws NoSuchResourceException {
062 return resolveResource(key, args, Locale.getDefault());
063 }
064
065 @Nonnull
066 @Override
067 public Object resolveResource(@Nonnull String key, @Nonnull Object[] args, @Nonnull Locale locale) throws NoSuchResourceException {
068 requireNonBlank(key, ERROR_KEY_BLANK);
069 requireNonNull(args, ERROR_ARGS_NULL);
070 requireNonNull(locale, ERROR_LOCALE_NULL);
071 Object resource = resolveResourceValue(key, locale);
072 Object result = evalResourceWithArguments(resource, args);
073 if (result != null) return result;
074 throw new NoSuchResourceException(key, locale);
075 }
076
077 @Nonnull
078 @Override
079 public Object resolveResource(@Nonnull String key, @Nonnull List<?> args) throws NoSuchResourceException {
080 return resolveResource(key, toObjectArray(args), Locale.getDefault());
081 }
082
083 @Nonnull
084 @Override
085 public Object resolveResource(@Nonnull String key, @Nonnull List<?> args, @Nonnull Locale locale) throws NoSuchResourceException {
086 return resolveResource(key, toObjectArray(args), locale);
087 }
088
089 @Nullable
090 @Override
091 public Object resolveResource(@Nonnull String key, @Nullable Object defaultValue) {
092 return resolveResource(key, EMPTY_OBJECT_ARGS, Locale.getDefault(), defaultValue);
093 }
094
095 @Nullable
096 @Override
097 public Object resolveResource(@Nonnull String key, @Nonnull Locale locale, @Nullable Object defaultValue) {
098 return resolveResource(key, EMPTY_OBJECT_ARGS, locale, defaultValue);
099 }
100
101 @Nullable
102 @Override
103 public Object resolveResource(@Nonnull String key, @Nonnull Object[] args, @Nullable Object defaultValue) {
104 return resolveResource(key, args, Locale.getDefault(), defaultValue);
105 }
106
107 @Nullable
108 @Override
109 public Object resolveResource(@Nonnull String key, @Nonnull Object[] args, @Nonnull Locale locale, @Nullable Object defaultValue) {
110 try {
111 return resolveResource(key, args, locale);
112 } catch (NoSuchResourceException nsre) {
113 return null == defaultValue ? key : defaultValue;
114 }
115 }
116
117 @Nullable
118 @Override
119 public Object resolveResource(@Nonnull String key, @Nonnull List<?> args, @Nullable Object defaultValue) {
120 return resolveResource(key, toObjectArray(args), Locale.getDefault(), defaultValue);
121 }
122
123 @Nullable
124 @Override
125 public Object resolveResource(@Nonnull String key, @Nonnull List<?> args, @Nonnull Locale locale, @Nullable Object defaultValue) {
126 return resolveResource(key, toObjectArray(args), locale, defaultValue);
127 }
128
129 @Nonnull
130 @Override
131 public Object resolveResource(@Nonnull String key, @Nonnull Map<String, Object> args) throws NoSuchResourceException {
132 return resolveResource(key, args, Locale.getDefault());
133 }
134
135 @Nonnull
136 @Override
137 public Object resolveResource(@Nonnull String key, @Nonnull Map<String, Object> args, @Nonnull Locale locale) throws NoSuchResourceException {
138 requireNonBlank(key, ERROR_KEY_BLANK);
139 requireNonNull(args, ERROR_ARGS_NULL);
140 requireNonNull(locale, ERROR_LOCALE_NULL);
141 Object resource = resolveResourceValue(key, locale);
142 Object result = evalResourceWithArguments(resource, args);
143 if (result != null) return result;
144 throw new NoSuchResourceException(key, locale);
145 }
146
147 @Nullable
148 @Override
149 public Object resolveResource(@Nonnull String key, @Nonnull Map<String, Object> args, @Nullable Object defaultValue) {
150 return resolveResource(key, args, Locale.getDefault(), defaultValue);
151 }
152
153 @Nullable
154 @Override
155 public Object resolveResource(@Nonnull String key, @Nonnull Map<String, Object> args, @Nonnull Locale locale, @Nullable Object defaultValue) {
156 try {
157 return resolveResource(key, args, locale);
158 } catch (NoSuchResourceException nsre) {
159 return null == defaultValue ? key : defaultValue;
160 }
161 }
162
163 @Nullable
164 @Override
165 public <T> T resolveResourceConverted(@Nonnull String key, @Nonnull List<?> args, @Nullable T defaultValue, @Nonnull Class<T> type) {
166 return convertValue(resolveResource(key, args, defaultValue), type);
167 }
168
169 @Nullable
170 @Override
171 public <T> T resolveResourceConverted(@Nonnull String key, @Nonnull List<?> args, @Nonnull Locale locale, @Nullable T defaultValue, @Nonnull Class<T> type) {
172 return convertValue(resolveResource(key, args, locale, defaultValue), type);
173 }
174
175 @Nonnull
176 @Override
177 public <T> T resolveResourceConverted(@Nonnull String key, @Nonnull List<?> args, @Nonnull Locale locale, @Nonnull Class<T> type) throws NoSuchResourceException {
178 return convertValue(resolveResource(key, args, locale), type);
179 }
180
181 @Nonnull
182 @Override
183 public <T> T resolveResourceConverted(@Nonnull String key, @Nonnull List<?> args, @Nonnull Class<T> type) throws NoSuchResourceException {
184 return convertValue(resolveResource(key, args), type);
185 }
186
187 @Nullable
188 @Override
189 public <T> T resolveResourceConverted(@Nonnull String key, @Nonnull Map<String, Object> args, @Nullable T defaultValue, @Nonnull Class<T> type) {
190 return convertValue(resolveResource(key, args, defaultValue), type);
191 }
192
193 @Nullable
194 @Override
195 public <T> T resolveResourceConverted(@Nonnull String key, @Nonnull Map<String, Object> args, @Nonnull Locale locale, @Nullable T defaultValue, @Nonnull Class<T> type) {
196 return convertValue(resolveResource(key, args, locale, defaultValue), type);
197 }
198
199 @Nonnull
200 @Override
201 public <T> T resolveResourceConverted(@Nonnull String key, @Nonnull Map<String, Object> args, @Nonnull Locale locale, @Nonnull Class<T> type) throws NoSuchResourceException {
202 return convertValue(resolveResource(key, args, locale), type);
203 }
204
205 @Nonnull
206 @Override
207 public <T> T resolveResourceConverted(@Nonnull String key, @Nonnull Map<String, Object> args, @Nonnull Class<T> type) throws NoSuchResourceException {
208 return convertValue(resolveResource(key, args), type);
209 }
210
211 @Nullable
212 @Override
213 public <T> T resolveResourceConverted(@Nonnull String key, @Nonnull Object[] args, @Nullable T defaultValue, @Nonnull Class<T> type) {
214 return convertValue(resolveResource(key, args, defaultValue), type);
215 }
216
217 @Nullable
218 @Override
219 public <T> T resolveResourceConverted(@Nonnull String key, @Nonnull Object[] args, @Nonnull Locale locale, @Nullable T defaultValue, @Nonnull Class<T> type) {
220 return convertValue(resolveResource(key, args, locale, defaultValue), type);
221 }
222
223 @Nonnull
224 @Override
225 public <T> T resolveResourceConverted(@Nonnull String key, @Nonnull Object[] args, @Nonnull Locale locale, @Nonnull Class<T> type) throws NoSuchResourceException {
226 return convertValue(resolveResource(key, args, locale), type);
227 }
228
229 @Nonnull
230 @Override
231 public <T> T resolveResourceConverted(@Nonnull String key, @Nonnull Object[] args, @Nonnull Class<T> type) throws NoSuchResourceException {
232 return convertValue(resolveResource(key, args), type);
233 }
234
235 @Nullable
236 @Override
237 public <T> T resolveResourceConverted(@Nonnull String key, @Nullable T defaultValue, @Nonnull Class<T> type) {
238 return convertValue(resolveResource(key, defaultValue), type);
239 }
240
241 @Nullable
242 @Override
243 public <T> T resolveResourceConverted(@Nonnull String key, @Nonnull Locale locale, @Nullable T defaultValue, @Nonnull Class<T> type) {
244 return convertValue(resolveResource(key, locale, defaultValue), type);
245 }
246
247 @Nonnull
248 @Override
249 public <T> T resolveResourceConverted(@Nonnull String key, @Nonnull Locale locale, @Nonnull Class<T> type) throws NoSuchResourceException {
250 return convertValue(resolveResource(key, locale), type);
251 }
252
253 @Nonnull
254 @Override
255 public <T> T resolveResourceConverted(@Nonnull String key, @Nonnull Class<T> type) throws NoSuchResourceException {
256 return convertValue(resolveResource(key), type);
257 }
258
259 @Nonnull
260 @Override
261 public Object resolveResourceValue(@Nonnull String key, @Nonnull Locale locale) throws NoSuchResourceException {
262 requireNonBlank(key, ERROR_KEY_BLANK);
263 requireNonNull(locale, ERROR_LOCALE_NULL);
264 try {
265 Object resource = doResolveResourceValue(key, locale);
266 if (resource instanceof CharSequence) {
267 String msg = resource.toString();
268 if (msg.length() >= 4 && msg.startsWith(REF_KEY_START) && msg.endsWith(REF_KEY_END)) {
269 String refKey = msg.substring(2, msg.length() - 1);
270 resource = resolveResourceValue(refKey, locale);
271 }
272 }
273 return resource;
274 } catch (MissingResourceException mre) {
275 throw new NoSuchResourceException(key, locale);
276 }
277 }
278
279 @Nonnull
280 @Override
281 public String formatResource(@Nonnull String resource, @Nonnull List<?> args) {
282 requireNonNull(resource, ERROR_RESOURCE_NULL);
283 requireNonNull(args, ERROR_ARGS_NULL);
284 return formatResource(resource, args.toArray(new Object[args.size()]));
285 }
286
287 @Nonnull
288 @Override
289 public String formatResource(@Nonnull String resource, @Nonnull Object[] args) {
290 requireNonNull(resource, ERROR_RESOURCE_NULL);
291 requireNonNull(args, ERROR_ARGS_NULL);
292 if (args.length == 0) return resource;
293 return MessageFormat.format(resource, args);
294 }
295
296 @Nonnull
297 @Override
298 public String formatResource(@Nonnull String resource, @Nonnull Map<String, Object> args) {
299 requireNonNull(resource, ERROR_RESOURCE_NULL);
300 requireNonNull(args, ERROR_ARGS_NULL);
301 for (Map.Entry<String, Object> variable : args.entrySet()) {
302 String var = variable.getKey();
303 String value = variable.getValue() != null ? variable.getValue().toString() : null;
304 if (value != null) {
305 resource = resource.replace("{:" + var + "}", value);
306 }
307 }
308 return resource;
309 }
310
311 @Nonnull
312 protected abstract Object doResolveResourceValue(@Nonnull String key, @Nonnull Locale locale) throws NoSuchResourceException;
313
314 @Nullable
315 protected Object evalResourceWithArguments(@Nonnull Object resource, @Nonnull Object[] args) {
316 if (resource instanceof CallableWithArgs) {
317 CallableWithArgs<?> callable = (CallableWithArgs<?>) resource;
318 return callable.call(args);
319 } else if (resource instanceof CharSequence) {
320 return formatResource(String.valueOf(resource), args);
321 }
322 return resource;
323 }
324
325 @Nullable
326 protected Object evalResourceWithArguments(@Nonnull Object resource, @Nonnull Map<String, Object> args) {
327 if (resource instanceof CallableWithArgs) {
328 CallableWithArgs<?> callable = (CallableWithArgs<?>) resource;
329 return callable.call(args);
330 } else if (resource instanceof CharSequence) {
331 return formatResource(String.valueOf(resource), args);
332 }
333 return resource;
334 }
335
336 @Nonnull
337 protected Object[] toObjectArray(@Nonnull List<?> args) {
338 if (args.isEmpty()) {
339 return EMPTY_OBJECT_ARGS;
340 }
341 return args.toArray(new Object[args.size()]);
342 }
343
344 @SuppressWarnings("unchecked")
345 protected <T> T convertValue(@Nullable Object value, @Nonnull Class<T> type) {
346 if (value != null) {
347 if (type.isAssignableFrom(value.getClass())) {
348 return (T) value;
349 } else {
350 PropertyEditor editor = findEditor(type);
351 editor.setValue(value);
352 return (T) editor.getValue();
353 }
354 }
355 return null;
356 }
357 }
|