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