mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#35 Raising warning in case of unmapped target properties
This commit is contained in:
parent
895a715727
commit
bf5a4303b6
@ -90,7 +90,9 @@
|
||||
<module name="AvoidStarImport"/>
|
||||
<module name="IllegalImport"/> <!-- defaults to sun.* packages -->
|
||||
<module name="RedundantImport"/>
|
||||
<module name="UnusedImports"/>
|
||||
<module name="UnusedImports">
|
||||
<property name="processJavadoc" value="true"/>
|
||||
</module>
|
||||
|
||||
|
||||
<!-- Checks for Size Violations. -->
|
||||
|
@ -39,4 +39,12 @@ public @interface Mapper {
|
||||
* @return The mapper types used by this mapper.
|
||||
*/
|
||||
Class<?>[] uses() default { };
|
||||
|
||||
/**
|
||||
* How unmapped properties of the target type of a mapping should be
|
||||
* reported.
|
||||
*
|
||||
* @return The reporting policy for unmapped target properties.
|
||||
*/
|
||||
ReportingPolicy unmappedTargetPolicy() default ReportingPolicy.WARN;
|
||||
}
|
||||
|
46
core/src/main/java/org/mapstruct/ReportingPolicy.java
Normal file
46
core/src/main/java/org/mapstruct/ReportingPolicy.java
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import javax.tools.Diagnostic.Kind;
|
||||
|
||||
/**
|
||||
* Policy for reporting issues occurring during the generation of a mapper
|
||||
* implementation.
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
public enum ReportingPolicy {
|
||||
|
||||
/**
|
||||
* No report will be created for the given issue.
|
||||
*/
|
||||
IGNORE,
|
||||
|
||||
/**
|
||||
* A report with {@link Kind#WARNING} will be created for the given issue.
|
||||
*/
|
||||
WARN,
|
||||
|
||||
/**
|
||||
* A report with {@link Kind#ERROR} will be created for the given issue,
|
||||
* causing the compilation to fail.
|
||||
*/
|
||||
ERROR;
|
||||
}
|
@ -20,8 +20,8 @@ package org.mapstruct.ap;
|
||||
|
||||
import java.beans.Introspector;
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
@ -32,6 +32,7 @@ import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementVisitor;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.element.VariableElement;
|
||||
@ -50,6 +51,7 @@ import org.mapstruct.ap.model.Mapper;
|
||||
import org.mapstruct.ap.model.MappingMethod;
|
||||
import org.mapstruct.ap.model.Options;
|
||||
import org.mapstruct.ap.model.PropertyMapping;
|
||||
import org.mapstruct.ap.model.ReportingPolicy;
|
||||
import org.mapstruct.ap.model.Type;
|
||||
import org.mapstruct.ap.model.source.MappedProperty;
|
||||
import org.mapstruct.ap.model.source.Mapping;
|
||||
@ -57,6 +59,7 @@ import org.mapstruct.ap.model.source.Method;
|
||||
import org.mapstruct.ap.model.source.Parameter;
|
||||
import org.mapstruct.ap.util.Executables;
|
||||
import org.mapstruct.ap.util.Filters;
|
||||
import org.mapstruct.ap.util.Strings;
|
||||
import org.mapstruct.ap.util.TypeUtil;
|
||||
import org.mapstruct.ap.writer.ModelWriter;
|
||||
|
||||
@ -133,8 +136,14 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
||||
}
|
||||
|
||||
private Mapper retrieveModel(TypeElement element) {
|
||||
List<Method> methods = retrieveMethods( null, element );
|
||||
List<BeanMapping> mappings = getMappings( methods );
|
||||
//1.) build up "source" model
|
||||
List<Method> methods = retrieveMethods( element, true );
|
||||
|
||||
//2.) build up aggregated "target" model
|
||||
List<BeanMapping> mappings = getMappings(
|
||||
methods,
|
||||
ReportingPolicy.valueOf( MapperPrism.getInstanceOn( element ).unmappedTargetPolicy() )
|
||||
);
|
||||
List<Type> usedMapperTypes = getUsedMapperTypes( element );
|
||||
|
||||
Mapper mapper = new Mapper(
|
||||
@ -149,7 +158,8 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
||||
return mapper;
|
||||
}
|
||||
|
||||
private List<BeanMapping> getMappings(List<Method> methods) {
|
||||
private List<BeanMapping> getMappings(List<Method> methods,
|
||||
ReportingPolicy unmappedTargetPolicy) {
|
||||
Conversions conversions = new Conversions( elementUtils, typeUtils, typeUtil );
|
||||
|
||||
List<BeanMapping> mappings = new ArrayList<BeanMapping>();
|
||||
@ -181,8 +191,13 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
||||
}
|
||||
|
||||
List<PropertyMapping> propertyMappings = new ArrayList<PropertyMapping>();
|
||||
Set<String> mappedSourceProperties = new HashSet<String>();
|
||||
Set<String> mappedTargetProperties = new HashSet<String>();
|
||||
|
||||
for ( MappedProperty property : method.getMappedProperties() ) {
|
||||
mappedSourceProperties.add( property.getSourceName() );
|
||||
mappedTargetProperties.add( property.getTargetName() );
|
||||
|
||||
Method propertyMappingMethod = getPropertyMappingMethod( methods, property );
|
||||
Method reversePropertyMappingMethod = getReversePropertyMappingMethod( methods, property );
|
||||
Conversion conversion = conversions.getConversion( property.getSourceType(), property.getTargetType() );
|
||||
@ -229,6 +244,23 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
||||
boolean isIterableMapping = method.getSourceType().isIterableType() && method.getTargetType()
|
||||
.isIterableType();
|
||||
|
||||
if ( mappingMethod.isGenerationRequired() && !isIterableMapping ) {
|
||||
reportErrorForUnmappedTargetPropertiesIfRequired(
|
||||
method.getExecutable(),
|
||||
unmappedTargetPolicy,
|
||||
method.getTargetProeprties(),
|
||||
mappedTargetProperties
|
||||
);
|
||||
}
|
||||
if ( reverseMappingMethod != null && reverseMappingMethod.isGenerationRequired() && !isIterableMapping ) {
|
||||
reportErrorForUnmappedTargetPropertiesIfRequired(
|
||||
rawReverseMappingMethod.getExecutable(),
|
||||
unmappedTargetPolicy,
|
||||
method.getSourceProperties(),
|
||||
mappedSourceProperties
|
||||
);
|
||||
}
|
||||
|
||||
String toConversionString = null;
|
||||
String fromConversionString = null;
|
||||
|
||||
@ -262,6 +294,25 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
||||
return mappings;
|
||||
}
|
||||
|
||||
private void reportErrorForUnmappedTargetPropertiesIfRequired(ExecutableElement method,
|
||||
ReportingPolicy unmappedTargetPolicy,
|
||||
Set<String> targetProperties,
|
||||
Set<String> mappedTargetProperties) {
|
||||
|
||||
if ( targetProperties.size() > mappedTargetProperties.size() && unmappedTargetPolicy.requiresReport() ) {
|
||||
targetProperties.removeAll( mappedTargetProperties );
|
||||
printMessage(
|
||||
unmappedTargetPolicy,
|
||||
MessageFormat.format(
|
||||
"Unmapped target {0,choice,1#property|1<properties}: \"{1}\"",
|
||||
targetProperties.size(),
|
||||
Strings.join( targetProperties, ", " )
|
||||
),
|
||||
method
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void reportErrorIfPropertyCanNotBeMapped(Method method, Method reverseMethod, MappedProperty property,
|
||||
Method propertyMappingMethod, Method reversePropertyMappingMethod,
|
||||
Conversion conversion) {
|
||||
@ -379,15 +430,32 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<Method> retrieveMethods(Type declaringMapper, Element element) {
|
||||
/**
|
||||
* Retrieves the mapping methods declared by the given mapper type.
|
||||
*
|
||||
* @param element The type of interest
|
||||
* @param implementationRequired Whether an implementation of this type must be generated or
|
||||
* not. {@code true} if the type is the currently processed
|
||||
* mapper interface, {@code false} if the given type is one
|
||||
* referred to via {@code Mapper#uses()}.
|
||||
*
|
||||
* @return All mapping methods declared by the given type
|
||||
*/
|
||||
private List<Method> retrieveMethods(TypeElement element, boolean implementationRequired) {
|
||||
List<Method> methods = new ArrayList<Method>();
|
||||
|
||||
MapperPrism mapperPrism = implementationRequired ? MapperPrism.getInstanceOn( element ) : null;
|
||||
|
||||
//TODO Extract to separate method
|
||||
for ( ExecutableElement method : methodsIn( element.getEnclosedElements() ) ) {
|
||||
Parameter parameter = retrieveParameter( method );
|
||||
Type returnType = retrieveReturnType( method );
|
||||
Element returnTypeElement = typeUtils.asElement( method.getReturnType() );
|
||||
Element parameterElement = typeUtils.asElement( method.getParameters().get( 0 ).asType() );
|
||||
|
||||
boolean mappingErroneous = false;
|
||||
|
||||
if ( declaringMapper == null ) {
|
||||
if ( implementationRequired ) {
|
||||
if ( parameter.getType().isIterableType() && !returnType.isIterableType() ) {
|
||||
reportError( "Can't generate mapping method from iterable type to non-iterable type.", method );
|
||||
mappingErroneous = true;
|
||||
@ -410,30 +478,48 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
||||
}
|
||||
}
|
||||
|
||||
//retrieve property mappings if an implementation for the method needs to be generated
|
||||
List<MappedProperty> properties = declaringMapper == null ? retrieveMappedProperties( method ) : Collections
|
||||
.<MappedProperty>emptyList();
|
||||
//add method with property mappings if an implementation needs to be generated
|
||||
if ( implementationRequired ) {
|
||||
Set<String> sourceProperties = Executables.getPropertyNames(
|
||||
Filters.getterMethodsIn( parameterElement.getEnclosedElements() )
|
||||
);
|
||||
Set<String> targetProperties = Executables.getPropertyNames(
|
||||
Filters.setterMethodsIn( returnTypeElement.getEnclosedElements() )
|
||||
);
|
||||
|
||||
methods.add(
|
||||
new Method(
|
||||
declaringMapper,
|
||||
Method.forMethodRequiringImplementation(
|
||||
method,
|
||||
parameter.getName(),
|
||||
parameter.getType(),
|
||||
returnType,
|
||||
properties
|
||||
sourceProperties,
|
||||
targetProperties,
|
||||
retrieveMappedProperties( method, sourceProperties, targetProperties )
|
||||
)
|
||||
);
|
||||
}
|
||||
//otherwise add reference to existing mapper method
|
||||
else {
|
||||
methods.add(
|
||||
Method.forReferencedMethod(
|
||||
typeUtil.getType( typeUtils.getDeclaredType( element ) ),
|
||||
method,
|
||||
parameter.getName(),
|
||||
parameter.getType(),
|
||||
returnType
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
MapperPrism mapperPrism = MapperPrism.getInstanceOn( element );
|
||||
|
||||
if ( mapperPrism != null ) {
|
||||
//Add all methods of used mappers in order to reference them in the aggregated model
|
||||
if ( implementationRequired ) {
|
||||
for ( TypeMirror usedMapper : mapperPrism.uses() ) {
|
||||
methods.addAll(
|
||||
retrieveMethods(
|
||||
typeUtil.retrieveType( usedMapper ),
|
||||
( (DeclaredType) usedMapper ).asElement()
|
||||
(TypeElement) ( (DeclaredType) usedMapper ).asElement(),
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -448,10 +534,14 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
||||
* method.
|
||||
*
|
||||
* @param method The method of interest
|
||||
* @param targetProperties
|
||||
* @param sourceProperties
|
||||
*
|
||||
* @return All mapped properties for the given method
|
||||
*/
|
||||
private List<MappedProperty> retrieveMappedProperties(ExecutableElement method) {
|
||||
private List<MappedProperty> retrieveMappedProperties(ExecutableElement method, Set<String> sourceProperties,
|
||||
Set<String> targetProperties) {
|
||||
|
||||
Map<String, Mapping> mappings = getMappings( method );
|
||||
|
||||
TypeElement returnTypeElement = (TypeElement) typeUtils.asElement( method.getReturnType() );
|
||||
@ -472,7 +562,7 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
||||
elementUtils.getAllMembers( returnTypeElement )
|
||||
);
|
||||
|
||||
reportErrorIfMappedPropertiesDontExist( method, mappings, sourceGetters, targetSetters );
|
||||
reportErrorIfMappedPropertiesDontExist( method, sourceProperties, targetProperties, mappings );
|
||||
|
||||
for ( ExecutableElement getterMethod : sourceGetters ) {
|
||||
String sourcePropertyName = Executables.getPropertyName( getterMethod );
|
||||
@ -509,12 +599,9 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
||||
return properties;
|
||||
}
|
||||
|
||||
private void reportErrorIfMappedPropertiesDontExist(ExecutableElement method, Map<String, Mapping> mappings,
|
||||
List<ExecutableElement> sourceGetters,
|
||||
List<ExecutableElement> targetSetters) {
|
||||
|
||||
Set<String> sourcePropertyNames = Executables.getPropertyNames( sourceGetters );
|
||||
Set<String> targetPropertyNames = Executables.getPropertyNames( targetSetters );
|
||||
private void reportErrorIfMappedPropertiesDontExist(ExecutableElement method, Set<String> sourcePropertyNames,
|
||||
Set<String> targetPropertyNames,
|
||||
Map<String, Mapping> mappings) {
|
||||
|
||||
for ( Mapping mappedProperty : mappings.values() ) {
|
||||
if ( !sourcePropertyNames.contains( mappedProperty.getSourceName() ) ) {
|
||||
@ -594,4 +681,11 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
||||
.printMessage( Kind.ERROR, message, element, annotationMirror, annotationValue );
|
||||
mappingErroneous = true;
|
||||
}
|
||||
|
||||
private void printMessage(ReportingPolicy reportingPolicy, String message, Element element) {
|
||||
processingEnvironment.getMessager().printMessage( reportingPolicy.getDiagnosticKind(), message, element );
|
||||
if ( reportingPolicy.failsBuild() ) {
|
||||
mappingErroneous = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* 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.model;
|
||||
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.Diagnostic.Kind;
|
||||
|
||||
/**
|
||||
* Possible issue reporting policies. Duplicates the enum of the same name from
|
||||
* the core module as this can't be referenced here.
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
public enum ReportingPolicy {
|
||||
|
||||
IGNORE( null, false, false ), WARN( Kind.WARNING, true, false ), ERROR( Kind.ERROR, true, true );
|
||||
|
||||
private final Diagnostic.Kind diagnosticKind;
|
||||
private final boolean requiresReport;
|
||||
private final boolean failsBuild;
|
||||
|
||||
private ReportingPolicy(Diagnostic.Kind diagnosticKind, boolean requiresReport, boolean failsBuild) {
|
||||
this.requiresReport = requiresReport;
|
||||
this.diagnosticKind = diagnosticKind;
|
||||
this.failsBuild = failsBuild;
|
||||
}
|
||||
|
||||
public Diagnostic.Kind getDiagnosticKind() {
|
||||
return diagnosticKind;
|
||||
}
|
||||
|
||||
public boolean requiresReport() {
|
||||
return requiresReport;
|
||||
}
|
||||
|
||||
public boolean failsBuild() {
|
||||
return failsBuild;
|
||||
}
|
||||
}
|
@ -18,7 +18,9 @@
|
||||
*/
|
||||
package org.mapstruct.ap.model.source;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
|
||||
import org.mapstruct.ap.model.Type;
|
||||
@ -36,18 +38,64 @@ public class Method {
|
||||
private final String parameterName;
|
||||
private final Type sourceType;
|
||||
private final Type targetType;
|
||||
private Set<String> sourceProperties;
|
||||
private Set<String> targetProeprties;
|
||||
private final List<MappedProperty> mappedProperties;
|
||||
|
||||
public Method(Type declaringMapper, ExecutableElement executable, String parameterName, Type sourceType,
|
||||
Type targetType, List<MappedProperty> mappedProperties) {
|
||||
public static Method forMethodRequiringImplementation(ExecutableElement executable, String parameterName,
|
||||
Type sourceType,
|
||||
Type targetType, Set<String> sourceProperties,
|
||||
Set<String> targetProperties,
|
||||
List<MappedProperty> mappedProperties) {
|
||||
|
||||
return new Method(
|
||||
null,
|
||||
executable,
|
||||
parameterName,
|
||||
sourceType,
|
||||
targetType,
|
||||
sourceProperties,
|
||||
targetProperties,
|
||||
mappedProperties
|
||||
);
|
||||
}
|
||||
|
||||
public static Method forReferencedMethod(Type declaringMapper, ExecutableElement executable, String parameterName,
|
||||
Type sourceType,
|
||||
Type targetType) {
|
||||
|
||||
return new Method(
|
||||
declaringMapper,
|
||||
executable,
|
||||
parameterName,
|
||||
sourceType,
|
||||
targetType,
|
||||
Collections.<String>emptySet(),
|
||||
Collections.<String>emptySet(),
|
||||
Collections.<MappedProperty>emptyList()
|
||||
);
|
||||
}
|
||||
|
||||
private Method(Type declaringMapper, ExecutableElement executable, String parameterName, Type sourceType,
|
||||
Type targetType, Set<String> sourceProperties, Set<String> targetProperties,
|
||||
List<MappedProperty> mappedProperties) {
|
||||
this.declaringMapper = declaringMapper;
|
||||
this.executable = executable;
|
||||
this.parameterName = parameterName;
|
||||
this.sourceType = sourceType;
|
||||
this.targetType = targetType;
|
||||
this.sourceProperties = sourceProperties;
|
||||
this.targetProeprties = targetProperties;
|
||||
this.mappedProperties = mappedProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mapper type declaring this method if it is not declared by
|
||||
* the mapper interface currently processed but by another mapper imported
|
||||
* via {@code Mapper#users()}.
|
||||
*
|
||||
* @return The declaring mapper type
|
||||
*/
|
||||
public Type getDeclaringMapper() {
|
||||
return declaringMapper;
|
||||
}
|
||||
@ -72,6 +120,14 @@ public class Method {
|
||||
return targetType;
|
||||
}
|
||||
|
||||
public Set<String> getSourceProperties() {
|
||||
return sourceProperties;
|
||||
}
|
||||
|
||||
public Set<String> getTargetProeprties() {
|
||||
return targetProeprties;
|
||||
}
|
||||
|
||||
public List<MappedProperty> getMappedProperties() {
|
||||
return mappedProperties;
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ import java.beans.Introspector;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
|
||||
|
@ -18,6 +18,11 @@
|
||||
*/
|
||||
package org.mapstruct.ap.util;
|
||||
|
||||
/**
|
||||
* Helper class for dealing with strings.
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
public class Strings {
|
||||
|
||||
private Strings() {
|
||||
@ -26,4 +31,22 @@ public class Strings {
|
||||
public static String capitalize(String name) {
|
||||
return name == null ? null : name.substring( 0, 1 ).toUpperCase() + name.substring( 1 );
|
||||
}
|
||||
|
||||
public static String join(Iterable<?> iterable, String separator) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
boolean isFirst = true;
|
||||
|
||||
for ( Object object : iterable ) {
|
||||
if ( !isFirst ) {
|
||||
sb.append( separator );
|
||||
}
|
||||
else {
|
||||
isFirst = false;
|
||||
}
|
||||
|
||||
sb.append( object );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,10 @@ public class ErroneousMappingsTest extends MapperTestBase {
|
||||
kind = Kind.ERROR,
|
||||
line = 27,
|
||||
messageRegExp = ".*Unknown property \"bar\" in return type.*"),
|
||||
@Diagnostic(type = ErroneousMapper.class,
|
||||
kind = Kind.WARNING,
|
||||
line = 28,
|
||||
messageRegExp = "Unmapped target property: \"foo\""),
|
||||
@Diagnostic(type = ErroneousMapper.class,
|
||||
kind = Kind.ERROR,
|
||||
line = 30,
|
||||
|
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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.unmappedtarget;
|
||||
|
||||
public class Source {
|
||||
|
||||
private Long foo;
|
||||
|
||||
private String qux;
|
||||
|
||||
public Long getFoo() {
|
||||
return foo;
|
||||
}
|
||||
|
||||
public void setFoo(Long foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
public String getQux() {
|
||||
return qux;
|
||||
}
|
||||
|
||||
public void setQux(String qux) {
|
||||
this.qux = qux;
|
||||
}
|
||||
}
|
@ -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.unmappedtarget;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface SourceTargetMapper {
|
||||
|
||||
SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
|
||||
|
||||
Target sourceToTarget(Source source);
|
||||
|
||||
Source targetToSource(Target target);
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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.unmappedtarget;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mappers;
|
||||
import org.mapstruct.ReportingPolicy;
|
||||
|
||||
@Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR)
|
||||
public interface StrictSourceTargetMapper {
|
||||
|
||||
StrictSourceTargetMapper INSTANCE = Mappers.getMapper( StrictSourceTargetMapper.class );
|
||||
|
||||
Target sourceToTarget(Source source);
|
||||
|
||||
Source targetToSource(Target target);
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* 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.unmappedtarget;
|
||||
|
||||
public class Target {
|
||||
|
||||
private Long foo;
|
||||
private int bar;
|
||||
|
||||
public Long getFoo() {
|
||||
return foo;
|
||||
}
|
||||
|
||||
public void setFoo(Long foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
public int getBar() {
|
||||
return bar;
|
||||
}
|
||||
|
||||
public void setBar(int bar) {
|
||||
this.bar = bar;
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/**
|
||||
* 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.unmappedtarget;
|
||||
|
||||
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;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests expected diagnostics for unmapped target properties.
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
@IssueKey("35")
|
||||
public class UnmappedTargetTest extends MapperTestBase {
|
||||
|
||||
@Test
|
||||
@WithClasses({ Source.class, Target.class, SourceTargetMapper.class })
|
||||
@ExpectedCompilationOutcome(
|
||||
value = CompilationResult.SUCCEEDED,
|
||||
diagnostics = {
|
||||
@Diagnostic(type = SourceTargetMapper.class,
|
||||
kind = Kind.WARNING,
|
||||
line = 29,
|
||||
messageRegExp = "Unmapped target property: \"bar\""),
|
||||
@Diagnostic(type = SourceTargetMapper.class,
|
||||
kind = Kind.WARNING,
|
||||
line = 31,
|
||||
messageRegExp = "Unmapped target property: \"qux\"")
|
||||
}
|
||||
)
|
||||
public void shouldLeaveUnmappedTargetPropertyUnset() {
|
||||
Source source = new Source();
|
||||
source.setFoo( 42L );
|
||||
|
||||
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
|
||||
|
||||
assertThat( target ).isNotNull();
|
||||
assertThat( target.getFoo() ).isEqualTo( 42L );
|
||||
assertThat( target.getBar() ).isEqualTo( 0 );
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithClasses({ Source.class, Target.class, StrictSourceTargetMapper.class })
|
||||
@ExpectedCompilationOutcome(
|
||||
value = CompilationResult.FAILED,
|
||||
diagnostics = {
|
||||
@Diagnostic(type = StrictSourceTargetMapper.class,
|
||||
kind = Kind.ERROR,
|
||||
line = 30,
|
||||
messageRegExp = "Unmapped target property: \"bar\""),
|
||||
@Diagnostic(type = StrictSourceTargetMapper.class,
|
||||
kind = Kind.ERROR,
|
||||
line = 32,
|
||||
messageRegExp = "Unmapped target property: \"qux\"")
|
||||
}
|
||||
)
|
||||
public void shouldRaiseErrorDueToUnsetTargetProperty() {
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user