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