summaryrefslogtreecommitdiffstats
path: root/compatibility-server
diff options
context:
space:
mode:
authorArtur Signell <artur@vaadin.com>2016-08-25 13:21:36 +0300
committerArtur Signell <artur@vaadin.com>2016-08-26 11:40:12 +0300
commit58853fe47bb01a0c0c2b5c380056d22ccccd6f08 (patch)
tree3a45b08366f53943326e14750d2c4d90f1e1128d /compatibility-server
parent50f294513f929fcd0e6a519283d5a88e09331081 (diff)
downloadvaadin-framework-58853fe47bb01a0c0c2b5c380056d22ccccd6f08.tar.gz
vaadin-framework-58853fe47bb01a0c0c2b5c380056d22ccccd6f08.zip
Move old TextField to compatibility package
Change-Id: Ic1e8d3f9859f5e496c0e27e2fece4b5a9da74f01
Diffstat (limited to 'compatibility-server')
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/event/FieldEvents.java109
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/ui/AbstractTextField.java813
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/ui/TextField.java151
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/AnyEnumToStringConverterTest.java129
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/ConverterFactoryTest.java128
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/DateToLongConverterTest.java28
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/DateToSqlDateConverterTest.java28
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/DefaultConverterFactoryTest.java124
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/SpecificEnumToStringConverterTest.java125
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToBigDecimalConverterTest.java59
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToBigIntegerConverterTest.java64
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToBooleanConverterTest.java82
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToByteConverterTest.java76
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToCollectionConverterTest.java172
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToDateConverterTest.java32
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToDoubleConverterTest.java29
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToEnumConverterTest.java135
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToFloatConverterTest.java29
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToIntegerConverterTest.java48
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToLongConverterTest.java78
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToShortConverterTest.java76
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/server/EventRouterTest.java40
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/server/PropertysetItemListenersTest.java (renamed from compatibility-server/src/test/java/com/vaadin/tests/server/PropertysetItemListenersTest.java)2
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbsFieldDataSourceLocaleChangeTest.java65
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbsFieldValidatorsTest.java79
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbsFieldValueConversionErrorTest.java92
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbsFieldValueConversionsTest.java216
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbstractFieldDeclarativeTest.java65
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbstractFieldReadOnlyTest.java51
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/DefaultConverterFactoryTest.java138
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/RemoveListenersOnDetachTest.java106
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstracttextfield/AbstractTextFieldListenersTest.java34
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/textfield/TextFieldTest.java50
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/textfield/TextFieldValueChangeTest.java131
34 files changed, 3583 insertions, 1 deletions
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/event/FieldEvents.java b/compatibility-server/src/main/java/com/vaadin/v7/event/FieldEvents.java
new file mode 100644
index 0000000000..abd17df49b
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/event/FieldEvents.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2000-2016 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.v7.event;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+
+import com.vaadin.event.ConnectorEventListener;
+import com.vaadin.ui.Component;
+import com.vaadin.util.ReflectTools;
+import com.vaadin.v7.ui.Field;
+import com.vaadin.v7.ui.Field.ValueChangeEvent;
+import com.vaadin.v7.ui.TextField;
+
+/**
+ * Interface that serves as a wrapper for {@link Field} related events.
+ */
+public interface FieldEvents {
+
+ /**
+ * TextChangeEvents are fired when the user is editing the text content of a
+ * field. Most commonly text change events are triggered by typing text with
+ * keyboard, but e.g. pasting content from clip board to a text field also
+ * triggers an event.
+ * <p>
+ * TextChangeEvents differ from {@link ValueChangeEvent}s so that they are
+ * triggered repeatedly while the end user is filling the field.
+ * ValueChangeEvents are not fired until the user for example hits enter or
+ * focuses another field. Also note the difference that TextChangeEvents are
+ * only fired if the change is triggered from the user, while
+ * ValueChangeEvents are also fired if the field value is set by the
+ * application code.
+ * <p>
+ * The {@link TextChangeNotifier}s implementation may decide when exactly
+ * TextChangeEvents are fired. TextChangeEvents are not necessary fire for
+ * example on each key press, but buffered with a small delay. The
+ * {@code TextField} component supports different modes for triggering
+ * TextChangeEvents.
+ *
+ * @see TextChangeListener
+ * @see TextChangeNotifier
+ * @see TextField#setTextChangeEventMode(com.vaadin.ui.TextField.TextChangeEventMode)
+ * @since 6.5
+ */
+ public static abstract class TextChangeEvent extends Component.Event {
+
+ public TextChangeEvent(Component source) {
+ super(source);
+ }
+
+ /**
+ * @return the text content of the field after the
+ * {@link TextChangeEvent}
+ */
+ public abstract String getText();
+
+ /**
+ * @return the cursor position during after the {@link TextChangeEvent}
+ */
+ public abstract int getCursorPosition();
+ }
+
+ /**
+ * A listener for {@link TextChangeEvent}s.
+ *
+ * @since 6.5
+ */
+ public interface TextChangeListener extends ConnectorEventListener {
+
+ public static String EVENT_ID = "ie";
+ public static Method EVENT_METHOD = ReflectTools.findMethod(
+ TextChangeListener.class, "textChange", TextChangeEvent.class);
+
+ /**
+ * This method is called repeatedly while the text is edited by a user.
+ *
+ * @param event
+ * the event providing details of the text change
+ */
+ public void textChange(TextChangeEvent event);
+ }
+
+ /**
+ * An interface implemented by a {@link Field} supporting
+ * {@link TextChangeEvent}s. An example a {@link TextField} supports
+ * {@link TextChangeListener}s.
+ */
+ public interface TextChangeNotifier extends Serializable {
+ public void addTextChangeListener(TextChangeListener listener);
+
+ public void removeTextChangeListener(TextChangeListener listener);
+
+ }
+
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/ui/AbstractTextField.java b/compatibility-server/src/main/java/com/vaadin/v7/ui/AbstractTextField.java
new file mode 100644
index 0000000000..f534662583
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/ui/AbstractTextField.java
@@ -0,0 +1,813 @@
+/*
+ * Copyright 2000-2016 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.v7.ui;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.jsoup.nodes.Attributes;
+import org.jsoup.nodes.Element;
+
+import com.vaadin.event.FieldEvents.BlurEvent;
+import com.vaadin.event.FieldEvents.BlurListener;
+import com.vaadin.event.FieldEvents.BlurNotifier;
+import com.vaadin.event.FieldEvents.FocusEvent;
+import com.vaadin.event.FieldEvents.FocusListener;
+import com.vaadin.event.FieldEvents.FocusNotifier;
+import com.vaadin.server.PaintException;
+import com.vaadin.server.PaintTarget;
+import com.vaadin.shared.v7.ui.textfield.LegacyAbstractTextFieldState;
+import com.vaadin.shared.v7.ui.textfield.LegacyTextFieldConstants;
+import com.vaadin.ui.LegacyComponent;
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+import com.vaadin.ui.declarative.DesignContext;
+import com.vaadin.v7.event.FieldEvents.TextChangeEvent;
+import com.vaadin.v7.event.FieldEvents.TextChangeListener;
+import com.vaadin.v7.event.FieldEvents.TextChangeNotifier;
+
+@Deprecated
+public abstract class AbstractTextField extends AbstractField<String> implements
+ BlurNotifier, FocusNotifier, TextChangeNotifier, LegacyComponent {
+
+ /**
+ * Null representation.
+ */
+ private String nullRepresentation = "null";
+ /**
+ * Is setting to null from non-null value allowed by setting with null
+ * representation .
+ */
+ private boolean nullSettingAllowed = false;
+ /**
+ * The text content when the last messages to the server was sent. Cleared
+ * when value is changed.
+ */
+ private String lastKnownTextContent;
+
+ /**
+ * The position of the cursor when the last message to the server was sent.
+ */
+ private int lastKnownCursorPosition;
+
+ /**
+ * Flag indicating that a text change event is pending to be triggered.
+ * Cleared by {@link #setInternalValue(Object)} and when the event is fired.
+ */
+ private boolean textChangeEventPending;
+
+ private boolean isFiringTextChangeEvent = false;
+
+ private TextChangeEventMode textChangeEventMode = TextChangeEventMode.LAZY;
+
+ private final int DEFAULT_TEXTCHANGE_TIMEOUT = 400;
+
+ private int textChangeEventTimeout = DEFAULT_TEXTCHANGE_TIMEOUT;
+
+ /**
+ * Temporarily holds the new selection position. Cleared on paint.
+ */
+ private int selectionPosition = -1;
+
+ /**
+ * Temporarily holds the new selection length.
+ */
+ private int selectionLength;
+
+ /**
+ * Flag used to determine whether we are currently handling a state change
+ * triggered by a user. Used to properly fire text change event before value
+ * change event triggered by the client side.
+ */
+ private boolean changingVariables;
+
+ protected AbstractTextField() {
+ super();
+ }
+
+ @Override
+ protected LegacyAbstractTextFieldState getState() {
+ return (LegacyAbstractTextFieldState) super.getState();
+ }
+
+ @Override
+ protected LegacyAbstractTextFieldState getState(boolean markAsDirty) {
+ return (LegacyAbstractTextFieldState) super.getState(markAsDirty);
+ }
+
+ @Override
+ public void beforeClientResponse(boolean initial) {
+ super.beforeClientResponse(initial);
+
+ String value = getValue();
+ if (value == null) {
+ value = getNullRepresentation();
+ }
+ getState().text = value;
+ }
+
+ @Override
+ public void paintContent(PaintTarget target) throws PaintException {
+
+ if (selectionPosition != -1) {
+ target.addAttribute("selpos", selectionPosition);
+ target.addAttribute("sellen", selectionLength);
+ selectionPosition = -1;
+ }
+
+ if (hasListeners(TextChangeEvent.class)) {
+ target.addAttribute(
+ LegacyTextFieldConstants.ATTR_TEXTCHANGE_EVENTMODE,
+ getTextChangeEventMode().toString());
+ target.addAttribute(
+ LegacyTextFieldConstants.ATTR_TEXTCHANGE_TIMEOUT,
+ getTextChangeTimeout());
+ if (lastKnownTextContent != null) {
+ /*
+ * The field has be repainted for some reason (e.g. caption,
+ * size, stylename), but the value has not been changed since
+ * the last text change event. Let the client side know about
+ * the value the server side knows. Client side may then ignore
+ * the actual value, depending on its state.
+ */
+ target.addAttribute(
+ LegacyTextFieldConstants.ATTR_NO_VALUE_CHANGE_BETWEEN_PAINTS,
+ true);
+ }
+ }
+
+ }
+
+ @Override
+ public void changeVariables(Object source, Map<String, Object> variables) {
+ changingVariables = true;
+
+ try {
+
+ // Sets the height set by the user when resize the <textarea>.
+ String newHeight = (String) variables.get("height");
+ if (newHeight != null) {
+ setHeight(newHeight);
+ }
+
+ // Sets the width set by the user when resize the <textarea>.
+ String newWidth = (String) variables.get("width");
+ if (newWidth != null) {
+ setWidth(newWidth);
+ }
+
+ if (variables.containsKey(LegacyTextFieldConstants.VAR_CURSOR)) {
+ Integer object = (Integer) variables
+ .get(LegacyTextFieldConstants.VAR_CURSOR);
+ lastKnownCursorPosition = object.intValue();
+ }
+
+ if (variables.containsKey(LegacyTextFieldConstants.VAR_CUR_TEXT)) {
+ /*
+ * NOTE, we might want to develop this further so that on a
+ * value change event the whole text content don't need to be
+ * sent from the client to server. Just "commit" the value from
+ * currentText to the value.
+ */
+ handleInputEventTextChange(variables);
+ }
+
+ // Sets the text
+ if (variables.containsKey("text") && !isReadOnly()) {
+
+ // Only do the setting if the string representation of the value
+ // has been updated
+ String newValue = (String) variables.get("text");
+
+ // server side check for max length
+ if (getMaxLength() != -1
+ && newValue.length() > getMaxLength()) {
+ newValue = newValue.substring(0, getMaxLength());
+ }
+ final String oldValue = getValue();
+ if (newValue != null
+ && (oldValue == null || isNullSettingAllowed())
+ && newValue.equals(getNullRepresentation())) {
+ newValue = null;
+ }
+ if (newValue != oldValue
+ && (newValue == null || !newValue.equals(oldValue))) {
+ boolean wasModified = isModified();
+ setValue(newValue, true);
+
+ // If the modified status changes, or if we have a
+ // formatter, repaint is needed after all.
+ if (wasModified != isModified()) {
+ markAsDirty();
+ }
+ }
+ }
+ firePendingTextChangeEvent();
+
+ if (variables.containsKey(FocusEvent.EVENT_ID)) {
+ fireEvent(new FocusEvent(this));
+ }
+ if (variables.containsKey(BlurEvent.EVENT_ID)) {
+ fireEvent(new BlurEvent(this));
+ }
+ } finally {
+ changingVariables = false;
+
+ }
+
+ }
+
+ @Override
+ public Class<String> getType() {
+ return String.class;
+ }
+
+ /**
+ * Gets the null-string representation.
+ *
+ * <p>
+ * The null-valued strings are represented on the user interface by
+ * replacing the null value with this string. If the null representation is
+ * set null (not 'null' string), painting null value throws exception.
+ * </p>
+ *
+ * <p>
+ * The default value is string 'null'.
+ * </p>
+ *
+ * @return the String Textual representation for null strings.
+ * @see TextField#isNullSettingAllowed()
+ */
+ public String getNullRepresentation() {
+ return nullRepresentation;
+ }
+
+ /**
+ * Is setting nulls with null-string representation allowed.
+ *
+ * <p>
+ * If this property is true, writing null-representation string to text
+ * field always sets the field value to real null. If this property is
+ * false, null setting is not made, but the null values are maintained.
+ * Maintenance of null-values is made by only converting the textfield
+ * contents to real null, if the text field matches the null-string
+ * representation and the current value of the field is null.
+ * </p>
+ *
+ * <p>
+ * By default this setting is false
+ * </p>
+ *
+ * @return boolean Should the null-string represenation be always converted
+ * to null-values.
+ * @see TextField#getNullRepresentation()
+ */
+ public boolean isNullSettingAllowed() {
+ return nullSettingAllowed;
+ }
+
+ /**
+ * Sets the null-string representation.
+ *
+ * <p>
+ * The null-valued strings are represented on the user interface by
+ * replacing the null value with this string. If the null representation is
+ * set null (not 'null' string), painting null value throws exception.
+ * </p>
+ *
+ * <p>
+ * The default value is string 'null'
+ * </p>
+ *
+ * @param nullRepresentation
+ * Textual representation for null strings.
+ * @see TextField#setNullSettingAllowed(boolean)
+ */
+ public void setNullRepresentation(String nullRepresentation) {
+ this.nullRepresentation = nullRepresentation;
+ markAsDirty();
+ }
+
+ /**
+ * Sets the null conversion mode.
+ *
+ * <p>
+ * If this property is true, writing null-representation string to text
+ * field always sets the field value to real null. If this property is
+ * false, null setting is not made, but the null values are maintained.
+ * Maintenance of null-values is made by only converting the textfield
+ * contents to real null, if the text field matches the null-string
+ * representation and the current value of the field is null.
+ * </p>
+ *
+ * <p>
+ * By default this setting is false.
+ * </p>
+ *
+ * @param nullSettingAllowed
+ * Should the null-string representation always be converted to
+ * null-values.
+ * @see TextField#getNullRepresentation()
+ */
+ public void setNullSettingAllowed(boolean nullSettingAllowed) {
+ this.nullSettingAllowed = nullSettingAllowed;
+ markAsDirty();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return super.isEmpty() || getValue().length() == 0;
+ }
+
+ /**
+ * Returns the maximum number of characters in the field. Value -1 is
+ * considered unlimited. Terminal may however have some technical limits.
+ *
+ * @return the maxLength
+ */
+ public int getMaxLength() {
+ return getState(false).maxLength;
+ }
+
+ /**
+ * Sets the maximum number of characters in the field. Value -1 is
+ * considered unlimited. Terminal may however have some technical limits.
+ *
+ * @param maxLength
+ * the maxLength to set
+ */
+ public void setMaxLength(int maxLength) {
+ getState().maxLength = maxLength;
+ }
+
+ /**
+ * Gets the number of columns in the editor. If the number of columns is set
+ * 0, the actual number of displayed columns is determined implicitly by the
+ * adapter.
+ *
+ * @return the number of columns in the editor.
+ */
+ public int getColumns() {
+ return getState(false).columns;
+ }
+
+ /**
+ * Sets the number of columns in the editor. If the number of columns is set
+ * 0, the actual number of displayed columns is determined implicitly by the
+ * adapter.
+ *
+ * @param columns
+ * the number of columns to set.
+ */
+ public void setColumns(int columns) {
+ if (columns < 0) {
+ columns = 0;
+ }
+ getState().columns = columns;
+ }
+
+ /**
+ * Gets the current input prompt.
+ *
+ * @see #setInputPrompt(String)
+ * @return the current input prompt, or null if not enabled
+ */
+ public String getInputPrompt() {
+ return getState(false).inputPrompt;
+ }
+
+ /**
+ * Sets the input prompt - a textual prompt that is displayed when the field
+ * would otherwise be empty, to prompt the user for input.
+ *
+ * @param inputPrompt
+ */
+ public void setInputPrompt(String inputPrompt) {
+ getState().inputPrompt = inputPrompt;
+ }
+
+ /* ** Text Change Events ** */
+
+ private void firePendingTextChangeEvent() {
+ if (textChangeEventPending && !isFiringTextChangeEvent) {
+ isFiringTextChangeEvent = true;
+ textChangeEventPending = false;
+ try {
+ fireEvent(new TextChangeEventImpl(this));
+ } finally {
+ isFiringTextChangeEvent = false;
+ }
+ }
+ }
+
+ @Override
+ protected void setInternalValue(String newValue) {
+ if (changingVariables && !textChangeEventPending) {
+
+ /*
+ * TODO check for possible (minor?) issue (not tested)
+ *
+ * -field with e.g. PropertyFormatter.
+ *
+ * -TextChangeListener and it changes value.
+ *
+ * -if formatter again changes the value, do we get an extra
+ * simulated text change event ?
+ */
+
+ /*
+ * Fire a "simulated" text change event before value change event if
+ * change is coming from the client side.
+ *
+ * Iff there is both value change and textChangeEvent in same
+ * variable burst, it is a text field in non immediate mode and the
+ * text change event "flushed" queued value change event. In this
+ * case textChangeEventPending flag is already on and text change
+ * event will be fired after the value change event.
+ */
+ if (newValue == null && lastKnownTextContent != null
+ && !lastKnownTextContent.equals(getNullRepresentation())) {
+ // Value was changed from something to null representation
+ lastKnownTextContent = getNullRepresentation();
+ textChangeEventPending = true;
+ } else if (newValue != null
+ && !newValue.toString().equals(lastKnownTextContent)) {
+ // Value was changed to something else than null representation
+ lastKnownTextContent = newValue.toString();
+ textChangeEventPending = true;
+ }
+ firePendingTextChangeEvent();
+ }
+
+ super.setInternalValue(newValue);
+ }
+
+ @Override
+ public void setValue(String newValue) throws ReadOnlyException {
+ super.setValue(newValue);
+ /*
+ * Make sure w reset lastKnownTextContent field on value change. The
+ * clearing must happen here as well because TextChangeListener can
+ * revert the original value. Client must respect the value in this
+ * case. LegacyAbstractField optimizes value change if the existing
+ * value is reset. Also we need to force repaint if the flag is on.
+ */
+ if (lastKnownTextContent != null) {
+ lastKnownTextContent = null;
+ markAsDirty();
+ }
+ }
+
+ private void handleInputEventTextChange(Map<String, Object> variables) {
+ /*
+ * TODO we could vastly optimize the communication of values by using
+ * some sort of diffs instead of always sending the whole text content.
+ * Also on value change events we could use the mechanism.
+ */
+ String object = (String) variables
+ .get(LegacyTextFieldConstants.VAR_CUR_TEXT);
+ lastKnownTextContent = object;
+ textChangeEventPending = true;
+ }
+
+ /**
+ * Sets the mode how the TextField triggers {@link TextChangeEvent}s.
+ *
+ * @param inputEventMode
+ * the new mode
+ *
+ * @see TextChangeEventMode
+ */
+ public void setTextChangeEventMode(TextChangeEventMode inputEventMode) {
+ textChangeEventMode = inputEventMode;
+ markAsDirty();
+ }
+
+ /**
+ * @return the mode used to trigger {@link TextChangeEvent}s.
+ */
+ public TextChangeEventMode getTextChangeEventMode() {
+ return textChangeEventMode;
+ }
+
+ /**
+ * Different modes how the TextField can trigger {@link TextChangeEvent}s.
+ */
+ public enum TextChangeEventMode {
+
+ /**
+ * An event is triggered on each text content change, most commonly key
+ * press events.
+ */
+ EAGER,
+ /**
+ * Each text change event in the UI causes the event to be communicated
+ * to the application after a timeout. The length of the timeout can be
+ * controlled with {@link TextField#setTextChangeTimeout(int)}. Only the
+ * last input event is reported to the server side if several text
+ * change events happen during the timeout.
+ * <p>
+ * In case of a {@link ValueChangeEvent} the schedule is not kept
+ * strictly. Before a {@link ValueChangeEvent} a {@link TextChangeEvent}
+ * is triggered if the text content has changed since the previous
+ * TextChangeEvent regardless of the schedule.
+ */
+ TIMEOUT,
+ /**
+ * An event is triggered when there is a pause of text modifications.
+ * The length of the pause can be modified with
+ * {@link TextField#setTextChangeTimeout(int)}. Like with the
+ * {@link #TIMEOUT} mode, an event is forced before
+ * {@link ValueChangeEvent}s, even if the user did not keep a pause
+ * while entering the text.
+ * <p>
+ * This is the default mode.
+ */
+ LAZY
+ }
+
+ @Override
+ public void addTextChangeListener(TextChangeListener listener) {
+ addListener(TextChangeListener.EVENT_ID, TextChangeEvent.class,
+ listener, TextChangeListener.EVENT_METHOD);
+ }
+
+ /**
+ * @deprecated As of 7.0, replaced by
+ * {@link #addTextChangeListener(TextChangeListener)}
+ **/
+ @Deprecated
+ public void addListener(TextChangeListener listener) {
+ addTextChangeListener(listener);
+ }
+
+ @Override
+ public void removeTextChangeListener(TextChangeListener listener) {
+ removeListener(TextChangeListener.EVENT_ID, TextChangeEvent.class,
+ listener);
+ }
+
+ /**
+ * @deprecated As of 7.0, replaced by
+ * {@link #removeTextChangeListener(TextChangeListener)}
+ **/
+ @Deprecated
+ public void removeListener(TextChangeListener listener) {
+ removeTextChangeListener(listener);
+ }
+
+ /**
+ * The text change timeout modifies how often text change events are
+ * communicated to the application when {@link #getTextChangeEventMode()} is
+ * {@link TextChangeEventMode#LAZY} or {@link TextChangeEventMode#TIMEOUT}.
+ *
+ *
+ * @see #getTextChangeEventMode()
+ *
+ * @param timeout
+ * the timeout in milliseconds
+ */
+ public void setTextChangeTimeout(int timeout) {
+ textChangeEventTimeout = timeout;
+ markAsDirty();
+ }
+
+ /**
+ * Gets the timeout used to fire {@link TextChangeEvent}s when the
+ * {@link #getTextChangeEventMode()} is {@link TextChangeEventMode#LAZY} or
+ * {@link TextChangeEventMode#TIMEOUT}.
+ *
+ * @return the timeout value in milliseconds
+ */
+ public int getTextChangeTimeout() {
+ return textChangeEventTimeout;
+ }
+
+ public static class TextChangeEventImpl extends TextChangeEvent {
+ private String curText;
+ private int cursorPosition;
+
+ private TextChangeEventImpl(final AbstractTextField tf) {
+ super(tf);
+ curText = tf.getCurrentTextContent();
+ cursorPosition = tf.getCursorPosition();
+ }
+
+ @Override
+ public AbstractTextField getComponent() {
+ return (AbstractTextField) super.getComponent();
+ }
+
+ @Override
+ public String getText() {
+ return curText;
+ }
+
+ @Override
+ public int getCursorPosition() {
+ return cursorPosition;
+ }
+
+ }
+
+ /**
+ * Gets the current (or the last known) text content in the field.
+ * <p>
+ * Note the text returned by this method is not necessary the same that is
+ * returned by the {@link #getValue()} method. The value is updated when the
+ * terminal fires a value change event via e.g. blurring the field or by
+ * pressing enter. The value returned by this method is updated also on
+ * {@link TextChangeEvent}s. Due to this high dependency to the terminal
+ * implementation this method is (at least at this point) not published.
+ *
+ * @return the text which is currently displayed in the field.
+ */
+ private String getCurrentTextContent() {
+ if (lastKnownTextContent != null) {
+ return lastKnownTextContent;
+ } else {
+ Object text = getValue();
+ if (text == null) {
+ return getNullRepresentation();
+ }
+ return text.toString();
+ }
+ }
+
+ /**
+ * Selects all text in the field.
+ *
+ * @since 6.4
+ */
+ public void selectAll() {
+ String text = getValue() == null ? "" : getValue().toString();
+ setSelectionRange(0, text.length());
+ }
+
+ /**
+ * Sets the range of text to be selected.
+ *
+ * As a side effect the field will become focused.
+ *
+ * @since 6.4
+ *
+ * @param pos
+ * the position of the first character to be selected
+ * @param length
+ * the number of characters to be selected
+ */
+ public void setSelectionRange(int pos, int length) {
+ selectionPosition = pos;
+ selectionLength = length;
+ focus();
+ markAsDirty();
+ }
+
+ /**
+ * Sets the cursor position in the field. As a side effect the field will
+ * become focused.
+ *
+ * @since 6.4
+ *
+ * @param pos
+ * the position for the cursor
+ */
+ public void setCursorPosition(int pos) {
+ setSelectionRange(pos, 0);
+ lastKnownCursorPosition = pos;
+ }
+
+ /**
+ * Returns the last known cursor position of the field.
+ *
+ * <p>
+ * Note that due to the client server nature or the GWT terminal, Vaadin
+ * cannot provide the exact value of the cursor position in most situations.
+ * The value is updated only when the client side terminal communicates to
+ * TextField, like on {@link ValueChangeEvent}s and {@link TextChangeEvent}
+ * s. This may change later if a deep push integration is built to Vaadin.
+ *
+ * @return the cursor position
+ */
+ public int getCursorPosition() {
+ return lastKnownCursorPosition;
+ }
+
+ @Override
+ public void addFocusListener(FocusListener listener) {
+ addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener,
+ FocusListener.focusMethod);
+ }
+
+ /**
+ * @deprecated As of 7.0, replaced by
+ * {@link #addFocusListener(FocusListener)}
+ **/
+ @Deprecated
+ public void addListener(FocusListener listener) {
+ addFocusListener(listener);
+ }
+
+ @Override
+ public void removeFocusListener(FocusListener listener) {
+ removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener);
+ }
+
+ /**
+ * @deprecated As of 7.0, replaced by
+ * {@link #removeFocusListener(FocusListener)}
+ **/
+ @Deprecated
+ public void removeListener(FocusListener listener) {
+ removeFocusListener(listener);
+ }
+
+ @Override
+ public void addBlurListener(BlurListener listener) {
+ addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener,
+ BlurListener.blurMethod);
+ }
+
+ /**
+ * @deprecated As of 7.0, replaced by {@link #addBlurListener(BlurListener)}
+ **/
+ @Deprecated
+ public void addListener(BlurListener listener) {
+ addBlurListener(listener);
+ }
+
+ @Override
+ public void removeBlurListener(BlurListener listener) {
+ removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener);
+ }
+
+ /**
+ * @deprecated As of 7.0, replaced by
+ * {@link #removeBlurListener(BlurListener)}
+ **/
+ @Deprecated
+ public void removeListener(BlurListener listener) {
+ removeBlurListener(listener);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.ui.AbstractField#readDesign(org.jsoup.nodes.Element ,
+ * com.vaadin.ui.declarative.DesignContext)
+ */
+ @Override
+ public void readDesign(Element design, DesignContext designContext) {
+ super.readDesign(design, designContext);
+ Attributes attr = design.attributes();
+ if (attr.hasKey("maxlength")) {
+ setMaxLength(DesignAttributeHandler.readAttribute("maxlength", attr,
+ Integer.class));
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.ui.AbstractField#getCustomAttributes()
+ */
+ @Override
+ protected Collection<String> getCustomAttributes() {
+ Collection<String> customAttributes = super.getCustomAttributes();
+ customAttributes.add("maxlength");
+ customAttributes.add("max-length"); // to prevent this appearing in
+ // output
+ customAttributes.add("cursor-position");
+ return customAttributes;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.ui.AbstractField#writeDesign(org.jsoup.nodes.Element,
+ * com.vaadin.ui.declarative.DesignContext)
+ */
+ @Override
+ public void writeDesign(Element design, DesignContext designContext) {
+ super.writeDesign(design, designContext);
+ AbstractTextField def = (AbstractTextField) designContext
+ .getDefaultInstance(this);
+ Attributes attr = design.attributes();
+ DesignAttributeHandler.writeAttribute("maxlength", attr, getMaxLength(),
+ def.getMaxLength(), Integer.class);
+ }
+
+}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/ui/TextField.java b/compatibility-server/src/main/java/com/vaadin/v7/ui/TextField.java
new file mode 100644
index 0000000000..0bd9511a71
--- /dev/null
+++ b/compatibility-server/src/main/java/com/vaadin/v7/ui/TextField.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2000-2016 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.v7.ui;
+
+import org.jsoup.nodes.Attributes;
+import org.jsoup.nodes.Element;
+
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+import com.vaadin.ui.declarative.DesignContext;
+import com.vaadin.v7.data.Property;
+
+/**
+ * <p>
+ * A text editor component that can be bound to any bindable Property. The text
+ * editor supports both multiline and single line modes, default is one-line
+ * mode.
+ * </p>
+ *
+ * <p>
+ * Since <code>TextField</code> extends <code>LegacyAbstractField</code> it
+ * implements the {@link com.vaadin.v7.data.Buffered} interface. A
+ * <code>TextField</code> is in write-through mode by default, so
+ * {@link com.vaadin.v7.ui.AbstractField#setWriteThrough(boolean)}
+ * must be called to enable buffering.
+ * </p>
+ *
+ * @author Vaadin Ltd.
+ * @since 3.0
+ */
+@SuppressWarnings("serial")
+@Deprecated
+public class TextField extends AbstractTextField {
+
+ /**
+ * Constructs an empty <code>TextField</code> with no caption.
+ */
+ public TextField() {
+ clear();
+ }
+
+ /**
+ * Constructs an empty <code>TextField</code> with given caption.
+ *
+ * @param caption
+ * the caption <code>String</code> for the editor.
+ */
+ public TextField(String caption) {
+ this();
+ setCaption(caption);
+ }
+
+ /**
+ * Constructs a new <code>TextField</code> that's bound to the specified
+ * <code>Property</code> and has no caption.
+ *
+ * @param dataSource
+ * the Property to be edited with this editor.
+ */
+ public TextField(Property dataSource) {
+ setPropertyDataSource(dataSource);
+ }
+
+ /**
+ * Constructs a new <code>TextField</code> that's bound to the specified
+ * <code>Property</code> and has the given caption <code>String</code>.
+ *
+ * @param caption
+ * the caption <code>String</code> for the editor.
+ * @param dataSource
+ * the Property to be edited with this editor.
+ */
+ public TextField(String caption, Property dataSource) {
+ this(dataSource);
+ setCaption(caption);
+ }
+
+ /**
+ * Constructs a new <code>TextField</code> with the given caption and
+ * initial text contents. The editor constructed this way will not be bound
+ * to a Property unless
+ * {@link com.vaadin.v7.data.Property.Viewer#setPropertyDataSource(Property)}
+ * is called to bind it.
+ *
+ * @param caption
+ * the caption <code>String</code> for the editor.
+ * @param value
+ * the initial text content of the editor.
+ */
+ public TextField(String caption, String value) {
+ setValue(value);
+ setCaption(caption);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.ui.AbstractTextField#readDesign(org.jsoup.nodes.Element,
+ * com.vaadin.ui.declarative.DesignContext)
+ */
+ @Override
+ public void readDesign(Element design, DesignContext designContext) {
+ super.readDesign(design, designContext);
+ Attributes attr = design.attributes();
+ if (attr.hasKey("value")) {
+ String newFieldValue = DesignAttributeHandler.readAttribute("value",
+ attr, String.class);
+ setValue(newFieldValue, false, true);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.ui.AbstractTextField#writeDesign(org.jsoup.nodes.Element
+ * , com.vaadin.ui.declarative.DesignContext)
+ */
+ @Override
+ public void writeDesign(Element design, DesignContext designContext) {
+ super.writeDesign(design, designContext);
+ AbstractTextField def = (AbstractTextField) designContext
+ .getDefaultInstance(this);
+ Attributes attr = design.attributes();
+ DesignAttributeHandler.writeAttribute("value", attr, getValue(),
+ def.getValue(), String.class);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.ui.AbstractField#clear()
+ */
+ @Override
+ public void clear() {
+ setValue("");
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/AnyEnumToStringConverterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/AnyEnumToStringConverterTest.java
new file mode 100644
index 0000000000..4f0c286d2d
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/AnyEnumToStringConverterTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2000-2016 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.v7.tests.data.converter;
+
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.tests.data.bean.AnotherTestEnum;
+import com.vaadin.tests.data.bean.TestEnum;
+import com.vaadin.v7.data.util.ObjectProperty;
+import com.vaadin.v7.data.util.converter.Converter;
+import com.vaadin.v7.data.util.converter.ReverseConverter;
+import com.vaadin.v7.ui.TextField;
+
+public class AnyEnumToStringConverterTest {
+
+ public class AnyEnumToStringConverter
+ implements Converter<Enum, String> {
+
+ public AnyEnumToStringConverter() {
+ }
+
+ @Override
+ public String convertToModel(Enum value,
+ Class<? extends String> targetType, Locale locale)
+ throws com.vaadin.v7.data.util.converter.Converter.ConversionException {
+ if (value == null) {
+ return null;
+ }
+
+ return value.toString();
+ }
+
+ @Override
+ public Enum convertToPresentation(String value,
+ Class<? extends Enum> targetType, Locale locale)
+ throws com.vaadin.v7.data.util.converter.Converter.ConversionException {
+ if (value == null) {
+ return null;
+ }
+ for (Enum e : targetType.getEnumConstants()) {
+ if (e.toString().equals(value)) {
+ return e;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public Class<String> getModelType() {
+ return String.class;
+ }
+
+ @Override
+ public Class<Enum> getPresentationType() {
+ return Enum.class;
+ }
+
+ }
+
+ private AnyEnumToStringConverter converter;
+
+ @Before
+ public void setup() {
+ converter = new AnyEnumToStringConverter();
+ }
+
+ @Test
+ public void nullConversion() {
+ Assert.assertEquals(null, converter.convertToModel(null, null, null));
+ }
+
+ @Test
+ public void enumToStringConversion() {
+ Assert.assertEquals(TestEnum.TWO.toString(),
+ converter.convertToModel(TestEnum.TWO, String.class, null));
+ Assert.assertEquals(AnotherTestEnum.TWO.toString(), converter
+ .convertToModel(AnotherTestEnum.TWO, String.class, null));
+ }
+
+ @Test
+ public void stringToEnumConversion() {
+ Assert.assertEquals(TestEnum.TWO, converter.convertToPresentation(
+ TestEnum.TWO.toString(), TestEnum.class, null));
+ Assert.assertEquals(AnotherTestEnum.TWO,
+ converter.convertToPresentation(AnotherTestEnum.TWO.toString(),
+ AnotherTestEnum.class, null));
+ }
+
+ @Test
+ public void stringToEnumWithField() {
+ TextField tf = new TextField();
+ tf.setConverter(new ReverseConverter(converter));
+ tf.setPropertyDataSource(new ObjectProperty(AnotherTestEnum.TWO));
+ Assert.assertEquals(AnotherTestEnum.TWO.toString(), tf.getValue());
+ tf.setValue(AnotherTestEnum.ONE.toString());
+ Assert.assertEquals(AnotherTestEnum.ONE.toString(), tf.getValue());
+ Assert.assertEquals(AnotherTestEnum.ONE, tf.getConvertedValue());
+ Assert.assertEquals(AnotherTestEnum.ONE,
+ tf.getPropertyDataSource().getValue());
+
+ tf.setPropertyDataSource(new ObjectProperty(TestEnum.TWO));
+ Assert.assertEquals(TestEnum.TWO.toString(), tf.getValue());
+ tf.setValue(TestEnum.ONE.toString());
+ Assert.assertEquals(TestEnum.ONE.toString(), tf.getValue());
+ Assert.assertEquals(TestEnum.ONE, tf.getConvertedValue());
+ Assert.assertEquals(TestEnum.ONE,
+ tf.getPropertyDataSource().getValue());
+
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/ConverterFactoryTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/ConverterFactoryTest.java
new file mode 100644
index 0000000000..1f3a64cbb7
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/ConverterFactoryTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2000-2016 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.v7.tests.data.converter;
+
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.server.VaadinSession;
+import com.vaadin.tests.util.AlwaysLockedVaadinSession;
+import com.vaadin.v7.data.util.converter.Converter;
+import com.vaadin.v7.data.util.converter.DefaultConverterFactory;
+import com.vaadin.v7.ui.TextField;
+
+public class ConverterFactoryTest {
+
+ public static class ConvertTo42
+ implements Converter<String, Integer> {
+
+ @Override
+ public Integer convertToModel(String value,
+ Class<? extends Integer> targetType, Locale locale)
+ throws com.vaadin.v7.data.util.converter.Converter.ConversionException {
+ return 42;
+ }
+
+ @Override
+ public String convertToPresentation(Integer value,
+ Class<? extends String> targetType, Locale locale)
+ throws com.vaadin.v7.data.util.converter.Converter.ConversionException {
+ return "42";
+ }
+
+ @Override
+ public Class<Integer> getModelType() {
+ return Integer.class;
+ }
+
+ @Override
+ public Class<String> getPresentationType() {
+ return String.class;
+ }
+
+ }
+
+ public static class ConverterFactory42
+ extends DefaultConverterFactory {
+ @Override
+ public <PRESENTATION, MODEL> Converter<PRESENTATION, MODEL> createConverter(
+ Class<PRESENTATION> presentationType, Class<MODEL> modelType) {
+ if (modelType == Integer.class) {
+ return (Converter<PRESENTATION, MODEL>) new ConvertTo42();
+ }
+
+ return super.createConverter(presentationType, modelType);
+ }
+ }
+
+ @Test
+ public void testApplicationConverterFactoryInBackgroundThread() {
+ VaadinSession.setCurrent(null);
+ final VaadinSession appWithCustomIntegerConverter = new AlwaysLockedVaadinSession(
+ null);
+ appWithCustomIntegerConverter
+ .setConverterFactory(new ConverterFactory42());
+
+ TextField tf = new TextField("", "123") {
+ @Override
+ public VaadinSession getSession() {
+ return appWithCustomIntegerConverter;
+ }
+ };
+ tf.setConverter(Integer.class);
+ // The application converter always returns 42. Current application is
+ // null
+ Assert.assertEquals(42, tf.getConvertedValue());
+ }
+
+ @Test
+ public void testApplicationConverterFactoryForDetachedComponent() {
+ final VaadinSession appWithCustomIntegerConverter = new AlwaysLockedVaadinSession(
+ null);
+ appWithCustomIntegerConverter
+ .setConverterFactory(new ConverterFactory42());
+ VaadinSession.setCurrent(appWithCustomIntegerConverter);
+
+ TextField tf = new TextField("", "123");
+ tf.setConverter(Integer.class);
+ // The application converter always returns 42. Current application is
+ // null
+ Assert.assertEquals(42, tf.getConvertedValue());
+ }
+
+ @Test
+ public void testApplicationConverterFactoryForDifferentThanCurrentApplication() {
+ final VaadinSession fieldAppWithCustomIntegerConverter = new AlwaysLockedVaadinSession(
+ null);
+ fieldAppWithCustomIntegerConverter
+ .setConverterFactory(new ConverterFactory42());
+ VaadinSession.setCurrent(new AlwaysLockedVaadinSession(null));
+
+ TextField tf = new TextField("", "123") {
+ @Override
+ public VaadinSession getSession() {
+ return fieldAppWithCustomIntegerConverter;
+ }
+ };
+ tf.setConverter(Integer.class);
+
+ // The application converter always returns 42. Application.getCurrent()
+ // should not be used
+ Assert.assertEquals(42, tf.getConvertedValue());
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/DateToLongConverterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/DateToLongConverterTest.java
new file mode 100644
index 0000000000..6300ed9479
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/DateToLongConverterTest.java
@@ -0,0 +1,28 @@
+package com.vaadin.v7.tests.data.converter;
+
+import java.util.Date;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.v7.data.util.converter.DateToLongConverter;
+
+public class DateToLongConverterTest {
+
+ DateToLongConverter converter = new DateToLongConverter();
+
+ @Test
+ public void testNullConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel(null, Long.class, null));
+ }
+
+ @Test
+ public void testValueConversion() {
+ Date d = new Date(100, 0, 1);
+ Assert.assertEquals(
+ Long.valueOf(946677600000l
+ + (d.getTimezoneOffset() + 120) * 60 * 1000L),
+ converter.convertToModel(d, Long.class, null));
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/DateToSqlDateConverterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/DateToSqlDateConverterTest.java
new file mode 100644
index 0000000000..35a8c5dbec
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/DateToSqlDateConverterTest.java
@@ -0,0 +1,28 @@
+package com.vaadin.v7.tests.data.converter;
+
+import java.util.Date;
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.v7.data.util.converter.DateToSqlDateConverter;
+
+public class DateToSqlDateConverterTest {
+
+ DateToSqlDateConverter converter = new DateToSqlDateConverter();
+
+ @Test
+ public void testNullConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel(null, java.sql.Date.class, null));
+ }
+
+ @Test
+ public void testValueConversion() {
+ Date testDate = new Date(100, 0, 1);
+ long time = testDate.getTime();
+ Assert.assertEquals(testDate, converter.convertToModel(
+ new java.sql.Date(time), java.sql.Date.class, Locale.ENGLISH));
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/DefaultConverterFactoryTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/DefaultConverterFactoryTest.java
new file mode 100644
index 0000000000..a157884376
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/DefaultConverterFactoryTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2000-2016 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.v7.tests.data.converter;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.v7.data.util.converter.DefaultConverterFactory;
+
+public class DefaultConverterFactoryTest {
+
+ private DefaultConverterFactory factory = new DefaultConverterFactory();
+
+ @Test
+ public void stringToBigDecimal() {
+ assertConverter("14", new BigDecimal("14"));
+ }
+
+ @Test
+ public void stringToBigInteger() {
+ assertConverter("14", new BigInteger("14"));
+ }
+
+ @Test
+ public void stringToDouble() {
+ assertConverter("14", new Double("14"));
+ }
+
+ @Test
+ public void stringToFloat() {
+ assertConverter("14", new Float("14"));
+ }
+
+ @Test
+ public void stringToInteger() {
+ assertConverter("14", new Integer("14"));
+ }
+
+ @Test
+ public void stringToLong() {
+ assertConverter("14", new Long("14"));
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void stringToDate() {
+ assertConverter("Oct 12, 2014 12:00:00 AM",
+ new Date(2014 - 1900, 10 - 1, 12));
+ }
+
+ @Test
+ public void sqlDateToDate() {
+ long l = 1413071210000L;
+ assertConverter(new java.sql.Date(l), new java.util.Date(l));
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void longToDate() {
+ Date d = new Date(2014 - 1900, 10 - 1, 12);
+ assertConverter(
+ 1413061200000L + (d.getTimezoneOffset() + 180) * 60 * 1000L, d);
+ }
+
+ public enum Foo {
+ BAR, BAZ;
+ }
+
+ @Test
+ public void stringToEnum() {
+ assertConverter("Bar", Foo.BAR);
+ }
+
+ @Test
+ public void stringToShort() {
+ assertConverter("14", new Short("14"));
+ }
+
+ @Test
+ public void stringToByte() {
+ assertConverter("14", new Byte("14"));
+ }
+
+ private <T, U> void assertConverter(T t, U u) {
+ Class<T> tClass = (Class<T>) t.getClass();
+ Class<U> uClass = (Class<U>) u.getClass();
+
+ U tConvertedToU = factory.createConverter(tClass, uClass)
+ .convertToModel(t, uClass, Locale.ENGLISH);
+ Assert.assertEquals("Incorrect type of value converted from "
+ + tClass.getSimpleName() + " to " + uClass.getSimpleName(),
+ uClass, tConvertedToU.getClass());
+ Assert.assertEquals("Incorrect conversion of " + t + " to "
+ + uClass.getSimpleName(), u, tConvertedToU);
+
+ T uConvertedToT = factory.createConverter(uClass, tClass)
+ .convertToModel(u, tClass, Locale.ENGLISH);
+ Assert.assertEquals("Incorrect type of value converted from "
+ + uClass.getSimpleName() + " to " + tClass.getSimpleName(),
+ tClass, uConvertedToT.getClass());
+ Assert.assertEquals("Incorrect conversion of " + u + " to "
+ + tClass.getSimpleName(), t, uConvertedToT);
+
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/SpecificEnumToStringConverterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/SpecificEnumToStringConverterTest.java
new file mode 100644
index 0000000000..10b4a0065e
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/SpecificEnumToStringConverterTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2000-2016 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.v7.tests.data.converter;
+
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.tests.data.bean.AnotherTestEnum;
+import com.vaadin.tests.data.bean.TestEnum;
+import com.vaadin.v7.data.util.ObjectProperty;
+import com.vaadin.v7.data.util.converter.Converter;
+import com.vaadin.v7.data.util.converter.ReverseConverter;
+import com.vaadin.v7.ui.TextField;
+
+public class SpecificEnumToStringConverterTest {
+
+ public class SpecificEnumToStringConverter
+ implements Converter<Enum, String> {
+
+ private Class<? extends Enum> enumClass;
+
+ public SpecificEnumToStringConverter(Class<? extends Enum> enumClass) {
+ this.enumClass = enumClass;
+ }
+
+ @Override
+ public String convertToModel(Enum value,
+ Class<? extends String> targetType, Locale locale)
+ throws com.vaadin.v7.data.util.converter.Converter.ConversionException {
+ if (value == null) {
+ return null;
+ }
+
+ return value.toString();
+ }
+
+ @Override
+ public Enum convertToPresentation(String value,
+ Class<? extends Enum> targetType, Locale locale)
+ throws com.vaadin.v7.data.util.converter.Converter.ConversionException {
+ if (value == null) {
+ return null;
+ }
+
+ for (Enum e : enumClass.getEnumConstants()) {
+ if (e.toString().equals(value)) {
+ return e;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public Class<String> getModelType() {
+ return String.class;
+ }
+
+ @Override
+ public Class<Enum> getPresentationType() {
+ return (Class<Enum>) enumClass;
+ }
+
+ }
+
+ SpecificEnumToStringConverter testEnumConverter;
+ SpecificEnumToStringConverter anotherTestEnumConverter;
+
+ @Before
+ public void setup() {
+ testEnumConverter = new SpecificEnumToStringConverter(TestEnum.class);
+ anotherTestEnumConverter = new SpecificEnumToStringConverter(
+ AnotherTestEnum.class);
+ }
+
+ @Test
+ public void nullConversion() {
+ Assert.assertEquals(null,
+ testEnumConverter.convertToModel(null, null, null));
+ }
+
+ @Test
+ public void enumToStringConversion() {
+ Assert.assertEquals(TestEnum.TWO.toString(), testEnumConverter
+ .convertToModel(TestEnum.TWO, String.class, null));
+ }
+
+ @Test
+ public void stringToEnumConversion() {
+ Assert.assertEquals(TestEnum.TWO,
+ testEnumConverter.convertToPresentation(TestEnum.TWO.toString(),
+ TestEnum.class, null));
+ }
+
+ @Test
+ public void stringToEnumWithField() {
+ TextField tf = new TextField();
+ tf.setConverter(new ReverseConverter(anotherTestEnumConverter));
+ tf.setPropertyDataSource(new ObjectProperty(AnotherTestEnum.TWO));
+ Assert.assertEquals(AnotherTestEnum.TWO.toString(), tf.getValue());
+ tf.setValue(AnotherTestEnum.ONE.toString());
+ Assert.assertEquals(AnotherTestEnum.ONE.toString(), tf.getValue());
+ Assert.assertEquals(AnotherTestEnum.ONE, tf.getConvertedValue());
+ Assert.assertEquals(AnotherTestEnum.ONE,
+ tf.getPropertyDataSource().getValue());
+
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToBigDecimalConverterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToBigDecimalConverterTest.java
new file mode 100644
index 0000000000..00e384e594
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToBigDecimalConverterTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2016 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.v7.tests.data.converter;
+
+import java.math.BigDecimal;
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.v7.data.util.converter.StringToBigDecimalConverter;
+
+public class StringToBigDecimalConverterTest {
+
+ StringToBigDecimalConverter converter = new StringToBigDecimalConverter();
+
+ @Test
+ public void testNullConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel(null, BigDecimal.class, null));
+ }
+
+ @Test
+ public void testEmptyStringConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel("", BigDecimal.class, null));
+ }
+
+ @Test
+ public void testValueParsing() {
+ BigDecimal converted = converter.convertToModel("10", BigDecimal.class,
+ null);
+ BigDecimal expected = new BigDecimal(10);
+ Assert.assertEquals(expected, converted);
+ }
+
+ @Test
+ public void testValueFormatting() {
+ BigDecimal bd = new BigDecimal(12.5);
+ String expected = "12,5";
+
+ String converted = converter.convertToPresentation(bd, String.class,
+ Locale.GERMAN);
+ Assert.assertEquals(expected, converted);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToBigIntegerConverterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToBigIntegerConverterTest.java
new file mode 100644
index 0000000000..f613950c71
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToBigIntegerConverterTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2000-2016 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.v7.tests.data.converter;
+
+import java.math.BigInteger;
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.v7.data.util.converter.StringToBigIntegerConverter;
+
+public class StringToBigIntegerConverterTest {
+
+ StringToBigIntegerConverter converter = new StringToBigIntegerConverter();
+
+ @Test
+ public void testNullConversion() {
+ Assert.assertEquals("Null value was converted incorrectly", null,
+ converter.convertToModel(null, BigInteger.class, null));
+ }
+
+ @Test
+ public void testEmptyStringConversion() {
+ Assert.assertEquals("Empty value was converted incorrectly", null,
+ converter.convertToModel("", BigInteger.class, null));
+ }
+
+ @Test
+ public void testValueParsing() {
+ String bigInt = "1180591620717411303424"; // 2^70 > 2^63 - 1
+ BigInteger converted = converter.convertToModel(bigInt,
+ BigInteger.class, null);
+ BigInteger expected = new BigInteger(bigInt);
+ Assert.assertEquals(
+ "Value bigger than max long was converted incorrectly",
+ expected, converted);
+ }
+
+ @Test
+ public void testValueFormatting() {
+ BigInteger bd = new BigInteger("1000");
+ String expected = "1.000";
+
+ String converted = converter.convertToPresentation(bd, String.class,
+ Locale.GERMAN);
+ Assert.assertEquals(
+ "Value with specific locale was converted incorrectly",
+ expected, converted);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToBooleanConverterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToBooleanConverterTest.java
new file mode 100644
index 0000000000..9f94a4185e
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToBooleanConverterTest.java
@@ -0,0 +1,82 @@
+package com.vaadin.v7.tests.data.converter;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.v7.data.util.converter.StringToBooleanConverter;
+
+public class StringToBooleanConverterTest {
+
+ StringToBooleanConverter converter = new StringToBooleanConverter();
+ StringToBooleanConverter yesNoConverter = new StringToBooleanConverter(
+ "yes", "no");
+ StringToBooleanConverter localeConverter = new StringToBooleanConverter() {
+ @Override
+ public String getFalseString(Locale locale) {
+ Date d = new Date(3000000000000L);
+ return SimpleDateFormat
+ .getDateInstance(SimpleDateFormat.LONG, locale)
+ .format(d.getTime()
+ + (d.getTimezoneOffset() + 120) * 60 * 1000L);
+ }
+
+ @Override
+ public String getTrueString(Locale locale) {
+ Date d = new Date(2000000000000L);
+ return SimpleDateFormat
+ .getDateInstance(SimpleDateFormat.LONG, locale)
+ .format(d.getTime()
+ + (d.getTimezoneOffset() + 120) * 60 * 1000L);
+ }
+ };
+
+ @Test
+ public void testNullConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel(null, Boolean.class, null));
+ }
+
+ @Test
+ public void testEmptyStringConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel("", Boolean.class, null));
+ }
+
+ @Test
+ public void testValueConversion() {
+ Assert.assertTrue(
+ converter.convertToModel("true", Boolean.class, null));
+ Assert.assertFalse(
+ converter.convertToModel("false", Boolean.class, null));
+ }
+
+ @Test
+ public void testYesNoValueConversion() {
+ Assert.assertTrue(
+ yesNoConverter.convertToModel("yes", Boolean.class, null));
+ Assert.assertFalse(
+ yesNoConverter.convertToModel("no", Boolean.class, null));
+
+ Assert.assertEquals("yes",
+ yesNoConverter.convertToPresentation(true, String.class, null));
+ Assert.assertEquals("no", yesNoConverter.convertToPresentation(false,
+ String.class, null));
+ }
+
+ @Test
+ public void testLocale() {
+ Assert.assertEquals("May 18, 2033", localeConverter
+ .convertToPresentation(true, String.class, Locale.US));
+ Assert.assertEquals("January 24, 2065", localeConverter
+ .convertToPresentation(false, String.class, Locale.US));
+
+ Assert.assertEquals("18. Mai 2033", localeConverter
+ .convertToPresentation(true, String.class, Locale.GERMANY));
+ Assert.assertEquals("24. Januar 2065", localeConverter
+ .convertToPresentation(false, String.class, Locale.GERMANY));
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToByteConverterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToByteConverterTest.java
new file mode 100644
index 0000000000..1ffc7a020e
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToByteConverterTest.java
@@ -0,0 +1,76 @@
+package com.vaadin.v7.tests.data.converter;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.v7.data.util.converter.Converter;
+import com.vaadin.v7.data.util.converter.Converter.ConversionException;
+import com.vaadin.v7.data.util.converter.ReverseConverter;
+import com.vaadin.v7.data.util.converter.StringToByteConverter;
+
+public class StringToByteConverterTest {
+
+ StringToByteConverter converter = new StringToByteConverter();
+ Converter<Byte, String> reverseConverter = new ReverseConverter<Byte, String>(
+ converter);
+
+ @Test
+ public void testNullConversion() {
+ Assert.assertEquals("Null value was converted incorrectly", null,
+ converter.convertToModel(null, Byte.class, null));
+ }
+
+ @Test
+ public void testReverseNullConversion() {
+ Assert.assertEquals("Null value reversely was converted incorrectly",
+ null,
+ reverseConverter.convertToModel(null, String.class, null));
+ }
+
+ @Test
+ public void testEmptyStringConversion() {
+ Assert.assertEquals("Empty value was converted incorrectly", null,
+ converter.convertToModel("", Byte.class, null));
+ }
+
+ @Test
+ public void testValueConversion() {
+ Assert.assertEquals("Byte value was converted incorrectly",
+ Byte.valueOf((byte) 10),
+ converter.convertToModel("10", Byte.class, null));
+ }
+
+ @Test
+ public void testReverseValueConversion() {
+ Assert.assertEquals("Byte value reversely was converted incorrectly",
+ reverseConverter.convertToModel((byte) 10, String.class, null),
+ "10");
+ }
+
+ @Test
+ public void testExtremeByteValueConversion() {
+ byte b = converter.convertToModel("127", Byte.class, null);
+ Assert.assertEquals(Byte.MAX_VALUE, b);
+ b = converter.convertToModel("-128", Byte.class, null);
+ Assert.assertEquals("Min byte value was converted incorrectly",
+ Byte.MIN_VALUE, b);
+ }
+
+ @Test
+ public void testValueOutOfRange() {
+ Double[] values = new Double[] { Byte.MAX_VALUE * 2.0,
+ Byte.MIN_VALUE * 2.0, Long.MAX_VALUE * 2.0,
+ Long.MIN_VALUE * 2.0 };
+
+ boolean accepted = false;
+ for (Number value : values) {
+ try {
+ converter.convertToModel(String.format("%.0f", value),
+ Byte.class, null);
+ accepted = true;
+ } catch (ConversionException expected) {
+ }
+ }
+ Assert.assertFalse("Accepted value outside range of int", accepted);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToCollectionConverterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToCollectionConverterTest.java
new file mode 100644
index 0000000000..f6dc22face
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToCollectionConverterTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2000-2016 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.v7.tests.data.converter;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.Vector;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.v7.data.util.converter.StringToCollectionConverter;
+import com.vaadin.v7.data.util.converter.StringToCollectionConverter.CollectionFactory;
+import com.vaadin.v7.data.util.converter.StringToEnumConverter;
+import com.vaadin.v7.data.util.converter.StringToIntegerConverter;
+
+/**
+ * Tests for {@link StringToCollectionConverter}.
+ *
+ * @author Vaadin Ltd
+ */
+public class StringToCollectionConverterTest {
+
+ @Test
+ public void convertToModel_defaultCtor() {
+ StringToCollectionConverter converter = new StringToCollectionConverter();
+ Collection<?> model = converter.convertToModel("a, b, c", List.class,
+ null);
+ Assert.assertTrue("Unexpected model class", model instanceof ArrayList);
+ Iterator<?> iterator = model.iterator();
+ Assert.assertEquals("Incorrect fist token", "a", iterator.next());
+ Assert.assertEquals("Incorrect second token", "b", iterator.next());
+ Assert.assertEquals("Incorrect third token", "c", iterator.next());
+ }
+
+ @Test
+ public void convertToModel_customDelimiter() {
+ StringToCollectionConverter converter = new StringToCollectionConverter(
+ "x");
+ Collection<?> model = converter.convertToModel("axbxc", List.class,
+ null);
+ Assert.assertTrue("Unexpected model class", model instanceof ArrayList);
+ Iterator<?> iterator = model.iterator();
+ Assert.assertEquals("Incorrect fist token", "a", iterator.next());
+ Assert.assertEquals("Incorrect second token", "b", iterator.next());
+ Assert.assertEquals("Incorrect third token", "c", iterator.next());
+ }
+
+ @Test
+ public void convertToModel_customConverter() {
+ StringToCollectionConverter converter = new StringToCollectionConverter(
+ ",", new StringToIntegerConverter(), Integer.class);
+ Collection<?> model = converter.convertToModel("6,2,5", List.class,
+ null);
+ Assert.assertTrue("Unexpected model class", model instanceof ArrayList);
+ Iterator<?> iterator = model.iterator();
+ Assert.assertEquals("Incorrect fist token", 6, iterator.next());
+ Assert.assertEquals("Incorrect second token", 2, iterator.next());
+ Assert.assertEquals("Incorrect third token", 5, iterator.next());
+ }
+
+ @Test
+ public void convertToModel_setAsCollection() {
+ StringToCollectionConverter converter = new StringToCollectionConverter(
+ " ", new StringToEnumConverter(), TestEnum.class);
+ Collection<?> model = converter.convertToModel("Z X Y", Set.class,
+ null);
+ Assert.assertTrue("Unexpected model class", model instanceof HashSet);
+ EnumSet<TestEnum> set = EnumSet.allOf(TestEnum.class);
+ set.removeAll(model);
+ Assert.assertTrue("Some values are not in resutling collection",
+ set.isEmpty());
+ }
+
+ @Test
+ public void convertToModel_customFactory() {
+ CollectionFactory factory = new CollectionFactory() {
+
+ @Override
+ public Collection<?> createCollection(
+ Class<? extends Collection> type) {
+ return new Vector();
+ }
+ };
+ StringToCollectionConverter converter = new StringToCollectionConverter(
+ ", ", null, String.class, factory);
+ Collection<?> model = converter.convertToModel("a, b, c",
+ Collection.class, null);
+ Assert.assertTrue("Unexpected model class", model instanceof Vector);
+ Iterator<?> iterator = model.iterator();
+ Assert.assertEquals("Incorrect fist token", "a", iterator.next());
+ Assert.assertEquals("Incorrect second token", "b", iterator.next());
+ Assert.assertEquals("Incorrect third token", "c", iterator.next());
+ }
+
+ @Test
+ public void convertToPresentation_default() {
+ StringToCollectionConverter converter = new StringToCollectionConverter();
+ String presentation = converter.convertToPresentation(
+ Arrays.asList("a", "b", "c"), String.class, null);
+
+ Assert.assertEquals("a, b, c", presentation);
+ }
+
+ @Test
+ public void convertToPresentation_customDelimiter() {
+ StringToCollectionConverter converter = new StringToCollectionConverter(
+ "x");
+ String presentation = converter.convertToPresentation(
+ Arrays.asList("a", "b", "c"), String.class, null);
+
+ Assert.assertEquals("axbxc", presentation);
+ }
+
+ @Test
+ public void convertToPresentation_customConverter() {
+ StringToCollectionConverter converter = new StringToCollectionConverter(
+ ",", new StringToEnumConverter(), TestEnum.class);
+ String presentation = converter.convertToPresentation(
+ Arrays.asList(TestEnum.Z, TestEnum.Y), String.class, null);
+
+ Assert.assertEquals("Z,Y", presentation);
+ }
+
+ @Test
+ public void convertToModel_singleItem() {
+ StringToCollectionConverter converter = new StringToCollectionConverter();
+ Collection<?> model = converter.convertToModel("a", List.class, null);
+ Iterator<?> iterator = model.iterator();
+ Assert.assertEquals("Incorrect fist token", "a", iterator.next());
+ Assert.assertFalse("More than one item detected after conversation",
+ iterator.hasNext());
+ }
+
+ @Test
+ public void convertToModel_null() {
+ StringToCollectionConverter converter = new StringToCollectionConverter();
+ Assert.assertNull(converter.convertToModel(null, ArrayList.class,
+ Locale.ENGLISH));
+ }
+
+ @Test
+ public void convertToPresentation_null() {
+ StringToCollectionConverter converter = new StringToCollectionConverter();
+ Assert.assertNull(converter.convertToPresentation(null, String.class,
+ Locale.ENGLISH));
+ }
+
+ public enum TestEnum {
+ X, Y, Z;
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToDateConverterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToDateConverterTest.java
new file mode 100644
index 0000000000..c778e9e731
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToDateConverterTest.java
@@ -0,0 +1,32 @@
+package com.vaadin.v7.tests.data.converter;
+
+import java.util.Date;
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.v7.data.util.converter.StringToDateConverter;
+
+public class StringToDateConverterTest {
+
+ StringToDateConverter converter = new StringToDateConverter();
+
+ @Test
+ public void testNullConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel(null, Date.class, null));
+ }
+
+ @Test
+ public void testEmptyStringConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel("", Date.class, null));
+ }
+
+ @Test
+ public void testValueConversion() {
+ Assert.assertEquals(new Date(100, 0, 1), converter.convertToModel(
+ "Jan 1, 2000 12:00:00 AM", Date.class, Locale.ENGLISH));
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToDoubleConverterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToDoubleConverterTest.java
new file mode 100644
index 0000000000..a0891ecefe
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToDoubleConverterTest.java
@@ -0,0 +1,29 @@
+package com.vaadin.v7.tests.data.converter;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.v7.data.util.converter.StringToDoubleConverter;
+
+public class StringToDoubleConverterTest {
+
+ StringToDoubleConverter converter = new StringToDoubleConverter();
+
+ @Test
+ public void testNullConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel(null, Double.class, null));
+ }
+
+ @Test
+ public void testEmptyStringConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel("", Double.class, null));
+ }
+
+ @Test
+ public void testValueConversion() {
+ Double value = converter.convertToModel("10", Double.class, null);
+ Assert.assertEquals(10.0d, value, 0.01d);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToEnumConverterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToEnumConverterTest.java
new file mode 100644
index 0000000000..a86b8b82e0
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToEnumConverterTest.java
@@ -0,0 +1,135 @@
+package com.vaadin.v7.tests.data.converter;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.v7.data.util.converter.Converter;
+import com.vaadin.v7.data.util.converter.Converter.ConversionException;
+import com.vaadin.v7.data.util.converter.ReverseConverter;
+import com.vaadin.v7.data.util.converter.StringToEnumConverter;
+
+public class StringToEnumConverterTest {
+
+ public static enum FooEnum {
+ VALUE1, SOME_VALUE, FOO_BAR_BAZ, Bar, nonStandardCase, _HUGH;
+ }
+
+ public static enum EnumWithCustomToString {
+ ONE, TWO, THREE;
+
+ @Override
+ public String toString() {
+ return "case " + (ordinal() + 1);
+ }
+ }
+
+ public static enum EnumWithAmbigousToString {
+ FOO, FOOBAR, FOO_BAR;
+
+ @Override
+ public String toString() {
+ return name().replaceAll("_", "");
+ }
+ }
+
+ StringToEnumConverter converter = new StringToEnumConverter();
+ Converter<Enum, String> reverseConverter = new ReverseConverter<Enum, String>(
+ converter);
+
+ private String convertToString(Enum value) {
+ return converter.convertToPresentation(value, String.class, null);
+ }
+
+ public Enum convertToEnum(String string, Class<? extends Enum> type) {
+ return converter.convertToModel(string, type, null);
+ }
+
+ @Test
+ public void testEmptyStringConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel("", Enum.class, null));
+ }
+
+ @Test
+ public void testInvalidEnumClassConversion() {
+ try {
+ converter.convertToModel("Foo", Enum.class, null);
+ Assert.fail("No exception thrown");
+ } catch (ConversionException e) {
+ // OK
+ }
+ }
+
+ @Test
+ public void testNullConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel(null, Enum.class, null));
+ }
+
+ @Test
+ public void testReverseNullConversion() {
+ Assert.assertEquals(null,
+ reverseConverter.convertToModel(null, String.class, null));
+ }
+
+ @Test
+ public void testValueConversion() {
+ Assert.assertEquals(FooEnum.VALUE1,
+ converter.convertToModel("Value1", FooEnum.class, null));
+ Assert.assertEquals(FooEnum.SOME_VALUE,
+ converter.convertToModel("Some value", FooEnum.class, null));
+ Assert.assertEquals(FooEnum.FOO_BAR_BAZ,
+ converter.convertToModel("Foo bar baz", FooEnum.class, null));
+ Assert.assertEquals(FooEnum.Bar,
+ converter.convertToModel("Bar", FooEnum.class, null));
+ Assert.assertEquals(FooEnum.nonStandardCase, converter
+ .convertToModel("Nonstandardcase", FooEnum.class, null));
+ Assert.assertEquals(FooEnum._HUGH,
+ converter.convertToModel("_hugh", FooEnum.class, null));
+ }
+
+ @Test
+ public void testReverseValueConversion() {
+ Assert.assertEquals("Value1", reverseConverter
+ .convertToModel(FooEnum.VALUE1, String.class, null));
+ Assert.assertEquals("Some value", reverseConverter
+ .convertToModel(FooEnum.SOME_VALUE, String.class, null));
+ Assert.assertEquals("Foo bar baz", reverseConverter
+ .convertToModel(FooEnum.FOO_BAR_BAZ, String.class, null));
+ Assert.assertEquals("Bar", reverseConverter.convertToModel(FooEnum.Bar,
+ String.class, null));
+ Assert.assertEquals("Nonstandardcase", reverseConverter
+ .convertToModel(FooEnum.nonStandardCase, String.class, null));
+ Assert.assertEquals("_hugh", reverseConverter
+ .convertToModel(FooEnum._HUGH, String.class, null));
+
+ }
+
+ @Test
+ public void preserveFormattingWithCustomToString() {
+ for (EnumWithCustomToString e : EnumWithCustomToString.values()) {
+ Assert.assertEquals(e.toString(), convertToString(e));
+ }
+ }
+
+ @Test
+ public void findEnumWithCustomToString() {
+ for (EnumWithCustomToString e : EnumWithCustomToString.values()) {
+ Assert.assertSame(e,
+ convertToEnum(e.toString(), EnumWithCustomToString.class));
+ Assert.assertSame(e,
+ convertToEnum(e.name(), EnumWithCustomToString.class));
+ }
+ }
+
+ @Test
+ public void unambigousValueInEnumWithAmbigous_succeed() {
+ Assert.assertSame(EnumWithAmbigousToString.FOO,
+ convertToEnum("foo", EnumWithAmbigousToString.class));
+ }
+
+ @Test(expected = ConversionException.class)
+ public void ambigousValue_throws() {
+ convertToEnum("foobar", EnumWithAmbigousToString.class);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToFloatConverterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToFloatConverterTest.java
new file mode 100644
index 0000000000..70c408b808
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToFloatConverterTest.java
@@ -0,0 +1,29 @@
+package com.vaadin.v7.tests.data.converter;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.v7.data.util.converter.StringToFloatConverter;
+
+public class StringToFloatConverterTest {
+
+ StringToFloatConverter converter = new StringToFloatConverter();
+
+ @Test
+ public void testNullConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel(null, Float.class, null));
+ }
+
+ @Test
+ public void testEmptyStringConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel("", Float.class, null));
+ }
+
+ @Test
+ public void testValueConversion() {
+ Assert.assertEquals(Float.valueOf(10),
+ converter.convertToModel("10", Float.class, null));
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToIntegerConverterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToIntegerConverterTest.java
new file mode 100644
index 0000000000..0cc8e646dc
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToIntegerConverterTest.java
@@ -0,0 +1,48 @@
+package com.vaadin.v7.tests.data.converter;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.v7.data.util.converter.Converter.ConversionException;
+import com.vaadin.v7.data.util.converter.StringToIntegerConverter;
+
+public class StringToIntegerConverterTest {
+
+ StringToIntegerConverter converter = new StringToIntegerConverter();
+
+ @Test
+ public void testNullConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel(null, Integer.class, null));
+ }
+
+ @Test
+ public void testEmptyStringConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel("", Integer.class, null));
+ }
+
+ @Test
+ public void testValueOutOfRange() {
+ Double[] values = new Double[] { Integer.MAX_VALUE * 2.0,
+ Integer.MIN_VALUE * 2.0, Long.MAX_VALUE * 2.0,
+ Long.MIN_VALUE * 2.0 };
+
+ boolean accepted = false;
+ for (Number value : values) {
+ try {
+ converter.convertToModel(String.format("%.0f", value),
+ Integer.class, null);
+ accepted = true;
+ } catch (ConversionException expected) {
+ }
+ }
+ Assert.assertFalse("Accepted value outside range of int", accepted);
+ }
+
+ @Test
+ public void testValueConversion() {
+ Assert.assertEquals(Integer.valueOf(10),
+ converter.convertToModel("10", Integer.class, null));
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToLongConverterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToLongConverterTest.java
new file mode 100644
index 0000000000..5e5b9f1d86
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToLongConverterTest.java
@@ -0,0 +1,78 @@
+package com.vaadin.v7.tests.data.converter;
+
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.v7.data.util.converter.Converter;
+import com.vaadin.v7.data.util.converter.ReverseConverter;
+import com.vaadin.v7.data.util.converter.StringToLongConverter;
+
+public class StringToLongConverterTest {
+
+ StringToLongConverter converter = new StringToLongConverter();
+ Converter<Long, String> reverseConverter = new ReverseConverter<Long, String>(
+ converter);
+
+ @Test
+ public void testNullConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel(null, Long.class, null));
+ }
+
+ @Test
+ public void testReverseNullConversion() {
+ Assert.assertEquals(null,
+ reverseConverter.convertToModel(null, String.class, null));
+ }
+
+ @Test
+ public void testEmptyStringConversion() {
+ Assert.assertEquals(null,
+ converter.convertToModel("", Long.class, null));
+ }
+
+ @Test
+ public void testValueConversion() {
+ Assert.assertEquals(Long.valueOf(10),
+ converter.convertToModel("10", Long.class, null));
+ }
+
+ @Test
+ public void testReverseValueConversion() {
+ Assert.assertEquals(
+ reverseConverter.convertToModel(10L, String.class, null), "10");
+ }
+
+ @Test
+ public void testExtremeLongValueConversion() {
+ long l = converter.convertToModel("9223372036854775807", Long.class,
+ null);
+ Assert.assertEquals(Long.MAX_VALUE, l);
+ l = converter.convertToModel("-9223372036854775808", Long.class, null);
+ Assert.assertEquals(Long.MIN_VALUE, l);
+ }
+
+ @Test
+ public void testExtremeReverseLongValueConversion() {
+ String str = reverseConverter.convertToModel(Long.MAX_VALUE,
+ String.class, Locale.ENGLISH);
+ Assert.assertEquals("9,223,372,036,854,775,807", str);
+ str = reverseConverter.convertToModel(Long.MIN_VALUE, String.class,
+ Locale.ENGLISH);
+ Assert.assertEquals("-9,223,372,036,854,775,808", str);
+ }
+
+ @Test
+ public void testOutOfBoundsValueConversion() {
+ // Long.MAX_VALUE+1 is converted to Long.MAX_VALUE
+ long l = converter.convertToModel("9223372036854775808", Long.class,
+ null);
+ Assert.assertEquals(Long.MAX_VALUE, l);
+ // Long.MIN_VALUE-1 is converted to Long.MIN_VALUE
+ l = converter.convertToModel("-9223372036854775809", Long.class, null);
+ Assert.assertEquals(Long.MIN_VALUE, l);
+
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToShortConverterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToShortConverterTest.java
new file mode 100644
index 0000000000..a2a7332fd1
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/converter/StringToShortConverterTest.java
@@ -0,0 +1,76 @@
+package com.vaadin.v7.tests.data.converter;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.v7.data.util.converter.Converter;
+import com.vaadin.v7.data.util.converter.Converter.ConversionException;
+import com.vaadin.v7.data.util.converter.ReverseConverter;
+import com.vaadin.v7.data.util.converter.StringToShortConverter;
+
+public class StringToShortConverterTest {
+
+ StringToShortConverter converter = new StringToShortConverter();
+ Converter<Short, String> reverseConverter = new ReverseConverter<Short, String>(
+ converter);
+
+ @Test
+ public void testNullConversion() {
+ Assert.assertEquals("Null value was converted incorrectly", null,
+ converter.convertToModel(null, Short.class, null));
+ }
+
+ @Test
+ public void testReverseNullConversion() {
+ Assert.assertEquals("Null value reversely was converted incorrectly",
+ null,
+ reverseConverter.convertToModel(null, String.class, null));
+ }
+
+ @Test
+ public void testEmptyStringConversion() {
+ Assert.assertEquals("Empty value was converted incorrectly", null,
+ converter.convertToModel("", Short.class, null));
+ }
+
+ @Test
+ public void testValueConversion() {
+ Assert.assertEquals("Short value was converted incorrectly",
+ Short.valueOf((short) 10),
+ converter.convertToModel("10", Short.class, null));
+ }
+
+ @Test
+ public void testReverseValueConversion() {
+ Assert.assertEquals("Short value reversely was converted incorrectly",
+ reverseConverter.convertToModel((short) 10, String.class, null),
+ "10");
+ }
+
+ @Test
+ public void testExtremeShortValueConversion() {
+ short b = converter.convertToModel("32767", Short.class, null);
+ Assert.assertEquals(Short.MAX_VALUE, b);
+ b = converter.convertToModel("-32768", Short.class, null);
+ Assert.assertEquals("Min short value was converted incorrectly",
+ Short.MIN_VALUE, b);
+ }
+
+ @Test
+ public void testValueOutOfRange() {
+ Double[] values = new Double[] { Integer.MAX_VALUE * 2.0,
+ Integer.MIN_VALUE * 2.0, Long.MAX_VALUE * 2.0,
+ Long.MIN_VALUE * 2.0 };
+
+ boolean accepted = false;
+ for (Number value : values) {
+ try {
+ converter.convertToModel(String.format("%.0f", value),
+ Short.class, null);
+ accepted = true;
+ } catch (ConversionException expected) {
+ }
+ }
+ Assert.assertFalse("Accepted value outside range of int", accepted);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/EventRouterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/EventRouterTest.java
new file mode 100644
index 0000000000..7731941ca6
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/EventRouterTest.java
@@ -0,0 +1,40 @@
+package com.vaadin.v7.tests.server;
+
+import org.junit.Test;
+
+import com.vaadin.v7.data.Property.ValueChangeEvent;
+import com.vaadin.v7.data.Property.ValueChangeListener;
+import com.vaadin.v7.ui.TextField;
+
+public class EventRouterTest {
+
+ int innerListenerCalls = 0;
+
+ @Test
+ public void testAddInEventListener() {
+ final TextField tf = new TextField();
+
+ final ValueChangeListener outer = new ValueChangeListener() {
+
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ ValueChangeListener inner = new ValueChangeListener() {
+
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ innerListenerCalls++;
+ System.out.println("The inner listener was called");
+ }
+ };
+
+ tf.addListener(inner);
+ }
+ };
+
+ tf.addListener(outer);
+ tf.setValue("abc"); // No inner listener calls, adds one inner
+ tf.setValue("def"); // One inner listener call, adds one inner
+ tf.setValue("ghi"); // Two inner listener calls, adds one inner
+ assert (innerListenerCalls == 3);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/PropertysetItemListenersTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/PropertysetItemListenersTest.java
index 883130db32..8d1f432170 100644
--- a/compatibility-server/src/test/java/com/vaadin/tests/server/PropertysetItemListenersTest.java
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/PropertysetItemListenersTest.java
@@ -1,4 +1,4 @@
-package com.vaadin.tests.server;
+package com.vaadin.v7.tests.server;
import com.vaadin.tests.server.component.AbstractListenerMethodsTestBase;
import com.vaadin.v7.data.Item.PropertySetChangeEvent;
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbsFieldDataSourceLocaleChangeTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbsFieldDataSourceLocaleChangeTest.java
new file mode 100644
index 0000000000..5cc57a75b7
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbsFieldDataSourceLocaleChangeTest.java
@@ -0,0 +1,65 @@
+package com.vaadin.v7.tests.server.component.abstractfield;
+
+import java.text.NumberFormat;
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.VaadinSession;
+import com.vaadin.tests.util.AlwaysLockedVaadinSession;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.v7.data.util.converter.StringToIntegerConverter;
+import com.vaadin.v7.ui.TextField;
+
+public class AbsFieldDataSourceLocaleChangeTest {
+
+ private VaadinSession vaadinSession;
+ private UI ui;
+
+ @Before
+ public void setup() {
+ vaadinSession = new AlwaysLockedVaadinSession(null);
+ VaadinSession.setCurrent(vaadinSession);
+ ui = new UI() {
+
+ @Override
+ protected void init(VaadinRequest request) {
+
+ }
+ };
+ ui.setSession(vaadinSession);
+ UI.setCurrent(ui);
+ }
+
+ @Test
+ public void localeChangesOnAttach() {
+ TextField tf = new TextField();
+
+ tf.setConverter(new StringToIntegerConverter() {
+ @Override
+ protected NumberFormat getFormat(Locale locale) {
+ if (locale == null) {
+ NumberFormat format = super.getFormat(locale);
+ format.setGroupingUsed(false);
+ format.setMinimumIntegerDigits(10);
+ return format;
+ }
+ return super.getFormat(locale);
+ }
+ });
+ tf.setImmediate(true);
+ tf.setConvertedValue(10000);
+ Assert.assertEquals("0000010000", tf.getValue());
+
+ VerticalLayout vl = new VerticalLayout();
+ ui.setContent(vl);
+ ui.setLocale(new Locale("en", "US"));
+
+ vl.addComponent(tf);
+ Assert.assertEquals("10,000", tf.getValue());
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbsFieldValidatorsTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbsFieldValidatorsTest.java
new file mode 100644
index 0000000000..09ab8fe65f
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbsFieldValidatorsTest.java
@@ -0,0 +1,79 @@
+package com.vaadin.v7.tests.server.component.abstractfield;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+import com.vaadin.v7.data.Validator;
+import com.vaadin.v7.ui.AbstractField;
+
+public class AbsFieldValidatorsTest {
+
+ AbstractField<Object> field = new AbstractField<Object>() {
+ @Override
+ public Class getType() {
+ return Object.class;
+ }
+ };
+
+ Validator validator = EasyMock.createMock(Validator.class);
+ Validator validator2 = EasyMock.createMock(Validator.class);
+
+ @Test
+ public void testAddValidator() {
+ assertNotNull(field.getValidators());
+ assertEquals(0, field.getValidators().size());
+
+ field.addValidator(validator);
+ assertEquals(1, field.getValidators().size());
+ assertTrue(field.getValidators().contains(validator));
+
+ field.addValidator(validator2);
+ assertEquals(2, field.getValidators().size());
+ assertTrue(field.getValidators().contains(validator));
+ assertTrue(field.getValidators().contains(validator2));
+ }
+
+ @Test
+ public void testRemoveValidator() {
+ field.addValidator(validator);
+ field.addValidator(validator2);
+
+ field.removeValidator(validator);
+ assertNotNull(field.getValidators());
+ assertEquals(1, field.getValidators().size());
+ assertFalse(field.getValidators().contains(validator));
+ assertTrue(field.getValidators().contains(validator2));
+
+ field.removeValidator(validator2);
+ assertNotNull(field.getValidators());
+ assertEquals(0, field.getValidators().size());
+ assertFalse(field.getValidators().contains(validator));
+ assertFalse(field.getValidators().contains(validator2));
+ }
+
+ @Test
+ public void testRemoveAllValidators() {
+ field.addValidator(validator);
+ field.addValidator(validator2);
+
+ field.removeAllValidators();
+ assertNotNull(field.getValidators());
+ assertEquals(0, field.getValidators().size());
+ assertFalse(field.getValidators().contains(validator));
+ assertFalse(field.getValidators().contains(validator2));
+ }
+
+ @Test
+ public void nonImmediateFieldWithValidator() {
+ field.setImmediate(false);
+ field.addValidator(validator);
+ assertFalse("field should be non-immediate because explicitly set",
+ field.isImmediate());
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbsFieldValueConversionErrorTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbsFieldValueConversionErrorTest.java
new file mode 100644
index 0000000000..4def8caca7
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbsFieldValueConversionErrorTest.java
@@ -0,0 +1,92 @@
+package com.vaadin.v7.tests.server.component.abstractfield;
+
+import static org.junit.Assert.fail;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.tests.data.bean.Address;
+import com.vaadin.tests.data.bean.Country;
+import com.vaadin.tests.data.bean.Person;
+import com.vaadin.tests.data.bean.Sex;
+import com.vaadin.v7.data.Validator.InvalidValueException;
+import com.vaadin.v7.data.util.converter.Converter.ConversionException;
+import com.vaadin.v7.data.util.MethodProperty;
+import com.vaadin.v7.data.util.converter.StringToIntegerConverter;
+import com.vaadin.v7.ui.TextField;
+
+public class AbsFieldValueConversionErrorTest {
+
+ Person paulaBean = new Person("Paula", "Brilliant", "paula@brilliant.com",
+ 34, Sex.FEMALE,
+ new Address("Paula street 1", 12345, "P-town", Country.FINLAND));
+
+ @Test
+ public void testValidateConversionErrorParameters() {
+ TextField tf = new TextField();
+ tf.setConverter(new StringToIntegerConverter());
+ tf.setPropertyDataSource(new MethodProperty<String>(paulaBean, "age"));
+ tf.setConversionError("(Type: {0}) Converter exception message: {1}");
+ tf.setValue("abc");
+ try {
+ tf.validate();
+ fail();
+ } catch (InvalidValueException e) {
+ Assert.assertEquals(
+ "(Type: Integer) Converter exception message: Could not convert 'abc' to java.lang.Integer",
+ e.getMessage());
+ }
+
+ }
+
+ @Test
+ public void testConvertToModelConversionErrorParameters() {
+ TextField tf = new TextField();
+ tf.setConverter(new StringToIntegerConverter());
+ tf.setPropertyDataSource(new MethodProperty<String>(paulaBean, "age"));
+ tf.setConversionError("(Type: {0}) Converter exception message: {1}");
+ tf.setValue("abc");
+ try {
+ tf.getConvertedValue();
+ fail();
+ } catch (ConversionException e) {
+ Assert.assertEquals(
+ "(Type: Integer) Converter exception message: Could not convert 'abc' to java.lang.Integer",
+ e.getMessage());
+ }
+
+ }
+
+ @Test
+ public void testNullConversionMessages() {
+ TextField tf = new TextField();
+ tf.setConverter(new StringToIntegerConverter());
+ tf.setPropertyDataSource(new MethodProperty<String>(paulaBean, "age"));
+ tf.setConversionError(null);
+ tf.setValue("abc");
+ try {
+ tf.validate();
+ fail();
+ } catch (InvalidValueException e) {
+ Assert.assertEquals(null, e.getMessage());
+ }
+
+ }
+
+ @Test
+ public void testDefaultConversionErrorMessage() {
+ TextField tf = new TextField();
+ tf.setConverter(new StringToIntegerConverter());
+ tf.setPropertyDataSource(new MethodProperty<String>(paulaBean, "age"));
+ tf.setValue("abc");
+
+ try {
+ tf.validate();
+ fail();
+ } catch (InvalidValueException e) {
+ Assert.assertEquals("Could not convert value to Integer",
+ e.getMessage());
+ }
+
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbsFieldValueConversionsTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbsFieldValueConversionsTest.java
new file mode 100644
index 0000000000..6594ed9351
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbsFieldValueConversionsTest.java
@@ -0,0 +1,216 @@
+package com.vaadin.v7.tests.server.component.abstractfield;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.server.VaadinSession;
+import com.vaadin.tests.data.bean.Address;
+import com.vaadin.tests.data.bean.Country;
+import com.vaadin.tests.data.bean.Person;
+import com.vaadin.tests.data.bean.Sex;
+import com.vaadin.tests.util.AlwaysLockedVaadinSession;
+import com.vaadin.v7.data.util.MethodProperty;
+import com.vaadin.v7.data.util.ObjectProperty;
+import com.vaadin.v7.data.util.converter.Converter;
+import com.vaadin.v7.data.util.converter.Converter.ConversionException;
+import com.vaadin.v7.data.util.converter.StringToIntegerConverter;
+import com.vaadin.v7.ui.TextField;
+
+public class AbsFieldValueConversionsTest {
+
+ Person paulaBean = new Person("Paula", "Brilliant", "paula@brilliant.com",
+ 34, Sex.FEMALE,
+ new Address("Paula street 1", 12345, "P-town", Country.FINLAND));
+
+ /**
+ * Java uses a non-breaking space (ascii 160) instead of space when
+ * formatting
+ */
+ private static final char FORMATTED_SPACE = 160;
+
+ @Test
+ public void testWithoutConversion() {
+ TextField tf = new TextField();
+ tf.setPropertyDataSource(
+ new MethodProperty<String>(paulaBean, "firstName"));
+ assertEquals("Paula", tf.getValue());
+ assertEquals("Paula", tf.getPropertyDataSource().getValue());
+ tf.setValue("abc");
+ assertEquals("abc", tf.getValue());
+ assertEquals("abc", tf.getPropertyDataSource().getValue());
+ assertEquals("abc", paulaBean.getFirstName());
+ }
+
+ @Test
+ public void testNonmodifiedBufferedFieldConversion() {
+ VaadinSession.setCurrent(new AlwaysLockedVaadinSession(null));
+ TextField tf = new TextField("salary");
+ tf.setBuffered(true);
+ tf.setLocale(new Locale("en", "US"));
+ ObjectProperty<Integer> ds = new ObjectProperty<Integer>(123456789);
+ tf.setPropertyDataSource(ds);
+ assertEquals((Integer) 123456789, ds.getValue());
+ assertEquals("123,456,789", tf.getValue());
+ tf.setLocale(new Locale("fi", "FI"));
+ assertEquals((Integer) 123456789, ds.getValue());
+ assertEquals("123" + FORMATTED_SPACE + "456" + FORMATTED_SPACE + "789",
+ tf.getValue());
+
+ }
+
+ @Test
+ public void testModifiedBufferedFieldConversion() {
+ VaadinSession.setCurrent(new AlwaysLockedVaadinSession(null));
+ TextField tf = new TextField("salary");
+ tf.setBuffered(true);
+ tf.setLocale(new Locale("en", "US"));
+ ObjectProperty<Integer> ds = new ObjectProperty<Integer>(123456789);
+ tf.setPropertyDataSource(ds);
+ assertEquals((Integer) 123456789, ds.getValue());
+ assertEquals("123,456,789", tf.getValue());
+ tf.setValue("123,123");
+ assertEquals((Integer) 123456789, ds.getValue());
+ assertEquals("123,123", tf.getValue());
+
+ tf.setLocale(new Locale("fi", "FI"));
+ assertEquals((Integer) 123456789, ds.getValue());
+ // Value should not be updated when field is buffered
+ assertEquals("123,123", tf.getValue());
+ }
+
+ @Test
+ public void testStringIdentityConversion() {
+ TextField tf = new TextField();
+ tf.setConverter(new Converter<String, String>() {
+
+ @Override
+ public String convertToModel(String value,
+ Class<? extends String> targetType, Locale locale) {
+ return value;
+ }
+
+ @Override
+ public String convertToPresentation(String value,
+ Class<? extends String> targetType, Locale locale) {
+ return value;
+ }
+
+ @Override
+ public Class<String> getModelType() {
+ return String.class;
+ }
+
+ @Override
+ public Class<String> getPresentationType() {
+ return String.class;
+ }
+ });
+ tf.setPropertyDataSource(
+ new MethodProperty<String>(paulaBean, "firstName"));
+ assertEquals("Paula", tf.getValue());
+ assertEquals("Paula", tf.getPropertyDataSource().getValue());
+ tf.setValue("abc");
+ assertEquals("abc", tf.getValue());
+ assertEquals("abc", tf.getPropertyDataSource().getValue());
+ assertEquals("abc", paulaBean.getFirstName());
+ }
+
+ @Test
+ public void testIntegerStringConversion() {
+ TextField tf = new TextField();
+
+ tf.setConverter(new StringToIntegerConverter());
+ tf.setPropertyDataSource(new MethodProperty<Integer>(paulaBean, "age"));
+ assertEquals(34, tf.getPropertyDataSource().getValue());
+ assertEquals("34", tf.getValue());
+ tf.setValue("12");
+ assertEquals(12, tf.getPropertyDataSource().getValue());
+ assertEquals("12", tf.getValue());
+ tf.getPropertyDataSource().setValue(42);
+ assertEquals(42, tf.getPropertyDataSource().getValue());
+ assertEquals("42", tf.getValue());
+ }
+
+ @Test
+ public void testChangeReadOnlyFieldLocale() {
+ VaadinSession.setCurrent(new AlwaysLockedVaadinSession(null));
+
+ TextField tf = new TextField("salary");
+ tf.setLocale(new Locale("en", "US"));
+ ObjectProperty<Integer> ds = new ObjectProperty<Integer>(123456789);
+ ds.setReadOnly(true);
+ tf.setPropertyDataSource(ds);
+ assertEquals((Integer) 123456789, ds.getValue());
+ assertEquals("123,456,789", tf.getValue());
+ tf.setLocale(new Locale("fi", "FI"));
+ assertEquals((Integer) 123456789, ds.getValue());
+ assertEquals("123" + FORMATTED_SPACE + "456" + FORMATTED_SPACE + "789",
+ tf.getValue());
+ }
+
+ // Now specific to Integer because StringToNumberConverter has been removed
+ public static class NumberBean {
+ private Integer number;
+
+ public Integer getNumber() {
+ return number;
+ }
+
+ public void setNumber(Integer number) {
+ this.number = number;
+ }
+
+ }
+
+ @Test
+ public void testNumberDoubleConverterChange() {
+ final VaadinSession a = new AlwaysLockedVaadinSession(null);
+ VaadinSession.setCurrent(a);
+ TextField tf = new TextField() {
+ @Override
+ public VaadinSession getSession() {
+ return a;
+ }
+ };
+ NumberBean nb = new NumberBean();
+ nb.setNumber(490);
+
+ tf.setPropertyDataSource(new MethodProperty<Number>(nb, "number"));
+ assertEquals(490, tf.getPropertyDataSource().getValue());
+ assertEquals("490", tf.getValue());
+
+ Converter c1 = tf.getConverter();
+
+ tf.setPropertyDataSource(new MethodProperty<Number>(nb, "number"));
+ Converter c2 = tf.getConverter();
+ assertTrue(
+ "StringToInteger converter is ok for integer types and should stay even though property is changed",
+ c1 == c2);
+ assertEquals(490, tf.getPropertyDataSource().getValue());
+ assertEquals("490", tf.getValue());
+
+ }
+
+ @Test
+ public void testNullConverter() {
+ TextField tf = new TextField("foo");
+ tf.setConverter(new StringToIntegerConverter());
+ tf.setPropertyDataSource(new ObjectProperty<Integer>(12));
+ tf.setConverter((Converter) null);
+ try {
+ Object v = tf.getConvertedValue();
+ System.out.println(v);
+ Assert.fail(
+ "Trying to convert String -> Integer should fail when there is no converter");
+ } catch (ConversionException e) {
+ // ok, should happen when there is no converter but conversion is
+ // needed
+ }
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbstractFieldDeclarativeTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbstractFieldDeclarativeTest.java
new file mode 100644
index 0000000000..ea420100c2
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbstractFieldDeclarativeTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2016 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.v7.tests.server.component.abstractfield;
+
+import org.junit.Test;
+
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.AbstractField;
+import com.vaadin.ui.TextField;
+
+/**
+ * Tests declarative support for implementations of {@link AbstractField}.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+public class AbstractFieldDeclarativeTest
+ extends DeclarativeTestBase<AbstractField<?>> {
+
+ @Test
+ public void testPlainText() {
+ // FIXME
+ // String design = "<vaadin-text-field readonly tabindex=3"
+ // + "required"
+ // + "/>";
+ // AbstractField<String> tf = new TextField();
+ // tf.setRequired(true);
+ // tf.setTabIndex(3);
+ // tf.setReadOnly(true);
+ // testRead(design, tf);
+ // testWrite(design, tf);
+ //
+ // // Test with readonly=false
+ // design = design.replace("readonly", "");
+ // tf.setReadOnly(false);
+ // testRead(design, tf);
+ // testWrite(design, tf);
+ }
+
+ @Test
+ public void testModelReadOnly() {
+ // Test that read only value coming from property data source is not
+ // written to design.
+ String design = "<vaadin-text-field readonly value=test></vaadin-text-field>";
+ AbstractField<String> component = new TextField();
+ component.setReadOnly(true);
+ component.setValue("test");
+ // FIXME (?) current implementation only
+ // disables client-side modification
+ testWrite(design, component);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbstractFieldReadOnlyTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbstractFieldReadOnlyTest.java
new file mode 100644
index 0000000000..9f0871106d
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/AbstractFieldReadOnlyTest.java
@@ -0,0 +1,51 @@
+package com.vaadin.v7.tests.server.component.abstractfield;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.vaadin.tests.data.bean.Address;
+import com.vaadin.tests.data.bean.Country;
+import com.vaadin.tests.data.bean.Person;
+import com.vaadin.tests.data.bean.Sex;
+import com.vaadin.ui.Label;
+import com.vaadin.v7.data.Property.ReadOnlyStatusChangeEvent;
+import com.vaadin.v7.data.Property.ReadOnlyStatusChangeListener;
+import com.vaadin.v7.data.util.MethodProperty;
+import com.vaadin.v7.ui.TextField;
+
+public class AbstractFieldReadOnlyTest {
+
+ Person paulaBean = new Person("Paula", "Brilliant", "paula@brilliant.com",
+ 34, Sex.FEMALE,
+ new Address("Paula street 1", 12345, "P-town", Country.FINLAND));
+
+ @Test
+ public void testReadOnlyProperty() {
+ TextField tf = new TextField();
+ tf.setPropertyDataSource(
+ new MethodProperty<String>(paulaBean, "firstName"));
+ assertFalse(tf.isReadOnly());
+ tf.getPropertyDataSource().setReadOnly(true);
+ assertTrue(tf.isReadOnly());
+ }
+
+ @Test
+ public void testReadOnlyEventFromProperty() {
+ final Label valueStore = new Label("");
+ TextField tf = new TextField();
+ tf.addReadOnlyStatusChangeListener(new ReadOnlyStatusChangeListener() {
+ @Override
+ public void readOnlyStatusChange(ReadOnlyStatusChangeEvent event) {
+ valueStore.setValue("event received!");
+ }
+ });
+ tf.setPropertyDataSource(
+ new MethodProperty<String>(paulaBean, "firstName"));
+ assertTrue(valueStore.getValue().isEmpty());
+ tf.getPropertyDataSource().setReadOnly(true);
+ assertFalse(valueStore.getValue().isEmpty());
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/DefaultConverterFactoryTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/DefaultConverterFactoryTest.java
new file mode 100644
index 0000000000..03b92aaa6e
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/DefaultConverterFactoryTest.java
@@ -0,0 +1,138 @@
+package com.vaadin.v7.tests.server.component.abstractfield;
+
+import static org.junit.Assert.assertEquals;
+
+import java.math.BigDecimal;
+import java.util.Locale;
+
+import org.junit.Test;
+
+import com.vaadin.server.VaadinSession;
+import com.vaadin.tests.data.bean.Address;
+import com.vaadin.tests.data.bean.Country;
+import com.vaadin.tests.data.bean.Person;
+import com.vaadin.tests.data.bean.Sex;
+import com.vaadin.tests.util.AlwaysLockedVaadinSession;
+import com.vaadin.v7.data.util.MethodProperty;
+import com.vaadin.v7.ui.TextField;
+
+public class DefaultConverterFactoryTest {
+
+ public static class FloatBean {
+ float f1;
+ Float f2;
+
+ public FloatBean(float f1, Float f2) {
+ this.f1 = f1;
+ this.f2 = f2;
+ }
+
+ public float getF1() {
+ return f1;
+ }
+
+ public void setF1(float f1) {
+ this.f1 = f1;
+ }
+
+ public Float getF2() {
+ return f2;
+ }
+
+ public void setF2(Float f2) {
+ this.f2 = f2;
+ }
+
+ }
+
+ public static class LongBean {
+ long l1;
+ Long l2;
+
+ public LongBean(long l1, Long l2) {
+ this.l1 = l1;
+ this.l2 = l2;
+ }
+
+ public long getL1() {
+ return l1;
+ }
+
+ public void setL1(long l1) {
+ this.l1 = l1;
+ }
+
+ public Long getL2() {
+ return l2;
+ }
+
+ public void setL2(Long l2) {
+ this.l2 = l2;
+ }
+
+ }
+
+ Person paulaBean = new Person("Paula", "Brilliant", "paula@brilliant.com",
+ 34, Sex.FEMALE,
+ new Address("Paula street 1", 12345, "P-town", Country.FINLAND));
+ {
+ paulaBean.setSalary(49000);
+ BigDecimal rent = new BigDecimal(57223);
+ rent = rent.scaleByPowerOfTen(-2);
+ paulaBean.setRent(rent);
+ }
+
+ @Test
+ public void testFloatConversion() {
+ VaadinSession sess = new AlwaysLockedVaadinSession(null);
+ VaadinSession.setCurrent(sess);
+
+ TextField tf = new TextField();
+ tf.setLocale(new Locale("en", "US"));
+ tf.setPropertyDataSource(
+ new MethodProperty<Integer>(new FloatBean(12f, 23f), "f2"));
+ assertEquals("23", tf.getValue());
+ tf.setValue("24");
+ assertEquals("24", tf.getValue());
+ assertEquals(24f, tf.getConvertedValue());
+ assertEquals(24f, tf.getPropertyDataSource().getValue());
+ }
+
+ @Test
+ public void testLongConversion() {
+ VaadinSession sess = new AlwaysLockedVaadinSession(null);
+ VaadinSession.setCurrent(sess);
+
+ TextField tf = new TextField();
+ tf.setLocale(new Locale("en", "US"));
+ tf.setPropertyDataSource(new MethodProperty<Integer>(
+ new LongBean(12, 1982739187238L), "l2"));
+ assertEquals("1,982,739,187,238", tf.getValue());
+ tf.setValue("1982739187239");
+ assertEquals("1,982,739,187,239", tf.getValue());
+ assertEquals(1982739187239L, tf.getConvertedValue());
+ assertEquals(1982739187239L, tf.getPropertyDataSource().getValue());
+ }
+
+ @Test
+ public void testDefaultNumberConversion() {
+ VaadinSession app = new AlwaysLockedVaadinSession(null);
+ VaadinSession.setCurrent(app);
+ TextField tf = new TextField();
+ tf.setLocale(new Locale("en", "US"));
+ tf.setPropertyDataSource(
+ new MethodProperty<Integer>(paulaBean, "salary"));
+ assertEquals("49,000", tf.getValue());
+
+ tf.setLocale(new Locale("fi", "FI"));
+ // FIXME: The following line should not be necessary and should be
+ // removed
+ tf.setPropertyDataSource(
+ new MethodProperty<Integer>(paulaBean, "salary"));
+ String value = tf.getValue();
+ // Java uses a non-breaking space (ascii 160) instead of space when
+ // formatting
+ String expected = "49" + (char) 160 + "000";
+ assertEquals(expected, value);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/RemoveListenersOnDetachTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/RemoveListenersOnDetachTest.java
new file mode 100644
index 0000000000..82cb2751ff
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstractfield/RemoveListenersOnDetachTest.java
@@ -0,0 +1,106 @@
+package com.vaadin.v7.tests.server.component.abstractfield;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.VaadinSession;
+import com.vaadin.tests.util.AlwaysLockedVaadinSession;
+import com.vaadin.ui.UI;
+import com.vaadin.v7.data.Property;
+import com.vaadin.v7.data.util.AbstractProperty;
+import com.vaadin.v7.data.util.converter.Converter.ConversionException;
+import com.vaadin.v7.ui.AbstractField;
+
+public class RemoveListenersOnDetachTest {
+
+ int numValueChanges = 0;
+ int numReadOnlyChanges = 0;
+
+ AbstractField field = new AbstractField() {
+ final private VaadinSession application = new AlwaysLockedVaadinSession(
+ null);
+ private UI uI = new UI() {
+
+ @Override
+ protected void init(VaadinRequest request) {
+
+ }
+
+ @Override
+ public VaadinSession getSession() {
+ return application;
+ }
+
+ };
+
+ @Override
+ public Class<?> getType() {
+ return String.class;
+ }
+
+ @Override
+ public void valueChange(Property.ValueChangeEvent event) {
+ super.valueChange(event);
+ numValueChanges++;
+ }
+
+ @Override
+ public void readOnlyStatusChange(
+ Property.ReadOnlyStatusChangeEvent event) {
+ super.readOnlyStatusChange(event);
+ numReadOnlyChanges++;
+ }
+
+ @Override
+ public com.vaadin.ui.UI getUI() {
+ return uI;
+ }
+
+ @Override
+ public VaadinSession getSession() {
+ return application;
+ }
+ };
+
+ Property<String> property = new AbstractProperty<String>() {
+ @Override
+ public String getValue() {
+ return null;
+ }
+
+ @Override
+ public void setValue(String newValue)
+ throws ReadOnlyException, ConversionException {
+ fireValueChange();
+ }
+
+ @Override
+ public Class<String> getType() {
+ return String.class;
+ }
+ };
+
+ @Test
+ public void testAttachDetach() {
+ field.setPropertyDataSource(property);
+
+ property.setValue(null);
+ property.setReadOnly(true);
+ assertEquals(1, numValueChanges);
+ assertEquals(1, numReadOnlyChanges);
+
+ field.attach();
+ property.setValue(null);
+ property.setReadOnly(false);
+ assertEquals(2, numValueChanges);
+ assertEquals(2, numReadOnlyChanges);
+
+ field.detach();
+ property.setValue(null);
+ property.setReadOnly(true);
+ assertEquals(2, numValueChanges);
+ assertEquals(2, numReadOnlyChanges);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstracttextfield/AbstractTextFieldListenersTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstracttextfield/AbstractTextFieldListenersTest.java
new file mode 100644
index 0000000000..022bdd075b
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/abstracttextfield/AbstractTextFieldListenersTest.java
@@ -0,0 +1,34 @@
+package com.vaadin.v7.tests.server.component.abstracttextfield;
+
+import org.junit.Test;
+
+import com.vaadin.event.FieldEvents.BlurEvent;
+import com.vaadin.event.FieldEvents.BlurListener;
+import com.vaadin.event.FieldEvents.FocusEvent;
+import com.vaadin.event.FieldEvents.FocusListener;
+import com.vaadin.tests.server.component.AbstractListenerMethodsTestBase;
+import com.vaadin.v7.event.FieldEvents.TextChangeEvent;
+import com.vaadin.v7.event.FieldEvents.TextChangeListener;
+import com.vaadin.v7.ui.TextField;
+
+public class AbstractTextFieldListenersTest
+ extends AbstractListenerMethodsTestBase {
+
+ @Test
+ public void testTextChangeListenerAddGetRemove() throws Exception {
+ testListenerAddGetRemove(TextField.class, TextChangeEvent.class,
+ TextChangeListener.class);
+ }
+
+ @Test
+ public void testFocusListenerAddGetRemove() throws Exception {
+ testListenerAddGetRemove(TextField.class, FocusEvent.class,
+ FocusListener.class);
+ }
+
+ @Test
+ public void testBlurListenerAddGetRemove() throws Exception {
+ testListenerAddGetRemove(TextField.class, BlurEvent.class,
+ BlurListener.class);
+ }
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/textfield/TextFieldTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/textfield/TextFieldTest.java
new file mode 100644
index 0000000000..79f1640257
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/textfield/TextFieldTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2016 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.v7.tests.server.component.textfield;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.v7.data.util.ObjectProperty;
+import com.vaadin.v7.ui.TextField;
+
+public class TextFieldTest {
+
+ @Test
+ public void initiallyEmpty() {
+ TextField tf = new TextField();
+ Assert.assertTrue(tf.isEmpty());
+ }
+
+ @Test
+ public void emptyAfterClearUsingPDS() {
+ TextField tf = new TextField(
+ new ObjectProperty<String>("foo"));
+ Assert.assertFalse(tf.isEmpty());
+ tf.clear();
+ Assert.assertTrue(tf.isEmpty());
+ }
+
+ @Test
+ public void emptyAfterClear() {
+ TextField tf = new TextField();
+ tf.setValue("foobar");
+ Assert.assertFalse(tf.isEmpty());
+ tf.clear();
+ Assert.assertTrue(tf.isEmpty());
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/textfield/TextFieldValueChangeTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/textfield/TextFieldValueChangeTest.java
new file mode 100644
index 0000000000..bb286296b4
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/textfield/TextFieldValueChangeTest.java
@@ -0,0 +1,131 @@
+package com.vaadin.v7.tests.server.component.textfield;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.tests.server.components.AbstractFieldValueChangeTestBase;
+import com.vaadin.v7.data.Property.ValueChangeEvent;
+import com.vaadin.v7.data.util.ObjectProperty;
+import com.vaadin.v7.ui.AbstractField;
+import com.vaadin.v7.ui.TextField;
+
+/**
+ * Check that the value change listener for a text field is triggered exactly
+ * once when setting the value, at the correct time.
+ *
+ * See <a href="http://dev.vaadin.com/ticket/4394">Ticket 4394</a>.
+ */
+public class TextFieldValueChangeTest
+ extends AbstractFieldValueChangeTestBase<String> {
+
+ @Before
+ public void setUp() {
+ super.setUp(new TextField());
+ }
+
+ /**
+ * Case where the text field only uses its internal buffer, no external
+ * property data source.
+ */
+ @Test
+ public void testNoDataSource() {
+ getField().setPropertyDataSource(null);
+
+ expectValueChangeFromSetValueNotCommit();
+ }
+
+ @Override
+ protected void setValue(AbstractField<String> field) {
+ Map<String, Object> variables = new HashMap<String, Object>();
+ variables.put("text", "newValue");
+ ((TextField) field).changeVariables(field, variables);
+ }
+
+ /**
+ * Test that field propagates value change events originating from property,
+ * but don't fire value change events twice if value has only changed once.
+ *
+ *
+ * TODO make test field type agnostic (eg. combobox)
+ */
+ @Test
+ public void testValueChangeEventPropagationWithReadThrough() {
+ ObjectProperty<String> property = new ObjectProperty<String>("");
+ getField().setPropertyDataSource(property);
+
+ // defaults, buffering off
+ getField().setBuffered(false);
+
+ // Expectations and start test
+ getListener().valueChange(EasyMock.isA(ValueChangeEvent.class));
+ EasyMock.replay(getListener());
+
+ // Add listener and set the value -> should end up in listener once
+ getField().addListener(getListener());
+
+ property.setValue("Foo");
+
+ // Ensure listener was called once
+ EasyMock.verify(getListener());
+
+ // get value should not fire value change again
+ Object value = getField().getValue();
+ Assert.assertEquals("Foo", value);
+
+ // Ensure listener still has been called only once
+ EasyMock.verify(getListener());
+ }
+
+ /**
+ * Value change events from property should not propagate if read through is
+ * false. Execpt when the property is being set.
+ *
+ * TODO make test field type agnostic (eg. combobox)
+ */
+ @Test
+ public void testValueChangePropagationWithReadThroughOff() {
+ final String initialValue = "initial";
+ ObjectProperty<String> property = new ObjectProperty<String>(
+ initialValue);
+
+ // set buffering
+ getField().setBuffered(true);
+
+ // Value change should only happen once, when setting the property,
+ // further changes via property should not cause value change listener
+ // in field to be notified
+ getListener().valueChange(EasyMock.isA(ValueChangeEvent.class));
+ EasyMock.replay(getListener());
+
+ getField().addListener(getListener());
+ getField().setPropertyDataSource(property);
+
+ // Ensure listener was called once
+ EasyMock.verify(getListener());
+
+ // modify property value, should not fire value change in field as the
+ // read buffering is on (read through == false)
+ property.setValue("Foo");
+
+ // Ensure listener still has been called only once
+ EasyMock.verify(getListener());
+
+ // get value should not fire value change again
+ Object value = getField().getValue();
+
+ // field value should be different from the original value and current
+ // proeprty value
+ boolean isValueEqualToInitial = value.equals(initialValue);
+ Assert.assertTrue(isValueEqualToInitial);
+
+ // Ensure listener still has been called only once
+ EasyMock.verify(getListener());
+
+ }
+
+}