Package org.axonframework.commandhandling.annotation

Source Code of org.axonframework.commandhandling.annotation.ConstructorCommandMessageHandler

/*
* Copyright (c) 2010-2014. Axon Framework
*
* 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.axonframework.commandhandling.annotation;

import org.axonframework.common.annotation.AbstractMessageHandler;
import org.axonframework.common.annotation.ParameterResolver;
import org.axonframework.common.annotation.ParameterResolverFactory;
import org.axonframework.common.annotation.UnsupportedHandlerException;
import org.axonframework.domain.AggregateRoot;
import org.axonframework.domain.Message;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import static java.lang.String.format;
import static org.axonframework.common.ReflectionUtils.ensureAccessible;

/**
* Command Handler that creates a new aggregate instance by invoking that aggregate's constructor.
*
* @param <T> the type of aggregate this handler handles commands for
* @author Allard Buijze
* @since 1.2
*/
public final class ConstructorCommandMessageHandler<T extends AggregateRoot> extends AbstractMessageHandler {

    private final Constructor<T> constructor;

    /**
     * Creates a ConstructorCommandMessageHandler for the given <code>constructor</code>.
     *
     * @param constructor              The constructor to wrap as a Handler
     * @param parameterResolverFactory The strategy for resolving parameter values of handler methods
     * @param <T>                      The type of Aggregate created by the constructor
     * @return ConstructorCommandMessageHandler
     *
     * @throws UnsupportedHandlerException when the given constructor is not suitable as a Handler
     */
    public static <T extends AggregateRoot> ConstructorCommandMessageHandler<T> forConstructor(
            Constructor<T> constructor, ParameterResolverFactory parameterResolverFactory) {
        ParameterResolver[] resolvers = findResolvers(parameterResolverFactory,
                                                      constructor.getAnnotations(),
                                                      constructor.getParameterTypes(),
                                                      constructor.getParameterAnnotations(),
                                                      true);
        Class<?> firstParameter = constructor.getParameterTypes()[0];
        Class payloadType;
        if (Message.class.isAssignableFrom(firstParameter)) {
            payloadType = Object.class;
        } else {
            payloadType = firstParameter;
        }
        ensureAccessible(constructor);
        validate(constructor, resolvers);
        return new ConstructorCommandMessageHandler<T>(constructor, resolvers, payloadType);
    }

    private static void validate(Constructor constructor, ParameterResolver[] parameterResolvers) {
        for (int i = 0; i < constructor.getParameterTypes().length; i++) {
            if (parameterResolvers[i] == null) {
                throw new UnsupportedHandlerException(
                        format("On method %s, parameter %s is invalid. It is not of any format supported by a provided"
                                       + "ParameterValueResolver.",
                               constructor.toGenericString(), i + 1), constructor);
            }
        }
    }

    /**
     * Creates a new instance for the given <code>constructor</code>, accepting the given <code>parameterType</code>
     * and an <code>optionalParameter</code>.
     *
     * @param constructor             The constructor this handler should invoke
     * @param parameterValueResolvers The resolvers for the constructor parameters
     * @param payloadType             The payload type the constructor is assigned to handle
     */
    private ConstructorCommandMessageHandler(Constructor<T> constructor, ParameterResolver[] parameterValueResolvers,
                                             Class payloadType) {
        super(payloadType, constructor.getDeclaringClass(), parameterValueResolvers);
        this.constructor = constructor;
    }

    @Override
    public T invoke(Object target, Message message) throws InvocationTargetException, IllegalAccessException {
        Object[] parameterValues = new Object[getParameterValueResolvers().length];
        for (int i = 0; i < parameterValues.length; i++) {
            parameterValues[i] = getParameterValueResolvers()[i].resolveParameterValue(message);
        }
        try {
            return constructor.newInstance(parameterValues);
        } catch (InstantiationException e) {
            throw new InvocationTargetException(e.getCause()); // NOSONAR
        }
    }

    @Override
    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
        return constructor.getAnnotation(annotationType);
    }
}
TOP

Related Classes of org.axonframework.commandhandling.annotation.ConstructorCommandMessageHandler

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.