mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#10 Raising error in case a property can not be mapped
This commit is contained in:
parent
f4a2260d80
commit
b826304d4c
@ -69,6 +69,8 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
private final TypeUtil typeUtil;
|
private final TypeUtil typeUtil;
|
||||||
private final Options options;
|
private final Options options;
|
||||||
|
|
||||||
|
private boolean mappingErronuous = false;
|
||||||
|
|
||||||
public MapperGenerationVisitor(ProcessingEnvironment processingEnvironment, Options options) {
|
public MapperGenerationVisitor(ProcessingEnvironment processingEnvironment, Options options) {
|
||||||
this.processingEnvironment = processingEnvironment;
|
this.processingEnvironment = processingEnvironment;
|
||||||
this.typeUtils = processingEnvironment.getTypeUtils();
|
this.typeUtils = processingEnvironment.getTypeUtils();
|
||||||
@ -80,9 +82,11 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
@Override
|
@Override
|
||||||
public Void visitTypeAsInterface(TypeElement element, Void p) {
|
public Void visitTypeAsInterface(TypeElement element, Void p) {
|
||||||
Mapper model = retrieveModel( element );
|
Mapper model = retrieveModel( element );
|
||||||
String sourceFileName = element.getQualifiedName() + IMPLEMENTATION_SUFFIX;
|
|
||||||
|
|
||||||
writeModelToSourceFile( sourceFileName, model );
|
if ( !mappingErronuous ) {
|
||||||
|
String sourceFileName = element.getQualifiedName() + IMPLEMENTATION_SUFFIX;
|
||||||
|
writeModelToSourceFile( sourceFileName, model );
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -153,9 +157,17 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
for ( MappedProperty property : method.getMappedProperties() ) {
|
for ( MappedProperty property : method.getMappedProperties() ) {
|
||||||
Method propertyMappingMethod = getPropertyMappingMethod( methods, property );
|
Method propertyMappingMethod = getPropertyMappingMethod( methods, property );
|
||||||
Method reversePropertyMappingMethod = getReversePropertyMappingMethod( methods, property );
|
Method reversePropertyMappingMethod = getReversePropertyMappingMethod( methods, property );
|
||||||
|
|
||||||
Conversion conversion = conversions.getConversion( property.getSourceType(), property.getTargetType() );
|
Conversion conversion = conversions.getConversion( property.getSourceType(), property.getTargetType() );
|
||||||
|
|
||||||
|
reportErrorIfPropertyCanNotBeMapped(
|
||||||
|
method,
|
||||||
|
rawReverseMappingMethod,
|
||||||
|
property,
|
||||||
|
propertyMappingMethod,
|
||||||
|
reversePropertyMappingMethod,
|
||||||
|
conversion
|
||||||
|
);
|
||||||
|
|
||||||
propertyMappings.add(
|
propertyMappings.add(
|
||||||
new PropertyMapping(
|
new PropertyMapping(
|
||||||
property.getSourceReadAccessorName(),
|
property.getSourceReadAccessorName(),
|
||||||
@ -222,6 +234,48 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
return mappings;
|
return mappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void reportErrorIfPropertyCanNotBeMapped(Method method, Method reverseMethod, MappedProperty property, Method propertyMappingMethod, Method reversePropertyMappingMethod, Conversion conversion) {
|
||||||
|
if ( property.getSourceType().equals( property.getTargetType() ) ||
|
||||||
|
propertyMappingMethod != null ||
|
||||||
|
conversion != null ||
|
||||||
|
( property.getTargetType().isCollectionType() && property.getTargetType()
|
||||||
|
.getCollectionImplementationType() != null ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reportError(
|
||||||
|
String.format(
|
||||||
|
"Can't map property \"%s %s\" to \"%s %s\".",
|
||||||
|
property.getSourceType(),
|
||||||
|
property.getSourceName(),
|
||||||
|
property.getTargetType(),
|
||||||
|
property.getTargetName()
|
||||||
|
),
|
||||||
|
method.getExecutable()
|
||||||
|
);
|
||||||
|
|
||||||
|
mappingErronuous = true;
|
||||||
|
|
||||||
|
if ( reverseMethod == null ||
|
||||||
|
reversePropertyMappingMethod != null ||
|
||||||
|
conversion != null ||
|
||||||
|
( property.getSourceType().isCollectionType() && property.getSourceType()
|
||||||
|
.getCollectionImplementationType() == null ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reportError(
|
||||||
|
String.format(
|
||||||
|
"Can't map property \"%s %s\" to \"%s %s\".",
|
||||||
|
property.getTargetType(),
|
||||||
|
property.getTargetName(),
|
||||||
|
property.getSourceType(),
|
||||||
|
property.getSourceName()
|
||||||
|
),
|
||||||
|
reverseMethod.getExecutable()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private String getIterableConversionString(Conversions conversions, Type sourceElementType, Type targetElementType, boolean isToConversion) {
|
private String getIterableConversionString(Conversions conversions, Type sourceElementType, Type targetElementType, boolean isToConversion) {
|
||||||
Conversion conversion = conversions.getConversion( sourceElementType, targetElementType );
|
Conversion conversion = conversions.getConversion( sourceElementType, targetElementType );
|
||||||
|
|
||||||
@ -300,7 +354,7 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
methods.add(
|
methods.add(
|
||||||
new Method(
|
new Method(
|
||||||
declaringMapper,
|
declaringMapper,
|
||||||
method.getSimpleName().toString(),
|
method,
|
||||||
parameter.getName(),
|
parameter.getName(),
|
||||||
parameter.getType(),
|
parameter.getType(),
|
||||||
returnType,
|
returnType,
|
||||||
@ -310,21 +364,11 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
|
|
||||||
if ( declaringMapper == null ) {
|
if ( declaringMapper == null ) {
|
||||||
if ( parameter.getType().isIterableType() && !returnType.isIterableType() ) {
|
if ( parameter.getType().isIterableType() && !returnType.isIterableType() ) {
|
||||||
processingEnvironment.getMessager()
|
reportError( "Can't generate mapping method from iterable type to non-iterable ype.", method );
|
||||||
.printMessage(
|
|
||||||
Kind.ERROR,
|
|
||||||
"Can't generate mapping method from iterable type to non-iterable ype.",
|
|
||||||
method
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !parameter.getType().isIterableType() && returnType.isIterableType() ) {
|
if ( !parameter.getType().isIterableType() && returnType.isIterableType() ) {
|
||||||
processingEnvironment.getMessager()
|
reportError( "Can't generate mapping method from non-iterable type to iterable ype.", method );
|
||||||
.printMessage(
|
|
||||||
Kind.ERROR,
|
|
||||||
"Can't generate mapping method from non-iterable type to iterable ype.",
|
|
||||||
method
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -434,4 +478,9 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
private Type retrieveReturnType(ExecutableElement method) {
|
private Type retrieveReturnType(ExecutableElement method) {
|
||||||
return typeUtil.retrieveType( method.getReturnType() );
|
return typeUtil.retrieveType( method.getReturnType() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void reportError(String message, Element element) {
|
||||||
|
processingEnvironment.getMessager().printMessage( Kind.ERROR, message, element );
|
||||||
|
mappingErronuous = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package org.mapstruct.ap.model.source;
|
package org.mapstruct.ap.model.source;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import javax.lang.model.element.ExecutableElement;
|
||||||
|
|
||||||
import org.mapstruct.ap.model.Type;
|
import org.mapstruct.ap.model.Type;
|
||||||
|
|
||||||
@ -26,19 +27,15 @@ import org.mapstruct.ap.model.Type;
|
|||||||
public class Method {
|
public class Method {
|
||||||
|
|
||||||
private final Type declaringMapper;
|
private final Type declaringMapper;
|
||||||
private final String name;
|
private final ExecutableElement executable;
|
||||||
private final String parameterName;
|
private final String parameterName;
|
||||||
private final Type sourceType;
|
private final Type sourceType;
|
||||||
private final Type targetType;
|
private final Type targetType;
|
||||||
private final List<MappedProperty> mappedProperties;
|
private final List<MappedProperty> mappedProperties;
|
||||||
|
|
||||||
public Method(String name, String parameterName, Type sourceType, Type targetType, List<MappedProperty> mappedProperties) {
|
public Method(Type declaringMapper, ExecutableElement executable, String parameterName, Type sourceType, Type targetType, List<MappedProperty> mappedProperties) {
|
||||||
this( null, name, parameterName, sourceType, targetType, mappedProperties );
|
|
||||||
}
|
|
||||||
|
|
||||||
public Method(Type declaringMapper, String name, String parameterName, Type sourceType, Type targetType, List<MappedProperty> mappedProperties) {
|
|
||||||
this.declaringMapper = declaringMapper;
|
this.declaringMapper = declaringMapper;
|
||||||
this.name = name;
|
this.executable = executable;
|
||||||
this.parameterName = parameterName;
|
this.parameterName = parameterName;
|
||||||
this.sourceType = sourceType;
|
this.sourceType = sourceType;
|
||||||
this.targetType = targetType;
|
this.targetType = targetType;
|
||||||
@ -49,8 +46,12 @@ public class Method {
|
|||||||
return declaringMapper;
|
return declaringMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ExecutableElement getExecutable() {
|
||||||
|
return executable;
|
||||||
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return executable.getSimpleName().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getParameterName() {
|
public String getParameterName() {
|
||||||
@ -81,6 +82,6 @@ public class Method {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return targetType + " " + name + "(" + sourceType + " " + parameterName + ")";
|
return targetType + " " + getName() + "(" + sourceType + " " + parameterName + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,12 +150,12 @@ public class ${implementationName} implements ${interfaceName} {
|
|||||||
<#-- b) invoke mapping method -->
|
<#-- b) invoke mapping method -->
|
||||||
<#elseif mappingMethod != "">
|
<#elseif mappingMethod != "">
|
||||||
${targetBeanName}.${targetAccessorName}( <#if mappingMethod.declaringMapper??>${mappingMethod.declaringMapper.name?uncap_first}.</#if>${mappingMethod.name}( ${sourceBeanName}.${sourceAccessorName}() ) );
|
${targetBeanName}.${targetAccessorName}( <#if mappingMethod.declaringMapper??>${mappingMethod.declaringMapper.name?uncap_first}.</#if>${mappingMethod.name}( ${sourceBeanName}.${sourceAccessorName}() ) );
|
||||||
|
<#-- c) simply set -->
|
||||||
<#else>
|
<#else>
|
||||||
<#if targetType.collectionType == true>
|
<#if targetType.collectionType == true>
|
||||||
if ( ${sourceBeanName}.${sourceAccessorName}() != null ) {
|
if ( ${sourceBeanName}.${sourceAccessorName}() != null ) {
|
||||||
${targetBeanName}.${targetAccessorName}( new <#if targetType.collectionImplementationType??>${targetType.collectionImplementationType.name}<#else>${targetType.name}</#if><#if targetType.elementType??><${targetType.elementType.name}></#if>( ${sourceBeanName}.${sourceAccessorName}() ) );
|
${targetBeanName}.${targetAccessorName}( new <#if targetType.collectionImplementationType??>${targetType.collectionImplementationType.name}<#else>${targetType.name}</#if><#if targetType.elementType??><${targetType.elementType.name}></#if>( ${sourceBeanName}.${sourceAccessorName}() ) );
|
||||||
}
|
}
|
||||||
<#-- c) simply set -->
|
|
||||||
<#else>
|
<#else>
|
||||||
${targetBeanName}.${targetAccessorName}( ${sourceBeanName}.${sourceAccessorName}() );
|
${targetBeanName}.${targetAccessorName}( ${sourceBeanName}.${sourceAccessorName}() );
|
||||||
</#if>
|
</#if>
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.erronuous;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ErronuousMapper {
|
||||||
|
|
||||||
|
Target sourceToTarget(Source source);
|
||||||
|
|
||||||
|
Source targetToSource(Target target);
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.erronuous;
|
||||||
|
|
||||||
|
import javax.tools.Diagnostic.Kind;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
|
import org.mapstruct.ap.testutil.MapperTestBase;
|
||||||
|
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.testng.annotations.Test;
|
||||||
|
|
||||||
|
@WithClasses({ ErronuousMapper.class, Source.class, Target.class })
|
||||||
|
public class MappedPropertiesWithDifferentTypesTest extends MapperTestBase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IssueKey("6")
|
||||||
|
@ExpectedCompilationOutcome(
|
||||||
|
value = CompilationResult.FAILED,
|
||||||
|
diagnostics = {
|
||||||
|
@Diagnostic(type = ErronuousMapper.class, kind = Kind.ERROR, line = 26),
|
||||||
|
@Diagnostic(type = ErronuousMapper.class, kind = Kind.ERROR, line = 28)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public void shouldFailToGenerateMappingFromListToString() {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.erronuous;
|
||||||
|
|
||||||
|
public class Source {
|
||||||
|
|
||||||
|
private boolean foo;
|
||||||
|
|
||||||
|
public boolean isFoo() {
|
||||||
|
return foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFoo(boolean foo) {
|
||||||
|
this.foo = foo;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.erronuous;
|
||||||
|
|
||||||
|
public class Target {
|
||||||
|
|
||||||
|
private int foo;
|
||||||
|
|
||||||
|
public int getFoo() {
|
||||||
|
return foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFoo(int foo) {
|
||||||
|
this.foo = foo;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user