diff --git a/bundles/org.eclipse.core.databinding/META-INF/MANIFEST.MF b/bundles/org.eclipse.core.databinding/META-INF/MANIFEST.MF index 12009435d88..da03b94e727 100644 --- a/bundles/org.eclipse.core.databinding/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.core.databinding/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.core.databinding -Bundle-Version: 1.13.700.qualifier +Bundle-Version: 1.13.800.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Export-Package: org.eclipse.core.databinding;version="1.0.0", diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/conversion/text/NumberToStringConverter.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/conversion/text/NumberToStringConverter.java index 94c425fd7a7..1d422761fc1 100644 --- a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/conversion/text/NumberToStringConverter.java +++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/conversion/text/NumberToStringConverter.java @@ -29,12 +29,6 @@ * The first type parameter of {@link Converter} is set to {@link Object} to * preserve backwards compatibility, but the argument is meant to always be a * {@link Number}. - *

- * This class is a variant of the class with the same name in the parent - * package, but it uses {@code java.text} instead of {@code com.ibm.icu}. - *

- * Methods on this class that don't take an argument number format use ICU if it - * is available on the classpath, otherwise they use {@code java.text}. * * @since 1.9 */ diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/conversion/text/StringToNumberConverter.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/conversion/text/StringToNumberConverter.java index fe7c7ed1178..10af03ae70a 100644 --- a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/conversion/text/StringToNumberConverter.java +++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/conversion/text/StringToNumberConverter.java @@ -33,12 +33,6 @@ * The first type parameter of {@link NumberFormatConverter} is set to * {@link Object} to preserve backwards compatibility, but the argument is meant * to always be a {@link String}. - *

- * This class is a variant of the class with the same name in the parent - * package, but it uses {@code java.text} instead of {@code com.ibm.icu}. - *

- * Methods on this class that don't take an argument number format use ICU if it - * is available on the classpath, otherwise they use {@code java.text}. * * @param The type to which values are converted. * diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/conversion/AbstractNumberToStringConverter.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/conversion/AbstractNumberToStringConverter.java index c23ebc3f007..e71b08c8fcf 100644 --- a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/conversion/AbstractNumberToStringConverter.java +++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/conversion/AbstractNumberToStringConverter.java @@ -13,8 +13,6 @@ ******************************************************************************/ package org.eclipse.core.internal.databinding.conversion; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; import java.math.BigDecimal; import java.math.BigInteger; import java.text.Format; @@ -24,8 +22,7 @@ /** * Converts a Number to a String using Format.format(...). This - * class is thread safe. This class is used to share code between converters - * that are based on ICU and java.text. + * class is thread safe. * * @since 1.9 */ @@ -37,30 +34,6 @@ public class AbstractNumberToStringConverter extends Converter { private boolean fromTypeIsBigInteger; private boolean fromTypeIsBigDecimal; - static Class icuBigDecimal = null; - static Constructor icuBigDecimalCtr = null; - static Class icuDecimalFormat = null; - - { - /* - * If the full ICU4J library is available, we use the ICU BigDecimal class to - * support proper formatting and parsing of java.math.BigDecimal. - * - * The version of ICU NumberFormat (DecimalFormat) included in eclipse excludes - * support for java.math.BigDecimal, and if used falls back to converting as an - * unknown Number type via doubleValue(), which is undesirable. - * - * See Bug #180392. - */ - try { - icuBigDecimal = Class.forName("com.ibm.icu.math.BigDecimal"); //$NON-NLS-1$ - icuBigDecimalCtr = icuBigDecimal.getConstructor(BigInteger.class, int.class); - icuDecimalFormat = Class.forName("com.ibm.icu.text.DecimalFormat"); //$NON-NLS-1$ -// System.out.println("DEBUG: Full ICU4J support state: icuBigDecimal="+(icuBigDecimal != null)+", icuBigDecimalCtr="+(icuBigDecimalCtr != null)); //$NON-NLS-1$ //$NON-NLS-2$ - } catch (ClassNotFoundException | NoSuchMethodException e) { - } - } - /** * Constructs a new instance. *

