Class MessageFmt

java.lang.Object
org.dellroad.stuff.text.MessageFmt
All Implemented Interfaces:
SelfValidating

@SelfValidates public class MessageFmt extends Object implements SelfValidating
POJO representing a MessageFormat that models its internal structure, supporting arbitrary recursive nesting of MessageFormat with ChoiceFormat.

The point of this class is to make it easier to work with MessageFormat instances by allowing for structural introspection and eliminating complex quoting/escaping issues.

Locales

Unlike the MessageFormat class, instances of MessageFmt do not have an associated Locale; they represent the structure of the format string only. However, some of that structure may implicitly refer to Locale-provided defaults; for example, a MessageFmt.CurrencyArgumentSegment means "format as currency using NumberFormat.getCurrencyInstance(Locale)", which produces a different result depending on the Locale. So, in contrast to MessageFormat, the Locale to be used is always provided separately.

Having said that, it is possible to create MessageFmt instances that "capture" any Locale defaults at the time of construction and therefore avoid the use of Locale-dependent segments such as MessageFmt.CurrencyArgumentSegment; see MessageFmt(MessageFormat, boolean) for details.

Classes are annotated to support JSR 303 validation.

  • Constructor Details

    • MessageFmt

      public MessageFmt()
      Default constructor.

      Creates an empty instance.

    • MessageFmt

      public MessageFmt(MessageFmt.Segment... segments)
      Create an instance from explicitly given MessageFmt.Segments.
      Parameters:
      segments - message components
      Throws:
      IllegalArgumentException - if segments or any element thereof is null
    • MessageFmt

      public MessageFmt(MessageFormat format)
      Create an instance modeling the given MessageFormat.

      Equivalent to: MessageFmt(format, false).

      Parameters:
      format - source message format
      Throws:
      IllegalArgumentException - if format is null
    • MessageFmt

      public MessageFmt(MessageFormat format, boolean captureLocaleDefaults)
      Create an instance modeling the given MessageFormat with optional capturing of Locale defaults.

      The captureLocaleDefaults parameter controls whether MessageFmt.FormatArgumentSegments that refer to Locale defaults are allowed. Such segments produce different results depending on the locale; see FormatArgumentSegment.of(). If captureLocaleDefaults is true, these implicit locale-dependent formats are not allowed; instead the actual formats are captured whenever possible.

      Here's a concrete example:

      
       final Object[] args = new Object[] { new Date(1590000000000L) };         // May 20, 2020
      
       final MessageFormat messageFormat = new MessageFormat("date = {0,date,short}", Locale.US);
      
       System.out.println("messageFormat -> " + messageFormat.format(args));
      
       final MessageFmt messageFmt1 = new MessageFmt(messageFormat, false);     // leave "date,short" alone; bind to locale later
       final MessageFmt messageFmt2 = new MessageFmt(messageFormat, true);      // capture "date,short" in Locale.US
      
       System.out.println("messageFmt1.toPattern() = " + messageFmt1.toPattern());
       System.out.println("messageFmt2.toPattern() = " + messageFmt2.toPattern());
      
       final MessageFormat messageFormat1 = messageFmt1.toMessageFormat(Locale.FRANCE);
       final MessageFormat messageFormat2 = messageFmt2.toMessageFormat(Locale.FRANCE);
      
       System.out.println("messageFormat1 -> " + messageFormat1.format(args));
       System.out.println("messageFormat2 -> " + messageFormat2.format(args));
       
      This would produce the following output:
       messageFormat -> date = 5/20/20
       messageFmt1.toPattern() = date = {0,date,short}
       messageFmt2.toPattern() = date = {0,date,M/d/yy}
       messageFormat1 -> date = 20/05/20
       messageFormat2 -> date = 5/20/20
       

      Note that regardless of captureLocaleDefaults, some MessageFormat arguments are always Locale-dependent. For example, a simple argument parameter like {0}, when applied to a numerical argument, is always formatted using the Locale default number format.

      Parameters:
      format - source message format
      captureLocaleDefaults - true to capture locale defaults, false to allow implicit locale defaults
      Throws:
      IllegalArgumentException - if format is null
      RuntimeException - if reflective access into MessageFormat is denied
      See Also:
  • Method Details