Package org.appfuse.webapp.client.application.base.activity

Source Code of org.appfuse.webapp.client.application.base.activity.AbstractProxyEditActivity

package org.appfuse.webapp.client.application.base.activity;

import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.validation.ConstraintViolation;

import org.appfuse.webapp.client.application.Application;
import org.appfuse.webapp.client.application.base.place.EntityProxyPlace;
import org.appfuse.webapp.client.application.base.place.EntitySearchPlace;
import org.appfuse.webapp.client.application.base.view.ProxyEditView;
import org.appfuse.webapp.client.ui.home.HomePlace;

import com.github.gwtbootstrap.client.ui.constants.AlertType;
import com.google.gwt.activity.shared.Activity;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.place.shared.Place;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.web.bindery.requestfactory.gwt.client.RequestFactoryEditorDriver;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.EntityProxyId;
import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.google.web.bindery.requestfactory.shared.ServerFailure;

/**
* Abstract activity for editing a record. Subclasses must provide access to the
* request that will be fired when Save is clicked.
* <p>
* Instances are not reusable. Once an activity is stoped, it cannot be
* restarted.
*
* Required methods are:
* <ol>
*   <li> {@link #createView(Place)}</li>
*   <li> {@link #createProxyRequest()}</li>
<li> {@link #loadProxyRequest(RequestContext, EntityProxyId)}</li>
*   <li> {@link #saveOrUpdateRequest(RequestContext, EntityProxy)}</li>
*   <li> {@link #deleteRequest(RequestContext, EntityProxy)}</li>
* </ol>
*
* Customization:
* <ol>
*   <li> {@link #createProxy(RequestContext)}</li>
*   <li> {@link #getEntityId()}</li>
*   <li> {@link #getProxyClass()}</li>
*   <li> {@link #loadProxyRequest(RequestContext, EntityProxyId)}</li>
*   <li> {@link #getSavedMessage()}</li>
*   <li> {@link #getDeletedMessage()}</li>
*   <li> {@link #nextPlace(boolean)}</li>
*   <li> {@link #previousPlace()}</li>
* </ol>
*
* @param <P> the type of Proxy being edited
*/
public abstract class AbstractProxyEditActivity<P extends EntityProxy> extends AbstractBaseActivity implements Activity,  ProxyEditView.Delegate {

    protected ProxyEditView<P, ?> view;
    protected RequestFactoryEditorDriver<P, ?> editorDriver;
    protected P entityProxy;
    private boolean waiting;

    private String abandonChangesMessage = "Are you sure you want to abandon your changes?";//FIXME i18n
    private String savedMessage = i18n.entity_saved();
    private String deletedMessage = i18n.entity_deleted();
    private String deleteConfirmation = i18n.delete_confirm("");

    public String getAbandonChangesMessage() {
        return abandonChangesMessage;
    }

    public void setAbandonChangesMessage(final String abandonChangesMessage) {
        this.abandonChangesMessage = abandonChangesMessage;
    }

    public String getSavedMessage() {
        return savedMessage;
    }

    public void setSavedMessage(final String savedMessage) {
        this.savedMessage = savedMessage;
    }

    public String getDeletedMessage() {
        return deletedMessage;
    }

    public void setDeletedMessage(final String deletedMessage) {
        this.deletedMessage = deletedMessage;
    }

    public String getDeleteConfirmation() {
        return deleteConfirmation;
    }

    public void setDeleteConfirmation(final String deleteConfirmation) {
        this.deleteConfirmation = deleteConfirmation;
    }


    /**
     * Called once to create the appropriate request to create/find and edit this entity and
     * that will be fired when the save button is clicked.
     *
     * @return the request context to edit this entity proxy.
     */
    protected abstract RequestContext createProxyRequest();

    /**
     *
     * @param requestContext
     * @return
     */
    protected P createProxy(final RequestContext requestContext) {
        return (P) requestContext.create(getProxyClass());
    }

    /**
     * Create are Request to load this entity proxy.
     *
     * Note: Request.find() method is disabled in the server for security reasons.
     *
     * @param requestContext
     * @param proxyId
     * @return
     */
    protected abstract Request<P> loadProxyRequest(RequestContext requestContext, String proxyId);

    /**
     *
     * @param requestContext
     * @param proxy
     * @return
     */
    protected abstract RequestContext saveOrUpdateRequest(RequestContext requestContext, P proxy);

    /**
     * Called on {@link #deleteClicked()} to create the appropriate request to delete entity.
     *
     * @return the request context to fire when the delete button is clicked
     */
    protected abstract RequestContext deleteRequest(RequestContext requestContext, P proxy);


    /**
     * @param currentPlace
     * @param view
     */
    public AbstractProxyEditActivity(final Application application, final ProxyEditView<P, ?> view) {
        super(application);
        this.view = view;
    }


    /**
     *
     */
    @Override
    public void start(final AcceptsOneWidget display, final EventBus eventBus) {
        view.setDelegate(this);
        editorDriver = view.createEditorDriver();

        doLoadEntityProxy(new Receiver<P>() {
            @Override
            public void onSuccess(final P response) {
                entityProxy = response;
                display.setWidget(view);
                setDocumentTitleAndBodyAttributtes();
            }
        });
    }

    protected String getEntityId(){
        if(currentPlace instanceof EntityProxyPlace) {
            return ((EntityProxyPlace) currentPlace).getEntityId();
        }
        return null;
    }

    protected Class<? extends EntityProxy> getProxyClass(){
        if(currentPlace instanceof EntityProxyPlace) {
            return ((EntityProxyPlace) currentPlace).getProxyClass();
        }
        return null;
    }


    /**
     *
     */
    protected void doLoadEntityProxy(final Receiver<P> onloadCallback) {
        final String proxyId = getEntityId();
        if(proxyId == null) {
            //create a brand new proxy entity
            final RequestContext requestContext = createProxyRequest();
            final P proxy = createProxy(requestContext);
            //edit this entity proxy on the same request it was created
            editorDriver.edit(proxy, saveOrUpdateRequest(requestContext, proxy));
            //finish loading
            onloadCallback.onSuccess(proxy);
        } else {
            //find this entity proxy on the server
            loadProxyRequest(createProxyRequest(), proxyId)
            .with(editorDriver.getPaths())
            .fire(new Receiver<P>() {
                @Override
                public void onSuccess(final P response) {
                    if(editorDriver != null) {
                        //edit this entity proxy on a new request
                        editorDriver.edit(response, saveOrUpdateRequest(createProxyRequest(), response));
                        //finish loading
                        onloadCallback.onSuccess(response);
                    }
                }
            });
        }
    }


    /**
     *
     * @see org.appfuse.webapp.client.application.base.view.ProxyEditView.Delegate#saveClicked()
     */
    @Override
    public void saveClicked() {

        setWaiting(true);
        editorDriver.flush().fire(new Receiver<Void>() {
            /*
             * Callbacks do nothing if editorDriver is null, we were stopped in
             * midflight
             */
            @Override
            public void onFailure(final ServerFailure error) {
                if (editorDriver != null) {
                    setWaiting(false);
                    throw new RuntimeException(error.getMessage());//FIXME
                }
            }

            @Override
            public void onSuccess(final Void ignore) {
                if (editorDriver != null) {
                    editorDriver = null;
                    setWaiting(false);
                    placeController.goTo(nextPlace(true));
                    addMessage(getSavedMessage(), AlertType.SUCCESS);
                }
            }

            @Override
            public void onConstraintViolation(final Set<ConstraintViolation<?>> violations) {
                if (editorDriver != null) {
                    setWaiting(false);
                    editorDriver.setConstraintViolations(violations);
                }
            }

        });
    }


    /**
     *
     * @see org.appfuse.webapp.client.application.base.view.ProxyEditView.Delegate#deleteClicked()
     */
    @Override
    public void deleteClicked() {
        if(!Window.confirm(getDeleteConfirmation())) {
            return;
        }
        deleteRequest(createProxyRequest(), entityProxy).fire(new Receiver<Void>() {
            @Override
            public void onSuccess(final Void response) {
                placeController.goTo(nextPlace(false));
                addMessage(getDeletedMessage(), AlertType.SUCCESS);
            }
        });
    }

    /**
     *
     * @see org.appfuse.webapp.client.application.base.view.ProxyEditView.Delegate#cancelClicked()
     */
    @Override
    public void cancelClicked() {
        final String unsavedChangesWarning = mayStop();
        if ((unsavedChangesWarning == null)
                || Window.confirm(unsavedChangesWarning)) {
            editorDriver = null;
            placeController.goTo(previousPlace());
        }
    }


    /**
     * Creates the {@link Place} to go when this activity is canceled.
     * @param saved
     * @return
     */
    protected Place previousPlace() {
        return new EntitySearchPlace(getProxyClass());
    }

    /**
     * Creates the {@link Place} to go after successfully saved or deleted this entity.
     * @param saved
     * @return
     */
    protected Place nextPlace(final boolean saved) {
        if(saved) {
            return new EntitySearchPlace(getProxyClass());
        } else { // deleted
            return new HomePlace();
        }
    }

    protected void clearMessages() {
        shell.clearMessages();
    }

    protected void addMessage(final String html, final AlertType alertType) {
        shell.addMessage(html, alertType);
    }

    /**
     *
     * @see com.google.gwt.activity.shared.AbstractActivity#mayStop()
     */
    @Override
    public String mayStop() {
        if (isWaiting() || changed()) {
            return getAbandonChangesMessage();
        }

        return null;
    }

    /**
     *
     * @see com.google.gwt.activity.shared.AbstractActivity#onCancel()
     */
    @Override
    public void onCancel() {
        onStop();
    }

    /**
     *
     * @see com.google.gwt.activity.shared.AbstractActivity#onStop()
     */
    @Override
    public void onStop() {
        view.setDelegate(null);
        editorDriver = null;
    }

    /**
     *
     * @return
     */
    private boolean changed() {
        try {
            return editorDriver != null && editorDriver.isDirty();
        } catch (final Exception e) {
            Logger.getLogger("").log(Level.SEVERE, e.getMessage(), e);
            return false;
        }
    }

    /**
     * @return true if we're waiting for an rpc response.
     */
    protected boolean isWaiting() {
        return waiting;
    }

    /**
     * While we are waiting for a response, we cannot poke setters on the proxy
     * (that is, we cannot call editorDriver.flush). So we set the waiting flag to
     * warn ourselves not to, and to disable the view.
     */
    protected void setWaiting(final boolean wait) {
        this.waiting = wait;
        view.setEnabled(!wait);
    }

}
TOP

Related Classes of org.appfuse.webapp.client.application.base.activity.AbstractProxyEditActivity

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.