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     */
017    package org.apache.camel.model;
018    
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.List;
022    
023    import javax.xml.bind.annotation.XmlElement;
024    import javax.xml.bind.annotation.XmlElementRef;
025    import javax.xml.bind.annotation.XmlRootElement;
026    import javax.xml.bind.annotation.XmlTransient;
027    
028    import org.apache.camel.Exchange;
029    import org.apache.camel.Expression;
030    import org.apache.camel.Processor;
031    import org.apache.camel.Route;
032    import org.apache.camel.impl.RouteContext;
033    import org.apache.camel.model.config.BatchResequencerConfig;
034    import org.apache.camel.model.config.StreamResequencerConfig;
035    import org.apache.camel.model.language.ExpressionType;
036    import org.apache.camel.processor.Resequencer;
037    import org.apache.camel.processor.StreamResequencer;
038    
039    /**
040     * @version $Revision: 36321 $
041     */
042    @XmlRootElement(name = "resequencer")
043    public class ResequencerType extends ProcessorType<ProcessorType> {
044        @XmlElementRef
045        private List<ExpressionType> expressions = new ArrayList<ExpressionType>();
046        @XmlElementRef
047        private List<ProcessorType<?>> outputs = new ArrayList<ProcessorType<?>>();
048        // Binding annotation at setter
049        private BatchResequencerConfig batchConfig;
050        // Binding annotation at setter
051        private StreamResequencerConfig streamConfig;
052        @XmlTransient
053        private List<Expression> expressionList;
054    
055        public ResequencerType() {
056            this(null);
057        }
058    
059        public ResequencerType(List<Expression> expressions) {
060            this.expressionList = expressions;
061            this.batch();
062        }
063    
064        /**
065         * Configures the stream-based resequencing algorithm using the default
066         * configuration.
067         *
068         * @return <code>this</code> instance.
069         */
070        public ResequencerType stream() {
071            return stream(StreamResequencerConfig.getDefault());
072        }
073    
074        /**
075         * Configures the batch-based resequencing algorithm using the default
076         * configuration.
077         *
078         * @return <code>this</code> instance.
079         */
080        public ResequencerType batch() {
081            return batch(BatchResequencerConfig.getDefault());
082        }
083    
084        /**
085         * Configures the stream-based resequencing algorithm using the given
086         * {@link StreamResequencerConfig}.
087         *
088         * @return <code>this</code> instance.
089         */
090        public ResequencerType stream(StreamResequencerConfig config) {
091            this.streamConfig = config;
092            this.batchConfig = null;
093            return this;
094        }
095    
096        /**
097         * Configures the batch-based resequencing algorithm using the given
098         * {@link BatchResequencerConfig}.
099         *
100         * @return <code>this</code> instance.
101         */
102        public ResequencerType batch(BatchResequencerConfig config) {
103            this.batchConfig = config;
104            this.streamConfig = null;
105            return this;
106        }
107    
108        public ResequencerType expression(ExpressionType expression) {
109            expressions.add(expression);
110            return this;
111        }
112    
113    
114        @Override
115        public String toString() {
116            return "Resequencer[ " + getExpressions() + " -> " + getOutputs() + "]";
117        }
118    
119        @Override
120        public String getLabel() {
121            return ExpressionType.getLabel(getExpressions());
122        }
123    
124        public List<ExpressionType> getExpressions() {
125            return expressions;
126        }
127    
128        public List<ProcessorType<?>> getOutputs() {
129            return outputs;
130        }
131    
132        public void setOutputs(List<ProcessorType<?>> outputs) {
133            this.outputs = outputs;
134        }
135    
136        public BatchResequencerConfig getBatchConfig() {
137            return batchConfig;
138        }
139    
140        public BatchResequencerConfig getBatchConfig(BatchResequencerConfig defaultConfig) {
141            return batchConfig;
142        }
143    
144        public StreamResequencerConfig getStreamConfig() {
145            return streamConfig;
146        }
147    
148        //
149        // TODO: find out how to have these two within an <xsd:choice>
150        //
151    
152        @XmlElement(name = "batch-config", required = false)
153        public void setBatchConfig(BatchResequencerConfig batchConfig) {
154            batch(batchConfig);
155        }
156    
157        @XmlElement(name = "stream-config", required = false)
158        public void setStreamConfig(StreamResequencerConfig streamConfig) {
159            stream(streamConfig);
160        }
161    
162        //
163        // END_TODO
164        //
165    
166        @Override
167        public Processor createProcessor(RouteContext routeContext) throws Exception {
168            return createStreamResequencer(routeContext, streamConfig);
169        }
170    
171        @Override
172        public void addRoutes(RouteContext routeContext, Collection<Route> routes) throws Exception {
173            if (batchConfig != null) {
174                routes.add(createBatchResequencerRoute(routeContext));
175            } else {
176                // StreamResequencer created via createProcessor method
177                super.addRoutes(routeContext, routes);
178            }
179        }
180    
181        private Route<? extends Exchange> createBatchResequencerRoute(RouteContext routeContext) throws Exception {
182            final Resequencer resequencer = createBatchResequencer(routeContext, batchConfig);
183            return new Route(routeContext.getEndpoint(), resequencer) {
184                @Override
185                public String toString() {
186                    return "BatchResequencerRoute[" + getEndpoint() + " -> " + resequencer.getProcessor() + "]";
187                }
188            };
189        }
190    
191        protected Resequencer createBatchResequencer(RouteContext routeContext,
192                BatchResequencerConfig config) throws Exception {
193            Processor processor = routeContext.createProcessor(this);
194            Resequencer resequencer = new Resequencer(routeContext.getEndpoint(),
195                    processor, resolveExpressionList(routeContext));
196            resequencer.setBatchSize(config.getBatchSize());
197            resequencer.setBatchTimeout(config.getBatchTimeout());
198            return resequencer;
199        }
200    
201        protected StreamResequencer createStreamResequencer(RouteContext routeContext,
202                StreamResequencerConfig config) throws Exception {
203            config.getComparator().setExpressions(resolveExpressionList(routeContext));
204            Processor processor = routeContext.createProcessor(this);
205            StreamResequencer resequencer = new StreamResequencer(processor,
206                    config.getComparator(), config.getCapacity());
207            resequencer.setTimeout(config.getTimeout());
208            return resequencer;
209    
210        }
211    
212        private List<Expression> resolveExpressionList(RouteContext routeContext) {
213            if (expressionList == null) {
214                expressionList = new ArrayList<Expression>();
215                for (ExpressionType expression : expressions) {
216                    expressionList.add(expression.createExpression(routeContext));
217                }
218            }
219            if (expressionList.isEmpty()) {
220                throw new IllegalArgumentException("No expressions configured for: " + this);
221            }
222            return expressionList;
223        }
224    }