1 /* 2 * Copyright 2002-2011 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.springframework.format.support; 18 19 import java.util.Calendar; 20 import java.util.Collections; 21 import java.util.Date; 22 import java.util.HashSet; 23 import java.util.Set; 24 25 import org.springframework.core.convert.support.DefaultConversionService; 26 import org.springframework.format.AnnotationFormatterFactory; 27 import org.springframework.format.FormatterRegistry; 28 import org.springframework.format.Parser; 29 import org.springframework.format.Printer; 30 import org.springframework.format.annotation.DateTimeFormat; 31 import org.springframework.format.datetime.joda.JodaTimeFormatterRegistrar; 32 import org.springframework.format.number.NumberFormatAnnotationFormatterFactory; 33 import org.springframework.util.ClassUtils; 34 import org.springframework.util.StringValueResolver; 35 36 /** 37 * A specialization of {@link FormattingConversionService} configured by default with 38 * converters and formatters appropriate for most applications. 39 * 40 * <p>Designed for direct instantiation but also exposes the static {@link #addDefaultFormatters} 41 * utility method for ad hoc use against any {@code FormatterRegistry} instance, just 42 * as {@code DefaultConversionService} exposes its own 43 * {@link DefaultConversionService#addDefaultConverters addDefaultConverters} method. 44 * 45 * @author Chris Beams 46 * @since 3.1 47 */ 48 public class DefaultFormattingConversionService extends FormattingConversionService { 49 50 private static final boolean jodaTimePresent = ClassUtils.isPresent( 51 "org.joda.time.LocalDate", DefaultFormattingConversionService.class.getClassLoader()); 52 53 /** 54 * Create a new {@code DefaultFormattingConversionService} with the set of 55 * {@linkplain DefaultConversionService#addDefaultConverters default converters} and 56 * {@linkplain #addDefaultFormatters default formatters}. 57 */ DefaultFormattingConversionService()58 public DefaultFormattingConversionService() { 59 this(null, true); 60 } 61 62 /** 63 * Create a new {@code DefaultFormattingConversionService} with the set of 64 * {@linkplain DefaultConversionService#addDefaultConverters default converters} and, 65 * based on the value of {@code registerDefaultFormatters}, the set of 66 * {@linkplain #addDefaultFormatters default formatters}. 67 * @param registerDefaultFormatters whether to register default formatters 68 */ DefaultFormattingConversionService(boolean registerDefaultFormatters)69 public DefaultFormattingConversionService(boolean registerDefaultFormatters) { 70 this(null, registerDefaultFormatters); 71 } 72 73 /** 74 * Create a new {@code DefaultFormattingConversionService} with the set of 75 * {@linkplain DefaultConversionService#addDefaultConverters default converters} and, 76 * based on the value of {@code registerDefaultFormatters}, the set of 77 * {@linkplain #addDefaultFormatters default formatters} 78 * @param embeddedValueResolver delegated to {@link #setEmbeddedValueResolver(StringValueResolver)} 79 * prior to calling {@link #addDefaultFormatters}. 80 * @param registerDefaultFormatters whether to register default formatters 81 */ DefaultFormattingConversionService(StringValueResolver embeddedValueResolver, boolean registerDefaultFormatters)82 public DefaultFormattingConversionService(StringValueResolver embeddedValueResolver, boolean registerDefaultFormatters) { 83 this.setEmbeddedValueResolver(embeddedValueResolver); 84 DefaultConversionService.addDefaultConverters(this); 85 if (registerDefaultFormatters) { 86 addDefaultFormatters(this); 87 } 88 } 89 90 /** 91 * Add formatters appropriate for most environments, including number formatters and a Joda-Time 92 * date formatter if Joda-Time is present on the classpath. 93 * @param formatterRegistry the service to register default formatters against 94 */ addDefaultFormatters(FormatterRegistry formatterRegistry)95 public static void addDefaultFormatters(FormatterRegistry formatterRegistry) { 96 formatterRegistry.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory()); 97 if (jodaTimePresent) { 98 new JodaTimeFormatterRegistrar().registerFormatters(formatterRegistry); 99 } else { 100 formatterRegistry.addFormatterForFieldAnnotation(new NoJodaDateTimeFormatAnnotationFormatterFactory()); 101 } 102 } 103 104 105 /** 106 * Dummy AnnotationFormatterFactory that simply fails if @DateTimeFormat is being used 107 * without the JodaTime library being present. 108 */ 109 private static final class NoJodaDateTimeFormatAnnotationFormatterFactory 110 implements AnnotationFormatterFactory<DateTimeFormat> { 111 112 private final Set<Class<?>> fieldTypes; 113 NoJodaDateTimeFormatAnnotationFormatterFactory()114 public NoJodaDateTimeFormatAnnotationFormatterFactory() { 115 Set<Class<?>> rawFieldTypes = new HashSet<Class<?>>(4); 116 rawFieldTypes.add(Date.class); 117 rawFieldTypes.add(Calendar.class); 118 rawFieldTypes.add(Long.class); 119 this.fieldTypes = Collections.unmodifiableSet(rawFieldTypes); 120 } 121 getFieldTypes()122 public Set<Class<?>> getFieldTypes() { 123 return this.fieldTypes; 124 } 125 getPrinter(DateTimeFormat annotation, Class<?> fieldType)126 public Printer<?> getPrinter(DateTimeFormat annotation, Class<?> fieldType) { 127 throw new IllegalStateException("JodaTime library not available - @DateTimeFormat not supported"); 128 } 129 getParser(DateTimeFormat annotation, Class<?> fieldType)130 public Parser<?> getParser(DateTimeFormat annotation, Class<?> fieldType) { 131 throw new IllegalStateException("JodaTime library not available - @DateTimeFormat not supported"); 132 } 133 } 134 135 } 136