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.Comparator;
020
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.model.language.ExpressionDefinition;
030import org.apache.camel.processor.SortProcessor;
031import org.apache.camel.spi.Metadata;
032import org.apache.camel.spi.RouteContext;
033import org.apache.camel.util.ObjectHelper;
034
035import static org.apache.camel.builder.ExpressionBuilder.bodyExpression;
036
037/**
038 * Sorts the contents of the message
039 */
040@Metadata(label = "eip,routing")
041@XmlRootElement(name = "sort")
042@XmlAccessorType(XmlAccessType.FIELD)
043public class SortDefinition<T> extends NoOutputExpressionNode {
044    @XmlTransient
045    private Comparator<? super T> comparator;
046    @XmlAttribute
047    private String comparatorRef;
048
049    public SortDefinition() {
050    }
051
052    public SortDefinition(Expression expression) {
053        setExpression(ExpressionNodeHelper.toExpressionDefinition(expression));
054    }
055
056    public SortDefinition(Expression expression, Comparator<? super T> comparator) {
057        this(expression);
058        this.comparator = comparator;
059    }
060
061    @Override
062    public String toString() {
063        return "sort[" + getExpression() + " by: " + (comparatorRef != null ? "ref:" + comparatorRef : comparator) + "]";
064    }
065    
066    @Override
067    public String getShortName() {
068        return "sort";
069    }
070
071    @Override
072    public String getLabel() {
073        return "sort[" + getExpression() + "]";
074    }
075
076    @Override
077    @SuppressWarnings("unchecked")
078    public Processor createProcessor(RouteContext routeContext) throws Exception {
079        // lookup in registry
080        if (ObjectHelper.isNotEmpty(comparatorRef)) {
081            comparator = routeContext.getCamelContext().getRegistry().lookupByNameAndType(comparatorRef, Comparator.class);
082        }
083
084        // if no comparator then default on to string representation
085        if (comparator == null) {
086            comparator = new Comparator<T>() {
087                public int compare(T o1, T o2) {
088                    return ObjectHelper.compare(o1, o2);
089                }
090            };
091        }
092
093        // if no expression provided then default to body expression
094        Expression exp;
095        if (getExpression() == null) {
096            exp = bodyExpression();
097        } else {
098            exp = getExpression().createExpression(routeContext);
099        }
100        return new SortProcessor<T>(exp, getComparator());
101    }
102
103    /**
104     * Optional expression to sort by something else than the message body
105     */
106    @Override
107    public void setExpression(ExpressionDefinition expression) {
108        // override to include javadoc what the expression is used for
109        super.setExpression(expression);
110    }
111
112    public Comparator<? super T> getComparator() {
113        return comparator;
114    }
115
116    public void setComparator(Comparator<T> comparator) {
117        this.comparator = comparator;
118    }
119
120    public String getComparatorRef() {
121        return comparatorRef;
122    }
123
124    public void setComparatorRef(String comparatorRef) {
125        this.comparatorRef = comparatorRef;
126    }
127
128    /**
129     * Sets the comparator to use for sorting
130     *
131     * @param comparator  the comparator to use for sorting
132     * @return the builder
133     */
134    public SortDefinition<T> comparator(Comparator<T> comparator) {
135        setComparator(comparator);
136        return this;
137    }
138
139    /**
140     * Sets a reference to lookup for the comparator to use for sorting
141     *
142     * @param ref reference for the comparator
143     * @return the builder
144     */
145    public SortDefinition<T> comparatorRef(String ref) {
146        setComparatorRef(ref);
147        return this;
148    }
149}