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.model;
018
019import java.util.concurrent.ExecutorService;
020import java.util.concurrent.ScheduledExecutorService;
021
022import javax.xml.bind.annotation.XmlAccessType;
023import javax.xml.bind.annotation.XmlAccessorType;
024import javax.xml.bind.annotation.XmlAttribute;
025import javax.xml.bind.annotation.XmlRootElement;
026import javax.xml.bind.annotation.XmlTransient;
027
028import org.apache.camel.Expression;
029import org.apache.camel.Processor;
030import org.apache.camel.builder.ExpressionBuilder;
031import org.apache.camel.model.language.ExpressionDefinition;
032import org.apache.camel.processor.Delayer;
033import org.apache.camel.spi.Metadata;
034import org.apache.camel.spi.RouteContext;
035
036/**
037 * Delays processing for a specified length of time
038 *
039 * @version 
040 */
041@Metadata(label = "eip,routing")
042@XmlRootElement(name = "delay")
043@XmlAccessorType(XmlAccessType.FIELD)
044public class DelayDefinition extends ExpressionNode implements ExecutorServiceAwareDefinition<DelayDefinition> {
045
046    // TODO: Camel 3.0 Should extend NoOutputExpressionNode
047
048    @XmlTransient
049    private ExecutorService executorService;
050    @XmlAttribute
051    private String executorServiceRef;
052    @XmlAttribute @Metadata(defaultValue = "false")
053    private Boolean asyncDelayed;
054    @XmlAttribute @Metadata(defaultValue = "true")
055    private Boolean callerRunsWhenRejected;
056
057    public DelayDefinition() {
058    }
059
060    public DelayDefinition(Expression delay) {
061        super(delay);
062    }
063
064    @Override
065    public String getShortName() {
066        return "delay";
067    }
068
069    @Override
070    public String getLabel() {
071        return "delay[" + getExpression() + "]";
072    }
073
074    @Override
075    public String toString() {
076        return "Delay[" + getExpression() + " -> " + getOutputs() + "]";
077    }
078
079    @Override
080    public Processor createProcessor(RouteContext routeContext) throws Exception {
081        Processor childProcessor = this.createChildProcessor(routeContext, false);
082        Expression delay = createAbsoluteTimeDelayExpression(routeContext);
083
084        boolean async = getAsyncDelayed() != null && getAsyncDelayed();
085        boolean shutdownThreadPool = ProcessorDefinitionHelper.willCreateNewThreadPool(routeContext, this, async);
086        ScheduledExecutorService threadPool = ProcessorDefinitionHelper.getConfiguredScheduledExecutorService(routeContext, "Delay", this, async);
087
088        Delayer answer = new Delayer(routeContext.getCamelContext(), childProcessor, delay, threadPool, shutdownThreadPool);
089        if (getAsyncDelayed() != null) {
090            answer.setAsyncDelayed(getAsyncDelayed());
091        }
092        if (getCallerRunsWhenRejected() == null) {
093            // should be default true
094            answer.setCallerRunsWhenRejected(true);
095        } else {
096            answer.setCallerRunsWhenRejected(getCallerRunsWhenRejected());
097        }
098        return answer;
099    }
100
101    private Expression createAbsoluteTimeDelayExpression(RouteContext routeContext) {
102        ExpressionDefinition expr = getExpression();
103        if (expr != null) {
104            return expr.createExpression(routeContext);
105        }
106        return null;
107    }
108
109    // Fluent API
110    // -------------------------------------------------------------------------
111
112    /**
113     * Sets the delay time in millis to delay
114     *
115     * @param delay delay time in millis
116     * @return the builder
117     */
118    public DelayDefinition delayTime(Long delay) {
119        setExpression(ExpressionNodeHelper.toExpressionDefinition(ExpressionBuilder.constantExpression(delay)));
120        return this;
121    }
122
123    /**
124     * Whether or not the caller should run the task when it was rejected by the thread pool.
125     * <p/>
126     * Is by default <tt>true</tt>
127     *
128     * @param callerRunsWhenRejected whether or not the caller should run
129     * @return the builder
130     */
131    public DelayDefinition callerRunsWhenRejected(boolean callerRunsWhenRejected) {
132        setCallerRunsWhenRejected(callerRunsWhenRejected);
133        return this;
134    }
135
136    /**
137     * Enables asynchronous delay which means the thread will <b>noy</b> block while delaying.
138     */
139    public DelayDefinition asyncDelayed() {
140        setAsyncDelayed(true);
141        return this;
142    }
143
144    /**
145     * To use a custom Thread Pool if asyncDelay has been enabled.
146     */
147    public DelayDefinition executorService(ExecutorService executorService) {
148        setExecutorService(executorService);
149        return this;
150    }
151
152    /**
153     * Refers to a custom Thread Pool if asyncDelay has been enabled.
154     */
155    public DelayDefinition executorServiceRef(String executorServiceRef) {
156        setExecutorServiceRef(executorServiceRef);
157        return this;
158    }
159
160    // Properties
161    // -------------------------------------------------------------------------
162
163    /**
164     * Expression to define how long time to wait (in millis)
165     */
166    @Override
167    public void setExpression(ExpressionDefinition expression) {
168        // override to include javadoc what the expression is used for
169        super.setExpression(expression);
170    }
171
172    public Boolean getAsyncDelayed() {
173        return asyncDelayed;
174    }
175
176    public void setAsyncDelayed(Boolean asyncDelayed) {
177        this.asyncDelayed = asyncDelayed;
178    }
179
180    public Boolean getCallerRunsWhenRejected() {
181        return callerRunsWhenRejected;
182    }
183
184    public void setCallerRunsWhenRejected(Boolean callerRunsWhenRejected) {
185        this.callerRunsWhenRejected = callerRunsWhenRejected;
186    }
187
188    public ExecutorService getExecutorService() {
189        return executorService;
190    }
191
192    public void setExecutorService(ExecutorService executorService) {
193        this.executorService = executorService;
194    }
195
196    public String getExecutorServiceRef() {
197        return executorServiceRef;
198    }
199
200    public void setExecutorServiceRef(String executorServiceRef) {
201        this.executorServiceRef = executorServiceRef;
202    }
203}