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;
}
}