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 org.apache.camel.Expression;
020import org.apache.camel.Processor;
021import org.apache.camel.model.ProcessorDefinition;
022import org.apache.camel.model.ResequenceDefinition;
023import org.apache.camel.model.config.BatchResequencerConfig;
024import org.apache.camel.model.config.StreamResequencerConfig;
025import org.apache.camel.processor.CamelInternalProcessor;
026import org.apache.camel.processor.Resequencer;
027import org.apache.camel.processor.StreamResequencer;
028import org.apache.camel.processor.resequencer.DefaultExchangeComparator;
029import org.apache.camel.processor.resequencer.ExpressionResultComparator;
030import org.apache.camel.spi.RouteContext;
031import org.apache.camel.support.CamelContextHelper;
032import org.apache.camel.util.ObjectHelper;
033
034public class ResequenceReifier extends ProcessorReifier<ResequenceDefinition> {
035
036    public ResequenceReifier(ProcessorDefinition<?> definition) {
037        super((ResequenceDefinition)definition);
038    }
039
040    @Override
041    public Processor createProcessor(RouteContext routeContext) throws Exception {
042        // if configured from XML then streamConfig has been set with the
043        // configuration
044        if (definition.getResequencerConfig() != null) {
045            if (definition.getResequencerConfig() instanceof StreamResequencerConfig) {
046                definition.setStreamConfig((StreamResequencerConfig)definition.getResequencerConfig());
047            } else {
048                definition.setBatchConfig((BatchResequencerConfig)definition.getResequencerConfig());
049            }
050        }
051
052        if (definition.getStreamConfig() != null) {
053            return createStreamResequencer(routeContext, definition.getStreamConfig());
054        } else {
055            if (definition.getBatchConfig() == null) {
056                // default as batch mode
057                definition.batch();
058            }
059            return createBatchResequencer(routeContext, definition.getBatchConfig());
060        }
061    }
062
063    /**
064     * Creates a batch {@link Resequencer} instance applying the given
065     * <code>config</code>.
066     *
067     * @param routeContext route context.
068     * @param config batch resequencer configuration.
069     * @return the configured batch resequencer.
070     * @throws Exception can be thrown
071     */
072    @SuppressWarnings("deprecation")
073    protected Resequencer createBatchResequencer(RouteContext routeContext, BatchResequencerConfig config) throws Exception {
074        Processor processor = this.createChildProcessor(routeContext, true);
075        Expression expression = definition.getExpression().createExpression(routeContext);
076
077        // and wrap in unit of work
078        CamelInternalProcessor internal = new CamelInternalProcessor(processor);
079        internal.addAdvice(new CamelInternalProcessor.UnitOfWorkProcessorAdvice(routeContext));
080
081        ObjectHelper.notNull(config, "config", this);
082        ObjectHelper.notNull(expression, "expression", this);
083
084        boolean isReverse = config.getReverse() != null && config.getReverse();
085        boolean isAllowDuplicates = config.getAllowDuplicates() != null && config.getAllowDuplicates();
086
087        Resequencer resequencer = new Resequencer(routeContext.getCamelContext(), internal, expression, isAllowDuplicates, isReverse);
088        resequencer.setBatchSize(config.getBatchSize());
089        resequencer.setBatchTimeout(config.getBatchTimeout());
090        resequencer.setReverse(isReverse);
091        resequencer.setAllowDuplicates(isAllowDuplicates);
092        if (config.getIgnoreInvalidExchanges() != null) {
093            resequencer.setIgnoreInvalidExchanges(config.getIgnoreInvalidExchanges());
094        }
095        return resequencer;
096    }
097
098    /**
099     * Creates a {@link StreamResequencer} instance applying the given
100     * <code>config</code>.
101     *
102     * @param routeContext route context.
103     * @param config stream resequencer configuration.
104     * @return the configured stream resequencer.
105     * @throws Exception can be thrwon
106     */
107    protected StreamResequencer createStreamResequencer(RouteContext routeContext, StreamResequencerConfig config) throws Exception {
108        Processor processor = this.createChildProcessor(routeContext, true);
109        Expression expression = definition.getExpression().createExpression(routeContext);
110
111        CamelInternalProcessor internal = new CamelInternalProcessor(processor);
112        internal.addAdvice(new CamelInternalProcessor.UnitOfWorkProcessorAdvice(routeContext));
113
114        ObjectHelper.notNull(config, "config", this);
115        ObjectHelper.notNull(expression, "expression", this);
116
117        ExpressionResultComparator comparator;
118        if (config.getComparatorRef() != null) {
119            comparator = CamelContextHelper.mandatoryLookup(routeContext.getCamelContext(), config.getComparatorRef(), ExpressionResultComparator.class);
120        } else {
121            comparator = config.getComparator();
122            if (comparator == null) {
123                comparator = new DefaultExchangeComparator();
124            }
125        }
126        comparator.setExpression(expression);
127
128        StreamResequencer resequencer = new StreamResequencer(routeContext.getCamelContext(), internal, comparator, expression);
129        resequencer.setTimeout(config.getTimeout());
130        if (config.getDeliveryAttemptInterval() != null) {
131            resequencer.setDeliveryAttemptInterval(config.getDeliveryAttemptInterval());
132        }
133        resequencer.setCapacity(config.getCapacity());
134        resequencer.setRejectOld(config.getRejectOld());
135        if (config.getIgnoreInvalidExchanges() != null) {
136            resequencer.setIgnoreInvalidExchanges(config.getIgnoreInvalidExchanges());
137        }
138        return resequencer;
139    }
140
141}