001: /*
002: * Copyright (c) 2001 - 2005 ivata limited.
003: * All rights reserved.
004: * -----------------------------------------------------------------------------
005: * ivata groupware may be redistributed under the GNU General Public
006: * License as published by the Free Software Foundation;
007: * version 2 of the License.
008: *
009: * These programs are free software; you can redistribute them and/or
010: * modify them under the terms of the GNU General Public License
011: * as published by the Free Software Foundation; version 2 of the License.
012: *
013: * These programs are distributed in the hope that they will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016: *
017: * See the GNU General Public License in the file LICENSE.txt for more
018: * details.
019: *
020: * If you would like a copy of the GNU General Public License write to
021: *
022: * Free Software Foundation, Inc.
023: * 59 Temple Place - Suite 330
024: * Boston, MA 02111-1307, USA.
025: *
026: *
027: * To arrange commercial support and licensing, contact ivata at
028: * http://www.ivata.com/contact.jsp
029: * -----------------------------------------------------------------------------
030: * $Log: MaskMessageResources.java,v $
031: * Revision 1.4 2005/11/03 14:30:49 colinmacleod
032: * Extended getMessage to search without prefix.
033: *
034: * Revision 1.3 2005/10/14 20:59:56 colinmacleod
035: * Added getMessage with just key parameter (no args).
036: *
037: * Revision 1.2 2005/10/12 18:35:57 colinmacleod
038: * Standardized format of Logger declaration - to make it easier to find
039: * instances which are not both static and final.
040: *
041: * Revision 1.1 2005/10/11 09:08:05 colinmacleod
042: * Renamed MaskMessageResources (from MessageResourcesHandling)
043: * and re-worked as a POJO rather than a utility class.
044: *
045: * Revision 1.3 2005/10/03 10:17:26 colinmacleod
046: * Fixed some style and javadoc issues.
047: *
048: * Revision 1.2 2005/10/02 14:06:34 colinmacleod
049: * Added/improved log4j logging.
050: *
051: * Revision 1.1 2005/10/02 10:51:25 colinmacleod
052: * Moved from web subproject to webtheme.
053: *
054: * Revision 1.5 2005/09/29 12:16:11 colinmacleod
055: * Added setting resources.
056: *
057: * Revision 1.4 2005/09/14 12:55:25 colinmacleod
058: * Replaced library resource with cms.
059: *
060: * Revision 1.3 2005/04/11 14:46:11 colinmacleod
061: * Added guessing of field label from field name.
062: *
063: * Revision 1.2 2005/04/09 18:04:19 colinmacleod
064: * Changed copyright text to GPL v2 explicitly.
065: *
066: * Revision 1.1 2005/03/10 10:29:39 colinmacleod
067: * Split off from MaskProperties, so the message
068: * resources for labels, etc. can be accessed globally.
069: *
070: * -----------------------------------------------------------------------------
071: */
072: package com.ivata.mask.web.struts.util;
073:
074: import java.util.HashMap;
075: import java.util.List;
076: import java.util.Locale;
077: import java.util.Map;
078: import java.util.Vector;
079:
080: import org.apache.log4j.Logger;
081: import org.apache.struts.util.MessageResources;
082:
083: import com.ivata.mask.util.StringHandling;
084: import com.ivata.mask.util.SystemException;
085:
086: /**
087: * Methods in this class wrap/extend the message resource system of
088: * <strong>Struts</strong>.
089: *
090: * @since ivata masks 0.5 (2005-01-20)
091: * @author Colin MacLeod
092: * <a href="mailto:colin.macleod@ivata.com">colin.macleod@ivata.com</a>
093: * @version $Revision: 1.4 $
094: */
095: public class MaskMessageResources {
096: /**
097: * This is prepended to fields to get their message resource string.
098: */
099: public static final String FIELD_PREFIX = "field.";
100: /**
101: * If <code>true</code>, then the field name is returned for fields which
102: * have not been defined.
103: */
104: private static boolean guessLabel = true;
105: /**
106: * Logger for this class.
107: */
108: private static final Logger logger = Logger
109: .getLogger(MaskMessageResources.class);
110:
111: /**
112: * Stores all of the message resources, indexed by bundle name or
113: * the vale of the field <code>NULL_BUNDLE</code> for the default bundle.
114: */
115: private static Map messageResourcesMap = new HashMap();
116: /**
117: * Name of the <code>null</code> bundle in the map.
118: */
119: public static final String NULL_BUNDLE = "null_bundle";
120: /**
121: * This is prepended to submit buttons to get their message resource string.
122: */
123: public static final String SUBMIT_PREFIX = "submit.";
124: /**
125: * This string is appended to field names to find their titles in the
126: * message resource bundle.
127: */
128: public static final String TITLE_SUFFIX = ".title";
129: /**
130: * This string is appended to field names to find their values in the
131: * message resource bundle.
132: */
133: public static final String VALUE_SUFFIX = ".value";
134: static {
135: MaskMessageResources.registerMessages("cms",
136: "com.ivata.cms.ApplicationResources");
137:
138: MaskMessageResources.registerMessages(null,
139: "com.ivata.groupware.business.ApplicationResources");
140: MaskMessageResources
141: .registerMessages("addressBook",
142: "com.ivata.groupware.business.addressbook.ApplicationResources");
143: MaskMessageResources.registerMessages("admin",
144: "com.ivata.groupware.admin.ApplicationResources");
145: MaskMessageResources
146: .registerMessages("calendar",
147: "com.ivata.groupware.business.calendar.ApplicationResources");
148: MaskMessageResources
149: .registerMessages("mail",
150: "com.ivata.groupware.business.mail.ApplicationResources");
151: MaskMessageResources
152: .registerMessages("security",
153: "com.ivata.groupware.admin.security.ApplicationResources");
154: MaskMessageResources
155: .registerMessages("setting",
156: "com.ivata.groupware.admin.setting.ApplicationResources");
157: }
158:
159: /**
160: * Get a bundle with the given name.
161: * @param bundleParam message resources identifier -
162: * see <code>Struts</code> docu.
163: * @return resources message resources instance.
164: * @throws SystemException if the message resources are undefined.
165: */
166: public static MessageResources getMessages(final String bundleParam)
167: throws SystemException {
168: if (logger.isDebugEnabled()) {
169: logger.debug("getMessages(String bundle = " + bundleParam
170: + ") - start");
171: }
172:
173: MessageResources messageResources;
174: if (bundleParam == null) {
175: messageResources = (MessageResources) messageResourcesMap
176: .get(NULL_BUNDLE);
177: } else {
178: messageResources = (MessageResources) messageResourcesMap
179: .get(bundleParam);
180: }
181: if (messageResources == null) {
182: throw new SystemException("Resource bundle '" + bundleParam
183: + "' is undefined.");
184: }
185:
186: if (logger.isDebugEnabled()) {
187: logger.debug("getMessages(String) - end - return value = "
188: + messageResources);
189: }
190: return messageResources;
191: }
192:
193: /**
194: * Guess what the label should be for a given field or class.
195: *
196: * @param fieldNameParam name of the field or class to guess the label for
197: * @return guessed label.
198: */
199: private static String guessLabel(final String fieldNameParam) {
200: if (logger.isDebugEnabled()) {
201: logger.debug("guessLabel(String fieldNameParam = "
202: + fieldNameParam + ") - start");
203: }
204:
205: // assume hungarian notation - each capital letter means a space
206: // apart from the first letter which is lower case for a field (but
207: // should be the first word)
208: StringBuffer guessedLabel = new StringBuffer();
209: // if we have a dot, assume we're dealing with a full path and class
210: // name
211: int dotPos = fieldNameParam.lastIndexOf('.');
212: String fieldName;
213: if (dotPos == -1) {
214: fieldName = fieldNameParam;
215: } else {
216: // for classes, strip off the package path and any DO suffix
217: int end = fieldNameParam.length();
218: if (fieldNameParam.endsWith("DO")) {
219: end -= 2;
220: }
221: fieldName = fieldNameParam.substring(dotPos + 1, end);
222: }
223:
224: int pos = 0;
225: // first character should be capitalised
226: guessedLabel.append((char) Character.toUpperCase(fieldName
227: .charAt(pos++)));
228: int len = fieldName.length();
229: boolean lastUpper = true;
230: while (pos < len) {
231: char ch = fieldName.charAt(pos);
232: // see if it is a new word
233: if (Character.isUpperCase(ch)) {
234: // if last char was also upper case that means an acronym
235: // - don't add a space in that case
236: if (!lastUpper) {
237: guessedLabel.append(" ");
238: }
239: lastUpper = true;
240: } else {
241: lastUpper = false;
242: }
243: guessedLabel.append(ch);
244: ++pos;
245: }
246: String returnString = guessedLabel.toString();
247: if (logger.isDebugEnabled()) {
248: logger.debug("guessLabel(String) - end - return value = "
249: + returnString);
250: }
251: return returnString;
252: }
253:
254: /**
255: * Register resources for a given bundle.
256: * @param bundleParam message resources identifier - see <code>Struts</code>
257: * docu.
258: * @param fullPath full path to the resources
259: */
260: public static synchronized void registerMessages(
261: final String bundleParam, final String fullPath) {
262:
263: if (logger.isDebugEnabled()) {
264: logger.debug("registerMessages(String bundle = "
265: + bundleParam + ", String fullPath = " + fullPath
266: + ") - start");
267: }
268:
269: assert (fullPath != null);
270:
271: String this Bundle = bundleParam;
272: if (this Bundle == null) {
273: this Bundle = NULL_BUNDLE;
274: }
275: MessageResources messageResources = MessageResources
276: .getMessageResources(fullPath);
277: assert (messageResources != null);
278: messageResourcesMap.put(this Bundle, messageResources);
279:
280: if (logger.isDebugEnabled()) {
281: logger.debug("registerMessages(String, String) - end");
282: }
283: }
284:
285: /**
286: * <copyDoc>Refer to {@link MaskMessageResources#MaskMessageResources()}.
287: * </copyDoc>
288: */
289: private String bundle;
290: /**
291: * <copyDoc>Refer to {@link MaskMessageResources#MaskMessageResources()}.
292: * </copyDoc>
293: */
294: private Locale locale;
295: /**
296: * <copyDoc>Refer to {@link MaskMessageResources#MaskMessageResources()}.
297: * </copyDoc>
298: */
299: private String resourceFieldPath;
300:
301: /**
302: * Create message resources for a mask.
303: *
304: * @param localeParam The current user's locale - used to localize messages.
305: * @param bundleParam Identifies the message resources to use.
306: * @param resourceFieldPathParam Identifies the prefix of the resources
307: * to search for first.
308: */
309: public MaskMessageResources(final Locale localeParam,
310: final String bundleParam,
311: final String resourceFieldPathParam) {
312: locale = localeParam;
313: bundle = bundleParam;
314: resourceFieldPath = resourceFieldPathParam;
315: }
316:
317: /**
318: * Get the default label for this field. If no label key is specifically
319: * set, the combination of
320: * <code>labelFieldPath + ".label"</code> is tried in the
321: * application resources. Failing that, the same is attempted using the
322: * default path (<code>defaultPath + ".label"</code>).
323: *
324: * @param fieldName name of the field for which to return the title.
325: * @param labelKey key used to access the title in the resources. If this
326: * is <code>null</code>, a default key is tried.
327: * @param labelArgs arguments used in conjunction with the key, in the
328: * message resources.
329: * @param labelKeySuffix Some fields have multiple label keys. This
330: * suffix is appended to the key when retrieving the localized text from the
331: * application resources file.
332: * @param button buttons have a different default path to field.
333: * <code>true</code> if this field represents a button.
334: * @param mandatory if <code>true</code> an exception is thrown if no
335: * value is found for this combination.
336: * @return title, if this tag has one, otherwise <code>null</code>.
337: * @throws SystemException if the text cannot be retrieved because of a
338: * system failure, or if the field is mandatory and cannot be found.
339: */
340: public String getDefaultLabel(final String fieldName,
341: final String labelKey, final List labelArgs,
342: final String labelKeySuffix, final boolean button,
343: final boolean mandatory) throws SystemException {
344: if (logger.isDebugEnabled()) {
345: logger.debug("getDefaultLabel(String fieldName = "
346: + fieldName + ", String labelKey = " + labelKey
347: + ", List labelArgs = " + labelArgs
348: + ", String labelKeySuffix = " + labelKeySuffix
349: + ", boolean button = " + button
350: + ", boolean mandatory = " + mandatory
351: + ") - start");
352: }
353:
354: String labelKeySuffixAppend;
355: if (StringHandling.isNullOrEmpty(labelKeySuffix)) {
356: labelKeySuffixAppend = "";
357: } else {
358: labelKeySuffixAppend = "." + labelKeySuffix;
359: }
360: boolean reallyMandatory = mandatory;
361: if (guessLabel && mandatory) {
362: reallyMandatory = false;
363: }
364: String label = getDefaultMessage(fieldName, labelKey,
365: labelArgs, labelKeySuffixAppend, button,
366: reallyMandatory);
367: if (guessLabel && StringHandling.isNullOrEmpty(label)
368: && !StringHandling.isNullOrEmpty(fieldName)) {
369: label = guessLabel(fieldName);
370: }
371:
372: if (logger.isDebugEnabled()) {
373: logger.debug("getDefaultLabel - end - return value = "
374: + label);
375: }
376: return label;
377: }
378:
379: /**
380: * Work out the label field path, used to localize label strings.
381: *
382: * @param fieldName name of the field for which to return the title.
383: * @param button buttons have a different default path to field.
384: * <code>true</code> if this field represents a button.
385: * @return label field path for this tag.
386: */
387: private String getDefaultLabelFieldPath(final String fieldName,
388: final boolean button) {
389: if (logger.isDebugEnabled()) {
390: logger.debug("getDefaultLabelFieldPath(String fieldName = "
391: + fieldName + ", boolean button = " + button
392: + ") - start");
393: }
394:
395: StringBuffer labelFieldPath = new StringBuffer();
396: labelFieldPath.append(resourceFieldPath);
397: // if the field name was set, default anything which was not from that
398: if (!StringHandling.isNullOrEmpty(fieldName)) {
399: if (!labelFieldPath.toString().endsWith(".")
400: && (labelFieldPath.length() > 0)) {
401: labelFieldPath.append(".");
402: }
403: }
404: labelFieldPath.append(getDefaultPath(button, fieldName));
405: String returnString = labelFieldPath.toString();
406: if (logger.isDebugEnabled()) {
407: logger
408: .debug("getDefaultLabelFieldPath - end - return value = "
409: + returnString);
410: }
411: return returnString;
412: }
413:
414: /**
415: * Private helper to avoid repetition. This method is used in all of the
416: * <code>getDefault...</code> methods.
417: *
418: * @param fieldName name of the field for which to return the message.
419: * @param key key used to access the message in the resources. If this
420: * is <code>null</code>, a default key is tried.
421: * @param args arguments used in conjunction with the key, in the
422: * message resources.
423: * @param suffix one of the <code>..._SUFFIX</code> constants from this
424: * class.
425: * @param button buttons have a different default path to field.
426: * <code>true</code> if this field represents a button.
427: * @param mandatory if <code>true</code> an exception is thrown if no
428: * value is found for this combination.
429: * @return text from the message resources.
430: * @throws SystemException if the text cannot be retrieved because of a
431: * system failure, or if the field is mandatory and cannot be found.
432: */
433: private String getDefaultMessage(final String fieldName,
434: final String key, final List args, final String suffix,
435: final boolean button, final boolean mandatory)
436: throws SystemException {
437: if (logger.isDebugEnabled()) {
438: logger.debug("getDefaultMessage(String fieldName = "
439: + fieldName + ", String key = " + key
440: + ", List args = " + args + ", String suffix = "
441: + suffix + ", boolean button = " + button
442: + ", boolean mandatory = " + mandatory
443: + ") - start");
444: }
445:
446: List keysTried = new Vector();
447:
448: String defaultPath = getDefaultPath(button, fieldName);
449: String actualKey = key;
450: String message = null;
451:
452: if (actualKey != null) {
453: keysTried.add(actualKey);
454: message = getMessage(actualKey, args);
455: if (logger.isDebugEnabled()) {
456: logger.debug("Got " + suffix + "'" + message
457: + "' from key '" + actualKey + "'");
458: }
459: }
460: if ((message == null)
461: && (!StringHandling.isNullOrEmpty(fieldName))) {
462: actualKey = getDefaultLabelFieldPath(fieldName, button)
463: + suffix;
464: keysTried.add(actualKey);
465: // see if there is a resource here
466: message = getMessage(actualKey, args);
467: if (logger.isDebugEnabled()) {
468: logger.debug("Got " + suffix + " '" + message
469: + "' from field name key '" + actualKey + "'");
470: }
471: // if there is no resource with this path, try the default one
472: if (message == null) {
473: actualKey = defaultPath + suffix;
474: keysTried.add(actualKey);
475: message = getMessage(actualKey, args);
476: if (logger.isDebugEnabled()) {
477: logger.debug("Got " + suffix + " '" + message
478: + "' from default path key '" + actualKey
479: + "'");
480: }
481: }
482: // these types _need_ to have a key
483: if ((message == null) && mandatory) {
484: throw new SystemException("No message resource "
485: + suffix + " key found for field name '"
486: + fieldName + "', bundle '" + bundle
487: + "', resourceFieldPath '" + resourceFieldPath
488: + suffix + "'. Tried these keys: " + keysTried
489: + ".");
490: }
491: }
492:
493: if (logger.isDebugEnabled()) {
494: logger.debug("getDefaultMessage - end - return value = "
495: + message);
496: }
497: return message;
498: }
499:
500: /**
501: * The default message resource path depends on type - buttons have a
502: * different application resource path from other types.
503: *
504: * @param button buttons have a different default path to field.
505: * <code>true</code> if this field represents a button.
506: * @param fieldName name of the field to default the path for.
507: * @return default path for this field.
508: */
509: private String getDefaultPath(final boolean button,
510: final String fieldName) {
511: if (logger.isDebugEnabled()) {
512: logger
513: .debug("getDefaultPath(boolean button = " + button
514: + ", String fieldName = " + fieldName
515: + ") - start");
516: }
517:
518: StringBuffer defaultPath;
519: if (button) {
520: defaultPath = new StringBuffer(
521: MaskMessageResources.SUBMIT_PREFIX);
522: } else {
523: defaultPath = new StringBuffer(
524: MaskMessageResources.FIELD_PREFIX);
525: }
526: defaultPath.append(fieldName);
527: String returnString = defaultPath.toString();
528: if (logger.isDebugEnabled()) {
529: logger.debug("getDefaultPath - end - return value = "
530: + returnString);
531: }
532: return returnString;
533: }
534:
535: /**
536: * Get the default title for this field. If no title key is specifically
537: * set, the combination of
538: * <code>labelFieldPath + ".title"</code> is tried in the
539: * application resources. Failing that, the same is attempted using the
540: * default path (<code>defaultPath + ".title"</code>).
541: *
542: * @param fieldName name of the field for which to return the title.
543: * @param titleKey key used to access the title in the resources. If this
544: * is <code>null</code>, a default key is tried.
545: * @param titleArgs arguments used in conjunction with the key, in the
546: * message resources.
547: * @param button buttons have a different default path to field.
548: * <code>true</code> if this field represents a button.
549: * @param mandatory if <code>true</code> an exception is thrown if no
550: * value is found for this combination.
551: * @return title, if this tag has one, otherwise <code>null</code>.
552: * @throws SystemException if the text cannot be retrieved because of a
553: * system failure, or if the field is mandatory and cannot be found.
554: */
555: public String getDefaultTitle(final String fieldName,
556: final String titleKey, final List titleArgs,
557: final boolean button, final boolean mandatory)
558: throws SystemException {
559: if (logger.isDebugEnabled()) {
560: logger.debug("getDefaultTitle(String fieldName = "
561: + fieldName + ", String titleKey = " + titleKey
562: + ", List titleArgs = " + titleArgs
563: + ", boolean button = " + button
564: + ", boolean mandatory = " + mandatory
565: + ") - start");
566: }
567:
568: String returnString = getDefaultMessage(fieldName, titleKey,
569: titleArgs, TITLE_SUFFIX, button, mandatory);
570: if (logger.isDebugEnabled()) {
571: logger.debug("getDefaultTitle - end - return value = "
572: + returnString);
573: }
574: return returnString;
575: }
576:
577: /**
578: * Get the default value for this field. If no value key is specifically
579: * set, the combination of
580: * <code>labelFieldPath + ".value"</code> is tried in the
581: * application resources. Failing that, the same is attempted using the
582: * default path (<code>defaultPath + ".value"</code>).
583: *
584: * @param fieldName name of the field for which to return the title.
585: * @param valueKey key used to access the title in the resources. If this
586: * is <code>null</code>, a default key is tried.
587: * @param valueArgs arguments used in conjunction with the key, in the
588: * message resources.
589: * @param button buttons have a different default path to field.
590: * <code>true</code> if this field represents a button.
591: * @param mandatory if <code>true</code> an exception is thrown if no
592: * value is found for this combination.
593: * @return title, if this tag has one, otherwise <code>null</code>.
594: * @throws SystemException if the text cannot be retrieved because of a
595: * system failure, or if the field is mandatory and cannot be found.
596: */
597: public String getDefaultValue(final String fieldName,
598: final String valueKey, final List valueArgs,
599: final boolean button, final boolean mandatory)
600: throws SystemException {
601: if (logger.isDebugEnabled()) {
602: logger.debug("getDefaultValue(Locale locale = " + locale
603: + ", String bundle = " + bundle
604: + ", String fieldName = " + fieldName
605: + ", String valueKey = " + valueKey
606: + ", List valueArgs = " + valueArgs
607: + ", String resourceFieldPath = "
608: + resourceFieldPath + ", boolean button = "
609: + button + ", boolean mandatory = " + mandatory
610: + ") - start");
611: }
612:
613: String returnString = getDefaultMessage(fieldName, valueKey,
614: valueArgs, VALUE_SUFFIX, button, mandatory);
615: if (logger.isDebugEnabled()) {
616: logger.debug("getDefaultValue - end - return value = "
617: + returnString);
618: }
619: return returnString;
620: }
621:
622: /**
623: * <copyDoc>Refer to {@link #getMessage(String, List)}.</copyDoc>.
624: * @param key
625: * <copyDoc>Refer to {@link #getMessage(String, List)}.</copyDoc>.
626: * @return
627: * <copyDoc>Refer to {@link #getMessage(String, List)}.</copyDoc>.
628: * @throws SystemException
629: * <copyDoc>Refer to {@link #getMessage(String, List)}.</copyDoc>.
630: */
631: public String getMessage(final String key) throws SystemException {
632: return getMessage(key, new Object[] {});
633: }
634:
635: /**
636: * This first tries using the
637: * bundle you provided. If that returns <code>null</code>, it tries again
638: * without a bundle.
639: * @param key
640: * <copyDoc>Refer to {@link MessageResources#getMessage}.</copyDoc>
641: * @param argsList Will be converted to an array of objects. Refer to
642: * {@link MessageResources#getMessage}.
643: *
644: * @return <copyDoc>Refer to {@link MessageResources#getMessage}.</copyDoc>
645: * @throws SystemException
646: * <copyDoc>Refer to {@link MessageResources#getMessage}.</copyDoc>
647: */
648: public String getMessage(final String key, final List argsList)
649: throws SystemException {
650: if (logger.isDebugEnabled()) {
651: logger.debug("getMessage(String bundle = " + bundle
652: + ", Locale locale = " + locale + ", String key = "
653: + key + ", List argsList = " + argsList
654: + ") - start");
655: }
656:
657: Object[] args;
658: if (argsList == null) {
659: args = new Object[] {};
660: } else {
661: args = argsList.toArray();
662: }
663: String returnString = getMessage(key, args);
664: if (logger.isDebugEnabled()) {
665: logger.debug("getMessage - end - return value = "
666: + returnString);
667: }
668: return returnString;
669: }
670:
671: /**
672: * This first tries using the
673: * bundle you provided. If that returns <code>null</code>, it tries again
674: * without a bundle.
675: * @param key
676: * <copyDoc>Refer to {@link MessageResources#getMessage}.</copyDoc>
677: * @param args
678: * <copyDoc>Refer to {@link MessageResources#getMessage}.</copyDoc>
679: *
680: * @return <copyDoc>Refer to {@link MessageResources#getMessage}.</copyDoc>
681: * @throws SystemException
682: * <copyDoc>Refer to {@link MessageResources#getMessage}.</copyDoc>
683: */
684: public String getMessage(final String key, final Object[] args)
685: throws SystemException {
686: if (logger.isDebugEnabled()) {
687: logger.debug("getMessage(String bundle = " + bundle
688: + ", Locale locale = " + locale + ", String key = "
689: + key + ", Object[] args = " + args + ") - start");
690: }
691:
692: assert (key != null);
693: String message = null;
694: if (bundle != null) {
695: MessageResources messages = getMessages(bundle);
696: message = messages.getMessage(locale, key, args);
697: }
698: if (message == null) {
699: MessageResources messages = getMessages(null);
700: message = messages.getMessage(locale, key, args);
701: }
702: // if it is still null, try removing a prefix
703: int dotPos = key.indexOf('.');
704: if ((message == null) && (dotPos != -1)) {
705: message = getMessage(key.substring(dotPos + 1), args);
706: }
707:
708: if (logger.isDebugEnabled()) {
709: logger
710: .debug("getMessage - end - return value = "
711: + message);
712: }
713: return message;
714: }
715: }
|