mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#1321 Support index for list properties
This commit is contained in:
parent
e0a7d3d0e6
commit
0b095fb062
@ -21,13 +21,13 @@ import org.mapstruct.ap.internal.model.beanmapping.PropertyEntry;
|
|||||||
import org.mapstruct.ap.internal.model.beanmapping.SourceReference;
|
import org.mapstruct.ap.internal.model.beanmapping.SourceReference;
|
||||||
import org.mapstruct.ap.internal.model.beanmapping.TargetReference;
|
import org.mapstruct.ap.internal.model.beanmapping.TargetReference;
|
||||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||||
import org.mapstruct.ap.internal.util.accessor.ReadAccessor;
|
|
||||||
import org.mapstruct.ap.internal.model.common.Type;
|
import org.mapstruct.ap.internal.model.common.Type;
|
||||||
import org.mapstruct.ap.internal.model.source.MappingOptions;
|
import org.mapstruct.ap.internal.model.source.MappingOptions;
|
||||||
import org.mapstruct.ap.internal.model.source.Method;
|
import org.mapstruct.ap.internal.model.source.Method;
|
||||||
import org.mapstruct.ap.internal.util.Message;
|
import org.mapstruct.ap.internal.util.Message;
|
||||||
import org.mapstruct.ap.internal.util.Strings;
|
import org.mapstruct.ap.internal.util.Strings;
|
||||||
import org.mapstruct.ap.internal.util.accessor.Accessor;
|
import org.mapstruct.ap.internal.util.accessor.Accessor;
|
||||||
|
import org.mapstruct.ap.internal.util.accessor.ReadAccessor;
|
||||||
|
|
||||||
import static org.mapstruct.ap.internal.util.Collections.first;
|
import static org.mapstruct.ap.internal.util.Collections.first;
|
||||||
|
|
||||||
@ -665,6 +665,15 @@ public class NestedTargetPropertyMappingHolder {
|
|||||||
pathProperties.set( pathProperties.size() - 1, mostSimilarProperty );
|
pathProperties.set( pathProperties.size() - 1, mostSimilarProperty );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean reverseInheritedListElementAccessor = mapping.getInheritContext() != null
|
||||||
|
&& mapping.getInheritContext().isReversed()
|
||||||
|
&& targetPropertyName.contains( "[" );
|
||||||
|
if ( reverseInheritedListElementAccessor ) {
|
||||||
|
// ignore reverse inherited source properties with index accessor like "names[0]"
|
||||||
|
errorOccurred = false;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
mappingContext.getMessager()
|
mappingContext.getMessager()
|
||||||
.printMessage(
|
.printMessage(
|
||||||
mapping.getElement(),
|
mapping.getElement(),
|
||||||
|
@ -23,6 +23,7 @@ import org.mapstruct.ap.internal.model.source.Method;
|
|||||||
import org.mapstruct.ap.internal.util.FormattingMessager;
|
import org.mapstruct.ap.internal.util.FormattingMessager;
|
||||||
import org.mapstruct.ap.internal.util.Message;
|
import org.mapstruct.ap.internal.util.Message;
|
||||||
import org.mapstruct.ap.internal.util.Strings;
|
import org.mapstruct.ap.internal.util.Strings;
|
||||||
|
import org.mapstruct.ap.internal.util.accessor.ListElementAccessor;
|
||||||
import org.mapstruct.ap.internal.util.accessor.PresenceCheckAccessor;
|
import org.mapstruct.ap.internal.util.accessor.PresenceCheckAccessor;
|
||||||
import org.mapstruct.ap.internal.util.accessor.ReadAccessor;
|
import org.mapstruct.ap.internal.util.accessor.ReadAccessor;
|
||||||
|
|
||||||
@ -322,12 +323,51 @@ public class SourceReference extends AbstractReference {
|
|||||||
boolean allowedMapToBean) {
|
boolean allowedMapToBean) {
|
||||||
List<PropertyEntry> sourceEntries = new ArrayList<>();
|
List<PropertyEntry> sourceEntries = new ArrayList<>();
|
||||||
Type newType = type;
|
Type newType = type;
|
||||||
for ( int i = 0; i < entryNames.length; i++ ) {
|
for (int i = 0; i < entryNames.length; i++) {
|
||||||
boolean matchFound = false;
|
boolean matchFound = false;
|
||||||
|
|
||||||
|
String entryName = entryNames[i];
|
||||||
|
int bracketIndex = entryName.indexOf( '[' );
|
||||||
|
boolean containsIndex = bracketIndex != -1 && entryName.endsWith( "]" );
|
||||||
|
if ( containsIndex ) {
|
||||||
|
String baseName = entryName.substring( 0, bracketIndex );
|
||||||
|
String rawIndex = entryName.substring( bracketIndex + 1, entryName.length() - 1 );
|
||||||
|
|
||||||
|
ReadAccessor listAccessor = newType.withoutBounds()
|
||||||
|
.getReadAccessor( baseName, i > 0 || allowedMapToBean );
|
||||||
|
if ( listAccessor != null ) {
|
||||||
|
|
||||||
|
newType = typeFactory.getReturnType(
|
||||||
|
(DeclaredType) newType.withoutBounds().getTypeMirror(),
|
||||||
|
listAccessor
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( !newType.isListType() ) {
|
||||||
|
reportMappingError( Message.PROPERTYMAPPING_INDEX_ACCESSORS_ONLY_ON_LIST, baseName );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type elementType = newType.getTypeParameters().get( 0 );
|
||||||
|
int index = tryParseIndex( rawIndex );
|
||||||
|
ReadAccessor listElementAccessor =
|
||||||
|
new ListElementAccessor( listAccessor, elementType.getTypeMirror(), index );
|
||||||
|
|
||||||
|
sourceEntries.add( forSourceReference(
|
||||||
|
Arrays.copyOf( entryNames, i + 1 ),
|
||||||
|
listElementAccessor,
|
||||||
|
PresenceCheckAccessor.listSizeGreaterThan( listAccessor, index ),
|
||||||
|
elementType
|
||||||
|
) );
|
||||||
|
newType = elementType;
|
||||||
|
matchFound = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
Type noBoundsType = newType.withoutBounds();
|
Type noBoundsType = newType.withoutBounds();
|
||||||
ReadAccessor readAccessor = noBoundsType.getReadAccessor( entryNames[i], i > 0 || allowedMapToBean );
|
ReadAccessor readAccessor = noBoundsType.getReadAccessor( entryName, i > 0 || allowedMapToBean );
|
||||||
if ( readAccessor != null ) {
|
if (readAccessor != null) {
|
||||||
PresenceCheckAccessor presenceChecker = noBoundsType.getPresenceChecker( entryNames[i] );
|
PresenceCheckAccessor presenceChecker = noBoundsType.getPresenceChecker( entryName );
|
||||||
newType = typeFactory.getReturnType(
|
newType = typeFactory.getReturnType(
|
||||||
(DeclaredType) noBoundsType.getTypeMirror(),
|
(DeclaredType) noBoundsType.getTypeMirror(),
|
||||||
readAccessor
|
readAccessor
|
||||||
@ -340,6 +380,7 @@ public class SourceReference extends AbstractReference {
|
|||||||
) );
|
) );
|
||||||
matchFound = true;
|
matchFound = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if ( !matchFound ) {
|
if ( !matchFound ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -347,6 +388,17 @@ public class SourceReference extends AbstractReference {
|
|||||||
return sourceEntries;
|
return sourceEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int tryParseIndex(String rawIndex) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Integer.parseInt( rawIndex );
|
||||||
|
}
|
||||||
|
catch ( NumberFormatException e ) {
|
||||||
|
reportMappingError( Message.PROPERTYMAPPING_INDEX_NOT_A_NUMBER, rawIndex );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void reportMappingError(Message msg, Object... objects) {
|
private void reportMappingError(Message msg, Object... objects) {
|
||||||
messager.printMessage( method.getExecutable(), annotationMirror, sourceAnnotationValue, msg, objects );
|
messager.printMessage( method.getExecutable(), annotationMirror, sourceAnnotationValue, msg, objects );
|
||||||
}
|
}
|
||||||
|
@ -105,6 +105,7 @@ public class Type extends ModelElement implements Comparable<Type> {
|
|||||||
private final boolean isEnumType;
|
private final boolean isEnumType;
|
||||||
private final boolean isIterableType;
|
private final boolean isIterableType;
|
||||||
private final boolean isCollectionType;
|
private final boolean isCollectionType;
|
||||||
|
private final boolean isListType;
|
||||||
private final boolean isMapType;
|
private final boolean isMapType;
|
||||||
private final boolean isVoid;
|
private final boolean isVoid;
|
||||||
private final boolean isStream;
|
private final boolean isStream;
|
||||||
@ -145,7 +146,7 @@ public class Type extends ModelElement implements Comparable<Type> {
|
|||||||
List<Type> typeParameters, ImplementationType implementationType, Type componentType,
|
List<Type> typeParameters, ImplementationType implementationType, Type componentType,
|
||||||
String packageName, String name, String qualifiedName,
|
String packageName, String name, String qualifiedName,
|
||||||
boolean isInterface, boolean isEnumType, boolean isIterableType,
|
boolean isInterface, boolean isEnumType, boolean isIterableType,
|
||||||
boolean isCollectionType, boolean isMapType, boolean isStreamType,
|
boolean isCollectionType, boolean isListType, boolean isMapType, boolean isStreamType,
|
||||||
Map<String, String> toBeImportedTypes,
|
Map<String, String> toBeImportedTypes,
|
||||||
Map<String, String> notToBeImportedTypes,
|
Map<String, String> notToBeImportedTypes,
|
||||||
Boolean isToBeImported,
|
Boolean isToBeImported,
|
||||||
@ -170,6 +171,7 @@ public class Type extends ModelElement implements Comparable<Type> {
|
|||||||
this.isEnumType = isEnumType;
|
this.isEnumType = isEnumType;
|
||||||
this.isIterableType = isIterableType;
|
this.isIterableType = isIterableType;
|
||||||
this.isCollectionType = isCollectionType;
|
this.isCollectionType = isCollectionType;
|
||||||
|
this.isListType = isListType;
|
||||||
this.isMapType = isMapType;
|
this.isMapType = isMapType;
|
||||||
this.isStream = isStreamType;
|
this.isStream = isStreamType;
|
||||||
this.isVoid = typeMirror.getKind() == TypeKind.VOID;
|
this.isVoid = typeMirror.getKind() == TypeKind.VOID;
|
||||||
@ -344,6 +346,10 @@ public class Type extends ModelElement implements Comparable<Type> {
|
|||||||
return isCollectionType;
|
return isCollectionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isListType() {
|
||||||
|
return isListType;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isMapType() {
|
public boolean isMapType() {
|
||||||
return isMapType;
|
return isMapType;
|
||||||
}
|
}
|
||||||
@ -552,6 +558,7 @@ public class Type extends ModelElement implements Comparable<Type> {
|
|||||||
isEnumType,
|
isEnumType,
|
||||||
isIterableType,
|
isIterableType,
|
||||||
isCollectionType,
|
isCollectionType,
|
||||||
|
isListType,
|
||||||
isMapType,
|
isMapType,
|
||||||
isStream,
|
isStream,
|
||||||
toBeImportedTypes,
|
toBeImportedTypes,
|
||||||
@ -595,6 +602,7 @@ public class Type extends ModelElement implements Comparable<Type> {
|
|||||||
isEnumType,
|
isEnumType,
|
||||||
isIterableType,
|
isIterableType,
|
||||||
isCollectionType,
|
isCollectionType,
|
||||||
|
isListType,
|
||||||
isMapType,
|
isMapType,
|
||||||
isStream,
|
isStream,
|
||||||
toBeImportedTypes,
|
toBeImportedTypes,
|
||||||
|
@ -94,6 +94,7 @@ public class TypeFactory {
|
|||||||
|
|
||||||
private final TypeMirror iterableType;
|
private final TypeMirror iterableType;
|
||||||
private final TypeMirror collectionType;
|
private final TypeMirror collectionType;
|
||||||
|
private final TypeMirror listType;
|
||||||
private final TypeMirror mapType;
|
private final TypeMirror mapType;
|
||||||
private final TypeMirror streamType;
|
private final TypeMirror streamType;
|
||||||
|
|
||||||
@ -115,6 +116,8 @@ public class TypeFactory {
|
|||||||
iterableType = typeUtils.erasure( elementUtils.getTypeElement( Iterable.class.getCanonicalName() ).asType() );
|
iterableType = typeUtils.erasure( elementUtils.getTypeElement( Iterable.class.getCanonicalName() ).asType() );
|
||||||
collectionType =
|
collectionType =
|
||||||
typeUtils.erasure( elementUtils.getTypeElement( Collection.class.getCanonicalName() ).asType() );
|
typeUtils.erasure( elementUtils.getTypeElement( Collection.class.getCanonicalName() ).asType() );
|
||||||
|
listType =
|
||||||
|
typeUtils.erasure( elementUtils.getTypeElement( List.class.getCanonicalName() ).asType() );
|
||||||
mapType = typeUtils.erasure( elementUtils.getTypeElement( Map.class.getCanonicalName() ).asType() );
|
mapType = typeUtils.erasure( elementUtils.getTypeElement( Map.class.getCanonicalName() ).asType() );
|
||||||
TypeElement streamTypeElement = elementUtils.getTypeElement( JavaStreamConstants.STREAM_FQN );
|
TypeElement streamTypeElement = elementUtils.getTypeElement( JavaStreamConstants.STREAM_FQN );
|
||||||
streamType = streamTypeElement == null ? null : typeUtils.erasure( streamTypeElement.asType() );
|
streamType = streamTypeElement == null ? null : typeUtils.erasure( streamTypeElement.asType() );
|
||||||
@ -235,6 +238,7 @@ public class TypeFactory {
|
|||||||
|
|
||||||
boolean isIterableType = typeUtils.isSubtypeErased( mirror, iterableType );
|
boolean isIterableType = typeUtils.isSubtypeErased( mirror, iterableType );
|
||||||
boolean isCollectionType = typeUtils.isSubtypeErased( mirror, collectionType );
|
boolean isCollectionType = typeUtils.isSubtypeErased( mirror, collectionType );
|
||||||
|
boolean isListType = typeUtils.isSubtypeErased( mirror, listType );
|
||||||
boolean isMapType = typeUtils.isSubtypeErased( mirror, mapType );
|
boolean isMapType = typeUtils.isSubtypeErased( mirror, mapType );
|
||||||
boolean isStreamType = streamType != null && typeUtils.isSubtypeErased( mirror, streamType );
|
boolean isStreamType = streamType != null && typeUtils.isSubtypeErased( mirror, streamType );
|
||||||
|
|
||||||
@ -344,6 +348,7 @@ public class TypeFactory {
|
|||||||
isEnumType,
|
isEnumType,
|
||||||
isIterableType,
|
isIterableType,
|
||||||
isCollectionType,
|
isCollectionType,
|
||||||
|
isListType,
|
||||||
isMapType,
|
isMapType,
|
||||||
isStreamType,
|
isStreamType,
|
||||||
toBeImportedTypes,
|
toBeImportedTypes,
|
||||||
@ -574,6 +579,7 @@ public class TypeFactory {
|
|||||||
implementationType.isEnumType(),
|
implementationType.isEnumType(),
|
||||||
implementationType.isIterableType(),
|
implementationType.isIterableType(),
|
||||||
implementationType.isCollectionType(),
|
implementationType.isCollectionType(),
|
||||||
|
implementationType.isListType(),
|
||||||
implementationType.isMapType(),
|
implementationType.isMapType(),
|
||||||
implementationType.isStreamType(),
|
implementationType.isStreamType(),
|
||||||
toBeImportedTypes,
|
toBeImportedTypes,
|
||||||
|
@ -92,6 +92,8 @@ public enum Message {
|
|||||||
PROPERTYMAPPING_CANNOT_DETERMINE_SOURCE_PARAMETER_FROM_TARGET("No property named \"%s\" exists in source parameter(s). Please define the source explicitly."),
|
PROPERTYMAPPING_CANNOT_DETERMINE_SOURCE_PARAMETER_FROM_TARGET("No property named \"%s\" exists in source parameter(s). Please define the source explicitly."),
|
||||||
PROPERTYMAPPING_NO_SUITABLE_COLLECTION_OR_MAP_CONSTRUCTOR( "%s does not have an accessible copy or no-args constructor." ),
|
PROPERTYMAPPING_NO_SUITABLE_COLLECTION_OR_MAP_CONSTRUCTOR( "%s does not have an accessible copy or no-args constructor." ),
|
||||||
PROPERTYMAPPING_EXPRESSION_AND_CONDITION_QUALIFIED_BY_NAME_BOTH_DEFINED( "Expression and condition qualified by name are both defined in @Mapping, either define an expression or a condition qualified by name." ),
|
PROPERTYMAPPING_EXPRESSION_AND_CONDITION_QUALIFIED_BY_NAME_BOTH_DEFINED( "Expression and condition qualified by name are both defined in @Mapping, either define an expression or a condition qualified by name." ),
|
||||||
|
PROPERTYMAPPING_INDEX_ACCESSORS_ONLY_ON_LIST( "Can't access element with index because \"%s\" is not of type List." ),
|
||||||
|
PROPERTYMAPPING_INDEX_NOT_A_NUMBER( "Index accessor must be an integer but was: \"%s\"." ),
|
||||||
|
|
||||||
CONVERSION_LOSSY_WARNING( "%s has a possibly lossy conversion from %s to %s.", Diagnostic.Kind.WARNING ),
|
CONVERSION_LOSSY_WARNING( "%s has a possibly lossy conversion from %s to %s.", Diagnostic.Kind.WARNING ),
|
||||||
CONVERSION_LOSSY_ERROR( "Can't map %s. It has a possibly lossy conversion from %s to %s." ),
|
CONVERSION_LOSSY_ERROR( "Can't map %s. It has a possibly lossy conversion from %s to %s." ),
|
||||||
@ -185,8 +187,8 @@ public enum Message {
|
|||||||
RETRIEVAL_MAPPER_USES_CYCLE( "The mapper %s is referenced itself in Mapper#uses.", Diagnostic.Kind.WARNING ),
|
RETRIEVAL_MAPPER_USES_CYCLE( "The mapper %s is referenced itself in Mapper#uses.", Diagnostic.Kind.WARNING ),
|
||||||
RETRIEVAL_AFTER_METHOD_NOT_IMPLEMENTED( "@AfterMapping can only be applied to an implemented method." ),
|
RETRIEVAL_AFTER_METHOD_NOT_IMPLEMENTED( "@AfterMapping can only be applied to an implemented method." ),
|
||||||
RETRIEVAL_BEFORE_METHOD_NOT_IMPLEMENTED( "@BeforeMapping can only be applied to an implemented method." ),
|
RETRIEVAL_BEFORE_METHOD_NOT_IMPLEMENTED( "@BeforeMapping can only be applied to an implemented method." ),
|
||||||
RETRIEVAL_SOURCE_PROPERTY_NAME_WRONG_TYPE( "@SourcePropertyName can only by applied to a String parameter." ),
|
RETRIEVAL_SOURCE_PROPERTY_NAME_WRONG_TYPE( "@SourcePropertyName can only be applied to a String parameter." ),
|
||||||
RETRIEVAL_TARGET_PROPERTY_NAME_WRONG_TYPE( "@TargetPropertyName can only by applied to a String parameter." ),
|
RETRIEVAL_TARGET_PROPERTY_NAME_WRONG_TYPE( "@TargetPropertyName can only be applied to a String parameter." ),
|
||||||
|
|
||||||
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\"." ),
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.internal.util.accessor;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.lang.model.element.Element;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
import javax.lang.model.type.TypeMirror;
|
||||||
|
|
||||||
|
public class ListElementAccessor implements ReadAccessor {
|
||||||
|
|
||||||
|
private final ReadAccessor listAccessor;
|
||||||
|
private final TypeMirror elementTypeMirror;
|
||||||
|
private final int index;
|
||||||
|
|
||||||
|
public ListElementAccessor(ReadAccessor listAccessor, TypeMirror elementTypeMirror, int index) {
|
||||||
|
this.listAccessor = listAccessor;
|
||||||
|
this.elementTypeMirror = elementTypeMirror;
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeMirror getAccessedType() {
|
||||||
|
return elementTypeMirror;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSimpleName() {
|
||||||
|
return listAccessor.getSimpleName() + "[" + index + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Modifier> getModifiers() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Element getElement() {
|
||||||
|
return listAccessor.getElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessorType getAccessorType() {
|
||||||
|
return AccessorType.GETTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getReadValueSource() {
|
||||||
|
return listAccessor.getReadValueSource() + ".get( " + index + " )";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -22,6 +22,10 @@ public interface PresenceCheckAccessor {
|
|||||||
return suffix( ".containsKey( \"" + propertyName + "\" )" );
|
return suffix( ".containsKey( \"" + propertyName + "\" )" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PresenceCheckAccessor listSizeGreaterThan(ReadAccessor listAccessor, int index) {
|
||||||
|
return suffix( "." + listAccessor.getSimpleName() + "().size() > " + index );
|
||||||
|
}
|
||||||
|
|
||||||
static PresenceCheckAccessor suffix(String suffix) {
|
static PresenceCheckAccessor suffix(String suffix) {
|
||||||
return () -> suffix;
|
return () -> suffix;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<#lt>private <@includeModel object=returnType.typeBound/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>)<@throws/> {
|
<#lt>private <@includeModel object=returnType.typeBound/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>)<@throws/> {
|
||||||
<#list propertyEntries as entry>
|
<#list propertyEntries as entry>
|
||||||
<#if entry.presenceChecker?? >
|
<#if entry.presenceChecker?? >
|
||||||
if ( <#if entry_index != 0>${entry.previousPropertyName} == null || </#if>!<@includeModel object=entry.presenceChecker /> ) {
|
if ( <#if entry_index != 0>${entry.previousPropertyName} == null || </#if><@includeModel object=entry.presenceChecker.negate() /> ) {
|
||||||
return ${returnType.null};
|
return ${returnType.null};
|
||||||
}
|
}
|
||||||
</#if>
|
</#if>
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.internal.model.common;
|
package org.mapstruct.ap.internal.model.common;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@ -14,7 +12,6 @@ import java.time.LocalTime;
|
|||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.lang.model.element.AnnotationMirror;
|
import javax.lang.model.element.AnnotationMirror;
|
||||||
import javax.lang.model.type.TypeKind;
|
import javax.lang.model.type.TypeKind;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
@ -24,6 +21,8 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.mapstruct.ap.internal.util.JodaTimeConstants;
|
import org.mapstruct.ap.internal.util.JodaTimeConstants;
|
||||||
import org.mapstruct.ap.testutil.IssueKey;
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link org.mapstruct.ap.internal.model.common.DateFormatValidatorFactory}.
|
* Tests for {@link org.mapstruct.ap.internal.model.common.DateFormatValidatorFactory}.
|
||||||
*
|
*
|
||||||
@ -174,6 +173,7 @@ public class DateFormatValidatorFactoryTest {
|
|||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
new HashMap<>( ),
|
new HashMap<>( ),
|
||||||
new HashMap<>( ),
|
new HashMap<>( ),
|
||||||
false,
|
false,
|
||||||
|
@ -5,13 +5,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.internal.model.common;
|
package org.mapstruct.ap.internal.model.common;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
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.Element;
|
import javax.lang.model.element.Element;
|
||||||
@ -25,6 +22,8 @@ import org.mapstruct.ap.internal.util.FormattingMessager;
|
|||||||
import org.mapstruct.ap.internal.util.Message;
|
import org.mapstruct.ap.internal.util.Message;
|
||||||
import org.mapstruct.ap.testutil.IssueKey;
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Testing DefaultConversionContext for dateFormat
|
* Testing DefaultConversionContext for dateFormat
|
||||||
*
|
*
|
||||||
@ -122,6 +121,7 @@ public class DefaultConversionContextTest {
|
|||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
new HashMap<>( ),
|
new HashMap<>( ),
|
||||||
new HashMap<>( ),
|
new HashMap<>( ),
|
||||||
false,
|
false,
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.collection.index;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Car {
|
||||||
|
|
||||||
|
String make;
|
||||||
|
List<Person> personList;
|
||||||
|
|
||||||
|
public String getMake() {
|
||||||
|
return make;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMake(String make) {
|
||||||
|
this.make = make;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Person> getPersonList() {
|
||||||
|
return personList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPersonList(List<Person> personList) {
|
||||||
|
this.personList = personList;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.collection.index;
|
||||||
|
|
||||||
|
public class CarDto {
|
||||||
|
|
||||||
|
Person driver;
|
||||||
|
String manufacturer;
|
||||||
|
|
||||||
|
public Person getDriver() {
|
||||||
|
return driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDriver(Person driver) {
|
||||||
|
this.driver = driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getManufacturer() {
|
||||||
|
return manufacturer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setManufacturer(String manufacturer) {
|
||||||
|
this.manufacturer = manufacturer;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.collection.index;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class CarWithArrayList {
|
||||||
|
|
||||||
|
String make;
|
||||||
|
ArrayList<Person> personList;
|
||||||
|
|
||||||
|
public String getMake() {
|
||||||
|
return make;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMake(String make) {
|
||||||
|
this.make = make;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Person> getPersonList() {
|
||||||
|
return personList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPersonList(ArrayList<Person> personList) {
|
||||||
|
this.personList = personList;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.collection.index;
|
||||||
|
|
||||||
|
public class CarWithDriverNameDto {
|
||||||
|
|
||||||
|
String driverName;
|
||||||
|
Person driver;
|
||||||
|
String manufacturer;
|
||||||
|
|
||||||
|
public String getDriverName() {
|
||||||
|
return driverName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDriverName(String driverName) {
|
||||||
|
this.driverName = driverName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person getDriver() {
|
||||||
|
return driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDriver(Person driver) {
|
||||||
|
this.driver = driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getManufacturer() {
|
||||||
|
return manufacturer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setManufacturer(String manufacturer) {
|
||||||
|
this.manufacturer = manufacturer;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.collection.index;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class DriverList {
|
||||||
|
|
||||||
|
Set<Person> drivers;
|
||||||
|
|
||||||
|
public Set<Person> getDrivers() {
|
||||||
|
return drivers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDrivers(Set<Person> drivers) {
|
||||||
|
this.drivers = drivers;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.collection.index;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ErroneousListIndexIsNoNumberMapper {
|
||||||
|
|
||||||
|
@Mapping(target = "manufacturer", source = "make")
|
||||||
|
@Mapping(target = "driver", source = "personList[x]")
|
||||||
|
CarDto mapList(Car source);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.collection.index;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ErroneousListIndexOnSetMapper {
|
||||||
|
|
||||||
|
@Mapping(target = "name", source = "drivers[0].name")
|
||||||
|
PersonDto sourceToTarget(DriverList source);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.collection.index;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ErroneousListIndexOnStringMapper {
|
||||||
|
|
||||||
|
@Mapping(target = "name", source = "name[0]")
|
||||||
|
PersonDto sourceToTarget(Person source);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.collection.index;
|
||||||
|
|
||||||
|
import org.mapstruct.InheritInverseConfiguration;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ListIndexInheritInverseMapper {
|
||||||
|
|
||||||
|
@Mapping(target = "manufacturer", source = "make")
|
||||||
|
@Mapping(target = "driver", source = "personList[0]")
|
||||||
|
CarDto mapList(Car source);
|
||||||
|
|
||||||
|
@InheritInverseConfiguration
|
||||||
|
@Mapping(target = "personList", ignore = true)
|
||||||
|
Car mapListInverseInherited(CarDto source);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.collection.index;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.MappingTarget;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ListIndexMapper {
|
||||||
|
|
||||||
|
@Mapping(target = "manufacturer", source = "make")
|
||||||
|
@Mapping(target = "driver", source = "personList[0]")
|
||||||
|
CarDto mapList(Car source);
|
||||||
|
|
||||||
|
@Mapping(target = "manufacturer", source = "make")
|
||||||
|
@Mapping(target = "driver", source = "personList[0]")
|
||||||
|
void updateList(Car source, @MappingTarget CarDto target);
|
||||||
|
|
||||||
|
@Mapping(target = "manufacturer", source = "make")
|
||||||
|
@Mapping(target = "driver", source = "personList[0]")
|
||||||
|
CarDto mapArrayList(CarWithArrayList source);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.collection.index;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
|
import org.mapstruct.ap.testutil.ProcessorTest;
|
||||||
|
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.factory.Mappers;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Oliver Erhart
|
||||||
|
*/
|
||||||
|
@WithClasses({
|
||||||
|
Car.class,
|
||||||
|
CarDto.class,
|
||||||
|
CarWithArrayList.class,
|
||||||
|
CarWithDriverNameDto.class,
|
||||||
|
Person.class,
|
||||||
|
PersonDto.class,
|
||||||
|
ListIndexMapper.class,
|
||||||
|
ListIndexNestedPropertyMapper.class
|
||||||
|
})
|
||||||
|
@IssueKey("1321")
|
||||||
|
public class ListIndexMappingTest {
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
public void shouldMapWithDirectAssignment() {
|
||||||
|
|
||||||
|
Car source = new Car();
|
||||||
|
List<Person> personList = new ArrayList<>();
|
||||||
|
personList.add( new Person( "First" ) );
|
||||||
|
personList.add( new Person( "Second" ) );
|
||||||
|
source.setPersonList( personList );
|
||||||
|
|
||||||
|
CarDto target = Mappers.getMapper( ListIndexMapper.class ).mapList( source );
|
||||||
|
|
||||||
|
assertThat( target.getDriver().getName() ).isEqualTo( "First" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
public void shouldMapWithDirectArrayListAssignment() {
|
||||||
|
|
||||||
|
CarWithArrayList source = new CarWithArrayList();
|
||||||
|
ArrayList<Person> personList = new ArrayList<>();
|
||||||
|
personList.add( new Person( "First" ) );
|
||||||
|
personList.add( new Person( "Second" ) );
|
||||||
|
source.setPersonList( personList );
|
||||||
|
|
||||||
|
CarDto target = Mappers.getMapper( ListIndexMapper.class ).mapArrayList( source );
|
||||||
|
|
||||||
|
assertThat( target.getDriver().getName() ).isEqualTo( "First" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
public void shouldBeNullWhenDirectAssignmentIndexOutOfBounds() {
|
||||||
|
|
||||||
|
Car source = new Car();
|
||||||
|
source.setPersonList( new ArrayList<>() );
|
||||||
|
|
||||||
|
CarDto target = Mappers.getMapper( ListIndexMapper.class ).mapList( source );
|
||||||
|
|
||||||
|
assertThat( target.getDriver() ).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
public void shouldMapWithNestedPropertyAssignment() {
|
||||||
|
|
||||||
|
Car source = new Car();
|
||||||
|
List<Person> personList = new ArrayList<>();
|
||||||
|
personList.add( new Person( "First" ) );
|
||||||
|
personList.add( new Person( "Second" ) );
|
||||||
|
source.setPersonList( personList );
|
||||||
|
|
||||||
|
CarWithDriverNameDto target = Mappers.getMapper( ListIndexNestedPropertyMapper.class ).sourceToTarget( source );
|
||||||
|
|
||||||
|
assertThat( target.getDriver().getName() ).isEqualTo( "First" );
|
||||||
|
assertThat( target.getDriverName() ).isEqualTo( "First" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
public void shouldBeNullWhenNestedPropertyAssignmentIndexOutOfBounds() {
|
||||||
|
|
||||||
|
Car source = new Car();
|
||||||
|
source.setPersonList( new ArrayList<>() );
|
||||||
|
|
||||||
|
CarWithDriverNameDto target = Mappers.getMapper( ListIndexNestedPropertyMapper.class ).sourceToTarget( source );
|
||||||
|
|
||||||
|
assertThat( target.getDriver() ).isNull();
|
||||||
|
assertThat( target.getDriverName() ).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
@WithClasses(ErroneousListIndexOnStringMapper.class)
|
||||||
|
@ExpectedCompilationOutcome(
|
||||||
|
value = CompilationResult.FAILED,
|
||||||
|
diagnostics = {
|
||||||
|
@Diagnostic(
|
||||||
|
kind = javax.tools.Diagnostic.Kind.ERROR,
|
||||||
|
type = ErroneousListIndexOnStringMapper.class,
|
||||||
|
line = 14,
|
||||||
|
message = "Can't access element with index because \"name\" is not of type List."
|
||||||
|
),
|
||||||
|
@Diagnostic(
|
||||||
|
kind = javax.tools.Diagnostic.Kind.ERROR,
|
||||||
|
type = ErroneousListIndexOnStringMapper.class,
|
||||||
|
line = 14,
|
||||||
|
message = "No property named \"name[0]\" exists in source parameter(s). Did you mean \"name\"?"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public void errorWhenSourceIsStringInsteadOfList() { }
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
@WithClasses(ErroneousListIndexIsNoNumberMapper.class)
|
||||||
|
@ExpectedCompilationOutcome(
|
||||||
|
value = CompilationResult.FAILED,
|
||||||
|
diagnostics = {
|
||||||
|
@Diagnostic(
|
||||||
|
kind = javax.tools.Diagnostic.Kind.ERROR,
|
||||||
|
type = ErroneousListIndexIsNoNumberMapper.class,
|
||||||
|
message = "Index accessor must be an integer but was: \"x\"."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public void errorWhenIndexIsNoNumber() { }
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
@WithClasses({
|
||||||
|
ErroneousListIndexOnSetMapper.class,
|
||||||
|
DriverList.class
|
||||||
|
})
|
||||||
|
@ExpectedCompilationOutcome(
|
||||||
|
value = CompilationResult.FAILED,
|
||||||
|
diagnostics = {
|
||||||
|
@Diagnostic(
|
||||||
|
kind = javax.tools.Diagnostic.Kind.ERROR,
|
||||||
|
type = ErroneousListIndexOnSetMapper.class,
|
||||||
|
line = 14,
|
||||||
|
message = "Can't access element with index because \"drivers\" is not of type List."
|
||||||
|
),
|
||||||
|
@Diagnostic(
|
||||||
|
kind = javax.tools.Diagnostic.Kind.ERROR,
|
||||||
|
type = ErroneousListIndexOnSetMapper.class,
|
||||||
|
line = 14,
|
||||||
|
message = "No property named \"drivers[0].name\" exists in source parameter(s)." +
|
||||||
|
" Did you mean \"drivers\"?"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public void errorWhenSourceIsSetInsteadOfList() { }
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.collection.index;
|
||||||
|
|
||||||
|
import org.mapstruct.InheritInverseConfiguration;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ListIndexNestedPropertyMapper {
|
||||||
|
|
||||||
|
@Mapping(target = "manufacturer", source = "make")
|
||||||
|
@Mapping(target = "driver", source = "personList[0]")
|
||||||
|
@Mapping(target = "driverName", source = "source.personList[0].name")
|
||||||
|
CarWithDriverNameDto sourceToTarget(Car source);
|
||||||
|
|
||||||
|
@Mapping(target = "personList", ignore = true)
|
||||||
|
@InheritInverseConfiguration
|
||||||
|
Car inverseInherited(CarWithDriverNameDto source);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.collection.index;
|
||||||
|
|
||||||
|
public class Person {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Person(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.collection.index;
|
||||||
|
|
||||||
|
public class PersonDto {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
@ -302,7 +302,7 @@ public class SourcePropertyNameTest {
|
|||||||
kind = javax.tools.Diagnostic.Kind.ERROR,
|
kind = javax.tools.Diagnostic.Kind.ERROR,
|
||||||
type = ErroneousNonStringSourcePropertyNameParameter.class,
|
type = ErroneousNonStringSourcePropertyNameParameter.class,
|
||||||
line = 23,
|
line = 23,
|
||||||
message = "@SourcePropertyName can only by applied to a String parameter."
|
message = "@SourcePropertyName can only be applied to a String parameter."
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -301,7 +301,7 @@ public class TargetPropertyNameTest {
|
|||||||
kind = javax.tools.Diagnostic.Kind.ERROR,
|
kind = javax.tools.Diagnostic.Kind.ERROR,
|
||||||
type = ErroneousNonStringTargetPropertyNameParameter.class,
|
type = ErroneousNonStringTargetPropertyNameParameter.class,
|
||||||
line = 23,
|
line = 23,
|
||||||
message = "@TargetPropertyName can only by applied to a String parameter."
|
message = "@TargetPropertyName can only be applied to a String parameter."
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user