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