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}