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.Iterator;
021 import java.util.List;
022 import javax.xml.bind.annotation.XmlAccessType;
023 import javax.xml.bind.annotation.XmlAccessorType;
024 import javax.xml.bind.annotation.XmlAttribute;
025 import javax.xml.bind.annotation.XmlElement;
026 import javax.xml.bind.annotation.XmlElementRef;
027 import javax.xml.bind.annotation.XmlRootElement;
028
029 import org.apache.camel.Predicate;
030 import org.apache.camel.Processor;
031 import org.apache.camel.builder.ExpressionClause;
032 import org.apache.camel.processor.OnCompletionProcessor;
033 import org.apache.camel.processor.UnitOfWorkProcessor;
034 import org.apache.camel.spi.RouteContext;
035
036 /**
037 * Represents an XML <onCompletion/> element
038 *
039 * @version $Revision: 896185 $
040 */
041 @XmlRootElement(name = "onCompletion")
042 @XmlAccessorType(XmlAccessType.FIELD)
043 public class OnCompletionDefinition extends ProcessorDefinition<ProcessorDefinition> {
044
045 @XmlAttribute(required = false)
046 private Boolean onCompleteOnly = Boolean.FALSE;
047 @XmlAttribute(required = false)
048 private Boolean onFailureOnly = Boolean.FALSE;
049 @XmlElement(name = "onWhen", required = false)
050 private WhenDefinition onWhen;
051 @XmlElementRef
052 private List<ProcessorDefinition> outputs = new ArrayList<ProcessorDefinition>();
053
054 public OnCompletionDefinition() {
055 }
056
057 @Override
058 public String toString() {
059 return "onCompletion[" + getOutputs() + "]";
060 }
061
062 @Override
063 public String getShortName() {
064 return "onCompletion";
065 }
066
067 @Override
068 public String getLabel() {
069 return "onCompletion";
070 }
071
072 @Override
073 public boolean isAbstract() {
074 return true;
075 }
076
077 @Override
078 public Processor createProcessor(RouteContext routeContext) throws Exception {
079 Processor childProcessor = createOutputsProcessor(routeContext);
080
081 // wrap the on completion route in a unit of work processor
082 childProcessor = new UnitOfWorkProcessor(routeContext, childProcessor);
083
084 Predicate when = null;
085 if (onWhen != null) {
086 when = onWhen.getExpression().createPredicate(routeContext);
087 }
088
089 if (onCompleteOnly && onFailureOnly) {
090 throw new IllegalArgumentException("Both onCompleteOnly and onFailureOnly cannot be true. Only one of them can be true. On node: " + this);
091 }
092
093 return new OnCompletionProcessor(childProcessor, onCompleteOnly, onFailureOnly, when);
094 }
095
096 /**
097 * Removes all existing {@link org.apache.camel.model.OnCompletionDefinition} from the definition.
098 * <p/>
099 * This is used to let route scoped <tt>onCompletion</tt> overrule any global <tt>onCompletion</tt>.
100 * Hence we remove all existing as they are global.
101 *
102 * @param definition the parent definition that is the route
103 */
104 @SuppressWarnings("unchecked")
105 public void removeAllOnCompletionDefinition(ProcessorDefinition definition) {
106 for (Iterator<ProcessorDefinition> it = definition.getOutputs().iterator(); it.hasNext();) {
107 ProcessorDefinition out = it.next();
108 if (out instanceof OnCompletionDefinition) {
109 it.remove();
110 }
111 }
112 }
113
114 @Override
115 public ProcessorDefinition<? extends ProcessorDefinition<?>> end() {
116 // pop parent block, as we added our self as block to parent when synchronized was defined in the route
117 getParent().popBlock();
118 return super.end();
119 }
120
121 /**
122 * Will only synchronize when the {@link org.apache.camel.Exchange} completed successfully (no errors).
123 *
124 * @return the builder
125 */
126 public OnCompletionDefinition onCompleteOnly() {
127 // must define return type as OutputDefinition and not this type to avoid end user being able
128 // to invoke onFailureOnly/onCompleteOnly more than once
129 setOnCompleteOnly(Boolean.TRUE);
130 setOnFailureOnly(Boolean.FALSE);
131 return this;
132 }
133
134 /**
135 * Will only synchronize when the {@link org.apache.camel.Exchange} ended with failure (exception or FAULT message).
136 *
137 * @return the builder
138 */
139 public OnCompletionDefinition onFailureOnly() {
140 // must define return type as OutputDefinition and not this type to avoid end user being able
141 // to invoke onFailureOnly/onCompleteOnly more than once
142 setOnCompleteOnly(Boolean.FALSE);
143 setOnFailureOnly(Boolean.TRUE);
144 return this;
145 }
146
147 /**
148 * Sets an additional predicate that should be true before the onCompletion is triggered.
149 * <p/>
150 * To be used for fine grained controlling whether a completion callback should be invoked or not
151 *
152 * @param predicate predicate that determines true or false
153 * @return the builder
154 */
155 public OnCompletionDefinition onWhen(Predicate predicate) {
156 setOnWhen(new WhenDefinition(predicate));
157 return this;
158 }
159
160 /**
161 * Creates an expression to configure an additional predicate that should be true before the
162 * onCompletion is triggered.
163 * <p/>
164 * To be used for fine grained controlling whether a completion callback should be invoked or not
165 *
166 * @return the expression clause to configure
167 */
168 public ExpressionClause<OnCompletionDefinition> onWhen() {
169 onWhen = new WhenDefinition();
170 ExpressionClause<OnCompletionDefinition> clause = new ExpressionClause<OnCompletionDefinition>(this);
171 onWhen.setExpression(clause);
172 return clause;
173 }
174
175
176 public List<ProcessorDefinition> getOutputs() {
177 return outputs;
178 }
179
180 public void setOutputs(List<ProcessorDefinition> outputs) {
181 this.outputs = outputs;
182 }
183
184 public Boolean getOnCompleteOnly() {
185 return onCompleteOnly;
186 }
187
188 public void setOnCompleteOnly(Boolean onCompleteOnly) {
189 this.onCompleteOnly = onCompleteOnly;
190 }
191
192 public Boolean getOnFailureOnly() {
193 return onFailureOnly;
194 }
195
196 public void setOnFailureOnly(Boolean onFailureOnly) {
197 this.onFailureOnly = onFailureOnly;
198 }
199
200 public WhenDefinition getOnWhen() {
201 return onWhen;
202 }
203
204 public void setOnWhen(WhenDefinition onWhen) {
205 this.onWhen = onWhen;
206 }
207
208 }