<commit_before>/*
 * Copyright 2017, TeamDev Ltd. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package io.spine.server.reflect;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
import com.google.protobuf.Message;
import io.spine.annotation.Internal;
import io.spine.core.CommandContext;
import io.spine.core.React;
import io.spine.core.RejectionClass;

import javax.annotation.CheckReturnValue;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Set;

import static com.google.common.base.Preconditions.checkNotNull;
import static io.spine.util.Exceptions.unsupported;

/**
 * A wrapper for a rejection reactor method.
 *
 * @author <NAME>
 * @author <NAME>
 * @author <NAME>
 */
@Internal
public class RejectionReactorMethod extends RejectionHandlerMethod {

    /** The instance of the predicate to filter rejection reactor methods of a class. */
    private static final MethodPredicate PREDICATE = new FilterPredicate();

    /**
     * Creates a new instance to wrap {@code method} on {@code target}.
     *
     * @param method reactor method
     */
    @VisibleForTesting
    RejectionReactorMethod(Method method) {
        super(method);
    }

    /**
     * Invokes the reactor method in the passed object.
     */
    public static List<? extends Message> invokeFor(Object target,
                                                    Message rejectionMessage,
                                                    Message commandMessage,
                                                    CommandContext context) {
        checkNotNull(target);
        checkNotNull(rejectionMessage);
        checkNotNull(commandMessage);
        checkNotNull(context);

        final RejectionReactorMethod method =
                getMethod(target.getClass(), rejectionMessage, commandMessage);
        final List<? extends Message> result =
                method.invoke(target, rejectionMessage, commandMessage, context);
        return result;
    }

    /**
     * Obtains the method for handling the rejection in the passed class.
     *
     * @throws IllegalStateException if the passed class does not have an rejection handling method
     *                               for the class of the passed message
     */
    public static RejectionReactorMethod getMethod(Class<?> cls,
                                                   Message rejectionMessage,
                                                   Message commandMessage) {
        checkNotNull(cls);
        checkNotNull(rejectionMessage);
        checkNotNull(commandMessage);

        final Class<? extends Message> rejectionClass = rejectionMessage.getClass();
        final MethodRegistry registry = MethodRegistry.getInstance();
        final RejectionReactorMethod method = registry.get(cls,
                                                           rejectionClass,
                                                           factory());
        if (method == null) {
            throw missingRejectionHandler(cls, rejectionClass);
        }
        return method;
    }

    @CheckReturnValue
    public static Set<RejectionClass> inspect(Class<?> cls) {
        return inspectWith(cls, predicate());
    }


    /**
     * Invokes the wrapped handler method to handle {@code rejectionMessage},
     * {@code commandMessage} with the passed {@code context} of the {@code Command}.
     *
     * <p>Unlike the {@linkplain #invoke(Object, Message, Message) overloaded alternative method},
     * this one does return any value, since the rejection handler methods are {@code void}
     * by design.
     *
     * @param  target           the target object on which call the method
     * @param  rejectionMessage the rejection message to handle
     * @param  commandMessage   the command message
     * @param  context          the context of the command
     * @return the list of event messages produced by the reacting method or empty list if no event
     * messages were produced
     */
    public List<? extends Message> invoke(Object target,
                                          Message rejectionMessage,
                                          Message commandMessage,
                                          CommandContext context) {

        final Object output = doInvoke(target, rejectionMessage, commandMessage, context);
        final List<? extends Message> eventMessages = toList(output);
        return eventMessages;
    }<commit_msg>Clarify the documentation a bit.<commit_after>/*
 * Copyright 2017, TeamDev Ltd. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package io.spine.server.reflect;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
import com.google.protobuf.Message;
import io.spine.annotation.Internal;
import io.spine.core.CommandContext;
import io.spine.core.React;
import io.spine.core.RejectionClass;

import javax.annotation.CheckReturnValue;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Set;

import static com.google.common.base.Preconditions.checkNotNull;
import static io.spine.util.Exceptions.unsupported;

/**
 * A wrapper for a rejection reactor method.
 *
 * @author <NAME>
 * @author <NAME>
 * @author <NAME>
 */
@Internal
public class RejectionReactorMethod extends RejectionHandlerMethod {

    /** The instance of the predicate to filter rejection reactor methods of a class. */
    private static final MethodPredicate PREDICATE = new FilterPredicate();

    /**
     * Creates a new instance to wrap {@code method} on {@code target}.
     *
     * @param method reactor method
     */
    @VisibleForTesting
    RejectionReactorMethod(Method method) {
        super(method);
    }

    /**
     * Invokes the reactor method in the passed object.
     */
    public static List<? extends Message> invokeFor(Object target,
                                                    Message rejectionMessage,
                                                    Message commandMessage,
                                                    CommandContext context) {
        checkNotNull(target);
        checkNotNull(rejectionMessage);
        checkNotNull(commandMessage);
        checkNotNull(context);

        final RejectionReactorMethod method =
                getMethod(target.getClass(), rejectionMessage, commandMessage);
        final List<? extends Message> result =
                method.invoke(target, rejectionMessage, commandMessage, context);
        return result;
    }

    /**
     * Obtains the method for handling the rejection in the passed class.
     *
     * @throws IllegalStateException if the passed class does not have an rejection handling method
     *                               for the class of the passed message
     */
    public static RejectionReactorMethod getMethod(Class<?> cls,
                                                   Message rejectionMessage,
                                                   Message commandMessage) {
        checkNotNull(cls);
        checkNotNull(rejectionMessage);
        checkNotNull(commandMessage);

        final Class<? extends Message> rejectionClass = rejectionMessage.getClass();
        final MethodRegistry registry = MethodRegistry.getInstance();
        final RejectionReactorMethod method = registry.get(cls,
                                                           rejectionClass,
                                                           factory());
        if (method == null) {
            throw missingRejectionHandler(cls, rejectionClass);
        }
        return method;
    }

    @CheckReturnValue
    public static Set<RejectionClass> inspect(Class<?> cls) {
        return inspectWith(cls, predicate());
    }


    /**
     * Invokes the wrapped handler method to handle {@code rejectionMessage},
     * {@code commandMessage} with the passed {@code context} of the {@code Command}.
     *
     * <p>Unlike the {@linkplain #invoke(Object, Message, Message) overloaded alternative method},
     * this one implies returning the value, being a reaction to the rejection passed.
     *
     * @param  target           the target object on which call the method
     * @param  rejectionMessage the rejection message to handle
     * @param  commandMessage   the command message
     * @param  context          the context of the command
     * @return the list of event messages produced by the reacting method or empty list if no event
     * messages were produced
     */
    public List<? extends Message> invoke(Object target,
                                          Message rejectionMessage,
                                          Message commandMessage,
                                          CommandContext context) {

        final Object output = doInvoke(target, rejectionMessage, commandMessage, context);
        final List<? extends Message> eventMessages = toList(output);
        return eventMessages;
    }
{'fraction_non_alphanumeric': 0.06934039831902064, 'fraction_numerical': 0.0007308605883427736, 'mean_word_length': 2.3507805325987143, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 42, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2145315', 'n_tokens_mistral': 2559, 'n_tokens_neox': 2397, 'n_words': 951}