All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hibernate.validator.internal.util.TypeVariableBindings Maven / Gradle / Ivy

Go to download

JSR 380's RI, Hibernate Validator version ${hibernate-validator.version} and its dependencies repackaged as OSGi bundle

There is a newer version: 5.1.0
Show newest version
/*
 * Hibernate Validator, declare and validate application constraints
 *
 * License: Apache License, Version 2.0
 * See the license.txt file in the root directory or .
 */
package org.hibernate.validator.internal.util;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

/**
 * @author Gunnar Morling
 *
 */
public class TypeVariableBindings {

	private TypeVariableBindings() {
	}

	/**
	 * Returns the bindings for all the type variables from the given type's hierarchy. The returned map will contain an
	 * entry for each type in the given type's class hierarchy (including interfaces). Each entry is a map from the
	 * given type's type variables to the corresponding type variables of the type represented by that entry.
	 */
	public static Map, Map, TypeVariable>> getTypeVariableBindings(Class type) {
		Map, Map, TypeVariable>> allBindings = new HashMap<>();
		Map, TypeVariable> currentBindings = new HashMap<>();

		TypeVariable[] subTypeParameters = type.getTypeParameters();
		for ( TypeVariable typeVariable : subTypeParameters ) {
			currentBindings.put( typeVariable, typeVariable );
		}
		allBindings.put( type, currentBindings );

		collectTypeBindings( type, allBindings, currentBindings );

		allBindings.put( Object.class, Collections.emptyMap() );

		return CollectionHelper.toImmutableMap( allBindings );
	}

	private static void collectTypeBindings(Class subType, Map, Map, TypeVariable>> allBindings, Map, TypeVariable> bindings) {
		processGenericSuperType( allBindings, bindings, subType.getGenericSuperclass() );

		for ( Type genericInterface : subType.getGenericInterfaces() ) {
			processGenericSuperType( allBindings, bindings, genericInterface );
		}
	}

	private static void processGenericSuperType(Map, Map, TypeVariable>> allBindings,
			Map, TypeVariable> bindings, Type genericSuperType) {
		if ( genericSuperType == null ) {
			return;
		}
		else if ( genericSuperType instanceof ParameterizedType ) {
			Map, TypeVariable> newBindings = new HashMap<>();
			Type[] typeArguments = ( (ParameterizedType) genericSuperType ).getActualTypeArguments();
			TypeVariable[] typeParameters = ( (Class) ( (ParameterizedType) genericSuperType ).getRawType() ).getTypeParameters();

			for ( int i = 0; i < typeArguments.length; i++ ) {
				Type typeArgument = typeArguments[i];
				TypeVariable typeParameter = typeParameters[i];

				boolean typeParameterFoundInSubType = false;
				for ( Entry, TypeVariable> subTypeParameter : bindings.entrySet() ) {
					if ( typeArgument.equals( subTypeParameter.getValue() ) ) {
						newBindings.put( subTypeParameter.getKey(), typeParameter );
						typeParameterFoundInSubType = true;
					}
				}
				if ( !typeParameterFoundInSubType ) {
					newBindings.put( typeParameter, typeParameter );
				}
			}

			allBindings.put( ( (Class) ( (ParameterizedType) genericSuperType ).getRawType() ), newBindings );
			collectTypeBindings( ( (Class) ( (ParameterizedType) genericSuperType ).getRawType() ), allBindings, newBindings );
		}
		else if ( genericSuperType instanceof Class ) {
			allBindings.put( (Class) genericSuperType, Collections.emptyMap() );
			collectTypeBindings( (Class) genericSuperType, allBindings, new HashMap<>() );
		}
		else {
			throw new IllegalArgumentException( "Unexpected type: " + genericSuperType );
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy