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}