001/* 002 * Copyright 2002-2015 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.format.support; 018 019import org.springframework.core.convert.support.DefaultConversionService; 020import org.springframework.format.FormatterRegistry; 021import org.springframework.format.datetime.DateFormatterRegistrar; 022import org.springframework.format.datetime.joda.JodaTimeFormatterRegistrar; 023import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar; 024import org.springframework.format.number.money.CurrencyUnitFormatter; 025import org.springframework.format.number.money.Jsr354NumberFormatAnnotationFormatterFactory; 026import org.springframework.format.number.money.MonetaryAmountFormatter; 027import org.springframework.format.number.NumberFormatAnnotationFormatterFactory; 028import org.springframework.util.ClassUtils; 029import org.springframework.util.StringValueResolver; 030 031/** 032 * A specialization of {@link FormattingConversionService} configured by default with 033 * converters and formatters appropriate for most applications. 034 * 035 * <p>Designed for direct instantiation but also exposes the static {@link #addDefaultFormatters} 036 * utility method for ad hoc use against any {@code FormatterRegistry} instance, just 037 * as {@code DefaultConversionService} exposes its own 038 * {@link DefaultConversionService#addDefaultConverters addDefaultConverters} method. 039 * 040 * <p>Automatically registers formatters for JSR-354 Money & Currency, JSR-310 Date-Time 041 * and/or Joda-Time, depending on the presence of the corresponding API on the classpath. 042 * 043 * @author Chris Beams 044 * @author Juergen Hoeller 045 * @since 3.1 046 */ 047public class DefaultFormattingConversionService extends FormattingConversionService { 048 049 private static final boolean jsr354Present = ClassUtils.isPresent( 050 "javax.money.MonetaryAmount", DefaultFormattingConversionService.class.getClassLoader()); 051 052 private static final boolean jsr310Present = ClassUtils.isPresent( 053 "java.time.LocalDate", DefaultFormattingConversionService.class.getClassLoader()); 054 055 private static final boolean jodaTimePresent = ClassUtils.isPresent( 056 "org.joda.time.LocalDate", DefaultFormattingConversionService.class.getClassLoader()); 057 058 059 /** 060 * Create a new {@code DefaultFormattingConversionService} with the set of 061 * {@linkplain DefaultConversionService#addDefaultConverters default converters} and 062 * {@linkplain #addDefaultFormatters default formatters}. 063 */ 064 public DefaultFormattingConversionService() { 065 this(null, true); 066 } 067 068 /** 069 * Create a new {@code DefaultFormattingConversionService} with the set of 070 * {@linkplain DefaultConversionService#addDefaultConverters default converters} and, 071 * based on the value of {@code registerDefaultFormatters}, the set of 072 * {@linkplain #addDefaultFormatters default formatters}. 073 * @param registerDefaultFormatters whether to register default formatters 074 */ 075 public DefaultFormattingConversionService(boolean registerDefaultFormatters) { 076 this(null, registerDefaultFormatters); 077 } 078 079 /** 080 * Create a new {@code DefaultFormattingConversionService} with the set of 081 * {@linkplain DefaultConversionService#addDefaultConverters default converters} and, 082 * based on the value of {@code registerDefaultFormatters}, the set of 083 * {@linkplain #addDefaultFormatters default formatters} 084 * @param embeddedValueResolver delegated to {@link #setEmbeddedValueResolver(StringValueResolver)} 085 * prior to calling {@link #addDefaultFormatters}. 086 * @param registerDefaultFormatters whether to register default formatters 087 */ 088 public DefaultFormattingConversionService(StringValueResolver embeddedValueResolver, boolean registerDefaultFormatters) { 089 setEmbeddedValueResolver(embeddedValueResolver); 090 DefaultConversionService.addDefaultConverters(this); 091 if (registerDefaultFormatters) { 092 addDefaultFormatters(this); 093 } 094 } 095 096 097 /** 098 * Add formatters appropriate for most environments: including number formatters, 099 * JSR-354 Money & Currency formatters, JSR-310 Date-Time and/or Joda-Time formatters, 100 * depending on the presence of the corresponding API on the classpath. 101 * @param formatterRegistry the service to register default formatters with 102 */ 103 public static void addDefaultFormatters(FormatterRegistry formatterRegistry) { 104 // Default handling of number values 105 formatterRegistry.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory()); 106 107 // Default handling of monetary values 108 if (jsr354Present) { 109 formatterRegistry.addFormatter(new CurrencyUnitFormatter()); 110 formatterRegistry.addFormatter(new MonetaryAmountFormatter()); 111 formatterRegistry.addFormatterForFieldAnnotation(new Jsr354NumberFormatAnnotationFormatterFactory()); 112 } 113 114 // Default handling of date-time values 115 if (jsr310Present) { 116 // just handling JSR-310 specific date and time types 117 new DateTimeFormatterRegistrar().registerFormatters(formatterRegistry); 118 } 119 if (jodaTimePresent) { 120 // handles Joda-specific types as well as Date, Calendar, Long 121 new JodaTimeFormatterRegistrar().registerFormatters(formatterRegistry); 122 } 123 else { 124 // regular DateFormat-based Date, Calendar, Long converters 125 new DateFormatterRegistrar().registerFormatters(formatterRegistry); 126 } 127 } 128 129}