package org.javers.core.metamodel.type; import org.javers.common.collections.Lists; import org.javers.common.exception.JaversException; import org.javers.common.exception.JaversExceptionCode; import org.javers.common.reflection.ReflectionUtil; import org.javers.core.metamodel.annotation.DiffIgnore; import org.javers.core.metamodel.clazz.ClientsClassDefinition; import org.javers.core.metamodel.property.Property; import org.javers.core.metamodel.scanner.ClassScan; import org.javers.core.metamodel.scanner.ClassScanner; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import static org.javers.common.collections.Lists.positiveFilter; /** * @author bartosz walacik */ class ManagedClassFactory { private final ClassScanner classScanner; private final TypeMapper typeMapper; public ManagedClassFactory(ClassScanner classScanner, TypeMapper typeMapper) { this.classScanner = classScanner; this.typeMapper = typeMapper; } ManagedClass create(Class<?> baseJavaClass){ ClassScan scan = classScanner.scan(baseJavaClass); List<JaversProperty> allProperties = convert(scan.getProperties()); return new ManagedClass(baseJavaClass, allProperties, positiveFilter(allProperties, p -> p.looksLikeId())); } ManagedClass create(ClientsClassDefinition def){ ClassScan scan = classScanner.scan(def.getBaseJavaClass()); List<JaversProperty> allProperties = convert(scan.getProperties()); List<JaversProperty> filtered = filterIgnored(allProperties, def); filtered = filterIgnoredType(filtered, def.getBaseJavaClass()); return new ManagedClass(def.getBaseJavaClass(), filtered, positiveFilter(allProperties, p -> p.looksLikeId())); } private List<JaversProperty> convert(List<Property> properties) { return Lists.transform(properties, p -> { if (typeMapper.contains(p.getGenericType())) { final JaversType javersType = typeMapper.getJaversType(p.getGenericType()); return new JaversProperty(() -> javersType, p); } return new JaversProperty(() -> typeMapper.getJaversType(p.getGenericType()), p); }); } private List<JaversProperty> filterIgnoredType(List<JaversProperty> properties, final Class<?> currentClass){ return (List)Lists.negativeFilter(properties, property -> { if (property.getRawType() == currentClass){ return false; } //prevents stackoverflow if (typeMapper.contains(property.getRawType()) || typeMapper.contains(property.getGenericType())) { return typeMapper.getJaversType(property.getRawType()) instanceof IgnoredType; } return ReflectionUtil.isAnnotationPresentInHierarchy(property.getRawType(), DiffIgnore.class); }); } private List<JaversProperty> filterIgnored(List<JaversProperty> properties, ClientsClassDefinition definition){ if (definition.getIgnoredProperties().isEmpty()){ return properties; } List<JaversProperty> filtered = new ArrayList<>(properties); for (String ignored : definition.getIgnoredProperties()){ filterOneProperty(filtered, ignored, definition.getBaseJavaClass()); } return filtered; } private void filterOneProperty(List<JaversProperty> properties, String ignoredName, Class<?> clientsClass) { Iterator<JaversProperty> it = properties.iterator(); while (it.hasNext()) { JaversProperty property = it.next(); if (property.getName().equals(ignoredName)) { it.remove(); return; } } throw new JaversException(JaversExceptionCode.PROPERTY_NOT_FOUND, ignoredName, clientsClass.getName()); } }