/* * Copyright (c) 2010-2016. 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.messaging.annotation; import org.axonframework.common.annotation.PriorityAnnotationComparator; import java.lang.reflect.Executable; import java.lang.reflect.Parameter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; /** * ParameterResolverFactory instance that delegates to multiple other instances, in the order provided. * * @author Allard Buijze * @since 2.1 */ public class MultiParameterResolverFactory implements ParameterResolverFactory { private final ParameterResolverFactory[] factories; /** * Creates a MultiParameterResolverFactory instance with the given {@code delegates}, which are automatically * ordered based on the {@link org.axonframework.common.Priority @Priority} annotation on their respective classes. * Classes with the same Priority are kept in the order as provided in the {@code delegates}. * <p> * If one of the delegates is a MultiParameterResolverFactory itself, that factory's delegates are 'mixed' with * the given {@code delegates}, based on their respective order. * * @param delegates The delegates to include in the factory * @return an instance delegating to the given {@code delegates} */ public static MultiParameterResolverFactory ordered(ParameterResolverFactory... delegates) { return ordered(Arrays.asList(delegates)); } /** * Creates a MultiParameterResolverFactory instance with the given {@code delegates}, which are automatically * ordered based on the {@link org.axonframework.common.Priority @Priority} annotation on their respective classes. * Classes with the same Priority are kept in the order as provided in the {@code delegates}. * <p> * If one of the delegates is a MultiParameterResolverFactory itself, that factory's delegates are 'mixed' with * the given {@code delegates}, based on their respective order. * * @param delegates The delegates to include in the factory * @return an instance delegating to the given {@code delegates} */ public static MultiParameterResolverFactory ordered(List<ParameterResolverFactory> delegates) { return new MultiParameterResolverFactory(flatten(delegates)); } /** * Initializes an instance that delegates to the given {@code delegates}, in the order provided. Changes in * the given array are not reflected in the created instance. * * @param delegates The factories providing the parameter values to use */ public MultiParameterResolverFactory(ParameterResolverFactory... delegates) { this.factories = Arrays.copyOf(delegates, delegates.length); } /** * Initializes an instance that delegates to the given {@code delegates}, in the order provided. Changes in * the given List are not reflected in the created instance. * * @param delegates The list of factories providing the parameter values to use */ public MultiParameterResolverFactory(List<ParameterResolverFactory> delegates) { this.factories = delegates.toArray(new ParameterResolverFactory[delegates.size()]); } private static ParameterResolverFactory[] flatten(List<ParameterResolverFactory> factories) { List<ParameterResolverFactory> flattened = new ArrayList<>(factories.size()); for (ParameterResolverFactory parameterResolverFactory : factories) { if (parameterResolverFactory instanceof MultiParameterResolverFactory) { flattened.addAll(((MultiParameterResolverFactory) parameterResolverFactory).getDelegates()); } else { flattened.add(parameterResolverFactory); } } Collections.sort(flattened, PriorityAnnotationComparator.getInstance()); return flattened.toArray(new ParameterResolverFactory[flattened.size()]); } /** * Returns the delegates of this instance, in the order they are evaluated to resolve parameters. * * @return the delegates of this instance, in the order they are evaluated to resolve parameters */ public List<ParameterResolverFactory> getDelegates() { return Arrays.asList(factories); } @Override public ParameterResolver createInstance(Executable executable, Parameter[] parameters, int parameterIndex) { for (ParameterResolverFactory factory : factories) { ParameterResolver resolver = factory.createInstance(executable, parameters, parameterIndex); if (resolver != null) { return resolver; } } return null; } }