package enterpriseapp.ui.crud; import javax.persistence.GeneratedValue; import javax.persistence.OneToMany; import com.vaadin.data.Item; import com.vaadin.data.util.BeanItem; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.Field; import com.vaadin.ui.Form; import com.vaadin.ui.FormFieldFactory; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import enterpriseapp.Utils; import enterpriseapp.ui.Constants; /** * A CRUD form used by CrudComponent. * * @author Alejandro Duarte. * * @param <T> CRUD Entity class. */ public class CrudForm<T> extends Form implements FieldContainer { private static final long serialVersionUID = 1L; protected Class<T> type; protected boolean autogeneratedId; protected boolean hideNewButton; protected boolean hideUpdateButton; protected boolean hideDeleteButton; protected Button newButton = new Button(Constants.uiNew); protected Button updateButton = new Button(Constants.uiModify); protected Button deleteButton = new Button(Constants.uiDelete); protected Button saveButton = new Button(Constants.uiSave); protected Button cancelButton = new Button(Constants.uiCancel); protected Button firstButton = new Button(Constants.uiFirst); protected Button previousButton = new Button(Constants.uiPrevious); protected Button nextButton = new Button(Constants.uiNext); protected Button lastButton = new Button(Constants.uiLast); /** * @param type Entity class. * @param formFieldFactory FormFieldFactory used to create the fields.. */ public CrudForm(Class<T> type, FormFieldFactory formFieldFactory) { super(); this.type = type; hideNewButton = false; hideUpdateButton = false; hideDeleteButton = false; try { autogeneratedId = type.getDeclaredField("id").getAnnotation(GeneratedValue.class) != null; } catch (SecurityException e) { throw new RuntimeException(e); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } setFormFieldFactory(formFieldFactory); setBuffered(false); setImmediate(true); initLayout(); setReadOnly(true); } /** * Inits the layout. Adds a footer with the CRUD action buttons. */ public void initLayout() { HorizontalLayout footer = new HorizontalLayout(); footer.setSpacing(true); footer.setWidth("100%"); Label leftSpacer = new Label(); leftSpacer.setWidth("100%"); footer.addComponent(leftSpacer); footer.setExpandRatio(leftSpacer, 1); footer.addComponent(newButton); footer.addComponent(updateButton); footer.addComponent(deleteButton); footer.addComponent(saveButton); footer.addComponent(cancelButton); footer.setComponentAlignment(newButton, Alignment.BOTTOM_RIGHT); footer.setComponentAlignment(updateButton, Alignment.BOTTOM_RIGHT); footer.setComponentAlignment(deleteButton, Alignment.BOTTOM_RIGHT); footer.setComponentAlignment(saveButton, Alignment.BOTTOM_RIGHT); footer.setComponentAlignment(cancelButton, Alignment.BOTTOM_RIGHT); setFooter(footer); } @SuppressWarnings("unchecked") @Override public BeanItem<T> getItemDataSource() { return (BeanItem<T>) super.getItemDataSource(); } @Override public void setItemDataSource(Item newDataSource) { setComponentError(null); super.setItemDataSource(newDataSource); setReadOnly(true); } @Override public void setReadOnly(boolean readOnly) { if(getItemDataSource() != null) { for(Object propertyId : getItemDataSource().getItemPropertyIds()) { Field field = getField(propertyId); if(field != null) { configureField(field, propertyId); } } Object[] visibleFieldsFromConfig = Utils.getVisibleFormProperties(type); if(visibleFieldsFromConfig != null) { setVisibleItemProperties(visibleFieldsFromConfig); } } newButton.setVisible(readOnly && !hideNewButton); updateButton.setVisible(readOnly && getItemDataSource() != null && !hideUpdateButton); deleteButton.setVisible(readOnly && getItemDataSource() != null && !hideDeleteButton); saveButton.setVisible(!readOnly); cancelButton.setVisible(!readOnly); super.setReadOnly(readOnly); Field idField = getField("id"); if(idField != null) { if(autogeneratedId || idField.getValue() != null) { idField.setReadOnly(true); } } if(!readOnly && getItemDataSource() != null) { focus(); } } /** * Configures the field when the Form becomes editable (setReadOnly(false)). * @param field Field to configure. * @param propertyId propertyId, usually String with the property name. */ public void configureField(Field field, Object propertyId) { try { OneToMany oneToManyAnnotation = type.getDeclaredField(propertyId.toString()).getAnnotation(OneToMany.class); if(oneToManyAnnotation != null && !oneToManyAnnotation.mappedBy().isEmpty()) { field.setReadOnly(true); field.setVisible(false); } } catch (SecurityException e) { throw new RuntimeException(e); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } } @Override public void addField(Field field, Object propertyId, Item item) { super.addField(propertyId, field); } @Override public Field getField(Object propertyId, Item item) { return super.getField(propertyId); } /** * @return true if the ID property is autogenerated. */ public boolean isAutogeneratedId() { return autogeneratedId; } /** * Hides "new" button. */ public void hideNewButton() { newButton.setEnabled(false); newButton.setVisible(false); hideNewButton = true; } /** * Hides "update" button. */ public void hideUpdateButton() { updateButton.setEnabled(false); updateButton.setVisible(false); hideUpdateButton = true; } /** * Hides "delete" button. */ public void hideDeleteButton() { deleteButton.setEnabled(false); deleteButton.setVisible(false); hideDeleteButton = true; } }