From e701801ec568d9aafe3b1c0656fad9f6b993ba54 Mon Sep 17 00:00:00 2001 From: sjaakd Date: Sat, 19 Apr 2014 20:09:08 +0200 Subject: [PATCH] #187 introducing constant mapping --- core/src/main/java/org/mapstruct/Mapping.java | 19 ++- .../mapstruct/ap/model/BeanMappingMethod.java | 35 +++-- .../mapstruct/ap/model/source/Mapping.java | 93 ++++++++----- .../ap/processor/MapperCreationProcessor.java | 119 +++++++++++++++-- .../processor/MethodRetrievalProcessor.java | 7 +- ...g.mapstruct.ap.model.BeanMappingMethod.ftl | 3 + .../sourceconstants/ErroneousMapper1.java | 43 ++++++ .../sourceconstants/ErroneousMapper2.java | 43 ++++++ .../ap/test/sourceconstants/Source.java | 39 ++++++ .../sourceconstants/SourceConstantsTest.java | 122 ++++++++++++++++++ .../sourceconstants/SourceTargetMapper.java | 43 ++++++ .../sourceconstants/StringListMapper.java | 30 +++++ .../ap/test/sourceconstants/Target.java | 85 ++++++++++++ 13 files changed, 625 insertions(+), 56 deletions(-) create mode 100644 processor/src/test/java/org/mapstruct/ap/test/sourceconstants/ErroneousMapper1.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/sourceconstants/ErroneousMapper2.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/sourceconstants/Source.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/sourceconstants/SourceConstantsTest.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/sourceconstants/SourceTargetMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/sourceconstants/StringListMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/sourceconstants/Target.java diff --git a/core/src/main/java/org/mapstruct/Mapping.java b/core/src/main/java/org/mapstruct/Mapping.java index 872cba812..1b156f53f 100644 --- a/core/src/main/java/org/mapstruct/Mapping.java +++ b/core/src/main/java/org/mapstruct/Mapping.java @@ -35,12 +35,15 @@ import java.util.Date; public @interface Mapping { /** - * The source name of the configured property as defined by the JavaBeans specification. If used to map an enum - * constant, the name of the constant member is to be given. + * The source to use for this Mapping. This can either be: + *
    + *
  1. The source name of the configured property as defined by the JavaBeans specification.
  2. + *
  3. When used to map an enum constant, the name of the constant member is to be given<./li>. + *
