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.util;
018    
019    
020    
021    import java.lang.reflect.Method;
022    import java.util.ArrayList;
023    import java.util.Collections;
024    import java.util.Comparator;
025    import java.util.List;
026    
027    import org.apache.camel.TypeConverter;
028    import org.apache.camel.impl.converter.AnnotationTypeConverterLoader;
029    import org.apache.camel.impl.converter.TypeConverterRegistry;
030    import static org.apache.camel.util.ObjectHelper.equal;
031    
032    public class ReportingTypeConverterLoader extends AnnotationTypeConverterLoader {
033    
034        private static final Comparator<TypeMapping> COMPARE_LAST_LOADED_FIRST = new Comparator<TypeMapping>() {
035            public int compare(TypeMapping t1, TypeMapping t2) {
036                if (equal(t1.fromType, t2.fromType)) {
037                    return equal(t1.toType, t2.toType) ? t1.index - t2.index : ObjectHelper
038                        .compare(getTypeName(t1.toType), getTypeName(t2.toType));
039                }
040                return ObjectHelper.compare(getTypeName(t1.fromType), getTypeName(t2.fromType));
041            }
042    
043        };
044        private List<TypeMapping> typeMappings = new ArrayList<TypeMapping>();
045    
046        public TypeMapping[] getTypeConversions() {
047            Collections.sort(typeMappings, COMPARE_LAST_LOADED_FIRST);
048            return typeMappings.toArray(new TypeMapping[typeMappings.size()]);
049        }
050    
051        protected void registerTypeConverter(TypeConverterRegistry registry, Method method, Class toType,
052                                             Class fromType, TypeConverter typeConverter) {
053    
054            TypeMapping mapping = new TypeMapping(toType, fromType, typeConverter.getClass(), method);
055            typeMappings.add(mapping);
056        }
057    
058        private static String getTypeName(Class type) {
059            return type != null ? type.getName() : null;
060        }
061    
062        /**
063         * Represents a mapping from one type (which can be null) to another
064         */
065        public static class TypeMapping {
066            private static int counter;
067            Class toType;
068            Class fromType;
069            Class converterType;
070            Method method;
071            int index;
072    
073            public TypeMapping(Class toType, Class fromType, Class converterType, Method method) {
074                this.toType = toType;
075                this.fromType = fromType;
076                this.converterType = converterType;
077                this.method = method;
078                this.index = counter++;
079            }
080    
081            public Class getFromType() {
082                return fromType;
083            }
084    
085            public Class getToType() {
086                return toType;
087            }
088    
089            public Class getConverterType() {
090                return converterType;
091            }
092    
093            public Method getMethod() {
094                return method;
095            }
096    
097            public int getIndex() {
098                return index;
099            }
100    
101            @Override
102            public boolean equals(Object object) {
103                if (object instanceof TypeMapping) {
104                    TypeMapping that = (TypeMapping)object;
105                    return this.index == that.index;
106                }
107                return false;
108            }
109    
110            @Override
111            public int hashCode() {
112                int answer = toType.hashCode();
113                if (fromType != null) {
114                    answer *= 37 + fromType.hashCode();
115                }
116                return answer;
117            }
118    
119            @Override
120            public String toString() {
121                return "[" + fromType.getSimpleName() + "=>" + toType.getSimpleName() + "]";
122            }
123        }
124    }