#187 introducing constant mapping

This commit is contained in:
sjaakd 2014-04-19 20:09:08 +02:00 committed by Gunnar Morling
parent c8f6be3204
commit e701801ec5
13 changed files with 625 additions and 56 deletions

View File

@ -35,12 +35,15 @@ import java.util.Date;
public @interface Mapping { public @interface Mapping {
/** /**
* The source name of the configured property as defined by the JavaBeans specification. If used to map an enum * The source to use for this Mapping. This can either be:
* constant, the name of the constant member is to be given. * <ol>
* <li>The source name of the configured property as defined by the JavaBeans specification.</li>
* <li>When used to map an enum constant, the name of the constant member is to be given<./li>.
* </ol>
* *
* @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 * 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}. * @return A date format string as processable by {@link SimpleDateFormat}.
*/ */
String dateFormat() default ""; 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 "";
} }

View File

@ -38,6 +38,10 @@ import org.mapstruct.ap.model.source.SourceMethod;
public class BeanMappingMethod extends MappingMethod { public class BeanMappingMethod extends MappingMethod {
private final List<PropertyMapping> propertyMappings; private final List<PropertyMapping> propertyMappings;
private final Map<String, List<PropertyMapping>> mappingsByParameter;
private final List<PropertyMapping> constantMappings;
private final FactoryMethod factoryMethod; private final FactoryMethod factoryMethod;
public BeanMappingMethod(SourceMethod method, public BeanMappingMethod(SourceMethod method,
@ -45,6 +49,22 @@ public class BeanMappingMethod extends MappingMethod {
FactoryMethod factoryMethod) { FactoryMethod factoryMethod) {
super( method ); super( method );
this.propertyMappings = propertyMappings; 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<String, List<PropertyMapping>>();
this.constantMappings = new ArrayList<PropertyMapping>( propertyMappings );
for ( Parameter sourceParameter : getSourceParameters() ) {
ArrayList<PropertyMapping> mappingsOfParameter = new ArrayList<PropertyMapping>();
mappingsByParameter.put( sourceParameter.getName(), mappingsOfParameter );
for ( PropertyMapping mapping : propertyMappings ) {
if ( sourceParameter.getName().equals( mapping.getSourceBeanName() ) ) {
mappingsOfParameter.add( mapping );
constantMappings.remove( mapping );
}
}
}
this.factoryMethod = factoryMethod; this.factoryMethod = factoryMethod;
} }
@ -52,18 +72,11 @@ public class BeanMappingMethod extends MappingMethod {
return propertyMappings; return propertyMappings;
} }
public Map<String, List<PropertyMapping>> getPropertyMappingsByParameter() { public List<PropertyMapping> getConstantMappings() {
Map<String, List<PropertyMapping>> mappingsByParameter = new HashMap<String, List<PropertyMapping>>(); return constantMappings;
}
for ( Parameter sourceParameter : getSourceParameters() ) { public Map<String, List<PropertyMapping>> getPropertyMappingsByParameter() {
ArrayList<PropertyMapping> mappingsOfParameter = new ArrayList<PropertyMapping>();
mappingsByParameter.put( sourceParameter.getName(), mappingsOfParameter );
for ( PropertyMapping mapping : propertyMappings ) {
if ( mapping.getSourceBeanName().equals( sourceParameter.getName() ) ) {
mappingsOfParameter.add( mapping );
}
}
}
return mappingsByParameter; return mappingsByParameter;
} }

View File

@ -22,9 +22,11 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.annotation.processing.Messager;
import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element; import javax.lang.model.element.Element;
import javax.tools.Diagnostic;
import org.mapstruct.ap.prism.MappingPrism; import org.mapstruct.ap.prism.MappingPrism;
import org.mapstruct.ap.prism.MappingsPrism; import org.mapstruct.ap.prism.MappingsPrism;
@ -40,42 +42,63 @@ public class Mapping {
private final String sourceName; private final String sourceName;
private final String sourceParameterName; private final String sourceParameterName;
private final String sourcePropertyName; private final String sourcePropertyName;
private final String expression;
private final String targetName; private final String targetName;
private final String dateFormat; private final String dateFormat;
private final AnnotationMirror mirror; private final AnnotationMirror mirror;
private final AnnotationValue sourceAnnotationValue; private final AnnotationValue sourceAnnotationValue;
private final AnnotationValue targetAnnotationValue; private final AnnotationValue targetAnnotationValue;
public static Map<String, List<Mapping>> fromMappingsPrism(MappingsPrism mappingsAnnotation, Element element) { public static Map<String, List<Mapping>> fromMappingsPrism(MappingsPrism mappingsAnnotation, Element element,
Messager messager) {
Map<String, List<Mapping>> mappings = new HashMap<String, List<Mapping>>(); Map<String, List<Mapping>> mappings = new HashMap<String, List<Mapping>>();
for ( MappingPrism mapping : mappingsAnnotation.value() ) { for ( MappingPrism mappingPrism : mappingsAnnotation.value() ) {
if ( !mappings.containsKey( mapping.source() ) ) { if ( !mappings.containsKey( mappingPrism.source() ) ) {
mappings.put( mapping.source(), new ArrayList<Mapping>() ); mappings.put( mappingPrism.source(), new ArrayList<Mapping>() );
}
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; return mappings;
} }
public static Mapping fromMappingPrism(MappingPrism mapping, Element element) { public static Mapping fromMappingPrism(MappingPrism mappingPrism, Element element, Messager messager) {
String[] sourceNameParts = getSourceNameParts( String[] sourceNameParts = getSourceNameParts(
mapping.source(), mappingPrism.source(),
element, element,
mapping.mirror, mappingPrism.mirror,
mapping.values.source() 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( return new Mapping(
mapping.source(), mappingPrism.source(),
sourceNameParts != null ? sourceNameParts[0] : null, sourceNameParts != null ? sourceNameParts[0] : null,
sourceNameParts != null ? sourceNameParts[1] : mapping.source(), sourceNameParts != null ? sourceNameParts[1] : mappingPrism.source(),
mapping.target(), mappingPrism.expression(),
mapping.dateFormat(), mappingPrism.target(),
mapping.mirror, mappingPrism.dateFormat(),
mapping.values.source(), mappingPrism.mirror,
mapping.values.target() mappingPrism.values.source(),
mappingPrism.values.target()
); );
} }
@ -98,12 +121,13 @@ public class Mapping {
return parts; return parts;
} }
private Mapping(String sourceName, String sourceParameterName, String sourcePropertyName, String targetName, private Mapping(String sourceName, String sourceParameterName, String sourcePropertyName, String expression,
String dateFormat, AnnotationMirror mirror, AnnotationValue sourceAnnotationValue, String targetName, String dateFormat, AnnotationMirror mirror,
AnnotationValue targetAnnotationValue) { AnnotationValue sourceAnnotationValue, AnnotationValue targetAnnotationValue) {
this.sourceName = sourceName; this.sourceName = sourceName;
this.sourceParameterName = sourceParameterName; this.sourceParameterName = sourceParameterName;
this.sourcePropertyName = sourcePropertyName; this.sourcePropertyName = sourcePropertyName;
this.expression = expression;
this.targetName = targetName.equals( "" ) ? sourceName : targetName; this.targetName = targetName.equals( "" ) ? sourceName : targetName;
this.dateFormat = dateFormat; this.dateFormat = dateFormat;
this.mirror = mirror; this.mirror = mirror;
@ -139,6 +163,11 @@ public class Mapping {
return sourceParameterName; return sourceParameterName;
} }
public String getExpression() {
return expression;
}
public String getTargetName() { public String getTargetName() {
return targetName; return targetName;
} }
@ -160,16 +189,22 @@ public class Mapping {
} }
public Mapping reverse() { public Mapping reverse() {
return new Mapping( Mapping reverse = null;
targetName, if ( expression != null ) {
null, /* mapping can only be reversed if the source was not a constant */
targetName, reverse = new Mapping(
sourceName, targetName,
dateFormat, null,
mirror, targetName,
sourceAnnotationValue, expression,
targetAnnotationValue sourceName,
); dateFormat,
mirror,
sourceAnnotationValue,
targetAnnotationValue
);
}
return reverse;
} }
@Override @Override

View File

@ -376,7 +376,10 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
if ( !reversed.containsKey( mapping.getTargetName() ) ) { if ( !reversed.containsKey( mapping.getTargetName() ) ) {
reversed.put( mapping.getTargetName(), new ArrayList<Mapping>() ); reversed.put( mapping.getTargetName(), new ArrayList<Mapping>() );
} }
reversed.get( mapping.getTargetName() ).add( mapping.reverse() ); Mapping reverseMapping = mapping.reverse();
if ( reverseMapping != null ) {
reversed.get( mapping.getTargetName() ).add( reverseMapping );
}
} }
} }
return reversed; return reversed;
@ -387,12 +390,39 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
SourceMethod method, SourceMethod method,
ExecutableElement targetAcessor, ExecutableElement targetAcessor,
Parameter parameter) { Parameter parameter) {
String targetPropertyName = Executables.getPropertyName( targetAcessor ); String targetPropertyName = Executables.getPropertyName( targetAcessor );
// check if there's a mapping defined
Mapping mapping = method.getMappingByTargetPropertyName( targetPropertyName ); Mapping mapping = method.getMappingByTargetPropertyName( targetPropertyName );
String dateFormat = mapping != null ? mapping.getDateFormat() : null; String dateFormat = null;
String sourcePropertyName = mapping != null ? mapping.getSourcePropertyName() : targetPropertyName; boolean isSourceConstant = false;
String sourceConstant = null;
String sourcePropertyName;
if ( mapping != null ) {
dateFormat = mapping.getDateFormat();
isSourceConstant = !mapping.getExpression().isEmpty();
sourceConstant = "\"" + mapping.getExpression() + "\"";
sourcePropertyName = mapping.getSourcePropertyName();
}
else {
sourcePropertyName = targetPropertyName;
}
List<ExecutableElement> sourceGetters = parameter.getType().getGetters(); List<ExecutableElement> 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 ) { for ( ExecutableElement sourceAccessor : sourceGetters ) {
List<Mapping> sourceMappings = method.getMappings().get( sourcePropertyName ); List<Mapping> sourceMappings = method.getMappings().get( sourcePropertyName );
@ -425,7 +455,6 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
); );
} }
} }
return null; return null;
} }
@ -592,10 +621,8 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
} }
} }
else if ( !hasSourceProperty( else if ( mappedProperty.getExpression().isEmpty() &&
method, !hasSourceProperty( method, mappedProperty.getSourcePropertyName() ) ) {
mappedProperty.getSourcePropertyName()
) ) {
messager.printMessage( messager.printMessage(
Kind.ERROR, Kind.ERROR,
String.format( String.format(
@ -627,7 +654,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
return !foundUnmappedProperty; return !foundUnmappedProperty;
} }
private PropertyMapping getPropertyMapping(List<MapperReference> mapperReferences, private PropertyMapping getPropertyMapping(List<MapperReference> mapperReferences,
List<SourceMethod> methods, List<SourceMethod> methods,
SourceMethod method, SourceMethod method,
Parameter parameter, Parameter parameter,
@ -703,6 +730,78 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
); );
} }
private PropertyMapping getConstantMapping(List<MapperReference> mapperReferences,
List<SourceMethod> 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<MapperReference> mapperReferences, private IterableMappingMethod getIterableMappingMethod(List<MapperReference> mapperReferences,
List<SourceMethod> methods, List<SourceMethod> methods,
SourceMethod method) { SourceMethod method) {

View File

@ -384,11 +384,14 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
if ( !mappings.containsKey( mappingAnnotation.source() ) ) { if ( !mappings.containsKey( mappingAnnotation.source() ) ) {
mappings.put( mappingAnnotation.source(), new ArrayList<Mapping>() ); mappings.put( mappingAnnotation.source(), new ArrayList<Mapping>() );
} }
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 ) { if ( mappingsAnnotation != null ) {
mappings.putAll( Mapping.fromMappingsPrism( mappingsAnnotation, method ) ); mappings.putAll( Mapping.fromMappingsPrism( mappingsAnnotation, method, messager ) );
} }
return mappings; return mappings;

View File

@ -38,6 +38,9 @@
<@includeModel object=propertyMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping/> <@includeModel object=propertyMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping/>
</#list> </#list>
</#if> </#if>
<#list constantMappings as constantMapping>
<@includeModel object=constantMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping/>
</#list>
<#if returnType.name != "void"> <#if returnType.name != "void">
return ${resultName}; return ${resultName};

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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<String> stringToStringList(String string) {
return string == null ? null : Arrays.asList( string.split( "-" ) );
}
}

View File

@ -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<String> 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<String> getNameConstants() {
return nameConstants;
}
public void setNameConstants( List<String> nameConstants ) {
this.nameConstants = nameConstants;
}
}