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

net.amygdalum.testrecorder.deserializers.HintManager Maven / Gradle / Ivy

package net.amygdalum.testrecorder.deserializers;

import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;

import net.amygdalum.testrecorder.types.RoleVisitor;
import net.amygdalum.testrecorder.types.SerializedArgument;
import net.amygdalum.testrecorder.types.SerializedField;
import net.amygdalum.testrecorder.types.SerializedImmutableType;
import net.amygdalum.testrecorder.types.SerializedReferenceType;
import net.amygdalum.testrecorder.types.SerializedResult;
import net.amygdalum.testrecorder.types.SerializedRole;
import net.amygdalum.testrecorder.types.SerializedValueType;

public class HintManager implements RoleVisitor> {

	private Map> hints;

	public HintManager() {
		hints = new HashMap<>();
	}

	public void addHint(AnnotatedElement role, Object hint) {
		hints.computeIfAbsent(role, key -> new HashSet<>())
			.add(hint);
	}

	public  Stream fetch(Class clazz, SerializedRole role) {
		return role.accept(this)
			.filter(clazz::isInstance)
			.map(clazz::cast);
	}

	public  Stream fetch(Class clazz, AnnotatedElement element) {
		if (element instanceof Executable) {
			return fetchResultHints((Executable) element)
				.filter(clazz::isInstance)
				.map(clazz::cast);
		} else if (element instanceof Field) {
			return fetchFieldHints((Field) element)
				.filter(clazz::isInstance)
				.map(clazz::cast);
		} else if (element instanceof Class) {
			return fetchTypeHints((Class) element)
				.filter(clazz::isInstance)
				.map(clazz::cast);
		} else {
			return Stream.empty();
		}
	}

	public Stream fetchArgumentHints(Executable method, int index) {
		Stream argumentHints = Arrays.stream(method.getParameterAnnotations()[index]);
		Set methodHints = hints.get(method);
		if (methodHints == null) {
			return argumentHints;
		}
		Stream customHints = methodHints.stream()
			.filter(obj -> obj.getClass().isArray())
			.map(obj -> (Object[]) obj)
			.map(arguments -> arguments[index]);
		return Stream.concat(argumentHints, customHints);
	}

	public Stream fetchResultHints(Executable method) {
		Stream resultHints = Arrays.stream(method.getAnnotations());
		Set methodHints = hints.get(method);
		if (methodHints == null) {
			return resultHints;
		}
		Stream customHints = methodHints.stream()
			.filter(obj -> !obj.getClass().isArray());
		return Stream.concat(resultHints, customHints);
	}

	public Stream fetchFieldHints(Field field) {
		Stream fieldHints = Arrays.stream(field.getAnnotations());
		Set fieldCustomHints = hints.get(field);
		if (fieldCustomHints == null) {
			return fieldHints;
		}
		Stream customHints = fieldCustomHints.stream();
		return Stream.concat(fieldHints, customHints);
	}

	public Stream fetchTypeHints(Class type) {
		if (type == null) {
			return Stream.empty();
		}
		Stream typeHints = Arrays.stream(type.getAnnotations());
		Set typeCustomHints = hints.get(type);
		if (typeCustomHints == null) {
			return typeHints;
		}
		Stream customHints = typeCustomHints.stream();
		return Stream.concat(typeHints, customHints);
	}

	@Override
	public Stream visitArgument(SerializedArgument argument) {
		try {
			return fetchArgumentHints(argument.getSignature().resolveMethod(), argument.getIndex());
		} catch (NoSuchMethodException e) {
			return Stream.empty();
		}
	}

	@Override
	public Stream visitResult(SerializedResult result) {
		try {
			return fetchResultHints(result.getSignature().resolveMethod());
		} catch (NoSuchMethodException e) {
			return Stream.empty();
		}
	}

	@Override
	public Stream visitField(SerializedField field) {
		try {
			return fetchFieldHints(field.getSignature().resolveField());
		} catch (NoSuchFieldException e) {
			return Stream.empty();
		}
	}

	@Override
	public Stream visitReferenceType(SerializedReferenceType value) {
		return fetchTypeHints(value.getType());
	}

	@Override
	public Stream visitImmutableType(SerializedImmutableType value) {
		return fetchTypeHints(value.getType());
	}

	@Override
	public Stream visitValueType(SerializedValueType value) {
		return fetchTypeHints(value.getType());
	}

}