View Javadoc

1   /*
2    * Copyright 2007-2011 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.exceptions.i18n;
17  
18  import java.util.Locale;
19  
20  import org.apache.commons.lang.StringUtils;
21  
22  import de.smartics.exceptions.AbstractCoreRuntimeException;
23  import de.smartics.exceptions.core.Code;
24  import de.smartics.exceptions.i18n.message.LocalizedInfo;
25  import de.smartics.exceptions.i18n.message.MessageType;
26  
27  /**
28   * The base implementation of exceptions that support Internationalization for
29   * unchecked exceptions.
30   *
31   * @author <a href="mailto:robert.reiner@smartics.de">Robert Reiner</a>
32   * @version $Revision$
33   */
34  public abstract class AbstractLocalizedRuntimeException extends
35      AbstractCoreRuntimeException implements LocalizedException
36  {
37    // ********************************* Fields *********************************
38  
39    // --- constants ------------------------------------------------------------
40  
41    /**
42     * The class version identifier.
43     */
44    private static final long serialVersionUID = 1L;
45  
46    // ... resource key .........................................................
47  
48    // --- members --------------------------------------------------------------
49  
50    /**
51     * The localized information controls the localization information.
52     *
53     * @serial
54     */
55    protected final LocalizedInfo localizedInfo;
56  
57    // ****************************** Initializer *******************************
58  
59    // ****************************** Constructors ******************************
60  
61    /**
62     * Constructor.
63     *
64     * @param code the error or exception code of the exception.
65     * @see #AbstractLocalizedRuntimeException(Throwable,Code)
66     */
67    protected AbstractLocalizedRuntimeException(final Code code)
68    {
69      this(null, code);
70    }
71  
72    /**
73     * Constructor.
74     *
75     * @param code the error or exception code of the exception.
76     * @param bundleBaseName the fully qualified name of the bundle to use.
77     * @see #AbstractLocalizedRuntimeException(Throwable,Code,String)
78     */
79    protected AbstractLocalizedRuntimeException(final Code code,
80        final String bundleBaseName)
81    {
82      this(null, code, bundleBaseName);
83    }
84  
85    /**
86     * Constructor.
87     *
88     * @param cause the cause (which is saved for later retrieval by the
89     *          {@link #getCause()} method). (A <tt>null</tt> value is permitted,
90     *          and indicates that the cause is nonexistent or unknown.)
91     * @param code the error or exception code of the exception.
92     * @see #AbstractLocalizedRuntimeException(Throwable,Code,String)
93     */
94    protected AbstractLocalizedRuntimeException(final Throwable cause,
95        final Code code)
96    {
97      this(cause, code, null);
98    }
99  
100   /**
101    * Constructor.
102    *
103    * @param cause the cause (which is saved for later retrieval by the
104    *          {@link #getCause()} method). (A <tt>null</tt> value is permitted,
105    *          and indicates that the cause is nonexistent or unknown.)
106    * @param code the error or exception code of the exception.
107    * @param bundleBaseName the fully qualified name of the bundle to use.
108    * @see #AbstractLocalizedRuntimeException(Throwable,Code,String,String)
109    */
110   protected AbstractLocalizedRuntimeException(final Throwable cause,
111       final Code code, final String bundleBaseName)
112   {
113     this(cause, code, bundleBaseName, null);
114   }
115 
116   /**
117    * Constructor.
118    *
119    * @param cause the cause (which is saved for later retrieval by the
120    *          {@link #getCause()} method). (A <tt>null</tt> value is permitted,
121    *          and indicates that the cause is nonexistent or unknown.)
122    * @param code the error or exception code of the exception.
123    * @param bundleBaseName the fully qualified name of the bundle to use.
124    * @param resourceKey the localization key to fetch messages from message
125    *          bundles.
126    * @see AbstractCoreRuntimeException#AbstractCoreRuntimeException(String,
127    *      Throwable, Code)
128    */
129   protected AbstractLocalizedRuntimeException(final Throwable cause,
130       final Code code, final String bundleBaseName, final String resourceKey)
131   {
132     super(null, cause, code);
133     this.localizedInfo = new LocalizedInfo(code, bundleBaseName, resourceKey);
134   }
135 
136   // ****************************** Inner Classes *****************************
137 
138   // ********************************* Methods ********************************
139 
140   // --- init -----------------------------------------------------------------
141 
142   // --- get&set --------------------------------------------------------------
143 
144   /**
145    * Returns the localization key to fetch messages from message bundles. If
146    * this value is not set, the {@link String} representation of the
147    * {@link #getCode()} instance is used.
148    *
149    * @return the localization key to fetch messages from message bundles.
150    */
151   public String getResourceKey()
152   {
153     return localizedInfo.getResourceKey();
154   }
155 
156   /**
157    * Returns the fully qualified base name of the bundle to use.
158    *
159    * @return the fully qualified base name of the bundle to use.
160    */
161   public String getBundleBaseName()
162   {
163     return localizedInfo.getBundleBaseName();
164   }
165 
166   // --- business -------------------------------------------------------------
167 
168   // ... get message ..........................................................
169 
170   /**
171    * Returns the message for the given message type and the system's default
172    * locale.
173    *
174    * @param messageType the type if message to return.
175    * @return the message for the given message type.
176    */
177   public String getMessage(final MessageType messageType)
178   {
179     final Locale locale = Locale.getDefault();
180     return getMessage(locale, messageType);
181   }
182 
183   /**
184    * {@inheritDoc}
185    * <p>
186    * Returns the localized message for the default locale.
187    *
188    * @see java.lang.Throwable#getMessage()
189    */
190   @Override
191   public String getMessage()
192   {
193     return getLocalizedMessage();
194   }
195 
196   /**
197    * Returns the message for the given message type.
198    *
199    * @param locale the locale to select the localized message.
200    * @param messageType the type if message to return.
201    * @return the message for the given message type.
202    */
203   public String getMessage(final Locale locale, final MessageType messageType)
204   {
205     final String resourceKey = localizedInfo.getResourceKey();
206     return getLocalizedMessage(resourceKey, locale, messageType, null); // ,
207     // null
208     // );
209   }
210 
211   // ... throwable standard message
212 
213   /**
214    * Returns the localized message according to the system's default locale.
215    * <p>
216    * {@inheritDoc}
217    */
218   @Override
219   public String getLocalizedMessage()
220   {
221     return getLocalizedMessage(Locale.getDefault());
222   }
223 
224   /**
225    * Returns the localized message for the given locale.
226    *
227    * @param locale the locale for which the message is requested.
228    * @return returns the localized message of this exception.
229    */
230   public String getLocalizedMessage(final Locale locale)
231   {
232     return getLocalizedMessage(locale, null); // , null);
233   }
234 
235   /**
236    * Returns the localized message for the given locale.
237    *
238    * @param locale the locale for which the message is requested.
239    * @param loader the loader to read the message bundle.
240    * @return returns the localized message of this exception.
241    */
242   public String getLocalizedMessage(
243       final Locale locale,
244       final ClassLoader loader)
245   {
246     final String keyPrefix = getCode().getCode();
247     return getLocalizedMessage(keyPrefix, locale, MessageType.SUMMARY, loader);
248   }
249 
250   // /**
251   // * Returns the localized message for the given locale.
252   // *
253   // * @param locale the locale for which the message is requested.
254   // * @param control the controller to load the resource bundle.
255   // * @return returns the localized message of this exception.
256   // * @todo Should we really provide these methods with class loader and
257   // control?
258   // * What is the user scenario for this?
259   // */
260   // public String getLocalizedMessage(
261   // final Locale locale,
262   // final ResourceBundle.Control control)
263   // {
264   // return getLocalizedMessage(locale, null, control);
265   // }
266 
267   // /**
268   // * Returns the localized message for the given locale.
269   // *
270   // * @param locale the locale for which the message is requested.
271   // * @param loader the loader to read the message bundle.
272   // * @param control the controller to load the resource bundle.
273   // * @return returns the localized message of this exception.
274   // */
275   // public String getLocalizedMessage(
276   // final Locale locale,
277   // final ClassLoader loader,
278   // final ResourceBundle.Control control)
279   // {
280   // final String message = localizedInfo.getLocalizedMessage(this, locale,
281   // loader, control);
282   // return message;
283   // }
284 
285   // ... fetcher for all messages
286 
287   /**
288    * Returns the localized message for the given locale.
289    *
290    * @param keyPrefix the prefix of the key to load from the bundle.
291    * @param locale the locale for which the message is requested.
292    * @param messageType the type of message to localize.
293    * @param loader the loader to read the message bundle.
294    * @return returns the localized message of this exception.
295    * @todo Should we really provide these methods with class loader and control?
296    *       What is the user scenario for this?
297    */
298   public String getLocalizedMessage(
299       final String keyPrefix,
300       final Locale locale,
301       final MessageType messageType,
302       final ClassLoader loader) // ,
303   // final ResourceBundle.Control control)
304   {
305     final String message =
306         localizedInfo.getLocalizedMessage(this, keyPrefix, locale, messageType,
307             loader); // , control);
308     return message;
309   }
310 
311   /**
312    * {@inheritDoc}
313    *
314    * @see de.smartics.exceptions.i18n.LocalizedException#getMessages()
315    */
316   public String getMessages()
317   {
318     return getMessages(Locale.getDefault());
319   }
320 
321   /**
322    * {@inheritDoc}
323    *
324    * @see de.smartics.exceptions.i18n.LocalizedException#getMessages(java.util.Locale)
325    */
326   public String getMessages(final Locale locale)
327   {
328     final StringBuilder buffer = new StringBuilder();
329     for (MessageType type : MessageType.values())
330     {
331       buffer.append(type.name()).append('=').append(getMessage(locale, type))
332           .append(' ');
333     }
334     return StringUtils.chop(buffer.toString());
335   }
336 
337   // --- object basics --------------------------------------------------------
338 
339 }