diff --git a/framework/src/main/java/de/hsadmin/common/error/TechnicalException.java b/framework/src/main/java/de/hsadmin/common/error/TechnicalException.java index 8f59d6c..8fe349a 100644 --- a/framework/src/main/java/de/hsadmin/common/error/TechnicalException.java +++ b/framework/src/main/java/de/hsadmin/common/error/TechnicalException.java @@ -4,6 +4,10 @@ public class TechnicalException extends Exception { private static final long serialVersionUID = 1L; + public TechnicalException(String message, Exception e) { + super(message, e); + } + public TechnicalException(Exception e) { super(e); } diff --git a/framework/src/main/java/de/hsadmin/common/util/ReflectionUtil.java b/framework/src/main/java/de/hsadmin/common/util/ReflectionUtil.java index 9144bc5..073d530 100644 --- a/framework/src/main/java/de/hsadmin/common/util/ReflectionUtil.java +++ b/framework/src/main/java/de/hsadmin/common/util/ReflectionUtil.java @@ -43,7 +43,7 @@ public class ReflectionUtil { final PropertyDescriptor propertyDescriptor = new PropertyDescriptor(propertyName, anObject.getClass()); return propertyDescriptor.getReadMethod().invoke(anObject); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | IntrospectionException e) { - throw new TechnicalException(e); + throw new TechnicalException("cannot get value from " + anObject + "." + propertyName, e); } } @@ -52,7 +52,7 @@ public class ReflectionUtil { PropertyDescriptor propertyDescriptor = new PropertyDescriptor(propertyName, anObject.getClass()); propertyDescriptor.getWriteMethod().invoke(anObject, value); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | IntrospectionException e) { - throw new TechnicalException(e); + throw new TechnicalException("cannot set " + value + " to " + anObject + "." + propertyName, e); } } diff --git a/framework/src/main/java/de/hsadmin/module/property/BigDecimalProperty.java b/framework/src/main/java/de/hsadmin/module/property/BigDecimalProperty.java new file mode 100644 index 0000000..358520d --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/BigDecimalProperty.java @@ -0,0 +1,33 @@ +package de.hsadmin.module.property; + +import java.math.BigDecimal; + +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.impl.AbstractProperty; +import de.hsadmin.module.property.mapping.DefaultBigDecimalParameterMapMapper; +import de.hsadmin.module.property.mapping.DefaultBigDecimalPersistentObjectMapper; +import de.hsadmin.module.property.mapping.ParameterMapMapper; +import de.hsadmin.module.property.mapping.PersistentObjectMapper; + +public class BigDecimalProperty extends AbstractProperty implements Property { + + private static final PersistentObjectMapper defaultPersistentObjectMapper; + private static final ParameterMapMapper defaultParameterMapMapper; + + static { + defaultPersistentObjectMapper = new DefaultBigDecimalPersistentObjectMapper(); + defaultParameterMapMapper = new DefaultBigDecimalParameterMapMapper(); + } + + public BigDecimalProperty(final ValueObject ownerVO, final String propertyName, final ReadWritePolicy readWritePolicy, final SearchPolicy searchPolicy, final boolean required) { + super(ownerVO, propertyName, readWritePolicy, searchPolicy, required); + setPersistentObjectMapper(defaultPersistentObjectMapper); + setParameterMapMapper(defaultParameterMapMapper); + } + + @Override + public Class getValueType() { + return BigDecimal.class; + } + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultBigDecimalParameterMapMapper.java b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultBigDecimalParameterMapMapper.java new file mode 100644 index 0000000..596fe39 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultBigDecimalParameterMapMapper.java @@ -0,0 +1,38 @@ +package de.hsadmin.module.property.mapping; + +import java.math.BigDecimal; +import java.util.Map; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; + +public class DefaultBigDecimalParameterMapMapper implements ParameterMapMapper { + + @Override + public void writeValueToParameterMap(final Map rpcParameter, + final String propertyName, final BigDecimal value) + throws TechnicalException, UserException { + if (value != null) { + rpcParameter.put(propertyName, value.toString()); + } + } + + @Override + public BigDecimal readValueFromParameterMap(final Map rpcParameter, + final String propertyName, final Class propertyClass) throws TechnicalException, UserException { + final Object object = rpcParameter.get(propertyName); + if (object instanceof BigDecimal) { + return (BigDecimal) object; + } + if (object instanceof String) { + try { + BigDecimal value = new BigDecimal((String) object); + return value; + } catch (NumberFormatException exc) { + throw new TechnicalException("invalid decimal number '" + object + "'", exc); + } + + } + return null; + } +} \ No newline at end of file diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultBigDecimalPersistentObjectMapper.java b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultBigDecimalPersistentObjectMapper.java new file mode 100644 index 0000000..7c9a5fe --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultBigDecimalPersistentObjectMapper.java @@ -0,0 +1,32 @@ +package de.hsadmin.module.property.mapping; + +import java.math.BigDecimal; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.util.ReflectionUtil; + +public class DefaultBigDecimalPersistentObjectMapper implements PersistentObjectMapper { + + @Override + public void writeValueToPersistentObject(final Object persistentObject, final String propertyName, final BigDecimal value) throws TechnicalException { + ReflectionUtil.invokeSetter(persistentObject, propertyName, value); + } + + @Override + public BigDecimal readValueFromPersistentObject(final Object persistentObject, final String propertyName) throws TechnicalException { + final Object object = ReflectionUtil.invokeGetter(persistentObject, propertyName); + if (object instanceof BigDecimal) { + return (BigDecimal) object; + } else { + if (object instanceof String) { + try { + return new BigDecimal((String)object); + } catch ( NumberFormatException exc ) { + throw new TechnicalException(exc); + } + } else { + return null; + } + } + } +} \ No newline at end of file diff --git a/framework/src/test/java/de/hsadmin/module/property/BigDecimalPropertyTest.java b/framework/src/test/java/de/hsadmin/module/property/BigDecimalPropertyTest.java new file mode 100644 index 0000000..2c9fb08 --- /dev/null +++ b/framework/src/test/java/de/hsadmin/module/property/BigDecimalPropertyTest.java @@ -0,0 +1,150 @@ +package de.hsadmin.module.property; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.impl.AbstractVO; +import de.hsadmin.module.property.mapping.DefaultBigDecimalPersistentObjectMapper; +import de.hsadmin.module.property.mapping.DefaultStringParameterMapMapper; +import de.hsadmin.module.property.mapping.Mapping; + +public class BigDecimalPropertyTest { + + private final TestBO testBO = new TestBO(); + + private TestVO testVO; + private Property voPropertyFrontendConverted; + private Property voPropertyBackendConverted; + private Map rpcParameterMap = new HashMap(); + + @Before + @SuppressWarnings("unchecked") + public void init() throws TechnicalException, UserException { + testVO = new TestVO(); + testVO.amountFrontendConverted = new BigDecimal("9876.43"); + testVO.amountBackendConverted = new BigDecimal("1234.56"); + testVO.initPropertyValues(); + + voPropertyFrontendConverted = (Property) testVO.get("amountFrontendConverted"); + voPropertyBackendConverted = (Property) testVO.get("amountBackendConverted"); + } + + @Test + @Ignore("MHOENNIG: muss mit PHORMANNS geklaert werden, warum es diese PersistenceMapper ueberhaupt gibt, scheinen mir sinnlos ") + public void effectivePersistentObjectMapperIsDefaultBigDecimalPersistentObjectMapper() throws TechnicalException, UserException { + // VO -> BO + voPropertyBackendConverted.setValue(new BigDecimal("1234.56")); + // FIXME MHOENNIG->PHORMANNS: + // in writeValueToPersistentObject(...) haette ich die Konvertierung erwartet, + // aber auch beim DefaultDatePersistentObjectMapper ist gerade da keine Konvertierung, + // so nun zunäcsht auch analog beim DefaultBigDecimalPersistentObjectMapper. + voPropertyBackendConverted.copyValueToPersistentObject(testBO); + assertEquals("1234.56", testBO.amountBackendConverted); + + // BO -> VO + testBO.amountBackendConverted = "1111.11"; + voPropertyBackendConverted.copyValueFromPersistentObject(testBO); + assertEquals("1111.11", testVO.amountBackendConverted); + } + + @Test + public void effectiveParameterMapMapperIsDefaultBigDecimalParameterMapMapper() throws TechnicalException, UserException { + // VO -> rpcParameterMap + voPropertyFrontendConverted.setValue(new BigDecimal("1234.56")); + voPropertyFrontendConverted.copyValueToParameterMap(rpcParameterMap);; + assertEquals("1234.56", rpcParameterMap.get("amountFrontendConverted")); + + // rpcParameterMap -> VO + rpcParameterMap.put("amountFrontendConverted", "1111.11"); + voPropertyFrontendConverted.copyValueFromParameterMap(rpcParameterMap); + assertEquals(new BigDecimal("1111.11"), testVO.amountFrontendConverted); + } + + @Test + public void getValueTypeIsBigDecimal() { + assertSame(BigDecimal.class, voPropertyFrontendConverted.getValueType()); + } + + // === test fixture === + + public static class TestVO extends AbstractVO implements ValueObject { + + @ReadWrite(ReadWritePolicy.READWRITE) + @Required(true) + @Search(SearchPolicy.COMPARE) + private BigDecimal amountFrontendConverted; + + @Mapping(boMapping=DefaultBigDecimalPersistentObjectMapper.class, + rpcMapping=DefaultStringParameterMapMapper.class) + @ReadWrite(ReadWritePolicy.READWRITE) + @Required(true) + @Search(SearchPolicy.LIKE) + private BigDecimal amountBackendConverted; + + + public TestVO() throws TechnicalException { + super(); + } + + + public BigDecimal getAmountFrontendConverted() { + return amountFrontendConverted; + } + + + public void setAmountFrontendConverted(BigDecimal amountFrontendConverted) { + this.amountFrontendConverted = amountFrontendConverted; + } + + + public BigDecimal getAmountBackendConverted() { + return amountBackendConverted; + } + + + public void setAmountBackendConverted(BigDecimal amountBackendConverted) { + this.amountBackendConverted = amountBackendConverted; + } + } + + public static class TestBO { + + @ReadWrite(ReadWritePolicy.READWRITE) + @Required(true) + @Search(SearchPolicy.COMPARE) + private BigDecimal amountFrontendConverted; + + @ReadWrite(ReadWritePolicy.READWRITE) + @Required(true) + @Search(SearchPolicy.LIKE) + private String amountBackendConverted; + + public BigDecimal getAmountFrontendConverted() { + return amountFrontendConverted; + } + + public void setAmountFrontendConverted(BigDecimal amountFrontendConverted) { + this.amountFrontendConverted = amountFrontendConverted; + } + + public String getAmountBackendConverted() { + return amountBackendConverted; + } + + public void setAmountBackendConverted(String amountBackendConverted) { + this.amountBackendConverted = amountBackendConverted; + } + + } +} diff --git a/framework/src/test/java/de/hsadmin/module/property/mapping/DefaultBigDecimalParameterMapMapperTest.java b/framework/src/test/java/de/hsadmin/module/property/mapping/DefaultBigDecimalParameterMapMapperTest.java new file mode 100644 index 0000000..df9c8e7 --- /dev/null +++ b/framework/src/test/java/de/hsadmin/module/property/mapping/DefaultBigDecimalParameterMapMapperTest.java @@ -0,0 +1,63 @@ +package de.hsadmin.module.property.mapping; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; + +public class DefaultBigDecimalParameterMapMapperTest { + + private final Map rpcParameters = new HashMap(); + private final DefaultBigDecimalParameterMapMapper defaultBigDecimalParameterMapMapper = new DefaultBigDecimalParameterMapMapper(); + + @Test + public void readValueFromParameterMapWithNumericString() throws TechnicalException, UserException{ + rpcParameters.put("test", "1234.56"); + assertEquals(new BigDecimal("1234.56"), defaultBigDecimalParameterMapMapper.readValueFromParameterMap(rpcParameters, "test", BigDecimal.class)); + } + + @Test(expected=TechnicalException.class) + public void readValueFromParameterMapWithNonNumericString() throws TechnicalException, UserException{ + rpcParameters.put("test", "not a number"); + defaultBigDecimalParameterMapMapper.readValueFromParameterMap(rpcParameters, "test", BigDecimal.class); + } + + @Test(expected=TechnicalException.class) + public void readValueFromParameterMapWithNumericStringWithGarbage() throws TechnicalException, UserException{ + rpcParameters.put("test", "1234x"); + defaultBigDecimalParameterMapMapper.readValueFromParameterMap(rpcParameters, "test", BigDecimal.class); + } + + @Test + public void readValueFromParameterMapWithBigDecimal() throws TechnicalException, UserException{ + rpcParameters.put("test", new BigDecimal("1234.56")); + assertEquals(new BigDecimal("1234.56"), defaultBigDecimalParameterMapMapper.readValueFromParameterMap(rpcParameters, "test", BigDecimal.class)); + } + + @Test + public void readValueFromParameterMapWithBigOther() throws TechnicalException, UserException{ + rpcParameters.put("test", new Date()); + assertNull(defaultBigDecimalParameterMapMapper.readValueFromParameterMap(rpcParameters, "test", BigDecimal.class)); + } + + @Test + public void writeValueToParameterMap() throws TechnicalException, UserException{ + defaultBigDecimalParameterMapMapper.writeValueToParameterMap(rpcParameters, "test", new BigDecimal("9876.64")); + assertEquals("9876.64", rpcParameters.get("test")); + } + + @Test + public void writeNullValueToParameterMap() throws TechnicalException, UserException{ + defaultBigDecimalParameterMapMapper.writeValueToParameterMap(rpcParameters, "test", null); + assertFalse(rpcParameters.containsKey("test")); + } +} diff --git a/framework/src/test/java/de/hsadmin/module/property/mapping/DefaultBigDecimalPersistentObjectMapperTest.java b/framework/src/test/java/de/hsadmin/module/property/mapping/DefaultBigDecimalPersistentObjectMapperTest.java new file mode 100644 index 0000000..c042261 --- /dev/null +++ b/framework/src/test/java/de/hsadmin/module/property/mapping/DefaultBigDecimalPersistentObjectMapperTest.java @@ -0,0 +1,62 @@ +package de.hsadmin.module.property.mapping; + +import static org.junit.Assert.assertEquals; + +import java.math.BigDecimal; + +import org.junit.Test; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; + +public class DefaultBigDecimalPersistentObjectMapperTest { + + private DefaultBigDecimalPersistentObjectMapper mapper = new DefaultBigDecimalPersistentObjectMapper(); + + @Test + public void readValueFromPersistentObjectHavingEnum() throws TechnicalException, UserException { + SomeBO persistentObject = new SomeBO(new BigDecimal("1234.56")); + assertEquals( new BigDecimal("1234.56"), mapper.readValueFromPersistentObject(persistentObject, "someBigDecimalProp")); + } + + @Test + public void readValueFromPersistentObjectHavingString() throws TechnicalException, UserException { + SomeBO persistentObject = new SomeBO(new BigDecimal("9876.54")); + assertEquals( new BigDecimal("9876.54"), mapper.readValueFromPersistentObject(persistentObject, "someStringProp")); + } + + @Test + public void writeValueToPersistentObject() throws TechnicalException, UserException { + SomeBO persistentObject = new SomeBO(new BigDecimal(0)); + mapper.writeValueToPersistentObject(persistentObject, "someBigDecimalProp", new BigDecimal("3333.44") ); + assertEquals(new BigDecimal("3333.44"), persistentObject.getSomeBigDecimalProp()); + } + + public static class SomeBO { + + private BigDecimal someBigDecimalProp; + private String someStringProp; + + public SomeBO(BigDecimal someProp) { + this.someBigDecimalProp = someProp; + this.someStringProp = someProp.toString(); + } + + public BigDecimal getSomeBigDecimalProp() { + return someBigDecimalProp; + } + + public void setSomeBigDecimalProp(BigDecimal someProp) { + this.someBigDecimalProp = someProp; + } + + public String getSomeStringProp() { + return someStringProp; + } + + public void setSomeStringProp(String someStringProp) { + this.someStringProp = someStringProp; + } + } + +}