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