001/* Copyright (C) 2013 TU Dortmund 002 * This file is part of AutomataLib, http://www.automatalib.net/. 003 * 004 * AutomataLib is free software; you can redistribute it and/or 005 * modify it under the terms of the GNU Lesser General Public 006 * License version 3.0 as published by the Free Software Foundation. 007 * 008 * AutomataLib is distributed in the hope that it will be useful, 009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 011 * Lesser General Public License for more details. 012 * 013 * You should have received a copy of the GNU Lesser General Public 014 * License along with AutomataLib; if not, see 015 * http://www.gnu.de/documents/lgpl.en.html. 016 */ 017package net.automatalib.commons.util; 018 019import java.lang.reflect.Constructor; 020import java.lang.reflect.Method; 021import java.util.HashMap; 022import java.util.Map; 023 024public abstract class ReflectUtil { 025 026 private static final Class<?>[][] W2P_MAPPING = { 027 { Void.class, void.class }, 028 { Boolean.class, boolean.class }, 029 { Byte.class, byte.class }, 030 { Character.class, char.class }, 031 { Short.class, short.class }, 032 { Integer.class, int.class }, 033 { Long.class, long.class }, 034 { Float.class, float.class }, 035 { Double.class, double.class } 036 }; 037 038 private static final Map<Class<?>,Class<?>> w2pMap; 039 040 041 static { 042 w2pMap = new HashMap<Class<?>,Class<?>>(); 043 044 for(Class<?>[] w2p : W2P_MAPPING) 045 w2pMap.put(w2p[0], w2p[1]); 046 } 047 048 private ReflectUtil() {} 049 050 051 052 public static Class<?> wrapperToPrimitive(Class<?> wrapperClazz) { 053 Class<?> prim = w2pMap.get(wrapperClazz); 054 if(prim == null) 055 return wrapperClazz; 056 return prim; 057 } 058 059 public static Class<?>[] wrapperToPrimitive(Class<?> ...clazzes) { 060 Class<?>[] result = clazzes; 061 for(int i = 0; i < result.length; i++) { 062 Class<?> curr = result[i]; 063 Class<?> prim = wrapperToPrimitive(curr); 064 if(prim != curr) { 065 if(result == clazzes) 066 result = clazzes.clone(); 067 result[i] = prim; 068 } 069 } 070 071 return result; 072 } 073 074 public static boolean w2pEquals(Class<?> a, Class<?> b) { 075 a = wrapperToPrimitive(a); 076 b = wrapperToPrimitive(b); 077 return a.equals(b); 078 } 079 080 public static boolean w2pEquals(Class<?>[] a, Class<?> ...b) { 081 if(a.length != b.length) 082 return false; 083 084 for(int i = 0; i < a.length; i++) { 085 if(!w2pEquals(a[i], b[i])) 086 return false; 087 } 088 089 return true; 090 } 091 092 093 @SuppressWarnings("unchecked") 094 public static <T> Constructor<T> findConstructor(Class<T> clazz, Class<?> ...params) 095 throws SecurityException, NoSuchMethodException { 096 try { 097 return clazz.getConstructor(params); 098 } catch (NoSuchMethodException e) { 099 Class<?>[] primParams = wrapperToPrimitive(params); 100 if(primParams != params) { 101 try { 102 return clazz.getConstructor(primParams); 103 } 104 catch(NoSuchMethodException e2) {} 105 } 106 107 Constructor<T>[] ctors = (Constructor<T>[])clazz.getConstructors(); 108 109 for(Constructor<T> candidate : ctors) { 110 if(w2pEquals(candidate.getParameterTypes(), params)) 111 return candidate; 112 } 113 114 throw e; 115 } 116 } 117 118 public static Method findMethod(Class<?> clazz, String name, Class<?> ...params) 119 throws SecurityException, NoSuchMethodException { 120 try { 121 return clazz.getMethod(name, params); 122 } catch (NoSuchMethodException e) { 123 Class<?>[] primParams = wrapperToPrimitive(params); 124 if(primParams != params) { 125 try { 126 return clazz.getMethod(name, primParams); 127 } 128 catch(NoSuchMethodException e2) {} 129 } 130 131 Method[] methods = clazz.getMethods(); 132 133 for(Method candidate : methods) { 134 if(w2pEquals(candidate.getParameterTypes())) 135 return candidate; 136 } 137 138 throw e; 139 } 140 } 141 142 public static Method findMethodRT(Class<?> clazz, String name, Class<?> returnType, Class<?> ...params) 143 throws SecurityException, NoSuchMethodException { 144 Method m = findMethod(clazz, name, params); 145 146 if(returnType == null) 147 return m; 148 149 Class<?> rt = m.getReturnType(); 150 151 if(w2pEquals(rt, returnType) || returnType.isAssignableFrom(rt)) 152 return m; 153 154 throw new NoSuchMethodException("Method with matching parameters but incompatible return type " + rt.getName() 155 + " (expected " + returnType.getName() + ") found"); 156 } 157}