You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2013/12/05 16:10:17 UTC

git commit: ISIS-621: further improvements to BigDecimal parsing

Updated Branches:
  refs/heads/master ce5671b1b -> c3d8ca29b


ISIS-621: further improvements to BigDecimal parsing

* prohibit grouping (thousands) separator when enter value
* render thousands separator in view mode
* show decimal places up to scale (eg 123.40 for scale=2)

Implementation notes:
* JavaMathBigDecimalPanelFactory now caches BigDecimalConverterWithScale per scale,
  since each will have different behaviour but is still safe to
  be shared across threads.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/c3d8ca29
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/c3d8ca29
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/c3d8ca29

Branch: refs/heads/master
Commit: c3d8ca29bf27148e3e03a79b00820103099da6a6
Parents: ce5671b
Author: Dan Haywood <da...@apache.org>
Authored: Thu Dec 5 15:01:54 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Thu Dec 5 15:01:54 2013 +0000

----------------------------------------------------------------------
 .../scalars/ScalarPanelTextFieldAbstract.java   |   4 +-
 .../components/scalars/TextFieldAbstract.java   |  42 ++++++
 .../jdkmath/BigDecimalConverterWithScale.java   | 128 +++++++++++++++++
 .../scalars/jdkmath/BigDecimalTextField.java    |  57 ++++++++
 .../jdkmath/JavaMathBigDecimalPanel.java        |  64 +--------
 .../jdkmath/JavaMathBigDecimalPanelFactory.java |  28 +++-
 .../jdkmath/JavaMathBigIntegerPanel.java        |  15 --
 .../jdkmath/BigDecimalConverterTest.java        |  65 ---------
 ...DecimalConverterWithScaleTest_roundtrip.java | 144 +++++++++++++++++++
 9 files changed, 401 insertions(+), 146 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/c3d8ca29/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
index fcc0d90..b9e56cc 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
@@ -108,8 +108,8 @@ public abstract class ScalarPanelTextFieldAbstract<T extends Serializable> exten
      * Optional hook method
      */
     protected void addSemantics() {
-        // we don't call textField.setType(), since in most cases NO does the
-        // parsing, not wicket
+        // we don't call textField.setType(), since we want more control 
+        // over the parsing (using custom subclasses of TextField etc)
     }
 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/c3d8ca29/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/TextFieldAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/TextFieldAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/TextFieldAbstract.java
