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 key) throws 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 locale) throws NoSuchResourceException {
054 return resolveResource(key, EMPTY_OBJECT_ARGS, locale);
055 }
056
057 @Nonnull
058 @Override
059 public Object resolveResource(@Nonnull String key, @Nonnull Object[] args) throws 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 locale) throws 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 != null) return result;
072 throw new NoSuchResourceException(key, locale);
073 }
074
075 @Nonnull
076 @Override
077 public Object resolveResource(@Nonnull String key, @Nonnull List<?> args) throws 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 locale) throws 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> args) throws 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 locale) throws 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 != null) return 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 locale) throws 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() >= 4 && 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 == 0) return 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 locale) throws 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 }
|