From 34934d1055d2451a3633d4380648ce661da17ce7 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Wed, 24 Sep 2014 19:20:43 +0300 Subject: [PATCH] String <-> Enum converter which produces a human readable string (#14756) Change-Id: I3a825f52a43daea3172ced23bc510118376e76cb --- .../converter/DefaultConverterFactory.java | 2 + .../util/converter/StringToEnumConverter.java | 97 +++++++++++++++++++ .../converter/TestStringToEnumConverter.java | 59 +++++++++++ .../components/textfield/EnumTextField.java | 50 ++++++++++ .../textfield/EnumTextFieldTest.java | 57 +++++++++++ 5 files changed, 265 insertions(+) create mode 100644 server/src/com/vaadin/data/util/converter/StringToEnumConverter.java create mode 100644 server/tests/src/com/vaadin/tests/data/converter/TestStringToEnumConverter.java create mode 100644 uitest/src/com/vaadin/tests/components/textfield/EnumTextField.java create mode 100644 uitest/src/com/vaadin/tests/components/textfield/EnumTextFieldTest.java diff --git a/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java b/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java index fdf858a528..26613c5d02 100644 --- a/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java +++ b/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java @@ -110,6 +110,8 @@ public class DefaultConverterFactory implements ConverterFactory { return new StringToBooleanConverter(); } else if (Date.class.isAssignableFrom(sourceType)) { return new StringToDateConverter(); + } else if (Enum.class.isAssignableFrom(sourceType)) { + return new StringToEnumConverter(); } else { return null; } diff --git a/server/src/com/vaadin/data/util/converter/StringToEnumConverter.java b/server/src/com/vaadin/data/util/converter/StringToEnumConverter.java new file mode 100644 index 0000000000..a1328d831c --- /dev/null +++ b/server/src/com/vaadin/data/util/converter/StringToEnumConverter.java @@ -0,0 +1,97 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed 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 com.vaadin.data.util.converter; + +import java.util.EnumSet; +import java.util.Locale; + +/** + * A converter that converts from {@link String} to an {@link Enum} and back. + *

+ * Designed to provide nice human readable strings for {@link Enum} classes + * where the constants are named SOME_UPPERCASE_WORDS. Will not necessarily work + * correctly for other cases. + *

+ * + * @author Vaadin Ltd + * @since + */ +public class StringToEnumConverter implements Converter { + + @Override + public Enum convertToModel(String value, Class targetType, + Locale locale) throws ConversionException { + if (value == null) { + return null; + } + if (locale == null) { + locale = Locale.getDefault(); + } + + // Foo -> FOO + // Foo bar -> FOO_BAR + String result = value.replace(" ", "_").toUpperCase(locale); + try { + return Enum.valueOf(targetType, result); + } catch (IllegalArgumentException ee) { + // There was no match. Try to compare the available values to see if + // the constant is using something else than all upper case + + EnumSet set = EnumSet.allOf(targetType); + for (Enum e : set) { + if (e.name().toUpperCase(locale).equals(result)) { + return e; + } + } + + // Fallback did not work either, re-throw original exception so user + // knows what went wrong + throw new ConversionException(ee); + } + } + + @Override + public String convertToPresentation(Enum value, + Class targetType, Locale locale) + throws ConversionException { + if (value == null) { + return null; + } + if (locale == null) { + locale = Locale.getDefault(); + } + + String enumString = value.toString(); + // FOO -> Foo + // FOO_BAR -> Foo bar + // _FOO -> _foo + String result = enumString.substring(0, 1).toUpperCase(locale); + result += enumString.substring(1).toLowerCase(locale).replace('_', ' '); + + return result; + } + + @Override + public Class getModelType() { + return Enum.class; + } + + @Override + public Class getPresentationType() { + return String.class; + } + +} diff --git a/server/tests/src/com/vaadin/tests/data/converter/TestStringToEnumConverter.java b/server/tests/src/com/vaadin/tests/data/converter/TestStringToEnumConverter.java new file mode 100644 index 0000000000..2b19395c08 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/converter/TestStringToEnumConverter.java @@ -0,0 +1,59 @@ +package com.vaadin.tests.data.converter; + +import junit.framework.TestCase; + +import com.vaadin.data.util.converter.Converter; +import com.vaadin.data.util.converter.ReverseConverter; +import com.vaadin.data.util.converter.StringToEnumConverter; + +public class TestStringToEnumConverter extends TestCase { + + public static enum FooEnum { + VALUE1, SOME_VALUE, FOO_BAR_BAZ, Bar, nonStandardCase, _HUGH; + } + + StringToEnumConverter converter = new StringToEnumConverter(); + Converter reverseConverter = new ReverseConverter( + converter); + + public void testNullConversion() { + assertEquals(null, converter.convertToModel(null, Enum.class, null)); + } + + public void testReverseNullConversion() { + assertEquals(null, + reverseConverter.convertToModel(null, String.class, null)); + } + + public void testValueConversion() { + assertEquals(FooEnum.VALUE1, + converter.convertToModel("Value1", FooEnum.class, null)); + assertEquals(FooEnum.SOME_VALUE, + converter.convertToModel("Some value", FooEnum.class, null)); + assertEquals(FooEnum.FOO_BAR_BAZ, + converter.convertToModel("Foo bar baz", FooEnum.class, null)); + assertEquals(FooEnum.Bar, + converter.convertToModel("Bar", FooEnum.class, null)); + assertEquals(FooEnum.nonStandardCase, converter.convertToModel( + "Nonstandardcase", FooEnum.class, null)); + assertEquals(FooEnum._HUGH, + converter.convertToModel("_hugh", FooEnum.class, null)); + } + + public void testReverseValueConversion() { + assertEquals("Value1", reverseConverter.convertToModel(FooEnum.VALUE1, + String.class, null)); + assertEquals("Some value", reverseConverter.convertToModel( + FooEnum.SOME_VALUE, String.class, null)); + assertEquals("Foo bar baz", reverseConverter.convertToModel( + FooEnum.FOO_BAR_BAZ, String.class, null)); + assertEquals("Bar", reverseConverter.convertToModel(FooEnum.Bar, + String.class, null)); + assertEquals("Nonstandardcase", reverseConverter.convertToModel( + FooEnum.nonStandardCase, String.class, null)); + assertEquals("_hugh", reverseConverter.convertToModel(FooEnum._HUGH, + String.class, null)); + + } + +} diff --git a/uitest/src/com/vaadin/tests/components/textfield/EnumTextField.java b/uitest/src/com/vaadin/tests/components/textfield/EnumTextField.java new file mode 100644 index 0000000000..67b3b84688 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/textfield/EnumTextField.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed 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 com.vaadin.tests.components.textfield; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.ui.TextField; + +public class EnumTextField extends AbstractTestUIWithLog { + + public enum MyEnum { + FIRST_VALUE, VALUE, THE_LAST_VALUE; + } + + @Override + protected void setup(VaadinRequest request) { + final TextField tf = new TextField(); + tf.addValueChangeListener(new ValueChangeListener() { + + @Override + public void valueChange(ValueChangeEvent event) { + if (tf.isValid()) { + log(tf.getValue() + " (valid)"); + } else { + log(tf.getValue() + " (INVALID)"); + } + } + }); + + tf.setPropertyDataSource(new ObjectProperty(MyEnum.FIRST_VALUE)); + addComponent(tf); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/textfield/EnumTextFieldTest.java b/uitest/src/com/vaadin/tests/components/textfield/EnumTextFieldTest.java new file mode 100644 index 0000000000..113acee3a2 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/textfield/EnumTextFieldTest.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed 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 com.vaadin.tests.components.textfield; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.Keys; + +import com.vaadin.testbench.elements.TextFieldElement; +import com.vaadin.tests.tb3.SingleBrowserTest; + +public class EnumTextFieldTest extends SingleBrowserTest { + @Test + public void validValues() { + openTestURL(); + $(TextFieldElement.class).first().clear(); + $(TextFieldElement.class).first().sendKeys("Value"); + $(TextFieldElement.class).first().sendKeys(Keys.TAB); + Assert.assertEquals("3. Value (valid)", getLogRow(0)); + + $(TextFieldElement.class).first().clear(); + $(TextFieldElement.class).first().sendKeys("VaLuE"); + $(TextFieldElement.class).first().sendKeys(Keys.TAB); + Assert.assertEquals("5. Value (valid)", getLogRow(0)); + + $(TextFieldElement.class).first().clear(); + $(TextFieldElement.class).first().sendKeys("The last value"); + $(TextFieldElement.class).first().sendKeys(Keys.TAB); + Assert.assertEquals("7. The last value (valid)", getLogRow(0)); + + } + + @Test + public void invalidValue() { + openTestURL(); + $(TextFieldElement.class).first().clear(); + Assert.assertEquals("2. (INVALID)", getLogRow(0)); + + $(TextFieldElement.class).first().sendKeys("bar"); + $(TextFieldElement.class).first().sendKeys(Keys.TAB); + Assert.assertEquals("3. bar (INVALID)", getLogRow(0)); + + } +} -- 2.39.5