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 }