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