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: 788766 $
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 Processor createProcessor(RouteContext routeContext) throws Exception {
074 Processor childProcessor = createOutputsProcessor(routeContext);
075
076 // wrap the on completion route in a unit of work processor
077 childProcessor = new UnitOfWorkProcessor(childProcessor);
078
079 Predicate when = null;
080 if (onWhen != null) {
081 when = onWhen.getExpression().createPredicate(routeContext);
082 }
083
084 if (onCompleteOnly && onFailureOnly) {
085 throw new IllegalArgumentException("Both onCompleteOnly and onFailureOnly cannot be true. Only one of them can be true. On node: " + this);
086 }
087
088 return new OnCompletionProcessor(childProcessor, onCompleteOnly, onFailureOnly, when);
089 }
090
091 /**
092 * Removes all existing {@link org.apache.camel.model.OnCompletionDefinition} from the defintion.
093 * <p/>
094 * This is used to let route scoped <tt>onCompletion</tt> overrule any global <tt>onCompletion</tt>.
095 * Hence we remove all existing as they are global.
096 *
097 * @param definition the parent defintion that is the route
098 */
099 @SuppressWarnings("unchecked")
100 public void removeAllOnCompletionDefinition(ProcessorDefinition definition) {
101 for (Iterator<ProcessorDefinition> it = definition.getOutputs().iterator(); it.hasNext();) {
102 ProcessorDefinition out = it.next();
103 if (out instanceof OnCompletionDefinition) {
104 it.remove();
105 }
106 }
107 }
108
109 @Override
110 public ProcessorDefinition<? extends ProcessorDefinition> end() {
111 // pop parent block, as we added outself as block to parent when synchronized was defined in the route
112 getParent().popBlock();
113 return super.end();
114 }
115
116 /**
117 * Will only synchronize when the {@link org.apache.camel.Exchange} completed succesfully (no errors).
118 *
119 * @return the builder
120 */
121 public OnCompletionDefinition onCompleteOnly() {
122 // must define return type as OutputDefinition and not this type to avoid end user being able
123 // to invoke onFailureOnly/onCompleteOnly more than once
124 setOnCompleteOnly(Boolean.TRUE);
125 setOnFailureOnly(Boolean.FALSE);
126 return this;
127 }
128
129 /**
130 * Will only synchronize when the {@link org.apache.camel.Exchange} ended with failure (exception or FAULT message).
131 *
132 * @return the builder
133 */
134 public OnCompletionDefinition onFailureOnly() {
135 // must define return type as OutputDefinition and not this type to avoid end user being able
136 // to invoke onFailureOnly/onCompleteOnly more than once
137 setOnCompleteOnly(Boolean.FALSE);
138 setOnFailureOnly(Boolean.TRUE);
139 return this;
140 }
141
142 /**
143 * Sets an additional predicate that should be true before the onCompletion is triggered.
144 * <p/>
145 * To be used for fine grained controlling whether a completion callback should be invoked or not
146 *
147 * @param predicate predicate that determines true or false
148 * @return the builder
149 */
150 public OnCompletionDefinition onWhen(Predicate predicate) {
151 setOnWhen(new WhenDefinition(predicate));
152 return this;
153 }
154
155 /**
156 * Creates an expression to configure an additional predicate that should be true before the
157 * onCompletion is triggered.
158 * <p/>
159 * To be used for fine grained controlling whether a completion callback should be invoked or not
160 *
161 * @return the expression clause to configure
162 */
163 public ExpressionClause<OnCompletionDefinition> onWhen() {
164 onWhen = new WhenDefinition();
165 ExpressionClause<OnCompletionDefinition> clause = new ExpressionClause<OnCompletionDefinition>(this);
166 onWhen.setExpression(clause);
167 return clause;
168 }
169
170
171 public List<ProcessorDefinition> getOutputs() {
172 return outputs;
173 }
174
175 public void setOutputs(List<ProcessorDefinition> outputs) {
176 this.outputs = outputs;
177 }
178
179 public Boolean getOnCompleteOnly() {
180 return onCompleteOnly;
181 }
182
183 public void setOnCompleteOnly(Boolean onCompleteOnly) {
184 this.onCompleteOnly = onCompleteOnly;
185 }
186
187 public Boolean getOnFailureOnly() {
188 return onFailureOnly;
189 }
190
191 public void setOnFailureOnly(Boolean onFailureOnly) {
192 this.onFailureOnly = onFailureOnly;
193 }
194
195 public WhenDefinition getOnWhen() {
196 return onWhen;
197 }
198
199 public void setOnWhen(WhenDefinition onWhen) {
200 this.onWhen = onWhen;
201 }
202
203 }