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

net.jqwik.engine.facades.JavaBeanReportingFormatFacadeImpl Maven / Gradle / Ivy

The newest version!
package net.jqwik.engine.facades;

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

import org.junit.platform.commons.support.*;

import net.jqwik.api.*;
import net.jqwik.api.Tuple.*;
import net.jqwik.engine.support.*;

public class JavaBeanReportingFormatFacadeImpl extends JavaBeanReportingFormat.JavaBeanReportingFormatFacade {

	@Override
	public Object reportJavaBean(
			Object bean,
			boolean reportNulls,
			Collection excludeProperties,
			Function, List> sortProperties
	) {
		Map report = new LinkedHashMap<>();
		List> properties =
				Arrays.stream(bean.getClass().getMethods())
					  .filter(method -> !JqwikReflectionSupport.isStatic(method))
					  .filter(method -> method.getParameters().length == 0)
					  .filter(method -> !method.getName().equals("getClass"))
					  .filter(method -> !method.getName().equals("get"))
					  .filter(method -> !method.getName().equals("is"))
					  .filter(method -> method.getName().startsWith("get") ||
												method.getName().startsWith("is"))
					  .map(method -> Tuple.of(extractPropertyName(method), method))
					  .sorted(Comparator.comparing(Tuple1::get1))
					  .filter(tuple -> !excludeProperties.contains(tuple.get1()))
					  .collect(Collectors.toList());

		resort(properties, sortProperties).forEach(tuple -> appendGetterToReport(report, reportNulls, tuple, bean));
		return report;
	}

	private Iterable> resort(List> properties, Function, List> nameSorter) {
		List unsortedNames = properties.stream().map(p -> p.get1()).collect(Collectors.toList());
		List sortedNames = nameSorter.apply(unsortedNames);

		List> sortedProperties = new ArrayList<>();
		Map> propertyMap = toMap(properties);
		for (String name : sortedNames) {
			Tuple2 entry = propertyMap.get(name);
			if (entry != null) {
				sortedProperties.add(entry);
			}
		}

		return sortedProperties;
	}

	private Map> toMap(List> properties) {
		HashMap> map = new LinkedHashMap<>();
		for (Tuple2 entry : properties) {
			map.put(entry.get1(), entry);
		}
		return map;
	}

	private void appendGetterToReport(Map report, boolean reportNulls, Tuple2 method, Object bean) {
		maybeAppend(report, reportNulls, method.get1(), () -> {
			try {
				return ReflectionSupport.invokeMethod(method.get2(), bean);
			} catch (Throwable e) {
				JqwikExceptionSupport.rethrowIfBlacklisted(e);
				return "";
			}
		});
	}

	private String extractPropertyName(Method method) {
		String methodName = method.getName();
		String name = methodName.startsWith("get")
							  ? methodName.substring(3)
							  : methodName.startsWith("is")
										? methodName.substring(2)
										: methodName;
		name = Character.toLowerCase(name.charAt(0)) + name.substring(1);
		return name;
	}

	private void maybeAppend(
			Map report,
			boolean reportNulls,
			String name,
			Supplier supplier
	) {
		Object value = supplier.get();
		boolean isNullOrEmpty = value != null && !value.equals(Optional.empty());
		if (reportNulls || isNullOrEmpty) {
			report.put(SampleReportingFormat.plainLabel(name), value);
		}
	}

}