001/* 002 * Copyright 2002-2020 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.NumberFormatAnnotationFormatterFactory; 025import org.springframework.format.number.money.CurrencyUnitFormatter; 026import org.springframework.format.number.money.Jsr354NumberFormatAnnotationFormatterFactory; 027import org.springframework.format.number.money.MonetaryAmountFormatter; 028import org.springframework.lang.Nullable; 029import org.springframework.util.ClassUtils; 030import org.springframework.util.StringValueResolver; 031 032/** 033 * A specialization of {@link FormattingConversionService} configured by default with 034 * converters and formatters appropriate for most applications. 035 * 036 * <p>Designed for direct instantiation but also exposes the static {@link #addDefaultFormatters} 037 * utility method for ad hoc use against any {@code FormatterRegistry} instance, just 038 * as {@code DefaultConversionService} exposes its own 039 * {@link DefaultConversionService#addDefaultConverters addDefaultConverters} method. 040 * 041 * <p>Automatically registers formatters for JSR-354 Money & Currency, JSR-310 Date-Time 042 * and/or Joda-Time 2.x, depending on the presence of the corresponding API on the classpath. 043 * 044 * @author Chris Beams 045 * @author Juergen Hoeller 046 * @since 3.1 047 */ 048public class DefaultFormattingConversionService extends FormattingConversionService { 049 050 private static final boolean jsr354Present; 051 052 private static final boolean jodaTimePresent; 053 054 static { 055 ClassLoader classLoader = DefaultFormattingConversionService.class.getClassLoader(); 056 jsr354Present = ClassUtils.isPresent("javax.money.MonetaryAmount", classLoader); 057 jodaTimePresent = ClassUtils.isPresent("org.joda.time.YearMonth", classLoader); 058 } 059 060 061 /** 062 * Create a new {@code DefaultFormattingConversionService} with the set of 063 * {@linkplain DefaultConversionService#addDefaultConverters default converters} and 064 * {@linkplain #addDefaultFormatters default formatters}. 065 */ 066 public DefaultFormattingConversionService() { 067 this(null, true); 068 } 069 070 /** 071 * Create a new {@code DefaultFormattingConversionService} with the set of 072 * {@linkplain DefaultConversionService#addDefaultConverters default converters} and, 073 * based on the value of {@code registerDefaultFormatters}, the set of 074 * {@linkplain #addDefaultFormatters default formatters}. 075 * @param registerDefaultFormatters whether to register default formatters 076 */ 077 public DefaultFormattingConversionService(boolean registerDefaultFormatters) { 078 this(null, registerDefaultFormatters); 079 } 080 081 /** 082 * Create a new {@code DefaultFormattingConversionService} with the set of 083 * {@linkplain DefaultConversionService#addDefaultConverters default converters} and, 084 * based on the value of {@code registerDefaultFormatters}, the set of 085 * {@linkplain #addDefaultFormatters default formatters}. 086 * @param embeddedValueResolver delegated to {@link #setEmbeddedValueResolver(StringValueResolver)} 087 * prior to calling {@link #addDefaultFormatters}. 088 * @param registerDefaultFormatters whether to register default formatters 089 */ 090 public DefaultFormattingConversionService( 091 @Nullable StringValueResolver embeddedValueResolver, boolean registerDefaultFormatters) { 092 093 if (embeddedValueResolver != null) { 094 setEmbeddedValueResolver(embeddedValueResolver); 095 } 096 DefaultConversionService.addDefaultConverters(this); 097 if (registerDefaultFormatters) { 098 addDefaultFormatters(this); 099 } 100 } 101 102 103 /** 104 * Add formatters appropriate for most environments: including number formatters, 105 * JSR-354 Money & Currency formatters, JSR-310 Date-Time and/or Joda-Time formatters, 106 * depending on the presence of the corresponding API on the classpath. 107 * @param formatterRegistry the service to register default formatters with 108 */ 109 public static void addDefaultFormatters(FormatterRegistry formatterRegistry) { 110 // Default handling of number values 111 formatterRegistry.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory()); 112 113 // Default handling of monetary values 114 if (jsr354Present) { 115 formatterRegistry.addFormatter(new CurrencyUnitFormatter()); 116 formatterRegistry.addFormatter(new MonetaryAmountFormatter()); 117 formatterRegistry.addFormatterForFieldAnnotation(new Jsr354NumberFormatAnnotationFormatterFactory()); 118 } 119 120 // Default handling of date-time values 121 122 // just handling JSR-310 specific date and time types 123 new DateTimeFormatterRegistrar().registerFormatters(formatterRegistry); 124 125 if (jodaTimePresent) { 126 // handles Joda-specific types as well as Date, Calendar, Long 127 new JodaTimeFormatterRegistrar().registerFormatters(formatterRegistry); 128 } 129 else { 130 // regular DateFormat-based Date, Calendar, Long converters 131 new DateFormatterRegistrar().registerFormatters(formatterRegistry); 132 } 133 } 134 135}