diff --git a/core-common/src/main/java/org/mapstruct/BeanMapping.java b/core-common/src/main/java/org/mapstruct/BeanMapping.java index 76eac373f..10d0e70f7 100644 --- a/core-common/src/main/java/org/mapstruct/BeanMapping.java +++ b/core-common/src/main/java/org/mapstruct/BeanMapping.java @@ -83,4 +83,18 @@ public @interface BeanMapping { * @since 1.3 */ boolean ignoreByDefault() default false; + + /** + * Unmapped source properties to be ignored. This could be used when {@link ReportingPolicy#WARN} + * or {@link ReportingPolicy#ERROR} is used for {@link Mapper#unmappedSourcePolicy()} or + * {@link MapperConfig#unmappedSourcePolicy()}. Listed properties will be ignored when composing the unmapped + * source properties report. + *

+ * NOTE: This does not support ignoring nested source properties + * + * @return The source properties that should be ignored when performing a report + * + * @since 1.3 + */ + String[] ignoreUnmappedSourceProperties() default {}; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java index 506b4bf4e..4886e475e 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java @@ -45,6 +45,7 @@ import org.mapstruct.ap.internal.model.common.Parameter; import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.dependency.GraphAnalyzer; import org.mapstruct.ap.internal.model.dependency.GraphAnalyzer.GraphAnalyzerBuilder; +import org.mapstruct.ap.internal.model.source.BeanMapping; import org.mapstruct.ap.internal.model.source.ForgedMethod; import org.mapstruct.ap.internal.model.source.ForgedMethodHistory; import org.mapstruct.ap.internal.model.source.Mapping; @@ -133,6 +134,14 @@ public class BeanMappingMethod extends NormalTypeMappingMethod { } } existingVariableNames.addAll( method.getParameterNames() ); + + BeanMapping beanMapping = method.getMappingOptions().getBeanMapping(); + if ( beanMapping != null ) { + for ( String ignoreUnmapped : beanMapping.getIgnoreUnmappedSourceProperties() ) { + unprocessedSourceProperties.remove( ignoreUnmapped ); + } + } + return this; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/BeanMapping.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/BeanMapping.java index 55610f995..e3580de65 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/BeanMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/BeanMapping.java @@ -18,6 +18,8 @@ */ package org.mapstruct.ap.internal.model.source; +import java.util.Collections; +import java.util.List; import javax.lang.model.element.ExecutableElement; import javax.lang.model.type.TypeKind; import javax.lang.model.util.Types; @@ -39,6 +41,7 @@ public class BeanMapping { private final NullValueMappingStrategyPrism nullValueMappingStrategy; private final ReportingPolicyPrism reportingPolicy; private final boolean ignoreByDefault; + private final List ignoreUnmappedSourceProperties; /** * creates a mapping for inheritance. Will set ignoreByDefault to false. @@ -47,7 +50,13 @@ public class BeanMapping { * @return */ public static BeanMapping forInheritance( BeanMapping map ) { - return new BeanMapping( map.selectionParameters, map.nullValueMappingStrategy, map.reportingPolicy, false ); + return new BeanMapping( + map.selectionParameters, + map.nullValueMappingStrategy, + map.reportingPolicy, + false, + map.ignoreUnmappedSourceProperties + ); } public static BeanMapping fromPrism(BeanMappingPrism beanMapping, ExecutableElement method, @@ -66,6 +75,7 @@ public class BeanMapping { boolean ignoreByDefault = beanMapping.ignoreByDefault(); if ( !resultTypeIsDefined && beanMapping.qualifiedBy().isEmpty() && beanMapping.qualifiedByName().isEmpty() + && beanMapping.ignoreUnmappedSourceProperties().isEmpty() && ( nullValueMappingStrategy == null ) && !ignoreByDefault ) { messager.printMessage( method, Message.BEANMAPPING_NO_ELEMENTS ); @@ -79,7 +89,13 @@ public class BeanMapping { ); //TODO Do we want to add the reporting policy to the BeanMapping as well? To give more granular support? - return new BeanMapping( cmp, nullValueMappingStrategy, null, ignoreByDefault ); + return new BeanMapping( + cmp, + nullValueMappingStrategy, + null, + ignoreByDefault, + beanMapping.ignoreUnmappedSourceProperties() + ); } /** @@ -89,15 +105,17 @@ public class BeanMapping { * @return bean mapping that needs to be used for Mappings */ public static BeanMapping forForgedMethods() { - return new BeanMapping( null, null, ReportingPolicyPrism.IGNORE, false ); + return new BeanMapping( null, null, ReportingPolicyPrism.IGNORE, false, Collections.emptyList() ); } private BeanMapping(SelectionParameters selectionParameters, NullValueMappingStrategyPrism nvms, - ReportingPolicyPrism reportingPolicy, boolean ignoreByDefault) { + ReportingPolicyPrism reportingPolicy, boolean ignoreByDefault, + List ignoreUnmappedSourceProperties) { this.selectionParameters = selectionParameters; this.nullValueMappingStrategy = nvms; this.reportingPolicy = reportingPolicy; this.ignoreByDefault = ignoreByDefault; + this.ignoreUnmappedSourceProperties = ignoreUnmappedSourceProperties; } public SelectionParameters getSelectionParameters() { @@ -116,4 +134,7 @@ public class BeanMapping { return ignoreByDefault; } + public List getIgnoreUnmappedSourceProperties() { + return ignoreUnmappedSourceProperties; + } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/source/ignore/IgnoreUnmappedSourceMapper.java b/processor/src/test/java/org/mapstruct/ap/test/source/ignore/IgnoreUnmappedSourceMapper.java new file mode 100644 index 000000000..d6ad432ff --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/source/ignore/IgnoreUnmappedSourceMapper.java @@ -0,0 +1,41 @@ +/** + * Copyright 2012-2017 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.source.ignore; + +import org.mapstruct.BeanMapping; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; + +/** + * @author Filip Hrisafov + */ +@Mapper( + unmappedTargetPolicy = ReportingPolicy.IGNORE, + unmappedSourcePolicy = ReportingPolicy.ERROR +) +public interface IgnoreUnmappedSourceMapper { + + @BeanMapping( + ignoreUnmappedSourceProperties = { + "name", + "surname" + } + ) + PersonDto map(Person person); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/source/ignore/IgnoreUnmappedSourcePropertiesTest.java b/processor/src/test/java/org/mapstruct/ap/test/source/ignore/IgnoreUnmappedSourcePropertiesTest.java new file mode 100644 index 000000000..2a76a47ea --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/source/ignore/IgnoreUnmappedSourcePropertiesTest.java @@ -0,0 +1,43 @@ +/** + * Copyright 2012-2017 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.source.ignore; + +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.runner.AnnotationProcessorTestRunner; + +/** + * @author Filip Hrisafov + */ +@WithClasses({ + IgnoreUnmappedSourceMapper.class, + Person.class, + PersonDto.class +}) +@RunWith( AnnotationProcessorTestRunner.class ) +@IssueKey("1317") +public class IgnoreUnmappedSourcePropertiesTest { + + @Test + public void shouldNotReportErrorOnIgnoredUnmappedSourceProperties() { + + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/source/ignore/Person.java b/processor/src/test/java/org/mapstruct/ap/test/source/ignore/Person.java new file mode 100644 index 000000000..8bd43eff1 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/source/ignore/Person.java @@ -0,0 +1,44 @@ +/** + * Copyright 2012-2017 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.source.ignore; + +/** + * @author Filip Hrisafov + */ +public class Person { + + private String name; + private String surname; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSurname() { + return surname; + } + + public void setSurname(String surname) { + this.surname = surname; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/source/ignore/PersonDto.java b/processor/src/test/java/org/mapstruct/ap/test/source/ignore/PersonDto.java new file mode 100644 index 000000000..97faec652 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/source/ignore/PersonDto.java @@ -0,0 +1,44 @@ +/** + * Copyright 2012-2017 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.source.ignore; + +/** + * @author Filip Hrisafov + */ +public class PersonDto { + + private String firstName; + private String lastName; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } +}