<commit_before>/*
 * Copyright 2014-2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package org.lastaflute.web.ruts;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.dbflute.helper.message.ExceptionMessageBuilder;
import org.dbflute.optional.OptionalThing;
import org.lastaflute.db.jta.stage.TransactionGenre;
import org.lastaflute.db.jta.stage.TransactionStage;
import org.lastaflute.web.callback.ActionHook;
import org.lastaflute.web.callback.ActionRuntime;
import org.lastaflute.web.exception.ActionCallbackReturnNullException;
import org.lastaflute.web.exception.ExecuteMethodAccessFailureException;
import org.lastaflute.web.exception.ExecuteMethodArgumentMismatchException;
import org.lastaflute.web.exception.ExecuteMethodReturnNullException;
import org.lastaflute.web.exception.ExecuteMethodReturnTypeNotResponseException;
import org.lastaflute.web.exception.ExecuteMethodReturnUndefinedResponseException;
import org.lastaflute.web.response.ActionResponse;
import org.lastaflute.web.ruts.config.ActionExecute;
import org.lastaflute.web.ruts.message.ActionMessages;
import org.lastaflute.web.ruts.process.ActionResponseReflector;
import org.lastaflute.web.ruts.process.exception.ActionCreateFailureException;
import org.lastaflute.web.servlet.request.RequestManager;
import org.lastaflute.web.util.LaActionExecuteUtil;
import org.lastaflute.web.validation.VaErrorHook;
import org.lastaflute.web.validation.exception.ValidationErrorException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The wrapper of action, which can be God hand. <br>
 * This class is new-created per request.
 * @author jflute
 */
public class GodHandableAction implements VirtualAction {

    // ===================================================================================
    //                                                                          Definition
    //                                                                          ==========
    private static final Logger logger = LoggerFactory.getLogger(GodHandableAction.class);
    private static final Object[] EMPTY_ARRAY = new Object[0];

    // ===================================================================================
    //                                                                           Attribute
    //                                                                           =========
    protected final ActionExecute execute; // fixed info
    protected final ActionRuntime runtime; // has state
    protected final ActionResponseReflector reflector; // has state
    protected final TransactionStage stage; // singleton
    protected final RequestManager requestManager; // singleton
    protected final Object action; // created here

    // ===================================================================================
    //                                                                         Constructor
    //                                                                         ===========
    public GodHandableAction(ActionRuntime runtime, ActionResponseReflector reflector, TransactionStage stage,
            RequestManager requestManager) {
        this.execute = runtime.getActionExecute();
        this.runtime = runtime;
        this.reflector = reflector;
        this.stage = stage;
        this.requestManager = requestManager;
        this.action = createAction();
    }

    protected Object createAction() {
        try {
            return execute.getActionMapping().createAction();
        } catch (RuntimeException e) {
            throw new ActionCreateFailureException("Failed to create the action: " + execute, e);
        }
    }

    // ===================================================================================
    //                                                                             Execute
    //                                                                             =======
    @Override
    public NextJourney execute(OptionalThing<VirtualActionForm> form) {
        final NextJourney journey = godHandyExecute(form);
        setupDisplayData(journey);
        showTransition(journey);
        return journey;
    }

    // -----------------------------------------------------
    //                                             God Handy
    //                                             ---------
    protected NextJourney godHandyExecute(OptionalThing<VirtualActionForm> form) {
        final ActionHook hook = prepareActionHook();
        try {
            final ActionResponse before = processHookBefore(hook);
            if (before.isDefined()) { // e.g. login required
                return reflect(before);
            } else { // mainly here
                return transactionalExecute(form, hook); // #to_action
            }
        } catch (RuntimeException e) {
            return reflect(tellExceptionMonologue(hook, e));
        } finally {
            processHookFinally(hook);
        }
    }

    protected ActionHook prepareActionHook() {
        return action instanceof ActionHook ? (ActionHook) action : null;
    }

    protected NextJourney transactionalExecute(OptionalThing<VirtualActionForm> form, ActionHook hook) {
        final ExecuteTransactionResult result = (ExecuteTransactionResult) stage.selectable(tx -> {
            final ActionResponse response = actuallyExecute(form, hook); /* #to_action */
            assertExecuteMethodResponseDefined(response);
            final NextJourney journey = reflect(response); /* also response handling in transaction */
            tx.returns(new ExecuteTransactionResult(response, journey));
        } , getExecuteTransactionGenre()).get(); // because of not null
        hookAfterTxCommitIfExists(result);
        return result.getJourney();
    }

    protected static class ExecuteTransactionResult {
<commit_msg>small refactor<commit_after>/*
 * Copyright 2014-2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package org.lastaflute.web.ruts;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.dbflute.helper.message.ExceptionMessageBuilder;
import org.dbflute.optional.OptionalThing;
import org.lastaflute.db.jta.stage.TransactionGenre;
import org.lastaflute.db.jta.stage.TransactionStage;
import org.lastaflute.web.callback.ActionHook;
import org.lastaflute.web.callback.ActionRuntime;
import org.lastaflute.web.exception.ActionCallbackReturnNullException;
import org.lastaflute.web.exception.ExecuteMethodAccessFailureException;
import org.lastaflute.web.exception.ExecuteMethodArgumentMismatchException;
import org.lastaflute.web.exception.ExecuteMethodReturnNullException;
import org.lastaflute.web.exception.ExecuteMethodReturnTypeNotResponseException;
import org.lastaflute.web.exception.ExecuteMethodReturnUndefinedResponseException;
import org.lastaflute.web.response.ActionResponse;
import org.lastaflute.web.ruts.config.ActionExecute;
import org.lastaflute.web.ruts.message.ActionMessages;
import org.lastaflute.web.ruts.process.ActionResponseReflector;
import org.lastaflute.web.ruts.process.exception.ActionCreateFailureException;
import org.lastaflute.web.servlet.request.RequestManager;
import org.lastaflute.web.util.LaActionExecuteUtil;
import org.lastaflute.web.validation.VaErrorHook;
import org.lastaflute.web.validation.exception.ValidationErrorException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The wrapper of action, which can be God hand. <br>
 * This class is new-created per request.
 * @author jflute
 */
public class GodHandableAction implements VirtualAction {

    // ===================================================================================
    //                                                                          Definition
    //                                                                          ==========
    private static final Logger logger = LoggerFactory.getLogger(GodHandableAction.class);
    private static final Object[] EMPTY_ARRAY = new Object[0];

    // ===================================================================================
    //                                                                           Attribute
    //                                                                           =========
    protected final ActionExecute execute; // fixed info
    protected final ActionRuntime runtime; // has state
    protected final ActionResponseReflector reflector; // has state
    protected final TransactionStage stage; // singleton
    protected final RequestManager requestManager; // singleton
    protected final Object action; // created here

    // ===================================================================================
    //                                                                         Constructor
    //                                                                         ===========
    public GodHandableAction(ActionRuntime runtime, ActionResponseReflector reflector, TransactionStage stage,
            RequestManager requestManager) {
        this.execute = runtime.getActionExecute();
        this.runtime = runtime;
        this.reflector = reflector;
        this.stage = stage;
        this.requestManager = requestManager;
        this.action = createAction();
    }

    protected Object createAction() {
        try {
            return execute.getActionMapping().createAction();
        } catch (RuntimeException e) {
            throw new ActionCreateFailureException("Failed to create the action: " + execute, e);
        }
    }

    // ===================================================================================
    //                                                                             Execute
    //                                                                             =======
    @Override
    public NextJourney execute(OptionalThing<VirtualActionForm> form) {
        final NextJourney journey = godHandyExecute(form);
        setupDisplayData(journey);
        showTransition(journey);
        return journey;
    }

    // -----------------------------------------------------
    //                                             God Handy
    //                                             ---------
    protected NextJourney godHandyExecute(OptionalThing<VirtualActionForm> form) {
        final ActionHook hook = prepareActionHook();
        try {
            final ActionResponse before = processHookBefore(hook);
            if (before.isDefined()) { // e.g. login required
                return reflect(before);
            } else { // mainly here
                return transactionalExecute(form, hook); // #to_action
            }
        } catch (RuntimeException e) {
            final ActionResponse monologue = tellExceptionMonologue(hook, e);
            return reflect(monologue);
        } finally {
            processHookFinally(hook);
        }
    }

    protected ActionHook prepareActionHook() {
        return action instanceof ActionHook ? (ActionHook) action : null;
    }

    protected NextJourney transactionalExecute(OptionalThing<VirtualActionForm> form, ActionHook hook) {
        final ExecuteTransactionResult result = (ExecuteTransactionResult) stage.selectable(tx -> {
            final ActionResponse response = actuallyExecute(form, hook); /* #to_action */
            assertExecuteMethodResponseDefined(response);
            final NextJourney journey = reflect(response); /* also response handling in transaction */
            tx.returns(new ExecuteTransactionResult(response, journey));
        } , getExecuteTransactionGenre()).get(); // because of not null
        hookAfterTxCommitIfExists(result);
        return result.getJourney();
    }

    protected static class ExecuteTransactionResult {

{'fraction_non_alphanumeric': 0.13591790193842646, 'fraction_numerical': 0.002280501710376283, 'mean_word_length': 2.3297899266008604, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 56, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7057838', 'n_tokens_mistral': 2949, 'n_tokens_neox': 2863, 'n_words': 723}