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

works.lmz.syllabus.apidoc.utils.GenericUtils Maven / Gradle / Ivy

package works.lmz.syllabus.apidoc.utils;

import works.lmz.syllabus.events.EventHandler;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * Author: Marnix
 *
 * Generic related utility functions
 */
public class GenericUtils {

	private GenericUtils() {
		// helper
	}


	/**
	 * Dig up the inheritance tree to find the actual class at which the event handler is defined
	 *
	 * @param leafClass is the leafclass to start digging up from
	 * @return a parameterized type instance that defines the eventhandler.
	 */
	public static ParameterizedType getEventHandlerClass(Class leafClass) {

		for (Type interfaceType : leafClass.getGenericInterfaces()) {
			if (isEventHandlerInterface(interfaceType)) {
				return (ParameterizedType) interfaceType;
			}
		}

		return null;
	}

	/**
	 * @return true if this is the event handler level we're interested in
	 */
	public static boolean isEventHandlerInterface(Type interfaceType) {
		return
			interfaceType instanceof ParameterizedType &&
			((ParameterizedType) interfaceType).getRawType() == EventHandler.class;
	}

	/**
	 * Get the first parameterized type
	 *
	 * @param leafClass is the class to start at
	 * @return the parameterized type or null
	 */
	public static ParameterizedType getFirstParameterizedType(Class leafClass) {
		for (Type interfaceType : leafClass.getGenericInterfaces()) {
			if (interfaceType instanceof ParameterizedType) {
				return (ParameterizedType) interfaceType;
			}
		}

		return null;
	}

	/**
	 * Get the class instance of a specific generic index in the baseclass passed to this method.
	 *
	 * @param baseClass is the class to read from
	 * @param genericIdx is the index of the generic parameter's class we want
	 * @return the generic class
	 */
	public static Class getGenericClassAtIndex(ParameterizedType baseClass, int genericIdx) {
		if (baseClass == null) {
			throw new IllegalArgumentException("Base class cannot be null");
		}
		if (genericIdx < 0) {
			throw new IllegalArgumentException("The generic index cannot be smaller than zero");
		}

		// make sure we can actually retrieve the index we need
		if (baseClass.getActualTypeArguments().length <= genericIdx) {
			throw new IllegalArgumentException("Index cannot be retrieved, type does not have enough");
		}

		// get the correct generic instance, drill up a level when it's a parameterized type (generic in generic)
		Type genInstance = baseClass.getActualTypeArguments()[genericIdx];
		if (genInstance instanceof ParameterizedType) {
			genInstance = ((ParameterizedType) genInstance).getRawType();
		}

		// return its class
		return (Class) genInstance;
	}

	/**
	 * Get the class instance of a specific generic index in the baseclass passed to this method.
	 *
	 * @param baseClass is the class to read from
	 * @param genericIdx is the index of the generic parameter's class we want
	 * @return the generic class
	 */
	public static Class getGenericClassAtIndexForEvent(Class baseClass, int genericIdx) {
		if (baseClass == null) {
			throw new IllegalArgumentException("Base class cannot be null");
		}
		if (genericIdx < 0) {
			throw new IllegalArgumentException("The generic index cannot be smaller than zero");
		}

		// get to the level at which this class is defined as an EventHandler
		ParameterizedType eventHandlerType = getEventHandlerClass(baseClass);
		if (eventHandlerType == null) {
			throw new IllegalStateException(
					"Could not find event handler class for this base class, not an EventHandler."
			);
		}

		// make sure we can actually retrieve the index we need
		if (eventHandlerType.getActualTypeArguments().length <= genericIdx) {
			throw new IllegalArgumentException("Index cannot be retrieved, type does not have enough");
		}

		// get the correct generic instance, drill up a level when it's a parameterized type (generic in generic)
		Type genInstance = eventHandlerType.getActualTypeArguments()[genericIdx];
		if (genInstance instanceof ParameterizedType) {
			genInstance = ((ParameterizedType) genInstance).getRawType();
		}

		// return its class
		return (Class) genInstance;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy