AbstractMessageSource.java
001 /*
002  * SPDX-License-Identifier: Apache-2.0
003  *
004  * Copyright 2008-2017 the original author or authors.
005  *
006  * Licensed under the Apache License, Version 2.0 (the "License");
007  * you may not use this file except in compliance with the License.
008  * You may obtain a copy of the License at
009  *
010  *     http://www.apache.org/licenses/LICENSE-2.0
011  *
012  * Unless required by applicable law or agreed to in writing, software
013  * distributed under the License is distributed on an "AS IS" BASIS,
014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015  * See the License for the specific language governing permissions and
016  * limitations under the License.
017  */
018 package org.codehaus.griffon.runtime.core.i18n;
019 
020 import griffon.core.CallableWithArgs;
021 import griffon.core.i18n.MessageSource;
022 import griffon.core.i18n.NoSuchMessageException;
023 
024 import javax.annotation.Nonnull;
025 import javax.annotation.Nullable;
026 import java.text.MessageFormat;
027 import java.util.List;
028 import java.util.Locale;
029 import java.util.Map;
030 import java.util.MissingResourceException;
031 
032 import static griffon.util.GriffonNameUtils.requireNonBlank;
033 import static java.util.Objects.requireNonNull;
034 
035 /**
036  @author Andres Almiray
037  @author Alexander Klein
038  @since 2.0.0
039  */
040 public abstract class AbstractMessageSource implements MessageSource {
041     protected static final String ERROR_KEY_BLANK = "Argument 'key' must not be blank";
042     protected static final String ERROR_LOCALE_NULL = "Argument 'locale' must not be null";
043     protected static final String ERROR_ARGS_NULL = "Argument 'args' must not be null";
044     protected static final String ERROR_MESSAGE_NULL = "Argument 'message' must not be null";
045 
046     protected static final Object[] EMPTY_OBJECT_ARGS = new Object[0];
047 
048     @Nonnull
049     @Override
050     public String getMessage(@Nonnull String keythrows NoSuchMessageException {
051         return getMessage(key, EMPTY_OBJECT_ARGS, Locale.getDefault());
052     }
053 
054     @Nonnull
055     @Override
056     public String getMessage(@Nonnull String key, @Nonnull Locale localethrows NoSuchMessageException {
057         return getMessage(key, EMPTY_OBJECT_ARGS, locale);
058     }
059 
060     @Nonnull
061     @Override
062     public String getMessage(@Nonnull String key, @Nonnull Object[] argsthrows NoSuchMessageException {
063         return getMessage(key, args, Locale.getDefault());
064     }
065 
066     @Nonnull
067     @Override
068     public String getMessage(@Nonnull String key, @Nonnull Object[] args, @Nonnull Locale localethrows NoSuchMessageException {
069         requireNonBlank(key, ERROR_KEY_BLANK);
070         requireNonNull(args, ERROR_ARGS_NULL);
071         requireNonNull(locale, ERROR_LOCALE_NULL);
072         Object message = resolveMessageValue(key, locale);
073         Object result = evalMessageWithArguments(message, args);
074         if (result != nullreturn result.toString();
075         throw new NoSuchMessageException(key, locale);
076     }
077 
078     @Nonnull
079     @Override
080     public String getMessage(@Nonnull String key, @Nonnull List<?> argsthrows NoSuchMessageException {
081         return getMessage(key, toObjectArray(args), Locale.getDefault());
082     }
083 
084     @Nonnull
085     @Override
086     public String getMessage(@Nonnull String key, @Nonnull List<?> args, @Nonnull Locale localethrows NoSuchMessageException {
087         return getMessage(key, toObjectArray(args), locale);
088     }
089 
090     @Nullable
091     @Override
092     public String getMessage(@Nonnull String key, @Nullable String defaultMessage) {
093         return getMessage(key, EMPTY_OBJECT_ARGS, Locale.getDefault(), defaultMessage);
094     }
095 
096     @Nullable
097     @Override
098     public String getMessage(@Nonnull String key, @Nonnull Locale locale, @Nullable String defaultMessage) {
099         return getMessage(key, EMPTY_OBJECT_ARGS, locale, defaultMessage);
100     }
101 
102     @Nullable
103     @Override
104     public String getMessage(@Nonnull String key, @Nonnull Object[] args, @Nullable String defaultMessage) {
105         return getMessage(key, args, Locale.getDefault(), defaultMessage);
106     }
107 
108     @Nullable
109     @Override
110     public String getMessage(@Nonnull String key, @Nonnull Object[] args, @Nonnull Locale locale, @Nullable String defaultMessage) {
111         try {
112             return getMessage(key, args, locale);
113         catch (NoSuchMessageException nsme) {
114             return null == defaultMessage ? key : defaultMessage;
115         }
116     }
117 
118     @Nullable
119     @Override
120     public String getMessage(@Nonnull String key, @Nonnull List<?> args, @Nullable String defaultMessage) {
121         return getMessage(key, toObjectArray(args), Locale.getDefault(), defaultMessage);
122     }
123 
124     @Nullable
125     @Override
126     public String getMessage(@Nonnull String key, @Nonnull List<?> args, @Nonnull Locale locale, @Nullable String defaultMessage) {
127         return getMessage(key, toObjectArray(args), locale, defaultMessage);
128     }
129 
130     @Nonnull
131     @Override
132     public String getMessage(@Nonnull String key, @Nonnull Map<String, Object> argsthrows NoSuchMessageException {
133         return getMessage(key, args, Locale.getDefault());
134     }
135 
136     @Nonnull
137     @Override
138     public String getMessage(@Nonnull String key, @Nonnull Map<String, Object> args, @Nonnull Locale localethrows NoSuchMessageException {
139         requireNonBlank(key, ERROR_KEY_BLANK);
140         requireNonNull(args, ERROR_ARGS_NULL);
141         requireNonNull(locale, ERROR_LOCALE_NULL);
142         Object message = resolveMessageValue(key, locale);
143         Object result = evalMessageWithArguments(message, args);
144         if (result != nullreturn result.toString();
145         throw new NoSuchMessageException(key, locale);
146     }
147 
148     @Nullable
149     @Override
150     public String getMessage(@Nonnull String key, @Nonnull Map<String, Object> args, @Nullable String defaultMessage) {
151         return getMessage(key, args, Locale.getDefault(), defaultMessage);
152     }
153 
154     @Nullable
155     @Override
156     public String getMessage(@Nonnull String key, @Nonnull Map<String, Object> args, @Nonnull Locale locale, @Nullable String defaultMessage) {
157         try {
158             return getMessage(key, args, locale);
159         catch (NoSuchMessageException nsme) {
160             return null == defaultMessage ? key : defaultMessage;
161         }
162     }
163 
164     @Nonnull
165     @Override
166     public Object resolveMessageValue(@Nonnull String key, @Nonnull Locale localethrows NoSuchMessageException {
167         requireNonBlank(key, ERROR_KEY_BLANK);
168         requireNonNull(locale, ERROR_LOCALE_NULL);
169         try {
170             Object message = doResolveMessageValue(key, locale);
171             if (message instanceof CharSequence) {
172                 String msg = message.toString();
173                 if (msg.length() >= && msg.startsWith(REF_KEY_START&& msg.endsWith(REF_KEY_END)) {
174                     String refKey = msg.substring(2, msg.length() 1);
175                     message = resolveMessageValue(refKey, locale);
176                 }
177             }
178             return message;
179         catch (MissingResourceException mre) {
180             throw new NoSuchMessageException(key, locale);
181         }
182     }
183 
184     @Nonnull
185     @Override
186     public String formatMessage(@Nonnull String message, @Nonnull List<?> args) {
187         requireNonNull(message, ERROR_MESSAGE_NULL);
188         requireNonNull(args, ERROR_ARGS_NULL);
189         return formatMessage(message, args.toArray(new Object[args.size()]));
190     }
191 
192     @Nonnull
193     @Override
194     public String formatMessage(@Nonnull String message, @Nonnull Object[] args) {
195         requireNonNull(message, ERROR_MESSAGE_NULL);
196         requireNonNull(args, ERROR_ARGS_NULL);
197         if (args.length == 0return message;
198         return MessageFormat.format(message, args);
199     }
200 
201     @Nonnull
202     @Override
203     public String formatMessage(@Nonnull String message, @Nonnull Map<String, Object> args) {
204         requireNonNull(message, ERROR_MESSAGE_NULL);
205         requireNonNull(args, ERROR_ARGS_NULL);
206         for (Map.Entry<String, Object> variable : args.entrySet()) {
207             String var = variable.getKey();
208             String value = variable.getValue() != null ? variable.getValue().toString() null;
209             if (value != null) {
210                 message = message.replace("{:" + var + "}", value);
211             }
212         }
213         return message;
214     }
215 
216     @Nonnull
217     protected abstract Object doResolveMessageValue(@Nonnull String key, @Nonnull Locale localethrows NoSuchMessageException;
218 
219     @Nullable
220     protected Object evalMessageWithArguments(@Nonnull Object message, @Nonnull Object[] args) {
221         if (message instanceof CallableWithArgs) {
222             CallableWithArgs<?> callable = (CallableWithArgs<?>message;
223             return callable.call(args);
224         else if (message instanceof CharSequence) {
225             return formatMessage(String.valueOf(message), args);
226         }
227         return null;
228     }
229 
230     @Nullable
231     protected Object evalMessageWithArguments(@Nonnull Object message, @Nonnull Map<String, Object> args) {
232         if (message instanceof CallableWithArgs) {
233             CallableWithArgs<?> callable = (CallableWithArgs<?>message;
234             return callable.call(args);
235         else if (message instanceof CharSequence) {
236             return formatMessage(String.valueOf(message), args);
237         }
238         return null;
239     }
240 
241     @Nonnull
242     protected Object[] toObjectArray(@Nonnull List<?> args) {
243         if (args.isEmpty()) {
244             return EMPTY_OBJECT_ARGS;
245         }
246         return args.toArray(new Object[args.size()]);
247     }
248 }