From 34f7badcffbf9cecd873d7b3ec5e12b3e74a280f Mon Sep 17 00:00:00 2001 From: felmer <felmer> Date: Tue, 11 Mar 2008 13:38:08 +0000 Subject: [PATCH] LMS-257 BeanUtils.Converter contract extended and tested SVN: 4770 --- .../cisd/common/utilities/BeanUtils.java | 37 ++++++++++++------- .../cisd/common/utilities/BeanUtilsTest.java | 23 +++++++++++- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/BeanUtils.java b/common/source/java/ch/systemsx/cisd/common/utilities/BeanUtils.java index 06abb2ec956..a90fe315a14 100644 --- a/common/source/java/ch/systemsx/cisd/common/utilities/BeanUtils.java +++ b/common/source/java/ch/systemsx/cisd/common/utilities/BeanUtils.java @@ -129,9 +129,15 @@ public final class BeanUtils * Marker interface for converter classes. The real method are determined via reflection. A converter needs to match * both the source and the destination bean. If the destination bean has a setter <code>setFoo(FooClass foo)</code> * and the converter has a method <code>FooClass convertToFoo(SourceBeanClass sourceBean)</code>, then this will - * be called instead of any getter of the <var>sourceBean</var>. Note that if there is a matching method - * <code>convertToFoo()</code>, it needs to have an appropriate return type or else an - * {@link IllegalArgumentException} will be thrown. + * be called instead of any getter of the <var>sourceBean</var>. + * <p> + * Note: + * <ul> + * <li>The declared <code>SourceBeanClass</code> in the converter method can also be a superclass of + * <code>sourceBean</code>or an interface implemented by <code>sourceBean</code> + * <li>If there is a matching method <code>convertToFoo()</code>, it needs to have an appropriate return type or + * else an {@link IllegalArgumentException} will be thrown. + * </ul> */ public interface Converter { @@ -731,20 +737,23 @@ public final class BeanUtils { if (converter != NULL_CONVERTER) { - try + String methodName = "convertTo" + setter.getName().substring(SETTER_PREFIX.length()); + Class<? extends Converter> converterClasss = converter.getClass(); + Collection<Class<?>> classes = ClassUtils.gatherAllCastableClassesAndInterfacesFor(sourceBean); + for (Class<?> clazz : classes) { - String methodName = "convertTo" + setter.getName().substring(SETTER_PREFIX.length()); - Class<? extends Converter> converterClasss = converter.getClass(); - final Method converterMethod = converterClasss.getMethod(methodName, new Class[] - { sourceBean.getClass() }); - if (converterMethod.isAccessible() == false) + try + { + final Method converterMethod = converterClasss.getMethod(methodName, new Class[] { clazz }); + if (converterMethod.isAccessible() == false) + { + converterMethod.setAccessible(true); + } + return converterMethod; + } catch (NoSuchMethodException e) { - converterMethod.setAccessible(true); + // Nothing to do here - there just isn't any converter method for this setter. } - return converterMethod; - } catch (NoSuchMethodException ex) - { - // Nothing to do here - there just isn't any converter method for this setter. } } return null; diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/BeanUtilsTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/BeanUtilsTest.java index 939c6df058a..459f8b32641 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/BeanUtilsTest.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/BeanUtilsTest.java @@ -955,8 +955,13 @@ public final class BeanUtilsTest assertEquals(msg, b2.getI(), b1.getI()); assertEquals(msg, b2.getS(), b1.getS()); } + + private static interface IFoo + { + public String getFoo(); + } - public static class FooBean + public static class FooBean implements IFoo { private String foo; @@ -1001,4 +1006,20 @@ public final class BeanUtilsTest }); assertEquals("some to Foo", toFooBean.getBar()); } + + @Test + public void testConverterWithArgumentOfInterfaceType() + { + final FooBean tofuBean = new FooBean(); + tofuBean.setFoo("some tofu"); + final BarBean toFooBean = BeanUtils.createBean(BarBean.class, tofuBean, new BeanUtils.Converter() + { + @SuppressWarnings("unused") + public String convertToBar(IFoo foo) + { + return StringUtils.replace(foo.getFoo(), "tofu", "to Foo"); + } + }); + assertEquals("some to Foo", toFooBean.getBar()); + } } \ No newline at end of file -- GitLab