Browse Source

Binder.bindInstanceFields(Object) method implementation (#47).

Binds class instance fields using reflection using Binder.forField()

Change-Id: I597f3832d112cfa69c73fb185f1564c482e4eb15
tags/8.0.0.alpha6
Denis Anisimov 7 years ago
parent
commit
0decd87411

+ 1
- 0
compatibility-server/src/main/java/com/vaadin/v7/data/fieldgroup/FieldGroup.java View File

@@ -25,6 +25,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.vaadin.annotations.PropertyId;
import com.vaadin.util.ReflectTools;
import com.vaadin.v7.data.Item;
import com.vaadin.v7.data.Property;

+ 1
- 1
compatibility-server/src/test/java/com/vaadin/v7/data/util/ReflectToolsGetSuperFieldTest.java View File

@@ -4,8 +4,8 @@ import static org.junit.Assert.assertTrue;

import org.junit.Test;

import com.vaadin.annotations.PropertyId;
import com.vaadin.v7.data.fieldgroup.FieldGroup;
import com.vaadin.v7.data.fieldgroup.PropertyId;
import com.vaadin.v7.ui.TextField;

public class ReflectToolsGetSuperFieldTest {

+ 1
- 1
compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/fieldgroup/BeanFieldGroupTest.java View File

@@ -5,10 +5,10 @@ import static org.junit.Assert.assertEquals;
import org.junit.Assert;
import org.junit.Test;

import com.vaadin.annotations.PropertyId;
import com.vaadin.v7.data.Item;
import com.vaadin.v7.data.fieldgroup.BeanFieldGroup;
import com.vaadin.v7.data.fieldgroup.FieldGroup.CommitException;
import com.vaadin.v7.data.fieldgroup.PropertyId;
import com.vaadin.v7.data.util.BeanItem;
import com.vaadin.v7.ui.Field;
import com.vaadin.v7.ui.RichTextArea;

+ 1
- 1
compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/fieldgroup/FieldNamedDescriptionTest.java View File

@@ -4,9 +4,9 @@ import static org.junit.Assert.assertTrue;

import org.junit.Test;

import com.vaadin.annotations.PropertyId;
import com.vaadin.ui.FormLayout;
import com.vaadin.v7.data.fieldgroup.FieldGroup;
import com.vaadin.v7.data.fieldgroup.PropertyId;
import com.vaadin.v7.data.util.ObjectProperty;
import com.vaadin.v7.data.util.PropertysetItem;
import com.vaadin.v7.ui.TextField;

+ 7
- 0
server/pom.xml View File

@@ -80,6 +80,13 @@
<artifactId>jsoup</artifactId>
</dependency>

<!-- Small reflection library -->
<dependency>
<groupId>com.googlecode.gentyref</groupId>
<artifactId>gentyref</artifactId>
<version>1.2.0</version>
</dependency>

<!-- TESTING DEPENDENCIES -->

<!-- Test dependencies -->

compatibility-server/src/main/java/com/vaadin/v7/data/fieldgroup/PropertyId.java → server/src/main/java/com/vaadin/annotations/PropertyId.java View File

@@ -13,25 +13,27 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.v7.data.fieldgroup;
package com.vaadin.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.vaadin.v7.ui.Field;
import com.vaadin.data.BeanBinder;
import com.vaadin.data.Binder;
import com.vaadin.data.HasValue;

/**
* Defines the custom property name to be bound to a {@link Field} using
* {@link FieldGroup} or {@link BeanFieldGroup}.
* {@link Binder} or {@link BeanBinder}.
* <p>
* The automatic data binding in FieldGroup and BeanFieldGroup relies on a
* naming convention by default: properties of an item are bound to similarly
* named field components in given a editor object. If you want to map a
* property with a different name (ID) to a {@link com.vaadin.client.ui.Field},
* you can use this annotation for the member fields, with the name (ID) of the
* desired property as the parameter.
* The automatic data binding in Binder and BeanBinder relies on a naming
* convention by default: properties of an item are bound to similarly named
* field components in given a editor object. If you want to map a property with
* a different name (ID) to a {@link HasValue}, you can use this annotation for
* the member fields, with the name (ID) of the desired property as the
* parameter.
* <p>
* In following usage example, the text field would be bound to property "foo"
* in the Entity class. <code>
@@ -46,8 +48,9 @@ import com.vaadin.v7.ui.Field;
}

{
Editor e = new Editor();
BeanFieldGroup.bindFieldsUnbuffered(new Entity(), e);
Editor editor = new Editor();
BeanBinder<Entity> binder = new BeanBinder(Entity.class);
binder.bindInstanceFields(editor);
}
</pre>
* </code>
@@ -57,7 +60,6 @@ import com.vaadin.v7.ui.Field;
*/
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Deprecated
public @interface PropertyId {
String value();
}

+ 233
- 0
server/src/main/java/com/vaadin/data/BeanBinder.java View File

@@ -18,10 +18,21 @@ package com.vaadin.data;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiConsumer;

import com.googlecode.gentyref.GenericTypeReflector;
import com.vaadin.annotations.PropertyId;
import com.vaadin.data.util.BeanUtil;
import com.vaadin.data.util.converter.Converter;
import com.vaadin.data.validator.BeanValidator;
@@ -184,6 +195,7 @@ public class BeanBinder<BEAN> extends Binder<BEAN> {
getter = descriptor.getReadMethod();
setter = descriptor.getWriteMethod();
finalBinding.bind(this::getValue, this::setValue);
getBinder().boundProperties.add(propertyName);
}

@Override
@@ -253,6 +265,7 @@ public class BeanBinder<BEAN> extends Binder<BEAN> {
}

private final Class<? extends BEAN> beanType;
private final Set<String> boundProperties;

/**
* Creates a new {@code BeanBinder} supporting beans of the given type.
@@ -263,6 +276,7 @@ public class BeanBinder<BEAN> extends Binder<BEAN> {
public BeanBinder(Class<? extends BEAN> beanType) {
BeanUtil.checkBeanValidationAvailable();
this.beanType = beanType;
boundProperties = new HashSet<>();
}

@Override
@@ -317,4 +331,223 @@ public class BeanBinder<BEAN> extends Binder<BEAN> {
return new BeanBindingImpl<>(this, field, converter, handler);
}

/**
* Binds member fields found in the given object.
* <p>
* This method processes all (Java) member fields whose type extends
* {@link HasValue} and that can be mapped to a property id. Property id
* mapping is done based on the field name or on a @{@link PropertyId}
* annotation on the field. All non-null unbound fields for which a property
* id can be determined are bound to the property id.
* </p>
* <p>
* For example:
*
* <pre>
* public class MyForm extends VerticalLayout {
* private TextField firstName = new TextField("First name");
* &#64;PropertyId("last")
* private TextField lastName = new TextField("Last name");
*
* MyForm myForm = new MyForm();
* ...
* binder.bindMemberFields(myForm);
* </pre>
*
* </p>
* This binds the firstName TextField to a "firstName" property in the item,
* lastName TextField to a "last" property.
* <p>
* It's not always possible to bind a field to a property because their
* types are incompatible. E.g. custom converter is required to bind
* {@code HasValue<String>} and {@code Integer} property (that would be a
* case of "age" property). In such case {@link IllegalStateException} will
* be thrown unless the field has been configured manually before calling
* the {@link #bindInstanceFields(Object)} method.
* <p>
* It's always possible to do custom binding for any field: the
* {@link #bindInstanceFields(Object)} method doesn't override existing
* bindings.
*
* @param objectWithMemberFields
* The object that contains (Java) member fields to bind
* @throws IllegalStateException
* if there are incompatible HasValue<T> and property types
*/
public void bindInstanceFields(Object objectWithMemberFields) {
Class<?> objectClass = objectWithMemberFields.getClass();

getFieldsInDeclareOrder(objectClass).stream()
.filter(memberField -> HasValue.class
.isAssignableFrom(memberField.getType()))
.forEach(memberField -> handleProperty(memberField,
(property, type) -> bindProperty(objectWithMemberFields,
memberField, property, type)));
}

/**
* Binds {@code property} with {@code propertyType} to the field in the
* {@code objectWithMemberFields} instance using {@code memberField} as a
* reference to a member.
*
* @param objectWithMemberFields
* the object that contains (Java) member fields to build and
* bind
* @param memberField
* reference to a member field to bind
* @param property
* property name to bind
* @param propertyType
* type of the property
*/
protected void bindProperty(Object objectWithMemberFields,
Field memberField, String property, Class<?> propertyType) {
Type valueType = GenericTypeReflector.getTypeParameter(
memberField.getGenericType(),
HasValue.class.getTypeParameters()[0]);
if (valueType == null) {
throw new IllegalStateException(String.format(
"Unable to detect value type for the member '%s' in the "
+ "class '%s'.",
memberField.getName(),
objectWithMemberFields.getClass().getName()));
}
if (propertyType.equals(valueType)) {
HasValue<?> field;
// Get the field from the object
try {
field = (HasValue<?>) ReflectTools.getJavaFieldValue(
objectWithMemberFields, memberField, HasValue.class);
} catch (IllegalArgumentException | IllegalAccessException
| InvocationTargetException e) {
// If we cannot determine the value, just skip the field
return;
}
if (field == null) {
field = makeFieldInstance(
(Class<? extends HasValue<?>>) memberField.getType());
initializeField(objectWithMemberFields, memberField, field);
}
forField(field).bind(property);
} else {
throw new IllegalStateException(String.format(
"Property type '%s' doesn't "
+ "match the field type '%s'. "
+ "Binding should be configured manulaly using converter.",
propertyType.getName(), valueType.getTypeName()));
}
}

/**
* Makes an instance of the field type {@code fieldClass}.
* <p>
* The resulting field instance is used to bind a property to it using the
* {@link #bindInstanceFields(Object)} method.
* <p>
* The default implementation relies on the default constructor of the
* class. If there is no suitable default constructor or you want to
* configure the instantiated class then override this method and provide
* your own implementation.
*
* @see #bindInstanceFields(Object)
* @param fieldClass
* type of the field
* @return a {@code fieldClass} instance object
*/
protected HasValue<?> makeFieldInstance(
Class<? extends HasValue<?>> fieldClass) {
try {
return fieldClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new IllegalStateException(
String.format("Couldn't create an '%s' type instance",
fieldClass.getName()),
e);
}
}

/**
* Returns an array containing {@link Field} objects reflecting all the
* fields of the class or interface represented by this Class object. The
* elements in the array returned are sorted in declare order from sub class
* to super class.
*
* @param searchClass
* class to introspect
* @return list of all fields in the class considering hierarchy
*/
protected List<Field> getFieldsInDeclareOrder(Class<?> searchClass) {
ArrayList<Field> memberFieldInOrder = new ArrayList<>();

while (searchClass != null) {
for (Field memberField : searchClass.getDeclaredFields()) {
memberFieldInOrder.add(memberField);
}
searchClass = searchClass.getSuperclass();
}
return memberFieldInOrder;
}

private void initializeField(Object objectWithMemberFields,
Field memberField, HasValue<?> value) {
try {
ReflectTools.setJavaFieldValue(objectWithMemberFields, memberField,
value);
} catch (IllegalArgumentException | IllegalAccessException
| InvocationTargetException e) {
throw new IllegalStateException(
String.format("Could not assign value to field '%s'",
memberField.getName()),
e);
}
}

private void handleProperty(Field field,
BiConsumer<String, Class<?>> propertyHandler) {
Optional<PropertyDescriptor> descriptor = getPropertyDescriptor(field);

if (!descriptor.isPresent()) {
return;
}

String propertyName = descriptor.get().getName();
if (boundProperties.contains(propertyName)) {
return;
}

propertyHandler.accept(propertyName,
descriptor.get().getPropertyType());
boundProperties.add(propertyName);
}

private Optional<PropertyDescriptor> getPropertyDescriptor(Field field) {
PropertyId propertyIdAnnotation = field.getAnnotation(PropertyId.class);

String propertyId;
if (propertyIdAnnotation != null) {
// @PropertyId(propertyId) always overrides property id
propertyId = propertyIdAnnotation.value();
} else {
propertyId = field.getName();
}

List<PropertyDescriptor> descriptors;
try {
descriptors = BeanUtil.getBeanPropertyDescriptors(beanType);
} catch (IntrospectionException e) {
throw new IllegalArgumentException(String.format(
"Could not resolve bean '%s' properties (see the cause):",
beanType.getName()), e);
}
Optional<PropertyDescriptor> propertyDescitpor = descriptors.stream()
.filter(descriptor -> minifyFieldName(descriptor.getName())
.equals(minifyFieldName(propertyId)))
.findFirst();
return propertyDescitpor;
}

private String minifyFieldName(String fieldName) {
return fieldName.toLowerCase(Locale.ENGLISH).replace("_", "");
}

}

+ 1
- 1
server/src/main/java/com/vaadin/data/Binder.java View File

@@ -1200,7 +1200,7 @@ public class Binder<BEAN> implements Serializable {
* the handler to notify of status changes, not null
* @return the new incomplete binding
*/
protected <FIELDVALUE, TARGET> BindingImpl<BEAN, FIELDVALUE, TARGET> createBinding(
protected <FIELDVALUE, TARGET> Binding<BEAN, FIELDVALUE, TARGET> createBinding(
HasValue<FIELDVALUE> field, Converter<FIELDVALUE, TARGET> converter,
ValidationStatusHandler handler) {
return new BindingImpl<>(this, field, converter, handler);

+ 387
- 0
server/src/test/java/com/vaadin/data/BeanBinderInstanceFieldTest.java View File

@@ -0,0 +1,387 @@
/*
* 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.data;

import java.time.LocalDate;

import org.junit.Assert;
import org.junit.Test;

import com.vaadin.annotations.PropertyId;
import com.vaadin.data.util.converter.StringToIntegerConverter;
import com.vaadin.data.validator.StringLengthValidator;
import com.vaadin.tests.data.bean.Person;
import com.vaadin.ui.AbstractField;
import com.vaadin.ui.AbstractTextField;
import com.vaadin.ui.DateField;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.TextField;

/**
* Unit tests for {@link BeanBinder#bindInstanceFields(Object)} method.
*
* @author Vaadin Ltd
*
*/
public class BeanBinderInstanceFieldTest {

public static class BindAllFields extends FormLayout {
private TextField firstName;
private DateField birthDate;
}

public static class BindFieldsUsingAnnotation extends FormLayout {
@PropertyId("firstName")
private TextField nameField;

@PropertyId("birthDate")
private DateField birthDateField;
}

public static class BindOnlyOneField extends FormLayout {
private TextField firstName;
private TextField noFieldInPerson;
}

public static class BindNoHasValueField extends FormLayout {
private String firstName;
}

public static class BindGenericField extends FormLayout {
private CustomField<String> firstName;
}

public static class BindGenericWrongTypeParameterField extends FormLayout {
private CustomField<Boolean> firstName;
}

public static class BindWrongTypeParameterField extends FormLayout {
private IntegerTextField firstName;
}

public static class BindGeneric<T> extends FormLayout {
private CustomField<T> firstName;
}

public static class BindRaw extends FormLayout {
private CustomField firstName;
}

public static class BindAbstract extends FormLayout {
private AbstractTextField firstName;
}

public static class BindNonInstantiatableType extends FormLayout {
private NoDefaultCtor firstName;
}

public static class BindComplextHierarchyGenericType extends FormLayout {
private ComplexHierarchy firstName;
}

public static class NoDefaultCtor extends TextField {
public NoDefaultCtor(int arg) {
}
}

public static class IntegerTextField extends CustomField<Integer> {

}

public static class ComplexHierarchy extends Generic<Long> {

}

public static class Generic<T> extends ComplexGeneric<Boolean, String, T> {

}

public static class ComplexGeneric<U, V, S> extends CustomField<V> {

}

public static class CustomField<T> extends AbstractField<T> {

private T value;

@Override
public T getValue() {
return value;
}

@Override
protected void doSetValue(T value) {
this.value = value;
}

}

@Test
public void bindInstanceFields_bindAllFields() {
BindAllFields form = new BindAllFields();
BeanBinder<Person> binder = new BeanBinder<>(Person.class);
binder.bindInstanceFields(form);

Person person = new Person();
person.setFirstName("foo");
person.setBirthDate(LocalDate.now());

binder.bind(person);

Assert.assertEquals(person.getFirstName(), form.firstName.getValue());
Assert.assertEquals(person.getBirthDate(), form.birthDate.getValue());

form.firstName.setValue("bar");
form.birthDate.setValue(person.getBirthDate().plusDays(345));

Assert.assertEquals(form.firstName.getValue(), person.getFirstName());
Assert.assertEquals(form.birthDate.getValue(), person.getBirthDate());
}

@Test
public void bindInstanceFields_bindOnlyOneFields() {
BindOnlyOneField form = new BindOnlyOneField();
BeanBinder<Person> binder = new BeanBinder<>(Person.class);
binder.bindInstanceFields(form);

Person person = new Person();
person.setFirstName("foo");

binder.bind(person);

Assert.assertEquals(person.getFirstName(), form.firstName.getValue());

Assert.assertNull(form.noFieldInPerson);

form.firstName.setValue("bar");

Assert.assertEquals(form.firstName.getValue(), person.getFirstName());
}

@Test
public void bindInstanceFields_bindNotHasValueField_fieldIsNull() {
BindNoHasValueField form = new BindNoHasValueField();
BeanBinder<Person> binder = new BeanBinder<>(Person.class);
binder.bindInstanceFields(form);

Person person = new Person();
person.setFirstName("foo");

binder.bind(person);

Assert.assertNull(form.firstName);
}

@Test
public void bindInstanceFields_genericField() {
BindGenericField form = new BindGenericField();
BeanBinder<Person> binder = new BeanBinder<>(Person.class);
binder.bindInstanceFields(form);

Person person = new Person();
person.setFirstName("foo");

binder.bind(person);

Assert.assertEquals(person.getFirstName(), form.firstName.getValue());

form.firstName.setValue("bar");

Assert.assertEquals(form.firstName.getValue(), person.getFirstName());
}

@Test(expected = IllegalStateException.class)
public void bindInstanceFields_genericFieldWithWrongTypeParameter() {
BindGenericWrongTypeParameterField form = new BindGenericWrongTypeParameterField();
BeanBinder<Person> binder = new BeanBinder<>(Person.class);
binder.bindInstanceFields(form);
}

@Test(expected = IllegalStateException.class)
public void bindInstanceFields_generic() {
BindGeneric<String> form = new BindGeneric<>();
BeanBinder<Person> binder = new BeanBinder<>(Person.class);
binder.bindInstanceFields(form);
}

@Test(expected = IllegalStateException.class)
public void bindInstanceFields_rawFieldType() {
BindRaw form = new BindRaw();
BeanBinder<Person> binder = new BeanBinder<>(Person.class);
binder.bindInstanceFields(form);
}

@Test(expected = IllegalStateException.class)
public void bindInstanceFields_abstractFieldType() {
BindAbstract form = new BindAbstract();
BeanBinder<Person> binder = new BeanBinder<>(Person.class);
binder.bindInstanceFields(form);
}

@Test(expected = IllegalStateException.class)
public void bindInstanceFields_noInstantiatableFieldType() {
BindNonInstantiatableType form = new BindNonInstantiatableType();
BeanBinder<Person> binder = new BeanBinder<>(Person.class);
binder.bindInstanceFields(form);
}

@Test(expected = IllegalStateException.class)
public void bindInstanceFields_wrongFieldType() {
BindWrongTypeParameterField form = new BindWrongTypeParameterField();
BeanBinder<Person> binder = new BeanBinder<>(Person.class);
binder.bindInstanceFields(form);
}

@Test
public void bindInstanceFields_complexGenericHierarchy() {
BindComplextHierarchyGenericType form = new BindComplextHierarchyGenericType();
BeanBinder<Person> binder = new BeanBinder<>(Person.class);
binder.bindInstanceFields(form);

Person person = new Person();
person.setFirstName("foo");

binder.bind(person);

Assert.assertEquals(person.getFirstName(), form.firstName.getValue());

form.firstName.setValue("bar");

Assert.assertEquals(form.firstName.getValue(), person.getFirstName());
}

@Test
public void bindInstanceFields_bindNotHasValueField_fieldIsNotReplaced() {
BindNoHasValueField form = new BindNoHasValueField();
BeanBinder<Person> binder = new BeanBinder<>(Person.class);

String name = "foo";
form.firstName = name;

binder.bindInstanceFields(form);

Person person = new Person();
person.setFirstName("foo");

binder.bind(person);

Assert.assertEquals(name, form.firstName);
}

@Test
public void bindInstanceFields_bindAllFieldsUsingAnnotations() {
BindFieldsUsingAnnotation form = new BindFieldsUsingAnnotation();
BeanBinder<Person> binder = new BeanBinder<>(Person.class);
binder.bindInstanceFields(form);

Person person = new Person();
person.setFirstName("foo");
person.setBirthDate(LocalDate.now());

binder.bind(person);

Assert.assertEquals(person.getFirstName(), form.nameField.getValue());
Assert.assertEquals(person.getBirthDate(),
form.birthDateField.getValue());

form.nameField.setValue("bar");
form.birthDateField.setValue(person.getBirthDate().plusDays(345));

Assert.assertEquals(form.nameField.getValue(), person.getFirstName());
Assert.assertEquals(form.birthDateField.getValue(),
person.getBirthDate());
}

@Test
public void bindInstanceFields_bindNotBoundFieldsOnly_customBindingIsNotReplaced() {
BindAllFields form = new BindAllFields();
BeanBinder<Person> binder = new BeanBinder<>(Person.class);

TextField name = new TextField();
form.firstName = name;
binder.forField(form.firstName)
.withValidator(
new StringLengthValidator("Name is invalid", 3, 10))
.bind("firstName");

binder.bindInstanceFields(form);

Person person = new Person();
String personName = "foo";
person.setFirstName(personName);
person.setBirthDate(LocalDate.now());

binder.bind(person);

Assert.assertEquals(person.getFirstName(), form.firstName.getValue());
Assert.assertEquals(person.getBirthDate(), form.birthDate.getValue());
// the instance is not overridden
Assert.assertEquals(name, form.firstName);

form.firstName.setValue("aa");
form.birthDate.setValue(person.getBirthDate().plusDays(345));

Assert.assertEquals(personName, person.getFirstName());
Assert.assertEquals(form.birthDate.getValue(), person.getBirthDate());

Assert.assertFalse(binder.validate().isOk());
}

@Test
public void bindInstanceFields_fieldsAreConfigured_customBindingIsNotReplaced() {
BindOnlyOneField form = new BindOnlyOneField();
BeanBinder<Person> binder = new BeanBinder<>(Person.class);

TextField name = new TextField();
form.firstName = name;
binder.forField(form.firstName)
.withValidator(
new StringLengthValidator("Name is invalid", 3, 10))
.bind("firstName");
TextField ageField = new TextField();
form.noFieldInPerson = ageField;
binder.forField(form.noFieldInPerson)
.withConverter(new StringToIntegerConverter(""))
.bind(Person::getAge, Person::setAge);

binder.bindInstanceFields(form);

Person person = new Person();
String personName = "foo";
int age = 11;
person.setFirstName(personName);
person.setAge(age);

binder.bind(person);

Assert.assertEquals(person.getFirstName(), form.firstName.getValue());
Assert.assertEquals(String.valueOf(person.getAge()),
form.noFieldInPerson.getValue());
// the instances are not overridden
Assert.assertEquals(name, form.firstName);
Assert.assertEquals(ageField, form.noFieldInPerson);

form.firstName.setValue("aa");
age = age + 56;
form.noFieldInPerson.setValue(String.valueOf(age));

Assert.assertEquals(personName, person.getFirstName());
Assert.assertEquals(form.noFieldInPerson.getValue(),
String.valueOf(person.getAge()));

Assert.assertFalse(binder.validate().isOk());
}
}

+ 4
- 4
server/src/test/java/com/vaadin/tests/data/bean/Person.java View File

@@ -1,7 +1,7 @@
package com.vaadin.tests.data.bean;

import java.math.BigDecimal;
import java.util.Date;
import java.time.LocalDate;

public class Person {
private String firstName;
@@ -11,7 +11,7 @@ public class Person {
private Sex sex;
private Address address;
private boolean deceased;
private Date birthDate;
private LocalDate birthDate;

private Integer salary; // null if unknown
private Double salaryDouble; // null if unknown
@@ -122,11 +122,11 @@ public class Person {
this.salaryDouble = salaryDouble;
}

public Date getBirthDate() {
public LocalDate getBirthDate() {
return birthDate;
}

public void setBirthDate(Date birthDate) {
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}


+ 1
- 1
uitest/src/main/java/com/vaadin/tests/declarative/PotusForm.java View File

@@ -16,11 +16,11 @@
package com.vaadin.tests.declarative;

import com.vaadin.annotations.DesignRoot;
import com.vaadin.annotations.PropertyId;
import com.vaadin.ui.Button;
import com.vaadin.ui.DateField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.declarative.Design;
import com.vaadin.v7.data.fieldgroup.PropertyId;
import com.vaadin.v7.ui.ComboBox;
import com.vaadin.v7.ui.TextField;


+ 1
- 1
uitest/src/main/java/com/vaadin/tests/fieldgroup/AbstractBasicCrud.java View File

@@ -18,6 +18,7 @@ package com.vaadin.tests.fieldgroup;
import java.util.Iterator;
import java.util.Map;

import com.vaadin.annotations.PropertyId;
import com.vaadin.server.VaadinRequest;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.shared.util.SharedUtil;
@@ -39,7 +40,6 @@ import com.vaadin.v7.data.Property.ValueChangeListener;
import com.vaadin.v7.data.Validator.InvalidValueException;
import com.vaadin.v7.data.fieldgroup.BeanFieldGroup;
import com.vaadin.v7.data.fieldgroup.FieldGroup.CommitException;
import com.vaadin.v7.data.fieldgroup.PropertyId;
import com.vaadin.v7.data.util.BeanItem;
import com.vaadin.v7.data.util.BeanItemContainer;
import com.vaadin.v7.data.validator.IntegerRangeValidator;

+ 1
- 1
uitest/src/main/java/com/vaadin/tests/fieldgroup/DateForm.java View File

@@ -3,6 +3,7 @@ package com.vaadin.tests.fieldgroup;
import java.util.Date;
import java.util.Locale;

import com.vaadin.annotations.PropertyId;
import com.vaadin.server.VaadinRequest;
import com.vaadin.tests.components.AbstractTestUIWithLog;
import com.vaadin.tests.data.bean.Person;
@@ -12,7 +13,6 @@ import com.vaadin.ui.Notification;
import com.vaadin.v7.data.fieldgroup.BeanFieldGroup;
import com.vaadin.v7.data.fieldgroup.FieldGroup;
import com.vaadin.v7.data.fieldgroup.FieldGroup.CommitException;
import com.vaadin.v7.data.fieldgroup.PropertyId;
import com.vaadin.v7.data.util.BeanItem;
import com.vaadin.v7.ui.DateField;
import com.vaadin.v7.ui.InlineDateField;

+ 1
- 1
uitest/src/main/java/com/vaadin/tests/fieldgroup/FormBuilderWithNestedProperties.java View File

@@ -1,5 +1,6 @@
package com.vaadin.tests.fieldgroup;

import com.vaadin.annotations.PropertyId;
import com.vaadin.tests.components.TestBase;
import com.vaadin.tests.data.bean.Address;
import com.vaadin.tests.data.bean.Country;
@@ -7,7 +8,6 @@ import com.vaadin.tests.data.bean.Person;
import com.vaadin.tests.data.bean.Sex;
import com.vaadin.v7.data.fieldgroup.BeanFieldGroup;
import com.vaadin.v7.data.fieldgroup.FieldGroup;
import com.vaadin.v7.data.fieldgroup.PropertyId;
import com.vaadin.v7.data.util.BeanItem;
import com.vaadin.v7.ui.TextField;


+ 1
- 1
uitest/src/main/java/com/vaadin/tests/fieldgroup/FormWithNestedProperties.java View File

@@ -1,5 +1,6 @@
package com.vaadin.tests.fieldgroup;

import com.vaadin.annotations.PropertyId;
import com.vaadin.tests.data.bean.Address;
import com.vaadin.tests.data.bean.Country;
import com.vaadin.tests.data.bean.Person;
@@ -7,7 +8,6 @@ import com.vaadin.tests.data.bean.Sex;
import com.vaadin.tests.util.Log;
import com.vaadin.ui.CheckBox;
import com.vaadin.v7.data.fieldgroup.BeanFieldGroup;
import com.vaadin.v7.data.fieldgroup.PropertyId;
import com.vaadin.v7.ui.NativeSelect;
import com.vaadin.v7.ui.TextField;


+ 1
- 1
uitest/src/main/java/com/vaadin/tests/minitutorials/v7a1/FormUsingExistingLayout.java View File

@@ -1,10 +1,10 @@
package com.vaadin.tests.minitutorials.v7a1;

import com.vaadin.annotations.PropertyId;
import com.vaadin.server.VaadinRequest;
import com.vaadin.tests.components.AbstractReindeerTestUI;
import com.vaadin.ui.GridLayout;
import com.vaadin.v7.data.fieldgroup.FieldGroup;
import com.vaadin.v7.data.fieldgroup.PropertyId;
import com.vaadin.v7.data.util.BeanItem;
import com.vaadin.v7.ui.TextArea;
import com.vaadin.v7.ui.TextField;

Loading…
Cancel
Save