* - * @return The source name of the configured property or enum constant + * @return The source name of the configured property or enum constant. */ - String source(); + String source() default ""; /** * The target name of the configured property as defined by the JavaBeans specification. Defaults to the source name @@ -57,4 +60,12 @@ public @interface Mapping { * @return A date format string as processable by {@link SimpleDateFormat}. */ String dateFormat() default ""; + + /** + * {@link String} expression that uses available mappings and conversion to set the designated target property to + * the provided expression. + * + * @return expression + */ + String expression() default ""; } diff --git a/processor/src/main/java/org/mapstruct/ap/model/BeanMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/model/BeanMappingMethod.java index 65a9ed6e7..83f61f2f3 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/BeanMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/model/BeanMappingMethod.java @@ -38,6 +38,10 @@ import org.mapstruct.ap.model.source.SourceMethod; public class BeanMappingMethod extends MappingMethod { private final List propertyMappings; + private final Map> mappingsByParameter; + private final List constantMappings; + + private final FactoryMethod factoryMethod; public BeanMappingMethod(SourceMethod method, @@ -45,6 +49,22 @@ public class BeanMappingMethod extends MappingMethod { FactoryMethod factoryMethod) { super( method ); this.propertyMappings = propertyMappings; + + + // intialize constant mappings as all mappings, but take out the ones that can be contributed to a + // parameter mapping. + this.mappingsByParameter = new HashMap>(); + this.constantMappings = new ArrayList( propertyMappings ); + for ( Parameter sourceParameter : getSourceParameters() ) { + ArrayList mappingsOfParameter = new ArrayList(); + mappingsByParameter.put( sourceParameter.getName(), mappingsOfParameter ); + for ( PropertyMapping mapping : propertyMappings ) { + if ( sourceParameter.getName().equals( mapping.getSourceBeanName() ) ) { + mappingsOfParameter.add( mapping ); + constantMappings.remove( mapping ); + } + } + } this.factoryMethod = factoryMethod; } @@ -52,18 +72,11 @@ public class BeanMappingMethod extends MappingMethod { return propertyMappings; } - public Map> getPropertyMappingsByParameter() { - Map> mappingsByParameter = new HashMap>(); + public List getConstantMappings() { + return constantMappings; + } - for ( Parameter sourceParameter : getSourceParameters() ) { - ArrayList mappingsOfParameter = new ArrayList(); - mappingsByParameter.put( sourceParameter.getName(), mappingsOfParameter ); - for ( PropertyMapping mapping : propertyMappings ) { - if ( mapping.getSourceBeanName().equals( sourceParameter.getName() ) ) { - mappingsOfParameter.add( mapping ); - } - } - } + public Map> getPropertyMappingsByParameter() { return mappingsByParameter; } diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/Mapping.java b/processor/src/main/java/org/mapstruct/ap/model/source/Mapping.java index 59ae76025..b30ac84af 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/source/Mapping.java +++ b/processor/src/main/java/org/mapstruct/ap/model/source/Mapping.java @@ -22,9 +22,11 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.annotation.processing.Messager; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; +import javax.tools.Diagnostic; import org.mapstruct.ap.prism.MappingPrism; import org.mapstruct.ap.prism.MappingsPrism; @@ -40,42 +42,63 @@ public class Mapping { private final String sourceName; private final String sourceParameterName; private final String sourcePropertyName; + private final String expression; private final String targetName; private final String dateFormat; private final AnnotationMirror mirror; private final AnnotationValue sourceAnnotationValue; private final AnnotationValue targetAnnotationValue; - public static Map> fromMappingsPrism(MappingsPrism mappingsAnnotation, Element element) { + public static Map> fromMappingsPrism(MappingsPrism mappingsAnnotation, Element element, + Messager messager) { Map> mappings = new HashMap>(); - for ( MappingPrism mapping : mappingsAnnotation.value() ) { - if ( !mappings.containsKey( mapping.source() ) ) { - mappings.put( mapping.source(), new ArrayList() ); + for ( MappingPrism mappingPrism : mappingsAnnotation.value() ) { + if ( !mappings.containsKey( mappingPrism.source() ) ) { + mappings.put( mappingPrism.source(), new ArrayList() ); + } + Mapping mapping = fromMappingPrism( mappingPrism, element, messager ); + if ( mapping != null ) { + mappings.get( mappingPrism.source() ).add( mapping ); } - mappings.get( mapping.source() ).add( fromMappingPrism( mapping, element ) ); } return mappings; } - public static Mapping fromMappingPrism(MappingPrism mapping, Element element) { + public static Mapping fromMappingPrism(MappingPrism mappingPrism, Element element, Messager messager) { String[] sourceNameParts = getSourceNameParts( - mapping.source(), + mappingPrism.source(), element, - mapping.mirror, - mapping.values.source() + mappingPrism.mirror, + mappingPrism.values.source() ); + if ( mappingPrism.source().isEmpty() && mappingPrism.expression().isEmpty() ) { + messager.printMessage( Diagnostic.Kind.ERROR, + "Either define a source or an expression in a Mapping", + element + ); + return null; + } + else if ( !mappingPrism.source().isEmpty() && !mappingPrism.expression().isEmpty() ) { + messager.printMessage( Diagnostic.Kind.ERROR, + "Source and expression are both defined in Mapping, either define a source or an expression", + element + ); + return null; + } + return new Mapping( - mapping.source(), + mappingPrism.source(), sourceNameParts != null ? sourceNameParts[0] : null, - sourceNameParts != null ? sourceNameParts[1] : mapping.source(), - mapping.target(), - mapping.dateFormat(), - mapping.mirror, - mapping.values.source(), - mapping.values.target() + sourceNameParts != null ? sourceNameParts[1] : mappingPrism.source(), + mappingPrism.expression(), + mappingPrism.target(), + mappingPrism.dateFormat(), + mappingPrism.mirror, + mappingPrism.values.source(), + mappingPrism.values.target() ); } @@ -98,12 +121,13 @@ public class Mapping { return parts; } - private Mapping(String sourceName, String sourceParameterName, String sourcePropertyName, String targetName, - String dateFormat, AnnotationMirror mirror, AnnotationValue sourceAnnotationValue, - AnnotationValue targetAnnotationValue) { + private Mapping(String sourceName, String sourceParameterName, String sourcePropertyName, String expression, + String targetName, String dateFormat, AnnotationMirror mirror, + AnnotationValue sourceAnnotationValue, AnnotationValue targetAnnotationValue) { this.sourceName = sourceName; this.sourceParameterName = sourceParameterName; this.sourcePropertyName = sourcePropertyName; + this.expression = expression; this.targetName = targetName.equals( "" ) ? sourceName : targetName; this.dateFormat = dateFormat; this.mirror = mirror; @@ -139,6 +163,11 @@ public class Mapping { return sourceParameterName; } + public String getExpression() { + return expression; + } + + public String getTargetName() { return targetName; } @@ -160,16 +189,22 @@ public class Mapping { } public Mapping reverse() { - return new Mapping( - targetName, - null, - targetName, - sourceName, - dateFormat, - mirror, - sourceAnnotationValue, - targetAnnotationValue - ); + Mapping reverse = null; + if ( expression != null ) { + /* mapping can only be reversed if the source was not a constant */ + reverse = new Mapping( + targetName, + null, + targetName, + expression, + sourceName, + dateFormat, + mirror, + sourceAnnotationValue, + targetAnnotationValue + ); + } + return reverse; } @Override diff --git a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java index e2b775bc3..6669f058d 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java @@ -376,7 +376,10 @@ public class MapperCreationProcessor implements ModelElementProcessor() ); } - reversed.get( mapping.getTargetName() ).add( mapping.reverse() ); + Mapping reverseMapping = mapping.reverse(); + if ( reverseMapping != null ) { + reversed.get( mapping.getTargetName() ).add( reverseMapping ); + } } } return reversed; @@ -387,12 +390,39 @@ public class MapperCreationProcessor implements ModelElementProcessor sourceGetters = parameter.getType().getGetters(); + // check constants first + if ( isSourceConstant ) { + return getConstantMapping( + mapperReferences, + methods, + method, + sourceConstant, + targetAcessor, + dateFormat + ); + } + + // then iterate over source accessors (assuming the source is a bean) for ( ExecutableElement sourceAccessor : sourceGetters ) { List sourceMappings = method.getMappings().get( sourcePropertyName ); @@ -425,7 +455,6 @@ public class MapperCreationProcessor implements ModelElementProcessor mapperReferences, + private PropertyMapping getPropertyMapping(List mapperReferences, List methods, SourceMethod method, Parameter parameter, @@ -703,6 +730,78 @@ public class MapperCreationProcessor implements ModelElementProcessor mapperReferences, + List methods, + SourceMethod method, + String sourceReference, + ExecutableElement targetAcessor, + String dateFormat) { + + // source + String mappedElement = "constant '" + sourceReference + "'"; + Type sourceType = typeFactory.getType( String.class ); + + // target + Type targetType = null; + if ( Executables.isSetterMethod( targetAcessor ) ) { + targetType = typeFactory.getSingleParameter( targetAcessor ).getType(); + } + else if ( Executables.isGetterMethod( targetAcessor ) ) { + targetType = typeFactory.getReturnType( targetAcessor ); + } + String targetPropertyName = Executables.getPropertyName( targetAcessor ); + + + Assignment assignment = mappingResolver.getTargetAssignment( + method, + mappedElement, + mapperReferences, + methods, + sourceType, + targetType, + targetPropertyName, + dateFormat, + sourceReference + ); + + if ( assignment != null ) { + + // create a new Map or Collection implementation if no method or type conversion + if ( targetType != null && ( targetType.isCollectionType() || targetType.isMapType() ) ) { + if ( assignment.isSimple() ) { + assignment = new NewCollectionOrMapWrapper( assignment ); + } + } + + // target accessor is setter, so decorate assigmment as setter + assignment = new SetterWrapper( assignment ); + + } + else { + messager.printMessage( + Kind.ERROR, + String.format( + "Can't map \"%s %s\" to \"%s %s\".", + sourceType, + sourceReference, + targetType, + Executables.getPropertyName( targetAcessor ) + ), + method.getExecutable() + ); + } + return new PropertyMapping( + null, + null, + null, + sourceType, + Executables.getPropertyName( targetAcessor ), + targetAcessor.getSimpleName().toString(), + targetType, + assignment + ); + } + private IterableMappingMethod getIterableMappingMethod(List mapperReferences, List methods, SourceMethod method) { diff --git a/processor/src/main/java/org/mapstruct/ap/processor/MethodRetrievalProcessor.java b/processor/src/main/java/org/mapstruct/ap/processor/MethodRetrievalProcessor.java index 06c7eace7..0eaeaec8d 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/MethodRetrievalProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/MethodRetrievalProcessor.java @@ -384,11 +384,14 @@ public class MethodRetrievalProcessor implements ModelElementProcessor() ); } - mappings.get( mappingAnnotation.source() ).add( Mapping.fromMappingPrism( mappingAnnotation, method ) ); + Mapping mapping = Mapping.fromMappingPrism( mappingAnnotation, method, messager ); + if ( mapping != null ) { + mappings.get( mappingAnnotation.source() ).add( mapping ); + } } if ( mappingsAnnotation != null ) { - mappings.putAll( Mapping.fromMappingsPrism( mappingsAnnotation, method ) ); + mappings.putAll( Mapping.fromMappingsPrism( mappingsAnnotation, method, messager ) ); } return mappings; diff --git a/processor/src/main/resources/org.mapstruct.ap.model.BeanMappingMethod.ftl b/processor/src/main/resources/org.mapstruct.ap.model.BeanMappingMethod.ftl index 734e75212..54301f3ff 100644 --- a/processor/src/main/resources/org.mapstruct.ap.model.BeanMappingMethod.ftl +++ b/processor/src/main/resources/org.mapstruct.ap.model.BeanMappingMethod.ftl @@ -38,6 +38,9 @@ <@includeModel object=propertyMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping/> + <#list constantMappings as constantMapping> + <@includeModel object=constantMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping/> + <#if returnType.name != "void"> return ${resultName}; diff --git a/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/ErroneousMapper1.java b/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/ErroneousMapper1.java new file mode 100644 index 000000000..5195124d4 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/ErroneousMapper1.java @@ -0,0 +1,43 @@ +/** + * Copyright 2012-2014 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.sourceconstants; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ +@Mapper(uses = StringListMapper.class) +public interface ErroneousMapper1 { + + ErroneousMapper1 INSTANCE = Mappers.getMapper( ErroneousMapper1.class ); + + @Mappings( { + @Mapping( target = "stringConstant", expression = "stringConstant"), + @Mapping( source = "test" , target = "integerConstant", expression = "14"), + @Mapping( target = "longWrapperConstant", expression = "3001"), + @Mapping( target = "dateConstant", dateFormat = "dd-MM-yyyy", expression = "09-01-2014"), + @Mapping( target = "nameConstants", expression = "jack-jill-tom" ) + } ) + Target sourceToTarget(Source s); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/ErroneousMapper2.java b/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/ErroneousMapper2.java new file mode 100644 index 000000000..c28837349 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/ErroneousMapper2.java @@ -0,0 +1,43 @@ +/** + * Copyright 2012-2014 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.sourceconstants; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ +@Mapper(uses = StringListMapper.class) +public interface ErroneousMapper2 { + + ErroneousMapper2 INSTANCE = Mappers.getMapper( ErroneousMapper2.class ); + + @Mappings( { + @Mapping( target = "stringConstant", expression = "stringConstant"), + @Mapping( target = "integerConstant" ), + @Mapping( target = "longWrapperConstant", expression = "3001"), + @Mapping( target = "dateConstant", dateFormat = "dd-MM-yyyy", expression = "09-01-2014"), + @Mapping( target = "nameConstants", expression = "jack-jill-tom" ) + } ) + Target sourceToTarget(Source s); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/Source.java b/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/Source.java new file mode 100644 index 000000000..c5b9f72b7 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/Source.java @@ -0,0 +1,39 @@ +/** + * Copyright 2012-2014 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.sourceconstants; + +/** + * + * @author Sjaak Derksen + */ +public class Source { + + private String propertyThatShouldBeMapped; + + public String getPropertyThatShouldBeMapped() { + return propertyThatShouldBeMapped; + } + + public void setPropertyThatShouldBeMapped( String propertyThatShouldBeMapped ) { + this.propertyThatShouldBeMapped = propertyThatShouldBeMapped; + } + + + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/SourceConstantsTest.java b/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/SourceConstantsTest.java new file mode 100644 index 000000000..42d2dc9ac --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/SourceConstantsTest.java @@ -0,0 +1,122 @@ +/** + * Copyright 2012-2014 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.sourceconstants; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import javax.tools.Diagnostic.Kind; +import static org.fest.assertions.Assertions.assertThat; +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 Sjaak Derksen + */ + +@RunWith(AnnotationProcessorTestRunner.class) +public class SourceConstantsTest { + + @Test + @IssueKey( "187" ) + @WithClasses( { + Source.class, + Target.class, + SourceTargetMapper.class, + StringListMapper.class + } ) + public void shouldMapSameSourcePropertyToSeveralTargetProperties() throws ParseException { + Source source = new Source(); + source.setPropertyThatShouldBeMapped( "SomeProperty" ); + + Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source ); + + assertThat( target ).isNotNull(); + assertThat( target.getPropertyThatShouldBeMapped() ).isEqualTo( "SomeProperty" ); + assertThat( target.getStringConstant() ).isEqualTo( "stringConstant" ); + assertThat( target.getIntegerConstant() ).isEqualTo( 14 ); + assertThat( target.getLongWrapperConstant() ).isEqualTo( new Long(3001L) ); + assertThat( target.getDateConstant() ).isEqualTo( getDate( "dd-MM-yyyy", "09-01-2014") ); + assertThat( target.getNameConstants() ).isEqualTo( Arrays.asList( "jack", "jill", "tom" ) ); + } + + @Test + @IssueKey( "187" ) + @WithClasses( { + Source.class, + Target.class, + ErroneousMapper1.class, + StringListMapper.class + } ) + @ExpectedCompilationOutcome( + value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic(type = ErroneousMapper1.class, + kind = Kind.ERROR, + line = 42, + messageRegExp = "Source and expression are both defined in Mapping, either define a source or an " + + "expression"), + @Diagnostic(type = ErroneousMapper1.class, + kind = Kind.WARNING, + line = 42, + messageRegExp = "Unmapped target property: \"integerConstant\"") + } + ) + public void errorOnSourceAndExpression() throws ParseException { + } + + @Test + @IssueKey( "187" ) + @WithClasses( { + Source.class, + Target.class, + ErroneousMapper2.class, + StringListMapper.class + } ) + @ExpectedCompilationOutcome( + value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic(type = ErroneousMapper2.class, + kind = Kind.ERROR, + line = 42, + messageRegExp = "Either define a source or an expression in a Mapping"), + @Diagnostic(type = ErroneousMapper2.class, + kind = Kind.WARNING, + line = 42, + messageRegExp = "Unmapped target property: \"integerConstant\"") + } + ) + public void errorOnNeitherSourceNorExpression() throws ParseException { + } + + private Date getDate(String format, String date) throws ParseException { + SimpleDateFormat dateFormat = new SimpleDateFormat( format ); + Date result = dateFormat.parse( date ); + return result; + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/SourceTargetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/SourceTargetMapper.java new file mode 100644 index 000000000..095baed10 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/SourceTargetMapper.java @@ -0,0 +1,43 @@ +/** + * Copyright 2012-2014 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.sourceconstants; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ +@Mapper(uses = StringListMapper.class) +public interface SourceTargetMapper { + + SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class ); + + @Mappings( { + @Mapping( target = "stringConstant", expression = "stringConstant"), + @Mapping( target = "integerConstant", expression = "14"), + @Mapping( target = "longWrapperConstant", expression = "3001"), + @Mapping( target = "dateConstant", dateFormat = "dd-MM-yyyy", expression = "09-01-2014"), + @Mapping( target = "nameConstants", expression = "jack-jill-tom" ) + } ) + Target sourceToTarget(Source s); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/StringListMapper.java b/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/StringListMapper.java new file mode 100644 index 000000000..97d7f3e27 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/StringListMapper.java @@ -0,0 +1,30 @@ +/** + * Copyright 2012-2014 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.sourceconstants; + +import java.util.Arrays; +import java.util.List; + + +public class StringListMapper { + + public List stringToStringList(String string) { + return string == null ? null : Arrays.asList( string.split( "-" ) ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/Target.java b/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/Target.java new file mode 100644 index 000000000..37871bd7e --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/sourceconstants/Target.java @@ -0,0 +1,85 @@ +/** + * Copyright 2012-2014 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.sourceconstants; + +import java.util.Date; +import java.util.List; + +/** + * + * @author Sjaak Derksen + */ +public class Target { + + private String propertyThatShouldBeMapped; + private String stringConstant; + private int integerConstant; + private Long longWrapperConstant; + private Date dateConstant; + private List nameConstants; + + public String getPropertyThatShouldBeMapped() { + return propertyThatShouldBeMapped; + } + + public void setPropertyThatShouldBeMapped( String propertyThatShouldBeMapped ) { + this.propertyThatShouldBeMapped = propertyThatShouldBeMapped; + } + + public String getStringConstant() { + return stringConstant; + } + + public void setStringConstant( String stringConstant ) { + this.stringConstant = stringConstant; + } + + public int getIntegerConstant() { + return integerConstant; + } + + public void setIntegerConstant( int integerConstant ) { + this.integerConstant = integerConstant; + } + + public Long getLongWrapperConstant() { + return longWrapperConstant; + } + + public void setLongWrapperConstant( Long longWrapperConstant ) { + this.longWrapperConstant = longWrapperConstant; + } + + public Date getDateConstant() { + return dateConstant; + } + + public void setDateConstant( Date dateConstant ) { + this.dateConstant = dateConstant; + } + + public List getNameConstants() { + return nameConstants; + } + + public void setNameConstants( List nameConstants ) { + this.nameConstants = nameConstants; + } + +}