From cf668bea77d5d48f34d32c229823a04dbd01f21d Mon Sep 17 00:00:00 2001 From: Sjaak Derksen Date: Tue, 6 Nov 2018 07:36:09 +0000 Subject: [PATCH] #1576 Delay determining whether a Type needs to be imported & java.time cleanup (#1642) --- parent/pom.xml | 2 +- .../org/mapstruct/ap/MappingProcessor.java | 17 +++- .../AbstractJavaTimeToStringConversion.java | 8 +- .../internal/conversion/ConversionUtils.java | 20 ++-- .../ap/internal/conversion/Conversions.java | 31 +++--- .../conversion/EnumStringConversion.java | 2 +- .../JavaLocalDateTimeToDateConversion.java | 12 +-- .../JavaLocalDateToDateConversion.java | 10 +- .../JavaLocalDateToSqlDateConversion.java | 6 +- .../JavaZonedDateTimeToDateConversion.java | 8 +- .../JodaDateTimeToCalendarConversion.java | 2 +- .../conversion/JodaTimeToDateConversion.java | 2 +- .../ap/internal/model/GeneratedType.java | 2 +- .../common/DateFormatValidatorFactory.java | 14 ++- .../ap/internal/model/common/Type.java | 94 ++++++++++++++++--- .../ap/internal/model/common/TypeFactory.java | 66 +++---------- .../source/builtin/BuiltInMappingMethods.java | 20 ++-- .../builtin/CalendarToZonedDateTime.java | 3 +- .../builtin/ZonedDateTimeToCalendar.java | 3 +- .../DefaultModelElementProcessorContext.java | 6 +- .../ap/internal/util/JavaTimeConstants.java | 27 ------ .../ap/internal/model/common/Type.ftl | 2 +- .../DateFormatValidatorFactoryTest.java | 16 +++- .../common/DefaultConversionContextTest.java | 9 +- .../model/common/TypeFactoryTest.java | 50 ---------- .../bugs/_1576/java8/Issue1576Mapper.java | 17 ++++ .../test/bugs/_1576/java8/Issue1576Test.java | 32 +++++++ .../ap/test/bugs/_1576/java8/Source.java | 57 +++++++++++ .../ap/test/bugs/_1576/java8/Target.java | 61 ++++++++++++ .../bugs/_1576/java8/Issue1576MapperImpl.java | 48 ++++++++++ 30 files changed, 417 insertions(+), 230 deletions(-) delete mode 100644 processor/src/main/java/org/mapstruct/ap/internal/util/JavaTimeConstants.java delete mode 100644 processor/src/test/java/org/mapstruct/ap/internal/model/common/TypeFactoryTest.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/bugs/_1576/java8/Issue1576Mapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/bugs/_1576/java8/Issue1576Test.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/bugs/_1576/java8/Source.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/bugs/_1576/java8/Target.java create mode 100644 processor/src/test/resources/fixtures/org/mapstruct/ap/test/bugs/_1576/java8/Issue1576MapperImpl.java diff --git a/parent/pom.xml b/parent/pom.xml index a30051d95..fdfb0dd47 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -613,7 +613,7 @@ org.codehaus.mojo.signature - java16 + java18 1.0 diff --git a/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java b/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java index 83841db52..dc565e13b 100644 --- a/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java @@ -13,9 +13,10 @@ import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.ServiceLoader; import java.util.Set; - +import java.util.stream.Collectors; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.Processor; @@ -25,6 +26,7 @@ import javax.annotation.processing.SupportedOptions; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; +import javax.lang.model.element.Name; import javax.lang.model.element.TypeElement; import javax.lang.model.util.ElementKindVisitor6; import javax.tools.Diagnostic.Kind; @@ -41,6 +43,8 @@ import org.mapstruct.ap.internal.util.AnnotationProcessorContext; import org.mapstruct.ap.internal.util.RoundContext; import org.mapstruct.ap.spi.TypeHierarchyErroneousException; +import static javax.lang.model.element.ElementKind.CLASS; + /** * A JSR 269 annotation {@link Processor} which generates the implementations for mapper interfaces (interfaces * annotated with {@code @Mapper}). @@ -209,8 +213,9 @@ public class MappingProcessor extends AbstractProcessor { // note that this assumes that a new source file is created for each mapper which must not // necessarily be the case, e.g. in case of several mapper interfaces declared as inner types // of one outer interface + List tst = mapperElement.getEnclosedElements(); ProcessorContext context = new DefaultModelElementProcessorContext( - processingEnv, options, roundContext + processingEnv, options, roundContext, getDeclaredTypesNotToBeImported( mapperElement ) ); processMapperTypeElement( context, mapperElement ); @@ -225,6 +230,14 @@ public class MappingProcessor extends AbstractProcessor { } } + private Map getDeclaredTypesNotToBeImported(TypeElement element) { + return element.getEnclosedElements().stream() + .filter( e -> CLASS.equals( e.getKind() ) ) + .map( Element::getSimpleName ) + .map( Name::toString ) + .collect( Collectors.toMap( k -> k, v -> element.getQualifiedName().toString() + "." + v ) ); + } + private void handleUncaughtError(Element element, Throwable thrown) { StringWriter sw = new StringWriter(); thrown.printStackTrace( new PrintWriter( sw ) ); diff --git a/processor/src/main/java/org/mapstruct/ap/internal/conversion/AbstractJavaTimeToStringConversion.java b/processor/src/main/java/org/mapstruct/ap/internal/conversion/AbstractJavaTimeToStringConversion.java index f3dfdf46d..e903c00e5 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/conversion/AbstractJavaTimeToStringConversion.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/conversion/AbstractJavaTimeToStringConversion.java @@ -5,12 +5,12 @@ */ package org.mapstruct.ap.internal.conversion; +import java.time.format.DateTimeFormatter; import java.util.Set; import org.mapstruct.ap.internal.model.common.ConversionContext; import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.util.Collections; -import org.mapstruct.ap.internal.util.JavaTimeConstants; import org.mapstruct.ap.internal.util.Strings; /** @@ -53,7 +53,7 @@ public abstract class AbstractJavaTimeToStringConversion extends SimpleConversio @Override protected String getFromExpression(ConversionContext conversionContext) { // See http://docs.oracle.com/javase/tutorial/datetime/iso/format.html for how to parse Dates - return new StringBuilder().append( conversionContext.getTargetType().getReferenceName() ) + return new StringBuilder().append( conversionContext.getTargetType().createReferenceName() ) .append( ".parse( " ) .append( parametersListForParsing( conversionContext ) ) .append( " )" ).toString(); @@ -72,7 +72,7 @@ public abstract class AbstractJavaTimeToStringConversion extends SimpleConversio @Override protected Set getToConversionImportTypes(ConversionContext conversionContext) { return Collections.asSet( - conversionContext.getTypeFactory().getType( JavaTimeConstants.DATE_TIME_FORMATTER_FQN ) + conversionContext.getTypeFactory().getType( DateTimeFormatter.class ) ); } @@ -81,7 +81,7 @@ public abstract class AbstractJavaTimeToStringConversion extends SimpleConversio if ( !Strings.isEmpty( conversionContext.getDateFormat() ) ) { return Collections.asSet( conversionContext.getTargetType(), - conversionContext.getTypeFactory().getType( JavaTimeConstants.DATE_TIME_FORMATTER_FQN ) + conversionContext.getTypeFactory().getType( DateTimeFormatter.class ) ); } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/conversion/ConversionUtils.java b/processor/src/main/java/org/mapstruct/ap/internal/conversion/ConversionUtils.java index b2210ec10..8d2557b33 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/conversion/ConversionUtils.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/conversion/ConversionUtils.java @@ -11,11 +11,15 @@ import java.sql.Time; import java.sql.Timestamp; import java.text.DecimalFormat; import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.util.Currency; import java.util.Locale; import org.mapstruct.ap.internal.model.common.ConversionContext; -import org.mapstruct.ap.internal.util.JavaTimeConstants; import org.mapstruct.ap.internal.util.JodaTimeConstants; /** @@ -37,7 +41,7 @@ public final class ConversionUtils { * @return Name or fully-qualified name. */ private static String typeReferenceName(ConversionContext conversionContext, String canonicalName) { - return conversionContext.getTypeFactory().getType( canonicalName ).getReferenceName(); + return conversionContext.getTypeFactory().getType( canonicalName ).createReferenceName(); } /** @@ -49,7 +53,7 @@ public final class ConversionUtils { * @return Name or fully-qualified name. */ private static String typeReferenceName(ConversionContext conversionContext, Class type) { - return conversionContext.getTypeFactory().getType( type ).getReferenceName(); + return conversionContext.getTypeFactory().getType( type ).createReferenceName(); } /** @@ -170,7 +174,7 @@ public final class ConversionUtils { * @return Name or fully-qualified name. */ public static String zoneOffset(ConversionContext conversionContext) { - return typeReferenceName( conversionContext, JavaTimeConstants.ZONE_OFFSET_FQN ); + return typeReferenceName( conversionContext, ZoneOffset.class ); } /** @@ -181,7 +185,7 @@ public final class ConversionUtils { * @return Name or fully-qualified name. */ public static String zoneId(ConversionContext conversionContext) { - return typeReferenceName( conversionContext, JavaTimeConstants.ZONE_ID_FQN ); + return typeReferenceName( conversionContext, ZoneId.class ); } /** @@ -192,7 +196,7 @@ public final class ConversionUtils { * @return Name or fully-qualified name. */ public static String localDateTime(ConversionContext conversionContext) { - return typeReferenceName( conversionContext, JavaTimeConstants.LOCAL_DATE_TIME_FQN ); + return typeReferenceName( conversionContext, LocalDateTime.class ); } /** @@ -203,7 +207,7 @@ public final class ConversionUtils { * @return Name or fully-qualified name. */ public static String zonedDateTime(ConversionContext conversionContext) { - return typeReferenceName( conversionContext, JavaTimeConstants.ZONED_DATE_TIME_FQN ); + return typeReferenceName( conversionContext, ZonedDateTime.class ); } /** @@ -214,7 +218,7 @@ public final class ConversionUtils { * @return Name or fully-qualified name. */ public static String dateTimeFormatter(ConversionContext conversionContext) { - return typeReferenceName( conversionContext, JavaTimeConstants.DATE_TIME_FORMATTER_FQN ); + return typeReferenceName( conversionContext, DateTimeFormatter.class ); } /** diff --git a/processor/src/main/java/org/mapstruct/ap/internal/conversion/Conversions.java b/processor/src/main/java/org/mapstruct/ap/internal/conversion/Conversions.java index 3bf9ccade..6f4db9316 100755 --- a/processor/src/main/java/org/mapstruct/ap/internal/conversion/Conversions.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/conversion/Conversions.java @@ -9,6 +9,11 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Time; import java.sql.Timestamp; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZonedDateTime; import java.util.Calendar; import java.util.Currency; import java.util.Date; @@ -18,7 +23,6 @@ import javax.lang.model.util.Elements; import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.common.TypeFactory; -import org.mapstruct.ap.internal.util.JavaTimeConstants; import org.mapstruct.ap.internal.util.JodaTimeConstants; import static org.mapstruct.ap.internal.conversion.ReverseConversion.reverse; @@ -207,22 +211,19 @@ public class Conversions { } private void registerJava8TimeConversions() { - if ( !isJava8TimeAvailable() ) { - return; - } // Java 8 time to String - register( JavaTimeConstants.ZONED_DATE_TIME_FQN, String.class, new JavaZonedDateTimeToStringConversion() ); - register( JavaTimeConstants.LOCAL_DATE_FQN, String.class, new JavaLocalDateToStringConversion() ); - register( JavaTimeConstants.LOCAL_DATE_TIME_FQN, String.class, new JavaLocalDateTimeToStringConversion() ); - register( JavaTimeConstants.LOCAL_TIME_FQN, String.class, new JavaLocalTimeToStringConversion() ); + register( ZonedDateTime.class, String.class, new JavaZonedDateTimeToStringConversion() ); + register( LocalDate.class, String.class, new JavaLocalDateToStringConversion() ); + register( LocalDateTime.class, String.class, new JavaLocalDateTimeToStringConversion() ); + register( LocalTime.class, String.class, new JavaLocalTimeToStringConversion() ); // Java 8 to Date - register( JavaTimeConstants.ZONED_DATE_TIME_FQN, Date.class, new JavaZonedDateTimeToDateConversion() ); - register( JavaTimeConstants.LOCAL_DATE_TIME_FQN, Date.class, new JavaLocalDateTimeToDateConversion() ); - register( JavaTimeConstants.LOCAL_DATE_FQN, Date.class, new JavaLocalDateToDateConversion() ); - register( JavaTimeConstants.LOCAL_DATE_FQN, java.sql.Date.class, new JavaLocalDateToSqlDateConversion() ); - register( JavaTimeConstants.INSTANT, Date.class, new JavaInstantToDateConversion() ); + register( ZonedDateTime.class, Date.class, new JavaZonedDateTimeToDateConversion() ); + register( LocalDateTime.class, Date.class, new JavaLocalDateTimeToDateConversion() ); + register( LocalDate.class, Date.class, new JavaLocalDateToDateConversion() ); + register( LocalDate.class, java.sql.Date.class, new JavaLocalDateToSqlDateConversion() ); + register( Instant.class, Date.class, new JavaInstantToDateConversion() ); } @@ -230,10 +231,6 @@ public class Conversions { return typeFactory.isTypeAvailable( JodaTimeConstants.DATE_TIME_FQN ); } - private boolean isJava8TimeAvailable() { - return typeFactory.isTypeAvailable( JavaTimeConstants.ZONED_DATE_TIME_FQN ); - } - private void registerNativeTypeConversion(Class sourceType, Class targetType) { if ( sourceType.isPrimitive() && targetType.isPrimitive() ) { register( sourceType, targetType, new PrimitiveToPrimitiveConversion( sourceType ) ); diff --git a/processor/src/main/java/org/mapstruct/ap/internal/conversion/EnumStringConversion.java b/processor/src/main/java/org/mapstruct/ap/internal/conversion/EnumStringConversion.java index 7f904dbe4..d06cad93b 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/conversion/EnumStringConversion.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/conversion/EnumStringConversion.java @@ -26,7 +26,7 @@ public class EnumStringConversion extends SimpleConversion { @Override public String getFromExpression(ConversionContext conversionContext) { - return "Enum.valueOf( " + conversionContext.getTargetType().getReferenceName() + return "Enum.valueOf( " + conversionContext.getTargetType().createReferenceName() + ".class, )"; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaLocalDateTimeToDateConversion.java b/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaLocalDateTimeToDateConversion.java index 579e45fd9..489fc39eb 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaLocalDateTimeToDateConversion.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaLocalDateTimeToDateConversion.java @@ -5,6 +5,9 @@ */ package org.mapstruct.ap.internal.conversion; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; import java.util.Date; import java.util.Set; @@ -16,9 +19,6 @@ import static org.mapstruct.ap.internal.conversion.ConversionUtils.date; import static org.mapstruct.ap.internal.conversion.ConversionUtils.localDateTime; import static org.mapstruct.ap.internal.conversion.ConversionUtils.zoneId; import static org.mapstruct.ap.internal.conversion.ConversionUtils.zoneOffset; -import static org.mapstruct.ap.internal.util.JavaTimeConstants.LOCAL_DATE_TIME_FQN; -import static org.mapstruct.ap.internal.util.JavaTimeConstants.ZONE_ID_FQN; -import static org.mapstruct.ap.internal.util.JavaTimeConstants.ZONE_OFFSET_FQN; /** * SimpleConversion for mapping {@link java.time.LocalDateTime} to @@ -38,7 +38,7 @@ public class JavaLocalDateTimeToDateConversion extends SimpleConversion { protected Set getToConversionImportTypes(ConversionContext conversionContext) { return Collections.asSet( conversionContext.getTypeFactory().getType( Date.class ), - conversionContext.getTypeFactory().getType( ZONE_OFFSET_FQN ) + conversionContext.getTypeFactory().getType( ZoneOffset.class ) ); } @@ -53,8 +53,8 @@ public class JavaLocalDateTimeToDateConversion extends SimpleConversion { @Override protected Set getFromConversionImportTypes(ConversionContext conversionContext) { return Collections.asSet( - conversionContext.getTypeFactory().getType( LOCAL_DATE_TIME_FQN ), - conversionContext.getTypeFactory().getType( ZONE_ID_FQN ) + conversionContext.getTypeFactory().getType( LocalDateTime.class ), + conversionContext.getTypeFactory().getType( ZoneId.class ) ); } } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaLocalDateToDateConversion.java b/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaLocalDateToDateConversion.java index 9d4f3a0c5..b28bc5078 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaLocalDateToDateConversion.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaLocalDateToDateConversion.java @@ -5,6 +5,8 @@ */ package org.mapstruct.ap.internal.conversion; +import java.time.LocalDateTime; +import java.time.ZoneOffset; import java.util.Date; import java.util.Set; @@ -15,8 +17,6 @@ import org.mapstruct.ap.internal.util.Collections; import static org.mapstruct.ap.internal.conversion.ConversionUtils.date; import static org.mapstruct.ap.internal.conversion.ConversionUtils.localDateTime; import static org.mapstruct.ap.internal.conversion.ConversionUtils.zoneOffset; -import static org.mapstruct.ap.internal.util.JavaTimeConstants.LOCAL_DATE_TIME_FQN; -import static org.mapstruct.ap.internal.util.JavaTimeConstants.ZONE_OFFSET_FQN; /** * SimpleConversion for mapping {@link java.time.LocalDate} to @@ -36,7 +36,7 @@ public class JavaLocalDateToDateConversion extends SimpleConversion { protected Set getToConversionImportTypes(ConversionContext conversionContext) { return Collections.asSet( conversionContext.getTypeFactory().getType( Date.class ), - conversionContext.getTypeFactory().getType( ZONE_OFFSET_FQN ) + conversionContext.getTypeFactory().getType( ZoneOffset.class ) ); } @@ -51,8 +51,8 @@ public class JavaLocalDateToDateConversion extends SimpleConversion { @Override protected Set getFromConversionImportTypes(ConversionContext conversionContext) { return Collections.asSet( - conversionContext.getTypeFactory().getType( LOCAL_DATE_TIME_FQN ), - conversionContext.getTypeFactory().getType( ZONE_OFFSET_FQN ) + conversionContext.getTypeFactory().getType( LocalDateTime.class ), + conversionContext.getTypeFactory().getType( ZoneOffset.class ) ); } } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaLocalDateToSqlDateConversion.java b/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaLocalDateToSqlDateConversion.java index 29663cbcf..cfc6ca31d 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaLocalDateToSqlDateConversion.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaLocalDateToSqlDateConversion.java @@ -6,6 +6,7 @@ package org.mapstruct.ap.internal.conversion; import java.sql.Date; +import java.time.ZoneOffset; import java.util.Set; import org.mapstruct.ap.internal.model.common.ConversionContext; @@ -14,7 +15,6 @@ import org.mapstruct.ap.internal.util.Collections; import static org.mapstruct.ap.internal.conversion.ConversionUtils.sqlDate; import static org.mapstruct.ap.internal.conversion.ConversionUtils.zoneOffset; -import static org.mapstruct.ap.internal.util.JavaTimeConstants.ZONE_OFFSET_FQN; /** * SimpleConversion for mapping {@link java.time.LocalDate} to @@ -34,7 +34,7 @@ public class JavaLocalDateToSqlDateConversion extends SimpleConversion { protected Set getToConversionImportTypes(ConversionContext conversionContext) { return Collections.asSet( conversionContext.getTypeFactory().getType( Date.class ), - conversionContext.getTypeFactory().getType( ZONE_OFFSET_FQN ) + conversionContext.getTypeFactory().getType( ZoneOffset.class ) ); } @@ -46,7 +46,7 @@ public class JavaLocalDateToSqlDateConversion extends SimpleConversion { @Override protected Set getFromConversionImportTypes(ConversionContext conversionContext) { return Collections.asSet( - conversionContext.getTypeFactory().getType( ZONE_OFFSET_FQN ) + conversionContext.getTypeFactory().getType( ZoneOffset.class ) ); } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaZonedDateTimeToDateConversion.java b/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaZonedDateTimeToDateConversion.java index fb2f7f402..cc88d72e4 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaZonedDateTimeToDateConversion.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaZonedDateTimeToDateConversion.java @@ -5,6 +5,8 @@ */ package org.mapstruct.ap.internal.conversion; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.Date; import java.util.Set; @@ -15,8 +17,6 @@ import org.mapstruct.ap.internal.util.Collections; import static org.mapstruct.ap.internal.conversion.ConversionUtils.date; import static org.mapstruct.ap.internal.conversion.ConversionUtils.zoneId; import static org.mapstruct.ap.internal.conversion.ConversionUtils.zonedDateTime; -import static org.mapstruct.ap.internal.util.JavaTimeConstants.ZONED_DATE_TIME_FQN; -import static org.mapstruct.ap.internal.util.JavaTimeConstants.ZONE_ID_FQN; /** * SimpleConversion for mapping {@link java.time.ZonedDateTime} to @@ -48,8 +48,8 @@ public class JavaZonedDateTimeToDateConversion extends SimpleConversion { @Override protected Set getFromConversionImportTypes(ConversionContext conversionContext) { return Collections.asSet( - conversionContext.getTypeFactory().getType( ZONED_DATE_TIME_FQN ), - conversionContext.getTypeFactory().getType( ZONE_ID_FQN ) + conversionContext.getTypeFactory().getType( ZonedDateTime.class ), + conversionContext.getTypeFactory().getType( ZoneId.class ) ); } } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/conversion/JodaDateTimeToCalendarConversion.java b/processor/src/main/java/org/mapstruct/ap/internal/conversion/JodaDateTimeToCalendarConversion.java index f32f6e369..f9c70ff8f 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/conversion/JodaDateTimeToCalendarConversion.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/conversion/JodaDateTimeToCalendarConversion.java @@ -34,7 +34,7 @@ public class JodaDateTimeToCalendarConversion extends SimpleConversion { @Override protected String getFromExpression(ConversionContext conversionContext) { - return "new " + conversionContext.getTargetType().getReferenceName() + "( )"; + return "new " + conversionContext.getTargetType().createReferenceName() + "( )"; } @Override diff --git a/processor/src/main/java/org/mapstruct/ap/internal/conversion/JodaTimeToDateConversion.java b/processor/src/main/java/org/mapstruct/ap/internal/conversion/JodaTimeToDateConversion.java index fecd079e3..0e47085bc 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/conversion/JodaTimeToDateConversion.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/conversion/JodaTimeToDateConversion.java @@ -32,7 +32,7 @@ public class JodaTimeToDateConversion extends SimpleConversion { @Override protected String getFromExpression(ConversionContext conversionContext) { - return "new " + conversionContext.getTargetType().getReferenceName() + "( )"; + return "new " + conversionContext.getTargetType().createReferenceName() + "( )"; } @Override diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/GeneratedType.java b/processor/src/main/java/org/mapstruct/ap/internal/model/GeneratedType.java index 92f10c529..de16a5ce0 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/GeneratedType.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/GeneratedType.java @@ -224,7 +224,7 @@ public abstract class GeneratedType extends ModelElement { } private boolean needsImportDeclaration(Type typeToAdd) { - if ( !typeToAdd.isImported() ) { + if ( !typeToAdd.isToBeImported() ) { return false; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/common/DateFormatValidatorFactory.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/DateFormatValidatorFactory.java index 774d18626..8e8c328f2 100755 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/common/DateFormatValidatorFactory.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/common/DateFormatValidatorFactory.java @@ -8,8 +8,11 @@ package org.mapstruct.ap.internal.model.common; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZonedDateTime; -import org.mapstruct.ap.internal.util.JavaTimeConstants; import org.mapstruct.ap.internal.util.JodaTimeConstants; import org.mapstruct.ap.internal.util.Message; import org.mapstruct.ap.internal.util.XmlConstants; @@ -89,10 +92,11 @@ final class DateFormatValidatorFactory { return typesEqualsOneOf( sourceType, targetType, - JavaTimeConstants.LOCAL_DATE_FQN, - JavaTimeConstants.LOCAL_TIME_FQN, - JavaTimeConstants.LOCAL_DATE_TIME_FQN, - JavaTimeConstants.ZONED_DATE_TIME_FQN ); + LocalDate.class.getCanonicalName(), + LocalTime.class.getCanonicalName(), + LocalDateTime.class.getCanonicalName(), + ZonedDateTime.class.getCanonicalName() + ); } private static boolean isJavaUtilDateSupposed(Type sourceType, Type targetType) { diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java index 60852b49b..7fa56b564 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java @@ -77,13 +77,16 @@ public class Type extends ModelElement implements Comparable { private final boolean isIterableType; private final boolean isCollectionType; private final boolean isMapType; - private final boolean isImported; private final boolean isVoid; private final boolean isStream; private final boolean isLiteral; private final List enumConstants; + private final Map toBeImportedTypes; + private final Map notToBeImportedTypes; + private Boolean isToBeImported; + private Map readAccessors = null; private Map presenceCheckers = null; @@ -104,7 +107,10 @@ public class Type extends ModelElement implements Comparable { BuilderInfo builderInfo, String packageName, String name, String qualifiedName, boolean isInterface, boolean isEnumType, boolean isIterableType, - boolean isCollectionType, boolean isMapType, boolean isStreamType, boolean isImported, + boolean isCollectionType, boolean isMapType, boolean isStreamType, + Map toBeImportedTypes, + Map notToBeImportedTypes, + Boolean isToBeImported, boolean isLiteral ) { this.typeUtils = typeUtils; @@ -128,7 +134,6 @@ public class Type extends ModelElement implements Comparable { this.isCollectionType = isCollectionType; this.isMapType = isMapType; this.isStream = isStreamType; - this.isImported = isImported; this.isVoid = typeMirror.getKind() == TypeKind.VOID; this.isLiteral = isLiteral; @@ -148,6 +153,9 @@ public class Type extends ModelElement implements Comparable { enumConstants = Collections.emptyList(); } + this.isToBeImported = isToBeImported; + this.toBeImportedTypes = toBeImportedTypes; + this.notToBeImportedTypes = notToBeImportedTypes; this.builderType = BuilderType.create( builderInfo, this, this.typeFactory, this.typeUtils ); } //CHECKSTYLE:ON @@ -169,12 +177,18 @@ public class Type extends ModelElement implements Comparable { } /** - * String that could be used in generated code to reference to this {@link Type}. + * Returns a String that could be used in generated code to reference to this {@link Type}.
+ *

