package org.teachingextensions.approvals.lite; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.teachingextensions.approvals.lite.reporters.DiffReporter; import org.teachingextensions.approvals.lite.reporters.FileLauncherReporter; import org.teachingextensions.approvals.lite.reporters.ImageReporter; import org.teachingextensions.approvals.lite.reporters.MultiReporter; import org.teachingextensions.approvals.lite.reporters.QuietReporter; import org.teachingextensions.approvals.lite.reporters.UseReporter; import org.teachingextensions.approvals.lite.util.ClassUtils; public class ReporterFactory { private static HashMap<String, Class<? extends ApprovalFailureReporter>> reporters = new HashMap<>(); public static class FileTypes { public static final String Text = "txt"; public static final String Html = "html"; public static final String Excel = "csv"; public static final String File = "file"; public static final String Image = "png"; private static final String Default = "default"; } static { setupReporters(); } public static ApprovalFailureReporter get(String string) { ApprovalFailureReporter returned = getFromAnnotation(); returned = tryFor(returned, reporters.get(string)); returned = tryFor(returned, reporters.get(FileTypes.Default)); return returned; } public static ApprovalFailureReporter getFromAnnotation() { UseReporter reporter = getAnnotationFromStackTrace(UseReporter.class); return reporter == null ? null : getReporter(reporter); } private static ApprovalFailureReporter getReporter(UseReporter reporter) { Class<? extends ApprovalFailureReporter>[] classes = reporter.value(); List<ApprovalFailureReporter> reporters = new ArrayList<>(); for (Class<? extends ApprovalFailureReporter> clazz : classes) { ApprovalFailureReporter instance = ClassUtils.create(clazz); reporters.add(instance); } return reporters.size() == 1 ? reporters.get(0) : new MultiReporter(reporters); } private static <T extends Annotation> T getAnnotationFromStackTrace(Class<T> annotationClass) { StackTraceElement[] trace = Thread.currentThread().getStackTrace(); for (StackTraceElement stack : trace) { Method method = null; Class<?> clazz = null; try { String methodName = stack.getMethodName(); clazz = Class.forName(stack.getClassName()); method = clazz.getMethod(methodName, (Class<?>[]) null); } catch (Exception e) { //ignore } T annotation = null; if (method != null) { annotation = method.getAnnotation(annotationClass); } if (annotation != null) { return annotation; } annotation = clazz != null ? clazz.getAnnotation(annotationClass) : null; if (annotation != null) { return annotation; } } return null; } private static ApprovalFailureReporter tryFor(ApprovalFailureReporter returned, Class<? extends ApprovalFailureReporter> trying) { if (returned == null && trying != null) { return ClassUtils.create(trying); } return returned; } private static void setupReporters() { reporters.put(FileTypes.Text, DiffReporter.class); reporters.put(FileTypes.Html, DiffReporter.class); reporters.put(FileTypes.Excel, FileLauncherReporter.class); reporters.put(FileTypes.File, FileLauncherReporter.class); reporters.put(FileTypes.Image, ImageReporter.class); reporters.put(FileTypes.Default, QuietReporter.class); } }