001/**
002 *   GRANITE DATA SERVICES
003 *   Copyright (C) 2006-2014 GRANITE DATA SERVICES S.A.S.
004 *
005 *   This file is part of the Granite Data Services Platform.
006 *
007 *   Granite Data Services is free software; you can redistribute it and/or
008 *   modify it under the terms of the GNU Lesser General Public
009 *   License as published by the Free Software Foundation; either
010 *   version 2.1 of the License, or (at your option) any later version.
011 *
012 *   Granite Data Services is distributed in the hope that it will be useful,
013 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
014 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
015 *   General Public License for more details.
016 *
017 *   You should have received a copy of the GNU Lesser General Public
018 *   License along with this library; if not, write to the Free Software
019 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
020 *   USA, or see <http://www.gnu.org/licenses/>.
021 */
022package org.granite.generator.util;
023
024import java.lang.reflect.ParameterizedType;
025import java.lang.reflect.Type;
026import java.lang.reflect.TypeVariable;
027import java.util.ArrayList;
028import java.util.List;
029
030import org.granite.util.ClassUtil;
031
032/**
033 * @author Franck WOLFF
034 */
035public abstract class GenericTypeUtil {
036    
037    public static ParameterizedType[] getDeclaringTypes(Class<?> type) {
038                List<ParameterizedType> supertypes = new ArrayList<ParameterizedType>();
039                
040                Type stype = type.getGenericSuperclass();
041                Class<?> sclass = type.getSuperclass();
042                while (sclass != null && sclass != Object.class) {
043                        if (stype instanceof ParameterizedType)
044                                supertypes.add((ParameterizedType)stype);
045                        stype = sclass.getGenericSuperclass();
046                        sclass = sclass.getSuperclass();
047                }
048                
049                collectGenericInterfaces(type.getGenericInterfaces(), supertypes);
050                
051                return supertypes.isEmpty() ? null : supertypes.toArray(new ParameterizedType[supertypes.size()]);
052    }
053    
054    private static void collectGenericInterfaces(Type[] types, List<ParameterizedType> supertypes) {
055        if (types == null)
056                return;
057                for (Type t : types) {
058                        if (t instanceof ParameterizedType)
059                                supertypes.add((ParameterizedType)t);
060                        else
061                                collectGenericInterfaces(((Class<?>)t).getGenericInterfaces(), supertypes);
062                }
063    }
064
065    public static Type primitiveToWrapperType(Type type) {
066                if (type.equals(short.class))
067                        return Short.class;
068                else if (type.equals(byte.class))
069                        return Byte.class;
070                else if (type.equals(boolean.class))
071                        return Boolean.class;
072                else if (type == int.class)
073                        return Integer.class;
074                else if (type == long.class)
075                        return Long.class;
076                else if (type == float.class)
077                        return Float.class;
078                else if (type == double.class)
079                        return Double.class;
080                return type;
081    }
082    
083    public static Type resolveTypeVariable(Type genericType, Class<?> declaringClass, ParameterizedType[] declaringTypes) {
084        if (genericType instanceof TypeVariable && declaringTypes != null) {
085                int index = -1;
086                TypeVariable<?> typeVariable = (TypeVariable<?>)genericType;
087                ParameterizedType declaringType = null;
088                for (int j = 0; j < declaringClass.getTypeParameters().length; j++) {
089                        Type typeParameter = declaringClass.getTypeParameters()[j];
090                        if (typeParameter == typeVariable)
091                                index = j;
092                        else if (typeVariable.getBounds() != null) {
093                                for (Type t : typeVariable.getBounds()) {
094                                        if (typeParameter == t) {
095                                                index = j;
096                                                break;
097                                        }
098                                }
099                        }
100                        if (index >= 0) {
101                                        for (ParameterizedType t : declaringTypes) {
102                                                if (declaringClass.isAssignableFrom(ClassUtil.classOfType(t))) {
103                                                        declaringType = t;
104                                                        break;
105                                                }
106                                        }
107                                        break;
108                        }
109                }
110                if (declaringType != null && index >= 0 && index < declaringType.getActualTypeArguments().length)
111                        return declaringType.getActualTypeArguments()[index];
112        }
113        return genericType;
114    }
115}