diff --git a/processor/src/main/java/org/mapstruct/ap/model/BeanMapping.java b/processor/src/main/java/org/mapstruct/ap/model/BeanMapping.java index b486ee8b1..0a3600184 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/BeanMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/model/BeanMapping.java @@ -20,7 +20,7 @@ package org.mapstruct.ap.model; import java.util.List; -public class BeanMapping { +public class BeanMapping extends AbstractModelElement { private final Type sourceType; private final Type targetType; diff --git a/processor/src/main/resources/org.mapstruct.ap.model.BeanMapping.ftl b/processor/src/main/resources/org.mapstruct.ap.model.BeanMapping.ftl new file mode 100644 index 000000000..401c6e2f2 --- /dev/null +++ b/processor/src/main/resources/org.mapstruct.ap.model.BeanMapping.ftl @@ -0,0 +1,144 @@ +<#-- + + Copyright 2012-2013 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. + +--> + <#if mappingMethod.generationRequired == true> + <#if iterableMapping == true> + @Override + public ${targetType.name}<${targetType.elementType.name}> ${mappingMethod.name}(${sourceType.name}<${sourceType.elementType.name}> ${mappingMethod.parameterName}) { + if ( ${mappingMethod.parameterName} == null ) { + return null; + } + + <#-- Use the interface type on the left side, except it is java.lang.Iterable; use the implementation type - if present - on the right side --> + <#if targetType.name == "Iterable" && targetType.packageName == "java.lang">${targetType.iterableImplementationType.name}<#else>${targetType.name}<${targetType.elementType.name}> ${targetType.name?uncap_first} = new <#if targetType.iterableImplementationType??>${targetType.iterableImplementationType.name}<#else>${targetType.name}<${targetType.elementType.name}>(); + + for ( ${sourceType.elementType.name} ${sourceType.elementType.name?uncap_first} : ${mappingMethod.parameterName} ) { + <#if toConversion??> + ${targetType.name?uncap_first}.add( ${toConversion} ); + <#else> + ${targetType.name?uncap_first}.add( ${mappingMethod.elementMappingMethod.name}( ${sourceType.elementType.name?uncap_first} ) ); + + } + + return ${targetType.name?uncap_first}; + } + <#else> + @Override + public ${targetType.name} ${mappingMethod.name}(${sourceType.name} ${mappingMethod.parameterName}) { + if ( ${mappingMethod.parameterName} == null ) { + return null; + } + + ${targetType.name} ${targetType.name?uncap_first} = new ${targetType.name}(); + + <#list propertyMappings as propertyMapping> + <@simpleMap + sourceBeanName=mappingMethod.parameterName + sourceType=propertyMapping.sourceType + sourceAccessorName=propertyMapping.sourceReadAccessorName + targetBeanName=targetType.name?uncap_first + targetType=propertyMapping.targetType + targetAccessorName=propertyMapping.targetWriteAccessorName + conversion=propertyMapping.toConversion + mappingMethod=propertyMapping.mappingMethod + /> + + + return ${targetType.name?uncap_first}; + } + + + + <#if reverseMappingMethod??> + <#if reverseMappingMethod.generationRequired == true> + <#if iterableMapping == true> + + @Override + public ${sourceType.name}<${sourceType.elementType.name}> ${reverseMappingMethod.name}(${targetType.name}<${targetType.elementType.name}> ${reverseMappingMethod.parameterName}) { + if ( ${reverseMappingMethod.parameterName} == null ) { + return null; + } + + <#-- Use the interface type on the left side, except it is java.lang.Iterable; use the implementation type - if present - on the right side --> + <#if sourceType.name == "Iterable" && sourceType.packageName == "java.lang">${sourceType.iterableImplementationType.name}<#else>${sourceType.name}<${sourceType.elementType.name}> ${sourceType.name?uncap_first} = new <#if sourceType.iterableImplementationType??>${sourceType.iterableImplementationType.name}<#else>${sourceType.name}<${sourceType.elementType.name}>(); + + for ( ${targetType.elementType.name} ${targetType.elementType.name?uncap_first} : ${reverseMappingMethod.parameterName} ) { + <#if fromConversion??> + ${sourceType.name?uncap_first}.add( ${fromConversion} ); + <#else> + ${sourceType.name?uncap_first}.add( ${reverseMappingMethod.elementMappingMethod.name}( ${targetType.elementType.name?uncap_first} ) ); + + } + + return ${sourceType.name?uncap_first}; + } + <#else> + @Override + public ${sourceType.name} ${reverseMappingMethod.name}(${targetType.name} ${reverseMappingMethod.parameterName}) { + if ( ${reverseMappingMethod.parameterName} == null ) { + return null; + } + + ${sourceType.name} ${sourceType.name?uncap_first} = new ${sourceType.name}(); + + <#list propertyMappings as propertyMapping> + <@simpleMap + sourceBeanName=reverseMappingMethod.parameterName + sourceType=propertyMapping.targetType + sourceAccessorName=propertyMapping.targetReadAccessorName + targetBeanName=sourceType.name?uncap_first + targetType=propertyMapping.sourceType + targetAccessorName=propertyMapping.sourceWriteAccessorName + conversion=propertyMapping.fromConversion + mappingMethod=propertyMapping.reverseMappingMethod + /> + + + return ${sourceType.name?uncap_first}; + } + + + + +<#-- Generates the mapping of one bean property --> +<#macro simpleMap sourceBeanName sourceType sourceAccessorName targetBeanName targetType targetAccessorName conversion="" mappingMethod=""> + <#-- a) invoke mapping method --> + <#if mappingMethod != ""> + ${targetBeanName}.${targetAccessorName}( <#if mappingMethod.declaringMapper??>${mappingMethod.declaringMapper.name?uncap_first}.${mappingMethod.name}( ${sourceBeanName}.${sourceAccessorName}() ) ); + <#-- b) simple conversion --> + <#elseif conversion != ""> + <#if sourceType.primitive == false> + if ( ${sourceBeanName}.${sourceAccessorName}() != null ) { + ${targetBeanName}.${targetAccessorName}( ${conversion} ); + } + <#else> + ${targetBeanName}.${targetAccessorName}( ${conversion} ); + + <#-- c) simply set --> + <#else> + <#if targetType.collectionType == true> + if ( ${sourceBeanName}.${sourceAccessorName}() != null ) { + ${targetBeanName}.${targetAccessorName}( new <#if targetType.collectionImplementationType??>${targetType.collectionImplementationType.name}<#else>${targetType.name}<#if targetType.elementType??><${targetType.elementType.name}>( ${sourceBeanName}.${sourceAccessorName}() ) ); + } + <#else> + ${targetBeanName}.${targetAccessorName}( ${sourceBeanName}.${sourceAccessorName}() ); + + + diff --git a/processor/src/main/resources/org.mapstruct.ap.model.Mapper.ftl b/processor/src/main/resources/org.mapstruct.ap.model.Mapper.ftl index 065f8a3cc..a7a39ac1c 100644 --- a/processor/src/main/resources/org.mapstruct.ap.model.Mapper.ftl +++ b/processor/src/main/resources/org.mapstruct.ap.model.Mapper.ftl @@ -35,129 +35,6 @@ public class ${implementationName} implements ${interfaceName} { <#list beanMappings as beanMapping> - <#if beanMapping.mappingMethod.generationRequired == true> - <#if beanMapping.iterableMapping == true> - @Override - public ${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}> ${beanMapping.mappingMethod.name}(${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}> ${beanMapping.mappingMethod.parameterName}) { - if ( ${beanMapping.mappingMethod.parameterName} == null ) { - return null; - } - - <#-- Use the interface type on the left side, except it is java.lang.Iterable; use the implementation type - if present - on the right side --> - <#if beanMapping.targetType.name == "Iterable" && beanMapping.targetType.packageName == "java.lang">${beanMapping.targetType.iterableImplementationType.name}<#else>${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}> ${beanMapping.targetType.name?uncap_first} = new <#if beanMapping.targetType.iterableImplementationType??>${beanMapping.targetType.iterableImplementationType.name}<#else>${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}>(); - - for ( ${beanMapping.sourceType.elementType.name} ${beanMapping.sourceType.elementType.name?uncap_first} : ${beanMapping.mappingMethod.parameterName} ) { - <#if beanMapping.toConversion??> - ${beanMapping.targetType.name?uncap_first}.add( ${beanMapping.toConversion} ); - <#else> - ${beanMapping.targetType.name?uncap_first}.add( ${beanMapping.mappingMethod.elementMappingMethod.name}( ${beanMapping.sourceType.elementType.name?uncap_first} ) ); - - } - - return ${beanMapping.targetType.name?uncap_first}; - } - <#else> - @Override - public ${beanMapping.targetType.name} ${beanMapping.mappingMethod.name}(${beanMapping.sourceType.name} ${beanMapping.mappingMethod.parameterName}) { - if ( ${beanMapping.mappingMethod.parameterName} == null ) { - return null; - } - - ${beanMapping.targetType.name} ${beanMapping.targetType.name?uncap_first} = new ${beanMapping.targetType.name}(); - - <#list beanMapping.propertyMappings as propertyMapping> - <@simpleMap - sourceBeanName=beanMapping.mappingMethod.parameterName - sourceType=propertyMapping.sourceType - sourceAccessorName=propertyMapping.sourceReadAccessorName - targetBeanName=beanMapping.targetType.name?uncap_first - targetType=propertyMapping.targetType - targetAccessorName=propertyMapping.targetWriteAccessorName - conversion=propertyMapping.toConversion - mappingMethod=propertyMapping.mappingMethod - /> - - - return ${beanMapping.targetType.name?uncap_first}; - } - - - - <#if beanMapping.reverseMappingMethod??> - <#if beanMapping.reverseMappingMethod.generationRequired == true> - <#if beanMapping.iterableMapping == true> - - @Override - public ${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}> ${beanMapping.reverseMappingMethod.name}(${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}> ${beanMapping.reverseMappingMethod.parameterName}) { - if ( ${beanMapping.reverseMappingMethod.parameterName} == null ) { - return null; - } - - <#-- Use the interface type on the left side, except it is java.lang.Iterable; use the implementation type - if present - on the right side --> - <#if beanMapping.sourceType.name == "Iterable" && beanMapping.sourceType.packageName == "java.lang">${beanMapping.sourceType.iterableImplementationType.name}<#else>${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}> ${beanMapping.sourceType.name?uncap_first} = new <#if beanMapping.sourceType.iterableImplementationType??>${beanMapping.sourceType.iterableImplementationType.name}<#else>${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}>(); - - for ( ${beanMapping.targetType.elementType.name} ${beanMapping.targetType.elementType.name?uncap_first} : ${beanMapping.reverseMappingMethod.parameterName} ) { - <#if beanMapping.fromConversion??> - ${beanMapping.sourceType.name?uncap_first}.add( ${beanMapping.fromConversion} ); - <#else> - ${beanMapping.sourceType.name?uncap_first}.add( ${beanMapping.reverseMappingMethod.elementMappingMethod.name}( ${beanMapping.targetType.elementType.name?uncap_first} ) ); - - } - - return ${beanMapping.sourceType.name?uncap_first}; - } - <#else> - @Override - public ${beanMapping.sourceType.name} ${beanMapping.reverseMappingMethod.name}(${beanMapping.targetType.name} ${beanMapping.reverseMappingMethod.parameterName}) { - if ( ${beanMapping.reverseMappingMethod.parameterName} == null ) { - return null; - } - - ${beanMapping.sourceType.name} ${beanMapping.sourceType.name?uncap_first} = new ${beanMapping.sourceType.name}(); - - <#list beanMapping.propertyMappings as propertyMapping> - <@simpleMap - sourceBeanName=beanMapping.reverseMappingMethod.parameterName - sourceType=propertyMapping.targetType - sourceAccessorName=propertyMapping.targetReadAccessorName - targetBeanName=beanMapping.sourceType.name?uncap_first - targetType=propertyMapping.sourceType - targetAccessorName=propertyMapping.sourceWriteAccessorName - conversion=propertyMapping.fromConversion - mappingMethod=propertyMapping.reverseMappingMethod - /> - - - return ${beanMapping.sourceType.name?uncap_first}; - } - - - +<@includeModel object=beanMapping/> } - -<#-- Generates the mapping of one bean property --> -<#macro simpleMap sourceBeanName sourceType sourceAccessorName targetBeanName targetType targetAccessorName conversion="" mappingMethod=""> - <#-- a) invoke mapping method --> - <#if mappingMethod != ""> - ${targetBeanName}.${targetAccessorName}( <#if mappingMethod.declaringMapper??>${mappingMethod.declaringMapper.name?uncap_first}.${mappingMethod.name}( ${sourceBeanName}.${sourceAccessorName}() ) ); - <#-- b) simple conversion --> - <#elseif conversion != ""> - <#if sourceType.primitive == false> - if ( ${sourceBeanName}.${sourceAccessorName}() != null ) { - ${targetBeanName}.${targetAccessorName}( ${conversion} ); - } - <#else> - ${targetBeanName}.${targetAccessorName}( ${conversion} ); - - <#-- c) simply set --> - <#else> - <#if targetType.collectionType == true> - if ( ${sourceBeanName}.${sourceAccessorName}() != null ) { - ${targetBeanName}.${targetAccessorName}( new <#if targetType.collectionImplementationType??>${targetType.collectionImplementationType.name}<#else>${targetType.name}<#if targetType.elementType??><${targetType.elementType.name}>( ${sourceBeanName}.${sourceAccessorName}() ) ); - } - <#else> - ${targetBeanName}.${targetAccessorName}( ${sourceBeanName}.${sourceAccessorName}() ); - - -