mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#168 Allow to inherit mapping method configurations from the @MapperConfig-annotated type, either automatically when all method types match, or explicitly using @InheritConfiguration.
This commit is contained in:
parent
2c845480a0
commit
952ee8526d
@ -112,4 +112,17 @@ public @interface Mapper {
|
|||||||
* @return The strategy to be applied when {@code null} is passed as source value to the methods of this mapper.
|
* @return The strategy to be applied when {@code null} is passed as source value to the methods of this mapper.
|
||||||
*/
|
*/
|
||||||
NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.DEFAULT;
|
NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.DEFAULT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The strategy to use for applying method-level configuration annotations of prototype methods in the interface
|
||||||
|
* specified with {@link #config()}. Annotations that can be inherited are for example {@link Mapping},
|
||||||
|
* {@link IterableMapping}, {@link MapMapping}, or {@link BeanMapping}.
|
||||||
|
* <p>
|
||||||
|
* If no strategy is configured, the strategy given via {@link MapperConfig#mappingInheritanceStrategy()} will be
|
||||||
|
* applied, using {@link MappingInheritanceStrategy#EXPLICIT} as default.
|
||||||
|
*
|
||||||
|
* @return The strategy to use for applying {@code @Mapping} configurations of prototype methods in the interface
|
||||||
|
* specified with {@link #config()}.
|
||||||
|
*/
|
||||||
|
MappingInheritanceStrategy mappingInheritanceStrategy() default MappingInheritanceStrategy.DEFAULT;
|
||||||
}
|
}
|
||||||
|
@ -26,10 +26,18 @@ import java.lang.annotation.Target;
|
|||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks a class-, interface-, enum declaration as (common) configuration.
|
* Marks a class- or interface-declaration as (common) configuration.
|
||||||
*
|
* <p>
|
||||||
* The {@link #unmappedTargetPolicy() } and {@link #componentModel() } can be overruled by a specific {@link Mapper}
|
* The {@link #unmappedTargetPolicy() } and {@link #componentModel() } can be overruled by a specific {@link Mapper}
|
||||||
* annotation. {@link #uses() } will be used in addition to what is specified in the {@link Mapper} annotation.
|
* annotation. {@link #uses() } will be used in addition to what is specified in the {@link Mapper} annotation.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Mapping methods defined in the annotated type can be used as <em>prototypes</em> from which method-level annotations
|
||||||
|
* such as {@code @Mapping}, {@code @IterableMapping}, etc. can be inherited. Depending on the configured
|
||||||
|
* {@link #mappingInheritanceStrategy()}, the configuration can be inherited either explicitly using
|
||||||
|
* {@link InheritConfiguration} or {@link InheritInverseConfiguration}, or automatically in case all source and target
|
||||||
|
* types are assignable.
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* @author Sjaak Derksen
|
* @author Sjaak Derksen
|
||||||
*/
|
*/
|
||||||
@ -80,7 +88,7 @@ public @interface MapperConfig {
|
|||||||
*
|
*
|
||||||
* @return The strategy applied when propagating the value of collection-typed properties.
|
* @return The strategy applied when propagating the value of collection-typed properties.
|
||||||
*/
|
*/
|
||||||
CollectionMappingStrategy collectionMappingStrategy() default CollectionMappingStrategy.DEFAULT;
|
CollectionMappingStrategy collectionMappingStrategy() default CollectionMappingStrategy.ACCESSOR_ONLY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The strategy to be applied when {@code null} is passed as source value to mapping methods. If no strategy is
|
* The strategy to be applied when {@code null} is passed as source value to mapping methods. If no strategy is
|
||||||
@ -88,5 +96,18 @@ public @interface MapperConfig {
|
|||||||
*
|
*
|
||||||
* @return The strategy to be applied when {@code null} is passed as source value to mapping methods.
|
* @return The strategy to be applied when {@code null} is passed as source value to mapping methods.
|
||||||
*/
|
*/
|
||||||
NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.DEFAULT;
|
NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.RETURN_NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The strategy to use for applying method-level configuration annotations of prototype methods in the interface
|
||||||
|
* annotated with this annotation. Annotations that can be inherited are for example {@link Mapping},
|
||||||
|
* {@link IterableMapping}, {@link MapMapping}, or {@link BeanMapping}.
|
||||||
|
* <p>
|
||||||
|
* If no strategy is configured, {@link MappingInheritanceStrategy#EXPLICIT} will be used as default.
|
||||||
|
*
|
||||||
|
* @return The strategy to use for applying {@code @Mapping} configurations of prototype methods in the interface
|
||||||
|
* annotated with this annotation.
|
||||||
|
*/
|
||||||
|
MappingInheritanceStrategy mappingInheritanceStrategy()
|
||||||
|
default MappingInheritanceStrategy.EXPLICIT;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The strategy to use for applying method-level configuration annotations of prototype methods in the interface
|
||||||
|
* specified with {@link Mapper#config()}.
|
||||||
|
*
|
||||||
|
* @author Andreas Gudian
|
||||||
|
*/
|
||||||
|
public enum MappingInheritanceStrategy {
|
||||||
|
/**
|
||||||
|
* Apply the method-level configuration annotations only if the prototype method is explicitly referenced using
|
||||||
|
* {@link InheritConfiguration}.
|
||||||
|
*/
|
||||||
|
EXPLICIT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the method-level configuration annotations if source and target types of the prototype method are
|
||||||
|
* assignable from the types of a given mapping method.
|
||||||
|
*/
|
||||||
|
AUTO_INHERIT_FROM_CONFIG,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When given via {@link Mapper#mappingInheritanceStrategy()}, the value specified via
|
||||||
|
* {@link MapperConfig#mappingInheritanceStrategy()} will be applied, if present.
|
||||||
|
* <p>
|
||||||
|
* When given via {@link MapperConfig#mappingInheritanceStrategy()}, the strategy {@link #EXPLICIT} will be applied.
|
||||||
|
*/
|
||||||
|
DEFAULT;
|
||||||
|
}
|
@ -27,6 +27,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
|
|
||||||
@ -43,9 +44,9 @@ import org.mapstruct.ap.option.ReportingPolicy;
|
|||||||
import org.mapstruct.ap.prism.BeanMappingPrism;
|
import org.mapstruct.ap.prism.BeanMappingPrism;
|
||||||
import org.mapstruct.ap.prism.CollectionMappingStrategyPrism;
|
import org.mapstruct.ap.prism.CollectionMappingStrategyPrism;
|
||||||
import org.mapstruct.ap.prism.NullValueMappingPrism;
|
import org.mapstruct.ap.prism.NullValueMappingPrism;
|
||||||
import org.mapstruct.ap.util.Message;
|
|
||||||
import org.mapstruct.ap.util.Executables;
|
import org.mapstruct.ap.util.Executables;
|
||||||
import org.mapstruct.ap.util.MapperConfig;
|
import org.mapstruct.ap.util.MapperConfig;
|
||||||
|
import org.mapstruct.ap.util.Message;
|
||||||
import org.mapstruct.ap.util.Strings;
|
import org.mapstruct.ap.util.Strings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,7 +146,7 @@ public class BeanMappingMethod extends MappingMethod {
|
|||||||
|
|
||||||
Set<String> handledTargets = new HashSet<String>();
|
Set<String> handledTargets = new HashSet<String>();
|
||||||
|
|
||||||
for ( Map.Entry<String, List<Mapping>> entry : method.getMappings().entrySet() ) {
|
for ( Map.Entry<String, List<Mapping>> entry : method.getMappingOptions().getMappings().entrySet() ) {
|
||||||
for ( Mapping mapping : entry.getValue() ) {
|
for ( Mapping mapping : entry.getValue() ) {
|
||||||
|
|
||||||
PropertyMapping propertyMapping = null;
|
PropertyMapping propertyMapping = null;
|
||||||
|
@ -29,6 +29,8 @@ import org.mapstruct.ap.model.source.SourceMethod;
|
|||||||
import org.mapstruct.ap.util.Message;
|
import org.mapstruct.ap.util.Message;
|
||||||
import org.mapstruct.ap.util.Strings;
|
import org.mapstruct.ap.util.Strings;
|
||||||
|
|
||||||
|
import static org.mapstruct.ap.util.Collections.first;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link MappingMethod} which maps one enum type to another, optionally configured by one or more
|
* A {@link MappingMethod} which maps one enum type to another, optionally configured by one or more
|
||||||
* {@link EnumMapping}s.
|
* {@link EnumMapping}s.
|
||||||
@ -63,8 +65,7 @@ public class EnumMappingMethod extends MappingMethod {
|
|||||||
|
|
||||||
List<EnumMapping> enumMappings = new ArrayList<EnumMapping>();
|
List<EnumMapping> enumMappings = new ArrayList<EnumMapping>();
|
||||||
|
|
||||||
List<String> sourceEnumConstants
|
List<String> sourceEnumConstants = first( method.getSourceParameters() ).getType().getEnumConstants();
|
||||||
= method.getSourceParameters().iterator().next().getType().getEnumConstants();
|
|
||||||
|
|
||||||
for ( String enumConstant : sourceEnumConstants ) {
|
for ( String enumConstant : sourceEnumConstants ) {
|
||||||
List<Mapping> mappedConstants = method.getMappingBySourcePropertyName( enumConstant );
|
List<Mapping> mappedConstants = method.getMappingBySourcePropertyName( enumConstant );
|
||||||
@ -75,7 +76,7 @@ public class EnumMappingMethod extends MappingMethod {
|
|||||||
else if ( mappedConstants.size() == 1 ) {
|
else if ( mappedConstants.size() == 1 ) {
|
||||||
enumMappings.add(
|
enumMappings.add(
|
||||||
new EnumMapping(
|
new EnumMapping(
|
||||||
enumConstant, mappedConstants.iterator().next().getTargetName()
|
enumConstant, first( mappedConstants ).getTargetName()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -96,13 +97,12 @@ public class EnumMappingMethod extends MappingMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean reportErrorIfMappedEnumConstantsDontExist(SourceMethod method) {
|
private boolean reportErrorIfMappedEnumConstantsDontExist(SourceMethod method) {
|
||||||
List<String> sourceEnumConstants =
|
List<String> sourceEnumConstants = first( method.getSourceParameters() ).getType().getEnumConstants();
|
||||||
method.getSourceParameters().iterator().next().getType().getEnumConstants();
|
|
||||||
List<String> targetEnumConstants = method.getReturnType().getEnumConstants();
|
List<String> targetEnumConstants = method.getReturnType().getEnumConstants();
|
||||||
|
|
||||||
boolean foundIncorrectMapping = false;
|
boolean foundIncorrectMapping = false;
|
||||||
|
|
||||||
for ( List<Mapping> mappedConstants : method.getMappings().values() ) {
|
for ( List<Mapping> mappedConstants : method.getMappingOptions().getMappings().values() ) {
|
||||||
for ( Mapping mappedConstant : mappedConstants ) {
|
for ( Mapping mappedConstant : mappedConstants ) {
|
||||||
|
|
||||||
if ( mappedConstant.getSourceName() == null ) {
|
if ( mappedConstant.getSourceName() == null ) {
|
||||||
@ -118,7 +118,7 @@ public class EnumMappingMethod extends MappingMethod {
|
|||||||
mappedConstant.getSourceAnnotationValue(),
|
mappedConstant.getSourceAnnotationValue(),
|
||||||
Message.ENUMMAPPING_NON_EXISTING_CONSTANT,
|
Message.ENUMMAPPING_NON_EXISTING_CONSTANT,
|
||||||
mappedConstant.getSourceName(),
|
mappedConstant.getSourceName(),
|
||||||
method.getSourceParameters().iterator().next().getType()
|
first( method.getSourceParameters() ).getType()
|
||||||
);
|
);
|
||||||
foundIncorrectMapping = true;
|
foundIncorrectMapping = true;
|
||||||
}
|
}
|
||||||
@ -148,8 +148,7 @@ public class EnumMappingMethod extends MappingMethod {
|
|||||||
private boolean reportErrorIfSourceEnumConstantsWithoutCorrespondingTargetConstantAreNotMapped(
|
private boolean reportErrorIfSourceEnumConstantsWithoutCorrespondingTargetConstantAreNotMapped(
|
||||||
SourceMethod method) {
|
SourceMethod method) {
|
||||||
|
|
||||||
List<String> sourceEnumConstants =
|
List<String> sourceEnumConstants = first( method.getSourceParameters() ).getType().getEnumConstants();
|
||||||
method.getSourceParameters().iterator().next().getType().getEnumConstants();
|
|
||||||
List<String> targetEnumConstants = method.getReturnType().getEnumConstants();
|
List<String> targetEnumConstants = method.getReturnType().getEnumConstants();
|
||||||
List<String> unmappedSourceEnumConstants = new ArrayList<String>();
|
List<String> unmappedSourceEnumConstants = new ArrayList<String>();
|
||||||
|
|
||||||
@ -182,6 +181,6 @@ public class EnumMappingMethod extends MappingMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Parameter getSourceParameter() {
|
public Parameter getSourceParameter() {
|
||||||
return getParameters().iterator().next();
|
return first( getParameters() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ package org.mapstruct.ap.model;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.lang.model.type.TypeKind;
|
import javax.lang.model.type.TypeKind;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
|
|
||||||
@ -30,10 +31,12 @@ import org.mapstruct.ap.model.common.Parameter;
|
|||||||
import org.mapstruct.ap.model.common.Type;
|
import org.mapstruct.ap.model.common.Type;
|
||||||
import org.mapstruct.ap.model.source.Method;
|
import org.mapstruct.ap.model.source.Method;
|
||||||
import org.mapstruct.ap.prism.NullValueMappingPrism;
|
import org.mapstruct.ap.prism.NullValueMappingPrism;
|
||||||
import org.mapstruct.ap.util.Message;
|
|
||||||
import org.mapstruct.ap.util.MapperConfig;
|
import org.mapstruct.ap.util.MapperConfig;
|
||||||
|
import org.mapstruct.ap.util.Message;
|
||||||
import org.mapstruct.ap.util.Strings;
|
import org.mapstruct.ap.util.Strings;
|
||||||
|
|
||||||
|
import static org.mapstruct.ap.util.Collections.first;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link MappingMethod} implemented by a {@link Mapper} class which maps one iterable type to another. The collection
|
* A {@link MappingMethod} implemented by a {@link Mapper} class which maps one iterable type to another. The collection
|
||||||
* elements are mapped either by a {@link TypeConversion} or another mapping method.
|
* elements are mapped either by a {@link TypeConversion} or another mapping method.
|
||||||
@ -82,7 +85,7 @@ public class IterableMappingMethod extends MappingMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IterableMappingMethod build() {
|
public IterableMappingMethod build() {
|
||||||
Type sourceParameterType = method.getSourceParameters().iterator().next().getType();
|
Type sourceParameterType = first( method.getSourceParameters() ).getType();
|
||||||
Type resultType = method.getResultType();
|
Type resultType = method.getResultType();
|
||||||
|
|
||||||
Type sourceElementType = sourceParameterType.isArrayType() ? sourceParameterType.getComponentType() :
|
Type sourceElementType = sourceParameterType.isArrayType() ? sourceParameterType.getComponentType() :
|
||||||
|
@ -20,6 +20,7 @@ package org.mapstruct.ap.model;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
|
|
||||||
import org.mapstruct.ap.model.assignment.Assignment;
|
import org.mapstruct.ap.model.assignment.Assignment;
|
||||||
@ -28,10 +29,12 @@ import org.mapstruct.ap.model.common.Parameter;
|
|||||||
import org.mapstruct.ap.model.common.Type;
|
import org.mapstruct.ap.model.common.Type;
|
||||||
import org.mapstruct.ap.model.source.Method;
|
import org.mapstruct.ap.model.source.Method;
|
||||||
import org.mapstruct.ap.prism.NullValueMappingPrism;
|
import org.mapstruct.ap.prism.NullValueMappingPrism;
|
||||||
import org.mapstruct.ap.util.Message;
|
|
||||||
import org.mapstruct.ap.util.MapperConfig;
|
import org.mapstruct.ap.util.MapperConfig;
|
||||||
|
import org.mapstruct.ap.util.Message;
|
||||||
import org.mapstruct.ap.util.Strings;
|
import org.mapstruct.ap.util.Strings;
|
||||||
|
|
||||||
|
import static org.mapstruct.ap.util.Collections.first;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link MappingMethod} implemented by a {@link Mapper} class which maps one {@code Map} type to another. Keys and
|
* A {@link MappingMethod} implemented by a {@link Mapper} class which maps one {@code Map} type to another. Keys and
|
||||||
* values are mapped either by a {@link TypeConversion} or another mapping method if required.
|
* values are mapped either by a {@link TypeConversion} or another mapping method if required.
|
||||||
@ -99,7 +102,7 @@ public class MapMappingMethod extends MappingMethod {
|
|||||||
|
|
||||||
public MapMappingMethod build() {
|
public MapMappingMethod build() {
|
||||||
|
|
||||||
List<Type> sourceTypeParams = method.getSourceParameters().iterator().next().getType().getTypeParameters();
|
List<Type> sourceTypeParams = first( method.getSourceParameters() ).getType().getTypeParameters();
|
||||||
List<Type> resultTypeParams = method.getResultType().getTypeParameters();
|
List<Type> resultTypeParams = method.getResultType().getTypeParameters();
|
||||||
|
|
||||||
// find mapping method or conversion for key
|
// find mapping method or conversion for key
|
||||||
|
@ -24,7 +24,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import org.mapstruct.ap.util.FormattingMessager;
|
|
||||||
import javax.lang.model.element.AnnotationMirror;
|
import javax.lang.model.element.AnnotationMirror;
|
||||||
import javax.lang.model.element.AnnotationValue;
|
import javax.lang.model.element.AnnotationValue;
|
||||||
import javax.lang.model.element.ElementKind;
|
import javax.lang.model.element.ElementKind;
|
||||||
@ -37,6 +37,7 @@ import org.mapstruct.ap.model.common.TypeFactory;
|
|||||||
import org.mapstruct.ap.prism.CollectionMappingStrategyPrism;
|
import org.mapstruct.ap.prism.CollectionMappingStrategyPrism;
|
||||||
import org.mapstruct.ap.prism.MappingPrism;
|
import org.mapstruct.ap.prism.MappingPrism;
|
||||||
import org.mapstruct.ap.prism.MappingsPrism;
|
import org.mapstruct.ap.prism.MappingsPrism;
|
||||||
|
import org.mapstruct.ap.util.FormattingMessager;
|
||||||
import org.mapstruct.ap.util.Message;
|
import org.mapstruct.ap.util.Message;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,7 +62,6 @@ public class Mapping {
|
|||||||
private final AnnotationValue sourceAnnotationValue;
|
private final AnnotationValue sourceAnnotationValue;
|
||||||
private final AnnotationValue targetAnnotationValue;
|
private final AnnotationValue targetAnnotationValue;
|
||||||
private SourceReference sourceReference;
|
private SourceReference sourceReference;
|
||||||
private SourceReference targetReference;
|
|
||||||
|
|
||||||
public static Map<String, List<Mapping>> fromMappingsPrism(MappingsPrism mappingsAnnotation,
|
public static Map<String, List<Mapping>> fromMappingsPrism(MappingsPrism mappingsAnnotation,
|
||||||
ExecutableElement method,
|
ExecutableElement method,
|
||||||
@ -239,10 +239,6 @@ public class Mapping {
|
|||||||
return sourceReference;
|
return sourceReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceReference getTargetReference() {
|
|
||||||
return targetReference;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeMirror getResultType() {
|
public TypeMirror getResultType() {
|
||||||
return resultType;
|
return resultType;
|
||||||
}
|
}
|
||||||
@ -298,6 +294,33 @@ public class Mapping {
|
|||||||
return reverse;
|
return reverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a copy of this mapping, which is adapted to the given method
|
||||||
|
*
|
||||||
|
* @param the method to adapt the copy to
|
||||||
|
*/
|
||||||
|
public Mapping copyForInheritanceTo(SourceMethod method) {
|
||||||
|
Mapping mapping = new Mapping(
|
||||||
|
sourceName,
|
||||||
|
constant,
|
||||||
|
javaExpression,
|
||||||
|
targetName,
|
||||||
|
dateFormat,
|
||||||
|
qualifiers,
|
||||||
|
isIgnored,
|
||||||
|
mirror,
|
||||||
|
sourceAnnotationValue,
|
||||||
|
targetAnnotationValue,
|
||||||
|
resultType
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( sourceReference != null ) {
|
||||||
|
mapping.sourceReference = sourceReference.copyForInheritanceTo( method );
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Mapping {" +
|
return "Mapping {" +
|
||||||
|
@ -0,0 +1,137 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.source;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.model.common.TypeFactory;
|
||||||
|
import org.mapstruct.ap.util.FormattingMessager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates all options specifiable on a mapping method
|
||||||
|
*
|
||||||
|
* @author Andreas Gudian
|
||||||
|
*/
|
||||||
|
public class MappingOptions {
|
||||||
|
private Map<String, List<Mapping>> mappings;
|
||||||
|
private IterableMapping iterableMapping;
|
||||||
|
private MapMapping mapMapping;
|
||||||
|
private boolean fullyInitialized;
|
||||||
|
|
||||||
|
public MappingOptions(Map<String, List<Mapping>> mappings, IterableMapping iterableMapping, MapMapping mapMapping) {
|
||||||
|
this.mappings = mappings;
|
||||||
|
this.iterableMapping = iterableMapping;
|
||||||
|
this.mapMapping = mapMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the {@link Mapping}s configured for this method, keyed by target property name. Only for enum mapping
|
||||||
|
* methods a target will be mapped by several sources.
|
||||||
|
*/
|
||||||
|
public Map<String, List<Mapping>> getMappings() {
|
||||||
|
return mappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IterableMapping getIterableMapping() {
|
||||||
|
return iterableMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MapMapping getMapMapping() {
|
||||||
|
return mapMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMappings(Map<String, List<Mapping>> mappings) {
|
||||||
|
this.mappings = mappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIterableMapping(IterableMapping iterableMapping) {
|
||||||
|
this.iterableMapping = iterableMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMapMapping(MapMapping mapMapping) {
|
||||||
|
this.mapMapping = mapMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the {@code true}, iff the options have been fully initialized by applying all available inheritance
|
||||||
|
* options
|
||||||
|
*/
|
||||||
|
public boolean isFullyInitialized() {
|
||||||
|
return fullyInitialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void markAsFullyInitialized() {
|
||||||
|
this.fullyInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges in all the mapping options configured, giving the already defined options precedence.
|
||||||
|
*
|
||||||
|
* @param inherited the options to inherit, may be {@code null}
|
||||||
|
* @param isInverse if {@code true}, the specified options are from an inverse method
|
||||||
|
* @param method the source method
|
||||||
|
* @param messager the messager
|
||||||
|
* @param typeFactory the type factory
|
||||||
|
*/
|
||||||
|
public void applyInheritedOptions(MappingOptions inherited, boolean isInverse, SourceMethod method,
|
||||||
|
FormattingMessager messager, TypeFactory typeFactory) {
|
||||||
|
if ( null != inherited ) {
|
||||||
|
if ( getIterableMapping() == null ) {
|
||||||
|
if ( inherited.getIterableMapping() != null ) {
|
||||||
|
setIterableMapping( inherited.getIterableMapping() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( getMapMapping() == null ) {
|
||||||
|
if ( inherited.getMapMapping() != null ) {
|
||||||
|
setMapMapping( inherited.getMapMapping() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, List<Mapping>> newMappings = new HashMap<String, List<Mapping>>();
|
||||||
|
|
||||||
|
for ( List<Mapping> lmappings : inherited.getMappings().values() ) {
|
||||||
|
for ( Mapping mapping : lmappings ) {
|
||||||
|
if ( isInverse ) {
|
||||||
|
mapping = mapping.reverse( method, messager, typeFactory );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( mapping != null ) {
|
||||||
|
List<Mapping> mappingsOfProperty = newMappings.get( mapping.getTargetName() );
|
||||||
|
if ( mappingsOfProperty == null ) {
|
||||||
|
mappingsOfProperty = new ArrayList<Mapping>();
|
||||||
|
newMappings.put( mapping.getTargetName(), mappingsOfProperty );
|
||||||
|
}
|
||||||
|
|
||||||
|
mappingsOfProperty.add( mapping.copyForInheritanceTo( method ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now add all of its own mappings
|
||||||
|
newMappings.putAll( getMappings() );
|
||||||
|
setMappings( newMappings );
|
||||||
|
}
|
||||||
|
|
||||||
|
markAsFullyInitialized();
|
||||||
|
}
|
||||||
|
}
|
@ -19,11 +19,12 @@
|
|||||||
package org.mapstruct.ap.model.source;
|
package org.mapstruct.ap.model.source;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.mapstruct.ap.util.FormattingMessager;
|
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
import javax.lang.model.element.Modifier;
|
import javax.lang.model.element.Modifier;
|
||||||
import javax.lang.model.util.Types;
|
import javax.lang.model.util.Types;
|
||||||
@ -33,9 +34,12 @@ import org.mapstruct.ap.model.common.Parameter;
|
|||||||
import org.mapstruct.ap.model.common.Type;
|
import org.mapstruct.ap.model.common.Type;
|
||||||
import org.mapstruct.ap.model.common.TypeFactory;
|
import org.mapstruct.ap.model.common.TypeFactory;
|
||||||
import org.mapstruct.ap.model.source.SourceReference.PropertyEntry;
|
import org.mapstruct.ap.model.source.SourceReference.PropertyEntry;
|
||||||
|
import org.mapstruct.ap.util.FormattingMessager;
|
||||||
import org.mapstruct.ap.util.MapperConfig;
|
import org.mapstruct.ap.util.MapperConfig;
|
||||||
import org.mapstruct.ap.util.Strings;
|
import org.mapstruct.ap.util.Strings;
|
||||||
|
|
||||||
|
import static org.mapstruct.ap.util.Collections.first;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a mapping method with source and target type and the mappings between the properties of source and target
|
* Represents a mapping method with source and target type and the mappings between the properties of source and target
|
||||||
* type.
|
* type.
|
||||||
@ -50,7 +54,6 @@ public class SourceMethod implements Method {
|
|||||||
|
|
||||||
private final Types typeUtils;
|
private final Types typeUtils;
|
||||||
private final TypeFactory typeFactory;
|
private final TypeFactory typeFactory;
|
||||||
private final FormattingMessager messager;
|
|
||||||
|
|
||||||
private final Type declaringMapper;
|
private final Type declaringMapper;
|
||||||
private final ExecutableElement executable;
|
private final ExecutableElement executable;
|
||||||
@ -61,10 +64,14 @@ public class SourceMethod implements Method {
|
|||||||
private final Accessibility accessibility;
|
private final Accessibility accessibility;
|
||||||
private final List<Type> exceptionTypes;
|
private final List<Type> exceptionTypes;
|
||||||
private final MapperConfig config;
|
private final MapperConfig config;
|
||||||
|
private final MappingOptions mappingOptions;
|
||||||
|
private final List<SourceMethod> prototypeMethods;
|
||||||
|
|
||||||
private Map<String, List<Mapping>> mappings;
|
private List<Parameter> sourceParameters;
|
||||||
private IterableMapping iterableMapping;
|
|
||||||
private MapMapping mapMapping;
|
private List<String> parameterNames;
|
||||||
|
|
||||||
|
private List<SourceMethod> applicablePrototypeMethods;
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
@ -80,6 +87,7 @@ public class SourceMethod implements Method {
|
|||||||
private TypeFactory typeFactory = null;
|
private TypeFactory typeFactory = null;
|
||||||
private FormattingMessager messager = null;
|
private FormattingMessager messager = null;
|
||||||
private MapperConfig mapperConfig = null;
|
private MapperConfig mapperConfig = null;
|
||||||
|
private List<SourceMethod> prototypeMethods = Collections.emptyList();
|
||||||
|
|
||||||
public Builder() {
|
public Builder() {
|
||||||
}
|
}
|
||||||
@ -144,24 +152,27 @@ public class SourceMethod implements Method {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceMethod createSourceMethod() {
|
public Builder setPrototypeMethods(List<SourceMethod> prototypeMethods) {
|
||||||
|
this.prototypeMethods = prototypeMethods;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SourceMethod buildSourceMethod() {
|
||||||
SourceMethod sourceMethod = new SourceMethod(
|
SourceMethod sourceMethod = new SourceMethod(
|
||||||
declaringMapper,
|
declaringMapper,
|
||||||
executable,
|
executable,
|
||||||
parameters,
|
parameters,
|
||||||
returnType,
|
returnType,
|
||||||
exceptionTypes,
|
exceptionTypes,
|
||||||
mappings,
|
new MappingOptions( mappings, iterableMapping, mapMapping ),
|
||||||
iterableMapping,
|
|
||||||
mapMapping,
|
|
||||||
typeUtils,
|
typeUtils,
|
||||||
typeFactory,
|
typeFactory,
|
||||||
messager,
|
mapperConfig,
|
||||||
mapperConfig
|
prototypeMethods
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( mappings != null ) {
|
if ( mappings != null ) {
|
||||||
for ( Map.Entry<String, List<Mapping>> entry : sourceMethod.getMappings().entrySet() ) {
|
for ( Map.Entry<String, List<Mapping>> entry : mappings.entrySet() ) {
|
||||||
for ( Mapping mapping : entry.getValue() ) {
|
for ( Mapping mapping : entry.getValue() ) {
|
||||||
mapping.init( sourceMethod, messager, typeFactory );
|
mapping.init( sourceMethod, messager, typeFactory );
|
||||||
}
|
}
|
||||||
@ -173,26 +184,24 @@ public class SourceMethod implements Method {
|
|||||||
|
|
||||||
@SuppressWarnings( "checkstyle:parameternumber" )
|
@SuppressWarnings( "checkstyle:parameternumber" )
|
||||||
private SourceMethod( Type declaringMapper, ExecutableElement executable, List<Parameter> parameters,
|
private SourceMethod( Type declaringMapper, ExecutableElement executable, List<Parameter> parameters,
|
||||||
Type returnType, List<Type> exceptionTypes, Map<String, List<Mapping>> mappings,
|
Type returnType, List<Type> exceptionTypes, MappingOptions mappingOptions, Types typeUtils,
|
||||||
IterableMapping iterableMapping, MapMapping mapMapping, Types typeUtils,
|
TypeFactory typeFactory, MapperConfig config, List<SourceMethod> prototypeMethods) {
|
||||||
TypeFactory typeFactory, FormattingMessager messager, MapperConfig config) {
|
|
||||||
this.declaringMapper = declaringMapper;
|
this.declaringMapper = declaringMapper;
|
||||||
this.executable = executable;
|
this.executable = executable;
|
||||||
this.parameters = parameters;
|
this.parameters = parameters;
|
||||||
this.returnType = returnType;
|
this.returnType = returnType;
|
||||||
this.exceptionTypes = exceptionTypes;
|
this.exceptionTypes = exceptionTypes;
|
||||||
this.mappings = mappings;
|
|
||||||
this.iterableMapping = iterableMapping;
|
|
||||||
this.mapMapping = mapMapping;
|
|
||||||
this.accessibility = Accessibility.fromModifiers( executable.getModifiers() );
|
this.accessibility = Accessibility.fromModifiers( executable.getModifiers() );
|
||||||
|
|
||||||
|
this.mappingOptions = mappingOptions;
|
||||||
|
|
||||||
this.mappingTargetParameter = determineMappingTargetParameter( parameters );
|
this.mappingTargetParameter = determineMappingTargetParameter( parameters );
|
||||||
this.targetTypeParameter = determineTargetTypeParameter( parameters );
|
this.targetTypeParameter = determineTargetTypeParameter( parameters );
|
||||||
|
|
||||||
this.typeUtils = typeUtils;
|
this.typeUtils = typeUtils;
|
||||||
this.typeFactory = typeFactory;
|
this.typeFactory = typeFactory;
|
||||||
this.messager = messager;
|
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
this.prototypeMethods = prototypeMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Parameter determineMappingTargetParameter(Iterable<Parameter> parameters) {
|
private Parameter determineMappingTargetParameter(Iterable<Parameter> parameters) {
|
||||||
@ -249,24 +258,28 @@ public class SourceMethod implements Method {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<Parameter> getSourceParameters() {
|
public List<Parameter> getSourceParameters() {
|
||||||
List<Parameter> sourceParameters = new ArrayList<Parameter>();
|
if ( sourceParameters == null ) {
|
||||||
|
sourceParameters = new ArrayList<Parameter>();
|
||||||
|
|
||||||
for ( Parameter parameter : parameters ) {
|
for ( Parameter parameter : parameters ) {
|
||||||
if ( !parameter.isMappingTarget() && !parameter.isTargetType() ) {
|
if ( !parameter.isMappingTarget() && !parameter.isTargetType() ) {
|
||||||
sourceParameters.add( parameter );
|
sourceParameters.add( parameter );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return sourceParameters;
|
return sourceParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getParameterNames() {
|
public List<String> getParameterNames() {
|
||||||
List<String> parameterNames = new ArrayList<String>( parameters.size() );
|
if ( parameterNames == null ) {
|
||||||
|
parameterNames = new ArrayList<String>( parameters.size() );
|
||||||
|
|
||||||
for ( Parameter parameter : parameters ) {
|
for ( Parameter parameter : parameters ) {
|
||||||
parameterNames.add( parameter.getName() );
|
parameterNames.add( parameter.getName() );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return parameterNames;
|
return parameterNames;
|
||||||
}
|
}
|
||||||
@ -289,84 +302,31 @@ public class SourceMethod implements Method {
|
|||||||
return accessibility;
|
return accessibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the {@link Mapping}s configured for this method, keyed by target property name. Only for enum mapping
|
|
||||||
* methods a target will be mapped by several sources.
|
|
||||||
*/
|
|
||||||
public Map<String, List<Mapping>> getMappings() {
|
|
||||||
return mappings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mapping getSingleMappingByTargetPropertyName(String targetPropertyName) {
|
public Mapping getSingleMappingByTargetPropertyName(String targetPropertyName) {
|
||||||
List<Mapping> all = mappings.get( targetPropertyName );
|
List<Mapping> all = mappingOptions.getMappings().get( targetPropertyName );
|
||||||
return all != null ? all.iterator().next() : null;
|
return all != null ? first( all ) : null;
|
||||||
}
|
|
||||||
|
|
||||||
public void setMappings(Map<String, List<Mapping>> mappings) {
|
|
||||||
this.mappings = mappings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IterableMapping getIterableMapping() {
|
|
||||||
return iterableMapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIterableMapping(IterableMapping iterableMapping) {
|
|
||||||
this.iterableMapping = iterableMapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MapMapping getMapMapping() {
|
|
||||||
return mapMapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMapMapping(MapMapping mapMapping) {
|
|
||||||
this.mapMapping = mapMapping;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean reverses(SourceMethod method) {
|
public boolean reverses(SourceMethod method) {
|
||||||
return getSourceParameters().size() == 1 && method.getSourceParameters().size() == 1
|
return getSourceParameters().size() == 1 && method.getSourceParameters().size() == 1
|
||||||
&& equals( getSourceParameters().iterator().next().getType(), method.getResultType() )
|
&& equals( first( getSourceParameters() ).getType(), method.getResultType() )
|
||||||
&& equals( getResultType(), method.getSourceParameters().iterator().next().getType() );
|
&& equals( getResultType(), first( method.getSourceParameters() ).getType() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isSame(SourceMethod method) {
|
public boolean isSame(SourceMethod method) {
|
||||||
return getSourceParameters().size() == 1 && method.getSourceParameters().size() == 1
|
return getSourceParameters().size() == 1 && method.getSourceParameters().size() == 1
|
||||||
&& equals( getSourceParameters().iterator().next().getType(),
|
&& equals( first( getSourceParameters() ).getType(),
|
||||||
method.getSourceParameters().iterator().next().getType())
|
first( method.getSourceParameters() ).getType() )
|
||||||
&& equals( getResultType(), method.getResultType() );
|
&& equals( getResultType(), method.getResultType() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSimilar(SourceMethod method) {
|
public boolean canInheritFrom(SourceMethod method) {
|
||||||
Map<Type, Integer> test = new HashMap<Type, Integer>();
|
return isMapMapping() == method.isMapMapping()
|
||||||
|
&& isIterableMapping() == method.isIterableMapping()
|
||||||
// check how many times a type occurs
|
&& isEnumMapping() == method.isEnumMapping()
|
||||||
for (Parameter sourceParam : method.getSourceParameters() ) {
|
&& getResultType().isAssignableTo( method.getResultType() )
|
||||||
Type sourceType = sourceParam.getType();
|
&& allParametersAreAssignable( getSourceParameters(), method.getSourceParameters() );
|
||||||
if ( !test.containsKey( sourceType ) ) {
|
|
||||||
test.put( sourceType, 0 );
|
|
||||||
}
|
|
||||||
increase( sourceType, test );
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if this method also contains the same time each parameter type.
|
|
||||||
for (Parameter sourceParam : getSourceParameters() ) {
|
|
||||||
Type sourceType = sourceParam.getType();
|
|
||||||
if ( !test.containsKey( sourceType ) ) {
|
|
||||||
// method contains a different parameter type than this
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
decrease( sourceType, test );
|
|
||||||
}
|
|
||||||
|
|
||||||
// now, if they match they should have the same source parameter types each
|
|
||||||
for ( Integer count : test.values() ) {
|
|
||||||
if ( count != 0 ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// finally check the return type.
|
|
||||||
return equals( getResultType(), method.getResultType() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -380,17 +340,17 @@ public class SourceMethod implements Method {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isIterableMapping() {
|
public boolean isIterableMapping() {
|
||||||
return getSourceParameters().size() == 1 && getSourceParameters().iterator().next().getType().isIterableType()
|
return getSourceParameters().size() == 1 && first( getSourceParameters() ).getType().isIterableType()
|
||||||
&& getResultType().isIterableType();
|
&& getResultType().isIterableType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMapMapping() {
|
public boolean isMapMapping() {
|
||||||
return getSourceParameters().size() == 1 && getSourceParameters().iterator().next().getType().isMapType()
|
return getSourceParameters().size() == 1 && first( getSourceParameters() ).getType().isMapType()
|
||||||
&& getResultType().isMapType();
|
&& getResultType().isMapType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnumMapping() {
|
public boolean isEnumMapping() {
|
||||||
return getSourceParameters().size() == 1 && getSourceParameters().iterator().next().getType().isEnumType()
|
return getSourceParameters().size() == 1 && first( getSourceParameters() ).getType().isEnumType()
|
||||||
&& getResultType().isEnumType();
|
&& getResultType().isEnumType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,7 +382,7 @@ public class SourceMethod implements Method {
|
|||||||
public List<Mapping> getMappingBySourcePropertyName(String sourcePropertyName) {
|
public List<Mapping> getMappingBySourcePropertyName(String sourcePropertyName) {
|
||||||
List<Mapping> mappingsOfSourceProperty = new ArrayList<Mapping>();
|
List<Mapping> mappingsOfSourceProperty = new ArrayList<Mapping>();
|
||||||
|
|
||||||
for ( List<Mapping> mappingOfProperty : mappings.values() ) {
|
for ( List<Mapping> mappingOfProperty : mappingOptions.getMappings().values() ) {
|
||||||
for ( Mapping mapping : mappingOfProperty ) {
|
for ( Mapping mapping : mappingOfProperty ) {
|
||||||
|
|
||||||
if ( isEnumMapping() ) {
|
if ( isEnumMapping() ) {
|
||||||
@ -435,7 +395,7 @@ public class SourceMethod implements Method {
|
|||||||
|
|
||||||
// there can only be a mapping if there's only one entry for a source property, so: param.property.
|
// there can only be a mapping if there's only one entry for a source property, so: param.property.
|
||||||
// There can be no mapping if there are more entries. So: param.property.property2
|
// There can be no mapping if there are more entries. So: param.property.property2
|
||||||
if ( sourceEntries.size() == 1 && sourcePropertyName.equals( sourceEntries.get( 0 ).getName() ) ) {
|
if ( sourceEntries.size() == 1 && sourcePropertyName.equals( first( sourceEntries ).getName() ) ) {
|
||||||
mappingsOfSourceProperty.add( mapping );
|
mappingsOfSourceProperty.add( mapping );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -455,6 +415,45 @@ public class SourceMethod implements Method {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<SourceMethod> getApplicablePrototypeMethods() {
|
||||||
|
if ( applicablePrototypeMethods == null ) {
|
||||||
|
applicablePrototypeMethods = new ArrayList<SourceMethod>();
|
||||||
|
|
||||||
|
for ( SourceMethod prototype : prototypeMethods ) {
|
||||||
|
if ( canInheritFrom( prototype ) ) {
|
||||||
|
applicablePrototypeMethods.add( prototype );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return applicablePrototypeMethods;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean allParametersAreAssignable(List<Parameter> fromParams, List<Parameter> toParams) {
|
||||||
|
if ( fromParams.size() == toParams.size() ) {
|
||||||
|
Set<Parameter> unaccountedToParams = new HashSet<Parameter>( toParams );
|
||||||
|
|
||||||
|
for ( Parameter fromParam : fromParams ) {
|
||||||
|
// each fromParam needs at least one match, and all toParam need to be accounted for at the end
|
||||||
|
boolean hasMatch = false;
|
||||||
|
for ( Parameter toParam : toParams ) {
|
||||||
|
if ( fromParam.getType().isAssignableTo( toParam.getType() ) ) {
|
||||||
|
unaccountedToParams.remove( toParam );
|
||||||
|
hasMatch = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !hasMatch ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unaccountedToParams.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether an implementation of this method must be generated or not.
|
* Whether an implementation of this method must be generated or not.
|
||||||
*
|
*
|
||||||
@ -494,57 +493,8 @@ public class SourceMethod implements Method {
|
|||||||
return exceptionTypes;
|
return exceptionTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public MappingOptions getMappingOptions() {
|
||||||
* Merges in all the mappings configured via the given inverse mapping method, giving the locally defined mappings
|
return mappingOptions;
|
||||||
* precedence.
|
|
||||||
* @param inverseMethod
|
|
||||||
* @param templateMethod
|
|
||||||
*/
|
|
||||||
public void mergeWithInverseMappings(SourceMethod inverseMethod, SourceMethod templateMethod) {
|
|
||||||
Map<String, List<Mapping>> newMappings = new HashMap<String, List<Mapping>>();
|
|
||||||
|
|
||||||
if ( inverseMethod != null && !inverseMethod.getMappings().isEmpty() ) {
|
|
||||||
for ( List<Mapping> lmappings : inverseMethod.getMappings().values() ) {
|
|
||||||
for ( Mapping inverseMapping : lmappings ) {
|
|
||||||
Mapping reversed = inverseMapping.reverse( this, messager, typeFactory );
|
|
||||||
if ( reversed != null ) {
|
|
||||||
List<Mapping> mappingsOfProperty = newMappings.get( reversed.getTargetName() );
|
|
||||||
if ( mappingsOfProperty == null ) {
|
|
||||||
mappingsOfProperty = new ArrayList<Mapping>();
|
|
||||||
newMappings.put( reversed.getTargetName(), mappingsOfProperty );
|
|
||||||
}
|
|
||||||
mappingsOfProperty.add( reversed );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( templateMethod != null && !templateMethod.getMappings().isEmpty() ) {
|
|
||||||
for ( List<Mapping> lmappings : templateMethod.getMappings().values() ) {
|
|
||||||
for ( Mapping templateMapping : lmappings ) {
|
|
||||||
if ( templateMapping != null ) {
|
|
||||||
List<Mapping> mappingsOfProperty = newMappings.get( templateMapping.getTargetName() );
|
|
||||||
if ( mappingsOfProperty == null ) {
|
|
||||||
mappingsOfProperty = new ArrayList<Mapping>();
|
|
||||||
newMappings.put( templateMapping.getTargetName(), mappingsOfProperty );
|
|
||||||
}
|
|
||||||
mappingsOfProperty.add( templateMapping );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( getMappings().isEmpty() ) {
|
|
||||||
// the mapping method is configuredByReverseMappingMethod, see SourceMethod#setMappings()
|
|
||||||
setMappings( newMappings );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// now add all of its own mappings
|
|
||||||
newMappings.putAll( getMappings() );
|
|
||||||
getMappings().clear();
|
|
||||||
// the mapping method is NOT configuredByReverseMappingMethod,
|
|
||||||
getMappings().putAll( newMappings );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -552,17 +502,6 @@ public class SourceMethod implements Method {
|
|||||||
return executable.getModifiers().contains( Modifier.STATIC );
|
return executable.getModifiers().contains( Modifier.STATIC );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void increase(Type key, Map<Type, Integer> test) {
|
|
||||||
Integer count = test.get( key );
|
|
||||||
count++;
|
|
||||||
test.put( key, count );
|
|
||||||
}
|
|
||||||
|
|
||||||
private void decrease(Type key, Map<Type, Integer> test) {
|
|
||||||
Integer count = test.get( key );
|
|
||||||
count--;
|
|
||||||
test.put( key, count );
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return the mapper config when this method needs to be implemented
|
* @return the mapper config when this method needs to be implemented
|
||||||
|
@ -22,16 +22,18 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.mapstruct.ap.util.FormattingMessager;
|
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
|
|
||||||
import org.mapstruct.ap.model.common.Parameter;
|
import org.mapstruct.ap.model.common.Parameter;
|
||||||
import org.mapstruct.ap.model.common.Type;
|
import org.mapstruct.ap.model.common.Type;
|
||||||
import org.mapstruct.ap.model.common.TypeFactory;
|
import org.mapstruct.ap.model.common.TypeFactory;
|
||||||
import org.mapstruct.ap.util.Message;
|
|
||||||
import org.mapstruct.ap.util.Executables;
|
import org.mapstruct.ap.util.Executables;
|
||||||
|
import org.mapstruct.ap.util.FormattingMessager;
|
||||||
|
import org.mapstruct.ap.util.Message;
|
||||||
import org.mapstruct.ap.util.Strings;
|
import org.mapstruct.ap.util.Strings;
|
||||||
|
|
||||||
|
import static org.mapstruct.ap.util.Collections.first;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class describes the source side of a property mapping.
|
* This class describes the source side of a property mapping.
|
||||||
* <p>
|
* <p>
|
||||||
@ -287,4 +289,25 @@ public class SourceReference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a copy of this reference, which is adapted to the given method
|
||||||
|
*
|
||||||
|
* @param the method to adapt the copy to
|
||||||
|
*/
|
||||||
|
public SourceReference copyForInheritanceTo(SourceMethod method) {
|
||||||
|
List<Parameter> replacementParamCandidates = new ArrayList<Parameter>();
|
||||||
|
for ( Parameter sourceParam : method.getSourceParameters() ) {
|
||||||
|
if ( sourceParam.getType().isAssignableTo( parameter.getType() ) ) {
|
||||||
|
replacementParamCandidates.add( sourceParam );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Parameter replacement = parameter;
|
||||||
|
if ( replacementParamCandidates.size() == 1 ) {
|
||||||
|
replacement = first( replacementParamCandidates );
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SourceReference( replacement, propertyEntries, isValid );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,8 @@ import org.mapstruct.ap.model.common.Parameter;
|
|||||||
import org.mapstruct.ap.model.common.Type;
|
import org.mapstruct.ap.model.common.Type;
|
||||||
import org.mapstruct.ap.model.source.Method;
|
import org.mapstruct.ap.model.source.Method;
|
||||||
|
|
||||||
|
import static org.mapstruct.ap.util.Collections.first;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects on inheritance distance, e.g. the amount of inheritance steps from the parameter type.
|
* Selects on inheritance distance, e.g. the amount of inheritance steps from the parameter type.
|
||||||
*
|
*
|
||||||
@ -50,7 +52,7 @@ public class InheritanceSelector implements MethodSelector {
|
|||||||
|
|
||||||
// find the methods with the minimum distance regarding getParameter getParameter type
|
// find the methods with the minimum distance regarding getParameter getParameter type
|
||||||
for ( T method : methods ) {
|
for ( T method : methods ) {
|
||||||
Parameter singleSourceParam = method.getSourceParameters().iterator().next();
|
Parameter singleSourceParam = first( method.getSourceParameters() );
|
||||||
|
|
||||||
int sourceTypeDistance = sourceType.distanceTo( singleSourceParam.getType() );
|
int sourceTypeDistance = sourceType.distanceTo( singleSourceParam.getType() );
|
||||||
bestMatchingSourceTypeDistance =
|
bestMatchingSourceTypeDistance =
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.prism;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prism for the enum {@link org.mapstruct.MappingInheritanceStrategy}
|
||||||
|
*
|
||||||
|
* @author Andreas Gudian
|
||||||
|
*/
|
||||||
|
public enum MappingInheritanceStrategyPrism {
|
||||||
|
EXPLICIT,
|
||||||
|
AUTO_INHERIT_FROM_CONFIG,
|
||||||
|
DEFAULT;
|
||||||
|
}
|
@ -24,7 +24,6 @@ import java.util.List;
|
|||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import org.mapstruct.ap.util.FormattingMessager;
|
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
import javax.lang.model.type.TypeKind;
|
import javax.lang.model.type.TypeKind;
|
||||||
@ -46,6 +45,7 @@ import org.mapstruct.ap.model.MappingBuilderContext;
|
|||||||
import org.mapstruct.ap.model.MappingMethod;
|
import org.mapstruct.ap.model.MappingMethod;
|
||||||
import org.mapstruct.ap.model.common.Type;
|
import org.mapstruct.ap.model.common.Type;
|
||||||
import org.mapstruct.ap.model.common.TypeFactory;
|
import org.mapstruct.ap.model.common.TypeFactory;
|
||||||
|
import org.mapstruct.ap.model.source.MappingOptions;
|
||||||
import org.mapstruct.ap.model.source.SourceMethod;
|
import org.mapstruct.ap.model.source.SourceMethod;
|
||||||
import org.mapstruct.ap.option.Options;
|
import org.mapstruct.ap.option.Options;
|
||||||
import org.mapstruct.ap.prism.DecoratedWithPrism;
|
import org.mapstruct.ap.prism.DecoratedWithPrism;
|
||||||
@ -53,11 +53,16 @@ import org.mapstruct.ap.prism.InheritConfigurationPrism;
|
|||||||
import org.mapstruct.ap.prism.InheritInverseConfigurationPrism;
|
import org.mapstruct.ap.prism.InheritInverseConfigurationPrism;
|
||||||
import org.mapstruct.ap.prism.MapperPrism;
|
import org.mapstruct.ap.prism.MapperPrism;
|
||||||
import org.mapstruct.ap.processor.creation.MappingResolverImpl;
|
import org.mapstruct.ap.processor.creation.MappingResolverImpl;
|
||||||
import org.mapstruct.ap.util.Message;
|
import org.mapstruct.ap.util.FormattingMessager;
|
||||||
import org.mapstruct.ap.util.MapperConfig;
|
import org.mapstruct.ap.util.MapperConfig;
|
||||||
|
import org.mapstruct.ap.util.Message;
|
||||||
import org.mapstruct.ap.util.Strings;
|
import org.mapstruct.ap.util.Strings;
|
||||||
import org.mapstruct.ap.version.VersionInformation;
|
import org.mapstruct.ap.version.VersionInformation;
|
||||||
|
|
||||||
|
import static org.mapstruct.ap.prism.MappingInheritanceStrategyPrism.AUTO_INHERIT_FROM_CONFIG;
|
||||||
|
import static org.mapstruct.ap.util.Collections.first;
|
||||||
|
import static org.mapstruct.ap.util.Collections.join;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link ModelElementProcessor} which creates a {@link Mapper} from the given
|
* A {@link ModelElementProcessor} which creates a {@link Mapper} from the given
|
||||||
* list of {@link SourceMethod}s.
|
* list of {@link SourceMethod}s.
|
||||||
@ -83,7 +88,8 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
this.versionInformation = context.getVersionInformation();
|
this.versionInformation = context.getVersionInformation();
|
||||||
this.typeFactory = context.getTypeFactory();
|
this.typeFactory = context.getTypeFactory();
|
||||||
|
|
||||||
List<MapperReference> mapperReferences = initReferencedMappers( mapperTypeElement );
|
MapperConfig mapperConfig = MapperConfig.getInstanceOn( mapperTypeElement );
|
||||||
|
List<MapperReference> mapperReferences = initReferencedMappers( mapperTypeElement, mapperConfig );
|
||||||
|
|
||||||
MappingBuilderContext ctx = new MappingBuilderContext(
|
MappingBuilderContext ctx = new MappingBuilderContext(
|
||||||
typeFactory,
|
typeFactory,
|
||||||
@ -104,7 +110,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
mapperReferences
|
mapperReferences
|
||||||
);
|
);
|
||||||
this.mappingContext = ctx;
|
this.mappingContext = ctx;
|
||||||
return getMapper( mapperTypeElement, sourceModel );
|
return getMapper( mapperTypeElement, mapperConfig, sourceModel );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -112,13 +118,11 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
return 1000;
|
return 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MapperReference> initReferencedMappers(TypeElement element) {
|
private List<MapperReference> initReferencedMappers(TypeElement element, MapperConfig mapperConfig) {
|
||||||
List<MapperReference> result = new LinkedList<MapperReference>();
|
List<MapperReference> result = new LinkedList<MapperReference>();
|
||||||
List<String> variableNames = new LinkedList<String>();
|
List<String> variableNames = new LinkedList<String>();
|
||||||
|
|
||||||
MapperConfig mapperPrism = MapperConfig.getInstanceOn( element );
|
for ( TypeMirror usedMapper : mapperConfig.uses() ) {
|
||||||
|
|
||||||
for ( TypeMirror usedMapper : mapperPrism.uses() ) {
|
|
||||||
DefaultMapperReference mapperReference = DefaultMapperReference.getInstance(
|
DefaultMapperReference mapperReference = DefaultMapperReference.getInstance(
|
||||||
typeFactory.getType( usedMapper ),
|
typeFactory.getType( usedMapper ),
|
||||||
MapperPrism.getInstanceOn( typeUtils.asElement( usedMapper ) ) != null,
|
MapperPrism.getInstanceOn( typeUtils.asElement( usedMapper ) ) != null,
|
||||||
@ -133,9 +137,9 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mapper getMapper(TypeElement element, List<SourceMethod> methods) {
|
private Mapper getMapper(TypeElement element, MapperConfig mapperConfig, List<SourceMethod> methods) {
|
||||||
List<MapperReference> mapperReferences = mappingContext.getMapperReferences();
|
List<MapperReference> mapperReferences = mappingContext.getMapperReferences();
|
||||||
List<MappingMethod> mappingMethods = getMappingMethods( methods );
|
List<MappingMethod> mappingMethods = getMappingMethods( mapperConfig, methods );
|
||||||
mappingMethods.addAll( mappingContext.getUsedVirtualMappings() );
|
mappingMethods.addAll( mappingContext.getUsedVirtualMappings() );
|
||||||
mappingMethods.addAll( mappingContext.getMappingsToGenerate() );
|
mappingMethods.addAll( mappingContext.getMappingsToGenerate() );
|
||||||
|
|
||||||
@ -194,7 +198,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
else if ( constructor.getParameters().size() == 1 ) {
|
else if ( constructor.getParameters().size() == 1 ) {
|
||||||
if ( typeUtils.isAssignable(
|
if ( typeUtils.isAssignable(
|
||||||
element.asType(),
|
element.asType(),
|
||||||
constructor.getParameters().iterator().next().asType()
|
first( constructor.getParameters() ).asType()
|
||||||
) ) {
|
) ) {
|
||||||
hasDelegateConstructor = true;
|
hasDelegateConstructor = true;
|
||||||
}
|
}
|
||||||
@ -233,7 +237,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
return extraImports;
|
return extraImports;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MappingMethod> getMappingMethods(List<SourceMethod> methods) {
|
private List<MappingMethod> getMappingMethods(MapperConfig mapperConfig, List<SourceMethod> methods) {
|
||||||
List<MappingMethod> mappingMethods = new ArrayList<MappingMethod>();
|
List<MappingMethod> mappingMethods = new ArrayList<MappingMethod>();
|
||||||
|
|
||||||
for ( SourceMethod method : methods ) {
|
for ( SourceMethod method : methods ) {
|
||||||
@ -241,29 +245,23 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceMethod inverseMappingMethod = getInverseMappingMethod( methods, method );
|
mergeInheritedOptions( method, mapperConfig, methods, new ArrayList<SourceMethod>() );
|
||||||
SourceMethod templateMappingMethod = getTemplateMappingMethod( methods, method );
|
|
||||||
|
MappingOptions mappingOptions = method.getMappingOptions();
|
||||||
|
|
||||||
boolean hasFactoryMethod = false;
|
boolean hasFactoryMethod = false;
|
||||||
|
|
||||||
if ( method.isIterableMapping() ) {
|
if ( method.isIterableMapping() ) {
|
||||||
|
|
||||||
IterableMappingMethod.Builder builder = new IterableMappingMethod.Builder();
|
IterableMappingMethod.Builder builder = new IterableMappingMethod.Builder();
|
||||||
if ( method.getIterableMapping() == null ) {
|
|
||||||
if ( inverseMappingMethod != null && inverseMappingMethod.getIterableMapping() != null ) {
|
|
||||||
method.setIterableMapping( inverseMappingMethod.getIterableMapping() );
|
|
||||||
}
|
|
||||||
else if ( templateMappingMethod != null && templateMappingMethod.getIterableMapping() != null ) {
|
|
||||||
method.setIterableMapping( templateMappingMethod.getIterableMapping() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String dateFormat = null;
|
String dateFormat = null;
|
||||||
List<TypeMirror> qualifiers = null;
|
List<TypeMirror> qualifiers = null;
|
||||||
TypeMirror qualifyingElementTargetType = null;
|
TypeMirror qualifyingElementTargetType = null;
|
||||||
if ( method.getIterableMapping() != null ) {
|
if ( mappingOptions.getIterableMapping() != null ) {
|
||||||
dateFormat = method.getIterableMapping().getDateFormat();
|
dateFormat = mappingOptions.getIterableMapping().getDateFormat();
|
||||||
qualifiers = method.getIterableMapping().getQualifiers();
|
qualifiers = mappingOptions.getIterableMapping().getQualifiers();
|
||||||
qualifyingElementTargetType = method.getIterableMapping().getQualifyingElementTargetType();
|
qualifyingElementTargetType = mappingOptions.getIterableMapping().getQualifyingElementTargetType();
|
||||||
}
|
}
|
||||||
|
|
||||||
IterableMappingMethod iterableMappingMethod = builder
|
IterableMappingMethod iterableMappingMethod = builder
|
||||||
@ -281,27 +279,19 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
|
|
||||||
MapMappingMethod.Builder builder = new MapMappingMethod.Builder();
|
MapMappingMethod.Builder builder = new MapMappingMethod.Builder();
|
||||||
|
|
||||||
if ( method.getMapMapping() == null ) {
|
|
||||||
if ( inverseMappingMethod != null && inverseMappingMethod.getMapMapping() != null ) {
|
|
||||||
method.setMapMapping( inverseMappingMethod.getMapMapping() );
|
|
||||||
}
|
|
||||||
else if ( templateMappingMethod != null && templateMappingMethod.getMapMapping() != null ) {
|
|
||||||
method.setMapMapping( templateMappingMethod.getMapMapping() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String keyDateFormat = null;
|
String keyDateFormat = null;
|
||||||
String valueDateFormat = null;
|
String valueDateFormat = null;
|
||||||
List<TypeMirror> keyQualifiers = null;
|
List<TypeMirror> keyQualifiers = null;
|
||||||
List<TypeMirror> valueQualifiers = null;
|
List<TypeMirror> valueQualifiers = null;
|
||||||
TypeMirror keyQualifyingTargetType = null;
|
TypeMirror keyQualifyingTargetType = null;
|
||||||
TypeMirror valueQualifyingTargetType = null;
|
TypeMirror valueQualifyingTargetType = null;
|
||||||
if ( method.getMapMapping() != null ) {
|
if ( mappingOptions.getMapMapping() != null ) {
|
||||||
keyDateFormat = method.getMapMapping().getKeyFormat();
|
keyDateFormat = mappingOptions.getMapMapping().getKeyFormat();
|
||||||
valueDateFormat = method.getMapMapping().getValueFormat();
|
valueDateFormat = mappingOptions.getMapMapping().getValueFormat();
|
||||||
keyQualifiers = method.getMapMapping().getKeyQualifiers();
|
keyQualifiers = mappingOptions.getMapMapping().getKeyQualifiers();
|
||||||
valueQualifiers = method.getMapMapping().getValueQualifiers();
|
valueQualifiers = mappingOptions.getMapMapping().getValueQualifiers();
|
||||||
keyQualifyingTargetType = method.getMapMapping().getKeyQualifyingTargetType();
|
keyQualifyingTargetType = mappingOptions.getMapMapping().getKeyQualifyingTargetType();
|
||||||
valueQualifyingTargetType = method.getMapMapping().getValueQualifyingTargetType();
|
valueQualifyingTargetType = mappingOptions.getMapMapping().getValueQualifyingTargetType();
|
||||||
}
|
}
|
||||||
|
|
||||||
MapMappingMethod mapMappingMethod = builder
|
MapMappingMethod mapMappingMethod = builder
|
||||||
@ -321,7 +311,6 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
else if ( method.isEnumMapping() ) {
|
else if ( method.isEnumMapping() ) {
|
||||||
|
|
||||||
EnumMappingMethod.Builder builder = new EnumMappingMethod.Builder();
|
EnumMappingMethod.Builder builder = new EnumMappingMethod.Builder();
|
||||||
method.mergeWithInverseMappings( inverseMappingMethod, templateMappingMethod );
|
|
||||||
MappingMethod enumMappingMethod = builder
|
MappingMethod enumMappingMethod = builder
|
||||||
.mappingContext( mappingContext )
|
.mappingContext( mappingContext )
|
||||||
.souceMethod( method )
|
.souceMethod( method )
|
||||||
@ -334,7 +323,6 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
else {
|
else {
|
||||||
|
|
||||||
BeanMappingMethod.Builder builder = new BeanMappingMethod.Builder();
|
BeanMappingMethod.Builder builder = new BeanMappingMethod.Builder();
|
||||||
method.mergeWithInverseMappings( inverseMappingMethod, templateMappingMethod );
|
|
||||||
BeanMappingMethod beanMappingMethod = builder
|
BeanMappingMethod beanMappingMethod = builder
|
||||||
.mappingContext( mappingContext )
|
.mappingContext( mappingContext )
|
||||||
.souceMethod( method )
|
.souceMethod( method )
|
||||||
@ -356,6 +344,61 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
return mappingMethods;
|
return mappingMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void mergeInheritedOptions(SourceMethod method, MapperConfig mapperConfig,
|
||||||
|
List<SourceMethod> availableMethods, List<SourceMethod> initializingMethods) {
|
||||||
|
if ( initializingMethods.contains( method ) ) {
|
||||||
|
// cycle detected
|
||||||
|
|
||||||
|
initializingMethods.add( method );
|
||||||
|
|
||||||
|
messager.printMessage(
|
||||||
|
method.getExecutable(),
|
||||||
|
Message.INHERITCONFIGURATION_CYCLE,
|
||||||
|
Strings.join( initializingMethods, " -> " ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
initializingMethods.add( method );
|
||||||
|
|
||||||
|
MappingOptions mappingOptions = method.getMappingOptions();
|
||||||
|
List<SourceMethod> applicablePrototypeMethods = method.getApplicablePrototypeMethods();
|
||||||
|
|
||||||
|
MappingOptions inverseMappingOptions =
|
||||||
|
getInverseMappingOptions( availableMethods, method, initializingMethods, mapperConfig );
|
||||||
|
|
||||||
|
MappingOptions templateMappingOptions =
|
||||||
|
getTemplateMappingOptions(
|
||||||
|
join( availableMethods, applicablePrototypeMethods ),
|
||||||
|
method,
|
||||||
|
initializingMethods,
|
||||||
|
mapperConfig );
|
||||||
|
|
||||||
|
if ( templateMappingOptions != null ) {
|
||||||
|
mappingOptions.applyInheritedOptions( templateMappingOptions, false, method, messager, typeFactory );
|
||||||
|
}
|
||||||
|
else if ( inverseMappingOptions != null ) {
|
||||||
|
mappingOptions.applyInheritedOptions( inverseMappingOptions, true, method, messager, typeFactory );
|
||||||
|
}
|
||||||
|
else if ( mapperConfig.getMappingInheritanceStrategy() == AUTO_INHERIT_FROM_CONFIG ) {
|
||||||
|
if ( applicablePrototypeMethods.size() == 1 ) {
|
||||||
|
mappingOptions.applyInheritedOptions(
|
||||||
|
first( applicablePrototypeMethods ).getMappingOptions(),
|
||||||
|
false,
|
||||||
|
method,
|
||||||
|
messager,
|
||||||
|
typeFactory );
|
||||||
|
}
|
||||||
|
else if ( applicablePrototypeMethods.size() > 1 ) {
|
||||||
|
messager.printMessage(
|
||||||
|
method.getExecutable(),
|
||||||
|
Message.INHERITCONFIGURATION_MULTIPLE_PROTOTYPE_METHODS_MATCH,
|
||||||
|
Strings.join( applicablePrototypeMethods, ", " ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mappingOptions.markAsFullyInitialized();
|
||||||
|
}
|
||||||
|
|
||||||
private void reportErrorIfNoImplementationTypeIsRegisteredForInterfaceReturnType(SourceMethod method) {
|
private void reportErrorIfNoImplementationTypeIsRegisteredForInterfaceReturnType(SourceMethod method) {
|
||||||
if ( method.getReturnType().getTypeMirror().getKind() != TypeKind.VOID &&
|
if ( method.getReturnType().getTypeMirror().getKind() != TypeKind.VOID &&
|
||||||
method.getReturnType().isInterface() &&
|
method.getReturnType().isInterface() &&
|
||||||
@ -365,12 +408,13 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the configuring inverse method in case the given method is annotated with
|
* Returns the configuring inverse method's options in case the given method is annotated with
|
||||||
* {@code @InheritInverseConfiguration} and exactly one such configuring method can unambiguously be selected (as
|
* {@code @InheritInverseConfiguration} and exactly one such configuring method can unambiguously be selected (as
|
||||||
* per the source/target type and optionally the name given via {@code @InheritInverseConfiguration}).
|
* per the source/target type and optionally the name given via {@code @InheritInverseConfiguration}).
|
||||||
*/
|
*/
|
||||||
private SourceMethod getInverseMappingMethod(List<SourceMethod> rawMethods, SourceMethod method) {
|
private MappingOptions getInverseMappingOptions(List<SourceMethod> rawMethods, SourceMethod method,
|
||||||
SourceMethod result = null;
|
List<SourceMethod> initializingMethods, MapperConfig mapperConfig) {
|
||||||
|
SourceMethod resultMethod = null;
|
||||||
InheritInverseConfigurationPrism reversePrism = InheritInverseConfigurationPrism.getInstanceOn(
|
InheritInverseConfigurationPrism reversePrism = InheritInverseConfigurationPrism.getInstanceOn(
|
||||||
method.getExecutable()
|
method.getExecutable()
|
||||||
);
|
);
|
||||||
@ -389,10 +433,10 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
if ( candidates.size() == 1 ) {
|
if ( candidates.size() == 1 ) {
|
||||||
// no ambiguity: if no configuredBy is specified, or configuredBy specified and match
|
// no ambiguity: if no configuredBy is specified, or configuredBy specified and match
|
||||||
if ( name.isEmpty() ) {
|
if ( name.isEmpty() ) {
|
||||||
result = candidates.get( 0 );
|
resultMethod = candidates.get( 0 );
|
||||||
}
|
}
|
||||||
else if ( candidates.get( 0 ).getName().equals( name ) ) {
|
else if ( candidates.get( 0 ).getName().equals( name ) ) {
|
||||||
result = candidates.get( 0 );
|
resultMethod = candidates.get( 0 );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
reportErrorWhenNonMatchingName( candidates.get( 0 ), method, reversePrism );
|
reportErrorWhenNonMatchingName( candidates.get( 0 ), method, reversePrism );
|
||||||
@ -409,35 +453,46 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( nameFilteredcandidates.size() == 1 ) {
|
if ( nameFilteredcandidates.size() == 1 ) {
|
||||||
result = nameFilteredcandidates.get( 0 );
|
resultMethod = nameFilteredcandidates.get( 0 );
|
||||||
}
|
}
|
||||||
else if ( nameFilteredcandidates.size() > 1 ) {
|
else if ( nameFilteredcandidates.size() > 1 ) {
|
||||||
reportErrorWhenSeveralNamesMatch( nameFilteredcandidates, method, reversePrism );
|
reportErrorWhenSeveralNamesMatch( nameFilteredcandidates, method, reversePrism );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( result == null ) {
|
if ( resultMethod == null ) {
|
||||||
reportErrorWhenAmbigousReverseMapping( candidates, method, reversePrism );
|
reportErrorWhenAmbigousReverseMapping( candidates, method, reversePrism );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( result != null ) {
|
|
||||||
reportErrorIfInverseMethodHasInheritAnnotation( result, method, reversePrism );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return extractInitializedOptions( resultMethod, rawMethods, mapperConfig, initializingMethods );
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
|
private MappingOptions extractInitializedOptions(SourceMethod resultMethod,
|
||||||
|
List<SourceMethod> rawMethods,
|
||||||
|
MapperConfig mapperConfig,
|
||||||
|
List<SourceMethod> initializingMethods) {
|
||||||
|
if ( resultMethod != null ) {
|
||||||
|
if ( !resultMethod.getMappingOptions().isFullyInitialized() ) {
|
||||||
|
mergeInheritedOptions( resultMethod, mapperConfig, rawMethods, initializingMethods );
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultMethod.getMappingOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the configuring forward method in case the given method is annotated with
|
* Returns the configuring forward method's options in case the given method is annotated with
|
||||||
* {@code @InheritConfiguration} and exactly one such configuring method can unambiguously be selected (as
|
* {@code @InheritConfiguration} and exactly one such configuring method can unambiguously be selected (as per the
|
||||||
* per the source/target type and optionally the name given via {@code @InheritConfiguration}).
|
* source/target type and optionally the name given via {@code @InheritConfiguration}). The method cannot be marked
|
||||||
*
|
* forward mapping itself (hence 'ohter'). And neither can it contain an {@code @InheritReverseConfiguration}
|
||||||
* The method cannot be marked forward mapping itself (hence 'ohter'). And neither can it contain an
|
|
||||||
* {@code @InheritReverseConfiguration}
|
|
||||||
*/
|
*/
|
||||||
private SourceMethod getTemplateMappingMethod(List<SourceMethod> rawMethods, SourceMethod method) {
|
private MappingOptions getTemplateMappingOptions(List<SourceMethod> rawMethods, SourceMethod method,
|
||||||
SourceMethod result = null;
|
List<SourceMethod> initializingMethods,
|
||||||
|
MapperConfig mapperConfig) {
|
||||||
|
SourceMethod resultMethod = null;
|
||||||
InheritConfigurationPrism forwardPrism = InheritConfigurationPrism.getInstanceOn(
|
InheritConfigurationPrism forwardPrism = InheritConfigurationPrism.getInstanceOn(
|
||||||
method.getExecutable()
|
method.getExecutable()
|
||||||
);
|
);
|
||||||
@ -445,11 +500,10 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
if (forwardPrism != null) {
|
if (forwardPrism != null) {
|
||||||
reportErrorWhenInheritForwardAlsoHasInheritReverseMapping( method );
|
reportErrorWhenInheritForwardAlsoHasInheritReverseMapping( method );
|
||||||
|
|
||||||
// method is configured as being reverse method, collect candidates
|
|
||||||
List<SourceMethod> candidates = new ArrayList<SourceMethod>();
|
List<SourceMethod> candidates = new ArrayList<SourceMethod>();
|
||||||
for ( SourceMethod oneMethod : rawMethods ) {
|
for ( SourceMethod oneMethod : rawMethods ) {
|
||||||
// method must be similar but not equal
|
// method must be similar but not equal
|
||||||
if ( oneMethod.isSimilar( method ) && !( oneMethod.equals( method ) ) ) {
|
if ( method.canInheritFrom( oneMethod ) && !( oneMethod.equals( method ) ) ) {
|
||||||
candidates.add( oneMethod );
|
candidates.add( oneMethod );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -457,14 +511,15 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
String name = forwardPrism.name();
|
String name = forwardPrism.name();
|
||||||
if ( candidates.size() == 1 ) {
|
if ( candidates.size() == 1 ) {
|
||||||
// no ambiguity: if no configuredBy is specified, or configuredBy specified and match
|
// no ambiguity: if no configuredBy is specified, or configuredBy specified and match
|
||||||
|
SourceMethod sourceMethod = first( candidates );
|
||||||
if ( name.isEmpty() ) {
|
if ( name.isEmpty() ) {
|
||||||
result = candidates.get( 0 );
|
resultMethod = sourceMethod;
|
||||||
}
|
}
|
||||||
else if ( candidates.get( 0 ).getName().equals( name ) ) {
|
else if ( sourceMethod.getName().equals( name ) ) {
|
||||||
result = candidates.get( 0 );
|
resultMethod = sourceMethod;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
reportErrorWhenNonMatchingName( candidates.get( 0 ), method, forwardPrism );
|
reportErrorWhenNonMatchingName( sourceMethod, method, forwardPrism );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( candidates.size() > 1 ) {
|
else if ( candidates.size() > 1 ) {
|
||||||
@ -478,23 +533,19 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( nameFilteredcandidates.size() == 1 ) {
|
if ( nameFilteredcandidates.size() == 1 ) {
|
||||||
result = nameFilteredcandidates.get( 0 );
|
resultMethod = first( nameFilteredcandidates );
|
||||||
}
|
}
|
||||||
else if ( nameFilteredcandidates.size() > 1 ) {
|
else if ( nameFilteredcandidates.size() > 1 ) {
|
||||||
reportErrorWhenSeveralNamesMatch( nameFilteredcandidates, method, forwardPrism );
|
reportErrorWhenSeveralNamesMatch( nameFilteredcandidates, method, forwardPrism );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( result == null ) {
|
if ( resultMethod == null ) {
|
||||||
reportErrorWhenAmbigousMapping( candidates, method, forwardPrism );
|
reportErrorWhenAmbigousMapping( candidates, method, forwardPrism );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( result != null ) {
|
|
||||||
reportErrorIfMethodHasAnnotation( result, method, forwardPrism );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
return extractInitializedOptions( resultMethod, rawMethods, mapperConfig, initializingMethods );
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reportErrorWhenInheritForwardAlsoHasInheritReverseMapping(SourceMethod method) {
|
private void reportErrorWhenInheritForwardAlsoHasInheritReverseMapping(SourceMethod method) {
|
||||||
@ -507,34 +558,6 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reportErrorIfInverseMethodHasInheritAnnotation(SourceMethod candidate,
|
|
||||||
SourceMethod method,
|
|
||||||
InheritInverseConfigurationPrism reversePrism) {
|
|
||||||
|
|
||||||
InheritInverseConfigurationPrism candidatePrism = InheritInverseConfigurationPrism.getInstanceOn(
|
|
||||||
candidate.getExecutable()
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( candidatePrism != null ) {
|
|
||||||
messager.printMessage( method.getExecutable(),
|
|
||||||
reversePrism.mirror,
|
|
||||||
Message.INHERITINVERSECONFIGURATION_REFERENCE_HAS_INVERSE,
|
|
||||||
candidate.getName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
InheritConfigurationPrism candidateTemplatePrism = InheritConfigurationPrism.getInstanceOn(
|
|
||||||
candidate.getExecutable()
|
|
||||||
);
|
|
||||||
if ( candidateTemplatePrism != null ) {
|
|
||||||
messager.printMessage( method.getExecutable(),
|
|
||||||
reversePrism.mirror,
|
|
||||||
Message.INHERITINVERSECONFIGURATION_REFERENCE_HAS_FORWARD,
|
|
||||||
candidate.getName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void reportErrorWhenAmbigousReverseMapping(List<SourceMethod> candidates, SourceMethod method,
|
private void reportErrorWhenAmbigousReverseMapping(List<SourceMethod> candidates, SourceMethod method,
|
||||||
InheritInverseConfigurationPrism reversePrism) {
|
InheritInverseConfigurationPrism reversePrism) {
|
||||||
|
|
||||||
@ -570,7 +593,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
reversePrism.mirror,
|
reversePrism.mirror,
|
||||||
Message.INHERITINVERSECONFIGURATION_DUPLICATE_MATCHES,
|
Message.INHERITINVERSECONFIGURATION_DUPLICATE_MATCHES,
|
||||||
reversePrism.name(),
|
reversePrism.name(),
|
||||||
Strings.join( candidates, "(), " )
|
Strings.join( candidates, ", " )
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -586,35 +609,6 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reportErrorIfMethodHasAnnotation(SourceMethod candidate,
|
|
||||||
SourceMethod method,
|
|
||||||
InheritConfigurationPrism prism) {
|
|
||||||
|
|
||||||
InheritConfigurationPrism candidatePrism = InheritConfigurationPrism.getInstanceOn(
|
|
||||||
candidate.getExecutable()
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( candidatePrism != null ) {
|
|
||||||
messager.printMessage( method.getExecutable(),
|
|
||||||
prism.mirror,
|
|
||||||
Message.INHERITCONFIGURATION_REFERENCE_HAS_FORWARD,
|
|
||||||
candidate.getName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
InheritInverseConfigurationPrism candidateInversePrism = InheritInverseConfigurationPrism.getInstanceOn(
|
|
||||||
candidate.getExecutable()
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( candidateInversePrism != null ) {
|
|
||||||
messager.printMessage( method.getExecutable(),
|
|
||||||
prism.mirror,
|
|
||||||
Message.INHERITCONFIGURATION_REFERENCE_HAS_INVERSE,
|
|
||||||
candidate.getName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void reportErrorWhenAmbigousMapping(List<SourceMethod> candidates, SourceMethod method,
|
private void reportErrorWhenAmbigousMapping(List<SourceMethod> candidates, SourceMethod method,
|
||||||
InheritConfigurationPrism prism) {
|
InheritConfigurationPrism prism) {
|
||||||
|
|
||||||
|
@ -18,14 +18,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.processor;
|
package org.mapstruct.ap.processor;
|
||||||
|
|
||||||
import static org.mapstruct.ap.util.Executables.getAllEnclosedExecutableElements;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.mapstruct.ap.util.FormattingMessager;
|
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
import javax.lang.model.element.Modifier;
|
import javax.lang.model.element.Modifier;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
@ -48,8 +46,11 @@ import org.mapstruct.ap.prism.MapMappingPrism;
|
|||||||
import org.mapstruct.ap.prism.MappingPrism;
|
import org.mapstruct.ap.prism.MappingPrism;
|
||||||
import org.mapstruct.ap.prism.MappingsPrism;
|
import org.mapstruct.ap.prism.MappingsPrism;
|
||||||
import org.mapstruct.ap.util.AnnotationProcessingException;
|
import org.mapstruct.ap.util.AnnotationProcessingException;
|
||||||
import org.mapstruct.ap.util.Message;
|
import org.mapstruct.ap.util.FormattingMessager;
|
||||||
import org.mapstruct.ap.util.MapperConfig;
|
import org.mapstruct.ap.util.MapperConfig;
|
||||||
|
import org.mapstruct.ap.util.Message;
|
||||||
|
|
||||||
|
import static org.mapstruct.ap.util.Executables.getAllEnclosedExecutableElements;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link ModelElementProcessor} which retrieves a list of {@link SourceMethod}s
|
* A {@link ModelElementProcessor} which retrieves a list of {@link SourceMethod}s
|
||||||
@ -72,7 +73,19 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
|||||||
this.typeFactory = context.getTypeFactory();
|
this.typeFactory = context.getTypeFactory();
|
||||||
this.typeUtils = context.getTypeUtils();
|
this.typeUtils = context.getTypeUtils();
|
||||||
this.elementUtils = context.getElementUtils();
|
this.elementUtils = context.getElementUtils();
|
||||||
return retrieveMethods( mapperTypeElement, mapperTypeElement );
|
|
||||||
|
MapperConfig mapperConfig = MapperConfig.getInstanceOn( mapperTypeElement );
|
||||||
|
|
||||||
|
if ( !mapperConfig.isValid() ) {
|
||||||
|
throw new AnnotationProcessingException(
|
||||||
|
"Couldn't retrieve @Mapper annotation",
|
||||||
|
mapperTypeElement,
|
||||||
|
mapperConfig.getAnnotationMirror() );
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SourceMethod> prototypeMethods =
|
||||||
|
retrievePrototypeMethods( mapperConfig.getMapperConfigMirror(), mapperConfig );
|
||||||
|
return retrieveMethods( mapperTypeElement, mapperTypeElement, mapperConfig, prototypeMethods );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -80,19 +93,60 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<SourceMethod> retrievePrototypeMethods(TypeMirror typeMirror, MapperConfig mapperConfig) {
|
||||||
|
if ( typeMirror == null || typeMirror.getKind() == TypeKind.VOID ) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeElement typeElement = asTypeElement( typeMirror );
|
||||||
|
List<SourceMethod> methods = new ArrayList<SourceMethod>();
|
||||||
|
for ( ExecutableElement executable : getAllEnclosedExecutableElements( elementUtils, typeElement ) ) {
|
||||||
|
|
||||||
|
ExecutableType methodType = typeFactory.getMethodType( typeElement, executable );
|
||||||
|
List<Parameter> parameters = typeFactory.getParameters( methodType, executable );
|
||||||
|
boolean containsTargetTypeParameter = SourceMethod.containsTargetTypeParameter( parameters );
|
||||||
|
|
||||||
|
// prototype methods don't have prototypes themselves
|
||||||
|
List<SourceMethod> prototypeMethods = Collections.emptyList();
|
||||||
|
|
||||||
|
SourceMethod method =
|
||||||
|
getMethodRequiringImplementation(
|
||||||
|
methodType,
|
||||||
|
executable,
|
||||||
|
parameters,
|
||||||
|
containsTargetTypeParameter,
|
||||||
|
mapperConfig,
|
||||||
|
prototypeMethods );
|
||||||
|
|
||||||
|
if ( method != null ) {
|
||||||
|
methods.add( method );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return methods;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the mapping methods declared by the given mapper type.
|
* Retrieves the mapping methods declared by the given mapper type.
|
||||||
*
|
*
|
||||||
* @param usedMapper The type of interest (either the mapper to implement or a used mapper via @uses annotation)
|
* @param usedMapper The type of interest (either the mapper to implement or a used mapper via @uses annotation)
|
||||||
* @param mapperToImplement the top level type (mapper) that requires implementation
|
* @param mapperToImplement the top level type (mapper) that requires implementation
|
||||||
*
|
* @param mapperConfig the mapper config
|
||||||
|
* @param prototypeMethods prototype methods defined in mapper config type
|
||||||
* @return All mapping methods declared by the given type
|
* @return All mapping methods declared by the given type
|
||||||
*/
|
*/
|
||||||
private List<SourceMethod> retrieveMethods(TypeElement usedMapper, TypeElement mapperToImplement) {
|
private List<SourceMethod> retrieveMethods(TypeElement usedMapper, TypeElement mapperToImplement,
|
||||||
|
MapperConfig mapperConfig, List<SourceMethod> prototypeMethods) {
|
||||||
List<SourceMethod> methods = new ArrayList<SourceMethod>();
|
List<SourceMethod> methods = new ArrayList<SourceMethod>();
|
||||||
|
|
||||||
for ( ExecutableElement executable : getAllEnclosedExecutableElements( elementUtils, usedMapper ) ) {
|
for ( ExecutableElement executable : getAllEnclosedExecutableElements( elementUtils, usedMapper ) ) {
|
||||||
SourceMethod method = getMethod( usedMapper, executable, mapperToImplement );
|
SourceMethod method = getMethod(
|
||||||
|
usedMapper,
|
||||||
|
executable,
|
||||||
|
mapperToImplement,
|
||||||
|
mapperConfig,
|
||||||
|
prototypeMethods );
|
||||||
|
|
||||||
if ( method != null ) {
|
if ( method != null ) {
|
||||||
methods.add( method );
|
methods.add( method );
|
||||||
}
|
}
|
||||||
@ -100,15 +154,12 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
|||||||
|
|
||||||
//Add all methods of used mappers in order to reference them in the aggregated model
|
//Add all methods of used mappers in order to reference them in the aggregated model
|
||||||
if ( usedMapper.equals( mapperToImplement ) ) {
|
if ( usedMapper.equals( mapperToImplement ) ) {
|
||||||
MapperConfig mapperSettings = MapperConfig.getInstanceOn( usedMapper );
|
for ( TypeMirror mapper : mapperConfig.uses() ) {
|
||||||
if ( !mapperSettings.isValid() ) {
|
methods.addAll( retrieveMethods(
|
||||||
throw new AnnotationProcessingException(
|
asTypeElement( mapper ),
|
||||||
"Couldn't retrieve @Mapper annotation", usedMapper, mapperSettings.getAnnotationMirror()
|
mapperToImplement,
|
||||||
);
|
mapperConfig,
|
||||||
}
|
prototypeMethods ) );
|
||||||
|
|
||||||
for ( TypeMirror mapper : mapperSettings.uses() ) {
|
|
||||||
methods.addAll( retrieveMethods( asTypeElement( mapper ), mapperToImplement ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +172,9 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
|||||||
|
|
||||||
private SourceMethod getMethod(TypeElement usedMapper,
|
private SourceMethod getMethod(TypeElement usedMapper,
|
||||||
ExecutableElement method,
|
ExecutableElement method,
|
||||||
TypeElement mapperToImplement) {
|
TypeElement mapperToImplement,
|
||||||
|
MapperConfig mapperConfig,
|
||||||
|
List<SourceMethod> prototypeMethods) {
|
||||||
|
|
||||||
ExecutableType methodType = typeFactory.getMethodType( usedMapper, method );
|
ExecutableType methodType = typeFactory.getMethodType( usedMapper, method );
|
||||||
List<Parameter> parameters = typeFactory.getParameters( methodType, method );
|
List<Parameter> parameters = typeFactory.getParameters( methodType, method );
|
||||||
@ -134,7 +187,8 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
|||||||
method,
|
method,
|
||||||
parameters,
|
parameters,
|
||||||
containsTargetTypeParameter,
|
containsTargetTypeParameter,
|
||||||
mapperToImplement );
|
mapperConfig,
|
||||||
|
prototypeMethods );
|
||||||
}
|
}
|
||||||
//otherwise add reference to existing mapper method
|
//otherwise add reference to existing mapper method
|
||||||
else if ( isValidReferencedMethod( parameters ) || isValidFactoryMethod( parameters ) ) {
|
else if ( isValidReferencedMethod( parameters ) || isValidFactoryMethod( parameters ) ) {
|
||||||
@ -148,7 +202,8 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
|||||||
private SourceMethod getMethodRequiringImplementation(ExecutableType methodType, ExecutableElement method,
|
private SourceMethod getMethodRequiringImplementation(ExecutableType methodType, ExecutableElement method,
|
||||||
List<Parameter> parameters,
|
List<Parameter> parameters,
|
||||||
boolean containsTargetTypeParameter,
|
boolean containsTargetTypeParameter,
|
||||||
TypeElement mapperToImplement) {
|
MapperConfig mapperConfig,
|
||||||
|
List<SourceMethod> prototypeMethods) {
|
||||||
Type returnType = typeFactory.getReturnType( methodType );
|
Type returnType = typeFactory.getReturnType( methodType );
|
||||||
List<Type> exceptionTypes = typeFactory.getThrownTypes( methodType );
|
List<Type> exceptionTypes = typeFactory.getThrownTypes( methodType );
|
||||||
List<Parameter> sourceParameters = extractSourceParameters( parameters );
|
List<Parameter> sourceParameters = extractSourceParameters( parameters );
|
||||||
@ -181,8 +236,9 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
|||||||
.setTypeUtils( typeUtils )
|
.setTypeUtils( typeUtils )
|
||||||
.setMessager( messager )
|
.setMessager( messager )
|
||||||
.setTypeFactory( typeFactory )
|
.setTypeFactory( typeFactory )
|
||||||
.setMapperConfig( MapperConfig.getInstanceOn( mapperToImplement ) )
|
.setMapperConfig( mapperConfig )
|
||||||
.createSourceMethod();
|
.setPrototypeMethods( prototypeMethods )
|
||||||
|
.buildSourceMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SourceMethod getReferencedMethod(TypeElement usedMapper, ExecutableType methodType,
|
private SourceMethod getReferencedMethod(TypeElement usedMapper, ExecutableType methodType,
|
||||||
@ -205,7 +261,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
|||||||
.setExceptionTypes( exceptionTypes )
|
.setExceptionTypes( exceptionTypes )
|
||||||
.setTypeUtils( typeUtils )
|
.setTypeUtils( typeUtils )
|
||||||
.setTypeFactory( typeFactory )
|
.setTypeFactory( typeFactory )
|
||||||
.createSourceMethod();
|
.buildSourceMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValidReferencedMethod(List<Parameter> parameters) {
|
private boolean isValidReferencedMethod(List<Parameter> parameters) {
|
||||||
|
@ -72,4 +72,17 @@ public class Collections {
|
|||||||
|
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T> T first(Collection<T> collection) {
|
||||||
|
return collection.iterator().next();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> join(List<T> a, List<T> b) {
|
||||||
|
List<T> result = new ArrayList<T>( a.size() + b.size() );
|
||||||
|
|
||||||
|
result.addAll( a );
|
||||||
|
result.addAll( b );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,11 +33,10 @@ import org.mapstruct.ap.option.ReportingPolicy;
|
|||||||
import org.mapstruct.ap.prism.CollectionMappingStrategyPrism;
|
import org.mapstruct.ap.prism.CollectionMappingStrategyPrism;
|
||||||
import org.mapstruct.ap.prism.MapperConfigPrism;
|
import org.mapstruct.ap.prism.MapperConfigPrism;
|
||||||
import org.mapstruct.ap.prism.MapperPrism;
|
import org.mapstruct.ap.prism.MapperPrism;
|
||||||
|
import org.mapstruct.ap.prism.MappingInheritanceStrategyPrism;
|
||||||
import org.mapstruct.ap.prism.NullValueMappingPrism;
|
import org.mapstruct.ap.prism.NullValueMappingPrism;
|
||||||
import org.mapstruct.ap.prism.NullValueMappingStrategyPrism;
|
import org.mapstruct.ap.prism.NullValueMappingStrategyPrism;
|
||||||
|
|
||||||
import static org.mapstruct.ap.prism.CollectionMappingStrategyPrism.valueOf;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class decorating the {@link MapperPrism} with the 'default' configuration.
|
* Class decorating the {@link MapperPrism} with the 'default' configuration.
|
||||||
*
|
*
|
||||||
@ -58,10 +57,6 @@ public class MapperConfig {
|
|||||||
return new MapperConfig( MapperPrism.getInstanceOn( e ) );
|
return new MapperConfig( MapperPrism.getInstanceOn( e ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MapperConfig getInstance(AnnotationMirror mirror) {
|
|
||||||
return new MapperConfig( MapperPrism.getInstance( mirror ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
private MapperConfig(MapperPrism mapperPrism) {
|
private MapperConfig(MapperPrism mapperPrism) {
|
||||||
this.mapperPrism = mapperPrism;
|
this.mapperPrism = mapperPrism;
|
||||||
TypeMirror typeMirror = mapperPrism.config();
|
TypeMirror typeMirror = mapperPrism.config();
|
||||||
@ -100,7 +95,8 @@ public class MapperConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CollectionMappingStrategyPrism getCollectionMappingStrategy() {
|
public CollectionMappingStrategyPrism getCollectionMappingStrategy() {
|
||||||
CollectionMappingStrategyPrism mapperPolicy = valueOf( mapperPrism.collectionMappingStrategy() );
|
CollectionMappingStrategyPrism mapperPolicy =
|
||||||
|
CollectionMappingStrategyPrism.valueOf( mapperPrism.collectionMappingStrategy() );
|
||||||
|
|
||||||
if ( mapperPolicy != CollectionMappingStrategyPrism.DEFAULT ) {
|
if ( mapperPolicy != CollectionMappingStrategyPrism.DEFAULT ) {
|
||||||
// it is not the default mapper configuration, so return the mapper configured value
|
// it is not the default mapper configuration, so return the mapper configured value
|
||||||
@ -108,7 +104,8 @@ public class MapperConfig {
|
|||||||
}
|
}
|
||||||
else if ( mapperConfigPrism != null ) {
|
else if ( mapperConfigPrism != null ) {
|
||||||
// try the config mapper configuration
|
// try the config mapper configuration
|
||||||
CollectionMappingStrategyPrism configPolicy = valueOf( mapperConfigPrism.collectionMappingStrategy() );
|
CollectionMappingStrategyPrism configPolicy =
|
||||||
|
CollectionMappingStrategyPrism.valueOf( mapperConfigPrism.collectionMappingStrategy() );
|
||||||
if ( configPolicy != CollectionMappingStrategyPrism.DEFAULT ) {
|
if ( configPolicy != CollectionMappingStrategyPrism.DEFAULT ) {
|
||||||
// its not the default configuration, so return the mapper config configured value
|
// its not the default configuration, so return the mapper config configured value
|
||||||
return configPolicy;
|
return configPolicy;
|
||||||
@ -118,6 +115,24 @@ public class MapperConfig {
|
|||||||
return CollectionMappingStrategyPrism.ACCESSOR_ONLY;
|
return CollectionMappingStrategyPrism.ACCESSOR_ONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MappingInheritanceStrategyPrism getMappingInheritanceStrategy() {
|
||||||
|
MappingInheritanceStrategyPrism mapperPolicy =
|
||||||
|
MappingInheritanceStrategyPrism.valueOf( mapperPrism.mappingInheritanceStrategy() );
|
||||||
|
|
||||||
|
if ( mapperPolicy != MappingInheritanceStrategyPrism.DEFAULT ) {
|
||||||
|
return mapperPolicy;
|
||||||
|
}
|
||||||
|
else if ( mapperConfigPrism != null ) {
|
||||||
|
MappingInheritanceStrategyPrism configPolicy =
|
||||||
|
MappingInheritanceStrategyPrism.valueOf( mapperConfigPrism.mappingInheritanceStrategy() );
|
||||||
|
if ( configPolicy != MappingInheritanceStrategyPrism.DEFAULT ) {
|
||||||
|
return configPolicy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MappingInheritanceStrategyPrism.EXPLICIT;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isMapToDefault(NullValueMappingPrism mapNullToDefault) {
|
public boolean isMapToDefault(NullValueMappingPrism mapNullToDefault) {
|
||||||
|
|
||||||
// check on method level
|
// check on method level
|
||||||
@ -165,6 +180,10 @@ public class MapperConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TypeMirror getMapperConfigMirror() {
|
||||||
|
return mapperPrism.config();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
return mapperPrism.isValid;
|
return mapperPrism.isValid;
|
||||||
}
|
}
|
||||||
|
@ -86,18 +86,16 @@ public enum Message {
|
|||||||
RETRIEVAL_NON_ENUM_TO_ENUM( "Can't generate mapping method from non-enum type to enum type." ),
|
RETRIEVAL_NON_ENUM_TO_ENUM( "Can't generate mapping method from non-enum type to enum type." ),
|
||||||
|
|
||||||
INHERITCONFIGURATION_BOTH( "Method cannot be annotated with both a @InheritConfiguration and @InheritInverseConfiguration." ),
|
INHERITCONFIGURATION_BOTH( "Method cannot be annotated with both a @InheritConfiguration and @InheritInverseConfiguration." ),
|
||||||
INHERITINVERSECONFIGURATION_REFERENCE_HAS_INVERSE( "Resolved inverse mapping method %s() should not carry the @InheritInverseConfiguration annotation itself." ),
|
|
||||||
INHERITINVERSECONFIGURATION_REFERENCE_HAS_FORWARD( "Resolved inverse mapping method %s() should not carry the @InheritConfiguration annotation." ),
|
|
||||||
INHERITINVERSECONFIGURATION_DUPLICATES( "Several matching inverse methods exist: %s(). Specify a name explicitly." ),
|
INHERITINVERSECONFIGURATION_DUPLICATES( "Several matching inverse methods exist: %s(). Specify a name explicitly." ),
|
||||||
INHERITINVERSECONFIGURATION_INVALID_NAME( "None of the candidates %s() matches given name: \"%s\"." ),
|
INHERITINVERSECONFIGURATION_INVALID_NAME( "None of the candidates %s() matches given name: \"%s\"." ),
|
||||||
INHERITINVERSECONFIGURATION_DUPLICATE_MATCHES( "Given name \"%s\" matches several candidate methods: %s()." ),
|
INHERITINVERSECONFIGURATION_DUPLICATE_MATCHES( "Given name \"%s\" matches several candidate methods: %s()." ),
|
||||||
INHERITINVERSECONFIGURATION_NO_NAME_MATCH( "Given name \"%s\" does not match the only candidate. Did you mean: \"%s\"." ),
|
INHERITINVERSECONFIGURATION_NO_NAME_MATCH( "Given name \"%s\" does not match the only candidate. Did you mean: \"%s\"." ),
|
||||||
INHERITCONFIGURATION_REFERENCE_HAS_FORWARD( "Resolved mapping method %s() should not carry the @InheritConfiguration annotation itself." ),
|
|
||||||
INHERITCONFIGURATION_REFERENCE_HAS_INVERSE( "Resolved mapping method %s() should not carry the @InheritInverseConfiguration annotation." ),
|
|
||||||
INHERITCONFIGURATION_DUPLICATES( "Several matching methods exist: %s(). Specify a name explicitly." ),
|
INHERITCONFIGURATION_DUPLICATES( "Several matching methods exist: %s(). Specify a name explicitly." ),
|
||||||
INHERITCONFIGURATION_INVALIDNAME( "None of the candidates %s() matches given name: \"%s\"." ),
|
INHERITCONFIGURATION_INVALIDNAME( "None of the candidates %s() matches given name: \"%s\"." ),
|
||||||
INHERITCONFIGURATION_DUPLICATE_MATCHES( "Given name \"%s\" matches several candidate methods: %s()." ),
|
INHERITCONFIGURATION_DUPLICATE_MATCHES( "Given name \"%s\" matches several candidate methods: %s()." ),
|
||||||
INHERITCONFIGURATION_NO_NAME_MATCH( "Given name \"%s\" does not match the only candidate. Did you mean: \"%s\"." );
|
INHERITCONFIGURATION_NO_NAME_MATCH( "Given name \"%s\" does not match the only candidate. Did you mean: \"%s\"." ),
|
||||||
|
INHERITCONFIGURATION_MULTIPLE_PROTOTYPE_METHODS_MATCH( "More than one configuration prototype method is applicable. Use @InheritConfiguration to select one of them explicitly: %s." ),
|
||||||
|
INHERITCONFIGURATION_CYCLE( "Cycle detected while evaluating inherited configurations. Inheritance path: %s" );
|
||||||
// CHECKSTYLE:ON
|
// CHECKSTYLE:ON
|
||||||
|
|
||||||
private final String description;
|
private final String description;
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.inheritfromconfig;
|
||||||
|
|
||||||
|
import org.mapstruct.MapperConfig;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.MappingInheritanceStrategy;
|
||||||
|
import org.mapstruct.Mappings;
|
||||||
|
import org.mapstruct.ReportingPolicy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andreas Gudian
|
||||||
|
*/
|
||||||
|
@MapperConfig(
|
||||||
|
mappingInheritanceStrategy = MappingInheritanceStrategy.AUTO_INHERIT_FROM_CONFIG,
|
||||||
|
unmappedTargetPolicy = ReportingPolicy.ERROR
|
||||||
|
)
|
||||||
|
public interface AutoInheritedConfig {
|
||||||
|
@Mappings( {
|
||||||
|
@Mapping( target = "primaryKey", source = "id" ),
|
||||||
|
@Mapping( target = "auditTrail", ignore = true )
|
||||||
|
} )
|
||||||
|
BaseVehicleEntity baseDtoToEntity(BaseVehicleDto dto);
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.inheritfromconfig;
|
||||||
|
|
||||||
|
import org.mapstruct.MapperConfig;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.MappingInheritanceStrategy;
|
||||||
|
import org.mapstruct.Mappings;
|
||||||
|
import org.mapstruct.ReportingPolicy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andreas Gudian
|
||||||
|
*/
|
||||||
|
@MapperConfig(
|
||||||
|
mappingInheritanceStrategy = MappingInheritanceStrategy.AUTO_INHERIT_FROM_CONFIG,
|
||||||
|
unmappedTargetPolicy = ReportingPolicy.ERROR
|
||||||
|
)
|
||||||
|
public interface AutoInheritedDriverConfig {
|
||||||
|
@Mappings( {
|
||||||
|
@Mapping( target = "primaryKey", source = "dto.id" ),
|
||||||
|
@Mapping( target = "auditTrail", ignore = true ),
|
||||||
|
@Mapping( target = "driverName", source = "drv.name" )
|
||||||
|
} )
|
||||||
|
CarWithDriverEntity baseDtoToEntity(DriverDto drv, BaseVehicleDto dto);
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.inheritfromconfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andreas Gudian
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class BaseVehicleDto {
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.inheritfromconfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andreas Gudian
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class BaseVehicleEntity {
|
||||||
|
private long primaryKey;
|
||||||
|
private String auditTrail;
|
||||||
|
|
||||||
|
public long getPrimaryKey() {
|
||||||
|
return primaryKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrimaryKey(long primaryKey) {
|
||||||
|
this.primaryKey = primaryKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuditTrail() {
|
||||||
|
return auditTrail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuditTrail(String auditTrail) {
|
||||||
|
this.auditTrail = auditTrail;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.inheritfromconfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andreas Gudian
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CarDto extends BaseVehicleDto {
|
||||||
|
private String colour;
|
||||||
|
|
||||||
|
public String getColour() {
|
||||||
|
return colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColour(String colour) {
|
||||||
|
this.colour = colour;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.inheritfromconfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andreas Gudian
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CarEntity extends BaseVehicleEntity {
|
||||||
|
private String color;
|
||||||
|
|
||||||
|
public String getColor() {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(String color) {
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.template;
|
package org.mapstruct.ap.test.inheritfromconfig;
|
||||||
|
|
||||||
import org.mapstruct.InheritConfiguration;
|
import org.mapstruct.InheritConfiguration;
|
||||||
import org.mapstruct.InheritInverseConfiguration;
|
import org.mapstruct.InheritInverseConfiguration;
|
||||||
@ -27,28 +27,30 @@ import org.mapstruct.Mappings;
|
|||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sjaak Derksen
|
* @author Andreas Gudian
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
@Mapper
|
@Mapper(
|
||||||
public interface SourceTargetMapperErroneouslyAnnotated2 {
|
config = AutoInheritedConfig.class
|
||||||
|
)
|
||||||
|
public interface CarMapperWithAutoInheritance {
|
||||||
|
CarMapperWithAutoInheritance INSTANCE = Mappers.getMapper( CarMapperWithAutoInheritance.class );
|
||||||
|
|
||||||
SourceTargetMapperErroneouslyAnnotated2 INSTANCE =
|
@Mapping( target = "color", source = "colour" )
|
||||||
Mappers.getMapper( SourceTargetMapperErroneouslyAnnotated2.class );
|
CarEntity toCarEntity(CarDto carDto);
|
||||||
|
|
||||||
|
@InheritInverseConfiguration( name = "toCarEntity" )
|
||||||
|
CarDto toCarDto(CarEntity entity);
|
||||||
|
|
||||||
@Mappings( {
|
@Mappings( {
|
||||||
@Mapping(target = "stringPropY", source = "stringPropX"),
|
@Mapping( target = "color", source = "colour" ),
|
||||||
@Mapping(target = "integerPropY", source = "integerPropX"),
|
@Mapping( target = "auditTrail", constant = "fixed" )
|
||||||
@Mapping(target = "nestedResultProp", source = "nestedSourceProp.nested"),
|
|
||||||
@Mapping(target = "constantProp", constant = "constant"),
|
|
||||||
@Mapping(target = "expressionProp", expression = "java(\"expression\")")
|
|
||||||
} )
|
} )
|
||||||
Target forwardCreate(Source source);
|
CarEntity toCarEntityWithFixedAuditTrail(CarDto carDto);
|
||||||
|
|
||||||
@InheritInverseConfiguration(name = "forwardCreate")
|
@Mapping( target = "color", source = "colour" )
|
||||||
@Mapping(target = "nestedSourceProp", ignore = true)
|
void intoCarEntityOnItsOwn(CarDto carDto, @MappingTarget CarEntity entity);
|
||||||
Source forwardCreate(Target source);
|
|
||||||
|
|
||||||
@InheritConfiguration( name = "forwardCreate" )
|
|
||||||
void forwardUpdate(Target source, @MappingTarget Source target);
|
|
||||||
|
|
||||||
|
@InheritConfiguration( name = "toCarEntity" )
|
||||||
|
void intoCarEntity(CarDto carDto, @MappingTarget CarEntity entity);
|
||||||
}
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.inheritfromconfig;
|
||||||
|
|
||||||
|
import org.mapstruct.InheritConfiguration;
|
||||||
|
import org.mapstruct.InheritInverseConfiguration;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.MappingInheritanceStrategy;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andreas Gudian
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Mapper(
|
||||||
|
config = AutoInheritedConfig.class,
|
||||||
|
mappingInheritanceStrategy = MappingInheritanceStrategy.EXPLICIT
|
||||||
|
)
|
||||||
|
public interface CarMapperWithExplicitInheritance {
|
||||||
|
CarMapperWithExplicitInheritance INSTANCE = Mappers.getMapper( CarMapperWithExplicitInheritance.class );
|
||||||
|
|
||||||
|
@InheritConfiguration( name = "baseDtoToEntity" )
|
||||||
|
@Mapping( target = "color", source = "colour" )
|
||||||
|
CarEntity toCarEntity(CarDto carDto);
|
||||||
|
|
||||||
|
@InheritInverseConfiguration( name = "toCarEntity" )
|
||||||
|
CarDto toCarDto(CarEntity entity);
|
||||||
|
|
||||||
|
@InheritConfiguration( name = "toCarEntity" )
|
||||||
|
@Mapping( target = "auditTrail", constant = "fixed" )
|
||||||
|
CarEntity toCarEntityWithFixedAuditTrail(CarDto carDto);
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.inheritfromconfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andreas Gudian
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CarWithDriverEntity extends CarEntity {
|
||||||
|
private String driverName;
|
||||||
|
|
||||||
|
public String getDriverName() {
|
||||||
|
return driverName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDriverName(String driverName) {
|
||||||
|
this.driverName = driverName;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.inheritfromconfig;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andreas Gudian
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Mapper(
|
||||||
|
config = AutoInheritedDriverConfig.class
|
||||||
|
)
|
||||||
|
public interface CarWithDriverMapperWithAutoInheritance {
|
||||||
|
CarWithDriverMapperWithAutoInheritance INSTANCE = Mappers.getMapper( CarWithDriverMapperWithAutoInheritance.class );
|
||||||
|
|
||||||
|
@Mapping( target = "color", source = "carDto.colour" )
|
||||||
|
CarWithDriverEntity toCarWithDriverEntity(CarDto carDto, DriverDto driverDto);
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.inheritfromconfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andreas Gudian
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DriverDto {
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.inheritfromconfig;
|
||||||
|
|
||||||
|
import org.mapstruct.MapperConfig;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.MappingInheritanceStrategy;
|
||||||
|
import org.mapstruct.Mappings;
|
||||||
|
import org.mapstruct.ReportingPolicy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Leads to ambiguous prototype methods error.
|
||||||
|
*
|
||||||
|
* @author Andreas Gudian
|
||||||
|
*/
|
||||||
|
@MapperConfig(
|
||||||
|
mappingInheritanceStrategy = MappingInheritanceStrategy.AUTO_INHERIT_FROM_CONFIG,
|
||||||
|
unmappedTargetPolicy = ReportingPolicy.WARN
|
||||||
|
)
|
||||||
|
public interface Erroneous1Config {
|
||||||
|
@Mappings( {
|
||||||
|
@Mapping( target = "primaryKey", source = "id" ),
|
||||||
|
@Mapping( target = "auditTrail", ignore = true )
|
||||||
|
} )
|
||||||
|
BaseVehicleEntity baseDtoToEntity(BaseVehicleDto dto);
|
||||||
|
|
||||||
|
@Mapping( target = "primaryKey", ignore = true )
|
||||||
|
BaseVehicleEntity anythingToEntity(Object anyting);
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.inheritfromconfig;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.Mappings;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andreas Gudian
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Mapper(
|
||||||
|
config = Erroneous1Config.class
|
||||||
|
)
|
||||||
|
public interface Erroneous1Mapper {
|
||||||
|
Erroneous1Mapper INSTANCE = Mappers.getMapper( Erroneous1Mapper.class );
|
||||||
|
|
||||||
|
@Mapping( target = "color", source = "colour" )
|
||||||
|
CarEntity toCarEntity(CarDto carDto);
|
||||||
|
|
||||||
|
@Mappings( {
|
||||||
|
@Mapping( target = "color", source = "colour" ),
|
||||||
|
@Mapping( target = "auditTrail", constant = "fixed" )
|
||||||
|
} )
|
||||||
|
CarEntity toCarEntityWithFixedAuditTrail(CarDto carDto);
|
||||||
|
}
|
@ -16,34 +16,36 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.reverse;
|
package org.mapstruct.ap.test.inheritfromconfig;
|
||||||
|
|
||||||
import org.mapstruct.InheritConfiguration;
|
import org.mapstruct.InheritConfiguration;
|
||||||
import org.mapstruct.InheritInverseConfiguration;
|
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.Mapping;
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.MappingTarget;
|
||||||
import org.mapstruct.Mappings;
|
import org.mapstruct.Mappings;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sjaak Derksen
|
* @author Andreas Gudian
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
@Mapper
|
@Mapper(
|
||||||
public interface SourceTargetMapperErroneouslyAnnotated2 {
|
config = AutoInheritedConfig.class
|
||||||
|
)
|
||||||
|
public interface Erroneous2Mapper {
|
||||||
|
Erroneous2Mapper INSTANCE = Mappers.getMapper( Erroneous2Mapper.class );
|
||||||
|
|
||||||
SourceTargetMapperErroneouslyAnnotated2 INSTANCE
|
@InheritConfiguration( name = "toCarEntity2" )
|
||||||
= Mappers.getMapper( SourceTargetMapperErroneouslyAnnotated2.class );
|
CarEntity toCarEntity1(CarDto carDto);
|
||||||
|
|
||||||
|
@InheritConfiguration( name = "toCarEntity3" )
|
||||||
|
CarEntity toCarEntity2(CarDto carDto);
|
||||||
|
|
||||||
|
@InheritConfiguration( name = "toCarEntity1" )
|
||||||
@Mappings( {
|
@Mappings( {
|
||||||
@Mapping(source = "stringPropX", target = "stringPropY"),
|
@Mapping( target = "color", ignore = true ),
|
||||||
@Mapping(source = "integerPropX", target = "integerPropY"),
|
@Mapping( target = "auditTrail", ignore = true ),
|
||||||
@Mapping(source = "propertyToIgnoreDownstream", target = "propertyNotToIgnoreUpstream")
|
@Mapping( target = "primaryKey", ignore = true )
|
||||||
} )
|
} )
|
||||||
Target forward(Source source);
|
void toCarEntity3(CarDto carDto, @MappingTarget CarEntity entity);
|
||||||
|
|
||||||
@InheritConfiguration(name = "forward2")
|
|
||||||
Source forward2(Target target);
|
|
||||||
|
|
||||||
@InheritInverseConfiguration(name = "forward2")
|
|
||||||
Target reverse(Source source);
|
|
||||||
}
|
}
|
@ -0,0 +1,216 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.inheritfromconfig;
|
||||||
|
|
||||||
|
import javax.tools.Diagnostic.Kind;
|
||||||
|
|
||||||
|
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.compilation.annotation.CompilationResult;
|
||||||
|
import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic;
|
||||||
|
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
|
||||||
|
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||||
|
|
||||||
|
import static org.fest.assertions.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andreas Gudian
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@RunWith( AnnotationProcessorTestRunner.class )
|
||||||
|
@WithClasses( {
|
||||||
|
BaseVehicleDto.class,
|
||||||
|
BaseVehicleEntity.class,
|
||||||
|
CarDto.class,
|
||||||
|
CarEntity.class,
|
||||||
|
CarMapperWithAutoInheritance.class,
|
||||||
|
CarMapperWithExplicitInheritance.class,
|
||||||
|
AutoInheritedConfig.class } )
|
||||||
|
@IssueKey( "168" )
|
||||||
|
public class InheritFromConfigTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void autoInheritedMappingIsApplied() {
|
||||||
|
CarDto carDto = newTestDto();
|
||||||
|
|
||||||
|
CarEntity carEntity = CarMapperWithAutoInheritance.INSTANCE.toCarEntity( carDto );
|
||||||
|
|
||||||
|
assertEntity( carEntity );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void autoInheritedMappingIsAppliedForMappingTarget() {
|
||||||
|
CarDto carDto = newTestDto();
|
||||||
|
CarEntity carEntity = new CarEntity();
|
||||||
|
|
||||||
|
CarMapperWithAutoInheritance.INSTANCE.intoCarEntityOnItsOwn( carDto, carEntity );
|
||||||
|
|
||||||
|
assertEntity( carEntity );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void autoInheritedMappingIsAppliedForMappingTargetWithTwoStepInheritance() {
|
||||||
|
CarDto carDto = newTestDto();
|
||||||
|
CarEntity carEntity = new CarEntity();
|
||||||
|
|
||||||
|
CarMapperWithAutoInheritance.INSTANCE.intoCarEntity( carDto, carEntity );
|
||||||
|
|
||||||
|
assertEntity( carEntity );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertEntity(CarEntity carEntity) {
|
||||||
|
assertThat( carEntity.getColor() ).isEqualTo( "red" );
|
||||||
|
assertThat( carEntity.getPrimaryKey() ).isEqualTo( 42L );
|
||||||
|
assertThat( carEntity.getAuditTrail() ).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
private CarDto newTestDto() {
|
||||||
|
CarDto carDto = new CarDto();
|
||||||
|
carDto.setColour( "red" );
|
||||||
|
carDto.setId( 42L );
|
||||||
|
return carDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void autoInheritedMappingIsOverriddenAtMethodLevel() {
|
||||||
|
CarDto carDto = newTestDto();
|
||||||
|
|
||||||
|
CarEntity carEntity = CarMapperWithAutoInheritance.INSTANCE.toCarEntityWithFixedAuditTrail( carDto );
|
||||||
|
|
||||||
|
assertThat( carEntity.getColor() ).isEqualTo( "red" );
|
||||||
|
assertThat( carEntity.getPrimaryKey() ).isEqualTo( 42L );
|
||||||
|
assertThat( carEntity.getAuditTrail() ).isEqualTo( "fixed" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void autoInheritedMappingIsAppliedInReverse() {
|
||||||
|
CarEntity carEntity = new CarEntity();
|
||||||
|
carEntity.setColor( "red" );
|
||||||
|
carEntity.setPrimaryKey( 42L );
|
||||||
|
|
||||||
|
CarDto carDto = CarMapperWithAutoInheritance.INSTANCE.toCarDto( carEntity );
|
||||||
|
|
||||||
|
assertThat( carDto.getColour() ).isEqualTo( "red" );
|
||||||
|
assertThat( carDto.getId() ).isEqualTo( 42L );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void explicitInheritedMappingIsAppliedInReverse() {
|
||||||
|
CarEntity carEntity = new CarEntity();
|
||||||
|
carEntity.setColor( "red" );
|
||||||
|
carEntity.setPrimaryKey( 42L );
|
||||||
|
|
||||||
|
CarDto carDto = CarMapperWithExplicitInheritance.INSTANCE.toCarDto( carEntity );
|
||||||
|
|
||||||
|
assertThat( carDto.getColour() ).isEqualTo( "red" );
|
||||||
|
assertThat( carDto.getId() ).isEqualTo( 42L );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void explicitInheritedMappingWithTwoLevelsIsOverriddenAtMethodLevel() {
|
||||||
|
CarDto carDto = newTestDto();
|
||||||
|
|
||||||
|
CarEntity carEntity = CarMapperWithExplicitInheritance.INSTANCE.toCarEntityWithFixedAuditTrail( carDto );
|
||||||
|
|
||||||
|
assertThat( carEntity.getColor() ).isEqualTo( "red" );
|
||||||
|
assertThat( carEntity.getPrimaryKey() ).isEqualTo( 42L );
|
||||||
|
assertThat( carEntity.getAuditTrail() ).isEqualTo( "fixed" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void explicitInheritedMappingIsApplied() {
|
||||||
|
CarDto carDto = newTestDto();
|
||||||
|
|
||||||
|
CarEntity carEntity = CarMapperWithExplicitInheritance.INSTANCE.toCarEntity( carDto );
|
||||||
|
|
||||||
|
assertEntity( carEntity );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithClasses( {
|
||||||
|
DriverDto.class,
|
||||||
|
CarWithDriverEntity.class,
|
||||||
|
CarWithDriverMapperWithAutoInheritance.class,
|
||||||
|
AutoInheritedDriverConfig.class } )
|
||||||
|
public void autoInheritedFromMultipleSources() {
|
||||||
|
CarDto carDto = newTestDto();
|
||||||
|
DriverDto driverDto = new DriverDto();
|
||||||
|
driverDto.setName( "Malcroft" );
|
||||||
|
|
||||||
|
CarWithDriverEntity carWithDriverEntity =
|
||||||
|
CarWithDriverMapperWithAutoInheritance.INSTANCE.toCarWithDriverEntity( carDto, driverDto );
|
||||||
|
|
||||||
|
assertEntity( carWithDriverEntity );
|
||||||
|
assertThat( carWithDriverEntity.getDriverName() ).isEqualTo( "Malcroft" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithClasses( { Erroneous1Mapper.class, Erroneous1Config.class } )
|
||||||
|
@ExpectedCompilationOutcome(
|
||||||
|
value = CompilationResult.FAILED,
|
||||||
|
diagnostics = {
|
||||||
|
@Diagnostic( type = Erroneous1Mapper.class,
|
||||||
|
kind = Kind.ERROR,
|
||||||
|
line = 37,
|
||||||
|
messageRegExp = "More than one configuration prototype method is applicable. Use @InheritConfiguration"
|
||||||
|
+ " to select one of them explicitly:"
|
||||||
|
+ " .*BaseVehicleEntity baseDtoToEntity\\(.*BaseVehicleDto dto\\),"
|
||||||
|
+ " .*BaseVehicleEntity anythingToEntity\\(java.lang.Object anyting\\)\\." ),
|
||||||
|
@Diagnostic( type = Erroneous1Mapper.class,
|
||||||
|
kind = Kind.WARNING,
|
||||||
|
line = 37,
|
||||||
|
messageRegExp = "Unmapped target properties: \"auditTrail, primaryKey\"\\." ),
|
||||||
|
@Diagnostic( type = Erroneous1Mapper.class,
|
||||||
|
kind = Kind.ERROR,
|
||||||
|
line = 43,
|
||||||
|
messageRegExp = "More than one configuration prototype method is applicable. Use @InheritConfiguration"
|
||||||
|
+ " to select one of them explicitly:"
|
||||||
|
+ " .*BaseVehicleEntity baseDtoToEntity\\(.*BaseVehicleDto dto\\),"
|
||||||
|
+ " .*BaseVehicleEntity anythingToEntity\\(java.lang.Object anyting\\)\\." ),
|
||||||
|
@Diagnostic( type = Erroneous1Mapper.class,
|
||||||
|
kind = Kind.WARNING,
|
||||||
|
line = 43,
|
||||||
|
messageRegExp = "Unmapped target property: \"primaryKey\"\\." )
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public void erroneous1MultiplePrototypeMethodsMatch() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithClasses( { Erroneous2Mapper.class } )
|
||||||
|
@ExpectedCompilationOutcome(
|
||||||
|
value = CompilationResult.FAILED,
|
||||||
|
diagnostics = {
|
||||||
|
@Diagnostic( type = Erroneous2Mapper.class,
|
||||||
|
kind = Kind.ERROR,
|
||||||
|
line = 39,
|
||||||
|
messageRegExp = "Cycle detected while evaluating inherited configurations. Inheritance path:"
|
||||||
|
+ " .*CarEntity toCarEntity1\\(.*CarDto carDto\\)"
|
||||||
|
+ " -> .*CarEntity toCarEntity2\\(.*CarDto carDto\\)"
|
||||||
|
+ " -> void toCarEntity3\\(.*CarDto carDto, @MappingTarget .*CarEntity entity\\)"
|
||||||
|
+ " -> .*CarEntity toCarEntity1\\(.*CarDto carDto\\)" )
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public void erroneous2InheritanceCycle() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -23,11 +23,13 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mapstruct.CollectionMappingStrategy;
|
import org.mapstruct.CollectionMappingStrategy;
|
||||||
|
import org.mapstruct.MappingInheritanceStrategy;
|
||||||
|
import org.mapstruct.NullValueMappingStrategy;
|
||||||
import org.mapstruct.ap.prism.CollectionMappingStrategyPrism;
|
import org.mapstruct.ap.prism.CollectionMappingStrategyPrism;
|
||||||
|
import org.mapstruct.ap.prism.MappingInheritanceStrategyPrism;
|
||||||
|
import org.mapstruct.ap.prism.NullValueMappingStrategyPrism;
|
||||||
|
|
||||||
import static org.fest.assertions.Assertions.assertThat;
|
import static org.fest.assertions.Assertions.assertThat;
|
||||||
import org.mapstruct.NullValueMappingStrategy;
|
|
||||||
import org.mapstruct.ap.prism.NullValueMappingStrategyPrism;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for manually created prisms on enumeration types
|
* Test for manually created prisms on enumeration types
|
||||||
@ -47,6 +49,12 @@ public class EnumPrismsTest {
|
|||||||
namesOf( NullValueMappingStrategyPrism.values() ) );
|
namesOf( NullValueMappingStrategyPrism.values() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mapMappingInheritanceStrategyPrismIsCorrect() {
|
||||||
|
assertThat( namesOf( MappingInheritanceStrategy.values() ) ).isEqualTo(
|
||||||
|
namesOf( MappingInheritanceStrategyPrism.values() ) );
|
||||||
|
}
|
||||||
|
|
||||||
private static List<String> namesOf(Enum<?>[] values) {
|
private static List<String> namesOf(Enum<?>[] values) {
|
||||||
List<String> names = new ArrayList<String>( values.length );
|
List<String> names = new ArrayList<String>( values.length );
|
||||||
|
|
||||||
|
@ -108,8 +108,8 @@ public class InheritInverseConfigurationTest {
|
|||||||
@Diagnostic(type = SourceTargetMapperAmbiguous3.class,
|
@Diagnostic(type = SourceTargetMapperAmbiguous3.class,
|
||||||
kind = Kind.ERROR,
|
kind = Kind.ERROR,
|
||||||
line = 50,
|
line = 50,
|
||||||
messageRegExp = "Given name \"forward\" matches several candidate methods: .*forward.*\\(\\), "
|
messageRegExp = "Given name \"forward\" matches several candidate methods: .*forward\\(.*\\), "
|
||||||
+ ".*forward.*\\(\\)"),
|
+ ".*forward\\(.*\\)"),
|
||||||
@Diagnostic(type = SourceTargetMapperAmbiguous3.class,
|
@Diagnostic(type = SourceTargetMapperAmbiguous3.class,
|
||||||
kind = Kind.WARNING,
|
kind = Kind.WARNING,
|
||||||
line = 55,
|
line = 55,
|
||||||
@ -119,46 +119,6 @@ public class InheritInverseConfigurationTest {
|
|||||||
public void shouldRaiseAmbiguousReverseMethodErrorDuplicatedName() {
|
public void shouldRaiseAmbiguousReverseMethodErrorDuplicatedName() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
@WithClasses({ SourceTargetMapperErroneouslyAnnotated1.class })
|
|
||||||
@ExpectedCompilationOutcome(
|
|
||||||
value = CompilationResult.FAILED,
|
|
||||||
diagnostics = {
|
|
||||||
@Diagnostic(type = SourceTargetMapperErroneouslyAnnotated1.class,
|
|
||||||
kind = Kind.ERROR,
|
|
||||||
line = 50,
|
|
||||||
messageRegExp = "Resolved inverse mapping method reverse\\(\\) should not carry the "
|
|
||||||
+ "@InheritInverseConfiguration annotation itself.")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
public void shouldUseWronglyAnnotatedError1() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@WithClasses({ SourceTargetMapperErroneouslyAnnotated2.class })
|
|
||||||
@ExpectedCompilationOutcome(
|
|
||||||
value = CompilationResult.FAILED,
|
|
||||||
diagnostics = {
|
|
||||||
@Diagnostic(type = SourceTargetMapperErroneouslyAnnotated2.class,
|
|
||||||
kind = Kind.WARNING,
|
|
||||||
line = 45,
|
|
||||||
messageRegExp = "Unmapped target properties: \"stringPropX, integerPropX, "
|
|
||||||
+ "someConstantDownstream, propertyToIgnoreDownstream\""),
|
|
||||||
@Diagnostic(type = SourceTargetMapperErroneouslyAnnotated2.class,
|
|
||||||
kind = Kind.ERROR,
|
|
||||||
line = 47,
|
|
||||||
messageRegExp = "Resolved inverse mapping method forward2\\(\\) should not carry "
|
|
||||||
+ "the @InheritConfiguration annotation"),
|
|
||||||
@Diagnostic(type = SourceTargetMapperErroneouslyAnnotated2.class,
|
|
||||||
kind = Kind.WARNING,
|
|
||||||
line = 48,
|
|
||||||
messageRegExp = "Unmapped target properties: \"stringPropY, integerPropY, "
|
|
||||||
+ "propertyNotToIgnoreUpstream\"")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
public void shouldUseWronglyAnnotatedError2() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithClasses({ SourceTargetMapperNonMatchingName.class })
|
@WithClasses({ SourceTargetMapperNonMatchingName.class })
|
||||||
@ExpectedCompilationOutcome(
|
@ExpectedCompilationOutcome(
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2012-2015 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.reverse;
|
|
||||||
|
|
||||||
import org.mapstruct.InheritInverseConfiguration;
|
|
||||||
import org.mapstruct.Mapper;
|
|
||||||
import org.mapstruct.Mapping;
|
|
||||||
import org.mapstruct.Mappings;
|
|
||||||
import org.mapstruct.factory.Mappers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Sjaak Derksen
|
|
||||||
*/
|
|
||||||
@Mapper
|
|
||||||
public interface SourceTargetMapperErroneouslyAnnotated1 {
|
|
||||||
|
|
||||||
SourceTargetMapperErroneouslyAnnotated1 INSTANCE =
|
|
||||||
Mappers.getMapper( SourceTargetMapperErroneouslyAnnotated1.class );
|
|
||||||
|
|
||||||
@Mappings({
|
|
||||||
@Mapping(source = "stringPropX", target = "stringPropY"),
|
|
||||||
@Mapping(source = "integerPropX", target = "integerPropY"),
|
|
||||||
@Mapping(source = "propertyToIgnoreDownstream", target = "propertyNotToIgnoreUpstream")
|
|
||||||
})
|
|
||||||
Target forward(Source source);
|
|
||||||
|
|
||||||
@InheritInverseConfiguration(name = "forward")
|
|
||||||
@Mappings({
|
|
||||||
@Mapping(target = "someConstantDownstream", constant = "test"),
|
|
||||||
@Mapping(target = "propertyToIgnoreDownstream", ignore = true)
|
|
||||||
})
|
|
||||||
Source reverse(Target target);
|
|
||||||
|
|
||||||
@InheritInverseConfiguration(name = "reverse")
|
|
||||||
@Mappings({
|
|
||||||
@Mapping(source = "stringPropX", target = "stringPropY"),
|
|
||||||
@Mapping(source = "integerPropX", target = "integerPropY"),
|
|
||||||
@Mapping(source = "propertyToIgnoreDownstream", target = "propertyNotToIgnoreUpstream")
|
|
||||||
})
|
|
||||||
Target forward2(Source source);
|
|
||||||
}
|
|
@ -182,36 +182,6 @@ public class InheritConfigurationTest {
|
|||||||
public void shouldRaiseAmbiguousReverseMethodErrorDuplicatedName() {
|
public void shouldRaiseAmbiguousReverseMethodErrorDuplicatedName() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
@WithClasses({ SourceTargetMapperErroneouslyAnnotated1.class })
|
|
||||||
@ExpectedCompilationOutcome(
|
|
||||||
value = CompilationResult.FAILED,
|
|
||||||
diagnostics = {
|
|
||||||
@Diagnostic(type = SourceTargetMapperErroneouslyAnnotated1.class,
|
|
||||||
kind = Kind.ERROR,
|
|
||||||
line = 49,
|
|
||||||
messageRegExp = "Resolved mapping method forwardCreate1\\(\\) should not carry the "
|
|
||||||
+ "@InheritConfiguration annotation itself.")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
public void shouldUseWronglyAnnotatedError1() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@WithClasses({ SourceTargetMapperErroneouslyAnnotated2.class })
|
|
||||||
@ExpectedCompilationOutcome(
|
|
||||||
value = CompilationResult.FAILED,
|
|
||||||
diagnostics = {
|
|
||||||
@Diagnostic(type = SourceTargetMapperErroneouslyAnnotated2.class,
|
|
||||||
kind = Kind.ERROR,
|
|
||||||
line = 51,
|
|
||||||
messageRegExp = "Resolved mapping method forwardCreate\\(\\) should not carry the "
|
|
||||||
+ "@InheritInverseConfiguration annotation.")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
public void shouldUseWronglyAnnotatedError2() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithClasses({ SourceTargetMapperNonMatchingName.class })
|
@WithClasses({ SourceTargetMapperNonMatchingName.class })
|
||||||
@ExpectedCompilationOutcome(
|
@ExpectedCompilationOutcome(
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2012-2015 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.template;
|
|
||||||
|
|
||||||
import org.mapstruct.InheritConfiguration;
|
|
||||||
import org.mapstruct.Mapper;
|
|
||||||
import org.mapstruct.Mapping;
|
|
||||||
import org.mapstruct.MappingTarget;
|
|
||||||
import org.mapstruct.Mappings;
|
|
||||||
import org.mapstruct.factory.Mappers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Sjaak Derksen
|
|
||||||
*/
|
|
||||||
@Mapper
|
|
||||||
public interface SourceTargetMapperErroneouslyAnnotated1 {
|
|
||||||
|
|
||||||
SourceTargetMapperErroneouslyAnnotated1 INSTANCE =
|
|
||||||
Mappers.getMapper( SourceTargetMapperErroneouslyAnnotated1.class );
|
|
||||||
|
|
||||||
@Mappings({
|
|
||||||
@Mapping(target = "stringPropY", source = "stringPropX"),
|
|
||||||
@Mapping(target = "integerPropY", source = "integerPropX"),
|
|
||||||
@Mapping(target = "nestedResultProp", source = "nestedSourceProp.nested"),
|
|
||||||
@Mapping(target = "constantProp", constant = "constant"),
|
|
||||||
@Mapping(target = "expressionProp", expression = "java(\"expression\")")
|
|
||||||
})
|
|
||||||
Target forwardCreate(Source source);
|
|
||||||
|
|
||||||
@InheritConfiguration( name = "forwardCreate" )
|
|
||||||
Target forwardCreate1(Source source);
|
|
||||||
|
|
||||||
@InheritConfiguration( name = "forwardCreate1" )
|
|
||||||
void forwardUpdate(Source source, @MappingTarget Target target);
|
|
||||||
}
|
|
@ -34,11 +34,11 @@ public interface SourceTargetMapperSeveralArgs {
|
|||||||
SourceTargetMapperSeveralArgs INSTANCE = Mappers.getMapper( SourceTargetMapperSeveralArgs.class );
|
SourceTargetMapperSeveralArgs INSTANCE = Mappers.getMapper( SourceTargetMapperSeveralArgs.class );
|
||||||
|
|
||||||
@Mappings({
|
@Mappings({
|
||||||
@Mapping(target = "stringPropY", source = "source.stringPropX"),
|
@Mapping( target = "stringPropY", source = "s1.stringPropX" ),
|
||||||
@Mapping(target = "integerPropY", source = "source.integerPropX"),
|
@Mapping( target = "integerPropY", source = "s1.integerPropX" ),
|
||||||
@Mapping(target = "nestedResultProp", source = "source.nestedSourceProp.nested")
|
@Mapping( target = "nestedResultProp", source = "s1.nestedSourceProp.nested" )
|
||||||
})
|
})
|
||||||
Target forwardCreate(Source source, String constantProp, String expressionProp);
|
Target forwardCreate(Source s1, String constantProp, String expressionProp);
|
||||||
|
|
||||||
@InheritConfiguration
|
@InheritConfiguration
|
||||||
void forwardUpdate(Source source, String constantProp, String expressionProp, @MappingTarget Target target);
|
void forwardUpdate(Source source, String constantProp, String expressionProp, @MappingTarget Target target);
|
||||||
|
@ -40,7 +40,7 @@ public interface SourceTargetMapperSingle {
|
|||||||
@Mapping(target = "constantProp", constant = "constant"),
|
@Mapping(target = "constantProp", constant = "constant"),
|
||||||
@Mapping(target = "expressionProp", expression = "java(\"expression\")"),
|
@Mapping(target = "expressionProp", expression = "java(\"expression\")"),
|
||||||
})
|
})
|
||||||
Target forwardCreate(Source source);
|
Target forwardCreate(Source s1);
|
||||||
|
|
||||||
|
|
||||||
@InheritConfiguration
|
@InheritConfiguration
|
||||||
|
Loading…
x
Reference in New Issue
Block a user