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