001/**
002 *   GRANITE DATA SERVICES
003 *   Copyright (C) 2006-2013 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 */
022
023package org.granite.generator.util;
024
025import java.lang.reflect.ParameterizedType;
026import java.lang.reflect.Type;
027import java.lang.reflect.TypeVariable;
028import java.util.ArrayList;
029import java.util.List;
030
031import org.granite.util.ClassUtil;
032
033/**
034 * @author Franck WOLFF
035 */
036public abstract class GenericTypeUtil {
037    
038    public static ParameterizedType[] getDeclaringTypes(Class<?> type) {
039                List<ParameterizedType> supertypes = new ArrayList<ParameterizedType>();
040                
041                Type stype = type.getGenericSuperclass();
042                Class<?> sclass = type.getSuperclass();
043                while (sclass != null && sclass != Object.class) {
044                        if (stype instanceof ParameterizedType)
045                                supertypes.add((ParameterizedType)stype);
046                        stype = sclass.getGenericSuperclass();
047                        sclass = sclass.getSuperclass();
048                }
049                
050                collectGenericInterfaces(type.getGenericInterfaces(), supertypes);
051                
052                return supertypes.isEmpty() ? null : supertypes.toArray(new ParameterizedType[supertypes.size()]);
053    }
054    
055    private static void collectGenericInterfaces(Type[] types, List<ParameterizedType> supertypes) {
056        if (types == null)
057                return;
058                for (Type t : types) {
059                        if (t instanceof ParameterizedType)
060                                supertypes.add((ParameterizedType)t);
061                        else
062                                collectGenericInterfaces(((Class<?>)t).getGenericInterfaces(), supertypes);
063                }
064    }
065
066    public static Type primitiveToWrapperType(Type type) {
067                if (type.equals(short.class))
068                        return Short.class;
069                else if (type.equals(byte.class))
070                        return Byte.class;
071                else if (type.equals(boolean.class))
072                        return Boolean.class;
073                else if (type == int.class)
074                        return Integer.class;
075                else if (type == long.class)
076                        return Long.class;
077                else if (type == float.class)
078                        return Float.class;
079                else if (type == double.class)
080                        return Double.class;
081                return type;
082    }
083    
084    public static Type resolveTypeVariable(Type genericType, Class<?> declaringClass, ParameterizedType[] declaringTypes) {
085        if (genericType instanceof TypeVariable && declaringTypes != null) {
086                int index = -1;
087                TypeVariable<?> typeVariable = (TypeVariable<?>)genericType;
088                ParameterizedType declaringType = null;
089                for (int j = 0; j < declaringClass.getTypeParameters().length; j++) {
090                        Type typeParameter = declaringClass.getTypeParameters()[j];
091                        if (typeParameter == typeVariable)
092                                index = j;
093                        else if (typeVariable.getBounds() != null) {
094                                for (Type t : typeVariable.getBounds()) {
095                                        if (typeParameter == t) {
096                                                index = j;
097                                                break;
098                                        }
099                                }
100                        }
101                        if (index >= 0) {
102                                        for (ParameterizedType t : declaringTypes) {
103                                                if (declaringClass.isAssignableFrom(ClassUtil.classOfType(t))) {
104                                                        declaringType = t;
105                                                        break;
106                                                }
107                                        }
108                                        break;
109                        }
110                }
111                if (declaringType != null && index >= 0 && index < declaringType.getActualTypeArguments().length)
112                        return declaringType.getActualTypeArguments()[index];
113        }
114        return genericType;
115    }
116}