001/* 002 * Copyright 2012-2018 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 * http://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.boot.convert; 018 019import org.springframework.core.convert.ConversionService; 020import org.springframework.core.convert.converter.ConverterRegistry; 021import org.springframework.core.convert.support.ConfigurableConversionService; 022import org.springframework.core.convert.support.DefaultConversionService; 023import org.springframework.format.FormatterRegistry; 024import org.springframework.format.support.DefaultFormattingConversionService; 025import org.springframework.format.support.FormattingConversionService; 026import org.springframework.util.StringValueResolver; 027 028/** 029 * A specialization of {@link FormattingConversionService} configured by default with 030 * converters and formatters appropriate for most Spring Boot applications. 031 * <p> 032 * Designed for direct instantiation but also exposes the static 033 * {@link #addApplicationConverters} and 034 * {@link #addApplicationFormatters(FormatterRegistry)} utility methods for ad-hoc use 035 * against registry instance. 036 * 037 * @author Phillip Webb 038 * @since 2.0.0 039 */ 040public class ApplicationConversionService extends FormattingConversionService { 041 042 private static volatile ApplicationConversionService sharedInstance; 043 044 public ApplicationConversionService() { 045 this(null); 046 } 047 048 public ApplicationConversionService(StringValueResolver embeddedValueResolver) { 049 if (embeddedValueResolver != null) { 050 setEmbeddedValueResolver(embeddedValueResolver); 051 } 052 configure(this); 053 } 054 055 /** 056 * Return a shared default application {@code ConversionService} instance, lazily 057 * building it once needed. 058 * <p> 059 * Note: This method actually returns an {@link ApplicationConversionService} 060 * instance. However, the {@code ConversionService} signature has been preserved for 061 * binary compatibility. 062 * @return the shared {@code ApplicationConversionService} instance (never 063 * {@code null}) 064 */ 065 public static ConversionService getSharedInstance() { 066 ApplicationConversionService sharedInstance = ApplicationConversionService.sharedInstance; 067 if (sharedInstance == null) { 068 synchronized (ApplicationConversionService.class) { 069 sharedInstance = ApplicationConversionService.sharedInstance; 070 if (sharedInstance == null) { 071 sharedInstance = new ApplicationConversionService(); 072 ApplicationConversionService.sharedInstance = sharedInstance; 073 } 074 } 075 } 076 return sharedInstance; 077 } 078 079 /** 080 * Configure the given {@link FormatterRegistry} with formatters and converters 081 * appropriate for most Spring Boot applications. 082 * @param registry the registry of converters to add to (must also be castable to 083 * ConversionService, e.g. being a {@link ConfigurableConversionService}) 084 * @throws ClassCastException if the given FormatterRegistry could not be cast to a 085 * ConversionService 086 */ 087 public static void configure(FormatterRegistry registry) { 088 DefaultConversionService.addDefaultConverters(registry); 089 DefaultFormattingConversionService.addDefaultFormatters(registry); 090 addApplicationFormatters(registry); 091 addApplicationConverters(registry); 092 } 093 094 /** 095 * Add converters useful for most Spring Boot applications. 096 * @param registry the registry of converters to add to (must also be castable to 097 * ConversionService, e.g. being a {@link ConfigurableConversionService}) 098 * @throws ClassCastException if the given ConverterRegistry could not be cast to a 099 * ConversionService 100 */ 101 public static void addApplicationConverters(ConverterRegistry registry) { 102 addDelimitedStringConverters(registry); 103 registry.addConverter(new StringToDurationConverter()); 104 registry.addConverter(new DurationToStringConverter()); 105 registry.addConverter(new NumberToDurationConverter()); 106 registry.addConverter(new DurationToNumberConverter()); 107 registry.addConverter(new StringToDataSizeConverter()); 108 registry.addConverter(new NumberToDataSizeConverter()); 109 registry.addConverterFactory(new StringToEnumIgnoringCaseConverterFactory()); 110 } 111 112 /** 113 * Add converters to support delimited strings. 114 * @param registry the registry of converters to add to (must also be castable to 115 * ConversionService, e.g. being a {@link ConfigurableConversionService}) 116 * @throws ClassCastException if the given ConverterRegistry could not be cast to a 117 * ConversionService 118 */ 119 public static void addDelimitedStringConverters(ConverterRegistry registry) { 120 ConversionService service = (ConversionService) registry; 121 registry.addConverter(new ArrayToDelimitedStringConverter(service)); 122 registry.addConverter(new CollectionToDelimitedStringConverter(service)); 123 registry.addConverter(new DelimitedStringToArrayConverter(service)); 124 registry.addConverter(new DelimitedStringToCollectionConverter(service)); 125 } 126 127 /** 128 * Add formatters useful for most Spring Boot applications. 129 * @param registry the service to register default formatters with 130 */ 131 public static void addApplicationFormatters(FormatterRegistry registry) { 132 registry.addFormatter(new CharArrayFormatter()); 133 registry.addFormatter(new InetAddressFormatter()); 134 registry.addFormatter(new IsoOffsetFormatter()); 135 } 136 137}