AbstractResourceResolver.java
001 /*
002  * Copyright 2008-2014 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.text.MessageFormat;
025 import java.util.List;
026 import java.util.Locale;
027 import java.util.Map;
028 import java.util.MissingResourceException;
029 
030 import static griffon.util.GriffonNameUtils.requireNonBlank;
031 import static java.util.Objects.requireNonNull;
032 
033 /**
034  @author Andres Almiray
035  @since 2.0.0
036  */
037 public abstract class AbstractResourceResolver implements ResourceResolver {
038     protected static final String ERROR_KEY_BLANK = "Argument 'key' must not be blank";
039     protected static final String ERROR_LOCALE_NULL = "Argument 'locale' must not be null";
040     protected static final String ERROR_ARGS_NULL = "Argument 'args' must not be null";
041     protected static final String ERROR_RESOURCE_BLANK = "Argument 'resource' must not be blank";
042 
043     protected static final Object[] EMPTY_OBJECT_ARGS = new Object[0];
044 
045     @Nonnull
046     @Override
047     public Object resolveResource(@Nonnull String keythrows NoSuchResourceException {
048         return resolveResource(key, EMPTY_OBJECT_ARGS, Locale.getDefault());
049     }
050 
051     @Nonnull
052     @Override
053     public Object resolveResource(@Nonnull String key, @Nonnull Locale localethrows NoSuchResourceException {
054         return resolveResource(key, EMPTY_OBJECT_ARGS, locale);
055     }
056 
057     @Nonnull
058     @Override
059     public Object resolveResource(@Nonnull String key, @Nonnull Object[] argsthrows NoSuchResourceException {
060         return resolveResource(key, args, Locale.getDefault());
061     }
062 
063     @Nonnull
064     @Override
065     public Object resolveResource(@Nonnull String key, @Nonnull Object[] args, @Nonnull Locale localethrows NoSuchResourceException {
066         requireNonBlank(key, ERROR_KEY_BLANK);
067         requireNonNull(args, ERROR_ARGS_NULL);
068         requireNonNull(locale, ERROR_LOCALE_NULL);
069         Object resource = resolveResourceValue(key, locale);
070         Object result = evalResourceWithArguments(resource, args);
071         if (result != nullreturn result;
072         throw new NoSuchResourceException(key, locale);
073     }
074 
075     @Nonnull
076     @Override
077     public Object resolveResource(@Nonnull String key, @Nonnull List<?> argsthrows NoSuchResourceException {
078         return resolveResource(key, toObjectArray(args), Locale.getDefault());
079     }
080 
081     @Nonnull
082     @Override
083     public Object resolveResource(@Nonnull String key, @Nonnull List<?> args, @Nonnull Locale localethrows NoSuchResourceException {
084         return resolveResource(key, toObjectArray(args), locale);
085     }
086 
087     @Nullable
088     @Override
089     public Object resolveResource(@Nonnull String key, @Nullable Object defaultValue) {
090         return resolveResource(key, EMPTY_OBJECT_ARGS, Locale.getDefault(), defaultValue);
091     }
092 
093     @Nullable
094     @Override
095     public Object resolveResource(@Nonnull String key, @Nonnull Locale locale, @Nullable Object defaultValue) {
096         return resolveResource(key, EMPTY_OBJECT_ARGS, locale, defaultValue);
097     }
098 
099     @Nullable
100     @Override
101     public Object resolveResource(@Nonnull String key, @Nonnull Object[] args, @Nullable Object defaultValue) {
102         return resolveResource(key, args, Locale.getDefault(), defaultValue);
103     }
104 
105     @Nullable
106     @Override
107     public Object resolveResource(@Nonnull String key, @Nonnull Object[] args, @Nonnull Locale locale, @Nullable Object defaultValue) {
108         try {
109             return resolveResource(key, args, locale);
110         catch (NoSuchResourceException nsre) {
111             return null == defaultValue ? key : defaultValue;
112         }
113     }
114 
115     @Nullable
116     @Override
117     public Object resolveResource(@Nonnull String key, @Nonnull List<?> args, @Nullable Object defaultValue) {
118         return resolveResource(key, toObjectArray(args), Locale.getDefault(), defaultValue);
119     }
120 
121     @Nullable
122     @Override
123     public Object resolveResource(@Nonnull String key, @Nonnull List<?> args, @Nonnull Locale locale, @Nullable Object defaultValue) {
124         return resolveResource(key, toObjectArray(args), locale, defaultValue);
125     }
126 
127     @Nonnull
128     @Override
129     public Object resolveResource(@Nonnull String key, @Nonnull Map<String, Object> argsthrows NoSuchResourceException {
130         return resolveResource(key, args, Locale.getDefault());
131     }
132 
133     @Nonnull
134     @Override
135     public Object resolveResource(@Nonnull String key, @Nonnull Map<String, Object> args, @Nonnull Locale localethrows NoSuchResourceException {
136         requireNonBlank(key, ERROR_KEY_BLANK);
137         requireNonNull(args, ERROR_ARGS_NULL);
138         requireNonNull(locale, ERROR_LOCALE_NULL);
139         Object resource = resolveResourceValue(key, locale);
140         Object result = evalResourceWithArguments(resource, args);
141         if (result != nullreturn result;
142         throw new NoSuchResourceException(key, locale);
143     }
144 
145     @Nullable
146     @Override
147     public Object resolveResource(@Nonnull String key, @Nonnull Map<String, Object> args, @Nullable Object defaultValue) {
148         return resolveResource(key, args, Locale.getDefault(), defaultValue);
149     }
150 
151     @Nullable
152     @Override
153     public Object resolveResource(@Nonnull String key, @Nonnull Map<String, Object> args, @Nonnull Locale locale, @Nullable Object defaultValue) {
154         try {
155             return resolveResource(key, args, locale);
156         catch (NoSuchResourceException nsre) {
157             return null == defaultValue ? key : defaultValue;
158         }
159     }
160 
161     @Nonnull
162     @Override
163     public Object resolveResourceValue(@Nonnull String key, @Nonnull Locale localethrows NoSuchResourceException {
164         requireNonBlank(key, ERROR_KEY_BLANK);
165         requireNonNull(locale, ERROR_LOCALE_NULL);
166         try {
167             Object resource = doResolveResourceValue(key, locale);
168             if (resource instanceof CharSequence) {
169                 String msg = resource.toString();
170                 if (msg.length() >= && msg.startsWith(REF_KEY_START&& msg.endsWith(REF_KEY_END)) {
171                     String refKey = msg.substring(2, msg.length() 1);
172                     resource = resolveResourceValue(refKey, locale);
173                 }
174             }
175             return resource;
176         catch (MissingResourceException mre) {
177             throw new NoSuchResourceException(key, locale);
178         }
179     }
180 
181     @Nonnull
182     @Override
183     public String formatResource(@Nonnull String resource, @Nonnull List<?> args) {
184         requireNonBlank(resource, ERROR_RESOURCE_BLANK);
185         requireNonNull(args, ERROR_ARGS_NULL);
186         return formatResource(resource, args.toArray(new Object[args.size()]));
187     }
188 
189     @Nonnull
190     @Override
191     public String formatResource(@Nonnull String resource, @Nonnull Object[] args) {
192         requireNonBlank(resource, ERROR_RESOURCE_BLANK);
193         requireNonNull(args, ERROR_ARGS_NULL);
194         if (args.length == 0return resource;
195         return MessageFormat.format(resource, args);
196     }
197 
198     @Nonnull
199     @Override
200     public String formatResource(@Nonnull String resource, @Nonnull Map<String, Object> args) {
201         requireNonBlank(resource, ERROR_RESOURCE_BLANK);
202         requireNonNull(args, ERROR_ARGS_NULL);
203         for (Map.Entry<String, Object> variable : args.entrySet()) {
204             String var = variable.getKey();
205             String value = variable.getValue() != null ? variable.getValue().toString() null;
206             if (value != null) {
207                 resource = resource.replace("{:" + var + "}", value);
208             }
209         }
210         return resource;
211     }
212 
213     @Nonnull
214     protected abstract Object doResolveResourceValue(@Nonnull String key, @Nonnull Locale localethrows NoSuchResourceException;
215 
216     @Nullable
217     protected Object evalResourceWithArguments(@Nonnull Object resource, @Nonnull Object[] args) {
218         if (resource instanceof CallableWithArgs) {
219             CallableWithArgs<?> callable = (CallableWithArgs<?>resource;
220             return callable.call(args);
221         else if (resource instanceof CharSequence) {
222             return formatResource(String.valueOf(resource), args);
223         }
224         return resource;
225     }
226 
227     @Nullable
228     protected Object evalResourceWithArguments(@Nonnull Object resource, @Nonnull Map<String, Object> args) {
229         if (resource instanceof CallableWithArgs) {
230             CallableWithArgs<?> callable = (CallableWithArgs<?>resource;
231             return callable.call(args);
232         else if (resource instanceof CharSequence) {
233             return formatResource(String.valueOf(resource), args);
234         }
235         return resource;
236     }
237 
238     @Nonnull
239     protected Object[] toObjectArray(@Nonnull List<?> args) {
240         if (args.isEmpty()) {
241             return EMPTY_OBJECT_ARGS;
242         }
243         return args.toArray(new Object[args.size()]);
244     }
245 }