Formatting Reference
Stripes' philosophy when it comes to formatting is pretty simple:
- Formatting should be easy (duh)
- Formatting should occur on the page, not in the ActionBean or business code
- Formatting should be localized
- Formatting should be easy to extend
To that end, formatting is accomplished using a couple of additional attributes on the set of Stripes tags that have the ability to display data (i.e. form input tags such as text, textarea etc.). Stripes does not supply formatting capabilities outside of form fields - JSTL has a bunch of pretty good formatting tags, and there's no reason to duplicate any of the functionality.
Speaking of JSTL, if you are familiar with the JSTL formatting tags, the Stripes formatting system should feel quite familiar. That's done on purpose. Stripes uses the java.text.DateFormat and java.text.NumberFormat to do most of the actual formatting. The main difference is how you specify formatting parameters - JSTL has specific tags to do formatting of numbers and dates, whereas Stripes has the need to add formatting to a set of input tags.
Using Formatting
You might think that an appropriate first question is how do I use formatting? But you'd be wrong! The Stripes input tags engage the formatting system every time they write a value out to the page. They do this as follows:
- Determine the type of object being output (String, Date, Number, Other?)
- Ask the FormatterFactory for a Formatter instance that can format the relevant type
- If there is a
Formatter
invoke it to format the object, otherwise useString.valueOf()
Other than the object itself, formatting in Stripes is driven by two parameters (supplied as attributes on the Stripes input tags). The parameters are formatType
and formatPattern
. formatType
is used to specify the type of information which should be output from the source object (e.g. for a java.util.Date
object, should it be date, time or both). formatPattern
can be either one of a set of named styles, or an explicit pattern as understood by the underlying java.text.Format
object. This will all make a bit more sense in the context of the two concrete Formatters supplied with Stripes.
When one or both of formatType
and formatPattern
are not supplied, the Formatter
being used must decide what to do. In the case of the NumberFormatter
and DateFormatter
included with Stripes they simply use the default java.text.NumberFormat
and java.text.DateFormat
for the Locale being used for the request.
Formatting Dates
Formatting of Date objects (java.util.Date
and subclasses) is done using an instance of DateFormatter. It accepts the following values for formatType
:
formatType | Description |
---|---|
date | Output only Date information, and no time information, e.g. Sep 3 2005. (Default) |
time | Output only Time information, and no date information, e.g. 18:24. |
datetime | Output both Date and Time information, e.g. Sep 3 2005, 18:24 |
The following named styles (in addition to custom patterns) may be supplied as the formatPattern
:
formatPattern | Description |
---|---|
short | Output information in as compact a manner as possible form. Maps to |
medium | Output information in a concise, slightly less compact form. Maps to |
long | Output information in a fairly verbose form. Maps to |
full | Output information in an extremely verbose form. Maps to |
A few things to be aware of:
- The output format using the named styles can vary according to locale
- You may use any pattern understood by java.text.SimpleDateFormat in addition to the named styles enumerated above
- If you specify a format pattern that includes date and/or time segments, this override the
formatType
parameter - your pattern will be used verbatim
Formatting Numbers
Formatting of Number objects (anything extending java.lang.Number or the primitive number types) is done using an instance of NumberFormatter. It accepts the following values for formatType
formatType | Description |
---|---|
number | Output the value as a regular number (Default) |
currency | Output the value as a currency amount, using the symbols for the current locale |
percentage | Output the value as a percentage (multiply by 100 and attach the % sign) |
The following named styles (in addition to custom patterns) may be supplied as the formatPattern
:
formatPattern | Description |
---|---|
plain | Output the value in a manner similar to that produced by |
integer | Outputs the value with grouping characters appropriate for the current locale, without a decimal separator and any fractional values. Despite the name (or rather the co-option of integer, by programming languages, to mean something more specific) the integer formatPattern can be used with any numeric type. E.g. 123456789.12 in the en_us locale would be output as 123,456,789. |
decimal | Outputs the value with grouping characters appropriate for the current locale, with a decimal fraction at least 2 digits long, and at most 6 digits long. E.g. 1234 in the en_us locale would be output as 1,234.00. |
A few things to be aware of:
- The output format using the named styles can vary according to locale
- You may use any pattern understood by java.text.DecimalFormat in addition to the named styles enumerated above
Using formatting outside of tags
The only place that Stripes integrates formatting is in the tags. But this doesn't mean that it's the only place you can use it! If you find yourself wanting to format objects somewhere in your Java code, all you have to do is call StripesFilter.getConfiguration().getFormatterFactory()
and you have full access to the formatting system.
Extending Formatting
To extend or modify the way formatting is performed will require an understanding of the formatting system. Luckily that's not hard to come by. Stripes uses a configured FormatterFactory to locate instances of the Formatter interface. It's probably worth spending a few minutes reading the javadoc for those interfaces.
Stripes supplies a DefaultFormatterFactory which knows how to supply the built in Date and Number formatters based on the inputs provided. In order to integrate a new formatter, or to substitute a different formatter for Date or Number types, you will have to provide your own implementation of FormatterFactory
. This is easily done by subclassing DefaultFormatterFactory
and overriding getFormatter()
to perform any specific lookups and then delegating to super.getFormatter()
. You are, of course, free to directly implement FormatterFactory
, just bare in mind that if you do this you will need to handle the lookups for Date and Number types too.
Now all that's left is implementing your own Formatter
class. This is a relatively simple operation. Remember that as your inputs you will receive an object to be formatted, a Locale
, a formatType
and a formatPattern
. You may choose to use, or ignore as many of these parameters as you see fit. The following is an example of a custom Formatter for formatting social security numbers:
public class SsnFormatter implements Formatter<Ssn> { private String formatType; /** Sets the format type to be used to render Ssns as Strings. */ public void setFormatType(String formatType) { this.formatType = formatType; } public void setFormatPattern(String formatPattern) { // SsnFormatter doesn't use format-pattern } public void setLocale(Locale locale) { // Ssn's are US specific, so no locale support either } /** Sets defaults if a formatType was not supplied. */ public void init() { if (this.formatType == null) { this.formatType = "lastfour"; } } /** Formats the Ssn supplied as a String. */ public String format(Ssn ssn) { if ("lastfour".equals(this.formatType)) { return "###-##-" + ssn.getLastFourDigits(); } else if ("allnine".equals(this.formatType)) { return ssn.getDigits(0,3) + "-" + ssn.getDigits(3,5) + "-" + ssn.getLastFourDigits(); } } }