001 /* 002 * Copyright (C) 2012 eXo Platform SAS. 003 * 004 * This is free software; you can redistribute it and/or modify it 005 * under the terms of the GNU Lesser General Public License as 006 * published by the Free Software Foundation; either version 2.1 of 007 * the License, or (at your option) any later version. 008 * 009 * This software is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * You should have received a copy of the GNU Lesser General Public 015 * License along with this software; if not, write to the Free 016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 018 */ 019 020 package org.crsh.util; 021 022 import java.lang.reflect.ParameterizedType; 023 import java.lang.reflect.Type; 024 import java.lang.reflect.TypeVariable; 025 import java.util.List; 026 027 public class TypeResolver { 028 029 public static Class<?> resolveToClass(Type implementation, Class<?> type, int parameterIndex) { 030 if (implementation == null) { 031 throw new NullPointerException("No null type accepted"); 032 } 033 034 // First resolve to type 035 Type resolvedType = resolve(implementation, type, parameterIndex); 036 037 // 038 if (resolvedType != null) { 039 return resolveToClass(resolvedType); 040 } else { 041 return null; 042 } 043 } 044 045 public static Class resolveToClass(Type type) { 046 if (type == null) { 047 throw new NullPointerException("No null type accepted"); 048 } 049 if (type instanceof Class<?>) { 050 return (Class<?>)type; 051 } else if (type instanceof TypeVariable) { 052 TypeVariable resolvedTypeVariable = (TypeVariable)type; 053 return resolveToClass(resolvedTypeVariable.getBounds()[0]); 054 } else { 055 throw new UnsupportedOperationException("Type resolution of " + type + " not yet implemented"); 056 } 057 } 058 059 /** 060 * A simplistic implementation, it may not handle all cases but it should handle enough. 061 * 062 * @param implementation the type for which the parameter requires a resolution 063 * @param type the type that owns the parameter 064 * @param parameterIndex the parameter index 065 * @return the resolved type 066 */ 067 public static Type resolve(Type implementation, Class<?> type, int parameterIndex) { 068 if (implementation == null) { 069 throw new NullPointerException(); 070 } 071 072 // 073 if (implementation == type) { 074 TypeVariable<? extends Class<?>>[] tp = type.getTypeParameters(); 075 if (parameterIndex < tp.length) { 076 return tp[parameterIndex]; 077 } else { 078 throw new IllegalArgumentException(); 079 } 080 } else if (implementation instanceof Class<?>) { 081 Class<?> c = (Class<?>) implementation; 082 Type gsc = c.getGenericSuperclass(); 083 Type resolved = null; 084 if (gsc != null) { 085 resolved = resolve(gsc, type, parameterIndex); 086 if (resolved == null) { 087 // Try with interface 088 } 089 } 090 return resolved; 091 } else if (implementation instanceof ParameterizedType) { 092 ParameterizedType pt = (ParameterizedType) implementation; 093 Type[] typeArgs = pt.getActualTypeArguments(); 094 Type rawType = pt.getRawType(); 095 if (rawType == type) { 096 return typeArgs[parameterIndex]; 097 } else if (rawType instanceof Class<?>) { 098 Class<?> classRawType = (Class<?>)rawType; 099 Type resolved = resolve(classRawType, type, parameterIndex); 100 if (resolved == null) { 101 return null; 102 } else if (resolved instanceof TypeVariable) { 103 TypeVariable resolvedTV = (TypeVariable)resolved; 104 TypeVariable[] a = classRawType.getTypeParameters(); 105 for (int i = 0;i < a.length;i++) { 106 if (a[i].equals(resolvedTV)) { 107 return resolve(implementation, classRawType, i); 108 } 109 } 110 throw new AssertionError(); 111 } else { 112 throw new UnsupportedOperationException("Cannot support resolution of " + resolved); 113 } 114 } else { 115 throw new UnsupportedOperationException(); 116 } 117 } else { 118 throw new UnsupportedOperationException("todo " + implementation + " " + implementation.getClass()); 119 } 120 } 121 122 public static boolean instanceOf(Class c, List<String> types) { 123 124 for (String type: types) { 125 if (instanceOf(c, type)) { 126 return true; 127 } 128 } 129 130 return false; 131 132 } 133 134 135 public static boolean instanceOf(Class c, String type) { 136 137 if (c.getName().equals(type)) { 138 return true; 139 } 140 141 for (Class i : c.getInterfaces()) { 142 if (instanceOf(i, type)) { 143 return true; 144 } 145 } 146 147 if (c.getSuperclass() != null) { 148 return instanceOf(c.getSuperclass(), type); 149 } 150 151 return false; 152 } 153 154 }