All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.commercetools.sunrise.common.controllers.WithFormFlow Maven / Gradle / Ivy

There is a newer version: 1.0.0-M10
Show newest version
package com.commercetools.sunrise.common.controllers;

import io.sphere.sdk.client.ClientErrorException;
import org.apache.commons.beanutils.BeanUtils;
import play.data.Form;
import play.libs.concurrent.HttpExecution;
import play.mvc.Result;
import play.mvc.Results;
import play.twirl.api.Html;

import javax.annotation.Nullable;
import java.util.Map;
import java.util.concurrent.CompletionStage;

import static io.sphere.sdk.utils.CompletableFutureUtils.*;
import static io.sphere.sdk.utils.CompletableFutureUtils.recoverWith;

/**
 * Approach to handle form data (Template Method Pattern).
 * @param  stereotype of the in a form wrapped class
 * @param  type of the context of the form, possibly a parameter object
 * @param  the type of the updated object if the form is valid
 */
public interface WithFormFlow extends WithForm {

    default CompletionStage showForm(final T context) {
        final Form form = createNewFilledForm(context);
        return renderPage(form, context, null)
                .thenApplyAsync(Results::ok, HttpExecution.defaultContext());
    }

    default CompletionStage validateForm(final T context) {
        return bindForm().thenComposeAsync(form -> {
            if (!form.hasErrors()) {
                return handleValidForm(form, context);
            } else {
                return handleInvalidForm(form, context);
            }
        }, HttpExecution.defaultContext());
    }

    default CompletionStage handleInvalidForm(final Form form, final T context) {
        return renderPage(form, context, null)
                .thenApplyAsync(Results::badRequest, HttpExecution.defaultContext());
    }

    default CompletionStage handleValidForm(final Form form, final T context) {
        final CompletionStage resultStage = doAction(form.get(), context)
                .thenComposeAsync(result -> handleSuccessfulAction(form.get(), context, result), HttpExecution.defaultContext());
        return recoverWith(resultStage, throwable -> handleFailedAction(form, context, throwable), HttpExecution.defaultContext());
    }

    CompletionStage doAction(final F formData, final T context);

    default CompletionStage handleFailedAction(final Form form, final T context, final Throwable throwable) {
        final Throwable causeThrowable = throwable.getCause();
        if (causeThrowable instanceof ClientErrorException) {
            return handleClientErrorFailedAction(form, context, (ClientErrorException) causeThrowable);
        }
        return handleGeneralFailedAction(throwable);
    }

    CompletionStage handleClientErrorFailedAction(final Form form, final T context, final ClientErrorException clientErrorException);

    default CompletionStage handleGeneralFailedAction(final Throwable throwable) {
        return exceptionallyCompletedFuture(throwable);
    }

    CompletionStage handleSuccessfulAction(final F formData, final T context, final R result);

    CompletionStage renderPage(final Form form, final T context, @Nullable final R result);

    default Form createNewFilledForm(final T context) {
        try {
            final F formData = getFormDataClass().getConstructor().newInstance();
            fillFormData(formData, context);
            final Map classFieldValues = BeanUtils.describe(formData);
            final Form filledForm = formFactory().form(getFormDataClass()).bind(classFieldValues);
            filledForm.discardErrors();
            return filledForm;
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException("Missing empty constructor for class " + getFormDataClass().getCanonicalName(), e);
        }
    }

    void fillFormData(final F formData, final T context);
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy