From fdf37cf45100c3de685aba5ef397a6701e47d349 Mon Sep 17 00:00:00 2001 From: Filip Hrisafov Date: Thu, 30 Mar 2017 19:18:57 +0200 Subject: [PATCH] #725 Flag the Annotation element with the wrong dateFormat --- .../model/ContainerMappingMethodBuilder.java | 2 +- .../ap/internal/model/MapMappingMethod.java | 2 +- .../internal/model/MappingBuilderContext.java | 2 +- .../ap/internal/model/PropertyMapping.java | 2 +- .../common/DateFormatValidationResult.java | 17 ++- .../common/DefaultConversionContext.java | 15 ++- .../FormattingParameters.java | 28 ++++- .../model/source/IterableMapping.java | 7 +- .../ap/internal/model/source/MapMapping.java | 13 +- .../ap/internal/model/source/Mapping.java | 10 +- .../processor/MapperCreationProcessor.java | 2 +- .../creation/MappingResolverImpl.java | 42 +++---- .../common/DefaultConversionContextTest.java | 27 +++- .../erroneous/ErroneousFormatMapper.java | 58 +++++++++ .../erroneous/InvalidDateFormatTest.java | 98 +++++++++++++++ .../ap/test/conversion/erroneous/Source.java | 117 ++++++++++++++++++ .../ap/test/conversion/erroneous/Target.java | 109 ++++++++++++++++ 17 files changed, 508 insertions(+), 43 deletions(-) rename processor/src/main/java/org/mapstruct/ap/internal/model/{source => common}/FormattingParameters.java (54%) create mode 100644 processor/src/test/java/org/mapstruct/ap/test/conversion/erroneous/ErroneousFormatMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/conversion/erroneous/InvalidDateFormatTest.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/conversion/erroneous/Source.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/conversion/erroneous/Target.java diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/ContainerMappingMethodBuilder.java b/processor/src/main/java/org/mapstruct/ap/internal/model/ContainerMappingMethodBuilder.java index be5d4ea99..a96f73813 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/ContainerMappingMethodBuilder.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/ContainerMappingMethodBuilder.java @@ -28,7 +28,7 @@ import java.util.Set; import org.mapstruct.ap.internal.model.assignment.Assignment; import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.source.ForgedMethod; -import org.mapstruct.ap.internal.model.source.FormattingParameters; +import org.mapstruct.ap.internal.model.common.FormattingParameters; import org.mapstruct.ap.internal.model.source.Method; import org.mapstruct.ap.internal.model.source.SelectionParameters; import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism; diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/MapMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/MapMappingMethod.java index d7f59ecf7..681f6b54e 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/MapMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/MapMappingMethod.java @@ -29,7 +29,7 @@ import org.mapstruct.ap.internal.model.assignment.LocalVarWrapper; import org.mapstruct.ap.internal.model.common.Parameter; import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.source.ForgedMethod; -import org.mapstruct.ap.internal.model.source.FormattingParameters; +import org.mapstruct.ap.internal.model.common.FormattingParameters; import org.mapstruct.ap.internal.model.source.Method; import org.mapstruct.ap.internal.model.source.SelectionParameters; import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism; diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/MappingBuilderContext.java b/processor/src/main/java/org/mapstruct/ap/internal/model/MappingBuilderContext.java index 9053fdc30..cb713ee78 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/MappingBuilderContext.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/MappingBuilderContext.java @@ -32,7 +32,7 @@ import org.mapstruct.ap.internal.model.assignment.Assignment; import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.common.TypeFactory; import org.mapstruct.ap.internal.model.source.ForgedMethod; -import org.mapstruct.ap.internal.model.source.FormattingParameters; +import org.mapstruct.ap.internal.model.common.FormattingParameters; import org.mapstruct.ap.internal.model.source.Method; import org.mapstruct.ap.internal.model.source.SelectionParameters; import org.mapstruct.ap.internal.model.source.SourceMethod; diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java b/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java index d8edebf6a..9fcff9eaf 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java @@ -45,7 +45,7 @@ import org.mapstruct.ap.internal.model.common.Parameter; import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.source.ForgedMethod; import org.mapstruct.ap.internal.model.source.ForgedMethodHistory; -import org.mapstruct.ap.internal.model.source.FormattingParameters; +import org.mapstruct.ap.internal.model.common.FormattingParameters; import org.mapstruct.ap.internal.model.source.MappingOptions; import org.mapstruct.ap.internal.model.source.Method; import org.mapstruct.ap.internal.model.source.ParameterProvidedMethods; diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/common/DateFormatValidationResult.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/DateFormatValidationResult.java index 597ece891..4409d50ea 100755 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/common/DateFormatValidationResult.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/common/DateFormatValidationResult.java @@ -18,6 +18,10 @@ */ package org.mapstruct.ap.internal.model.common; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; + import org.mapstruct.ap.internal.util.FormattingMessager; import org.mapstruct.ap.internal.util.Message; @@ -47,8 +51,17 @@ final class DateFormatValidationResult { return isValid; } - public void printErrorMessage(FormattingMessager messager) { - messager.printMessage( validationInfo, validationInfoArgs ); + /** + * Print the error with the most specific information possible. + * + * @param messager the messager to print the error message to + * @param element the element that had the error + * @param annotation the mirror of the annotation that had an error + * @param value the value of the annotation that had an error + */ + public void printErrorMessage(FormattingMessager messager, Element element, AnnotationMirror annotation, + AnnotationValue value) { + messager.printMessage( element, annotation, value, validationInfo, validationInfoArgs ); } } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/common/DefaultConversionContext.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/DefaultConversionContext.java index 236968a74..d1af4e85e 100755 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/common/DefaultConversionContext.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/common/DefaultConversionContext.java @@ -31,18 +31,20 @@ public class DefaultConversionContext implements ConversionContext { private final FormattingMessager messager; private final Type sourceType; private final Type targetType; + private final FormattingParameters formattingParameters; private final String dateFormat; private final String numberFormat; private final TypeFactory typeFactory; public DefaultConversionContext(TypeFactory typeFactory, FormattingMessager messager, Type sourceType, - Type targetType, String dateFormat, String numberFormat) { + Type targetType, FormattingParameters formattingParameters) { this.typeFactory = typeFactory; this.messager = messager; this.sourceType = sourceType; this.targetType = targetType; - this.dateFormat = dateFormat; - this.numberFormat = numberFormat; + this.formattingParameters = formattingParameters; + this.dateFormat = this.formattingParameters.getDate(); + this.numberFormat = this.formattingParameters.getNumber(); validateDateFormat(); } @@ -55,7 +57,12 @@ public class DefaultConversionContext implements ConversionContext { DateFormatValidationResult validationResult = dateFormatValidator.validate( dateFormat ); if ( !validationResult.isValid() ) { - validationResult.printErrorMessage( messager ); + validationResult.printErrorMessage( + messager, + formattingParameters.getElement(), + formattingParameters.getMirror(), + formattingParameters.getDateAnnotationValue() + ); } } } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/FormattingParameters.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/FormattingParameters.java similarity index 54% rename from processor/src/main/java/org/mapstruct/ap/internal/model/source/FormattingParameters.java rename to processor/src/main/java/org/mapstruct/ap/internal/model/common/FormattingParameters.java index 7d4e406a9..57428684f 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/FormattingParameters.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/common/FormattingParameters.java @@ -16,7 +16,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.mapstruct.ap.internal.model.source; +package org.mapstruct.ap.internal.model.common; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; /** * @@ -24,12 +28,21 @@ package org.mapstruct.ap.internal.model.source; */ public class FormattingParameters { + public static final FormattingParameters EMPTY = new FormattingParameters( null, null, null, null, null ); + private final String date; private final String number; + private final AnnotationMirror mirror; + private final AnnotationValue dateAnnotationValue; + private final Element element; - public FormattingParameters(String date, String number) { + public FormattingParameters(String date, String number, AnnotationMirror mirror, + AnnotationValue dateAnnotationValue, Element element) { this.date = date; this.number = number; + this.mirror = mirror; + this.dateAnnotationValue = dateAnnotationValue; + this.element = element; } public String getDate() { @@ -40,4 +53,15 @@ public class FormattingParameters { return number; } + public AnnotationMirror getMirror() { + return mirror; + } + + public AnnotationValue getDateAnnotationValue() { + return dateAnnotationValue; + } + + public Element getElement() { + return element; + } } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/IterableMapping.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/IterableMapping.java index 4121459de..f7cdcdc2e 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/IterableMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/IterableMapping.java @@ -22,6 +22,7 @@ import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.ExecutableElement; import javax.lang.model.type.TypeKind; +import org.mapstruct.ap.internal.model.common.FormattingParameters; import org.mapstruct.ap.internal.prism.IterableMappingPrism; import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism; import org.mapstruct.ap.internal.util.FormattingMessager; @@ -69,7 +70,11 @@ public class IterableMapping { FormattingParameters formatting = new FormattingParameters( iterableMapping.dateFormat(), - iterableMapping.numberFormat() ); + iterableMapping.numberFormat(), + iterableMapping.mirror, + iterableMapping.values.dateFormat(), + method + ); return new IterableMapping( formatting, selection, diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MapMapping.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MapMapping.java index 7b73ad30d..ecfe67ff5 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MapMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MapMapping.java @@ -22,6 +22,7 @@ import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.ExecutableElement; import javax.lang.model.type.TypeKind; +import org.mapstruct.ap.internal.model.common.FormattingParameters; import org.mapstruct.ap.internal.prism.MapMappingPrism; import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism; import org.mapstruct.ap.internal.util.FormattingMessager; @@ -82,11 +83,19 @@ public class MapMapping { FormattingParameters keyFormatting = new FormattingParameters( mapMapping.keyDateFormat(), - mapMapping.keyNumberFormat() ); + mapMapping.keyNumberFormat(), + mapMapping.mirror, + mapMapping.values.keyDateFormat(), + method + ); FormattingParameters valueFormatting = new FormattingParameters( mapMapping.valueDateFormat(), - mapMapping.valueNumberFormat() ); + mapMapping.valueNumberFormat(), + mapMapping.mirror, + mapMapping.values.valueDateFormat(), + method + ); return new MapMapping( keyFormatting, diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/Mapping.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/Mapping.java index 137628f71..c225adc13 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/Mapping.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/Mapping.java @@ -32,6 +32,8 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; + +import org.mapstruct.ap.internal.model.common.FormattingParameters; import org.mapstruct.ap.internal.model.common.Parameter; import org.mapstruct.ap.internal.model.common.TypeFactory; import org.mapstruct.ap.internal.prism.CollectionMappingStrategyPrism; @@ -140,7 +142,13 @@ public class Mapping { mappingPrism.dependsOn() != null ? mappingPrism.dependsOn() : Collections.emptyList(); - FormattingParameters formattingParam = new FormattingParameters( dateFormat, numberFormat ); + FormattingParameters formattingParam = new FormattingParameters( + dateFormat, + numberFormat, + mappingPrism.mirror, + mappingPrism.values.dateFormat(), + element + ); SelectionParameters selectionParams = new SelectionParameters( mappingPrism.qualifiedBy(), mappingPrism.qualifiedByName(), diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java index 1ae005cb0..a6908c4af 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java @@ -49,7 +49,7 @@ import org.mapstruct.ap.internal.model.StreamMappingMethod; import org.mapstruct.ap.internal.model.ValueMappingMethod; import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.common.TypeFactory; -import org.mapstruct.ap.internal.model.source.FormattingParameters; +import org.mapstruct.ap.internal.model.common.FormattingParameters; import org.mapstruct.ap.internal.model.source.MappingOptions; import org.mapstruct.ap.internal.model.source.Method; import org.mapstruct.ap.internal.model.source.SelectionParameters; diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/creation/MappingResolverImpl.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/creation/MappingResolverImpl.java index f261d3475..e86e7c7fe 100755 --- a/processor/src/main/java/org/mapstruct/ap/internal/processor/creation/MappingResolverImpl.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/creation/MappingResolverImpl.java @@ -49,7 +49,7 @@ import org.mapstruct.ap.internal.model.common.ConversionContext; import org.mapstruct.ap.internal.model.common.DefaultConversionContext; import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.common.TypeFactory; -import org.mapstruct.ap.internal.model.source.FormattingParameters; +import org.mapstruct.ap.internal.model.common.FormattingParameters; import org.mapstruct.ap.internal.model.source.Method; import org.mapstruct.ap.internal.model.source.SelectionParameters; import org.mapstruct.ap.internal.model.source.builtin.BuiltInMappingMethods; @@ -111,18 +111,10 @@ public class MappingResolverImpl implements MappingResolver { SelectionCriteria criteria = SelectionCriteria.forMappingMethods( selectionParameters, targetPropertyName, preferUpdateMapping ); - String dateFormat = null; - String numberFormat = null; - if ( formattingParameters != null ) { - dateFormat = formattingParameters.getDate(); - numberFormat = formattingParameters.getNumber(); - } - ResolvingAttempt attempt = new ResolvingAttempt( sourceModel, mappingMethod, - dateFormat, - numberFormat, + formattingParameters, sourceRHS, criteria ); @@ -186,24 +178,23 @@ public class MappingResolverImpl implements MappingResolver { private final Method mappingMethod; private final List methods; - private final String dateFormat; - private final String numberFormat; private final SelectionCriteria selectionCriteria; private final SourceRHS sourceRHS; private final boolean savedPreferUpdateMapping; + private final FormattingParameters formattingParameters; // resolving via 2 steps creates the possibillity of wrong matches, first builtin method matches, // second doesn't. In that case, the first builtin method should not lead to a virtual method // so this set must be cleared. private final Set virtualMethodCandidates; - private ResolvingAttempt(List sourceModel, Method mappingMethod, String dateFormat, - String numberFormat, SourceRHS sourceRHS, SelectionCriteria criteria) { + private ResolvingAttempt(List sourceModel, Method mappingMethod, + FormattingParameters formattingParameters, SourceRHS sourceRHS, SelectionCriteria criteria) { this.mappingMethod = mappingMethod; this.methods = filterPossibleCandidateMethods( sourceModel ); - this.dateFormat = dateFormat; - this.numberFormat = numberFormat; + this.formattingParameters = + formattingParameters == null ? FormattingParameters.EMPTY : formattingParameters; this.sourceRHS = sourceRHS; this.virtualMethodCandidates = new HashSet(); this.selectionCriteria = criteria; @@ -286,8 +277,13 @@ public class MappingResolverImpl implements MappingResolver { if ( conversionProvider == null ) { return null; } - ConversionContext ctx = new DefaultConversionContext( typeFactory, messager, sourceType, targetType, - dateFormat, numberFormat ); + ConversionContext ctx = new DefaultConversionContext( + typeFactory, + messager, + sourceType, + targetType, + formattingParameters + ); // add helper methods required in conversion for ( HelperMethod helperMethod : conversionProvider.getRequiredHelperMethods( ctx ) ) { @@ -322,9 +318,13 @@ public class MappingResolverImpl implements MappingResolver { if ( matchingBuiltInMethod != null ) { virtualMethodCandidates.add( new VirtualMappingMethod( matchingBuiltInMethod.getMethod() ) ); - ConversionContext ctx = new DefaultConversionContext( typeFactory, messager, - sourceType, - targetType, dateFormat, numberFormat); + ConversionContext ctx = new DefaultConversionContext( + typeFactory, + messager, + sourceType, + targetType, + formattingParameters + ); Assignment methodReference = MethodReference.forBuiltInMethod( matchingBuiltInMethod.getMethod(), ctx ); methodReference.setAssignment( sourceRHS ); return methodReference; 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 3995946c2..c6b5ce2cf 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 @@ -78,7 +78,12 @@ public class DefaultConversionContextTest { Type type = typeWithFQN( JavaTimeConstants.ZONED_DATE_TIME_FQN ); StatefulMessagerMock statefulMessagerMock = new StatefulMessagerMock(); new DefaultConversionContext( - null, statefulMessagerMock, type, type, "qwertz", null); + null, + statefulMessagerMock, + type, + type, + new FormattingParameters( "qwertz", null, null, null, null ) + ); assertThat( statefulMessagerMock.getLastKindPrinted() ).isEqualTo( Diagnostic.Kind.ERROR ); } @@ -87,7 +92,12 @@ public class DefaultConversionContextTest { Type type = typeWithFQN( JavaTimeConstants.ZONED_DATE_TIME_FQN ); StatefulMessagerMock statefulMessagerMock = new StatefulMessagerMock(); new DefaultConversionContext( - null, statefulMessagerMock, type, type, null, null); + null, + statefulMessagerMock, + type, + type, + new FormattingParameters( null, null, null, null, null ) + ); assertThat( statefulMessagerMock.getLastKindPrinted() ).isNull(); } @@ -95,8 +105,12 @@ public class DefaultConversionContextTest { public void testUnsupportedType() { Type type = typeWithFQN( "java.lang.String" ); StatefulMessagerMock statefulMessagerMock = new StatefulMessagerMock(); - new DefaultConversionContext( - null, statefulMessagerMock, type, type, "qwertz", null); + new DefaultConversionContext( null, + statefulMessagerMock, + type, + type, + new FormattingParameters( "qwertz", null, null, null, null ) + ); assertThat( statefulMessagerMock.getLastKindPrinted() ).isNull(); } @@ -128,19 +142,22 @@ public class DefaultConversionContextTest { @Override public void printMessage(Message msg, Object... arg) { - lastKindPrinted = msg.getDiagnosticKind(); + throw new UnsupportedOperationException( "Should not be called" ); } @Override public void printMessage(Element e, Message msg, Object... arg) { + throw new UnsupportedOperationException( "Should not be called" ); } @Override public void printMessage(Element e, AnnotationMirror a, Message msg, Object... arg) { + throw new UnsupportedOperationException( "Should not be called" ); } @Override public void printMessage(Element e, AnnotationMirror a, AnnotationValue v, Message msg, Object... arg) { + lastKindPrinted = msg.getDiagnosticKind(); } public Diagnostic.Kind getLastKindPrinted() { diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/erroneous/ErroneousFormatMapper.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/erroneous/ErroneousFormatMapper.java new file mode 100644 index 000000000..7f059125d --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/erroneous/ErroneousFormatMapper.java @@ -0,0 +1,58 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.conversion.erroneous; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +import org.mapstruct.IterableMapping; +import org.mapstruct.MapMapping; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; + +/** + * @author Filip Hrisafov + */ +@Mapper +public interface ErroneousFormatMapper { + + @Mappings( { + @Mapping(target = "date", dateFormat = "qwertz"), + @Mapping(target = "zonedDateTime", dateFormat = "qwertz"), + @Mapping(target = "localDateTime", dateFormat = "qwertz"), + @Mapping(target = "localDate", dateFormat = "qwertz"), + @Mapping(target = "localTime", dateFormat = "qwertz"), + @Mapping(target = "dateTime", dateFormat = "qwertz"), + @Mapping(target = "jodaLocalDateTime", dateFormat = "qwertz"), + @Mapping(target = "jodaLocalDate", dateFormat = "qwertz"), + @Mapping(target = "jodaLocalTime", dateFormat = "qwertz") + } ) + Target sourceToTarget(Source source); + + @IterableMapping(dateFormat = "qwertz") + List fromDates(List dates); + + @MapMapping(keyDateFormat = "qwertz") + Map fromDateKeys(Map dates); + + @MapMapping(valueDateFormat = "qwertz") + Map fromDateValues(Map dates); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/erroneous/InvalidDateFormatTest.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/erroneous/InvalidDateFormatTest.java new file mode 100644 index 000000000..09c4ad2c3 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/erroneous/InvalidDateFormatTest.java @@ -0,0 +1,98 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.conversion.erroneous; + +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.compilation.annotation.CompilationResult; +import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic; +import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome; +import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; + +/** + * @author Filip Hrisafov + */ +@WithClasses({ + Source.class, + Target.class +}) +@IssueKey("725") +@RunWith(AnnotationProcessorTestRunner.class) +public class InvalidDateFormatTest { + + @WithClasses({ + ErroneousFormatMapper.class + }) + @ExpectedCompilationOutcome(value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic(type = ErroneousFormatMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 38, + messageRegExp = "Given date format \"qwertz\" is invalid. Message: \"Illegal pattern character 'q'\""), + @Diagnostic(type = ErroneousFormatMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 39, + messageRegExp = "Given date format \"qwertz\" is invalid. Message: \"Unknown pattern letter: r\"\\."), + @Diagnostic(type = ErroneousFormatMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 40, + messageRegExp = "Given date format \"qwertz\" is invalid. Message: \"Unknown pattern letter: r\"\\."), + @Diagnostic(type = ErroneousFormatMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 41, + messageRegExp = "Given date format \"qwertz\" is invalid. Message: \"Unknown pattern letter: r\"\\."), + @Diagnostic(type = ErroneousFormatMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 42, + messageRegExp = "Given date format \"qwertz\" is invalid. Message: \"Unknown pattern letter: r\"\\."), + @Diagnostic(type = ErroneousFormatMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 43, + messageRegExp = "Given date format \"qwertz\" is invalid. Message: \"Illegal pattern component: q\""), + @Diagnostic(type = ErroneousFormatMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 44, + messageRegExp = "Given date format \"qwertz\" is invalid. Message: \"Illegal pattern component: q\""), + @Diagnostic(type = ErroneousFormatMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 45, + messageRegExp = "Given date format \"qwertz\" is invalid. Message: \"Illegal pattern component: q\""), + @Diagnostic(type = ErroneousFormatMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 46, + messageRegExp = "Given date format \"qwertz\" is invalid. Message: \"Illegal pattern component: q\""), + @Diagnostic(type = ErroneousFormatMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 50, + messageRegExp = "Given date format \"qwertz\" is invalid. Message: \"Illegal pattern character 'q'\""), + @Diagnostic(type = ErroneousFormatMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 53, + messageRegExp = "Given date format \"qwertz\" is invalid. Message: \"Illegal pattern character 'q'\""), + @Diagnostic(type = ErroneousFormatMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 56, + messageRegExp = "Given date format \"qwertz\" is invalid. Message: \"Illegal pattern character 'q'\"") + }) + @Test + public void shouldFailWithInvalidDateFormats() { + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/erroneous/Source.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/erroneous/Source.java new file mode 100644 index 000000000..8614d1d6d --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/erroneous/Source.java @@ -0,0 +1,117 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.conversion.erroneous; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZonedDateTime; +import java.util.Date; + +import org.joda.time.DateTime; + +/** + * @author Filip Hrisafov + */ +public class Source { + + private Date date; + + private ZonedDateTime zonedDateTime; + private LocalDateTime localDateTime; + private LocalDate localDate; + private LocalTime localTime; + + private DateTime dateTime; + private org.joda.time.LocalDateTime jodaLocalDateTime; + private org.joda.time.LocalDate jodaLocalDate; + private org.joda.time.LocalTime jodaLocalTime; + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public ZonedDateTime getZonedDateTime() { + return zonedDateTime; + } + + public void setZonedDateTime(ZonedDateTime zonedDateTime) { + this.zonedDateTime = zonedDateTime; + } + + 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 DateTime getDateTime() { + return dateTime; + } + + public void setDateTime(DateTime dateTime) { + this.dateTime = dateTime; + } + + public org.joda.time.LocalDateTime getJodaLocalDateTime() { + return jodaLocalDateTime; + } + + public void setJodaLocalDateTime(org.joda.time.LocalDateTime jodaLocalDateTime) { + this.jodaLocalDateTime = jodaLocalDateTime; + } + + public org.joda.time.LocalDate getJodaLocalDate() { + return jodaLocalDate; + } + + public void setJodaLocalDate(org.joda.time.LocalDate jodaLocalDate) { + this.jodaLocalDate = jodaLocalDate; + } + + public org.joda.time.LocalTime getJodaLocalTime() { + return jodaLocalTime; + } + + public void setJodaLocalTime(org.joda.time.LocalTime jodaLocalTime) { + this.jodaLocalTime = jodaLocalTime; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/erroneous/Target.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/erroneous/Target.java new file mode 100644 index 000000000..a6a71b8fd --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/erroneous/Target.java @@ -0,0 +1,109 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.conversion.erroneous; + +/** + * @author Filip Hrisafov + */ +public class Target { + + private String date; + + private String zonedDateTime; + private String localDateTime; + private String localDate; + private String localTime; + + private String dateTime; + private String jodaLocalDateTime; + private String jodaLocalDate; + private String jodaLocalTime; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String getZonedDateTime() { + return zonedDateTime; + } + + public void setZonedDateTime(String zonedDateTime) { + this.zonedDateTime = zonedDateTime; + } + + public String getLocalDateTime() { + return localDateTime; + } + + public void setLocalDateTime(String localDateTime) { + this.localDateTime = localDateTime; + } + + public String getLocalDate() { + return localDate; + } + + public void setLocalDate(String localDate) { + this.localDate = localDate; + } + + public String getLocalTime() { + return localTime; + } + + public void setLocalTime(String localTime) { + this.localTime = localTime; + } + + public String getDateTime() { + return dateTime; + } + + public void setDateTime(String dateTime) { + this.dateTime = dateTime; + } + + public String getJodaLocalDateTime() { + return jodaLocalDateTime; + } + + public void setJodaLocalDateTime(String jodaLocalDateTime) { + this.jodaLocalDateTime = jodaLocalDateTime; + } + + public String getJodaLocalDate() { + return jodaLocalDate; + } + + public void setJodaLocalDate(String jodaLocalDate) { + this.jodaLocalDate = jodaLocalDate; + } + + public String getJodaLocalTime() { + return jodaLocalTime; + } + + public void setJodaLocalTime(String jodaLocalTime) { + this.jodaLocalTime = jodaLocalTime; + } +}