/** * Guesses the clazz of a type. * * @param type * The type. * @return The clazz. */ public static Class<?> guessClazz(final Type type) { return GenericsUtil.guessClazz(type, 0); }
/** * Gets the type variable match. * * @param clazz * The type. * @param typeVariableSuper * The super variables. * @param result * The result. */ private static void getClassMatch(final Class<?> clazz, final TypeVariable<?>[] typeVariableSuper, final ParameterResult result) { for (int i = 0; i < typeVariableSuper.length; i = i + 1) { if (typeVariableSuper[i].equals(result.getResult())) { result.setIndex(i); result.setResult(typeVariableSuper[i]); } } }
/** * Finds originating type for this field. * * @param properties * The fields to look through. * @return The true type. */ public static Type getRealType(final Deque<? extends Member> properties) { final Member property = properties.pop(); final Type fieldType = property.getGenericType(); Type result = null; if (fieldType instanceof TypeVariable) { final TypeVariable<?> typeVariable = (TypeVariable<?>) fieldType; final Class<?> declaringType = GenericsUtil.getDeclaringClass(property.getDeclaringType(), typeVariable); final TypeVariable<?> superTypeVariable = GenericsUtil.getSuperDeclaration(property, typeVariable); final int param = GenericsUtil.getRealParameter(superTypeVariable); result = GenericsUtil.getPropertyGenericType(declaringType, param, properties); } else if (fieldType instanceof Class) { result = fieldType; } else if (fieldType instanceof ParameterizedType) { final ParameterizedType pType = (ParameterizedType) fieldType; result = pType.getRawType(); } 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; }
final ParameterResult result = new ParameterResult(); result.setIndex(originatingIndex); Type typeResult = result.getResult(); while (iterator.hasNext() && !(typeResult instanceof Class)) { final Type type = iterator.next(); if (CheckUtil.isNull(typeResult)) { result.setResult(GenericsUtil.processNoResult(originatingIndex, result.getIndex(), type)); } else { GenericsUtil.processExistingResult(result, type); typeResult = result.getResult(); if (typeResult instanceof TypeVariable<?>) { final Type type = property.getGenericType(); if (type instanceof ParameterizedType) { final ParameterizedType parameterizedType = (ParameterizedType) type; result.setResult(parameterizedType.getActualTypeArguments()[result.getIndex()]); return result.getResult();
/** * Adds a converter. * * @param converter * The converter. */ public final void addConverter(final Converter<?> converter) { Validate.notNull(converter, AbstractDefaultConverterTool.CONVERTER_NULL); final Type converterType = GenericsUtil.getEntityGenericType(converter.getClass(), 0, Converter.class); this.converters.put(GenericsUtil.guessClazz(converterType), converter); }
final Class<?> declaringClass = GenericsUtil.getDeclaringClass(property.getDeclaringType(), typeVariable); int index = -1; final TypeVariable<?>[] typeVariables = declaringClass.getTypeParameters(); if (GenericsUtil.isPositive(index)) { result = GenericsUtil.getPropertyGenericType(declaringClass, index, propertyHierarchy);
/** * 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; }
/** * Process an existing result. * * @param result * The result. * @param type * The result type. */ private static void processExistingResult(final ParameterResult result, final Type type) { if (type instanceof Class) { final Class<?> clazz = (Class<?>) type; final TypeVariable<?>[] typeVariableSuper = clazz.getTypeParameters(); GenericsUtil.getClassMatch(clazz, typeVariableSuper, result); } else if (type instanceof ParameterizedType) { final ParameterizedType parameterizedType = (ParameterizedType) type; final Class<?> clazz = (Class<?>) parameterizedType.getRawType(); Type[] types = clazz.getTypeParameters(); GenericsUtil.getClassMatch(clazz, types, result); types = parameterizedType.getActualTypeArguments(); GenericsUtil.getClassMatch(clazz, types, result); final Type actualType = parameterizedType.getActualTypeArguments()[result.getIndex()]; if (actualType instanceof Class) { result.setResult(actualType); } else if (actualType instanceof ParameterizedType) { final ParameterizedType actualParameterizedType = (ParameterizedType) actualType; result.setResult(actualParameterizedType.getRawType()); } } }
/** * Finds originating type for this field. * * @param propertyHierarchy * The fields to look through. * @return The true type. */ public static Type getRealType(final Member... propertyHierarchy) { final Deque<Member> properties = new LinkedList<Member>(); for (final Member property : propertyHierarchy) { properties.add(property); } return GenericsUtil.getRealType(properties); }
/** * Gets the most specific type we can assign to the given genericParameter * to the clazz in the known fieldHierarchy. * * @param clazz * THe clazz we're looking for. * @param genericParameter * The parameter number of the clazz we're looking for. * @param propertyHierarchy * The filed hierarchy. * @return The most specific type we can assign to the given parameter. */ public static Type getPropertyGenericType(final Class<?> clazz, final int genericParameter, final Member... propertyHierarchy) { final Deque<Member> properties = new LinkedList<Member>(); for (final Member property : propertyHierarchy) { properties.add(property); } return GenericsUtil.getPropertyGenericType(clazz, genericParameter, properties); }
/** * 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)); } }
/** * Guesses the clazz of a type. * * @param type * The type. * @param loops * Amount of loops. * @return The clazz. */ private static Class<?> guessClazz(final Type type, final int loops) { final int looped = loops + 1; Class<?> result; if (type instanceof Class) { result = (Class<?>) type; } else if (type instanceof ParameterizedType) { final ParameterizedType paramType = (ParameterizedType) type; result = GenericsUtil.decideGuessClazz(looped, paramType.getRawType()); } else if (type instanceof TypeVariable<?>) { final TypeVariable<?> typeVar = (TypeVariable<?>) type; final Type[] bounds = typeVar.getBounds(); result = GenericsUtil.decideGuessClazz(looped, bounds[0]); } else if (type instanceof WildcardType) { final WildcardType wildType = (WildcardType) type; final Type[] bounds = wildType.getUpperBounds(); result = GenericsUtil.decideGuessClazz(looped, bounds[0]); } else { result = Object.class; } return result; }
/** * Gets the most specific type we can assign to the given genericParameter * to the clazz in the known fieldHierarchy. * * @param clazz * THe clazz we're looking for. * @param genericParameter * The parameter number of the clazz we're looking for. * @param propertyHierarchy * The filed hierarachy. * @return The most specific type we can assign to the given parameter. */ public static Type getPropertyGenericType(final Class<?> clazz, final int genericParameter, final Deque<? extends Member> propertyHierarchy) { Type result = null; if (!propertyHierarchy.isEmpty()) { // First field. final Member property = propertyHierarchy.pop(); if (!CheckUtil.isNull(property)) { result = GenericsUtil.processProperty(clazz, genericParameter, propertyHierarchy, property); } } return result; }
/** * Gets the variable of the class that represents the variable for the * field. * * @param property * The field to match the variable to. * @param typeVariable * The variable to match. * @return The variable of the declaring class. */ public static TypeVariable<?> getSuperDeclaration(final Member property, final TypeVariable<?> typeVariable) { TypeVariable<?> result = typeVariable; Class<?> declaring = property.getDeclaringType(); while (!CheckUtil.isNull(declaring)) { for (final TypeVariable<?> declaringTypeVariable : declaring.getTypeParameters()) { if (result.equals(declaringTypeVariable)) { result = declaringTypeVariable; } } declaring = declaring.getDeclaringClass(); } return result; }
/** * Gets the clazz declaring the typevariable. * * @param declaringClazz * The declaring clazz. * @param target * The type variable we're looking for. * @return The clazz or one of it's declaring classes. */ public static Class<?> getDeclaringClass(final Class<?> declaringClazz, final TypeVariable<?> target) { Class<?> source = declaringClazz; boolean equals = false; // Test if we can find the declaring clazz. for (final TypeVariable<?> typeVariable : declaringClazz.getTypeParameters()) { if (typeVariable.equals(target)) { equals = true; } } // Search it's declaring clazz. final Class<?> nextDeclaring = declaringClazz.getDeclaringClass(); if (!equals && !CheckUtil.isNull(nextDeclaring)) { source = GenericsUtil.getDeclaringClass(nextDeclaring, target); } return source; }
/** * Decide if we continue on guessing the class or we stick to Object. * * @param looped * The amount of times we looped. * @param type * The guessed type. * @return The guessed type. */ private static Class<?> decideGuessClazz(final int looped, final Type type) { Class<?> result; if (looped > GenericsUtil.MAX_SCAN_DEPTH) { result = Object.class; } else { result = GenericsUtil.guessClazz(type, looped); } return result; }
/** * Gets the type variable match. * * @param clazz * The type. * @param types * The super variables. * @param result * The result. */ private static void getClassMatch(final Class<?> clazz, final Type[] types, final ParameterResult result) { for (int i = 0; i < types.length; i = i + 1) { if (types[i].equals(result.getResult())) { result.setIndex(i); result.setResult(types[i]); } } }
/** {@inheritDoc} */ @Override public void handleEvent(final UpdatedParameterEvent<P, B> event) throws EventException { SetParameterListener.LOGGER.debug("Handling event {}", event); Validate.notNull(event, "Event may not be null."); final AnnotationParameterDescriptorBuilder<P, B> builder = event.getBuilder(); final Deque<DescribedParameter<?>> params = new LinkedList<DescribedParameter<?>>(); params.add(event.getParameter()); final java.lang.reflect.Type type = GenericsUtil.getRealType(params); if (type instanceof Class) { builder.type((Class<?>) type); } else { builder.type(Object.class); } } }
/** {@inheritDoc} */ @Override public void handleEvent(final UpdatedPropertyTypeEvent<P, E, B> event) throws EventException { SetPropertyListener.LOGGER.debug("Handle event {}", event); Validate.notNull(event, "Event may not be null."); final AnnotationPropertyDescriptorBuilder<P, E, B> builder = event.getBuilder(); final java.lang.reflect.Type type = GenericsUtil.getRealType(builder.getBuilderContext().getAccessorContext() .getDescribedProperties()); if (type instanceof Class) { builder.type((Class<?>) type); } else { builder.type(Object.class); } } }