001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel.reifier;
018
019import java.util.concurrent.ExecutorService;
020
021import org.apache.camel.AggregationStrategy;
022import org.apache.camel.CamelContextAware;
023import org.apache.camel.Expression;
024import org.apache.camel.Processor;
025import org.apache.camel.model.ProcessorDefinition;
026import org.apache.camel.model.ProcessorDefinitionHelper;
027import org.apache.camel.model.SplitDefinition;
028import org.apache.camel.processor.Splitter;
029import org.apache.camel.processor.aggregate.AggregationStrategyBeanAdapter;
030import org.apache.camel.processor.aggregate.ShareUnitOfWorkAggregationStrategy;
031import org.apache.camel.spi.RouteContext;
032import org.apache.camel.support.CamelContextHelper;
033
034public class SplitReifier extends ExpressionReifier<SplitDefinition> {
035
036    public SplitReifier(ProcessorDefinition<?> definition) {
037        super((SplitDefinition)definition);
038    }
039
040    @Override
041    public Processor createProcessor(RouteContext routeContext) throws Exception {
042        Processor childProcessor = this.createChildProcessor(routeContext, true);
043        definition.setAggregationStrategy(createAggregationStrategy(routeContext));
044
045        boolean isParallelProcessing = definition.getParallelProcessing() != null && definition.getParallelProcessing();
046        boolean isStreaming = definition.getStreaming() != null && definition.getStreaming();
047        boolean isShareUnitOfWork = definition.getShareUnitOfWork() != null && definition.getShareUnitOfWork();
048        boolean isParallelAggregate = definition.getParallelAggregate() != null && definition.getParallelAggregate();
049        boolean isStopOnAggregateException = definition.getStopOnAggregateException() != null && definition.getStopOnAggregateException();
050        boolean shutdownThreadPool = ProcessorDefinitionHelper.willCreateNewThreadPool(routeContext, definition, isParallelProcessing);
051        ExecutorService threadPool = ProcessorDefinitionHelper.getConfiguredExecutorService(routeContext, "Split", definition, isParallelProcessing);
052
053        long timeout = definition.getTimeout() != null ? definition.getTimeout() : 0;
054        if (timeout > 0 && !isParallelProcessing) {
055            throw new IllegalArgumentException("Timeout is used but ParallelProcessing has not been enabled.");
056        }
057        if (definition.getOnPrepareRef() != null) {
058            definition.setOnPrepare(CamelContextHelper.mandatoryLookup(routeContext.getCamelContext(), definition.getOnPrepareRef(), Processor.class));
059        }
060
061        Expression exp = definition.getExpression().createExpression(routeContext);
062
063        Splitter answer = new Splitter(routeContext.getCamelContext(), exp, childProcessor, definition.getAggregationStrategy(), isParallelProcessing, threadPool,
064                                       shutdownThreadPool, isStreaming, definition.isStopOnException(), timeout, definition.getOnPrepare(), isShareUnitOfWork, isParallelAggregate,
065                                       isStopOnAggregateException);
066        return answer;
067    }
068
069    private AggregationStrategy createAggregationStrategy(RouteContext routeContext) {
070        AggregationStrategy strategy = definition.getAggregationStrategy();
071        if (strategy == null && definition.getStrategyRef() != null) {
072            Object aggStrategy = routeContext.lookup(definition.getStrategyRef(), Object.class);
073            if (aggStrategy instanceof AggregationStrategy) {
074                strategy = (AggregationStrategy)aggStrategy;
075            } else if (aggStrategy != null) {
076                AggregationStrategyBeanAdapter adapter = new AggregationStrategyBeanAdapter(aggStrategy, definition.getStrategyMethodName());
077                if (definition.getStrategyMethodAllowNull() != null) {
078                    adapter.setAllowNullNewExchange(definition.getStrategyMethodAllowNull());
079                    adapter.setAllowNullOldExchange(definition.getStrategyMethodAllowNull());
080                }
081                strategy = adapter;
082            } else {
083                throw new IllegalArgumentException("Cannot find AggregationStrategy in Registry with name: " + definition.getStrategyRef());
084            }
085        }
086
087        if (strategy instanceof CamelContextAware) {
088            ((CamelContextAware)strategy).setCamelContext(routeContext.getCamelContext());
089        }
090
091        if (strategy != null && definition.getShareUnitOfWork() != null && definition.getShareUnitOfWork()) {
092            // wrap strategy in share unit of work
093            strategy = new ShareUnitOfWorkAggregationStrategy(strategy);
094        }
095
096        return strategy;
097    }
098
099}