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