+ * The first time a name is referred-to it will be marked as to be imported. For instance + * {@code LocalDateTime} can be one of {@code java.time.LocalDateTime} and {@code org.joda.LocalDateTime}) + *

+ * If the {@code java.time} variant is referred to first, the {@code java.time.LocalDateTime} will be imported + * and the {@code org.joda} variant will be referred to with its FQN. * * @return Just the name if this {@link Type} will be imported, otherwise the fully-qualified name. */ - public String getReferenceName() { - return isImported ? name : qualifiedName; + public String createReferenceName() { + return isToBeImported() ? name : ( shouldUseSimpleName() ? name : qualifiedName ); } public List getTypeParameters() { @@ -314,7 +328,7 @@ public class Type extends ModelElement implements Comparable { * @return The name of this type as to be used within import statements. */ public String getImportName() { - return isArrayType() ? TypeFactory.trimSimpleClassName( qualifiedName ) : qualifiedName; + return isArrayType() ? trimSimpleClassName( qualifiedName ) : qualifiedName; } @Override @@ -341,14 +355,38 @@ public class Type extends ModelElement implements Comparable { } /** - * Whether this type is imported by means of an import statement in the currently generated source file (meaning it - * can be referenced in the generated source using its simple name) or not (meaning it has to be referenced using - * the fully-qualified name). + * Whether this type is to be imported by means of an import statement in the currently generated source file + * (it can be referenced in the generated source using its simple name) or not (referenced using the FQN). * * @return {@code true} if the type is imported, {@code false} otherwise. */ - public boolean isImported() { - return isImported; + public boolean isToBeImported() { + if ( isToBeImported == null ) { + String trimmedName = trimSimpleClassName( name ); + if ( notToBeImportedTypes.containsKey( trimmedName ) ) { + isToBeImported = false; + return isToBeImported; + } + String trimmedQualifiedName = trimSimpleClassName( qualifiedName ); + String importedType = toBeImportedTypes.get( trimmedName ); + + isToBeImported = false; + if ( importedType != null ) { + if ( importedType.equals( trimmedQualifiedName ) ) { + isToBeImported = true; + } + } + else { + toBeImportedTypes.put( trimmedName, trimmedQualifiedName ); + isToBeImported = true; + } + } + return isToBeImported; + } + + private boolean shouldUseSimpleName() { + String fqn = notToBeImportedTypes.get( name ); + return this.qualifiedName.equals( fqn ); } /** @@ -390,7 +428,9 @@ public class Type extends ModelElement implements Comparable { isCollectionType, isMapType, isStream, - isImported, + toBeImportedTypes, + notToBeImportedTypes, + isToBeImported, isLiteral ); } @@ -431,7 +471,9 @@ public class Type extends ModelElement implements Comparable { isCollectionType, isMapType, isStream, - isImported, + toBeImportedTypes, + notToBeImportedTypes, + isToBeImported, isLiteral ); } @@ -1004,4 +1046,28 @@ public class Type extends ModelElement implements Comparable { return isLiteral; } + /** + * It strips all the {@code []} from the {@code className}. + * + * E.g. + *

+     *     trimSimpleClassName("String[][][]") -> "String"
+     *     trimSimpleClassName("String[]") -> "String"
+     * 
+ * + * @param className that needs to be trimmed + * + * @return the trimmed {@code className}, or {@code null} if the {@code className} was {@code null} + */ + private String trimSimpleClassName(String className) { + if ( className == null ) { + return null; + } + String trimmedClassName = className; + while ( trimmedClassName.endsWith( "[]" ) ) { + trimmedClassName = trimmedClassName.substring( 0, trimmedClassName.length() - 2 ); + } + return trimmedClassName; + } + } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java index 6f46f073e..567053986 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java @@ -84,13 +84,16 @@ public class TypeFactory { private final TypeMirror streamType; private final Map implementationTypes = new HashMap<>(); - private final Map importedQualifiedTypesBySimpleName = new HashMap<>(); + private final Map toBeImportedTypes = new HashMap<>(); + private final Map notToBeImportedTypes; - public TypeFactory(Elements elementUtils, Types typeUtils, FormattingMessager messager, RoundContext roundContext) { + public TypeFactory(Elements elementUtils, Types typeUtils, FormattingMessager messager, RoundContext roundContext, + Map notToBeImportedTypes) { this.elementUtils = elementUtils; this.typeUtils = typeUtils; this.messager = messager; this.roundContext = roundContext; + this.notToBeImportedTypes = notToBeImportedTypes; iterableType = typeUtils.erasure( elementUtils.getTypeElement( Iterable.class.getCanonicalName() ).asType() ); collectionType = @@ -197,7 +200,7 @@ public class TypeFactory { String qualifiedName; TypeElement typeElement; Type componentType; - boolean isImported; + Boolean toBeImported = null; if ( mirror.getKind() == TypeKind.DECLARED ) { DeclaredType declaredType = (DeclaredType) mirror; @@ -218,7 +221,6 @@ public class TypeFactory { } componentType = null; - isImported = isImported( name, qualifiedName ); } else if ( mirror.getKind() == TypeKind.ARRAY ) { TypeMirror componentTypeMirror = getComponentType( mirror ); @@ -237,7 +239,6 @@ public class TypeFactory { name = componentTypeElement.getSimpleName().toString() + arraySuffix; packageName = elementUtils.getPackageOf( componentTypeElement ).getQualifiedName().toString(); qualifiedName = componentTypeElement.getQualifiedName().toString() + arraySuffix; - isImported = isImported( name, qualifiedName ); } else if (componentTypeMirror.getKind().isPrimitive()) { // When the component type is primitive and is annotated with ElementType.TYPE_USE then @@ -246,13 +247,13 @@ public class TypeFactory { packageName = null; // for primitive types only name (e.g. byte, short..) required as qualified name qualifiedName = name; - isImported = false; + toBeImported = false; } else { name = mirror.toString(); packageName = null; qualifiedName = name; - isImported = false; + toBeImported = false; } isEnumType = false; @@ -268,7 +269,7 @@ public class TypeFactory { qualifiedName = name; typeElement = null; componentType = null; - isImported = false; + toBeImported = false; } return new Type( @@ -289,7 +290,9 @@ public class TypeFactory { isCollectionType, isMapType, isStreamType, - isImported, + toBeImportedTypes, + notToBeImportedTypes, + toBeImported, isLiteral ); } @@ -509,7 +512,9 @@ public class TypeFactory { implementationType.isCollectionType(), implementationType.isMapType(), implementationType.isStreamType(), - isImported( implementationType.getName(), implementationType.getFullyQualifiedName() ), + toBeImportedTypes, + notToBeImportedTypes, + null, implementationType.isLiteral() ); return implementation.createNew( replacement ); @@ -545,24 +550,6 @@ public class TypeFactory { return arrayType.getComponentType(); } - private boolean isImported(String name, String qualifiedName) { - String trimmedName = TypeFactory.trimSimpleClassName( name ); - String trimmedQualifiedName = TypeFactory.trimSimpleClassName( qualifiedName ); - String importedType = importedQualifiedTypesBySimpleName.get( trimmedName ); - - boolean imported = false; - if ( importedType != null ) { - if ( importedType.equals( trimmedQualifiedName ) ) { - imported = true; - } - } - else { - importedQualifiedTypesBySimpleName.put( trimmedName, trimmedQualifiedName ); - imported = true; - } - return imported; - } - /** * Converts any collection type, e.g. {@code List} to {@code Collection} and any map type, e.g. * {@code HashMap} to {@code Map}. @@ -643,29 +630,6 @@ public class TypeFactory { return typeMirror; } - /** - * It strips the all the {@code []} from the {@code className}. - * - * E.g. - *
-     *     trimSimpleClassName("String[][][]") -> "String"
-     *     trimSimpleClassName("String[]") -> "String"
-     * 
- * - * @param className that needs to be trimmed - * - * @return the trimmed {@code className}, or {@code null} if the {@code className} was {@code null} - */ - static String trimSimpleClassName(String className) { - if ( className == null ) { - return null; - } - String trimmedClassName = className; - while ( trimmedClassName.endsWith( "[]" ) ) { - trimmedClassName = trimmedClassName.substring( 0, trimmedClassName.length() - 2 ); - } - return trimmedClassName; - } /** * Whether the given type is ready to be processed or not. It can be processed if it is not of kind diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/BuiltInMappingMethods.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/BuiltInMappingMethods.java index 908b8284f..5332651ab 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/BuiltInMappingMethods.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/BuiltInMappingMethods.java @@ -9,7 +9,6 @@ import java.util.ArrayList; import java.util.List; import org.mapstruct.ap.internal.model.common.TypeFactory; -import org.mapstruct.ap.internal.util.JavaTimeConstants; import org.mapstruct.ap.internal.util.JaxbConstants; import org.mapstruct.ap.internal.util.JodaTimeConstants; import org.mapstruct.ap.internal.util.XmlConstants; @@ -33,21 +32,18 @@ public class BuiltInMappingMethods { builtInMethods.add( new XmlGregorianCalendarToString( typeFactory ) ); builtInMethods.add( new CalendarToXmlGregorianCalendar( typeFactory ) ); builtInMethods.add( new XmlGregorianCalendarToCalendar( typeFactory ) ); + builtInMethods.add( new ZonedDateTimeToXmlGregorianCalendar( typeFactory ) ); } if ( isJaxbAvailable( typeFactory ) ) { builtInMethods.add( new JaxbElemToValue( typeFactory ) ); } - - if ( isJava8TimeAvailable( typeFactory ) ) { - builtInMethods.add( new ZonedDateTimeToCalendar( typeFactory ) ); - builtInMethods.add( new ZonedDateTimeToXmlGregorianCalendar( typeFactory ) ); - builtInMethods.add( new CalendarToZonedDateTime( typeFactory ) ); - if ( isXmlGregorianCalendarPresent ) { - builtInMethods.add( new XmlGregorianCalendarToLocalDate( typeFactory ) ); - builtInMethods.add( new LocalDateToXmlGregorianCalendar( typeFactory ) ); - } + builtInMethods.add( new ZonedDateTimeToCalendar( typeFactory ) ); + builtInMethods.add( new CalendarToZonedDateTime( typeFactory ) ); + if ( isXmlGregorianCalendarPresent ) { + builtInMethods.add( new XmlGregorianCalendarToLocalDate( typeFactory ) ); + builtInMethods.add( new LocalDateToXmlGregorianCalendar( typeFactory ) ); } if ( isJodaTimeAvailable( typeFactory ) && isXmlGregorianCalendarPresent ) { @@ -66,10 +62,6 @@ public class BuiltInMappingMethods { return JaxbConstants.isJaxbElementPresent() && typeFactory.isTypeAvailable( JaxbConstants.JAXB_ELEMENT_FQN ); } - private static boolean isJava8TimeAvailable(TypeFactory typeFactory) { - return typeFactory.isTypeAvailable( JavaTimeConstants.ZONED_DATE_TIME_FQN ); - } - private static boolean isXmlGregorianCalendarAvailable(TypeFactory typeFactory) { return XmlConstants.isXmlGregorianCalendarPresent() && typeFactory.isTypeAvailable( XmlConstants.JAVAX_XML_DATATYPE_XMLGREGORIAN_CALENDAR ); diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/CalendarToZonedDateTime.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/CalendarToZonedDateTime.java index 478f03ee4..729b65e5e 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/CalendarToZonedDateTime.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/CalendarToZonedDateTime.java @@ -12,7 +12,6 @@ import java.util.Set; import org.mapstruct.ap.internal.model.common.Parameter; import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.common.TypeFactory; -import org.mapstruct.ap.internal.util.JavaTimeConstants; import static org.mapstruct.ap.internal.util.Collections.asSet; @@ -28,7 +27,7 @@ public class CalendarToZonedDateTime extends BuiltInMethod { private final Set importedTypes; CalendarToZonedDateTime(TypeFactory typeFactory) { - this.returnType = typeFactory.getType( JavaTimeConstants.ZONED_DATE_TIME_FQN ); + this.returnType = typeFactory.getType( ZonedDateTime.class ); this.parameter = new Parameter( "cal", typeFactory.getType( Calendar.class ) ); this.importedTypes = asSet( returnType, parameter.getType() ); } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/ZonedDateTimeToCalendar.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/ZonedDateTimeToCalendar.java index 7e7a0751d..5a6c44790 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/ZonedDateTimeToCalendar.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/ZonedDateTimeToCalendar.java @@ -13,7 +13,6 @@ import java.util.TimeZone; import org.mapstruct.ap.internal.model.common.Parameter; import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.common.TypeFactory; -import org.mapstruct.ap.internal.util.JavaTimeConstants; import static org.mapstruct.ap.internal.util.Collections.asSet; @@ -29,7 +28,7 @@ public class ZonedDateTimeToCalendar extends BuiltInMethod { ZonedDateTimeToCalendar(TypeFactory typeFactory) { this.returnType = typeFactory.getType( Calendar.class ); - this.parameter = new Parameter( "dateTime", typeFactory.getType( JavaTimeConstants.ZONED_DATE_TIME_FQN ) ); + this.parameter = new Parameter( "dateTime", typeFactory.getType( ZonedDateTime.class ) ); this.importedTypes = asSet( returnType, parameter.getType(), typeFactory.getType( TimeZone.class ) ); } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/DefaultModelElementProcessorContext.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/DefaultModelElementProcessorContext.java index b178861dd..5168dccc1 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/processor/DefaultModelElementProcessorContext.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/DefaultModelElementProcessorContext.java @@ -5,6 +5,7 @@ */ package org.mapstruct.ap.internal.processor; +import java.util.Map; import javax.annotation.processing.Filer; import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; @@ -41,7 +42,7 @@ public class DefaultModelElementProcessorContext implements ProcessorContext { private final AccessorNamingUtils accessorNaming; public DefaultModelElementProcessorContext(ProcessingEnvironment processingEnvironment, Options options, - RoundContext roundContext) { + RoundContext roundContext, Map notToBeImported) { this.processingEnvironment = processingEnvironment; this.messager = new DelegatingMessager( processingEnvironment.getMessager() ); @@ -52,7 +53,8 @@ public class DefaultModelElementProcessorContext implements ProcessorContext { processingEnvironment.getElementUtils(), delegatingTypes, messager, - roundContext + roundContext, + notToBeImported ); this.options = options; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/JavaTimeConstants.java b/processor/src/main/java/org/mapstruct/ap/internal/util/JavaTimeConstants.java deleted file mode 100644 index 60053064b..000000000 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/JavaTimeConstants.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright MapStruct Authors. - * - * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 - */ -package org.mapstruct.ap.internal.util; - -/** - * Helper holding Java time full qualified class names for conversion registration - */ -public final class JavaTimeConstants { - - public static final String ZONED_DATE_TIME_FQN = "java.time.ZonedDateTime"; - public static final String ZONE_OFFSET_FQN = "java.time.ZoneOffset"; - public static final String ZONE_ID_FQN = "java.time.ZoneId"; - - public static final String LOCAL_DATE_TIME_FQN = "java.time.LocalDateTime"; - public static final String LOCAL_DATE_FQN = "java.time.LocalDate"; - public static final String LOCAL_TIME_FQN = "java.time.LocalTime"; - - public static final String DATE_TIME_FORMATTER_FQN = "java.time.format.DateTimeFormatter"; - - public static final String INSTANT = "java.time.Instant"; - - private JavaTimeConstants() { - } -} diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/common/Type.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/common/Type.ftl index d6b2d6850..89b2279a6 100644 --- a/processor/src/main/resources/org/mapstruct/ap/internal/model/common/Type.ftl +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/common/Type.ftl @@ -12,6 +12,6 @@ <#elseif wildCardSuperBound> ? super <@includeModel object=typeBound /> <#else> - <#if ext.asVarArgs!false>${referenceName?remove_ending("[]")}...<#else>${referenceName}<#if (!ext.raw?? && typeParameters?size > 0) ><<#list typeParameters as typeParameter><@includeModel object=typeParameter /><#if typeParameter_has_next>, > + <#if ext.asVarArgs!false>${createReferenceName()?remove_ending("[]")}...<#else>${createReferenceName()}<#if (!ext.raw?? && typeParameters?size > 0) ><<#list typeParameters as typeParameter><@includeModel object=typeParameter /><#if typeParameter_has_next>, > \ No newline at end of file diff --git a/processor/src/test/java/org/mapstruct/ap/internal/model/common/DateFormatValidatorFactoryTest.java b/processor/src/test/java/org/mapstruct/ap/internal/model/common/DateFormatValidatorFactoryTest.java index 68fee3bc8..064aabfd8 100755 --- a/processor/src/test/java/org/mapstruct/ap/internal/model/common/DateFormatValidatorFactoryTest.java +++ b/processor/src/test/java/org/mapstruct/ap/internal/model/common/DateFormatValidatorFactoryTest.java @@ -8,6 +8,11 @@ package org.mapstruct.ap.internal.model.common; import static org.assertj.core.api.Assertions.assertThat; import java.lang.annotation.Annotation; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZonedDateTime; +import java.util.HashMap; import java.util.List; import javax.lang.model.element.AnnotationMirror; @@ -16,7 +21,6 @@ import javax.lang.model.type.TypeMirror; import javax.lang.model.type.TypeVisitor; import org.junit.Test; -import org.mapstruct.ap.internal.util.JavaTimeConstants; import org.mapstruct.ap.internal.util.JodaTimeConstants; import org.mapstruct.ap.testutil.IssueKey; @@ -113,25 +117,25 @@ public class DateFormatValidatorFactoryTest { Type targetType = typeWithFQN( JAVA_LANG_STRING ); - Type sourceType = typeWithFQN( JavaTimeConstants.ZONED_DATE_TIME_FQN ); + Type sourceType = typeWithFQN( ZonedDateTime.class.getCanonicalName() ); assertInvalidDateFormat( sourceType, targetType ); assertInvalidDateFormat( targetType, sourceType ); assertValidDateFormat( sourceType, targetType ); assertValidDateFormat( targetType, sourceType ); - sourceType = typeWithFQN( JavaTimeConstants.LOCAL_DATE_FQN ); + sourceType = typeWithFQN( LocalDate.class.getCanonicalName() ); assertInvalidDateFormat( sourceType, targetType ); assertInvalidDateFormat( targetType, sourceType ); assertValidDateFormat( sourceType, targetType ); assertValidDateFormat( targetType, sourceType ); - sourceType = typeWithFQN( JavaTimeConstants.LOCAL_DATE_TIME_FQN ); + sourceType = typeWithFQN( LocalDateTime.class.getCanonicalName() ); assertInvalidDateFormat( sourceType, targetType ); assertInvalidDateFormat( targetType, sourceType ); assertValidDateFormat( sourceType, targetType ); assertValidDateFormat( targetType, sourceType ); - sourceType = typeWithFQN( JavaTimeConstants.LOCAL_TIME_FQN ); + sourceType = typeWithFQN( LocalTime.class.getCanonicalName() ); assertInvalidDateFormat( sourceType, targetType ); assertInvalidDateFormat( targetType, sourceType ); assertValidDateFormat( sourceType, targetType ); @@ -171,6 +175,8 @@ public class DateFormatValidatorFactoryTest { false, false, false, + new HashMap<>( ), + new HashMap<>( ), false, false); } diff --git a/processor/src/test/java/org/mapstruct/ap/internal/model/common/DefaultConversionContextTest.java b/processor/src/test/java/org/mapstruct/ap/internal/model/common/DefaultConversionContextTest.java index 40f7357e9..6b40de313 100755 --- a/processor/src/test/java/org/mapstruct/ap/internal/model/common/DefaultConversionContextTest.java +++ b/processor/src/test/java/org/mapstruct/ap/internal/model/common/DefaultConversionContextTest.java @@ -8,6 +8,8 @@ package org.mapstruct.ap.internal.model.common; import static org.assertj.core.api.Assertions.assertThat; import java.lang.annotation.Annotation; +import java.time.ZonedDateTime; +import java.util.HashMap; import java.util.List; import javax.lang.model.element.AnnotationMirror; @@ -20,7 +22,6 @@ import javax.tools.Diagnostic; import org.junit.Test; import org.mapstruct.ap.internal.util.FormattingMessager; -import org.mapstruct.ap.internal.util.JavaTimeConstants; import org.mapstruct.ap.internal.util.Message; import org.mapstruct.ap.testutil.IssueKey; @@ -62,7 +63,7 @@ public class DefaultConversionContextTest { @Test public void testInvalidDateFormatValidation() { - Type type = typeWithFQN( JavaTimeConstants.ZONED_DATE_TIME_FQN ); + Type type = typeWithFQN( ZonedDateTime.class.getCanonicalName() ); StatefulMessagerMock statefulMessagerMock = new StatefulMessagerMock(); new DefaultConversionContext( null, @@ -76,7 +77,7 @@ public class DefaultConversionContextTest { @Test public void testNullDateFormatValidation() { - Type type = typeWithFQN( JavaTimeConstants.ZONED_DATE_TIME_FQN ); + Type type = typeWithFQN( ZonedDateTime.class.getCanonicalName() ); StatefulMessagerMock statefulMessagerMock = new StatefulMessagerMock(); new DefaultConversionContext( null, @@ -122,6 +123,8 @@ public class DefaultConversionContextTest { false, false, false, + new HashMap<>( ), + new HashMap<>( ), false, false); } diff --git a/processor/src/test/java/org/mapstruct/ap/internal/model/common/TypeFactoryTest.java b/processor/src/test/java/org/mapstruct/ap/internal/model/common/TypeFactoryTest.java deleted file mode 100644 index 7b6fd6410..000000000 --- a/processor/src/test/java/org/mapstruct/ap/internal/model/common/TypeFactoryTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright MapStruct Authors. - * - * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 - */ -package org.mapstruct.ap.internal.model.common; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.Test; - -public class TypeFactoryTest { - - @Test - public void shouldReturnNullIfNoClassNameIsProvided() { - String result = TypeFactory.trimSimpleClassName( null ); - - assertThat( result ).isNull(); - } - - @Test - public void shouldNotModifyClassNameIfNotAnArray() { - String className = "SimpleClass"; - - String result = TypeFactory.trimSimpleClassName( className ); - - assertThat( result ).isEqualTo( className ); - } - - @Test - public void shouldTrimOneDimensionalArray() { - String result = TypeFactory.trimSimpleClassName( "SimpleClass[]" ); - - assertThat( result ).isEqualTo( "SimpleClass" ); - } - - @Test - public void shouldTrimTwoDimensionalArray() { - String result = TypeFactory.trimSimpleClassName( "SimpleClass[][]" ); - - assertThat( result ).isEqualTo( "SimpleClass" ); - } - - @Test - public void shouldTrimMultiDimensionalArray() { - String result = TypeFactory.trimSimpleClassName( "SimpleClass[][][][][]" ); - - assertThat( result ).isEqualTo( "SimpleClass" ); - } -} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1576/java8/Issue1576Mapper.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1576/java8/Issue1576Mapper.java new file mode 100644 index 000000000..a1c5a82a3 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1576/java8/Issue1576Mapper.java @@ -0,0 +1,17 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.bugs._1576.java8; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface Issue1576Mapper { + + Issue1576Mapper INSTANCE = Mappers.getMapper( Issue1576Mapper.class ); + + Target map( Source source ); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1576/java8/Issue1576Test.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1576/java8/Issue1576Test.java new file mode 100644 index 000000000..4b367a15a --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1576/java8/Issue1576Test.java @@ -0,0 +1,32 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.bugs._1576.java8; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; +import org.mapstruct.ap.testutil.runner.GeneratedSource; + +@IssueKey("1576") +@RunWith(AnnotationProcessorTestRunner.class) +@WithClasses( { Issue1576Mapper.class, Source.class, Target.class }) +public class Issue1576Test { + + @Rule + public final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( + Issue1576Mapper.class + ); + + @Test + public void testLocalDateTimeIsImported() { + + Issue1576Mapper.INSTANCE.map( new Source() ); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1576/java8/Source.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1576/java8/Source.java new file mode 100644 index 000000000..c23bb0359 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1576/java8/Source.java @@ -0,0 +1,57 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.bugs._1576.java8; + +import java.util.Date; + +public class Source { + + private Date localDateTime; + private Date localDate; + private String localTime; + private Date zonedDateTime; + private Date instant; + + public Date getLocalDateTime() { + return localDateTime; + } + + public void setLocalDateTime(Date localDateTime) { + this.localDateTime = localDateTime; + } + + public Date getLocalDate() { + return localDate; + } + + public void setLocalDate(Date localDate) { + this.localDate = localDate; + } + + public String getLocalTime() { + return localTime; + } + + public void setLocalTime(String localTime) { + this.localTime = localTime; + } + + public Date getZonedDateTime() { + return zonedDateTime; + } + + public void setZonedDateTime(Date zonedDateTime) { + this.zonedDateTime = zonedDateTime; + } + + public Date getInstant() { + return instant; + } + + public void setInstant(Date instant) { + this.instant = instant; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1576/java8/Target.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1576/java8/Target.java new file mode 100644 index 000000000..e43ecf073 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1576/java8/Target.java @@ -0,0 +1,61 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.bugs._1576.java8; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZonedDateTime; + +public class Target { + + private LocalDateTime localDateTime; + private LocalDate localDate; + private LocalTime localTime; + private ZonedDateTime zonedDateTime; + private Instant instant; + + public LocalDateTime getLocalDateTime() { + return localDateTime; + } + + public void setLocalDateTime(LocalDateTime localDateTime) { + this.localDateTime = localDateTime; + } + + public LocalDate getLocalDate() { + return localDate; + } + + public void setLocalDate(LocalDate localDate) { + this.localDate = localDate; + } + + public LocalTime getLocalTime() { + return localTime; + } + + public void setLocalTime(LocalTime localTime) { + this.localTime = localTime; + } + + public ZonedDateTime getZonedDateTime() { + return zonedDateTime; + } + + public void setZonedDateTime(ZonedDateTime zonedDateTime) { + this.zonedDateTime = zonedDateTime; + } + + public Instant getInstant() { + return instant; + } + + public void setInstant(Instant instant) { + this.instant = instant; + } +} diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/bugs/_1576/java8/Issue1576MapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/bugs/_1576/java8/Issue1576MapperImpl.java new file mode 100644 index 000000000..f15d1b683 --- /dev/null +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/bugs/_1576/java8/Issue1576MapperImpl.java @@ -0,0 +1,48 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.bugs._1576.java8; + +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import javax.annotation.Generated; + +@Generated( + value = "org.mapstruct.ap.MappingProcessor", + date = "2018-11-05T21:40:12+0100", + comments = "version: , compiler: javac, environment: Java 1.8.0_181 (Oracle Corporation)" +) +public class Issue1576MapperImpl implements Issue1576Mapper { + + @Override + public Target map(Source source) { + if ( source == null ) { + return null; + } + + Target target = new Target(); + + if ( source.getLocalDateTime() != null ) { + target.setLocalDateTime( LocalDateTime.ofInstant( source.getLocalDateTime().toInstant(), ZoneId.of( "UTC" ) ) ); + } + if ( source.getLocalDate() != null ) { + target.setLocalDate( LocalDateTime.ofInstant( source.getLocalDate().toInstant(), ZoneOffset.UTC ).toLocalDate() ); + } + if ( source.getLocalTime() != null ) { + target.setLocalTime( LocalTime.parse( source.getLocalTime() ) ); + } + if ( source.getZonedDateTime() != null ) { + target.setZonedDateTime( ZonedDateTime.ofInstant( source.getZonedDateTime().toInstant(), ZoneId.systemDefault() ) ); + } + if ( source.getInstant() != null ) { + target.setInstant( source.getInstant().toInstant() ); + } + + return target; + } +}