@@ -123,17 +96,6 @@ public String convert(Object fromObject) { result = numberFormat.format(number); } } else if (fromTypeIsBigDecimal) { - if (icuBigDecimal != null && icuBigDecimalCtr != null && icuDecimalFormat != null - && icuDecimalFormat.isInstance(numberFormat)) { - // Full ICU4J present. Convert java.math.BigDecimal to ICU BigDecimal to format. - // Bug #180392. - BigDecimal o = (BigDecimal) fromObject; - try { - fromObject = icuBigDecimalCtr.newInstance(o.unscaledValue(), Integer.valueOf(o.scale())); - } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) { - } - // Otherwise, replacement plugin present and supports java.math.BigDecimal. - } synchronized (numberFormat) { result = numberFormat.format(fromObject); } diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/conversion/AbstractStringToNumberConverter.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/conversion/AbstractStringToNumberConverter.java index b6ad03f7d67..1a3f34a974f 100644 --- a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/conversion/AbstractStringToNumberConverter.java +++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/conversion/AbstractStringToNumberConverter.java @@ -13,8 +13,6 @@ ******************************************************************************/ package org.eclipse.core.internal.databinding.conversion; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.BigInteger; import java.text.Format; @@ -25,8 +23,7 @@ /** * Converts a String to a Number using Format.parse(...). This - * class is thread safe. This class is used to share code between converters - * that are based on ICU and java.text. + * class is thread safe. * * @param The type to which values are converted. */ @@ -75,32 +72,6 @@ public class AbstractStringToNumberConverter extends NumberFor protected static final Byte MIN_BYTE = Byte.valueOf(Byte.MIN_VALUE); protected static final Byte MAX_BYTE = Byte.valueOf(Byte.MAX_VALUE); - static Class icuBigDecimal = null; - static Method icuBigDecimalScale = null; - static Method icuBigDecimalUnscaledValue = null; - - { - /* - * If the full ICU4J library is available, we use the ICU BigDecimal - * class to support proper formatting and parsing of java.math.BigDecimal. - * - * The version of ICU NumberFormat (DecimalFormat) included in eclipse excludes - * support for java.math.BigDecimal, and if used falls back to converting as - * an unknown Number type via doubleValue(), which is undesirable. - * - * See Bug #180392. - */ - try { - icuBigDecimal = Class.forName("com.ibm.icu.math.BigDecimal"); //$NON-NLS-1$ - icuBigDecimalScale = icuBigDecimal.getMethod("scale"); //$NON-NLS-1$ - icuBigDecimalUnscaledValue = icuBigDecimal.getMethod("unscaledValue"); //$NON-NLS-1$ -/* System.out.println("DEBUG: Full ICU4J support state: icuBigDecimal="+ //$NON-NLS-1$ - (icuBigDecimal != null)+", icuBigDecimalScale="+(icuBigDecimalScale != null)+ //$NON-NLS-1$ - ", icuBigDecimalUnscaledValue="+(icuBigDecimalUnscaledValue != null)); //$NON-NLS-1$ */ - } - catch(ClassNotFoundException | NoSuchMethodException e) {} - } - /** * @param numberFormat used to parse the strings numbers. * @param toType target number type. @@ -194,27 +165,16 @@ public T convert(Object fromObject) { return (T) new BigDecimal((BigInteger) n); } else if(n instanceof BigDecimal) { return (T) n; - } else if(icuBigDecimal != null && icuBigDecimal.isInstance(n)) { - try { - // Get ICU BigDecimal value and use to construct java.math.BigDecimal - int scale = ((Integer) icuBigDecimalScale.invoke(n)).intValue(); - BigInteger unscaledValue = (BigInteger) icuBigDecimalUnscaledValue.invoke(n); - return (T) new java.math.BigDecimal(unscaledValue, scale); - } catch(IllegalAccessException e) { - throw new IllegalArgumentException("Error (IllegalAccessException) converting BigDecimal using ICU"); //$NON-NLS-1$ - } catch(InvocationTargetException e) { - throw new IllegalArgumentException("Error (InvocationTargetException) converting BigDecimal using ICU"); //$NON-NLS-1$ - } } else if(n instanceof Double) { BigDecimal bd = BigDecimal.valueOf(n.doubleValue()); if (bd.scale() == 0) { return (T) bd; } throw new IllegalArgumentException("Non-integral Double value returned from NumberFormat " + //$NON-NLS-1$ - "which cannot be accurately stored in a BigDecimal due to lost precision. " + //$NON-NLS-1$ - "Consider using ICU4J or Java 5 which can properly format and parse these types."); //$NON-NLS-1$ + "which cannot be accurately stored in a BigDecimal due to lost precision."); //$NON-NLS-1$ } - } else if (Short.class.equals(boxedType)) { + } + else if (Short.class.equals(boxedType)) { if (StringToNumberParser.inShortRange(result.getNumber())) { return (T) Short.valueOf(result.getNumber().shortValue()); } diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/conversion/StringToNumberParser.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/conversion/StringToNumberParser.java index 2c9406dbad7..735a7978d11 100644 --- a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/conversion/StringToNumberParser.java +++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/conversion/StringToNumberParser.java @@ -14,14 +14,12 @@ package org.eclipse.core.internal.databinding.conversion; -import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.BigInteger; import java.text.DecimalFormat; import java.text.Format; import java.text.NumberFormat; import java.text.ParsePosition; -import java.util.function.Supplier; import org.eclipse.core.internal.databinding.BindingMessages; @@ -37,12 +35,6 @@ public class StringToNumberParser { private static final BigDecimal DOUBLE_MAX_BIG_DECIMAL = BigDecimal.valueOf(Double.MAX_VALUE); private static final BigDecimal DOUBLE_MIN_BIG_DECIMAL = BigDecimal.valueOf(-Double.MAX_VALUE); - private static final Supplier GET_INSTANCE = findMethod(NumberFormat::getInstance, "getInstance"); //$NON-NLS-1$ - private static final Supplier GET_NUMBER_INSTANCE = findMethod(NumberFormat::getNumberInstance, - "getNumberInstance"); //$NON-NLS-1$ - private static final Supplier GET_INTEGER_INSTANCE = findMethod(NumberFormat::getIntegerInstance, - "getIntegerInstance"); //$NON-NLS-1$ - /** * @return result */ @@ -181,12 +173,6 @@ private static boolean checkInteger(Number number, int bitLength) { } else if (number instanceof BigDecimal) { bigInteger = ((BigDecimal) number).toBigInteger(); } else { - /* - * The else is necessary as the ICU4J plugin has it's own BigDecimal - * implementation which isn't part of the replacement plugin. So - * that this will work we fall back on the double value of the - * number. - */ bigInteger = BigDecimal.valueOf(number.doubleValue()).toBigInteger(); } @@ -241,16 +227,6 @@ private static boolean checkDecimal(Number number, BigDecimal min, } else if (number instanceof BigDecimal) { bigDecimal = (BigDecimal) number; } else { - /* - * The else is necessary as the ICU4J plugin has it's own BigDecimal - * implementation which isn't part of the replacement plugin. So - * that this will work we fall back on the double value of the - * number. - */ - // if this is ever taken out, take care to un-comment the throw - // clause and the if condition below, they were commented because - // the - // compiler complained about dead code.. double doubleValue = number.doubleValue(); if (!Double.isNaN(doubleValue) && !Double.isInfinite(doubleValue)) { @@ -262,9 +238,6 @@ private static boolean checkDecimal(Number number, BigDecimal min, /* if (bigDecimal != null) */return max.compareTo(bigDecimal) >= 0 && min.compareTo(bigDecimal) <= 0; - - // throw new IllegalArgumentException( - // "Number of type [" + number.getClass().getName() + "] is not supported."); //$NON-NLS-1$ //$NON-NLS-2$ } /** @@ -302,24 +275,20 @@ public static boolean inByteRange(Number number) { /** * Returns the default number format. - * {@code com.ibm.icu.text.NumberFormat.getNumberInstance()} if it is available, - * otherwise {@code java.text.NumberFormat.getNumberInstance()}. * * @return the number format */ public static Format getDefaultFormat() { - return GET_INSTANCE.get(); + return NumberFormat.getInstance(); } /** * Returns the default number format. - * {@code com.ibm.icu.text.NumberFormat.getNumberInstance()} if it is available, - * otherwise {@code java.text.NumberFormat.getNumberInstance()}. * * @return the number format */ public static Format getDefaultBigDecimalFormat() { - Format format = GET_NUMBER_INSTANCE.get(); + Format format = NumberFormat.getNumberInstance(); if (format instanceof DecimalFormat) { ((DecimalFormat) format).setParseBigDecimal(true); } @@ -328,59 +297,32 @@ public static Format getDefaultBigDecimalFormat() { /** * Returns the default number format. - * {@code com.ibm.icu.text.NumberFormat.getNumberInstance()} if ICU is - * available, otherwise {@code java.text.NumberFormat.getNumberInstance()}. * * @return the number format */ public static Format getDefaultNumberFormat() { - return GET_NUMBER_INSTANCE.get(); + return NumberFormat.getNumberInstance(); } /** * Returns the default integer format. - * {@code com.ibm.icu.text.NumberFormat.getIntegerInstance()} if ICU is - * available, otherwise {@code java.text.NumberFormat.getIntegerInstance()}. * * @return the number format */ public static Format getDefaultIntegerFormat() { - return GET_INTEGER_INSTANCE.get(); + return NumberFormat.getIntegerInstance(); } /** * Returns the default integer format. - * {@code com.ibm.icu.text.NumberFormat.getIntegerInstance()} if ICU is - * available, otherwise {@code java.text.NumberFormat.getIntegerInstance()}. * * @return the number format */ public static Format getDefaultIntegerBigDecimalFormat() { - Format format = GET_INTEGER_INSTANCE.get(); + Format format = NumberFormat.getIntegerInstance(); if (format instanceof DecimalFormat) { ((DecimalFormat) format).setParseBigDecimal(true); } return format; } - - /** - * Creates a factory for {@link Format}s. The factory uses ICU if it is - * available on the class path, otherwise it uses the given supplier. - */ - private static Supplier findMethod(Supplier javaTextMethod, String methodName) { - try { - Method method = Class.forName("com.ibm.icu.text.NumberFormat").getMethod(methodName); //$NON-NLS-1$ - return () -> { - try { - return (Format) method.invoke(null); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); // Should never happen - } - }; - } catch (ClassNotFoundException | SecurityException e) { - return javaTextMethod; - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); // Should never happen - } - } } diff --git a/docs/JFaceDataBinding.md b/docs/JFaceDataBinding.md index 17add7c31af..3bee98d01ea 100644 --- a/docs/JFaceDataBinding.md +++ b/docs/JFaceDataBinding.md @@ -86,7 +86,7 @@ This page shows you how to create a simple example application using data bindin 6. In the plug-in manifest editor, switch to the 'Dependencies' tab. 7. Under 'Required Plug-ins', click 'Add...'. 8. In the dialog, type '*databinding'. (Note the leading wildcard character.) -9. Multi-select **org.eclipse.core.databinding**, **org.eclipse.core.databinding.beans**, **org.eclipse.core.databinding.property**, **org.eclipse.jface.databinding**, and **com.ibm.icu**, and click 'OK'. +9. Multi-select **org.eclipse.core.databinding**, **org.eclipse.core.databinding.beans**, **org.eclipse.core.databinding.property**, and **org.eclipse.jface.databinding**, and click 'OK'. 10. Save and then close the plug-in manifest editor. 11. Create a new Java package (File > New > Package) and pick a name for it, e.g. 'starting'. 12. Create a new Java class (File > New > Class) in that package, called 'GettingStarted'. @@ -375,7 +375,7 @@ Implementation Design Principles -------------------------------- 1. It's best for the converter to be immutable. This will allow for greater reuse of the instance especially across threads. -2. Synchronize during convert(...) if necessary. A good example of this is using `com.ibm.icu.text.NumberFormat` in a converter. NumberFormat expects to be externally synchronized as the state of NumberFormat changes during formatting and parsing. In order to be used across threads access to the internal NumberFormat must be synchronized. +2. Synchronize during convert(...) if necessary. 3. If the converter is converting to a primitive from an object ensure null is handled. # Validators @@ -497,7 +497,6 @@ For an example snippet, see the [Master Detail snippet](#Snippets). The core Data Binding bundle has the following dependencies: * org.eclipse.equinox.common (about 150 KB). We are currently using Assert, IStatus, and ListenerList from equinox.common, but we might potentially use more classes or interfaces from equinox.common in the future, such as e.g. ISafeRunnable/SafeRunner, IProgressMonitor, and IAdaptable. -* Databinding in Eclipse versions earlier than 4.16 had a dependency on ICU4J. 4.16 and later can use ICU if it is available but does not depend on it. (ICU4J is about 4MB for the real thing, or 100KB for the replacement bundle com.ibm.icu.base which is available from the Eclipse Project download pages.) The data binding framework will run without OSGi. There are optional dependencies on the packages org.osgi.framework, org.osgi.util.tracker, and org.eclipse.osgi.framework.log which allow us to log errors and warnings to the common log if OSGi is available. You can also inject a logger yourself by calling org.eclipse.core.databinding.util.Policy.setLog(), very similar to how this is solved in JFace. diff --git a/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/databinding/conversion/StringToNumberConverterTest.java b/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/databinding/conversion/StringToNumberConverterTest.java index 8ebd2d826ab..4c8e3228976 100644 --- a/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/databinding/conversion/StringToNumberConverterTest.java +++ b/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/databinding/conversion/StringToNumberConverterTest.java @@ -21,6 +21,7 @@ import java.math.BigDecimal; import java.math.BigInteger; +import java.text.DecimalFormat; import java.text.Format; import java.text.NumberFormat; @@ -40,9 +41,10 @@ public class StringToNumberConverterTest { public void setUp() throws Exception { numberFormat = StringToNumberParser.getDefaultNumberFormat(); - // Use reflection to work for both ICU and java.text - numberFormat.getClass().getMethod("setMaximumFractionDigits", int.class).invoke(numberFormat, 305); - numberFormat.getClass().getMethod("setParseBigDecimal", boolean.class).invoke(numberFormat, true); + if (numberFormat instanceof DecimalFormat) { + ((DecimalFormat) numberFormat).setMaximumFractionDigits(305); + ((DecimalFormat) numberFormat).setParseBigDecimal(true); + } numberIntegerFormat = NumberFormat.getIntegerInstance(); }