/** * Find the type path leading from the current type to the desired type. * * @param currentType * The current type. * @param clazz * The desired type. * @return The list from current type to desired type. */ public static Deque<Type> findTypePath(final Type currentType, final Class<?> clazz) { final Deque<Type> path = new LinkedList<Type>(); if (!clazz.equals(currentType)) { path.add(currentType); // If the clazz is a Class, look if we can find the clazz. if (currentType instanceof Class) { GenericsUtil.processPath((Class<?>) currentType, clazz, path); } else if (currentType instanceof ParameterizedType) { // Search the raw type. final ParameterizedType parameterizedType = (ParameterizedType) currentType; path.addAll(GenericsUtil.findTypePath(parameterizedType.getRawType(), clazz)); } } return path; }
/** * Process the path. * * @param currentType * The current type. * @param clazz * The type * @param path * The path. */ private static void processPath(final Class<?> currentType, final Class<?> clazz, final Deque<Type> path) { final Class<?> currentClazz = currentType; GenericsUtil.processInterfaces(clazz, path, currentClazz); // We haven't found it yet, try the superclasses. final Type superClass = currentClazz.getGenericSuperclass(); if ((path.size() < 2) && !CheckUtil.isNull(superClass)) { path.addAll(GenericsUtil.findTypePath(superClass, clazz)); } // Still haven't found it, try the declaring classes. final Class<?> declaringClass = currentClazz.getDeclaringClass(); if ((path.size() < 2) && !CheckUtil.isNull(declaringClass)) { path.addAll(GenericsUtil.findTypePath(declaringClass, clazz)); } }
/** * Process the property. * * @param clazz * The type. * @param genericParameter * The generic parameter number. * @param propertyHierarchy * The property hierachy. * @param property * The property. * @return The property type. */ private static Type processProperty(final Class<?> clazz, final int genericParameter, final Deque<? extends Member> propertyHierarchy, final Member property) { Type result = null; // Get the type path. final Type genericType = property.getGenericType(); final Deque<Type> typePath = GenericsUtil.findTypePath(genericType, clazz); // This field is part of the path. if (genericType instanceof ParameterizedType) { typePath.push(genericType); } if (!typePath.isEmpty()) { // Trace to root type. result = GenericsUtil.traceType(property, typePath, genericParameter); result = GenericsUtil.handleTypeVariable(propertyHierarchy, property, result); } return result; }
/** * Gets the generic argument of an entity type. * * @param clazz * The entity type. * @param genericParameter * The generic parameter to get. * @param targetClazz * The target of which the generic parameter is to be resolved. * @return The type of the generic parameter of the target. */ public static Type getEntityGenericType(final Class<?> clazz, final int genericParameter, final Class<?> targetClazz) { // Get the type path. final Deque<Type> typePath = GenericsUtil.findTypePath(clazz, targetClazz); final Iterator<Type> iterator = typePath.descendingIterator(); final ParameterResult result = new ParameterResult(); result.setIndex(genericParameter); Type typeResult = result.getResult(); while (iterator.hasNext() && !(typeResult instanceof Class)) { final Type type = iterator.next(); if (CheckUtil.isNull(typeResult)) { result.setResult(GenericsUtil.processNoResult(genericParameter, result.getIndex(), type)); } else { GenericsUtil.processExistingResult(result, type); } typeResult = result.getResult(); } typeResult = result.getResult(); return typeResult; }