package com.googlecode.tawus.components; import org.apache.tapestry5.BindingConstants; import org.apache.tapestry5.Block; import org.apache.tapestry5.ClientElement; import org.apache.tapestry5.ComponentResources; import org.apache.tapestry5.EventConstants; import org.apache.tapestry5.Field; import org.apache.tapestry5.FormValidationControl; import org.apache.tapestry5.SymbolConstants; import org.apache.tapestry5.ValidationException; import org.apache.tapestry5.annotations.Component; import org.apache.tapestry5.annotations.Parameter; import org.apache.tapestry5.annotations.Persist; import org.apache.tapestry5.annotations.Property; import org.apache.tapestry5.annotations.SupportsInformalParameters; import org.apache.tapestry5.beaneditor.BeanModel; import org.apache.tapestry5.corelib.components.Form; import org.apache.tapestry5.corelib.components.Zone; import org.apache.tapestry5.internal.beaneditor.BeanModelUtils; import org.apache.tapestry5.internal.util.CaptureResultCallback; import org.apache.tapestry5.ioc.annotations.Inject; import org.apache.tapestry5.ioc.annotations.Symbol; import org.apache.tapestry5.services.BeanModelSource; import com.googlecode.tawus.ActionType; import com.googlecode.tawus.TawusEvents; import com.googlecode.tawus.TawusUtils; import com.googlecode.tawus.annotations.XHR; import com.googlecode.tawus.internal.GridRuntime; import com.googlecode.tawus.services.EntityDAOLocator; import com.googlecode.tawus.services.EntityValidator; /** * An alternative for BeanEditorForm which uses tables instead of divs The * reorder parameter has been modified to accomidate the same. A reorder * parameter can take a list of row configurations. separated by semicolon(',') * <p/> * Each row configuration consists of a list of column configurations separated * by comma(,) * <p/> * Each column configuration consisting of four fields separated by * <strong>'/'</strong>. The order is * fieldName/columnSeparator/rowSeparator/rowClass * */ @SupportsInformalParameters public class EntityEditForm implements FormValidationControl, ClientElement { @Inject @Property(write = false) private ComponentResources resources; /** Model to be used for the current object */ @SuppressWarnings({ "rawtypes" }) @Property private BeanModel model; @SuppressWarnings("unused") @Parameter(value = "true", defaultPrefix = BindingConstants.LITERAL) @Property private boolean showHelp; /** Object to be edited */ @Parameter(value = "prop:grid.object", allowNull = false) @Property private Object object; @Parameter(defaultPrefix = BindingConstants.COMPONENT) @Property private GridRuntime grid; /** New properties to be add */ @Parameter(defaultPrefix = BindingConstants.LITERAL) @Property private String add; /** Properties to be included */ @SuppressWarnings("unused") @Parameter(defaultPrefix = BindingConstants.LITERAL) @Property private String include; /** Whether the object is deletable */ @SuppressWarnings("unused") @Parameter(value = "false", allowNull = false) @Property private boolean deletable; @SuppressWarnings("unused") @Parameter(value = "true", allowNull = false) @Property private boolean cancelable; @SuppressWarnings("unused") @Parameter(value = "true", allowNull = false) @Property private boolean updatable; /** Button panel to use. By default the defaultButtonPanel will be used */ @SuppressWarnings("unused") @Parameter(value = "block:defaultButtonPanel", defaultPrefix = BindingConstants.LITERAL) @Property private Block buttonPanel; @Inject private EntityDAOLocator locator; @Component(parameters = "validationId=componentResources.id") private Form form; @Inject @Symbol(SymbolConstants.FORM_CLIENT_LOGIC_ENABLED) private boolean clientLogicDefaultEnabled; @SuppressWarnings("unused") @Parameter(defaultPrefix = BindingConstants.LITERAL) @Property(write = false) private boolean clientValidation = clientLogicDefaultEnabled; @SuppressWarnings("unused") @Parameter @Property(write = false) private boolean autoFocus = clientLogicDefaultEnabled; @Parameter(defaultPrefix = BindingConstants.LITERAL) private String _zone; @Property @Persist private String zone; @Inject private EntityValidator entityValidator; @Inject private BeanModelSource beanModelSource; /** * On prepare */ @SuppressWarnings("unchecked") void onPrepareFromForm() { resources.triggerEvent(EventConstants.PREPARE, null, null); if(model == null) { @SuppressWarnings("rawtypes") Class beanType = object.getClass(); model = beanModelSource.createEditModel(beanType, resources.getContainerMessages()); BeanModelUtils.modify(model, add, null, null, null); } } void onPrepareForRenderFromForm() { resources.triggerEvent(EventConstants.PREPARE_FOR_RENDER, null, null); } void onPrepareForSubmitFromForm() { resources.triggerEvent(EventConstants.PREPARE_FOR_SUBMIT, null, null); } /** * On validate, trigger ENTITY_VALIDATE trigger * * @throws ValidationException */ void onValidateFromForm() throws ValidationException { entityValidator.validate(object); resources.triggerEvent(EventConstants.VALIDATE, new Object[] { object }, null); } private Object returnValue(ActionType actionType) { CaptureResultCallback<Object> callback = new CaptureResultCallback<Object>(); resources.triggerEvent(TawusEvents.FINISHED, new Object[] { actionType }, callback); if(callback.getResult() != null) { return callback.getResult(); } if(grid != null) { if(!form.getHasErrors() && !getHasErrors()) { grid.showGrid(); } if(zone == null) { zone = grid.getZone(); } } if(zone != null) { return ((Zone) resources.getContainerResources().getEmbeddedComponent(zone)).getBody(); } else { return null; } } public String getZoneId() { return zone == null ? null : ((Zone) resources.getContainerResources().getEmbeddedComponent(zone)).getClientId(); } /** * If cancel button is hit */ @XHR public Object onCancelFromCancel() { CaptureResultCallback<Object> callback = new CaptureResultCallback<Object>(); resources.triggerEvent(TawusEvents.CANCEL, null, callback); if(callback.getResult() != null) { return callback.getResult(); } return returnValue(ActionType.CANCEL); } /** * When delete button is hit */ @SuppressWarnings("unchecked") public Object onDeleteFromDelete() { try { CaptureResultCallback<Object> callback = new CaptureResultCallback<Object>(); resources.triggerEvent(TawusEvents.DELETE, null, callback); if(callback.getResult() == null) { locator.get(getObjectType()).remove(object); } } catch(Exception ex) { ex.printStackTrace(); this.recordError(ex.getMessage()); } return returnValue(ActionType.DELETE); } /** * On successful submission */ @SuppressWarnings("unchecked") public Object onSuccessFromForm() { try { CaptureResultCallback<Object> callback = new CaptureResultCallback<Object>(); resources.triggerEvent(TawusEvents.SAVE, null, callback); if(callback.getResult() == null) { locator.get(getObjectType()).saveOrUpdate(object); } return returnValue(ActionType.SAVE); } catch(Exception ex) { // locator.get(getObjectType()).setIdentifier(object, null); recordError(TawusUtils.stripExceptionPrefix(ex.getMessage())); return returnValue(ActionType.SAVE); } } public Object onFailureFromForm() { return returnValue(ActionType.SAVE); } @SuppressWarnings("rawtypes") private Class getObjectType() { return object.getClass(); } /** * Returns the client id of the embedded form. {@inheritDoc} */ public String getClientId() { return form.getClientId(); } /** * {@inheritDoc} */ public void clearErrors() { form.clearErrors(); } /** * {@inheritDoc} */ public boolean getHasErrors() { return form.getHasErrors(); } /** * {@inheritDoc} */ public boolean isValid() { return form.isValid(); } /** * {@inheritDoc} */ public void recordError(Field field, String errorMessage) { form.recordError(field, TawusUtils.stripExceptionPrefix(errorMessage)); } /** * {@inheritDoc} */ public void recordError(String errorMessage) { form.recordError(TawusUtils.stripExceptionPrefix(errorMessage)); } void setupRender() { zone = (_zone != null ? _zone : (grid != null ? grid.getZone() : null)); } }