ui.format system refining from RC1 feedback: Support for one format annotation applying to multiple field types, Printer/Parser building blocks for more flexibility, full Joda time formatting support, FormattingService as a service entry-point for clients to use

This commit is contained in:
Keith Donald
2009-10-30 18:44:40 +00:00
parent 471fbf7ebf
commit 913bc03a3b
56 changed files with 1731 additions and 1609 deletions

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.support;
import java.util.Calendar;
import java.util.Date;
import org.springframework.core.convert.converter.Converter;
/**
* Converts from a java.util.Calendar to a java.util.Date.
* @author Keith Donald
*/
final class CalendarToDateConverter implements Converter<Calendar, Date> {
public Date convert(Calendar source) {
return source.getTime();
}
}

View File

@@ -1,35 +0,0 @@
/*
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.support;
import java.util.Calendar;
import java.util.Date;
import org.springframework.core.convert.converter.Converter;
/**
* Converts from a java.util.Date to a java.util.Calendar.
* @author Keith Donald
*/
final class DateToCalendarConverter implements Converter<Date, Calendar> {
public Calendar convert(Date source) {
Calendar cal = Calendar.getInstance();
cal.setTime(source);
return cal;
}
}

View File

@@ -16,8 +16,6 @@
package org.springframework.core.convert.support;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
/**
@@ -38,9 +36,6 @@ public class DefaultConversionService extends GenericConversionService {
addConverter(String.class, Character.class, new StringToCharacterConverter());
addConverter(String.class, Locale.class, new StringToLocaleConverter());
addConverter(Number.class, Character.class, new NumberToCharacterConverter());
addConverter(Date.class, Calendar.class, new DateToCalendarConverter());
addConverter(Calendar.class, Date.class, new CalendarToDateConverter());
JodaTimeConverters.addConverters(this);
addConverter(Object.class, String.class, new ObjectToStringConverter());
addConverterFactory(String.class, Number.class, new StringToNumberConverterFactory());
addConverterFactory(String.class, Enum.class, new StringToEnumConverterFactory());

View File

@@ -42,8 +42,6 @@ import org.springframework.util.ClassUtils;
* @author Keith Donald
* @author Juergen Hoeller
* @since 3.0
* @see #addConverter(Converter)
* @see #addConverterFactory(ConverterFactory)
*/
public class GenericConversionService implements ConversionService, ConverterRegistry {
@@ -53,7 +51,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
}
};
private final Map<Class, Map<Class, GenericConverter>> sourceTypeConverters = new HashMap<Class, Map<Class, GenericConverter>>(36);
private final Map<Class<?>, Map<Class<?>, GenericConverter>> sourceTypeConverters = new HashMap<Class<?>, Map<Class<?>, GenericConverter>>(36);
private ConversionService parent;
@@ -90,8 +88,8 @@ public class GenericConversionService implements ConversionService, ConverterReg
* JavaBean-friendly alternative to calling {@link #addConverter(Converter)}.
* @see #addConverter(Converter)
*/
public void setConverters(Set<Converter> converters) {
for (Converter converter : converters) {
public void setConverters(Set<Converter<?, ?>> converters) {
for (Converter<?, ?> converter : converters) {
addConverter(converter);
}
}
@@ -101,8 +99,8 @@ public class GenericConversionService implements ConversionService, ConverterReg
* JavaBean-friendly alternative to calling {@link #addConverterFactory(ConverterFactory)}.
* @see #addConverterFactory(ConverterFactory)
*/
public void setConverterFactories(Set<ConverterFactory> converters) {
for (ConverterFactory converterFactory : converters) {
public void setConverterFactories(Set<ConverterFactory<?, ?>> converters) {
for (ConverterFactory<?, ?> converterFactory : converters) {
addConverterFactory(converterFactory);
}
}
@@ -124,24 +122,24 @@ public class GenericConversionService implements ConversionService, ConverterReg
// implementing ConverterRegistry
public void addConverter(Converter<?, ?> converter) {
Class[] typeInfo = getRequiredTypeInfo(converter, Converter.class);
Class<?>[] typeInfo = getRequiredTypeInfo(converter, Converter.class);
if (typeInfo == null) {
throw new IllegalArgumentException(
"Unable to the determine sourceType <S> and targetType <T> your Converter<S, T> converts between; declare these types or implement ConverterInfo");
}
Class sourceType = typeInfo[0];
Class targetType = typeInfo[1];
Class<?> sourceType = typeInfo[0];
Class<?> targetType = typeInfo[1];
addConverter(sourceType, targetType, converter);
}
public void addConverterFactory(ConverterFactory<?, ?> converterFactory) {
Class[] typeInfo = getRequiredTypeInfo(converterFactory, ConverterFactory.class);
Class<?>[] typeInfo = getRequiredTypeInfo(converterFactory, ConverterFactory.class);
if (typeInfo == null) {
throw new IllegalArgumentException(
"Unable to the determine sourceType <S> and targetRangeType R your ConverterFactory<S, R> converts between; declare these types or implement ConverterInfo");
}
Class sourceType = typeInfo[0];
Class targetType = typeInfo[1];
Class<?> sourceType = typeInfo[0];
Class<?> targetType = typeInfo[1];
addConverterFactory(sourceType, targetType, converterFactory);
}
@@ -155,6 +153,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
return canConvert(TypeDescriptor.valueOf(sourceType), TypeDescriptor.valueOf(targetType));
}
@SuppressWarnings("unchecked")
public <T> T convert(Object source, Class<T> targetType) {
return (T) convert(source, TypeDescriptor.forObject(source), TypeDescriptor.valueOf(targetType));
}
@@ -279,46 +278,46 @@ public class GenericConversionService implements ConversionService, ConverterReg
Assert.notNull(targetType, "The targetType to convert to is required");
}
private Class[] getRequiredTypeInfo(Object converter, Class genericIfc) {
private Class<?>[] getRequiredTypeInfo(Object converter, Class<?> genericIfc) {
return GenericTypeResolver.resolveTypeArguments(converter.getClass(), genericIfc);
}
private GenericConverter findConverterByClassPair(Class sourceType, Class targetType) {
private GenericConverter findConverterByClassPair(Class<?> sourceType, Class<?> targetType) {
if (sourceType.isInterface()) {
LinkedList<Class> classQueue = new LinkedList<Class>();
LinkedList<Class<?>> classQueue = new LinkedList<Class<?>>();
classQueue.addFirst(sourceType);
while (!classQueue.isEmpty()) {
Class currentClass = classQueue.removeLast();
Map<Class, GenericConverter> converters = getConvertersForSource(currentClass);
Class<?> currentClass = classQueue.removeLast();
Map<Class<?>, GenericConverter> converters = getConvertersForSource(currentClass);
GenericConverter converter = getConverter(converters, targetType);
if (converter != null) {
return converter;
}
Class[] interfaces = currentClass.getInterfaces();
for (Class ifc : interfaces) {
Class<?>[] interfaces = currentClass.getInterfaces();
for (Class<?> ifc : interfaces) {
classQueue.addFirst(ifc);
}
}
Map<Class, GenericConverter> objectConverters = getConvertersForSource(Object.class);
Map<Class<?>, GenericConverter> objectConverters = getConvertersForSource(Object.class);
return getConverter(objectConverters, targetType);
} else {
LinkedList<Class> classQueue = new LinkedList<Class>();
LinkedList<Class<?>> classQueue = new LinkedList<Class<?>>();
classQueue.addFirst(sourceType);
while (!classQueue.isEmpty()) {
Class currentClass = classQueue.removeLast();
Map<Class, GenericConverter> converters = getConvertersForSource(currentClass);
Class<?> currentClass = classQueue.removeLast();
Map<Class<?>, GenericConverter> converters = getConvertersForSource(currentClass);
GenericConverter converter = getConverter(converters, targetType);
if (converter != null) {
return converter;
}
if (currentClass.isArray()) {
Class componentType = ClassUtils.resolvePrimitiveIfNecessary(currentClass.getComponentType());
Class<?> componentType = ClassUtils.resolvePrimitiveIfNecessary(currentClass.getComponentType());
if (componentType.getSuperclass() != null) {
classQueue.addFirst(Array.newInstance(componentType.getSuperclass(), 0).getClass());
}
} else {
Class[] interfaces = currentClass.getInterfaces();
for (Class ifc : interfaces) {
Class<?>[] interfaces = currentClass.getInterfaces();
for (Class<?> ifc : interfaces) {
classQueue.addFirst(ifc);
}
if (currentClass.getSuperclass() != null) {
@@ -330,56 +329,56 @@ public class GenericConversionService implements ConversionService, ConverterReg
}
}
private Map<Class, GenericConverter> getSourceMap(Class sourceType) {
Map<Class, GenericConverter> sourceMap = sourceTypeConverters.get(sourceType);
private Map<Class<?>, GenericConverter> getSourceMap(Class<?> sourceType) {
Map<Class<?>, GenericConverter> sourceMap = sourceTypeConverters.get(sourceType);
if (sourceMap == null) {
sourceMap = new HashMap<Class, GenericConverter>();
sourceMap = new HashMap<Class<?>, GenericConverter>();
this.sourceTypeConverters.put(sourceType, sourceMap);
}
return sourceMap;
}
private Map<Class, GenericConverter> getConvertersForSource(Class sourceType) {
Map<Class, GenericConverter> converters = this.sourceTypeConverters.get(sourceType);
private Map<Class<?>, GenericConverter> getConvertersForSource(Class<?> sourceType) {
Map<Class<?>, GenericConverter> converters = this.sourceTypeConverters.get(sourceType);
if (converters == null) {
converters = Collections.emptyMap();
}
return converters;
}
private GenericConverter getConverter(Map<Class, GenericConverter> converters, Class targetType) {
private GenericConverter getConverter(Map<Class<?>, GenericConverter> converters, Class<?> targetType) {
if (targetType.isInterface()) {
LinkedList<Class> classQueue = new LinkedList<Class>();
LinkedList<Class<?>> classQueue = new LinkedList<Class<?>>();
classQueue.addFirst(targetType);
while (!classQueue.isEmpty()) {
Class currentClass = classQueue.removeLast();
Class<?> currentClass = classQueue.removeLast();
GenericConverter converter = converters.get(currentClass);
if (converter != null) {
return converter;
}
Class[] interfaces = currentClass.getInterfaces();
for (Class ifc : interfaces) {
Class<?>[] interfaces = currentClass.getInterfaces();
for (Class<?> ifc : interfaces) {
classQueue.addFirst(ifc);
}
}
return converters.get(Object.class);
} else {
LinkedList<Class> classQueue = new LinkedList<Class>();
LinkedList<Class<?>> classQueue = new LinkedList<Class<?>>();
classQueue.addFirst(targetType);
while (!classQueue.isEmpty()) {
Class currentClass = classQueue.removeLast();
Class<?> currentClass = classQueue.removeLast();
GenericConverter converter = converters.get(currentClass);
if (converter != null) {
return converter;
}
if (currentClass.isArray()) {
Class componentType = ClassUtils.resolvePrimitiveIfNecessary(currentClass.getComponentType());
Class<?> componentType = ClassUtils.resolvePrimitiveIfNecessary(currentClass.getComponentType());
if (componentType.getSuperclass() != null) {
classQueue.addFirst(Array.newInstance(componentType.getSuperclass(), 0).getClass());
}
} else {
Class[] interfaces = currentClass.getInterfaces();
for (Class ifc : interfaces) {
Class<?>[] interfaces = currentClass.getInterfaces();
for (Class<?> ifc : interfaces) {
classQueue.addFirst(ifc);
}
if (currentClass.getSuperclass() != null) {
@@ -391,11 +390,12 @@ public class GenericConversionService implements ConversionService, ConverterReg
}
}
@SuppressWarnings("unchecked")
private final class ConverterAdapter implements GenericConverter {
private final Converter converter;
public ConverterAdapter(Converter converter) {
public ConverterAdapter(Converter<?, ?> converter) {
this.converter = converter;
}
@@ -407,11 +407,12 @@ public class GenericConversionService implements ConversionService, ConverterReg
}
}
@SuppressWarnings("unchecked")
private final class ConverterFactoryAdapter implements GenericConverter {
private final ConverterFactory converterFactory;
public ConverterFactoryAdapter(ConverterFactory converterFactory) {
public ConverterFactoryAdapter(ConverterFactory<?, ?> converterFactory) {
this.converterFactory = converterFactory;
}

View File

@@ -1,130 +0,0 @@
/*
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.support;
import java.util.Calendar;
import java.util.Date;
import org.joda.time.DateMidnight;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.joda.time.LocalTime;
import org.springframework.core.convert.converter.Converter;
import org.springframework.util.ClassUtils;
class JodaTimeConverters {
public static void addConverters(GenericConversionService registry) {
if (!isJodaTimePresent()) {
return;
}
registry.addConverter(DateTime.class, LocalDate.class, new DateTimeToLocalDateConverter());
registry.addConverter(LocalDate.class, DateTime.class, new LocalDateToDateTimeConverter());
registry.addConverter(DateTime.class, LocalTime.class, new DateTimeToLocalTimeConverter());
registry.addConverter(LocalTime.class, DateTime.class, new LocalTimeToDateTimeConverter());
registry.addConverter(DateTime.class, LocalDateTime.class, new DateTimeToLocalDateTimeConverter());
registry.addConverter(LocalDateTime.class, DateTime.class, new LocalDateTimeToDateTimeConverter());
registry.addConverter(DateTime.class, DateMidnight.class, new DateTimeToDateMidnightConverter());
registry.addConverter(DateMidnight.class, Date.class, new DateMidnightToDateTimeConverter());
registry.addConverter(DateTime.class, Date.class, new DateTimeToDateConverter());
registry.addConverter(Date.class, DateTime.class, new DateToDateTimeConverter());
registry.addConverter(DateTime.class, Calendar.class, new DateTimeToCalendarConverter());
registry.addConverter(Calendar.class, DateTime.class, new CalendarToDateTimeConverter());
}
private static boolean isJodaTimePresent() {
return ClassUtils.isPresent("org.joda.time.DateTime", JodaTimeConverters.class.getClassLoader());
}
private static class DateTimeToLocalDateConverter implements Converter<DateTime, LocalDate> {
public LocalDate convert(DateTime source) {
return source.toLocalDate();
}
}
private static class LocalDateToDateTimeConverter implements Converter<LocalDate, DateTime> {
public DateTime convert(LocalDate source) {
return source.toDateTimeAtStartOfDay();
}
}
private static class DateTimeToLocalTimeConverter implements Converter<DateTime, LocalTime> {
public LocalTime convert(DateTime source) {
return source.toLocalTime();
}
}
private static class LocalTimeToDateTimeConverter implements Converter<LocalTime, DateTime> {
public DateTime convert(LocalTime source) {
return source.toDateTimeToday();
}
}
private static class DateTimeToLocalDateTimeConverter implements Converter<DateTime, LocalDateTime> {
public LocalDateTime convert(DateTime source) {
return source.toLocalDateTime();
}
}
private static class LocalDateTimeToDateTimeConverter implements Converter<LocalDateTime, DateTime> {
public DateTime convert(LocalDateTime source) {
return source.toDateTime();
}
}
private static class DateTimeToDateMidnightConverter implements Converter<DateTime, DateMidnight> {
public DateMidnight convert(DateTime source) {
return source.toDateMidnight();
}
}
private static class DateMidnightToDateTimeConverter implements Converter<DateMidnight, DateTime> {
public DateTime convert(DateMidnight source) {
return source.toDateTime();
}
}
private static class DateTimeToDateConverter implements Converter<DateTime, Date> {
public Date convert(DateTime source) {
return source.toDate();
}
}
private static class DateToDateTimeConverter implements Converter<Date, DateTime> {
public DateTime convert(Date source) {
return new DateTime(source);
}
}
private static class DateTimeToCalendarConverter implements Converter<DateTime, Calendar> {
public Calendar convert(DateTime source) {
return source.toGregorianCalendar();
}
}
private static class CalendarToDateTimeConverter implements Converter<Calendar, DateTime> {
public DateTime convert(Calendar source) {
return new DateTime(source);
}
}
}