AbstractResourceResolver.java
001 /*
002  * Copyright 2008-2016 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 keythrows 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 localethrows NoSuchResourceException {
056         return resolveResource(key, EMPTY_OBJECT_ARGS, locale);
057     }
058 
059     @Nonnull
060     @Override
061     public Object resolveResource(@Nonnull String key, @Nonnull Object[] argsthrows 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 localethrows 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 != nullreturn result;
074         throw new NoSuchResourceException(key, locale);
075     }
076 
077     @Nonnull
078     @Override
079     public Object resolveResource(@Nonnull String key, @Nonnull List<?> argsthrows 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 localethrows 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> argsthrows 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 localethrows 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 != nullreturn 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> typethrows 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> typethrows 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> typethrows 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> typethrows 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> typethrows 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> typethrows 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> typethrows 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> typethrows NoSuchResourceException {
256         return convertValue(resolveResource(key), type);
257     }
258 
259     @Nonnull
260     @Override
261     public Object resolveResourceValue(@Nonnull String key, @Nonnull Locale localethrows 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() >= && 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 == 0return 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 localethrows 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 (Tvalue;
349             else {
350                 PropertyEditor editor = findEditor(type);
351                 editor.setValue(value);
352                 return (Teditor.getValue();
353             }
354         }
355         return null;
356     }
357 }