diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/ConverterManagerImpl.java b/xml/dom-impl/src/com/intellij/util/xml/impl/ConverterManagerImpl.java index 744e61236661..da2ad13580e8 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/impl/ConverterManagerImpl.java +++ b/xml/dom-impl/src/com/intellij/util/xml/impl/ConverterManagerImpl.java @@ -19,9 +19,12 @@ import com.intellij.openapi.paths.PathReference; import com.intellij.util.containers.ConcurrentInstanceMap; import com.intellij.util.xml.*; import com.intellij.util.xml.converters.PathReferenceConverter; +import com.intellij.util.xml.converters.values.NumberValueConverter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.math.BigDecimal; +import java.math.BigInteger; import java.util.HashMap; import java.util.Map; @@ -43,10 +46,30 @@ class ConverterManagerImpl implements ConverterManager { private final Map mySimpleConverters = new HashMap<>(); ConverterManagerImpl() { - mySimpleConverters.put(int.class, Converter.INTEGER_CONVERTER); - mySimpleConverters.put(Integer.class, Converter.INTEGER_CONVERTER); + mySimpleConverters.put(byte.class, new NumberValueConverter<>(byte.class, false)); + mySimpleConverters.put(Byte.class, new NumberValueConverter<>(Byte.class, true)); + + mySimpleConverters.put(short.class, new NumberValueConverter<>(short.class, false)); + mySimpleConverters.put(Short.class, new NumberValueConverter<>(Short.class, true)); + + mySimpleConverters.put(int.class, new NumberValueConverter<>(int.class, false)); + mySimpleConverters.put(Integer.class, new NumberValueConverter<>(Integer.class, false)); + + mySimpleConverters.put(long.class, new NumberValueConverter<>(long.class, false)); + mySimpleConverters.put(Long.class, new NumberValueConverter<>(Long.class, true)); + + mySimpleConverters.put(float.class, new NumberValueConverter<>(float.class, false)); + mySimpleConverters.put(Float.class, new NumberValueConverter<>(Float.class, true)); + + mySimpleConverters.put(double.class, new NumberValueConverter<>(double.class, false)); + mySimpleConverters.put(Double.class, new NumberValueConverter<>(Double.class, true)); + + mySimpleConverters.put(BigDecimal.class, new NumberValueConverter<>(BigDecimal.class, true)); + mySimpleConverters.put(BigInteger.class, new NumberValueConverter<>(BigInteger.class, true)); + mySimpleConverters.put(boolean.class, ResolvingConverter.BOOLEAN_CONVERTER); mySimpleConverters.put(Boolean.class, ResolvingConverter.BOOLEAN_CONVERTER); + mySimpleConverters.put(String.class, Converter.EMPTY_CONVERTER); mySimpleConverters.put(Object.class, Converter.EMPTY_CONVERTER); mySimpleConverters.put(PathReference.class, PathReferenceConverter.INSTANCE); diff --git a/xml/dom-openapi/src/com/intellij/util/xml/converters/values/NumberValueConverter.java b/xml/dom-openapi/src/com/intellij/util/xml/converters/values/NumberValueConverter.java index bf24b6b9cc3d..eab573fc7555 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/converters/values/NumberValueConverter.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/converters/values/NumberValueConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2017 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,46 +28,80 @@ import java.math.BigInteger; import java.util.Collection; import java.util.Collections; -public class NumberValueConverter extends ResolvingConverter { +public class NumberValueConverter extends ResolvingConverter { private final Class myNumberClass; private final boolean myAllowEmpty; - - public NumberValueConverter(@NotNull final Class numberClass, final boolean allowEmpty) { + public NumberValueConverter(@NotNull final Class numberClass, final boolean allowEmpty) { myNumberClass = numberClass; myAllowEmpty = allowEmpty; } @Override - public String fromString(@Nullable @NonNls final String s, final ConvertContext context) { + public T fromString(@Nullable @NonNls final String s, final ConvertContext context) { if (s == null) return null; - if (myAllowEmpty && s.trim().length() == 0) return s; + if (myAllowEmpty && s.trim().length() == 0) { + return null; + } - return parseNumber(s, myNumberClass) == null ? null : s; + //noinspection unchecked + return (T)parseNumber(s, myNumberClass); } @Override - public String toString(@Nullable final String s, final ConvertContext context) { - return null; + public String toString(@Nullable final T value, final ConvertContext context) { + return value == null ? null : parseText(value, myNumberClass); } @Override public String getErrorMessage(@Nullable final String s, final ConvertContext context) { if (s == null) return super.getErrorMessage(s, context); - return s.trim().length() == 0 ? - DomBundle.message("value.converter.format.exception.empty.string", myNumberClass.getName()) : - DomBundle.message("value.converter.format.exception", s, myNumberClass.getName()); + final boolean isEmpty = s.trim().length() == 0; + if (isEmpty && myAllowEmpty) return null; + + return isEmpty ? + DomBundle.message("value.converter.format.exception.empty.string", myNumberClass.getName()) : + DomBundle.message("value.converter.format.exception", s, myNumberClass.getName()); } @NotNull @Override - public Collection getVariants(ConvertContext context) { + public Collection getVariants(ConvertContext context) { return Collections.emptySet(); } + @Nullable + public static String parseText(@NotNull Number value, @NotNull Class targetClass) { + if (targetClass.equals(Byte.class) || targetClass.equals(byte.class)) { + return Byte.toString((Byte)value); + } + if (targetClass.equals(Short.class) || targetClass.equals(short.class)) { + return Short.toString((Short)value); + } + if (targetClass.equals(Integer.class) || targetClass.equals(int.class)) { + return Integer.toString((Integer)value); + } + if (targetClass.equals(Long.class) || targetClass.equals(long.class)) { + return Long.toString((Long)value); + } + if (targetClass.equals(BigInteger.class)) { + return value.toString(); + } + if (targetClass.equals(Float.class) || targetClass.equals(float.class)) { + return Float.toString((Float)value); + } + if (targetClass.equals(Double.class) || targetClass.equals(double.class)) { + return Double.toString((Double)value); + } + if (targetClass.equals(BigDecimal.class) || targetClass.equals(Number.class)) { + return ((BigDecimal)value).toPlainString(); + } + return null; + } + @Nullable public static Number parseNumber(@NotNull String text, @NotNull Class targetClass) { try { @@ -76,28 +110,29 @@ public class NumberValueConverter extends ResolvingConverter { if (targetClass.equals(Byte.class) || targetClass.equals(byte.class)) { return Byte.decode(trimmed); } - else if (targetClass.equals(Short.class) || targetClass.equals(short.class)) { + if (targetClass.equals(Short.class) || targetClass.equals(short.class)) { return Short.decode(trimmed); } - else if (targetClass.equals(Integer.class) || targetClass.equals(int.class)) { + if (targetClass.equals(Integer.class) || targetClass.equals(int.class)) { return Integer.decode(trimmed); } - else if (targetClass.equals(Long.class) || targetClass.equals(long.class)) { + if (targetClass.equals(Long.class) || targetClass.equals(long.class)) { return Long.decode(trimmed); } - else if (targetClass.equals(BigInteger.class)) { + if (targetClass.equals(BigInteger.class)) { return decodeBigInteger(trimmed); } - else if (targetClass.equals(Float.class) || targetClass.equals(float.class)) { + if (targetClass.equals(Float.class) || targetClass.equals(float.class)) { return Float.valueOf(trimmed); } - else if (targetClass.equals(Double.class) || targetClass.equals(double.class)) { + if (targetClass.equals(Double.class) || targetClass.equals(double.class)) { return Double.valueOf(trimmed); } - else if (targetClass.equals(BigDecimal.class) || targetClass.equals(Number.class)) { + if (targetClass.equals(BigDecimal.class) || targetClass.equals(Number.class)) { return new BigDecimal(trimmed); } - } catch (NumberFormatException ex) { + } + catch (NumberFormatException ex) { return null; } return null; diff --git a/xml/dom-tests/tests/com/intellij/util/xml/DomSimpleValuesTest.java b/xml/dom-tests/tests/com/intellij/util/xml/DomSimpleValuesTest.java index e0d626d2f765..2cbcb854f8ab 100644 --- a/xml/dom-tests/tests/com/intellij/util/xml/DomSimpleValuesTest.java +++ b/xml/dom-tests/tests/com/intellij/util/xml/DomSimpleValuesTest.java @@ -28,6 +28,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.math.BigDecimal; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -83,6 +84,15 @@ public class DomSimpleValuesTest extends DomTestCase { assertEquals(true, createElement("true").getBoolean()); assertEquals("true", createElement("true").getBuffer().toString()); + assertEquals((short)239, createElement("239").getShort()); + assertEquals(new Long("239"), createElement("239").getLong()); + assertEquals(new Float("239.42"), createElement("239.42").getFloat()); + assertEquals(new BigDecimal("239.42"), createElement("239.42").getBigDecimal()); + + final MyElement bigDecimalValue = createElement("239.42"); + bigDecimalValue.setValue(new BigDecimal("111.234")); + assertEquals("111.234", bigDecimalValue.getValue()); + try { createElement("true").getInt(); fail(); @@ -401,6 +411,20 @@ public class DomSimpleValuesTest extends DomTestCase { @TagValue() String getTagValue(); + @TagValue + Long getLong(); + + @TagValue + Float getFloat(); + + @TagValue + short getShort(); + + @TagValue + BigDecimal getBigDecimal(); + + void setValue(BigDecimal value); + GenericDomValue getGenericChild(); @SubTag("buffer")