#880 Fix override behaviour for componentModel and unmappedTargetPolicy.

This commit is contained in:
Andreas Gudian 2016-09-01 22:31:21 +02:00
parent c73d007fc8
commit 8071723bae
10 changed files with 200 additions and 70 deletions

View File

@ -127,13 +127,12 @@ public class MappingProcessor extends AbstractProcessor {
private Options createOptions() {
String unmappedTargetPolicy = processingEnv.getOptions().get( UNMAPPED_TARGET_POLICY );
String defaultComponentModel = processingEnv.getOptions().get( DEFAULT_COMPONENT_MODEL );
return new Options(
Boolean.valueOf( processingEnv.getOptions().get( SUPPRESS_GENERATOR_TIMESTAMP ) ),
Boolean.valueOf( processingEnv.getOptions().get( SUPPRESS_GENERATOR_VERSION_INFO_COMMENT ) ),
unmappedTargetPolicy != null ? ReportingPolicy.valueOf( unmappedTargetPolicy ) : null,
defaultComponentModel == null ? "default" : defaultComponentModel,
unmappedTargetPolicy != null ? ReportingPolicy.valueOf( unmappedTargetPolicy.toUpperCase() ) : null,
processingEnv.getOptions().get( DEFAULT_COMPONENT_MODEL ),
Boolean.valueOf( processingEnv.getOptions().get( ALWAYS_GENERATE_SERVICE_FILE ) )
);
}

View File

@ -508,32 +508,16 @@ public class BeanMappingMethod extends MappingMethod {
return method.getResultType().getPropertyReadAccessors().get( propertyName );
}
/**
* Returns the effective policy for reporting unmapped getReturnType properties. If explicitly set via
* {@code Mapper}, this value will be returned. Otherwise the value from the corresponding processor option will
* be returned. If that is not set either, the default value from {@code Mapper#unmappedTargetPolicy()} will be
* returned.
*
* @return The effective policy for reporting unmapped target properties.
*/
private ReportingPolicy getEffectiveUnmappedTargetPolicy() {
private ReportingPolicy getUnmappedTargetPolicy() {
MapperConfiguration mapperSettings = MapperConfiguration.getInstanceOn( ctx.getMapperTypeElement() );
boolean setViaAnnotation = mapperSettings.isSetUnmappedTargetPolicy();
ReportingPolicy annotationValue = ReportingPolicy.valueOf( mapperSettings.unmappedTargetPolicy() );
if ( setViaAnnotation
|| ctx.getOptions().getUnmappedTargetPolicy() == null ) {
return annotationValue;
}
else {
return ctx.getOptions().getUnmappedTargetPolicy();
}
return mapperSettings.unmappedTargetPolicy( ctx.getOptions() );
}
private void reportErrorForUnmappedTargetPropertiesIfRequired() {
// fetch settings from element to implement
ReportingPolicy unmappedTargetPolicy = getEffectiveUnmappedTargetPolicy();
ReportingPolicy unmappedTargetPolicy = getUnmappedTargetPolicy();
if ( !unprocessedTargetProperties.isEmpty() && unmappedTargetPolicy.requiresReport() ) {

View File

@ -32,7 +32,6 @@ import org.mapstruct.ap.internal.model.Field;
import org.mapstruct.ap.internal.model.Mapper;
import org.mapstruct.ap.internal.model.MapperReference;
import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.option.OptionsHelper;
import org.mapstruct.ap.internal.util.MapperConfiguration;
/**
@ -51,13 +50,10 @@ public abstract class AnnotationBasedComponentModelProcessor implements ModelEle
public Mapper process(ProcessorContext context, TypeElement mapperTypeElement, Mapper mapper) {
this.typeFactory = context.getTypeFactory();
String componentModel = MapperConfiguration.getInstanceOn( mapperTypeElement ).componentModel();
String effectiveComponentModel = OptionsHelper.getEffectiveComponentModel(
context.getOptions(),
componentModel
);
String componentModel = MapperConfiguration.getInstanceOn( mapperTypeElement )
.componentModel( context.getOptions() );
if ( !getComponentModelIdentifier().equalsIgnoreCase( effectiveComponentModel ) ) {
if ( !getComponentModelIdentifier().equalsIgnoreCase( componentModel ) ) {
return mapper;
}

View File

@ -28,7 +28,6 @@ import javax.tools.StandardLocation;
import org.mapstruct.ap.internal.model.GeneratedType;
import org.mapstruct.ap.internal.model.Mapper;
import org.mapstruct.ap.internal.model.ServicesEntry;
import org.mapstruct.ap.internal.option.OptionsHelper;
import org.mapstruct.ap.internal.util.MapperConfiguration;
import org.mapstruct.ap.internal.writer.ModelWriter;
@ -50,13 +49,10 @@ public class MapperServiceProcessor implements ModelElementProcessor<Mapper, Vo
spiGenerationNeeded = true;
}
else {
String componentModel = MapperConfiguration.getInstanceOn( mapperTypeElement ).componentModel();
String effectiveComponentModel = OptionsHelper.getEffectiveComponentModel(
context.getOptions(),
componentModel
);
String componentModel =
MapperConfiguration.getInstanceOn( mapperTypeElement ).componentModel( context.getOptions() );
spiGenerationNeeded = "default".equals( effectiveComponentModel );
spiGenerationNeeded = "default".equals( componentModel );
}
if ( !context.isErroneous() && spiGenerationNeeded && mapper.hasCustomImplementation() ) {

View File

@ -27,12 +27,14 @@ import javax.lang.model.element.Element;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import org.mapstruct.ap.internal.option.Options;
import org.mapstruct.ap.internal.option.ReportingPolicy;
import org.mapstruct.ap.internal.prism.CollectionMappingStrategyPrism;
import org.mapstruct.ap.internal.prism.MapperConfigPrism;
import org.mapstruct.ap.internal.prism.MapperPrism;
import org.mapstruct.ap.internal.prism.MappingInheritanceStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
/**
* Provides an aggregated view to the settings given via {@link org.mapstruct.Mapper} and
@ -109,13 +111,21 @@ public class MapperConfiguration {
return mapperPrism.imports();
}
public String unmappedTargetPolicy() {
if ( mapperConfigPrism != null && mapperPrism.values.unmappedTargetPolicy() == null ) {
return mapperConfigPrism.unmappedTargetPolicy();
public ReportingPolicy unmappedTargetPolicy(Options options) {
if ( mapperPrism.values.unmappedTargetPolicy() != null ) {
return ReportingPolicy.valueOf( mapperPrism.unmappedTargetPolicy() );
}
else {
return mapperPrism.unmappedTargetPolicy();
if ( mapperConfigPrism != null && mapperConfigPrism.values.unmappedTargetPolicy() != null ) {
return ReportingPolicy.valueOf( mapperConfigPrism.unmappedTargetPolicy() );
}
if ( options.getUnmappedTargetPolicy() != null ) {
return options.getUnmappedTargetPolicy();
}
// fall back to default defined in the annotation
return ReportingPolicy.valueOf( mapperPrism.unmappedTargetPolicy() );
}
public CollectionMappingStrategyPrism getCollectionMappingStrategy() {
@ -169,13 +179,20 @@ public class MapperConfiguration {
}
public String componentModel() {
if ( mapperConfigPrism != null && mapperPrism.values.componentModel() == null ) {
return mapperConfigPrism.componentModel();
}
else {
public String componentModel(Options options) {
if ( mapperPrism.values.componentModel() != null ) {
return mapperPrism.componentModel();
}
if ( mapperConfigPrism != null && mapperConfigPrism.values.componentModel() != null ) {
return mapperConfigPrism.componentModel();
}
if ( options.getDefaultComponentModel() != null ) {
return options.getDefaultComponentModel();
}
return mapperPrism.componentModel(); // fall back to default defined in the annotation
}
public DeclaredType config() {
@ -186,12 +203,7 @@ public class MapperConfiguration {
return mapperPrism.isValid;
}
public boolean isSetUnmappedTargetPolicy() {
return mapperPrism.values.unmappedTargetPolicy() != null;
}
public AnnotationMirror getAnnotationMirror() {
return mapperPrism.mirror;
}
}

View File

@ -0,0 +1,30 @@
/**
* Copyright 2012-2016 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.bugs._880;
import org.mapstruct.MapperConfig;
import org.mapstruct.ReportingPolicy;
/**
* @author Andreas Gudian
*/
@MapperConfig(unmappedTargetPolicy = ReportingPolicy.WARN)
public interface Config {
}

View File

@ -0,0 +1,30 @@
/**
* Copyright 2012-2016 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.bugs._880;
import org.mapstruct.Mapper;
/**
* @author Andreas Gudian
*
*/
@Mapper
public interface DefaultsToProcessorOptionsMapper {
Poodle metamorph(Object essence);
}

View File

@ -0,0 +1,63 @@
/**
* Copyright 2012-2016 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.bugs._880;
import javax.tools.Diagnostic.Kind;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
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.compilation.annotation.ProcessorOption;
import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOptions;
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
import org.mapstruct.ap.testutil.runner.GeneratedSource;
import org.springframework.stereotype.Component;
/**
* @author Andreas Gudian
*/
@RunWith(AnnotationProcessorTestRunner.class)
@WithClasses({
UsesConfigFromAnnotationMapper.class,
DefaultsToProcessorOptionsMapper.class,
Poodle.class,
Config.class })
@ProcessorOptions({
@ProcessorOption(name = "mapstruct.defaultComponentModel", value = "spring"),
@ProcessorOption(name = "mapstruct.unmappedTargetPolicy", value = "ignore") })
public class Issue880Test {
@Rule
public GeneratedSource generatedSource = new GeneratedSource();
@Test
@ExpectedCompilationOutcome(
value = CompilationResult.SUCCEEDED,
diagnostics = @Diagnostic(kind = Kind.WARNING,
type = UsesConfigFromAnnotationMapper.class, line = 29,
messageRegExp = "Unmapped target property: \"core\"\\."))
public void compilationSucceedsAndAppliesCorrectComponentModel() {
generatedSource.forMapper( UsesConfigFromAnnotationMapper.class ).containsNoImportFor( Component.class );
generatedSource.forMapper( DefaultsToProcessorOptionsMapper.class ).containsImportFor( Component.class );
}
}

View File

@ -16,30 +16,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.internal.option;
package org.mapstruct.ap.test.bugs._880;
/**
* Helper class for dealing with {@link Options}.
*
* @author Andreas Gudian
*
*/
public class OptionsHelper {
public class Poodle {
private String core;
private OptionsHelper() {
public String getCore() {
return core;
}
/**
* @param options the options
* @param locallyDeclaredComponentModel the locally declared component model
*
* @return the effective component model to be used
*/
public static String getEffectiveComponentModel(Options options, String locallyDeclaredComponentModel) {
if ( "default".equals( locallyDeclaredComponentModel ) ) {
return options.getDefaultComponentModel();
}
return locallyDeclaredComponentModel;
public void setCore(String core) {
this.core = core;
}
}

View File

@ -0,0 +1,30 @@
/**
* Copyright 2012-2016 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.bugs._880;
import org.mapstruct.Mapper;
/**
* @author Andreas Gudian
*
*/
@Mapper(componentModel = "default", config = Config.class)
public interface UsesConfigFromAnnotationMapper {
Poodle metamorph(Object essence);
}