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