From 5b5c702e260bf8059f17761d33cb3325f499ebdc Mon Sep 17 00:00:00 2001 From: Marcus Talbot Date: Mon, 2 Dec 2024 14:07:28 +0100 Subject: [PATCH 1/3] Various Sonar improvements - Converted BeanMapper to record - Converted AnnotationClass to record - Added Virtual Thread concurrency test. - Improved use of generics. - Added private constructors to utility-classes, to hide implicit public constructors. - Removed redundant MappingException.java --- .../io/beanmapper/BeanCollectionExample.java | 12 +- src/main/java/io/beanmapper/BeanMapper.java | 46 ++-- .../annotations/BeanCollection.java | 4 +- .../beanmapper/config/BeanMapperBuilder.java | 18 +- .../AbstractCollectionHandler.java | 1 + .../core/converter/AbstractBeanConverter.java | 2 +- .../collections/AnnotationClass.java | 8 +- .../collections/CollectionConverter.java | 2 +- .../collections/CollectionElementType.java | 10 +- .../impl/OptionalToObjectConverter.java | 15 +- .../converter/impl/PrimitiveConverter.java | 3 +- .../converter/impl/RecordToAnyConverter.java | 2 +- .../exceptions/BeanMappingException.java | 2 +- .../exceptions/MappingException.java | 13 - .../strategy/AbstractMapStrategy.java | 2 +- .../strategy/MapToDynamicClassStrategy.java | 4 +- .../utils/BeanMapperPerformanceLogger.java | 4 + .../java/io/beanmapper/BeanMapperTest.java | 231 +++++++++++++----- .../config/BeanMapperBuilderTest.java | 84 +++---- .../config/CollectionHandlerStoreTest.java | 8 +- .../config/OverrideConfigurationTest.java | 4 +- .../config/StrictMappingPropertiesTest.java | 2 +- .../converter/AbstractBeanConverterTest.java | 3 +- .../collections/AnnotationClassTest.java | 6 +- .../BeanCollectionInstructionsTest.java | 2 +- .../impl/OptionalToObjectConverterTest.java | 2 +- .../dynclass/AbstractConcurrentTest.java | 19 ++ .../dynclass/ClassGeneratorTest.java | 28 ++- .../beanmapper/dynclass/ClassStoreTest.java | 2 +- .../BeanInstantiationExceptionTest.java | 2 +- .../strategy/MapToRecordStrategyTest.java | 2 +- .../CountPerPairDiagnosticsLoggerTest.java | 6 +- .../CountTotalDiagnosticsLoggerTest.java | 2 +- .../TreeCompleteDiagnosticsLogger.java | 5 +- 34 files changed, 353 insertions(+), 203 deletions(-) delete mode 100644 src/main/java/io/beanmapper/exceptions/MappingException.java diff --git a/docs/src/test/java/io/beanmapper/BeanCollectionExample.java b/docs/src/test/java/io/beanmapper/BeanCollectionExample.java index 7a86d0af..1ee567b9 100644 --- a/docs/src/test/java/io/beanmapper/BeanCollectionExample.java +++ b/docs/src/test/java/io/beanmapper/BeanCollectionExample.java @@ -18,13 +18,13 @@ public class BeanCollectionExample { @Test void mapCollectionWithConstruct() { Source source = new Source(); - source.items = new LinkedHashSet(); + source.items = new LinkedHashSet<>(); source.items.add(new Person(1L, "Henk", 42)); source.items.add(new Person(2L, "Piet", 18)); source.items.add(new Person(3L, "Gijs", 67)); TargetWithConstruct target = new TargetWithConstruct(); - target.items = new ArrayList(); + target.items = new ArrayList<>(); target.items.add(new PersonResult("Kees", 13)); target.items.add(new PersonResult("Klaas", 24)); @@ -40,13 +40,13 @@ void mapCollectionWithConstruct() { @Test void mapCollectionWithReuse() { Source source = new Source(); - source.items = new LinkedHashSet(); + source.items = new LinkedHashSet<>(); source.items.add(new Person(1L, "Henk", 42)); source.items.add(new Person(2L, "Piet", 18)); source.items.add(new Person(3L, "Gijs", 67)); TargetWithReuse target = new TargetWithReuse(); - target.items = new ArrayList(); + target.items = new ArrayList<>(); target.items.add(new PersonResult("Kees", 13)); target.items.add(new PersonResult("Klaas", 24)); @@ -64,13 +64,13 @@ void mapCollectionWithReuse() { @Test void mapCollectionWithClear() { Source source = new Source(); - source.items = new LinkedHashSet(); + source.items = new LinkedHashSet<>(); source.items.add(new Person(1L, "Henk", 42)); source.items.add(new Person(2L, "Piet", 18)); source.items.add(new Person(3L, "Gijs", 67)); TargetWithClear target = new TargetWithClear(); - target.items = new ArrayList(); + target.items = new ArrayList<>(); target.items.add(new PersonResult("Kees", 13)); target.items.add(new PersonResult("Klaas", 24)); diff --git a/src/main/java/io/beanmapper/BeanMapper.java b/src/main/java/io/beanmapper/BeanMapper.java index 92a9926f..a0af3bf8 100644 --- a/src/main/java/io/beanmapper/BeanMapper.java +++ b/src/main/java/io/beanmapper/BeanMapper.java @@ -27,21 +27,16 @@ * objects. Once that has been determined, the applicable properties will be copied from * source to target. */ -public final class BeanMapper { +public record BeanMapper(Configuration configuration) { - private final Configuration configuration; - - public BeanMapper(Configuration configuration) { - this.configuration = configuration; - } - - private void addDiagnosticsNode(S source) { + @SuppressWarnings("unchecked") + private void addDiagnosticsNode(S source) { if (configuration instanceof DiagnosticsConfiguration dc && dc.isInDiagnosticsMode()) { if (dc.getParentConfiguration().orElse(null) instanceof DiagnosticsConfigurationImpl dci) { dci.getBeanMapperDiagnostics().ifPresent(bd -> bd.getDiagnostics().clear()); } Class sourceClass = source != null ? (Class) configuration.getBeanUnproxy().unproxy(source.getClass()) : (Class) Void.class; - DiagnosticsNode node = getsDiagnosticsNode(source, sourceClass); + DiagnosticsNode node = getsDiagnosticsNode(source, sourceClass); dc.setBeanMapperDiagnostics(node); if (configuration instanceof OverrideConfiguration) { dc.getParentConfiguration() @@ -52,13 +47,15 @@ private void addDiagnosticsNode(S source) { } } - private DiagnosticsNode getsDiagnosticsNode(S source, Class sourceClass) { - DiagnosticsNode node = new MappingDiagnosticsNode(sourceClass, configuration.getTargetClass()); + @SuppressWarnings({ "unchecked", "rawtypes" }) + private DiagnosticsNode getsDiagnosticsNode(S source, Class sourceClass) { + DiagnosticsNode node = new MappingDiagnosticsNode<>(sourceClass, configuration.getTargetClass()); if (source instanceof Collection) { node = new CollectionMappingDiagnosticNode<>(source, sourceClass, configuration.getPreferredCollectionClass(), configuration.getTargetClass()); } - if (source instanceof Map) { - node = new MapMappingDiagnosticsNode<>((Map) source, (Class) sourceClass, configuration.getPreferredCollectionClass(), configuration.getTargetClass()); + if (source instanceof Map map) { + node = new MapMappingDiagnosticsNode<>(map, (Class) sourceClass, configuration.getPreferredCollectionClass(), + configuration.getTargetClass()); } return node; } @@ -67,7 +64,7 @@ public T map(S source) { addDiagnosticsNode(source); if (source == null && !configuration.getUseNullValue()) { // noinspection unchecked - return (T) this.getConfiguration().getDefaultValueForClass(this.getConfiguration().getTargetClass()); + return (T) this.configuration().getDefaultValueForClass(this.configuration().getTargetClass()); } T result = MapStrategyType.getStrategy(this, configuration).map(source); if (this.configuration.getParentConfiguration().orElseThrow() instanceof DiagnosticsConfigurationImpl dc) { @@ -101,6 +98,7 @@ public T map(S source, T target) { * @param the instance to which the properties get copied * @return the optional target instance containing all applicable properties */ + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") public Optional map(Optional source, Class targetClass) { if (source.orElse(null) instanceof Optional optional && !targetClass.isInstance(Optional.class)) { return this.map(optional, targetClass); @@ -122,15 +120,12 @@ public Optional map(Optional source, Class targetClass) { * @return The result of the mapping. */ public Object map(S source, P target) { - if (source instanceof Collection collection) { - return this.map(collection, (Class) target.getActualTypeArguments()[0]); - } else if (source instanceof Map map) { - return this.map(map, (Class) target.getActualTypeArguments()[1]); - } else if (source instanceof Optional optional) { - return this.map(optional, (Class) target.getActualTypeArguments()[0]); - } else { - return this.map(source, (Class) target.getRawType()); - } + return switch (source) { + case Collection collection -> this.map(collection, (Class) target.getActualTypeArguments()[0]); + case Map map -> this.map(map, (Class) target.getActualTypeArguments()[1]); + case Optional optional -> this.map(optional, (Class) target.getActualTypeArguments()[0]); + default -> this.map(source, (Class) target.getRawType()); + }; } /** @@ -158,6 +153,7 @@ public T map(S source, Class targetClass) { * @param The type of the elements in the target array. * @return A newly constructed array of the type of the target class. */ + @SuppressWarnings("unchecked") public T[] map(S[] sourceArray, Class targetClass) { return Arrays.stream(sourceArray) .map(element -> this.wrap().setConverterChoosable(true).build().map(element, targetClass)) @@ -248,8 +244,4 @@ public BeanMapperBuilder wrap() { public BeanMapperBuilder wrap(DiagnosticsDetailLevel detailLevel) { return new BeanMapperBuilder(configuration, detailLevel); } - - public Configuration getConfiguration() { - return configuration; - } } diff --git a/src/main/java/io/beanmapper/annotations/BeanCollection.java b/src/main/java/io/beanmapper/annotations/BeanCollection.java index a9e10d19..17399881 100644 --- a/src/main/java/io/beanmapper/annotations/BeanCollection.java +++ b/src/main/java/io/beanmapper/annotations/BeanCollection.java @@ -20,7 +20,7 @@ * type will be used by BeanMapper to pass the target class type. * @return the class type of a target element collection */ - Class elementType() default void.class; + Class elementType() default void.class; /** * Determines how BeanMapper must deal with the target collection. The default option @@ -40,7 +40,7 @@ * instead of the default one provided by the collection handler * @return the class to instantiate instead of the one provided by the collection handler */ - Class preferredCollectionClass() default void.class; + Class preferredCollectionClass() default void.class; /** * When usage is CLEAR and the target collection is being managed by, eg, Hibernate's diff --git a/src/main/java/io/beanmapper/config/BeanMapperBuilder.java b/src/main/java/io/beanmapper/config/BeanMapperBuilder.java index db5ef8bc..128f1aae 100644 --- a/src/main/java/io/beanmapper/config/BeanMapperBuilder.java +++ b/src/main/java/io/beanmapper/config/BeanMapperBuilder.java @@ -33,7 +33,7 @@ public class BeanMapperBuilder { - private static final List DEFAULT_COLLECTION_HANDLERS = + private static final List> DEFAULT_COLLECTION_HANDLERS = List.of( new MapCollectionHandler(), new SetCollectionHandler(), @@ -45,7 +45,7 @@ public class BeanMapperBuilder { private final List customBeanConverters = new ArrayList<>(); - private final List customCollectionHandlers = new ArrayList<>(); + private final List> customCollectionHandlers = new ArrayList<>(); public BeanMapperBuilder() { this.configuration = new CoreConfiguration(); @@ -79,7 +79,7 @@ public BeanMapperBuilder addConverter(BeanConverter converter) { return this; } - public BeanMapperBuilder addCollectionHandler(CollectionHandler handler) { + public BeanMapperBuilder addCollectionHandler(CollectionHandler handler) { this.customCollectionHandlers.add(handler); return this; } @@ -114,7 +114,7 @@ public BeanMapperBuilder addAfterClearFlusher(AfterClearFlusher afterClearFlushe return this; } - public BeanMapperBuilder addLogicSecuredCheck(LogicSecuredCheck logicSecuredCheck) { + public BeanMapperBuilder addLogicSecuredCheck(LogicSecuredCheck logicSecuredCheck) { this.configuration.addLogicSecuredCheck(logicSecuredCheck); return this; } @@ -151,12 +151,12 @@ public BeanMapperBuilder downsizeTarget(List includeFields) { return this; } - public BeanMapperBuilder setCollectionClass(Class collectionClass) { + public BeanMapperBuilder setCollectionClass(Class collectionClass) { this.configuration.setCollectionClass(collectionClass); return this; } - public BeanMapperBuilder setTargetClass(Class targetClass) { + public BeanMapperBuilder setTargetClass(Class targetClass) { this.configuration.setTargetClass(targetClass); return this; } @@ -247,8 +247,8 @@ public BeanMapper build() { return beanMapper; } - private void addCollectionHandlers(List collectionHandlers) { - for (CollectionHandler collectionHandler : collectionHandlers) { + private void addCollectionHandlers(List> collectionHandlers) { + for (CollectionHandler collectionHandler : collectionHandlers) { attachCollectionHandler(collectionHandler); } } @@ -277,7 +277,7 @@ private void addDefaultConverters() { } } - private void attachCollectionHandler(CollectionHandler collectionHandler) { + private void attachCollectionHandler(CollectionHandler collectionHandler) { configuration.addCollectionHandler(collectionHandler); } diff --git a/src/main/java/io/beanmapper/core/collections/AbstractCollectionHandler.java b/src/main/java/io/beanmapper/core/collections/AbstractCollectionHandler.java index 54076258..bf658611 100644 --- a/src/main/java/io/beanmapper/core/collections/AbstractCollectionHandler.java +++ b/src/main/java/io/beanmapper/core/collections/AbstractCollectionHandler.java @@ -15,6 +15,7 @@ public abstract class AbstractCollectionHandler implements CollectionHandler< private final Class type; private final DefaultBeanInitializer beanInitializer = new DefaultBeanInitializer(); + @SuppressWarnings("unchecked") protected AbstractCollectionHandler() { this.type = (Class) Classes.getParameteredTypes(getClass())[0]; } diff --git a/src/main/java/io/beanmapper/core/converter/AbstractBeanConverter.java b/src/main/java/io/beanmapper/core/converter/AbstractBeanConverter.java index 6eac03ea..b8f288ec 100644 --- a/src/main/java/io/beanmapper/core/converter/AbstractBeanConverter.java +++ b/src/main/java/io/beanmapper/core/converter/AbstractBeanConverter.java @@ -49,7 +49,7 @@ public final R convert(BeanMapper beanMapper, U source, Class targetCl this.beanMapper = beanMapper; if (source == null) { if (beanMapper != null) - beanMapper.getConfiguration().getDefaultValueForClass(targetClass); + beanMapper.configuration().getDefaultValueForClass(targetClass); return null; } Check.argument(isMatchingSource(source.getClass()), "Unsupported source class."); diff --git a/src/main/java/io/beanmapper/core/converter/collections/AnnotationClass.java b/src/main/java/io/beanmapper/core/converter/collections/AnnotationClass.java index e92076b3..01bef88a 100644 --- a/src/main/java/io/beanmapper/core/converter/collections/AnnotationClass.java +++ b/src/main/java/io/beanmapper/core/converter/collections/AnnotationClass.java @@ -1,11 +1,9 @@ package io.beanmapper.core.converter.collections; -public class AnnotationClass { +public record AnnotationClass(Class annotationClass) { public static final AnnotationClass EMPTY_ANNOTATION_CLASS = new AnnotationClass(null); - private final Class annotationClass; - public AnnotationClass(Class annotationClass) { this.annotationClass = determineClass(annotationClass); } @@ -16,10 +14,6 @@ private Class determineClass(Class collectionElementType) { collectionElementType; } - public Class getAnnotationClass() { - return this.annotationClass; - } - public boolean isEmpty() { return this.annotationClass == null; } diff --git a/src/main/java/io/beanmapper/core/converter/collections/CollectionConverter.java b/src/main/java/io/beanmapper/core/converter/collections/CollectionConverter.java index efd2cda4..978d5771 100644 --- a/src/main/java/io/beanmapper/core/converter/collections/CollectionConverter.java +++ b/src/main/java/io/beanmapper/core/converter/collections/CollectionConverter.java @@ -30,7 +30,7 @@ public U convert( return BeanMapperPerformanceLogger.runTimed(() -> beanMapper.wrap() .setCollectionClass(collectionHandler.getType()) .setCollectionUsage(beanPropertyMatch.getCollectionInstructions().getBeanCollectionUsage()) - .setPreferredCollectionClass(beanPropertyMatch.getCollectionInstructions().getPreferredCollectionClass().getAnnotationClass()) + .setPreferredCollectionClass(beanPropertyMatch.getCollectionInstructions().getPreferredCollectionClass().annotationClass()) .setFlushAfterClear(beanPropertyMatch.getCollectionInstructions().getFlushAfterClear()) .setTargetClass(beanPropertyMatch.getCollectionInstructions().getCollectionElementType().getType()) .setTarget(beanPropertyMatch.getTargetObject()) diff --git a/src/main/java/io/beanmapper/core/converter/collections/CollectionElementType.java b/src/main/java/io/beanmapper/core/converter/collections/CollectionElementType.java index af470155..ab586251 100644 --- a/src/main/java/io/beanmapper/core/converter/collections/CollectionElementType.java +++ b/src/main/java/io/beanmapper/core/converter/collections/CollectionElementType.java @@ -5,12 +5,12 @@ public class CollectionElementType { public static final CollectionElementType EMPTY_COLLECTION_ELEMENT_TYPE = new CollectionElementType(null, true); - private final AnnotationClass collectionElementType; + private final AnnotationClass classOfCollectionElement; private final boolean derived; - private CollectionElementType(Class collectionElementType, boolean derived) { - this.collectionElementType = new AnnotationClass(collectionElementType); + private CollectionElementType(Class classOfCollectionElement, boolean derived) { + this.classOfCollectionElement = new AnnotationClass(classOfCollectionElement); this.derived = derived; } @@ -27,11 +27,11 @@ public boolean isDerived() { } public Class getType() { - return collectionElementType.getAnnotationClass(); + return classOfCollectionElement.annotationClass(); } public boolean isEmpty() { - return collectionElementType.isEmpty(); + return classOfCollectionElement.isEmpty(); } } diff --git a/src/main/java/io/beanmapper/core/converter/impl/OptionalToObjectConverter.java b/src/main/java/io/beanmapper/core/converter/impl/OptionalToObjectConverter.java index f7312269..e030503a 100644 --- a/src/main/java/io/beanmapper/core/converter/impl/OptionalToObjectConverter.java +++ b/src/main/java/io/beanmapper/core/converter/impl/OptionalToObjectConverter.java @@ -1,15 +1,20 @@ package io.beanmapper.core.converter.impl; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + import io.beanmapper.BeanMapper; import io.beanmapper.core.BeanPropertyMatch; import io.beanmapper.core.converter.BeanConverter; import io.beanmapper.utils.BeanMapperTraceLogger; import io.beanmapper.utils.Classes; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.*; - /** * This converter facilitates the conversion of an arbitrary amount of Optional wrappers, however, support for complex * datastructures, such as Maps, Sets, List, etc. is limited to a single layer. As such, if the user requires support @@ -101,6 +106,6 @@ private Object convertToCollection(BeanMapper beanMapper, Object source, BeanPro Type[] genericTypes = Classes.getParameteredTypes(beanPropertyMatch.getTarget().getClass(), beanPropertyMatch); return new HashMap<>(beanMapper.map((Map) map, (Class) genericTypes[1])); } - return beanMapper.getConfiguration().getDefaultValueForClass(source.getClass()); + return beanMapper.configuration().getDefaultValueForClass(source.getClass()); } } diff --git a/src/main/java/io/beanmapper/core/converter/impl/PrimitiveConverter.java b/src/main/java/io/beanmapper/core/converter/impl/PrimitiveConverter.java index d07a4721..380e30a3 100644 --- a/src/main/java/io/beanmapper/core/converter/impl/PrimitiveConverter.java +++ b/src/main/java/io/beanmapper/core/converter/impl/PrimitiveConverter.java @@ -9,7 +9,6 @@ import io.beanmapper.BeanMapper; import io.beanmapper.core.BeanPropertyMatch; import io.beanmapper.core.converter.BeanConverter; -import io.beanmapper.utils.Check; /** * Converter between boxed and primitive type. @@ -41,7 +40,7 @@ private static void register(Class boxedClass, Class primitiveClass) { */ @Override public T convert(BeanMapper beanMapper, S source, Class targetClass, BeanPropertyMatch beanPropertyMatch) { - return source != null ? (T) source : beanMapper.getConfiguration().getDefaultValueForClass(targetClass); // Value will automatically be boxed or unboxed + return source != null ? (T) source : beanMapper.configuration().getDefaultValueForClass(targetClass); // Value will automatically be boxed or unboxed } /** diff --git a/src/main/java/io/beanmapper/core/converter/impl/RecordToAnyConverter.java b/src/main/java/io/beanmapper/core/converter/impl/RecordToAnyConverter.java index b5dce05c..358bbb6c 100644 --- a/src/main/java/io/beanmapper/core/converter/impl/RecordToAnyConverter.java +++ b/src/main/java/io/beanmapper/core/converter/impl/RecordToAnyConverter.java @@ -20,7 +20,7 @@ public class RecordToAnyConverter implements BeanConverter { @Override public T convert(BeanMapper beanMapper, S source, Class targetClass, BeanPropertyMatch beanPropertyMatch) { try { - Class intermediaryClass = beanMapper.getConfiguration().getClassStore().getOrCreateGeneratedClass(source.getClass(), + Class intermediaryClass = beanMapper.configuration().getClassStore().getOrCreateGeneratedClass(source.getClass(), List.of(Records.getRecordFieldNames( (Class) source.getClass())), null); Object intermediaryObject = intermediaryClass.cast( diff --git a/src/main/java/io/beanmapper/exceptions/BeanMappingException.java b/src/main/java/io/beanmapper/exceptions/BeanMappingException.java index 2a9e6fd5..8fb3750a 100644 --- a/src/main/java/io/beanmapper/exceptions/BeanMappingException.java +++ b/src/main/java/io/beanmapper/exceptions/BeanMappingException.java @@ -1,6 +1,6 @@ package io.beanmapper.exceptions; -public abstract class BeanMappingException extends MappingException { +public abstract class BeanMappingException extends RuntimeException { protected BeanMappingException(String message) { super(message); diff --git a/src/main/java/io/beanmapper/exceptions/MappingException.java b/src/main/java/io/beanmapper/exceptions/MappingException.java deleted file mode 100644 index 521f910d..00000000 --- a/src/main/java/io/beanmapper/exceptions/MappingException.java +++ /dev/null @@ -1,13 +0,0 @@ -package io.beanmapper.exceptions; - -public abstract class MappingException extends RuntimeException { - - protected MappingException(final String message) { - super(message); - } - - protected MappingException(final String message, final Throwable cause) { - super(message, cause); - } - -} diff --git a/src/main/java/io/beanmapper/strategy/AbstractMapStrategy.java b/src/main/java/io/beanmapper/strategy/AbstractMapStrategy.java index cad07c59..b05f9e58 100644 --- a/src/main/java/io/beanmapper/strategy/AbstractMapStrategy.java +++ b/src/main/java/io/beanmapper/strategy/AbstractMapStrategy.java @@ -101,7 +101,7 @@ private void copySourceToTarget(BeanPropertyMatch beanPropertyMatch) { final Object convertedValue; if (beanPropertyMatch.sourceHasAnnotation(BeanParent.class) || beanPropertyMatch.targetHasAnnotation(BeanParent.class)) { - convertedValue = beanMapper.getConfiguration().getParent(); + convertedValue = beanMapper.configuration().getParent(); } else { convertedValue = convert(copyableSource, beanPropertyMatch.getTargetClass(), beanPropertyMatch); } diff --git a/src/main/java/io/beanmapper/strategy/MapToDynamicClassStrategy.java b/src/main/java/io/beanmapper/strategy/MapToDynamicClassStrategy.java index 64466061..e3de343a 100644 --- a/src/main/java/io/beanmapper/strategy/MapToDynamicClassStrategy.java +++ b/src/main/java/io/beanmapper/strategy/MapToDynamicClassStrategy.java @@ -21,7 +21,7 @@ public T map(S source) { List downsizeTargetFields = getConfiguration().getDownsizeTarget(); // If no collection class is set, but we are dealing with a collection class, make sure it is set - Class collectionClass = getConfiguration().getCollectionClass(); + Class collectionClass = getConfiguration().getCollectionClass(); if (collectionClass == null && Collection.class.isAssignableFrom(source.getClass())) { getConfiguration().setCollectionClass(source.getClass()); } @@ -73,7 +73,7 @@ public T downsizeTarget(S source, List downsizeTargetFields) { getConfiguration().determineTargetClass(), downsizeTargetFields, getConfiguration().getStrictMappingProperties()); - Class collectionClass = getBeanMapper().getConfiguration().getCollectionClass(); + Class collectionClass = getBeanMapper().configuration().getCollectionClass(); return BeanMapperPerformanceLogger.runTimed(() -> getBeanMapper() .wrap() .downsizeTarget(null) diff --git a/src/main/java/io/beanmapper/utils/BeanMapperPerformanceLogger.java b/src/main/java/io/beanmapper/utils/BeanMapperPerformanceLogger.java index 069086b6..f4e6ae48 100644 --- a/src/main/java/io/beanmapper/utils/BeanMapperPerformanceLogger.java +++ b/src/main/java/io/beanmapper/utils/BeanMapperPerformanceLogger.java @@ -12,6 +12,10 @@ public class BeanMapperPerformanceLogger { private static final Logger log = LoggerFactory.getLogger(BeanMapperPerformanceLogger.class); private static final String LOG_TEMPLATE = "Performed operation in {}ms. ({})"; + private BeanMapperPerformanceLogger() { + throw new AssertionError("Cannot instantiate utility-class."); + } + public static void runTimed(String taskName, Runnable task) { Stopwatch stopwatch = Stopwatch.create(); task.run(); diff --git a/src/test/java/io/beanmapper/BeanMapperTest.java b/src/test/java/io/beanmapper/BeanMapperTest.java index 5ca4656f..46e8baf7 100644 --- a/src/test/java/io/beanmapper/BeanMapperTest.java +++ b/src/test/java/io/beanmapper/BeanMapperTest.java @@ -1,5 +1,34 @@ package io.beanmapper; +import static io.beanmapper.utils.diagnostics.DiagnosticsDetailLevel.TREE_COMPLETE; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.PriorityQueue; +import java.util.Queue; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.concurrent.ArrayBlockingQueue; + import io.beanmapper.annotations.BeanCollectionUsage; import io.beanmapper.config.AfterClearFlusher; import io.beanmapper.config.BeanMapperBuilder; @@ -11,18 +40,72 @@ import io.beanmapper.core.converter.impl.LocalDateToLocalDateTime; import io.beanmapper.core.converter.impl.NestedSourceClassToNestedTargetClassConverter; import io.beanmapper.core.converter.impl.ObjectToStringConverter; -import io.beanmapper.exceptions.*; +import io.beanmapper.exceptions.BeanConversionException; +import io.beanmapper.exceptions.BeanMappingException; +import io.beanmapper.exceptions.BeanNoLogicSecuredCheckSetException; +import io.beanmapper.exceptions.BeanNoRoleSecuredCheckSetException; +import io.beanmapper.exceptions.BeanNoSuchPropertyException; +import io.beanmapper.exceptions.FieldShadowingException; import io.beanmapper.shared.ReflectionUtils; import io.beanmapper.testmodel.anonymous.Book; import io.beanmapper.testmodel.anonymous.BookForm; import io.beanmapper.testmodel.beanalias.NestedSourceWithAlias; import io.beanmapper.testmodel.beanalias.SourceWithAlias; import io.beanmapper.testmodel.beanalias.TargetWithAlias; -import io.beanmapper.testmodel.beanproperty.*; -import io.beanmapper.testmodel.beansecuredfield.*; -import io.beanmapper.testmodel.collections.*; -import io.beanmapper.testmodel.collections.target_is_wrapped.*; -import io.beanmapper.testmodel.construct.*; +import io.beanmapper.testmodel.beanproperty.SourceBeanProperty; +import io.beanmapper.testmodel.beanproperty.SourceBeanPropertyWithShadowing; +import io.beanmapper.testmodel.beanproperty.SourceNestedBeanProperty; +import io.beanmapper.testmodel.beanproperty.TargetBeanProperty; +import io.beanmapper.testmodel.beanproperty.TargetBeanPropertyWithShadowing; +import io.beanmapper.testmodel.beanproperty.TargetBeanPropertyWithShadowingNonPublicFieldWithoutSetter; +import io.beanmapper.testmodel.beanproperty.TargetNestedBeanProperty; +import io.beanmapper.testmodel.beansecuredfield.CheckSameNameLogicCheck; +import io.beanmapper.testmodel.beansecuredfield.NeverReturnTrueCheck; +import io.beanmapper.testmodel.beansecuredfield.SFSourceAWithSecuredField; +import io.beanmapper.testmodel.beansecuredfield.SFSourceB; +import io.beanmapper.testmodel.beansecuredfield.SFSourceCWithSecuredMethod; +import io.beanmapper.testmodel.beansecuredfield.SFSourceDLogicSecured; +import io.beanmapper.testmodel.beansecuredfield.SFSourceELogicSecured; +import io.beanmapper.testmodel.beansecuredfield.SFTargetA; +import io.beanmapper.testmodel.beansecuredfield.SFTargetBWithSecuredField; +import io.beanmapper.testmodel.collections.CollSourceClear; +import io.beanmapper.testmodel.collections.CollSourceClearFlush; +import io.beanmapper.testmodel.collections.CollSourceConstruct; +import io.beanmapper.testmodel.collections.CollSourceListIncompleteAnnotation; +import io.beanmapper.testmodel.collections.CollSourceListNotAnnotated; +import io.beanmapper.testmodel.collections.CollSourceMapNotAnnotated; +import io.beanmapper.testmodel.collections.CollSourceNoGenerics; +import io.beanmapper.testmodel.collections.CollSourceReuse; +import io.beanmapper.testmodel.collections.CollSubTargetList; +import io.beanmapper.testmodel.collections.CollTarget; +import io.beanmapper.testmodel.collections.CollTargetEmptyList; +import io.beanmapper.testmodel.collections.CollTargetListNotAnnotated; +import io.beanmapper.testmodel.collections.CollTargetListNotAnnotatedUseSetter; +import io.beanmapper.testmodel.collections.CollTargetMapNotAnnotated; +import io.beanmapper.testmodel.collections.CollTargetNoGenerics; +import io.beanmapper.testmodel.collections.CollectionListSource; +import io.beanmapper.testmodel.collections.CollectionListTarget; +import io.beanmapper.testmodel.collections.CollectionListTargetClear; +import io.beanmapper.testmodel.collections.CollectionMapSource; +import io.beanmapper.testmodel.collections.CollectionMapTarget; +import io.beanmapper.testmodel.collections.CollectionPriorityQueueTarget; +import io.beanmapper.testmodel.collections.CollectionQueueSource; +import io.beanmapper.testmodel.collections.CollectionSetSource; +import io.beanmapper.testmodel.collections.CollectionSetTarget; +import io.beanmapper.testmodel.collections.CollectionSetTargetIncorrectSubtype; +import io.beanmapper.testmodel.collections.CollectionSetTargetSpecificSubtype; +import io.beanmapper.testmodel.collections.SourceWithListGetter; +import io.beanmapper.testmodel.collections.TargetWithListPublicField; +import io.beanmapper.testmodel.collections.target_is_wrapped.SourceWithUnwrappedItems; +import io.beanmapper.testmodel.collections.target_is_wrapped.TargetWithWrappedItems; +import io.beanmapper.testmodel.collections.target_is_wrapped.UnwrappedSource; +import io.beanmapper.testmodel.collections.target_is_wrapped.UnwrappedToWrappedBeanConverter; +import io.beanmapper.testmodel.collections.target_is_wrapped.WrappedTarget; +import io.beanmapper.testmodel.construct.NestedSourceWithoutConstruct; +import io.beanmapper.testmodel.construct.SourceBeanConstructWithList; +import io.beanmapper.testmodel.construct.SourceWithConstruct; +import io.beanmapper.testmodel.construct.TargetBeanConstructWithList; +import io.beanmapper.testmodel.construct.TargetWithoutConstruct; import io.beanmapper.testmodel.construct_not_matching.BigConstructTarget; import io.beanmapper.testmodel.construct_not_matching.BigConstructTarget2; import io.beanmapper.testmodel.construct_not_matching.FlatConstructSource; @@ -40,11 +123,33 @@ import io.beanmapper.testmodel.emptyobject.EmptySource; import io.beanmapper.testmodel.emptyobject.EmptyTarget; import io.beanmapper.testmodel.emptyobject.NestedEmptyTarget; -import io.beanmapper.testmodel.encapsulate.*; +import io.beanmapper.testmodel.encapsulate.Address; +import io.beanmapper.testmodel.encapsulate.Country; +import io.beanmapper.testmodel.encapsulate.House; +import io.beanmapper.testmodel.encapsulate.ResultAddress; +import io.beanmapper.testmodel.encapsulate.ResultManyToMany; +import io.beanmapper.testmodel.encapsulate.ResultManyToOne; +import io.beanmapper.testmodel.encapsulate.ResultOneToMany; import io.beanmapper.testmodel.encapsulate.source_annotated.Car; import io.beanmapper.testmodel.encapsulate.source_annotated.CarDriver; import io.beanmapper.testmodel.encapsulate.source_annotated.Driver; -import io.beanmapper.testmodel.enums.*; +import io.beanmapper.testmodel.enums.ColorEntity; +import io.beanmapper.testmodel.enums.ColorResult; +import io.beanmapper.testmodel.enums.ColorStringResult; +import io.beanmapper.testmodel.enums.ComplexEnumResult; +import io.beanmapper.testmodel.enums.Day; +import io.beanmapper.testmodel.enums.DayEnumSourceArraysAsList; +import io.beanmapper.testmodel.enums.EnumSourceArraysAsList; +import io.beanmapper.testmodel.enums.EnumTargetList; +import io.beanmapper.testmodel.enums.OptionalEnumModel; +import io.beanmapper.testmodel.enums.OptionalEnumResult; +import io.beanmapper.testmodel.enums.RGB; +import io.beanmapper.testmodel.enums.UserRole; +import io.beanmapper.testmodel.enums.UserRoleResult; +import io.beanmapper.testmodel.enums.WeekEntity; +import io.beanmapper.testmodel.enums.WeekResult; +import io.beanmapper.testmodel.enums.WeekStringResult; +import io.beanmapper.testmodel.enums.WithAbstractMethod; import io.beanmapper.testmodel.ignore.IgnoreSource; import io.beanmapper.testmodel.ignore.IgnoreTarget; import io.beanmapper.testmodel.initially_unmatched_source.SourceWithUnmatchedField; @@ -71,7 +176,14 @@ import io.beanmapper.testmodel.numbers.ClassWithLong; import io.beanmapper.testmodel.numbers.SourceWithDouble; import io.beanmapper.testmodel.numbers.TargetWithDouble; -import io.beanmapper.testmodel.optional_getter.*; +import io.beanmapper.testmodel.optional_getter.EntityResultWithMap; +import io.beanmapper.testmodel.optional_getter.EntityWithMap; +import io.beanmapper.testmodel.optional_getter.EntityWithOptional; +import io.beanmapper.testmodel.optional_getter.EntityWithoutOptional; +import io.beanmapper.testmodel.optional_getter.MyEntity; +import io.beanmapper.testmodel.optional_getter.MyEntityResult; +import io.beanmapper.testmodel.optional_getter.MyEntityResultWithNestedOptionalField; +import io.beanmapper.testmodel.optional_getter.MyEntityResultWithOptionalField; import io.beanmapper.testmodel.othername.SourceWithOtherName; import io.beanmapper.testmodel.othername.TargetWithOtherName; import io.beanmapper.testmodel.parent.Player; @@ -97,24 +209,33 @@ import io.beanmapper.testmodel.similar_subclasses.DifferentSource; import io.beanmapper.testmodel.similar_subclasses.DifferentTarget; import io.beanmapper.testmodel.similar_subclasses.SimilarSubclass; -import io.beanmapper.testmodel.strict.*; -import io.beanmapper.testmodel.strict_convention.*; +import io.beanmapper.testmodel.strict.SourceAStrict; +import io.beanmapper.testmodel.strict.SourceBNonStrict; +import io.beanmapper.testmodel.strict.SourceCStrict; +import io.beanmapper.testmodel.strict.SourceDStrict; +import io.beanmapper.testmodel.strict.SourceEForm; +import io.beanmapper.testmodel.strict.SourceF; +import io.beanmapper.testmodel.strict.TargetANonStrict; +import io.beanmapper.testmodel.strict.TargetBStrict; +import io.beanmapper.testmodel.strict.TargetCNonStrict; +import io.beanmapper.testmodel.strict.TargetDNonStrict; +import io.beanmapper.testmodel.strict.TargetE; +import io.beanmapper.testmodel.strict.TargetFResult; +import io.beanmapper.testmodel.strict_convention.SCSourceAForm; +import io.beanmapper.testmodel.strict_convention.SCSourceB; +import io.beanmapper.testmodel.strict_convention.SCSourceCForm; +import io.beanmapper.testmodel.strict_convention.SCTargetA; +import io.beanmapper.testmodel.strict_convention.SCTargetBResult; +import io.beanmapper.testmodel.strict_convention.SCTargetC; import io.beanmapper.testmodel.tostring.SourceWithNonString; import io.beanmapper.testmodel.tostring.TargetWithString; import io.beanmapper.utils.Trinary; import io.beanmapper.utils.diagnostics.tree.DiagnosticsNode; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.*; -import java.util.concurrent.ArrayBlockingQueue; - -import static io.beanmapper.utils.diagnostics.DiagnosticsDetailLevel.TREE_COMPLETE; -import static org.junit.jupiter.api.Assertions.*; - class BeanMapperTest { private BeanMapper beanMapper; @@ -1039,7 +1160,7 @@ void mapWithInnerClass() { @Test void overrideConverterTest() { - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper localBeanMapper = new BeanMapperBuilder() .addPackagePrefix(BeanMapper.class) .build(); @@ -1047,20 +1168,20 @@ void overrideConverterTest() { source.setDiffType(LocalDate.of(2015, 1, 1)); source.setSameType(LocalDate.of(2000, 1, 1)); - TargetWithDateTime target = beanMapper.wrap() + TargetWithDateTime target = localBeanMapper.wrap() .addConverter(new LocalDateToLocalDateTime()) .build() .map(source, TargetWithDateTime.class); assertEquals(target.getDiffType(), LocalDateTime.of(2015, 1, 1, 0, 0)); assertEquals(target.getSameType(), LocalDate.of(2000, 1, 1)); - var exception = assertThrows(BeanConversionException.class, () -> beanMapper.map(source, TargetWithDateTime.class)); + var exception = assertThrows(BeanConversionException.class, () -> localBeanMapper.map(source, TargetWithDateTime.class)); assertEquals("Could not convert LocalDate to LocalDateTime.", exception.getMessage()); } @Test void beanParentDirectDescendantAnnotationOnSource() { - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper localBeanMapper = new BeanMapperBuilder() .addPackagePrefix(BeanMapper.class) .build(); @@ -1069,7 +1190,7 @@ void beanParentDirectDescendantAnnotationOnSource() { form.skill = new SkillForm(); form.skill.name = "Athletics"; - Player player = beanMapper.map(form, Player.class); + Player player = localBeanMapper.map(form, Player.class); assertEquals(form.name, player.getSkill().getPlayer1().getName(), "@BeanParent on source side was not triggered"); assertEquals(form.name, player.getSkill().getPlayer2().getName(), "@BeanParent on target side was not triggered"); @@ -1077,7 +1198,7 @@ void beanParentDirectDescendantAnnotationOnSource() { @Test void beanParentThroughCollection() { - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper localBeanMapper = new BeanMapperBuilder() .addPackagePrefix(BeanMapper.class) .build(); @@ -1091,7 +1212,7 @@ void beanParentThroughCollection() { form.skills.add(new SkillForm()); form.skills.get(2).name = "CLimbing"; - Player player = beanMapper.map(form, Player.class); + Player player = localBeanMapper.map(form, Player.class); assertEquals(form.name, player.getSkills().get(0).getPlayer1().getName()); assertEquals(form.name, player.getSkills().get(1).getPlayer1().getName()); @@ -1100,12 +1221,12 @@ void beanParentThroughCollection() { @Test void numberToNumberInList() { - BeanMapper beanMapper = new BeanMapperBuilder().build(); + BeanMapper localBeanMapper = new BeanMapperBuilder().build(); List numberStrings = new ArrayList<>(); numberStrings.add("1"); - List numbers = beanMapper.map(numberStrings, Integer.class); + List numbers = localBeanMapper.map(numberStrings, Integer.class); assertEquals((Integer) 1, numbers.get(0)); } @@ -1116,9 +1237,9 @@ void referenceCopy() { nestedInSource.setId(42L); source.setLayer4(nestedInSource); - BeanMapper beanMapper = new BeanMapperBuilder().build(); + BeanMapper localBeanMapper = new BeanMapperBuilder().build(); - Layer3 target = beanMapper.map(source, Layer3.class); + Layer3 target = localBeanMapper.map(source, Layer3.class); assertEquals(source.getLayer4(), target.getLayer4()); } @@ -1264,7 +1385,7 @@ void beanCollectionClear() { @Test void beanCollectionClearCallsAfterClearFlusher() throws Exception { AfterClearFlusher afterClearFlusher = createAfterClearFlusher(); - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper localBeanMapper = new BeanMapperBuilder() .addAfterClearFlusher(afterClearFlusher) .build().wrap() .setFlushEnabled(true) @@ -1277,7 +1398,7 @@ void beanCollectionClearCallsAfterClearFlusher() throws Exception { items = new ArrayList<>(); items.add("B"); }}; - beanMapper.map(source, target); + localBeanMapper.map(source, target); assertTrue(afterClearFlusher.getClass().getField("trigger").getBoolean(afterClearFlusher), "Should have called the afterClearFlusher instance"); } @@ -1285,7 +1406,7 @@ void beanCollectionClearCallsAfterClearFlusher() throws Exception { @Test void beanCollectionClearDoesNotCallFlusher() throws Exception { AfterClearFlusher afterClearFlusher = createAfterClearFlusher(); - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper localBeanMapper = new BeanMapperBuilder() .addAfterClearFlusher(afterClearFlusher) .build(); CollSourceClear source = new CollSourceClear() {{ @@ -1295,7 +1416,7 @@ void beanCollectionClearDoesNotCallFlusher() throws Exception { items = new ArrayList<>(); items.add("B"); }}; - beanMapper.map(source, target); + localBeanMapper.map(source, target); assertFalse(afterClearFlusher.getClass().getField("trigger").getBoolean(afterClearFlusher), "Should NOT have called the afterClearFlusher instance"); } @@ -1358,10 +1479,10 @@ void anonymousClass() { @Test void beanMapper_shouldMapFieldsFromSuperclass() { - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper localBeanMapper = new BeanMapperBuilder() .setApplyStrictMappingConvention(false) .build(); - UserRoleResult result = beanMapper.map(UserRole.ADMIN, UserRoleResult.class); + UserRoleResult result = localBeanMapper.map(UserRole.ADMIN, UserRoleResult.class); assertEquals(UserRole.ADMIN.name(), result.name); } @@ -1392,7 +1513,7 @@ void beanPropertyNestedMismatch() { @Test void wrap_mustAlwaysWrap() { - assertNotSame(beanMapper.getConfiguration(), beanMapper.wrap().build().getConfiguration()); + assertNotSame(beanMapper.configuration(), beanMapper.wrap().build().configuration()); } @Test @@ -1417,35 +1538,35 @@ void securedTargetFieldNoAccess() { @Test void securedSourceMethodNoAccess() { - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper localBeanMapper = new BeanMapperBuilder() .setSecuredPropertyHandler(roles -> false) .build(); SFSourceCWithSecuredMethod source = new SFSourceCWithSecuredMethod() {{ setName("Henk"); }}; - SFTargetA target = beanMapper.map(source, SFTargetA.class); + SFTargetA target = localBeanMapper.map(source, SFTargetA.class); assertNull(target.name); } private void assertSecuredSourceField(RoleSecuredCheck roleSecuredCheck, String expectedName) { - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper localBeanMapper = new BeanMapperBuilder() .setSecuredPropertyHandler(roleSecuredCheck) .build(); SFSourceAWithSecuredField source = new SFSourceAWithSecuredField() {{ name = "Henk"; }}; - SFTargetA target = beanMapper.map(source, SFTargetA.class); + SFTargetA target = localBeanMapper.map(source, SFTargetA.class); assertEquals(expectedName, target.name); } private void assertSecuredTargetField(RoleSecuredCheck roleSecuredCheck, String expectedName) { - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper localBeanMapper = new BeanMapperBuilder() .setSecuredPropertyHandler(roleSecuredCheck) .build(); SFSourceB source = new SFSourceB() {{ name = "Henk"; }}; - SFTargetBWithSecuredField target = beanMapper.map(source, SFTargetBWithSecuredField.class); + SFTargetBWithSecuredField target = localBeanMapper.map(source, SFTargetBWithSecuredField.class); assertEquals(expectedName, target.name); } @@ -1459,25 +1580,25 @@ void throwExceptionWhenSecuredPropertyDoesNotHaveAHandler() { @Test void allowSecuredPropertyDoesNotHaveAHandler() { - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper localBeanMapper = new BeanMapperBuilder() .setEnforcedSecuredProperties(false) .build(); SFSourceAWithSecuredField source = new SFSourceAWithSecuredField() {{ name = "Henk"; }}; - SFTargetA target = beanMapper.map(source, SFTargetA.class); + SFTargetA target = localBeanMapper.map(source, SFTargetA.class); assertEquals("Henk", target.name); } @Test void logicSecuredCheckMustBlock() { - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper localBeanMapper = new BeanMapperBuilder() .addLogicSecuredCheck(new NeverReturnTrueCheck()) .build(); SFSourceDLogicSecured source = new SFSourceDLogicSecured() {{ name = "Henk"; }}; - SFTargetA target = beanMapper.map(source, SFTargetA.class); + SFTargetA target = localBeanMapper.map(source, SFTargetA.class); assertNull(target.name); } @@ -1492,13 +1613,13 @@ void logicSecuredCheckMustAllowBecauseEqualName() { } private void logicCheckForEqualName(String initialName, String expectedName) { - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper localBeanMapper = new BeanMapperBuilder() .addLogicSecuredCheck(new CheckSameNameLogicCheck()) .build(); SFSourceELogicSecured source = new SFSourceELogicSecured() {{ name = initialName; }}; - SFTargetA target = beanMapper.map(source, SFTargetA.class); + SFTargetA target = localBeanMapper.map(source, SFTargetA.class); assertEquals(expectedName, target.name); } @@ -1512,7 +1633,7 @@ void logicSecuredMissingCheck() { @Test void unwrappedToWrapped() { - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper localBeanMapper = new BeanMapperBuilder() .addConverter(new UnwrappedToWrappedBeanConverter()) .addBeanPairWithStrictSource(SourceWithUnwrappedItems.class, TargetWithWrappedItems.class) .build(); @@ -1522,7 +1643,7 @@ void unwrappedToWrapped() { source.items.add(UnwrappedSource.ALPHA); TargetWithWrappedItems target = new TargetWithWrappedItems(); List targetItems = target.getItems(); - target = beanMapper.map(source, target); + target = localBeanMapper.map(source, target); assertEquals(targetItems, target.getItems()); assertEquals(source.items.get(0), target.getItems().get(0).getElement()); assertEquals(source.items.get(1), target.getItems().get(1).getElement()); @@ -1531,14 +1652,14 @@ void unwrappedToWrapped() { @Test void emptyListToExistingList() { - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper localBeanMapper = new BeanMapperBuilder() .addConverter(new UnwrappedToWrappedBeanConverter()) .build(); SourceWithUnwrappedItems source = new SourceWithUnwrappedItems(); source.items = null; TargetWithWrappedItems target = new TargetWithWrappedItems(); List targetItems = target.getItems(); - target = beanMapper.map(source, target); + target = localBeanMapper.map(source, target); assertEquals(targetItems, target.getItems()); } @@ -1845,7 +1966,7 @@ void testMapObjectContainingOptionalOfEnumToObjectContainingOptionalOfTheSameEnu void testDiagnosticsCreatesExpectedTree() { beanMapper = beanMapper.wrap(TREE_COMPLETE).build(); beanMapper.map(createMyEntity(), MyEntityResult.class); - DiagnosticsConfiguration dc = (DiagnosticsConfiguration) beanMapper.getConfiguration(); + DiagnosticsConfiguration dc = (DiagnosticsConfiguration) beanMapper.configuration(); DiagnosticsNode root = dc.getBeanMapperDiagnostics().orElse(null); assertNotNull(root); assertEquals(0, root.getDepth()); @@ -1857,7 +1978,7 @@ void testRootDiagnosticsNodeHasExactlyOneChild() { beanMapper = beanMapper.wrap(TREE_COMPLETE).build(); beanMapper.map(createMyEntity(), MyEntityResult.class); beanMapper.map(createPerson(), PersonResult.class); - DiagnosticsConfiguration dc = (DiagnosticsConfiguration) beanMapper.getConfiguration(); + DiagnosticsConfiguration dc = (DiagnosticsConfiguration) beanMapper.configuration(); assertEquals(1, dc.getBeanMapperDiagnostics().orElse(null).getDiagnostics().size()); } diff --git a/src/test/java/io/beanmapper/config/BeanMapperBuilderTest.java b/src/test/java/io/beanmapper/config/BeanMapperBuilderTest.java index 893f21ab..ded07d47 100644 --- a/src/test/java/io/beanmapper/config/BeanMapperBuilderTest.java +++ b/src/test/java/io/beanmapper/config/BeanMapperBuilderTest.java @@ -19,15 +19,22 @@ import io.beanmapper.strategy.ConstructorArguments; import io.beanmapper.utils.Trinary; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; class BeanMapperBuilderTest { + private BeanMapperBuilder builder; + + @BeforeEach + void setup() { + builder = new BeanMapperBuilder(); + } + @Test void setTargetClassOnCoreThrowsException() { assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - BeanMapperBuilder builder = new BeanMapperBuilder(); builder.setTargetClass(null); }); } @@ -35,7 +42,6 @@ void setTargetClassOnCoreThrowsException() { @Test void setCollectionUsage() { assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - BeanMapperBuilder builder = new BeanMapperBuilder(); builder.setCollectionUsage(null); }); } @@ -43,7 +49,6 @@ void setCollectionUsage() { @Test void setPreferredCollectionClass() { assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - BeanMapperBuilder builder = new BeanMapperBuilder(); builder.setPreferredCollectionClass(null); }); } @@ -51,7 +56,6 @@ void setPreferredCollectionClass() { @Test void setFlushAfterClear() { assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - BeanMapperBuilder builder = new BeanMapperBuilder(); builder.setFlushAfterClear(Trinary.ENABLED); }); } @@ -59,7 +63,6 @@ void setFlushAfterClear() { @Test void setTargetOnCoreThrowsException() { assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - BeanMapperBuilder builder = new BeanMapperBuilder(); builder.setTarget(null); }); } @@ -67,7 +70,6 @@ void setTargetOnCoreThrowsException() { @Test void setDownsizeSourceOnCoreThrowsException() { assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - BeanMapperBuilder builder = new BeanMapperBuilder(); builder.downsizeSource(null); }); } @@ -75,7 +77,6 @@ void setDownsizeSourceOnCoreThrowsException() { @Test void setDownsizeTargetOnCoreThrowsException() { assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - BeanMapperBuilder builder = new BeanMapperBuilder(); builder.downsizeTarget(null); }); } @@ -83,44 +84,43 @@ void setDownsizeTargetOnCoreThrowsException() { @Test void setCollectionClassOnCoreThrowsException() { assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - BeanMapperBuilder builder = new BeanMapperBuilder(); builder.setCollectionClass(null); }); } @Test void withoutDefaultConverters() { - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper beanMapper = builder .withoutDefaultConverters() .build(); - assertEquals(0, beanMapper.getConfiguration().getBeanConverters().size()); + assertEquals(0, beanMapper.configuration().getBeanConverters().size()); } @Test void addCollectionHandler() { - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper beanMapper = builder .addCollectionHandler(new ListCollectionHandler()) .build(); - assertEquals(5, beanMapper.getConfiguration().getCollectionHandlers().size()); + assertEquals(5, beanMapper.configuration().getCollectionHandlers().size()); } @Test void setProxySkipClass() { - Class expectedClass = Collections.EMPTY_LIST.getClass(); - BeanMapper beanMapper = new BeanMapperBuilder() + Class expectedClass = Collections.emptyList().getClass(); + BeanMapper beanMapper = builder .addProxySkipClass(expectedClass) .build(); - assertEquals(expectedClass, beanMapper.getConfiguration().getBeanUnproxy().unproxy(expectedClass)); + assertEquals(expectedClass, beanMapper.configuration().getBeanUnproxy().unproxy(expectedClass)); } @Test void addPackagePrefix() { String expectedPackagePrefix = "io.beanmapper.dummie"; - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper beanMapper = builder .addPackagePrefix(expectedPackagePrefix) .build(); - List packagePrefixes = beanMapper.getConfiguration().getPackagePrefixes(); - assertEquals(expectedPackagePrefix, packagePrefixes.get(0)); + List packagePrefixes = beanMapper.configuration().getPackagePrefixes(); + assertEquals(expectedPackagePrefix, packagePrefixes.getFirst()); } @Test @@ -131,80 +131,80 @@ public T instantiate(Class beanClass, ConstructorArguments arguments) { return null; } }; - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper beanMapper = builder .setBeanInitializer(expectedBeanInitializer) .build(); - assertEquals(expectedBeanInitializer, beanMapper.getConfiguration().getBeanInitializer()); + assertEquals(expectedBeanInitializer, beanMapper.configuration().getBeanInitializer()); } @Test @Disabled("BeanUnproxy should not be used as a Converter.") void setBeanUnproxy() { final BeanUnproxy expectedBeanUnproxy = beanClass -> Long.class; - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper beanMapper = builder .setBeanUnproxy(expectedBeanUnproxy) .build(); - assertEquals(Long.class, beanMapper.getConfiguration().getBeanUnproxy().unproxy(String.class)); + assertEquals(Long.class, beanMapper.configuration().getBeanUnproxy().unproxy(String.class)); } @Test void isConverterChoosableForCoreConfig() { - BeanMapper beanMapper = new BeanMapperBuilder().build(); - assertFalse(beanMapper.getConfiguration().isConverterChoosable(), + BeanMapper beanMapper = builder.build(); + assertFalse(beanMapper.configuration().isConverterChoosable(), "The Core configuration assumes that a top-level call always assumes a pure mapping (ie, not using converters)" ); } @Test void isConverterChoosableSettableForCoreConfig() { - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper beanMapper = builder .setConverterChoosable(true) .build(); - assertTrue(beanMapper.getConfiguration().isConverterChoosable(), + assertTrue(beanMapper.configuration().isConverterChoosable(), "The Core configuration converterChoosable is settable)" ); } @Test void isConverterChoosableCustomForOverrideConfig() { - BeanMapper beanMapper = new BeanMapperBuilder().build(); // Core wrap + BeanMapper beanMapper = builder.build(); // Core wrap beanMapper = beanMapper .wrap() .setConverterChoosable(false) // <<< override the converter choosable option here .build(); // Override wrap - assertFalse(beanMapper.getConfiguration().isConverterChoosable(), + assertFalse(beanMapper.configuration().isConverterChoosable(), "The Override configuration has a custom override for the converter choosable option, which should be false"); } @Test void newConfigOnOverrideLeadsToExistingConfig() { - BeanMapper beanMapper = new BeanMapperBuilder().build(); // Core wrap + BeanMapper beanMapper = builder.build(); // Core wrap beanMapper = beanMapper.wrap().build(); // Wrap in an override wrap - Configuration currentConfiguration = beanMapper.getConfiguration(); + Configuration currentConfiguration = beanMapper.configuration(); beanMapper = beanMapper.wrap().build(); // <<< explicitly wrap in an override wrap assertNotSame( - currentConfiguration, beanMapper.getConfiguration(), "The configuration must be a new one from the one we already had"); + currentConfiguration, beanMapper.configuration(), "The configuration must be a new one from the one we already had"); } @Test void strictMappingConventionForCoreConfig() { - BeanMapper beanMapper = new BeanMapperBuilder() + BeanMapper beanMapper = builder .setStrictSourceSuffix("Frm") .setStrictTargetSuffix("Rslt") .build(); // Core wrap - Configuration currentConfiguration = beanMapper.getConfiguration(); + Configuration currentConfiguration = beanMapper.configuration(); assertEquals("Frm", currentConfiguration.getStrictSourceSuffix()); assertEquals("Rslt", currentConfiguration.getStrictTargetSuffix()); } @Test void strictMappingConventionForOverrideConfig() { - BeanMapper beanMapper = new BeanMapperBuilder().build(); // Core wrap + BeanMapper beanMapper = builder.build(); // Core wrap beanMapper = beanMapper.wrap() .setStrictSourceSuffix("Frm") .build(); // Wrap in an override wrap - Configuration currentConfiguration = beanMapper.getConfiguration(); + Configuration currentConfiguration = beanMapper.configuration(); assertEquals("Frm", currentConfiguration.getStrictMappingProperties().getStrictSourceSuffix()); assertEquals("Result", @@ -214,18 +214,18 @@ void strictMappingConventionForOverrideConfig() { @Test void cleanConfig() { - BeanMapper beanMapper = new BeanMapperBuilder().build(); // Core wrap + BeanMapper beanMapper = builder.build(); // Core wrap beanMapper = wrapAndSetFieldsForSingleRun(beanMapper); beanMapper = wrapAndSetFieldsForSingleRun(beanMapper); // Wrap it twice to make sure we have a parent // override wrap with the fields all set - assertNotNull(beanMapper.getConfiguration().getCollectionClass(), "Container class must be set"); - assertNotNull(beanMapper.getConfiguration().getTargetClass(), "Target class must be set"); - assertNotNull(beanMapper.getConfiguration().getTarget(), "Target must be set"); + assertNotNull(beanMapper.configuration().getCollectionClass(), "Container class must be set"); + assertNotNull(beanMapper.configuration().getTargetClass(), "Target class must be set"); + assertNotNull(beanMapper.configuration().getTarget(), "Target must be set"); beanMapper = beanMapper.wrap().build(); - assertNull(beanMapper.getConfiguration().getCollectionClass(), "Container class must be cleared"); - assertNull(beanMapper.getConfiguration().getTargetClass(), "Target class must be cleared"); - assertNull(beanMapper.getConfiguration().getTarget(), "Target must be cleared"); + assertNull(beanMapper.configuration().getCollectionClass(), "Container class must be cleared"); + assertNull(beanMapper.configuration().getTargetClass(), "Target class must be cleared"); + assertNull(beanMapper.configuration().getTarget(), "Target must be cleared"); } private BeanMapper wrapAndSetFieldsForSingleRun(BeanMapper beanMapper) { diff --git a/src/test/java/io/beanmapper/config/CollectionHandlerStoreTest.java b/src/test/java/io/beanmapper/config/CollectionHandlerStoreTest.java index 14503e25..67acd350 100644 --- a/src/test/java/io/beanmapper/config/CollectionHandlerStoreTest.java +++ b/src/test/java/io/beanmapper/config/CollectionHandlerStoreTest.java @@ -11,7 +11,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class CollectionHandlerStoreTest { +class CollectionHandlerStoreTest { private Configuration configuration; @@ -19,7 +19,7 @@ public class CollectionHandlerStoreTest { public void setup() { BeanMapper beanMapper = new BeanMapperBuilder() .build(); - configuration = beanMapper.getConfiguration(); + configuration = beanMapper.configuration(); } @Test @@ -39,7 +39,9 @@ void getCollectionHandlerFor_List() { @Test void getCollectionHandlerFor_AnonymousClass() { - assertEquals(List.class, configuration.getCollectionHandlerFor(new ArrayList() {{}}.getClass()).getType()); + assertEquals(List.class, configuration.getCollectionHandlerFor(new ArrayList() {{ + // Empty specifically to make it an anonymous class. + }}.getClass()).getType()); } } diff --git a/src/test/java/io/beanmapper/config/OverrideConfigurationTest.java b/src/test/java/io/beanmapper/config/OverrideConfigurationTest.java index 93644e04..8ebe7f59 100644 --- a/src/test/java/io/beanmapper/config/OverrideConfigurationTest.java +++ b/src/test/java/io/beanmapper/config/OverrideConfigurationTest.java @@ -18,7 +18,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class OverrideConfigurationTest { +class OverrideConfigurationTest { private CoreConfiguration coreConfiguration; @@ -28,7 +28,7 @@ public class OverrideConfigurationTest { void setup() { BeanMapper beanMapper = new BeanMapperBuilder() .build(); - coreConfiguration = (CoreConfiguration) beanMapper.getConfiguration(); + coreConfiguration = (CoreConfiguration) beanMapper.configuration(); overrideConfiguration = new OverrideConfiguration(coreConfiguration); } diff --git a/src/test/java/io/beanmapper/config/StrictMappingPropertiesTest.java b/src/test/java/io/beanmapper/config/StrictMappingPropertiesTest.java index db56474b..c6537fbc 100644 --- a/src/test/java/io/beanmapper/config/StrictMappingPropertiesTest.java +++ b/src/test/java/io/beanmapper/config/StrictMappingPropertiesTest.java @@ -19,7 +19,7 @@ class StrictMappingPropertiesTest { void setup() { BeanMapper beanMapper = new BeanMapperBuilder() .build(); - coreConfiguration = (CoreConfiguration) beanMapper.getConfiguration(); + coreConfiguration = (CoreConfiguration) beanMapper.configuration(); } @Test diff --git a/src/test/java/io/beanmapper/core/converter/AbstractBeanConverterTest.java b/src/test/java/io/beanmapper/core/converter/AbstractBeanConverterTest.java index d9b71a41..b3132d3b 100644 --- a/src/test/java/io/beanmapper/core/converter/AbstractBeanConverterTest.java +++ b/src/test/java/io/beanmapper/core/converter/AbstractBeanConverterTest.java @@ -40,7 +40,8 @@ void testInvalidSource() { @Test void testInvalidTarget() { - assertThrows(IllegalArgumentException.class, () -> converter.convert(null, LocalDateTime.now(), String.class, null)); + LocalDateTime time = LocalDateTime.now(); + assertThrows(IllegalArgumentException.class, () -> converter.convert(null, time, String.class, null)); } } diff --git a/src/test/java/io/beanmapper/core/converter/collections/AnnotationClassTest.java b/src/test/java/io/beanmapper/core/converter/collections/AnnotationClassTest.java index 903a27d1..581c7549 100644 --- a/src/test/java/io/beanmapper/core/converter/collections/AnnotationClassTest.java +++ b/src/test/java/io/beanmapper/core/converter/collections/AnnotationClassTest.java @@ -12,21 +12,21 @@ class AnnotationClassTest { @Test void nullClass() { AnnotationClass annotationClass = new AnnotationClass(null); - assertNull(annotationClass.getAnnotationClass()); + assertNull(annotationClass.annotationClass()); assertTrue(annotationClass.isEmpty()); } @Test void voidClass() { AnnotationClass annotationClass = new AnnotationClass(void.class); - assertNull(annotationClass.getAnnotationClass()); + assertNull(annotationClass.annotationClass()); assertTrue(annotationClass.isEmpty()); } @Test void normalClass() { AnnotationClass annotationClass = new AnnotationClass(String.class); - assertEquals(String.class, annotationClass.getAnnotationClass()); + assertEquals(String.class, annotationClass.annotationClass()); assertFalse(annotationClass.isEmpty()); } diff --git a/src/test/java/io/beanmapper/core/converter/collections/BeanCollectionInstructionsTest.java b/src/test/java/io/beanmapper/core/converter/collections/BeanCollectionInstructionsTest.java index 5c2cf650..eeffd196 100644 --- a/src/test/java/io/beanmapper/core/converter/collections/BeanCollectionInstructionsTest.java +++ b/src/test/java/io/beanmapper/core/converter/collections/BeanCollectionInstructionsTest.java @@ -81,7 +81,7 @@ void sourceSideSuppliesInstructionsAndTargetSideGeneric() { assertNotNull(merged); assertEquals(Long.class, merged.getCollectionElementType().getType()); assertEquals(BeanCollectionUsage.REUSE, merged.getBeanCollectionUsage()); - assertEquals(ArrayList.class, merged.getPreferredCollectionClass().getAnnotationClass()); + assertEquals(ArrayList.class, merged.getPreferredCollectionClass().annotationClass()); assertEquals(Trinary.DISABLED, merged.getFlushAfterClear()); } diff --git a/src/test/java/io/beanmapper/core/converter/impl/OptionalToObjectConverterTest.java b/src/test/java/io/beanmapper/core/converter/impl/OptionalToObjectConverterTest.java index 2c6cf6b3..e8f72a2e 100644 --- a/src/test/java/io/beanmapper/core/converter/impl/OptionalToObjectConverterTest.java +++ b/src/test/java/io/beanmapper/core/converter/impl/OptionalToObjectConverterTest.java @@ -144,7 +144,7 @@ void convertListWithoutOptionalToListOfWithOptional() { assertEquals(list.size(), listOfLong.size()); assertTrue(unoReversedList.contains(Optional.of(42))); assertTrue(unoReversedList.contains(Optional.of(23))); - assertTrue(unoReversedList.contains(Optional.of(this.beanMapper.getConfiguration().getDefaultValueForClass(Integer.TYPE)))); + assertTrue(unoReversedList.contains(Optional.of(this.beanMapper.configuration().getDefaultValueForClass(Integer.TYPE)))); } @Test diff --git a/src/test/java/io/beanmapper/dynclass/AbstractConcurrentTest.java b/src/test/java/io/beanmapper/dynclass/AbstractConcurrentTest.java index c0dea39e..7cf440f3 100644 --- a/src/test/java/io/beanmapper/dynclass/AbstractConcurrentTest.java +++ b/src/test/java/io/beanmapper/dynclass/AbstractConcurrentTest.java @@ -1,5 +1,7 @@ package io.beanmapper.dynclass; +import static org.junit.jupiter.api.Assertions.assertTrue; + /** * Utility test class to spin up threads with a runnable and wait for them to finish. */ @@ -17,4 +19,21 @@ protected void run(int threads, Runnable r) throws InterruptedException { thread.join(); } } + + protected void runVirtual(int threads, Runnable r) throws InterruptedException { + // Run runnables as Virtual Threads + Thread[] tr = new Thread[threads]; + for (int t = 0; t < tr.length; t++) { + tr[t] = Thread.ofVirtual().name("VirtualThread %d".formatted(t)).unstarted(r); + } + + for (Thread thread : tr) { + assertTrue(thread.isVirtual()); + thread.start(); + } + + for (Thread thread : tr) { + thread.join(); + } + } } diff --git a/src/test/java/io/beanmapper/dynclass/ClassGeneratorTest.java b/src/test/java/io/beanmapper/dynclass/ClassGeneratorTest.java index 3932d030..e89e177f 100644 --- a/src/test/java/io/beanmapper/dynclass/ClassGeneratorTest.java +++ b/src/test/java/io/beanmapper/dynclass/ClassGeneratorTest.java @@ -26,7 +26,7 @@ void shouldNotFailConcurrently() throws Exception { Node.createTree(Collections.singletonList("name")), new BeanMapperBuilder() .build() - .getConfiguration() + .configuration() .getStrictMappingProperties()); Thread.yield(); } @@ -39,4 +39,30 @@ void shouldNotFailConcurrently() throws Exception { assertTrue(results.isEmpty(), "%d".formatted(results.size())); // Class generation should produce zero exceptions. } + + @Test + void shouldNotFailConcurrentlyVirtualThreads() throws InterruptedException { + final ClassGenerator gen = new ClassGenerator(new ClassPool(true)); + final List results = Collections.synchronizedList(new ArrayList<>()); + final Runnable r = () -> { + try { + for (int t = 0; t < 1000; t++) { + gen.createClass( + Person.class, + Node.createTree(Collections.singletonList("name")), + new BeanMapperBuilder() + .build() + .configuration() + .getStrictMappingProperties()); + Thread.yield(); + } + } catch (Throwable ex) { + results.add(ex); + } + }; + + runVirtual(8, r); + + assertTrue(results.isEmpty(), "%d".formatted(results.size())); + } } diff --git a/src/test/java/io/beanmapper/dynclass/ClassStoreTest.java b/src/test/java/io/beanmapper/dynclass/ClassStoreTest.java index 659d325b..32b5d1ae 100644 --- a/src/test/java/io/beanmapper/dynclass/ClassStoreTest.java +++ b/src/test/java/io/beanmapper/dynclass/ClassStoreTest.java @@ -30,7 +30,7 @@ void shouldCacheThreadSafe() throws InterruptedException { Collections.synchronizedList(Collections.singletonList("name")), new BeanMapperBuilder() .build() - .getConfiguration() + .configuration() .getStrictMappingProperties()))); assertEquals(1, results.size()); // A thread safe implementation should return one class. } diff --git a/src/test/java/io/beanmapper/exceptions/BeanInstantiationExceptionTest.java b/src/test/java/io/beanmapper/exceptions/BeanInstantiationExceptionTest.java index d07efa0c..a4ac6c21 100644 --- a/src/test/java/io/beanmapper/exceptions/BeanInstantiationExceptionTest.java +++ b/src/test/java/io/beanmapper/exceptions/BeanInstantiationExceptionTest.java @@ -9,7 +9,7 @@ class BeanInstantiationExceptionTest { @Test - void throwException() throws NoSuchFieldException { + void throwException() { try { throw new BeanInstantiationException(SourceWithDefaults.class, null); } catch (BeanMappingException e) { diff --git a/src/test/java/io/beanmapper/strategy/MapToRecordStrategyTest.java b/src/test/java/io/beanmapper/strategy/MapToRecordStrategyTest.java index e3c97378..c50eda85 100644 --- a/src/test/java/io/beanmapper/strategy/MapToRecordStrategyTest.java +++ b/src/test/java/io/beanmapper/strategy/MapToRecordStrategyTest.java @@ -202,7 +202,7 @@ void testMapRecordToRecordWithMoreFields() { var result = this.beanMapper.map(form, ResultRecordWithIdAndName.class); assertEquals(form.name(), result.name()); - assertEquals((int) this.beanMapper.getConfiguration().getDefaultValueForClass(int.class), result.id()); + assertEquals((int) this.beanMapper.configuration().getDefaultValueForClass(int.class), result.id()); } @Test diff --git a/src/test/java/io/beanmapper/utils/diagnostics/logging/CountPerPairDiagnosticsLoggerTest.java b/src/test/java/io/beanmapper/utils/diagnostics/logging/CountPerPairDiagnosticsLoggerTest.java index 2ef13feb..f1dee331 100644 --- a/src/test/java/io/beanmapper/utils/diagnostics/logging/CountPerPairDiagnosticsLoggerTest.java +++ b/src/test/java/io/beanmapper/utils/diagnostics/logging/CountPerPairDiagnosticsLoggerTest.java @@ -29,7 +29,7 @@ void testCountPerPairDiagnosticsShouldReturnPrintCorrectCounts() { """; beanMapper = beanMapper.wrap(DiagnosticsDetailLevel.COUNT_PER_PAIR).build(); - (((DiagnosticsConfiguration) beanMapper.getConfiguration()).getDiagnosticsLogger().orElseThrow()).getLogger().addHandler(handler); + (((DiagnosticsConfiguration) beanMapper.configuration()).getDiagnosticsLogger().orElseThrow()).getLogger().addHandler(handler); beanMapper.map(new PersonRecord(1, "Henk"), PersonResultRecord.class); handler.flush(); String output = outputStreamMock.toString(); @@ -55,7 +55,7 @@ void testCountPerPairDiagnosticsShouldReturnPrintCorrectCountsForList() { """; beanMapper = beanMapper.wrap(DiagnosticsDetailLevel.COUNT_PER_PAIR).build(); - (((DiagnosticsConfiguration) beanMapper.getConfiguration()).getDiagnosticsLogger().orElseThrow()).getLogger().addHandler(handler); + (((DiagnosticsConfiguration) beanMapper.configuration()).getDiagnosticsLogger().orElseThrow()).getLogger().addHandler(handler); beanMapper.map(new ArrayList<>(List.of(new PersonRecord(1, "Henk"))), PersonResultRecord.class); handler.flush(); String output = outputStreamMock.toString(); @@ -86,7 +86,7 @@ void testCountForComplexDiagnostics() { """; beanMapper = beanMapper.wrap(DiagnosticsDetailLevel.COUNT_PER_PAIR).build(); - (((DiagnosticsConfiguration) beanMapper.getConfiguration()).getDiagnosticsLogger().orElseThrow()).getLogger().addHandler(handler); + (((DiagnosticsConfiguration) beanMapper.configuration()).getDiagnosticsLogger().orElseThrow()).getLogger().addHandler(handler); beanMapper.map( new ArrayList<>(List.of(new CollectionListSource() {{items.add(new Person());}}, new CollectionListSource() {{items.add(new Person());}})), CollectionListTarget.class); diff --git a/src/test/java/io/beanmapper/utils/diagnostics/logging/CountTotalDiagnosticsLoggerTest.java b/src/test/java/io/beanmapper/utils/diagnostics/logging/CountTotalDiagnosticsLoggerTest.java index dd0d7c0e..0e69df6f 100644 --- a/src/test/java/io/beanmapper/utils/diagnostics/logging/CountTotalDiagnosticsLoggerTest.java +++ b/src/test/java/io/beanmapper/utils/diagnostics/logging/CountTotalDiagnosticsLoggerTest.java @@ -19,7 +19,7 @@ void testTotalDiagnosticsLoggerPrintsCorrectCount() { INFO: [Mapping ] io.beanmapper.testmodel.record.PersonRecord -> io.beanmapper.testmodel.record.PersonResultRecord {total mappings: 2, total conversions: 0, max depth: 2} (CountTotalDiagnosticsLoggerTest.java:18) """; beanMapper = beanMapper.wrap(COUNT_TOTAL).build(); - (((DiagnosticsConfiguration) beanMapper.getConfiguration()).getDiagnosticsLogger().orElseThrow()).getLogger().addHandler(handler); + (((DiagnosticsConfiguration) beanMapper.configuration()).getDiagnosticsLogger().orElseThrow()).getLogger().addHandler(handler); beanMapper.map(new PersonRecord(1, "Henk"), PersonResultRecord.class); handler.flush(); diff --git a/src/test/java/io/beanmapper/utils/diagnostics/logging/TreeCompleteDiagnosticsLogger.java b/src/test/java/io/beanmapper/utils/diagnostics/logging/TreeCompleteDiagnosticsLogger.java index 0d8df772..57162e00 100644 --- a/src/test/java/io/beanmapper/utils/diagnostics/logging/TreeCompleteDiagnosticsLogger.java +++ b/src/test/java/io/beanmapper/utils/diagnostics/logging/TreeCompleteDiagnosticsLogger.java @@ -35,7 +35,7 @@ void testCompleteTreePrintsCorrectTree() { """; beanMapper = beanMapper.wrap(TREE_COMPLETE).build(); - ((DiagnosticsConfiguration) beanMapper.getConfiguration()).getDiagnosticsLogger().orElseThrow().getLogger().addHandler(handler); + ((DiagnosticsConfiguration) beanMapper.configuration()).getDiagnosticsLogger().orElseThrow().getLogger().addHandler(handler); beanMapper.map(Layer1.createNestedClassObject(), Layer1Result.class); handler.flush(); @@ -65,12 +65,11 @@ void testCompleteTreePrintsCorrectTreeWhenConvertingMap() { """; beanMapper = beanMapper.wrap(TREE_COMPLETE).build(); - ((DiagnosticsConfiguration) beanMapper.getConfiguration()).getDiagnosticsLogger().orElseThrow().getLogger().addHandler(handler); + ((DiagnosticsConfiguration) beanMapper.configuration()).getDiagnosticsLogger().orElseThrow().getLogger().addHandler(handler); beanMapper.map(new CollectionMapSource() {{items.put("henk", new Person());}}, CollectionMapTarget.class); handler.flush(); String output = outputStreamMock.toString(); -// String[] outputLines = output.lines().toArray(String[]::new); assertEquals(12, output.split("\n").length); for (String s : outputTemplate.split("\n")) { assertTrue(output.contains(s)); From 66d1ecf7a10757a126aea5df4e0d342e4ed5eda0 Mon Sep 17 00:00:00 2001 From: Marcus Talbot Date: Mon, 2 Dec 2024 14:35:34 +0100 Subject: [PATCH 2/3] Improve test-coverage --- .../beanmapper/core/unproxy/BeanUnproxy.java | 3 ++ .../core/unproxy/SkippingBeanUnproxy.java | 4 ++ .../utils/BeanMapperTraceLogger.java | 4 ++ .../config/BeanMapperBuilderTest.java | 50 +++++++++++++++++++ 4 files changed, 61 insertions(+) diff --git a/src/main/java/io/beanmapper/core/unproxy/BeanUnproxy.java b/src/main/java/io/beanmapper/core/unproxy/BeanUnproxy.java index 6f6680ba..28f35369 100644 --- a/src/main/java/io/beanmapper/core/unproxy/BeanUnproxy.java +++ b/src/main/java/io/beanmapper/core/unproxy/BeanUnproxy.java @@ -18,4 +18,7 @@ public interface BeanUnproxy { */ Class unproxy(Class beanClass); + default BeanUnproxy getDelegate() { + return null; + } } diff --git a/src/main/java/io/beanmapper/core/unproxy/SkippingBeanUnproxy.java b/src/main/java/io/beanmapper/core/unproxy/SkippingBeanUnproxy.java index 62e4dd82..3c7f1ab2 100644 --- a/src/main/java/io/beanmapper/core/unproxy/SkippingBeanUnproxy.java +++ b/src/main/java/io/beanmapper/core/unproxy/SkippingBeanUnproxy.java @@ -83,4 +83,8 @@ public final void setDelegate(BeanUnproxy delegate) { this.delegate = delegate; } + @Override + public final BeanUnproxy getDelegate() { + return delegate; + } } diff --git a/src/main/java/io/beanmapper/utils/BeanMapperTraceLogger.java b/src/main/java/io/beanmapper/utils/BeanMapperTraceLogger.java index fc18a404..7b4390d1 100644 --- a/src/main/java/io/beanmapper/utils/BeanMapperTraceLogger.java +++ b/src/main/java/io/beanmapper/utils/BeanMapperTraceLogger.java @@ -5,6 +5,10 @@ public class BeanMapperTraceLogger { + private BeanMapperTraceLogger() { + throw new AssertionError("Cannot instantiate utility-class."); + } + private static final Logger log = LoggerFactory.getLogger(BeanMapperTraceLogger.class); public static void log(String message) { diff --git a/src/test/java/io/beanmapper/config/BeanMapperBuilderTest.java b/src/test/java/io/beanmapper/config/BeanMapperBuilderTest.java index ded07d47..6f10ca4f 100644 --- a/src/test/java/io/beanmapper/config/BeanMapperBuilderTest.java +++ b/src/test/java/io/beanmapper/config/BeanMapperBuilderTest.java @@ -1,5 +1,6 @@ package io.beanmapper.config; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -18,6 +19,7 @@ import io.beanmapper.exceptions.BeanConfigurationOperationNotAllowedException; import io.beanmapper.strategy.ConstructorArguments; import io.beanmapper.utils.Trinary; +import io.beanmapper.utils.diagnostics.DiagnosticsDetailLevel; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; @@ -212,6 +214,54 @@ void strictMappingConventionForOverrideConfig() { assertTrue(currentConfiguration.getStrictMappingProperties().isApplyStrictMappingConvention()); } + @Test + void createBeanMapperBuilderWithExistingConfiguration_shouldSucceed() { + BeanMapper beanMapper = builder.build(); + Configuration currentConfiguration = beanMapper.configuration(); + assertDoesNotThrow(() -> new BeanMapperBuilder(currentConfiguration)); + } + + @Test + void createBeanMapperBuilderWithExistingConfigurationAndDetailLevelDisabled_shouldSucceed() { + Configuration currentConfiguration = builder.build().configuration(); + assertDoesNotThrow(() -> new BeanMapperBuilder(currentConfiguration, DiagnosticsDetailLevel.DISABLED)); + } + + @Test + void createBeanMapperBuilderWithExistingDiagnosticsConfigAndDetailLevelDisabled_shouldSucceed() { + Configuration diagnosticsConfiguration = builder.build().wrap(DiagnosticsDetailLevel.TREE_COMPLETE).build().configuration(); + assertDoesNotThrow(() -> new BeanMapperBuilder(diagnosticsConfiguration, DiagnosticsDetailLevel.DISABLED)); + } + + @Test + void createBeanMapperBuilderWithExistingDiagnosticsConfigAndDetailLevelEnabled_shouldThrow() { + Configuration diagnosticsConfiguration = builder.build().wrap(DiagnosticsDetailLevel.TREE_COMPLETE).build().configuration(); + assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> new BeanMapperBuilder(diagnosticsConfiguration, DiagnosticsDetailLevel.TREE_COMPLETE)); + } + + @Test + void createBeanMapperBuilderWithoutExistingDiagnosticsConfigAndDetailLevelEnabled_shouldThrow() { + Configuration diagnosticsConfiguration = builder.build().configuration(); + assertDoesNotThrow(() -> new BeanMapperBuilder(diagnosticsConfiguration, DiagnosticsDetailLevel.TREE_COMPLETE)); + } + + @Test + void setBeanUnproxy_shouldSucceed() { + + class BeanUnproxyImpl implements BeanUnproxy { + @Override + public Class unproxy(Class beanClass) { + return null; + } + } + + BeanUnproxyImpl beanUnproxy = new BeanUnproxyImpl(); + + assertDoesNotThrow(() -> builder = builder.setBeanUnproxy(beanUnproxy)); + BeanMapper beanMapper = builder.build(); + assertEquals(beanUnproxy, beanMapper.configuration().getBeanUnproxy().getDelegate()); + } + @Test void cleanConfig() { BeanMapper beanMapper = builder.build(); // Core wrap From fbdc03e82c03158cbf075ef31a428682541e99fa Mon Sep 17 00:00:00 2001 From: Marcus Talbot Date: Mon, 2 Dec 2024 15:02:11 +0100 Subject: [PATCH 3/3] Improve coverage --- src/main/java/io/beanmapper/BeanMapper.java | 4 ++ .../core/converter/BeanConverterStore.java | 5 +- .../impl/OptionalToObjectConverter.java | 4 +- .../converter/impl/PrimitiveConverter.java | 2 +- .../io/beanmapper/utils/DefaultValues.java | 17 +++++- .../java/io/beanmapper/BeanMapperTest.java | 16 +++--- .../config/BeanMapperBuilderTest.java | 32 +++-------- .../config/CollectionHandlerStoreTest.java | 2 +- .../config/CoreConfigurationTest.java | 55 +++++++++++++++---- .../config/OverrideConfigurationTest.java | 10 ++-- .../converter/AbstractBeanConverterTest.java | 2 +- .../BeanCollectionInstructionsTest.java | 4 +- .../beanmapper/dynclass/ClassStoreTest.java | 2 +- 13 files changed, 95 insertions(+), 60 deletions(-) diff --git a/src/main/java/io/beanmapper/BeanMapper.java b/src/main/java/io/beanmapper/BeanMapper.java index a0af3bf8..983c1def 100644 --- a/src/main/java/io/beanmapper/BeanMapper.java +++ b/src/main/java/io/beanmapper/BeanMapper.java @@ -244,4 +244,8 @@ public BeanMapperBuilder wrap() { public BeanMapperBuilder wrap(DiagnosticsDetailLevel detailLevel) { return new BeanMapperBuilder(configuration, detailLevel); } + + public static BeanMapperBuilder builder() { + return new BeanMapperBuilder(); + } } diff --git a/src/main/java/io/beanmapper/core/converter/BeanConverterStore.java b/src/main/java/io/beanmapper/core/converter/BeanConverterStore.java index c1a3c5d8..bfb56d1f 100644 --- a/src/main/java/io/beanmapper/core/converter/BeanConverterStore.java +++ b/src/main/java/io/beanmapper/core/converter/BeanConverterStore.java @@ -36,8 +36,9 @@ public synchronized void add(Class source, Class target, BeanConverter bea var cachedConverters = beanConverterMap.get(source); if (cachedConverters == null) { - beanConverterMap.put(source, new HashMap<>()); - cachedConverters = beanConverterMap.get(target); + beanConverterMap.putIfAbsent(source, new HashMap<>()); + cachedConverters = beanConverterMap.get(source); + cachedConverters.put(target, beanConverter); } cachedConverters.put(target, beanConverter); diff --git a/src/main/java/io/beanmapper/core/converter/impl/OptionalToObjectConverter.java b/src/main/java/io/beanmapper/core/converter/impl/OptionalToObjectConverter.java index e030503a..0ad11722 100644 --- a/src/main/java/io/beanmapper/core/converter/impl/OptionalToObjectConverter.java +++ b/src/main/java/io/beanmapper/core/converter/impl/OptionalToObjectConverter.java @@ -84,8 +84,8 @@ private Optional convertToOptional(BeanMapper beanMapper, Optional S sourceObject = source.get(); - if (genericType instanceof Class targetType && Enum.class.isAssignableFrom((Class) genericType) && sourceObject.getClass() == targetType) { - return (Optional) Optional.ofNullable(sourceObject); + if (genericType instanceof Class targetType && Enum.class.isAssignableFrom(targetType) && sourceObject.getClass() == targetType) { + return (Optional) Optional.of(sourceObject); } // Place back in an Optional, as that is the target class diff --git a/src/main/java/io/beanmapper/core/converter/impl/PrimitiveConverter.java b/src/main/java/io/beanmapper/core/converter/impl/PrimitiveConverter.java index 380e30a3..396aa4a3 100644 --- a/src/main/java/io/beanmapper/core/converter/impl/PrimitiveConverter.java +++ b/src/main/java/io/beanmapper/core/converter/impl/PrimitiveConverter.java @@ -18,7 +18,7 @@ */ public class PrimitiveConverter implements BeanConverter { - private static final Map, Class> MAPPINGS = new HashMap, Class>(); + private static final Map, Class> MAPPINGS = new HashMap<>(); static { register(Byte.class, byte.class); diff --git a/src/main/java/io/beanmapper/utils/DefaultValues.java b/src/main/java/io/beanmapper/utils/DefaultValues.java index 2607a222..ed4a7022 100644 --- a/src/main/java/io/beanmapper/utils/DefaultValues.java +++ b/src/main/java/io/beanmapper/utils/DefaultValues.java @@ -33,6 +33,21 @@ private DefaultValues() { @SuppressWarnings("unchecked") public static V defaultValueFor(Class clazz) { - return (V) defaultValues.get(clazz); + var result = (V) defaultValues.get(clazz); + + if (result == null && clazz.getSuperclass() != null) { + result = defaultValueFor(clazz.getSuperclass()); + } + + if (result == null) { + for (Class iface : clazz.getInterfaces()) { + result = defaultValueFor(iface); + if (result != null) { + break; + } + } + } + + return result; } } \ No newline at end of file diff --git a/src/test/java/io/beanmapper/BeanMapperTest.java b/src/test/java/io/beanmapper/BeanMapperTest.java index 46e8baf7..49fe4d02 100644 --- a/src/test/java/io/beanmapper/BeanMapperTest.java +++ b/src/test/java/io/beanmapper/BeanMapperTest.java @@ -506,7 +506,7 @@ void mapToNestedCollectionArraysAsList() { EnumSourceArraysAsList source = new EnumSourceArraysAsList(); EnumTargetList target = beanMapper.map(source, EnumTargetList.class); assertEquals(RGB.values().length, target.items.size()); - assertEquals("RED", target.items.get(0)); + assertEquals("RED", target.items.getFirst()); } @Test @@ -974,8 +974,8 @@ void converterForClassesInCollection() { source.objects.add(nestedSourceClass); TargetWithCollection target = beanMapper.map(source, TargetWithCollection.class); - assertEquals(source.objects.get(0).name, target.objects.get(0).name); - assertEquals("[" + source.objects.get(0).laptopNumber + "]", target.objects.get(0).laptopNumber); + assertEquals(source.objects.getFirst().name, target.objects.getFirst().name); + assertEquals("[" + source.objects.getFirst().laptopNumber + "]", target.objects.getFirst().laptopNumber); } @Test @@ -1227,7 +1227,7 @@ void numberToNumberInList() { numberStrings.add("1"); List numbers = localBeanMapper.map(numberStrings, Integer.class); - assertEquals((Integer) 1, numbers.get(0)); + assertEquals((Integer) 1, numbers.getFirst()); } @Test @@ -1279,9 +1279,9 @@ void strictMultipleBeanMismatches() { .addBeanPairWithStrictSource(SourceDStrict.class, TargetDNonStrict.class); var exception = assertThrows(BeanStrictMappingRequirementsException.class, builder::build); assertEquals(SourceAStrict.class, exception.getValidationMessages().get(0).getSourceClass()); - assertEquals("noMatch", exception.getValidationMessages().get(0).getFields().get(0).getName()); + assertEquals("noMatch", exception.getValidationMessages().get(0).getFields().getFirst().getName()); assertEquals(TargetBStrict.class, exception.getValidationMessages().get(1).getTargetClass()); - assertEquals("noMatch", exception.getValidationMessages().get(1).getFields().get(0).getName()); + assertEquals("noMatch", exception.getValidationMessages().get(1).getFields().getFirst().getName()); assertEquals(SourceCStrict.class, exception.getValidationMessages().get(2).getSourceClass()); assertTrue(exception.getValidationMessages() @@ -1446,7 +1446,7 @@ void beanCollectionReuse() { target = beanMapper.map(source, target); assertEquals(4, target.items.size()); assertEquals(expectedList, target.items); - assertEquals("D", target.items.get(0)); + assertEquals("D", target.items.getFirst()); } @Test @@ -1491,7 +1491,7 @@ void unmodifiableRandomAccessList() { List numbers = List.of(42L, 57L, 33L); List numbersAsText = beanMapper.map(numbers, String.class); assertEquals(3, numbersAsText.size()); - assertEquals("42", numbersAsText.get(0)); + assertEquals("42", numbersAsText.getFirst()); } @Test diff --git a/src/test/java/io/beanmapper/config/BeanMapperBuilderTest.java b/src/test/java/io/beanmapper/config/BeanMapperBuilderTest.java index 6f10ca4f..a6c9ee12 100644 --- a/src/test/java/io/beanmapper/config/BeanMapperBuilderTest.java +++ b/src/test/java/io/beanmapper/config/BeanMapperBuilderTest.java @@ -36,58 +36,42 @@ void setup() { @Test void setTargetClassOnCoreThrowsException() { - assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - builder.setTargetClass(null); - }); + assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> builder.setTargetClass(null)); } @Test void setCollectionUsage() { - assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - builder.setCollectionUsage(null); - }); + assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> builder.setCollectionUsage(null)); } @Test void setPreferredCollectionClass() { - assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - builder.setPreferredCollectionClass(null); - }); + assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> builder.setPreferredCollectionClass(null)); } @Test void setFlushAfterClear() { - assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - builder.setFlushAfterClear(Trinary.ENABLED); - }); + assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> builder.setFlushAfterClear(Trinary.ENABLED)); } @Test void setTargetOnCoreThrowsException() { - assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - builder.setTarget(null); - }); + assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> builder.setTarget(null)); } @Test void setDownsizeSourceOnCoreThrowsException() { - assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - builder.downsizeSource(null); - }); + assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> builder.downsizeSource(null)); } @Test void setDownsizeTargetOnCoreThrowsException() { - assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - builder.downsizeTarget(null); - }); + assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> builder.downsizeTarget(null)); } @Test void setCollectionClassOnCoreThrowsException() { - assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - builder.setCollectionClass(null); - }); + assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> builder.setCollectionClass(null)); } @Test diff --git a/src/test/java/io/beanmapper/config/CollectionHandlerStoreTest.java b/src/test/java/io/beanmapper/config/CollectionHandlerStoreTest.java index 67acd350..2bfad219 100644 --- a/src/test/java/io/beanmapper/config/CollectionHandlerStoreTest.java +++ b/src/test/java/io/beanmapper/config/CollectionHandlerStoreTest.java @@ -39,7 +39,7 @@ void getCollectionHandlerFor_List() { @Test void getCollectionHandlerFor_AnonymousClass() { - assertEquals(List.class, configuration.getCollectionHandlerFor(new ArrayList() {{ + assertEquals(List.class, configuration.getCollectionHandlerFor(new ArrayList<>() {{ // Empty specifically to make it an anonymous class. }}.getClass()).getType()); } diff --git a/src/test/java/io/beanmapper/config/CoreConfigurationTest.java b/src/test/java/io/beanmapper/config/CoreConfigurationTest.java index 015cb3cb..20b2d559 100644 --- a/src/test/java/io/beanmapper/config/CoreConfigurationTest.java +++ b/src/test/java/io/beanmapper/config/CoreConfigurationTest.java @@ -2,56 +2,57 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import io.beanmapper.BeanMapper; +import io.beanmapper.core.converter.impl.StringToLongConverter; import io.beanmapper.exceptions.BeanConfigurationOperationNotAllowedException; import io.beanmapper.utils.Trinary; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; class CoreConfigurationTest { + private CoreConfiguration configuration; + + @BeforeEach + void setUp() { + configuration = (CoreConfiguration) BeanMapper.builder().build().configuration(); + } + @Test void setParent() { - assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - CoreConfiguration configuration = new CoreConfiguration(); - configuration.setParent(null); - }); + assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> configuration.setParent(null)); } @Test void setTarget() { - assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> { - CoreConfiguration configuration = new CoreConfiguration(); - configuration.setTarget("Hello world"); - }); + assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> configuration.setTarget("Hello world")); } @Test void determineTargetClass_noTargetSet() { - CoreConfiguration configuration = new CoreConfiguration(); assertNull(configuration.determineTargetClass()); } @Test void addNullPackagePrefix() { - CoreConfiguration configuration = new CoreConfiguration(); configuration.addPackagePrefix((Class) null); assertEquals(0, configuration.getPackagePrefixes().size()); } @Test void addWithoutDefaultConverters() { - CoreConfiguration configuration = new CoreConfiguration(); configuration.withoutDefaultConverters(); assertFalse(configuration.isAddDefaultConverters()); } @Test void singleMapRunProperties() { - CoreConfiguration configuration = new CoreConfiguration(); assertTrue(configuration.getDownsizeSource().isEmpty()); assertTrue(configuration.getDownsizeTarget().isEmpty()); assertNull(configuration.getTargetClass()); @@ -64,4 +65,34 @@ void singleMapRunProperties() { assertFalse(configuration.mustFlush()); } + @Test + void testSetFlushEnabledShouldSucceed() { + configuration.setFlushEnabled(true); + assertTrue(configuration.isFlushEnabled()); + + configuration.setFlushEnabled(false); + assertFalse(configuration.isFlushEnabled()); + } + + @Test + void testGetDefaultValueForUnknownTypeShouldReturnNull() { + assertNull(configuration.getDefaultValueForClass(Object.class)); + } + + @Test + void testGetDefaultValueForKnownTypeShouldReturnValue() { + assertNotNull(configuration.getDefaultValueForClass(int.class)); + } + + @Test + void testGetDefaultValueForCustomDefaultValueShouldReturnValue() { + configuration.addCustomDefaultValueForClass(Object.class, new Object()); + assertNotNull(configuration.getDefaultValueForClass(Object.class)); + } + + @Test + void testGetBeanConverterShouldReturnBeanConverter() { + configuration.getBeanConverterStore().add(String.class, Long.class, new StringToLongConverter()); + assertNotNull(configuration.getBeanConverter(String.class, Long.class)); + } } diff --git a/src/test/java/io/beanmapper/config/OverrideConfigurationTest.java b/src/test/java/io/beanmapper/config/OverrideConfigurationTest.java index 8ebe7f59..0b62baf7 100644 --- a/src/test/java/io/beanmapper/config/OverrideConfigurationTest.java +++ b/src/test/java/io/beanmapper/config/OverrideConfigurationTest.java @@ -42,7 +42,7 @@ void unsupportedCalls() { assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> overrideConfiguration.withoutDefaultConverters()); assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> overrideConfiguration.addProxySkipClass(null)); assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> overrideConfiguration.addPackagePrefix((String) null)); - assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> overrideConfiguration.addPackagePrefix((Class) null)); + assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> overrideConfiguration.addPackagePrefix((Class) null)); assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> overrideConfiguration.addAfterClearFlusher(null)); assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> overrideConfiguration.setBeanUnproxy(null)); assertThrows(BeanConfigurationOperationNotAllowedException.class, () -> overrideConfiguration.setRoleSecuredCheck(null)); @@ -90,8 +90,8 @@ void addBeanPairWithStrictSource() { overrideConfiguration.addBeanPairWithStrictSource(Long.class, String.class); List beanPairs = overrideConfiguration.getBeanPairs(); assertEquals(1, beanPairs.size()); - assertTrue(beanPairs.get(0).isSourceStrict()); - assertFalse(beanPairs.get(0).isTargetStrict()); + assertTrue(beanPairs.getFirst().isSourceStrict()); + assertFalse(beanPairs.getFirst().isTargetStrict()); } @Test @@ -99,8 +99,8 @@ void addBeanPairWithStrictTarget() { overrideConfiguration.addBeanPairWithStrictTarget(Long.class, String.class); List beanPairs = overrideConfiguration.getBeanPairs(); assertEquals(1, beanPairs.size()); - assertFalse(beanPairs.get(0).isSourceStrict()); - assertTrue(beanPairs.get(0).isTargetStrict()); + assertFalse(beanPairs.getFirst().isSourceStrict()); + assertTrue(beanPairs.getFirst().isTargetStrict()); } @Test diff --git a/src/test/java/io/beanmapper/core/converter/AbstractBeanConverterTest.java b/src/test/java/io/beanmapper/core/converter/AbstractBeanConverterTest.java index b3132d3b..fcd2631b 100644 --- a/src/test/java/io/beanmapper/core/converter/AbstractBeanConverterTest.java +++ b/src/test/java/io/beanmapper/core/converter/AbstractBeanConverterTest.java @@ -20,7 +20,7 @@ */ class AbstractBeanConverterTest { - private LocalDateTimeToLocalDate converter = new LocalDateTimeToLocalDate(); + private final LocalDateTimeToLocalDate converter = new LocalDateTimeToLocalDate(); @Test void testConvert() { diff --git a/src/test/java/io/beanmapper/core/converter/collections/BeanCollectionInstructionsTest.java b/src/test/java/io/beanmapper/core/converter/collections/BeanCollectionInstructionsTest.java index eeffd196..393335a4 100644 --- a/src/test/java/io/beanmapper/core/converter/collections/BeanCollectionInstructionsTest.java +++ b/src/test/java/io/beanmapper/core/converter/collections/BeanCollectionInstructionsTest.java @@ -98,11 +98,11 @@ private BeanCollectionInstructions createBeanCollectionInstructions( return instructions; } - public class SourceClassContainingList { + public static class SourceClassContainingList { public List list; } - public class TargetClassContainingList { + public static class TargetClassContainingList { public List list; } diff --git a/src/test/java/io/beanmapper/dynclass/ClassStoreTest.java b/src/test/java/io/beanmapper/dynclass/ClassStoreTest.java index 32b5d1ae..1f839663 100644 --- a/src/test/java/io/beanmapper/dynclass/ClassStoreTest.java +++ b/src/test/java/io/beanmapper/dynclass/ClassStoreTest.java @@ -24,7 +24,7 @@ void before() { @Test void shouldCacheThreadSafe() throws InterruptedException { - final Set results = new CopyOnWriteArraySet<>(); + final Set> results = new CopyOnWriteArraySet<>(); run(8, () -> results.add(store.getOrCreateGeneratedClass( Person.class, Collections.synchronizedList(Collections.singletonList("name")),