new file mode 100644
index 0000000..e122037
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/TextFieldAbstract.java
@@ -0,0 +1,42 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.apache.isis.viewer.wicket.ui.components.scalars;
+
+import java.math.BigDecimal;
+
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.util.convert.IConverter;
+import org.apache.wicket.validation.IValidatable;
+import org.apache.wicket.validation.IValidator;
+
+import org.apache.isis.viewer.wicket.model.models.ScalarModel;
+
+public abstract class TextFieldAbstract<T> extends TextField<T> {
+
+    private static final long serialVersionUID = 1L;
+    
+    protected final ScalarModel scalarModel;
+
+    public TextFieldAbstract(final String id, final IModel<T> model, final Class<T> type, final ScalarModel scalarModel) {
+        super(id, model, type);
+        this.scalarModel = scalarModel;
+    }
+    
+    protected abstract IConverter<T> getConverterFor(final ScalarModel scalarModel);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/c3d8ca29/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterWithScale.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterWithScale.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterWithScale.java
new file mode 100644
index 0000000..095a817
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterWithScale.java
@@ -0,0 +1,128 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.apache.isis.viewer.wicket.ui.components.scalars.jdkmath;
+
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.Locale;
+
+import org.apache.wicket.util.convert.ConversionException;
+import org.apache.wicket.util.convert.IConverter;
+import org.apache.wicket.util.convert.converter.AbstractNumberConverter;
+import org.apache.wicket.util.convert.converter.BigDecimalConverter;
+
+/**
+ * The {@link IConverter} implementation that our {@link BigDecimalTextField} delegates to for converting strings into
+ * values. 
+ * 
+ * <p>
+ * We reuse as much of Wicket's {@link BigDecimal} implementation as possible, but overriding where necessary.
+ * Whereas Wicket's own {@link BigDecimalConverter} is (clearly?) intended as a singleton, we actually want multiple
+ * instances, per scale.  The {@link JavaMathBigDecimalPanelFactory} actually takes care of handling this cache,
+ * providing the {@link JavaMathBigDecimalPanel} with an appropriate underlying converter for it to delegate to. 
+ */
+class BigDecimalConverterWithScale extends BigDecimalConverter {
+
+    /**
+     * For {@link JavaMathBigDecimalPanelFactory} to call, so that there is a single instance.
+     */
+    static AbstractNumberConverter<BigDecimal> newThreadSafeConverter(Integer scale) {
+        return new BigDecimalConverterWithScale(scale);
+    }
+
+    private static final long serialVersionUID = 1L;
+    private final Integer scale;
+    
+    BigDecimalConverterWithScale(final Integer scale) {
+        this.scale = scale;
+    }
+
+    /**
+     * Disables thousands separator grouping.
+     */
+    @Override
+    protected NumberFormat newNumberFormat(Locale locale) {
+        NumberFormat numberFormat = NumberFormat.getInstance(locale);
+        numberFormat.setGroupingUsed(false);
+        return numberFormat;
+    }
+    
+    /**
+     * Forces trailing zeros to be rendered. 
+     */
+    @Override
+    public NumberFormat getNumberFormat(final Locale locale)
+    {
+        // we obtain a clone, so is okay to modify it to our purposes.
+        NumberFormat numberFormat = super.getNumberFormat(locale);
+        if(scale != null) {
+            numberFormat.setMaximumFractionDigits(scale);
+            numberFormat.setMinimumFractionDigits(scale);
+        }
+        return numberFormat;
+    }
+    
+    @Override
+    public BigDecimal convertToObject(String valueStr, Locale locale) throws ConversionException {
+        DecimalFormat numberFormat = (DecimalFormat) getNumberFormat(locale);
+        char groupingSeparator = numberFormat.getDecimalFormatSymbols().getGroupingSeparator();
+        
+        if(valueStr.contains(""+groupingSeparator)) {
+            // TODO: this is not actually shown; we see a generic error
+            // need to configure the ConversionException somehow
+            throw new ConversionException("Thousands separator '" + groupingSeparator + "' is not allowed in input");
+        }
+        
+        // could also throw an exception
+        final BigDecimal bd = super.convertToObject(valueStr, locale);
+        
+        if(this.scale != null) {
+            if(bd.scale() > this.scale) {
+                // TODO: this is not actually shown; we see a generic error
+                // need to configure the ConversionException somehow
+                throw new ConversionException("No more than " + this.scale + " digits can be entered after the decimal place");
+            }
+            try {
+                return bd != null ? bd.setScale(this.scale) : null; 
+            } catch(Exception ex) {
+                // TODO: this is not actually shown; we see a generic error
+                // need to configure the ConversionException somehow
+                throw new ConversionException("'" + valueStr + "' is not a valid decimal number.");
+            }
+        } else {
+            return bd;
+        }
+    }
+
+    public IConverter<BigDecimal> forEditMode() {
+        return this;
+    }
+
+    public IConverter<BigDecimal> forViewMode() {
+        return new BigDecimalConverterWithScale(this.scale){
+            private static final long serialVersionUID = 1L;
+            @Override
+            public String convertToString(BigDecimal value, Locale locale) {
+                NumberFormat fmt = BigDecimalConverterWithScale.this.getNumberFormat(locale);
+                fmt.setGroupingUsed(true);// re-enable for view mode
+                return fmt.format(value);
+            }
+        };
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/c3d8ca29/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalTextField.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalTextField.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalTextField.java
new file mode 100644
index 0000000..89ee731
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalTextField.java
@@ -0,0 +1,57 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.apache.isis.viewer.wicket.ui.components.scalars.jdkmath;
+
+import java.math.BigDecimal;
+
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.util.convert.IConverter;
+
+import org.apache.isis.viewer.wicket.model.models.ScalarModel;
+import org.apache.isis.viewer.wicket.ui.components.scalars.TextFieldAbstract;
+
+final class BigDecimalTextField extends TextFieldAbstract<BigDecimal> {
+    
+    private static final long serialVersionUID = 1L;
+    
+    private final BigDecimalConverterWithScale converter;
+
+    BigDecimalTextField(
+            final String id, final IModel<BigDecimal> model, final Class<BigDecimal> type, 
+            final ScalarModel scalarModel, 
+            final BigDecimalConverterWithScale converter) {
+        super(id, model, type, scalarModel);
+        this.converter = converter;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <C> IConverter<C> getConverter(Class<C> type) {
+        if (type != BigDecimal.class) {
+            return super.getConverter(type);
+        } 
+        return (IConverter<C>) getConverterFor(scalarModel);
+    }
+
+    protected IConverter<BigDecimal> getConverterFor(ScalarModel scalarModel) {
+        if(scalarModel.isEditMode()) {
+            return converter.forEditMode();
+        } else {
+            return converter.forViewMode();
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/c3d8ca29/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/JavaMathBigDecimalPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/JavaMathBigDecimalPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/JavaMathBigDecimalPanel.java
index 144b624..e5d7cec 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/JavaMathBigDecimalPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/JavaMathBigDecimalPanel.java
@@ -20,11 +20,8 @@
 package org.apache.isis.viewer.wicket.ui.components.scalars.jdkmath;
 
 import java.math.BigDecimal;
-import java.util.Locale;
 
 import org.apache.wicket.markup.html.form.TextField;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.util.convert.IConverter;
 
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelTextFieldNumeric;
@@ -36,69 +33,16 @@ public class JavaMathBigDecimalPanel extends ScalarPanelTextFieldNumeric<BigDeci
 
     private static final long serialVersionUID = 1L;
     
-    private final IConverter<BigDecimal> threadSafeConverter;
+    private final BigDecimalConverterWithScale converter;
 
-    public JavaMathBigDecimalPanel(final String id, final ScalarModel scalarModel, final IConverter<BigDecimal> threadSafeConverter) {
+    public JavaMathBigDecimalPanel(final String id, final ScalarModel scalarModel, final BigDecimalConverterWithScale converter) {
         super(id, scalarModel, BigDecimal.class);
-        this.threadSafeConverter = threadSafeConverter;
+        this.converter = converter;
     }
  
     protected TextField<BigDecimal> createTextField(final String id) {
         final ScalarModel model = getModel();
-        return new BigDecimalTextField(id, newTextFieldValueModel(), cls, model, threadSafeConverter);
-    }
-    
-    static final class BigDecimalTextField extends TextField<BigDecimal> {
-        
-        private static final long serialVersionUID = 1L;
-        
-        private final ScalarModel scalarModel;
-        private final IConverter<BigDecimal> threadSafeConverter;
-
-        BigDecimalTextField(
-                final String id, final IModel<BigDecimal> model, final Class<BigDecimal> type, 
-                final ScalarModel scalarModel, 
-                final IConverter<BigDecimal> threadSafeConverter) {
-            super(id, model, type);
-            this.scalarModel = scalarModel;
-            this.threadSafeConverter = threadSafeConverter;
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public <C> IConverter<C> getConverter(Class<C> type) {
-            final Integer scale = scalarModel.getScale();
-            if (type != BigDecimal.class) {
-                return super.getConverter(type);
-            } 
-            if (scale == null) {
-                return (IConverter<C>) threadSafeConverter;
-            } 
-            return (IConverter<C>) new ConverterWithScale(scale, threadSafeConverter);
-        }
-    }
-    
-    static final class ConverterWithScale implements IConverter<BigDecimal> {
-        private static final long serialVersionUID = 1L;
-        
-        private final Integer scale;
-        private final IConverter<BigDecimal> converter;
-
-        ConverterWithScale(Integer scale, IConverter<BigDecimal> threadSafeConverter) {
-            this.scale = scale;
-            this.converter = threadSafeConverter;
-        }
-
-        @Override
-        public BigDecimal convertToObject(String valueStr, Locale locale) {
-            final BigDecimal bd = converter.convertToObject(valueStr, locale);
-            return bd != null ? bd.setScale(this.scale) : null; 
-        }
-
-        @Override
-        public String convertToString(BigDecimal value, Locale locale) {
-            return converter.convertToString(value, locale);
-        }
+        return new BigDecimalTextField(id, newTextFieldValueModel(), cls, model, converter);
     }
 }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/c3d8ca29/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/JavaMathBigDecimalPanelFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/JavaMathBigDecimalPanelFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/JavaMathBigDecimalPanelFactory.java
index beaef5a..8473b8e 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/JavaMathBigDecimalPanelFactory.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/JavaMathBigDecimalPanelFactory.java
@@ -20,10 +20,11 @@
 package org.apache.isis.viewer.wicket.ui.components.scalars.jdkmath;
 
 import java.math.BigDecimal;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.wicket.Component;
-import org.apache.wicket.util.convert.IConverter;
-import org.apache.wicket.util.convert.converter.BigDecimalConverter;
+import org.apache.wicket.util.convert.converter.AbstractNumberConverter;
 
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
@@ -36,7 +37,6 @@ public class JavaMathBigDecimalPanelFactory extends ComponentFactoryScalarAbstra
 
     private static final long serialVersionUID = 1L;
 
-    private final IConverter<BigDecimal> threadSafeConverter = new BigDecimalConverter();
     
     public JavaMathBigDecimalPanelFactory() {
         super(JavaMathBigDecimalPanel.class, java.math.BigDecimal.class);
@@ -44,7 +44,27 @@ public class JavaMathBigDecimalPanelFactory extends ComponentFactoryScalarAbstra
 
     @Override
     public Component createComponent(final String id, final ScalarModel scalarModel) {
-        return new JavaMathBigDecimalPanel(id, scalarModel, threadSafeConverter);
+        BigDecimalConverterWithScale converter = getConverter(scalarModel);
+        return new JavaMathBigDecimalPanel(id, scalarModel, converter);
+    }
+
+    
+    // //////////////////////////////////////
+    
+    private final BigDecimalConverterWithScale converterForNullScale = new BigDecimalConverterWithScale(null);
+    private final Map<Integer, BigDecimalConverterWithScale> converterByScale = new ConcurrentHashMap<Integer, BigDecimalConverterWithScale>();
+
+    private BigDecimalConverterWithScale getConverter(final ScalarModel scalarModel) {
+        final Integer scale = scalarModel.getScale();
+        if(scale == null) {
+            return converterForNullScale;
+        } 
+        BigDecimalConverterWithScale bigDecimalConverter = converterByScale.get(scale);
+        if(bigDecimalConverter == null) {
+            bigDecimalConverter = new BigDecimalConverterWithScale(scale);
+            converterByScale.put(scale, bigDecimalConverter);
+        }
+        return bigDecimalConverter;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/c3d8ca29/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/JavaMathBigIntegerPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/JavaMathBigIntegerPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/JavaMathBigIntegerPanel.java
index 2147416..7946a72 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/JavaMathBigIntegerPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/JavaMathBigIntegerPanel.java
@@ -20,12 +20,10 @@
 package org.apache.isis.viewer.wicket.ui.components.scalars.jdkmath;
 
 import java.math.BigInteger;
-import java.util.Locale;
 
 import org.apache.wicket.markup.html.form.AbstractTextComponent;
 import org.apache.wicket.markup.html.form.TextField;
 import org.apache.wicket.util.convert.IConverter;
-import org.apache.wicket.util.convert.converter.AbstractIntegerConverter;
 
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelTextFieldNumeric;
@@ -40,19 +38,6 @@ public class JavaMathBigIntegerPanel extends ScalarPanelTextFieldNumeric<BigInte
     private static final long serialVersionUID = 1L;
     private static final String ID_SCALAR_VALUE = "scalarValue";
     
-    @SuppressWarnings({ "rawtypes", "unused" })
-    private static final IConverter CONVERTER = new AbstractIntegerConverter() {
-        private static final long serialVersionUID = 1L;
-        @Override
-        public Object convertToObject(String value, Locale locale) {
-            return new BigInteger(value);
-        }
-        @Override
-        protected Class<?> getTargetType() {
-            return BigInteger.class;
-        }
-    };
-
     public JavaMathBigIntegerPanel(final String id, final ScalarModel scalarModel) {
         super(id, scalarModel, BigInteger.class);
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/c3d8ca29/component/viewer/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterTest.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterTest.java b/component/viewer/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterTest.java
deleted file mode 100644
index 1501e04..0000000
--- a/component/viewer/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you 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.apache.isis.viewer.wicket.ui.components.scalars.jdkmath;
-
-import java.math.BigDecimal;
-import java.util.Locale;
-
-import org.apache.wicket.util.convert.converter.BigDecimalConverter;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class BigDecimalConverterTest {
-
-    final BigDecimal bd_123_45_scale2 = new BigDecimal("123.45").setScale(2);
-    final BigDecimal bd_123_45_scale4 = new BigDecimal("123.45").setScale(4);
-    final BigDecimal bd_123_4500_scale2 = new BigDecimal("123.4500").setScale(2);
-    final BigDecimal bd_123_4500_scale4 = new BigDecimal("123.4500").setScale(4);
-
-    @Test
-    public void test_scale2() {
-        final BigDecimal actual = new JavaMathBigDecimalPanel.ConverterWithScale(2, new BigDecimalConverter()).convertToObject("123.45", Locale.ENGLISH);
-        Assert.assertEquals(bd_123_4500_scale2, actual);
-        Assert.assertEquals(bd_123_45_scale2, actual);
-        
-        Assert.assertNotEquals(bd_123_4500_scale4, actual);
-        Assert.assertNotEquals(bd_123_45_scale4, actual);
-    }
-    
-    @Test
-    public void test_scale4() {
-        final BigDecimal actual = new JavaMathBigDecimalPanel.ConverterWithScale(4, new BigDecimalConverter()).convertToObject("123.45", Locale.ENGLISH);
-        Assert.assertNotEquals(bd_123_4500_scale2, actual);
-        Assert.assertNotEquals(bd_123_45_scale2, actual);
-        
-        Assert.assertEquals(bd_123_4500_scale4, actual);
-        Assert.assertEquals(bd_123_45_scale4, actual);
-    }
-    
-    @Test
-    public void otherLocale() {
-        final BigDecimal actual = new JavaMathBigDecimalPanel.ConverterWithScale(2, new BigDecimalConverter()).convertToObject("123,45", Locale.ITALIAN);
-        Assert.assertEquals(bd_123_4500_scale2, actual);
-        Assert.assertEquals(bd_123_45_scale2, actual);
-        
-        Assert.assertNotEquals(bd_123_4500_scale4, actual);
-        Assert.assertNotEquals(bd_123_45_scale4, actual);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/c3d8ca29/component/viewer/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterWithScaleTest_roundtrip.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterWithScaleTest_roundtrip.java b/component/viewer/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterWithScaleTest_roundtrip.java
new file mode 100644
index 0000000..5528b61
--- /dev/null
+++ b/component/viewer/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterWithScaleTest_roundtrip.java
@@ -0,0 +1,144 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.isis.viewer.wicket.ui.components.scalars.jdkmath;
+
+import java.math.BigDecimal;
+import java.util.Locale;
+
+import org.apache.wicket.util.convert.ConversionException;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class BigDecimalConverterWithScaleTest_roundtrip {
+
+    final BigDecimal bd_123_45_scale2 = new BigDecimal("123.45").setScale(2);
+    final BigDecimal bd_123_4500_scale2 = new BigDecimal("123.4500").setScale(2);
+
+    final BigDecimal bd_789123_45_scale2 = new BigDecimal("789123.45").setScale(2);
+
+    final BigDecimal bd_123_45_scale4 = new BigDecimal("123.45").setScale(4);
+    final BigDecimal bd_123_4500_scale4 = new BigDecimal("123.4500").setScale(4);
+    
+    private BigDecimalConverterWithScale converter;
+
+    @Rule
+    public ExpectedException exception = ExpectedException.none();
+    
+    @Before
+    public void setUp() throws Exception {
+        converter = newConverter(2);
+    }
+    
+    @Test
+    public void scale2_english() {
+        
+        // when
+        final BigDecimal actual = converter.convertToObject("123.45", Locale.ENGLISH);
+        Assert.assertEquals(bd_123_4500_scale2, actual);
+        Assert.assertEquals(bd_123_45_scale2, actual);
+        
+        Assert.assertNotEquals(bd_123_4500_scale4, actual);
+        Assert.assertNotEquals(bd_123_45_scale4, actual);
+
+        // when
+        String actualStr = converter.convertToString(actual, Locale.ENGLISH);
+        Assert.assertEquals("123.45", actualStr);
+    }
+    
+    @Test
+    public void scale4_english() {
+        converter = newConverter(4);
+        
+        final BigDecimal actual = converter.convertToObject("123.45", Locale.ENGLISH);
+        Assert.assertNotEquals(bd_123_4500_scale2, actual);
+        Assert.assertNotEquals(bd_123_45_scale2, actual);
+        
+        Assert.assertEquals(bd_123_4500_scale4, actual);
+        Assert.assertEquals(bd_123_45_scale4, actual);
+        
+        // when
+        String actualStr = converter.convertToString(actual, Locale.ENGLISH);
+        Assert.assertEquals("123.4500", actualStr);
+    }
+    
+    
+    @Test
+    public void scaleNull_english() {
+        converter = newConverter(null);
+        
+        final BigDecimal actual = converter.convertToObject("123.45", Locale.ENGLISH);
+        Assert.assertEquals(bd_123_4500_scale2, actual);
+        Assert.assertEquals(bd_123_45_scale2, actual);
+        
+        final BigDecimal actual2 = converter.convertToObject("123.4500", Locale.ENGLISH);
+        Assert.assertEquals(bd_123_4500_scale4, actual2);
+        Assert.assertEquals(bd_123_45_scale4, actual2);
+    }
+    
+    
+    @Test
+    public void scale2_italian() {
+        
+        final BigDecimal actual = converter.convertToObject("123,45", Locale.ITALIAN);
+        Assert.assertEquals(bd_123_4500_scale2, actual);
+        Assert.assertEquals(bd_123_45_scale2, actual);
+        
+        Assert.assertNotEquals(bd_123_4500_scale4, actual);
+        Assert.assertNotEquals(bd_123_45_scale4, actual);
+    }
+
+    
+    @Test
+    public void scale2_english_withThousandSeparators() {
+        
+        exception.expect(ConversionException.class);
+        exception.expectMessage("Thousands separator ',' is not allowed in input");
+        
+        converter.convertToObject("789,123.45", Locale.ENGLISH);
+    }
+
+    @Test
+    public void scale2_english_withoutThousandSeparators() {
+        
+        // when
+        final BigDecimal actual = converter.convertToObject("789123.45", Locale.ENGLISH);
+        Assert.assertEquals(bd_789123_45_scale2, actual);
+        
+        // when
+        String actualStr = converter.convertToString(actual, Locale.ENGLISH);
+        Assert.assertEquals("789123.45", actualStr);
+    }
+
+    @Test
+    public void scale2_english_tooLargeScale() {
+        
+        exception.expect(ConversionException.class);
+        exception.expectMessage("No more than 2 digits can be entered after the decimal place");
+        
+        converter.convertToObject("123.454", Locale.ENGLISH);
+    }
+
+    private BigDecimalConverterWithScale newConverter(Integer scale) {
+        return new BigDecimalConverterWithScale(scale);
+    }
+
+}