View Javadoc

1   /*
2    * Copyright 2007-2013 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.message;
17  
18  import java.io.Serializable;
19  import java.util.Locale;
20  import java.util.MissingResourceException;
21  
22  import de.smartics.exceptions.core.Code;
23  import de.smartics.exceptions.i18n.CauseTrailMessages;
24  import de.smartics.exceptions.i18n.I18nExceptionContext;
25  import de.smartics.exceptions.i18n.I18nExceptionContextManager;
26  
27  /**
28   * Controls the localized information for a throwable.
29   */
30  public class LocalizedInfo implements Serializable
31  {
32    // ********************************* Fields *********************************
33  
34    // --- constants ------------------------------------------------------------
35  
36    /**
37     * The class version identifier.
38     */
39    private static final long serialVersionUID = 1L;
40  
41    /**
42     * The suffix for the auto generated bundle name.
43     * <p>
44     * The value of this constant is {@value}.
45     * </p>
46     */
47    public static final String BUNDLE_NAME_SUFFIX = "Bundle";
48  
49    // --- members --------------------------------------------------------------
50  
51    /**
52     * The localization key to fetch messages from message bundles. If this value
53     * is not set, the {@link String} representation of the provided code instance
54     * is used.
55     *
56     * @serial
57     */
58    protected final String resourceKey;
59  
60    /**
61     * The fully qualified base name of the bundle to use.
62     * <p>
63     * This bundle base name must never be <code>null</code>.
64     * </p>
65     *
66     * @serial
67     */
68    protected final String bundleBaseName;
69  
70    /**
71     * The cause to the problem.
72     *
73     * @serial
74     */
75    protected final Throwable cause;
76  
77    // ****************************** Initializer *******************************
78  
79    // ****************************** Constructors ******************************
80  
81    /**
82     * Convenience constructor.
83     *
84     * @param code the error or exception code of the exception.
85     */
86    public LocalizedInfo(final Code code)
87    {
88      this(code, null);
89    }
90  
91    /**
92     * Convenience constructor.
93     *
94     * @param code the error or exception code of the exception.
95     * @param cause the cause to the problem.
96     */
97    public LocalizedInfo(final Code code, final Throwable cause)
98    {
99      this(code, cause, null, null);
100   }
101 
102   /**
103    * Convenience constructor without cause trail.
104    *
105    * @param code the error or exception code of the exception.
106    * @param bundleBaseName the fully qualified name of the bundle to use.
107    * @param resourceKey the localization key to fetch messages from message
108    *          bundles.
109    */
110   public LocalizedInfo(final Code code, final String bundleBaseName,
111       final String resourceKey)
112   {
113     this(code, null, bundleBaseName, resourceKey);
114   }
115 
116   /**
117    * Default constructor.
118    *
119    * @param code the error or exception code of the exception.
120    * @param cause the cause to the problem.
121    * @param bundleBaseName the fully qualified name of the bundle to use.
122    * @param resourceKey the localization key to fetch messages from message
123    *          bundles.
124    */
125   public LocalizedInfo(final Code code, final Throwable cause,
126       final String bundleBaseName, final String resourceKey)
127   {
128     this.cause = cause;
129     this.resourceKey = resourceKey != null ? resourceKey : code.getCode();
130     this.bundleBaseName =
131         bundleBaseName != null ? bundleBaseName : createDefaultBundleName(code);
132   }
133 
134   // ****************************** Inner Classes *****************************
135 
136   // ********************************* Methods ********************************
137 
138   // --- init -----------------------------------------------------------------
139 
140   /**
141    * Created the default bundle name for the given code if no bundle name is
142    * provided. The name is build by using the class name of the code
143    * implementation and the {@link LocalizedInfo#BUNDLE_NAME_SUFFIX}.
144    *
145    * @param code the code that provides the bundle name prefix.
146    * @return the default bundle name derived from the code's class.
147    */
148   private String createDefaultBundleName(final Code code)
149   {
150     final String defaultBundleBaseName =
151         code.getClass().getName() + BUNDLE_NAME_SUFFIX;
152     return defaultBundleBaseName;
153   }
154 
155   // --- get&set --------------------------------------------------------------
156 
157   /**
158    * Returns the localization key to fetch messages from message bundles. If
159    * this value is not set, the {@link String} representation of the code
160    * instance is used.
161    *
162    * @return the localization key to fetch messages from message bundles.
163    */
164   public String getResourceKey()
165   {
166     return this.resourceKey;
167   }
168 
169   /**
170    * Returns the fully qualified base name of the bundle to use.
171    *
172    * @return the fully qualified base name of the bundle to use.
173    */
174   public String getBundleBaseName()
175   {
176     return this.bundleBaseName;
177   }
178 
179   // --- business -------------------------------------------------------------
180 
181   /**
182    * Returns the localized message for the given locale.
183    *
184    * @param bean the throwable to construct the localized message.
185    * @param locale the locale for which the message is requested.
186    * @param loader the loader to read the message bundle.
187    * @return returns the localized message of this exception.
188    */
189   public String getLocalizedMessage(final Object bean, final Locale locale,
190       final ClassLoader loader)
191   {
192     final I18nExceptionContext context =
193         I18nExceptionContextManager.getInstance().getContext(loader);
194     final MessageTemplate template = context.getMessageTemplateId();
195     if (MessageTemplate.SINGLE_LINE_STANDARD == template)
196     {
197       return getLocalizedSingleLineMessage(bean, locale, loader, true);
198     }
199     if (MessageTemplate.SINGLE_LINE_SUMMARY_ONLY == template)
200     {
201       return getLocalizedSingleLineMessage(bean, locale, loader, false);
202     }
203     else
204     // multi-line all
205     {
206       return getLocalizedTextMessage(bean, locale, loader);
207     }
208   }
209 
210   /**
211    * Returns the localized message for the given locale.
212    *
213    * @param bean the throwable to construct the localized message.
214    * @param locale the locale for which the message is requested.
215    * @param loader the loader to read the message bundle.
216    * @param standard the flag that adds all information to the exception text (
217    *          <code>true</code>) or only the summary (<code>false</code>).
218    * @return returns the localized message of this exception.
219    */
220   public String getLocalizedSingleLineMessage(final Object bean,
221       final Locale locale, final ClassLoader loader, final boolean standard)
222   {
223     final SingleLineTextHandler handler =
224         new SingleLineTextHandler(bundleBaseName, resourceKey, standard);
225     return handler.getMessage(bean, locale, loader);
226   }
227 
228   /**
229    * Returns the structured and localized message for the given locale,
230    * returning each part of information that is provided.
231    *
232    * @param bean the throwable to construct the localized message.
233    * @param locale the locale for which the message is requested.
234    * @param loader the loader to read the message bundle.
235    * @return returns the localized message of this exception.
236    */
237   public String getLocalizedTextMessage(final Object bean, final Locale locale,
238       final ClassLoader loader)
239   {
240     final StructuredTextHandler handler =
241         new StructuredTextHandler(bundleBaseName, resourceKey);
242     return handler.getMessage(bean, locale, loader);
243   }
244 
245   /**
246    * Returns the localized message for the given locale.
247    *
248    * @param bean the throwable to construct the localized message.
249    * @param keyPrefix the prefix of the key to load from the bundle.
250    * @param locale the locale for which the message is requested.
251    * @param messageType the type of message to localize.
252    * @param loader the loader to read the message bundle.
253    * @return returns the localized message of this exception.
254    */
255   public String getLocalizedMessage(final Object bean, final String keyPrefix,
256       final Locale locale, final MessageType messageType,
257       final ClassLoader loader)
258   {
259     final SingleLineTextHandler handler =
260         new SingleLineTextHandler(bundleBaseName, resourceKey, true);
261     try
262     {
263       return handler.fetchLocalizedMessage(bean, keyPrefix, locale,
264           messageType, loader);
265     }
266     catch (final MissingResourceException e)
267     {
268       return keyPrefix + '.' + messageType;
269     }
270   }
271 
272   /**
273    * Creates a localized message.
274    *
275    * @param bean the throwable to construct the localized message.
276    * @param keyPrefix the prefix of the key to load from the bundle.
277    * @param locale the locale for which the message is requested.
278    * @param messageType the type of message to localize.
279    * @param loader the loader to read the message bundle.
280    * @return returns the localized message of this exception.
281    */
282   public String createLocalizedMessage(final Object bean,
283       final String keyPrefix, final Locale locale,
284       final MessageType messageType, final ClassLoader loader)
285   {
286     final SingleLineTextHandler handler =
287         new SingleLineTextHandler(bundleBaseName, resourceKey, true);
288     try
289     {
290       return handler.fetchLocalizedMessage(bean, keyPrefix, locale,
291           messageType, loader);
292     }
293     catch (final MissingResourceException e)
294     {
295       return null;
296     }
297   }
298 
299   /**
300    * Creates a message.
301    *
302    * @param bean the throwable to construct the localized message.
303    * @param keyPrefix the prefix of the key to load from the bundle.
304    * @param messageType the type of message to localize.
305    * @param loader the loader to read the message bundle.
306    * @return returns the message of this exception.
307    */
308   public String createMessage(final Object bean, final String keyPrefix,
309       final MessageType messageType, final ClassLoader loader)
310   {
311     return createLocalizedMessage(bean, keyPrefix, Locale.getDefault(),
312         messageType, loader);
313   }
314 
315   /**
316    * Returns the messages of the cause up to the root cause.
317    *
318    * @return the messages of the cause up to the root cause.
319    */
320   public final CauseTrailMessages getCauseTrail()
321   {
322     return getCauseTrail(Locale.getDefault());
323   }
324 
325   /**
326    * Returns the cause to the exception. May be <code>null</code>.
327    *
328    * @return the cause to the exception. May be <code>null</code>.
329    */
330   public final Throwable getCause()
331   {
332     return cause;
333   }
334 
335   /**
336    * Returns the messages of the cause up to the root cause.
337    *
338    * @param locale the locale for which the message is requested.
339    * @return the messages of the cause up to the root cause.
340    */
341   public final CauseTrailMessages getCauseTrail(final Locale locale)
342   {
343     return new CauseTrailMessages(locale, cause);
344   }
345 
346   // --- object basics --------------------------------------------------------
347 
348 }