/* * 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.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.ContentMode; import com.vaadin.shared.util.SharedUtil; import com.vaadin.tests.components.AbstractTestUIWithLog; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.CheckBox; import com.vaadin.ui.Component; import com.vaadin.ui.GridLayout; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.Notification; import com.vaadin.ui.Notification.Type; import com.vaadin.ui.themes.ValoTheme; import com.vaadin.v7.data.Property.ValueChangeEvent; 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.util.BeanItem; import com.vaadin.v7.data.util.BeanItemContainer; import com.vaadin.v7.data.validator.IntegerRangeValidator; import com.vaadin.v7.ui.ComboBox; import com.vaadin.v7.ui.Field; import com.vaadin.v7.ui.TextField; public abstract class AbstractBasicCrud extends AbstractTestUIWithLog { protected AbstractForm form; protected static String[] columns = new String[] { "firstName", "lastName", "gender", "birthDate", "age", "alive", "address.streetAddress", "address.postalCode", "address.city", "address.country" }; protected BeanItemContainer<ComplexPerson> container = ComplexPerson .createContainer(100);; { container.addNestedContainerBean("address"); } protected ComboBox formType; /* * (non-Javadoc) * * @see com.vaadin.tests.components.AbstractTestUI#setup(com.vaadin.server. * VaadinRequest) */ @Override protected void setup(VaadinRequest request) { getLayout().setSizeFull(); getLayout().setSpacing(true); getContent().setSizeFull(); form = new CustomForm(); formType = new ComboBox(); formType.setNullSelectionAllowed(false); formType.setWidth("300px"); formType.addItem(form); formType.setValue(form); formType.addItem(new AutoGeneratedForm(TextField.class)); formType.addItem(new AutoGeneratedForm(Field.class)); Iterator<?> iterator = formType.getItemIds().iterator(); formType.setItemCaption(iterator.next(), "TextField based form"); formType.setItemCaption(iterator.next(), "Auto generated form (TextFields)"); formType.setItemCaption(iterator.next(), "Auto generated form (Any fields)"); formType.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { AbstractForm oldForm = form; form = (AbstractForm) formType.getValue(); replaceComponent(oldForm, form); } }); addComponent(formType); } public class CustomForm extends AbstractForm { private TextField firstName = new TextField("First name"); private TextField lastName = new TextField("Last name"); private TextField gender = new TextField("Gender"); private TextField birthDate = new TextField("Birth date"); private TextField age = new TextField("Age"); private CheckBox alive = new CheckBox("Alive"); private Label errorLabel = new Label((String) null, ContentMode.HTML); @PropertyId("address.streetAddress") private TextField address_streetAddress = new TextField( "Street address"); @PropertyId("address.postalCode") private TextField address_postalCode = new TextField("Postal code"); @PropertyId("address.city") private TextField address_city = new TextField("City"); @PropertyId("address.country") private TextField address_country = new TextField("Country"); public CustomForm() { fieldGroup.bindMemberFields(this); address_postalCode.setNullRepresentation(""); gender.setNullRepresentation(""); age.setNullRepresentation(""); address_country.setNullRepresentation(""); // Last name editing is disabled through property readonly. // Postal code editing is disabled through disabling field. /* * Currently only sets the initial state because of * https://dev.vaadin.com/ticket/17847 * * Must set lastName state initially as BeanFieldGroup can't tell it * should be read-only before setting an item data source */ lastName.setReadOnly(true); address_postalCode.setEnabled(false); birthDate.setNullRepresentation(""); age.addValidator(new IntegerRangeValidator( "Must be between 0 and 100", 0, 100)); setDefaultComponentAlignment(Alignment.MIDDLE_LEFT); addComponents(firstName, lastName, gender, birthDate, age, alive, address_streetAddress, address_postalCode, address_city, address_country); errorLabel.addStyleName(ValoTheme.LABEL_COLORED); setRows(3); addComponent(errorLabel, 0, 2, getColumns() - 1, 2); HorizontalLayout hl = new HorizontalLayout(save, cancel); hl.setSpacing(true); addComponent(hl); } @Override protected void handleCommitException(CommitException e) { String message = ""; // Produce error message in the order in which the fields are in the // layout for (Component c : this) { if (!(c instanceof Field)) { continue; } Field<?> f = (Field<?>) c; Map<Field<?>, InvalidValueException> exceptions = e .getInvalidFields(); if (exceptions.containsKey(f)) { message += f.getCaption() + ": " + exceptions.get(f).getLocalizedMessage() + "<br/>\n"; } } errorLabel.setValue(message); } @Override protected void discard() { super.discard(); errorLabel.setValue(null); } } protected abstract void deselectAll(); public class AbstractForm extends GridLayout { protected Button save = new Button("Save"); protected Button cancel = new Button("Cancel"); protected BeanFieldGroup<ComplexPerson> fieldGroup = new BeanFieldGroup<ComplexPerson>( ComplexPerson.class) { @Override protected void configureField(com.vaadin.v7.ui.Field<?> field) { super.configureField(field); if (field.getCaption().equals("Postal code")) { // Last name editing is disabled through property. // Postal code editing is disabled through field. /* * This is needed because of * https://dev.vaadin.com/ticket/17847 */ field.setEnabled(false); } }; }; public AbstractForm() { super(5, 1); setSpacing(true); setId("form"); save.addClickListener(new ClickListener() { @Override public void buttonClick(ClickEvent event) { try { fieldGroup.commit(); log("Saved " + fieldGroup.getItemDataSource()); } catch (CommitException e) { handleCommitException(e); log("Commit failed: " + e.getMessage()); } } }); cancel.addClickListener(new ClickListener() { @Override public void buttonClick(ClickEvent event) { log("Discarded " + fieldGroup.getItemDataSource()); discard(); } }); } protected void discard() { deselectAll(); } protected void handleCommitException(CommitException e) { String message = ""; for (Object propertyId : e.getInvalidFields().keySet()) { Field<?> f = e.getFieldGroup().getField(propertyId); message += f.getCaption() + ": " + e.getInvalidFields().get(propertyId); } if (!message.isEmpty()) { Notification.show(message, Type.ERROR_MESSAGE); } } public void edit(BeanItem<ComplexPerson> item) { fieldGroup.setItemDataSource(item); } } public class AutoGeneratedForm extends AbstractForm { public AutoGeneratedForm(Class<? extends Field> class1) { for (String p : columns) { Field f = fieldGroup.getFieldFactory() .createField(container.getType(p), class1); f.setCaption(SharedUtil.propertyIdToHumanFriendly(p)); fieldGroup.bind(f, p); addComponent(f); } HorizontalLayout hl = new HorizontalLayout(save, cancel); hl.setSpacing(true); addComponent(hl); } } }