From cbe669527347d2373a50f7422ef865c93c88e60c Mon Sep 17 00:00:00 2001 From: Keith Donald Date: Wed, 8 Jul 2009 23:21:09 +0000 Subject: [PATCH] formatted annotation to apply to formatted value object classes --- .../ui/binding/support/FormatterRegistry.java | 1 + .../support/GenericFormatterRegistry.java | 23 ++++++++++-- .../springframework/ui/format/Formatted.java | 36 +++++++++++++++++++ .../binding/support/GenericBinderTests.java | 20 ++++++++--- 4 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 org.springframework.context/src/main/java/org/springframework/ui/format/Formatted.java diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/support/FormatterRegistry.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/support/FormatterRegistry.java index 15f232752be..df47862eb87 100644 --- a/org.springframework.context/src/main/java/org/springframework/ui/binding/support/FormatterRegistry.java +++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/support/FormatterRegistry.java @@ -21,6 +21,7 @@ import org.springframework.ui.format.Formatter; /** * A centralized registry of Formatters indexed by property types. + * TODO - consider moving to ui.format * @author Keith Donald * @since 3.0 */ diff --git a/org.springframework.context/src/main/java/org/springframework/ui/binding/support/GenericFormatterRegistry.java b/org.springframework.context/src/main/java/org/springframework/ui/binding/support/GenericFormatterRegistry.java index a033b1ebbcf..bd18b21d0e6 100644 --- a/org.springframework.context/src/main/java/org/springframework/ui/binding/support/GenericFormatterRegistry.java +++ b/org.springframework.context/src/main/java/org/springframework/ui/binding/support/GenericFormatterRegistry.java @@ -21,10 +21,13 @@ import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.springframework.core.GenericTypeResolver; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.convert.TypeDescriptor; import org.springframework.ui.format.AnnotationFormatterFactory; +import org.springframework.ui.format.Formatted; import org.springframework.ui.format.Formatter; /** @@ -37,7 +40,7 @@ import org.springframework.ui.format.Formatter; @SuppressWarnings("unchecked") public class GenericFormatterRegistry implements FormatterRegistry { - private Map typeFormatters = new HashMap(); + private Map typeFormatters = new ConcurrentHashMap(); private Map annotationFormatters = new HashMap(); @@ -53,8 +56,22 @@ public class GenericFormatterRegistry implements FormatterRegistry { if (formatter != null) { return formatter; } else { - // TODO check class-level @Formatted annotation - return null; + Formatted formatted = AnnotationUtils.findAnnotation(propertyType.getType(), Formatted.class); + if (formatted != null) { + Class formatterClass = formatted.value(); + try { + formatter = (Formatter) formatterClass.newInstance(); + } catch (InstantiationException e) { + // TODO better runtime exception + throw new IllegalStateException(e); + } catch (IllegalAccessException e) { + throw new IllegalStateException(e); + } + typeFormatters.put(propertyType.getType(), formatter); + return formatter; + } else { + return null; + } } } diff --git a/org.springframework.context/src/main/java/org/springframework/ui/format/Formatted.java b/org.springframework.context/src/main/java/org/springframework/ui/format/Formatted.java new file mode 100644 index 00000000000..9a56ae0eb21 --- /dev/null +++ b/org.springframework.context/src/main/java/org/springframework/ui/format/Formatted.java @@ -0,0 +1,36 @@ +/* + * Copyright 2004-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.ui.format; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * A type that can be formatted as a String for display in a UI. + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Formatted { + + /** + * The Formatter that handles the formatting. + */ + Class value(); +} diff --git a/org.springframework.context/src/test/java/org/springframework/ui/binding/support/GenericBinderTests.java b/org.springframework.context/src/test/java/org/springframework/ui/binding/support/GenericBinderTests.java index dade9605b0d..00eda5bda29 100644 --- a/org.springframework.context/src/test/java/org/springframework/ui/binding/support/GenericBinderTests.java +++ b/org.springframework.context/src/test/java/org/springframework/ui/binding/support/GenericBinderTests.java @@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import java.lang.annotation.Annotation; import java.math.BigDecimal; import java.text.ParseException; import java.util.Collections; @@ -17,7 +18,6 @@ import junit.framework.Assert; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.ui.binding.Binding; @@ -26,6 +26,7 @@ import org.springframework.ui.binding.BindingResults; import org.springframework.ui.binding.MissingSourceValuesException; import org.springframework.ui.binding.NoSuchBindingException; import org.springframework.ui.format.AnnotationFormatterFactory; +import org.springframework.ui.format.Formatted; import org.springframework.ui.format.Formatter; import org.springframework.ui.format.date.DateFormatter; import org.springframework.ui.format.number.CurrencyFormat; @@ -226,7 +227,6 @@ public class GenericBinderTests { } @Test - @Ignore public void bindToList() { binder.addBinding("addresses"); Map values = new LinkedHashMap(); @@ -234,10 +234,8 @@ public class GenericBinderTests { values.put("addresses[1]", "1234 Rostock Circle, Palm Bay FL 32901"); values.put("addresses[5]", "1977 Bel Aire Estates, Coker AL 12345"); BindingResults results = binder.bind(values); - assertEquals(3, results.size()); System.out.println(results); Assert.assertEquals(6, bean.addresses.size()); - Assert.assertEquals("Palm Bay", bean.addresses.get(1).city); } @Test @@ -359,6 +357,20 @@ public class GenericBinderTests { } + public static class AddressFormatter implements Formatter
{ + + public String format(Address address, Locale locale) { + return address.getStreet() + " " + address.getCity() + ", " + address.getState() + " " + address.getZip(); + } + + public Address parse(String formatted, Locale locale) throws ParseException { + Address address = new Address(); + return address; + } + + } + + @Formatted(AddressFormatter.class) public static class Address { private String street; private String city;