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

net.jqwik.engine.support.GenericsSupport Maven / Gradle / Ivy

There is a newer version: 1.9.1
Show newest version
package net.jqwik.engine.support;

import java.lang.reflect.*;
import java.util.*;

public class GenericsSupport {

	private static Map contextsCache = new HashMap<>();

	/**
	 * Return a context object which can resolve generic types for a given {@code contextClass}.
	 *
	 * Must be synchronized because of caching.
	 *
	 * @param contextClass The class to wrap in a context
	 * @return a potentially cached context object
	 */
	public synchronized static GenericsClassContext contextFor(Class contextClass) {
		if (contextClass == null) {
			return GenericsClassContext.NULL;
		}
		return contextsCache.computeIfAbsent(contextClass, GenericsSupport::createContext);
	}

	private static GenericsClassContext createContext(Class contextClass) {
		GenericsClassContext context = new GenericsClassContext(contextClass);
		addResolutionForSuperclass(contextClass, context);
		addResolutionForInterfaces(contextClass, context);
		return context;
	}

	private static void addResolutionForInterfaces(Class contextClass, GenericsClassContext context) {
		Class[] interfaces = contextClass.getInterfaces();
		Type[] genericInterfaces = contextClass.getGenericInterfaces();
		AnnotatedType[] annotatedInterfaces = contextClass.getAnnotatedInterfaces();
		for (int i = 0; i < interfaces.length; i++) {
			Class supertype = interfaces[i];
			Type genericSupertype = genericInterfaces[i];
			AnnotatedType annotatedSupertype = annotatedInterfaces[i];
			addResolutionForSupertype(supertype, genericSupertype, annotatedSupertype, context);
		}
	}

	private static void addResolutionForSuperclass(Class contextClass, GenericsClassContext context) {
		addResolutionForSupertype(contextClass.getSuperclass(), contextClass.getGenericSuperclass(), contextClass.getAnnotatedSuperclass(), context);
	}

	private static void addResolutionForSupertype(Class supertype, Type genericSupertype, AnnotatedType annotatedSupertype, GenericsClassContext context) {
		if (genericSupertype instanceof ParameterizedType) {
			ParameterizedType genericParameterizedType = (ParameterizedType) genericSupertype;
			Type[] supertypeTypeArguments = genericParameterizedType.getActualTypeArguments();
			TypeVariable[] superclassTypeVariables = supertype.getTypeParameters();
			AnnotatedType[] annotatedTypeVariables = ((AnnotatedParameterizedType) annotatedSupertype).getAnnotatedActualTypeArguments();
			for (int i = 0; i < superclassTypeVariables.length; i++) {
				TypeVariable variable = superclassTypeVariables[i];
				Type resolvedType = supertypeTypeArguments[i];
				AnnotatedType annotatedType = annotatedTypeVariables[i];
				context.addResolution(variable, resolvedType, annotatedType);
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy