mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#1247 Make sure that nested target mappings works correctly for multiple source parameters
This commit is contained in:
parent
d9821a0cc8
commit
db3bb5eba0
@ -19,8 +19,9 @@
|
|||||||
package org.mapstruct.ap.internal.model;
|
package org.mapstruct.ap.internal.model;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -56,7 +57,8 @@ public class NestedTargetPropertyMappingHolder {
|
|||||||
Extractor<SourceReference, PropertyEntry>() {
|
Extractor<SourceReference, PropertyEntry>() {
|
||||||
@Override
|
@Override
|
||||||
public PropertyEntry apply(SourceReference sourceReference) {
|
public PropertyEntry apply(SourceReference sourceReference) {
|
||||||
return first( sourceReference.getPropertyEntries() );
|
return sourceReference.getPropertyEntries().isEmpty() ? null :
|
||||||
|
first( sourceReference.getPropertyEntries() );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -117,6 +119,8 @@ public class NestedTargetPropertyMappingHolder {
|
|||||||
private Method method;
|
private Method method;
|
||||||
private MappingBuilderContext mappingContext;
|
private MappingBuilderContext mappingContext;
|
||||||
private Set<String> existingVariableNames;
|
private Set<String> existingVariableNames;
|
||||||
|
private List<PropertyMapping> propertyMappings;
|
||||||
|
private Set<String> handledTargets;
|
||||||
|
|
||||||
public Builder method(Method method) {
|
public Builder method(Method method) {
|
||||||
this.method = method;
|
this.method = method;
|
||||||
@ -135,8 +139,8 @@ public class NestedTargetPropertyMappingHolder {
|
|||||||
|
|
||||||
public NestedTargetPropertyMappingHolder build() {
|
public NestedTargetPropertyMappingHolder build() {
|
||||||
List<Parameter> processedSourceParameters = new ArrayList<Parameter>();
|
List<Parameter> processedSourceParameters = new ArrayList<Parameter>();
|
||||||
Set<String> handledTargets = new HashSet<String>();
|
handledTargets = new HashSet<String>();
|
||||||
List<PropertyMapping> propertyMappings = new ArrayList<PropertyMapping>();
|
propertyMappings = new ArrayList<PropertyMapping>();
|
||||||
|
|
||||||
// first we group by the first property in the target properties and for each of those
|
// first we group by the first property in the target properties and for each of those
|
||||||
// properties we get the new mappings as if the first property did not exist.
|
// properties we get the new mappings as if the first property did not exist.
|
||||||
@ -164,7 +168,7 @@ public class NestedTargetPropertyMappingHolder {
|
|||||||
// Lastly we need to group by the source references. This will allow us to actually create
|
// Lastly we need to group by the source references. This will allow us to actually create
|
||||||
// the next mappings by popping source elements
|
// the next mappings by popping source elements
|
||||||
GroupedSourceReferences groupedSourceReferences = groupByPoppedSourceReferences(
|
GroupedSourceReferences groupedSourceReferences = groupByPoppedSourceReferences(
|
||||||
entryByParam.getValue(),
|
entryByParam,
|
||||||
groupedByTP.singleTargetReferences.get( targetProperty )
|
groupedByTP.singleTargetReferences.get( targetProperty )
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -229,6 +233,13 @@ public class NestedTargetPropertyMappingHolder {
|
|||||||
handledTargets.add( entryByTP.getKey().getName() );
|
handledTargets.add( entryByTP.getKey().getName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleSourceParameterMappings(
|
||||||
|
groupedSourceReferences.sourceParameterMappings,
|
||||||
|
targetProperty,
|
||||||
|
sourceParameter,
|
||||||
|
forceUpdateMethod
|
||||||
|
);
|
||||||
|
|
||||||
unprocessedDefinedTarget.put( targetProperty, groupedSourceReferences.notProcessedAppliesToAll );
|
unprocessedDefinedTarget.put( targetProperty, groupedSourceReferences.notProcessedAppliesToAll );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,6 +253,43 @@ public class NestedTargetPropertyMappingHolder {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the {@link PropertyMapping} creation for source parameter mappings.
|
||||||
|
*
|
||||||
|
* @param sourceParameterMappings the source parameter mappings for which property mapping should be done
|
||||||
|
* @param targetProperty the target property that is being mapped
|
||||||
|
* @param sourceParameter the source parameter that is used
|
||||||
|
* @param forceUpdateMethod whether we need to force an update method
|
||||||
|
*/
|
||||||
|
private void handleSourceParameterMappings(List<Mapping> sourceParameterMappings, PropertyEntry targetProperty,
|
||||||
|
Parameter sourceParameter, boolean forceUpdateMethod) {
|
||||||
|
if ( !sourceParameterMappings.isEmpty() ) {
|
||||||
|
// The source parameter mappings have no mappings, the source name is actually the parameter itself
|
||||||
|
MappingOptions nonNestedOptions = MappingOptions.forMappingsOnly(
|
||||||
|
new HashMap<String, List<Mapping>>(),
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
SourceReference reference = new SourceReference.BuilderFromProperty()
|
||||||
|
.sourceParameter( sourceParameter )
|
||||||
|
.name( targetProperty.getName() )
|
||||||
|
.build();
|
||||||
|
|
||||||
|
PropertyMapping propertyMapping = createPropertyMappingForNestedTarget(
|
||||||
|
nonNestedOptions,
|
||||||
|
targetProperty,
|
||||||
|
reference,
|
||||||
|
forceUpdateMethod
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( propertyMapping != null ) {
|
||||||
|
propertyMappings.add( propertyMapping );
|
||||||
|
}
|
||||||
|
|
||||||
|
handledTargets.add( targetProperty.getName() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The target references are popped. The {@code List<}{@link Mapping}{@code >} are keyed on the unique first
|
* The target references are popped. The {@code List<}{@link Mapping}{@code >} are keyed on the unique first
|
||||||
* entries of the target references.
|
* entries of the target references.
|
||||||
@ -464,15 +512,18 @@ public class NestedTargetPropertyMappingHolder {
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param mappings the list of {@link Mapping} that needs to be used for grouping on popped source references
|
* @param entryByParam the entry of a {@link Parameter} and it's associated {@link Mapping}(s) that need to
|
||||||
|
* be used for grouping on popped source references
|
||||||
* @param singleTargetReferences the single target references that match the source mappings
|
* @param singleTargetReferences the single target references that match the source mappings
|
||||||
*
|
*
|
||||||
* @return the Grouped Source References
|
* @return the Grouped Source References
|
||||||
*/
|
*/
|
||||||
private GroupedSourceReferences groupByPoppedSourceReferences(List<Mapping> mappings,
|
private GroupedSourceReferences groupByPoppedSourceReferences(Map.Entry<Parameter, List<Mapping>> entryByParam,
|
||||||
List<Mapping> singleTargetReferences) {
|
List<Mapping> singleTargetReferences) {
|
||||||
|
List<Mapping> mappings = entryByParam.getValue();
|
||||||
List<Mapping> nonNested = new ArrayList<Mapping>();
|
List<Mapping> nonNested = new ArrayList<Mapping>();
|
||||||
List<Mapping> appliesToAll = new ArrayList<Mapping>();
|
List<Mapping> appliesToAll = new ArrayList<Mapping>();
|
||||||
|
List<Mapping> sourceParameterMappings = new ArrayList<Mapping>();
|
||||||
// group all mappings based on the top level name before popping
|
// group all mappings based on the top level name before popping
|
||||||
Map<PropertyEntry, List<Mapping>> mappingsKeyedByProperty
|
Map<PropertyEntry, List<Mapping>> mappingsKeyedByProperty
|
||||||
= new LinkedHashMap<PropertyEntry, List<Mapping>>();
|
= new LinkedHashMap<PropertyEntry, List<Mapping>>();
|
||||||
@ -496,7 +547,24 @@ public class NestedTargetPropertyMappingHolder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
populateWithSingleTargetReferences( mappingsKeyedByProperty, singleTargetReferences, PROPERTY_EXTRACTOR );
|
// We consider that there were no mappings if there are no mappingsKeyedByProperty
|
||||||
|
// and no nonNested. appliesToAll Mappings are mappings that have no source reference and need to be
|
||||||
|
// applied to everything.
|
||||||
|
boolean hasNoMappings = mappingsKeyedByProperty.isEmpty() && nonNested.isEmpty();
|
||||||
|
Parameter sourceParameter = entryByParam.getKey();
|
||||||
|
List<Mapping> singleTargetReferencesToUse =
|
||||||
|
extractSingleTargetReferencesToUseAndPopulateSourceParameterMappings(
|
||||||
|
singleTargetReferences,
|
||||||
|
sourceParameterMappings,
|
||||||
|
hasNoMappings,
|
||||||
|
sourceParameter
|
||||||
|
);
|
||||||
|
|
||||||
|
populateWithSingleTargetReferences(
|
||||||
|
mappingsKeyedByProperty,
|
||||||
|
singleTargetReferencesToUse,
|
||||||
|
PROPERTY_EXTRACTOR
|
||||||
|
);
|
||||||
|
|
||||||
for ( Map.Entry<PropertyEntry, List<Mapping>> entry : mappingsKeyedByProperty.entrySet() ) {
|
for ( Map.Entry<PropertyEntry, List<Mapping>> entry : mappingsKeyedByProperty.entrySet() ) {
|
||||||
entry.getValue().addAll( appliesToAll );
|
entry.getValue().addAll( appliesToAll );
|
||||||
@ -516,10 +584,55 @@ public class NestedTargetPropertyMappingHolder {
|
|||||||
return new GroupedSourceReferences(
|
return new GroupedSourceReferences(
|
||||||
mappingsKeyedByProperty,
|
mappingsKeyedByProperty,
|
||||||
nonNested,
|
nonNested,
|
||||||
notProcessedAppliesToAll
|
notProcessedAppliesToAll,
|
||||||
|
sourceParameterMappings
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts all relevant single target references and populates the {@code sourceParameterMappings} if needed.
|
||||||
|
* A relevant single target reference mapping is a mapping that has a valid source reference and is for
|
||||||
|
* the {@code sourceParameter}. If there are no mappings i.e. {@code hasNoMappings = true} and the source
|
||||||
|
* reference in the mapping has no property entries then add that to the {@code sourceParameterMappings}
|
||||||
|
* (mappings like this have found themselves here because there is a mapping method with multiple parameters
|
||||||
|
* and that are using the same sub-path in the target properties).
|
||||||
|
*
|
||||||
|
* @param singleTargetReferences All the single target references for a target property
|
||||||
|
* @param sourceParameterMappings a List that needs to be populated with valid mappings when {@code
|
||||||
|
* hasNoMappings = true} and there are no property entries in the source reference
|
||||||
|
* @param hasNoMappings parameter indicating whether there were any extracted mappings for this target property
|
||||||
|
* @param sourceParameter the source parameter for which the grouping is being done
|
||||||
|
*
|
||||||
|
* @return a list with valid single target references
|
||||||
|
*/
|
||||||
|
private List<Mapping> extractSingleTargetReferencesToUseAndPopulateSourceParameterMappings(
|
||||||
|
List<Mapping> singleTargetReferences, List<Mapping> sourceParameterMappings, boolean hasNoMappings,
|
||||||
|
Parameter sourceParameter) {
|
||||||
|
List<Mapping> singleTargetReferencesToUse = null;
|
||||||
|
if ( singleTargetReferences != null ) {
|
||||||
|
singleTargetReferencesToUse = new ArrayList<Mapping>( singleTargetReferences.size() );
|
||||||
|
for ( Mapping mapping : singleTargetReferences ) {
|
||||||
|
if ( mapping.getSourceReference() == null || !mapping.getSourceReference().isValid() ||
|
||||||
|
!sourceParameter.equals( mapping.getSourceReference().getParameter() ) ) {
|
||||||
|
// If the mapping has no sourceReference, it is not valid or it does not have the same source
|
||||||
|
// parameter then we need to ignore it. When a mapping method has multiple parameters it can
|
||||||
|
// happen that different parameters somehow have same path in the nesting
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( hasNoMappings && mapping.getSourceReference().getPropertyEntries().isEmpty() ) {
|
||||||
|
// If there were no mappings for this source parameter and there are no property entries
|
||||||
|
// that means that this could be for a mapping method with multiple parameters.
|
||||||
|
// We have to consider and map this separately
|
||||||
|
sourceParameterMappings.add( mapping );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
singleTargetReferencesToUse.add( mapping );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return singleTargetReferencesToUse;
|
||||||
|
}
|
||||||
|
|
||||||
private Map<String, List<Mapping>> groupByTargetName(List<Mapping> mappingList) {
|
private Map<String, List<Mapping>> groupByTargetName(List<Mapping> mappingList) {
|
||||||
Map<String, List<Mapping>> result = new LinkedHashMap<String, List<Mapping>>();
|
Map<String, List<Mapping>> result = new LinkedHashMap<String, List<Mapping>>();
|
||||||
for ( Mapping mapping : mappingList ) {
|
for ( Mapping mapping : mappingList ) {
|
||||||
@ -563,11 +676,9 @@ public class NestedTargetPropertyMappingHolder {
|
|||||||
//This are non nested target references only their property needs to be added as they most probably
|
//This are non nested target references only their property needs to be added as they most probably
|
||||||
// define it
|
// define it
|
||||||
for ( Mapping mapping : singleTargetReferences ) {
|
for ( Mapping mapping : singleTargetReferences ) {
|
||||||
if ( mapping.getSourceReference() != null && mapping.getSourceReference().isValid()
|
if ( mapping.getSourceReference() != null && mapping.getSourceReference().isValid() ) {
|
||||||
&& !mapping.getSourceReference().getPropertyEntries().isEmpty() ) {
|
|
||||||
//TODO is this OK? Why there are no propertyEntries? For the Inverse LetterMapper for example
|
|
||||||
K key = keyExtractor.apply( mapping.getSourceReference() );
|
K key = keyExtractor.apply( mapping.getSourceReference() );
|
||||||
if ( !map.containsKey( key ) ) {
|
if ( key != null && !map.containsKey( key ) ) {
|
||||||
map.put( key, new ArrayList<Mapping>() );
|
map.put( key, new ArrayList<Mapping>() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -642,12 +753,15 @@ public class NestedTargetPropertyMappingHolder {
|
|||||||
private final Map<PropertyEntry, List<Mapping>> groupedBySourceReferences;
|
private final Map<PropertyEntry, List<Mapping>> groupedBySourceReferences;
|
||||||
private final List<Mapping> nonNested;
|
private final List<Mapping> nonNested;
|
||||||
private final List<Mapping> notProcessedAppliesToAll;
|
private final List<Mapping> notProcessedAppliesToAll;
|
||||||
|
private final List<Mapping> sourceParameterMappings;
|
||||||
|
|
||||||
private GroupedSourceReferences(Map<PropertyEntry, List<Mapping>> groupedBySourceReferences,
|
private GroupedSourceReferences(Map<PropertyEntry, List<Mapping>> groupedBySourceReferences,
|
||||||
List<Mapping> nonNested, List<Mapping> notProcessedAppliesToAll) {
|
List<Mapping> nonNested, List<Mapping> notProcessedAppliesToAll,
|
||||||
|
List<Mapping> sourceParameterMappings) {
|
||||||
this.groupedBySourceReferences = groupedBySourceReferences;
|
this.groupedBySourceReferences = groupedBySourceReferences;
|
||||||
this.nonNested = nonNested;
|
this.nonNested = nonNested;
|
||||||
this.notProcessedAppliesToAll = notProcessedAppliesToAll;
|
this.notProcessedAppliesToAll = notProcessedAppliesToAll;
|
||||||
|
this.sourceParameterMappings = sourceParameterMappings;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,11 +81,25 @@ public class MappingOptions {
|
|||||||
*/
|
*/
|
||||||
public static MappingOptions forMappingsOnly(Map<String, List<Mapping>> mappings,
|
public static MappingOptions forMappingsOnly(Map<String, List<Mapping>> mappings,
|
||||||
boolean restrictToDefinedMappings) {
|
boolean restrictToDefinedMappings) {
|
||||||
|
return forMappingsOnly( mappings, restrictToDefinedMappings, restrictToDefinedMappings );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* creates mapping options with only regular mappings
|
||||||
|
*
|
||||||
|
* @param mappings regular mappings to add
|
||||||
|
* @param restrictToDefinedMappings whether to restrict the mappings only to the defined mappings
|
||||||
|
* @param forForgedMethods whether the mappings are for forged methods
|
||||||
|
* @return MappingOptions with only regular mappings
|
||||||
|
*/
|
||||||
|
public static MappingOptions forMappingsOnly(Map<String, List<Mapping>> mappings,
|
||||||
|
boolean restrictToDefinedMappings, boolean forForgedMethods) {
|
||||||
return new MappingOptions(
|
return new MappingOptions(
|
||||||
mappings,
|
mappings,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
restrictToDefinedMappings ? BeanMapping.forForgedMethods() : null,
|
forForgedMethods ? BeanMapping.forForgedMethods() : null,
|
||||||
Collections.<ValueMapping>emptyList(),
|
Collections.<ValueMapping>emptyList(),
|
||||||
restrictToDefinedMappings
|
restrictToDefinedMappings
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
* and/or other contributors as indicated by the @authors tag. See the
|
||||||
|
* copyright.txt file in the distribution for a full listing of all
|
||||||
|
* contributors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.bugs._1247;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
public class DtoIn {
|
||||||
|
|
||||||
|
private final String data;
|
||||||
|
private final String data2;
|
||||||
|
|
||||||
|
public DtoIn(String data, String data2) {
|
||||||
|
this.data = data;
|
||||||
|
this.data2 = data2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getData2() {
|
||||||
|
return data2;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
* and/or other contributors as indicated by the @authors tag. See the
|
||||||
|
* copyright.txt file in the distribution for a full listing of all
|
||||||
|
* contributors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.bugs._1247;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
public class DtoOut {
|
||||||
|
|
||||||
|
private String data;
|
||||||
|
private InternalDto internal;
|
||||||
|
|
||||||
|
public String getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(String data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InternalDto getInternal() {
|
||||||
|
return internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInternal(InternalDto internal) {
|
||||||
|
this.internal = internal;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
* and/or other contributors as indicated by the @authors tag. See the
|
||||||
|
* copyright.txt file in the distribution for a full listing of all
|
||||||
|
* contributors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.bugs._1247;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
public class InternalData {
|
||||||
|
|
||||||
|
private List<String> list;
|
||||||
|
|
||||||
|
public List<String> getList() {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setList(List<String> list) {
|
||||||
|
this.list = list;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
* and/or other contributors as indicated by the @authors tag. See the
|
||||||
|
* copyright.txt file in the distribution for a full listing of all
|
||||||
|
* contributors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.bugs._1247;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
public class InternalDto {
|
||||||
|
|
||||||
|
private String data2;
|
||||||
|
private InternalData internalData;
|
||||||
|
|
||||||
|
public String getData2() {
|
||||||
|
return data2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData2(String data2) {
|
||||||
|
this.data2 = data2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InternalData getInternalData() {
|
||||||
|
return internalData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInternalData(InternalData internalData) {
|
||||||
|
this.internalData = internalData;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
* and/or other contributors as indicated by the @authors tag. See the
|
||||||
|
* copyright.txt file in the distribution for a full listing of all
|
||||||
|
* contributors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.bugs._1247;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.Mappings;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface Issue1247Mapper {
|
||||||
|
|
||||||
|
Issue1247Mapper INSTANCE = Mappers.getMapper( Issue1247Mapper.class );
|
||||||
|
|
||||||
|
@Mappings( {
|
||||||
|
@Mapping(target = "internal", source = "in"),
|
||||||
|
@Mapping(target = "internal.internalData.list", source = "list")
|
||||||
|
} )
|
||||||
|
DtoOut map(DtoIn in, List<String> list);
|
||||||
|
|
||||||
|
@Mappings( {
|
||||||
|
@Mapping(target = "internal", source = "in"),
|
||||||
|
@Mapping(target = "internal.expression", expression = "java(\"testingExpression\")"),
|
||||||
|
@Mapping(target = "internal.internalData.list", source = "list"),
|
||||||
|
@Mapping(target = "internal.internalData.defaultValue", source = "in.data2", defaultValue = "missing"),
|
||||||
|
@Mapping(target = "constant", constant = "someConstant")
|
||||||
|
} )
|
||||||
|
OtherDtoOut mapWithConstantExpressionAndDefault(DtoIn in, List<String> list);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,101 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
* and/or other contributors as indicated by the @authors tag. See the
|
||||||
|
* copyright.txt file in the distribution for a full listing of all
|
||||||
|
* contributors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.bugs._1247;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@IssueKey("1247")
|
||||||
|
@RunWith(AnnotationProcessorTestRunner.class)
|
||||||
|
@WithClasses({
|
||||||
|
Issue1247Mapper.class,
|
||||||
|
DtoIn.class,
|
||||||
|
DtoOut.class,
|
||||||
|
InternalData.class,
|
||||||
|
InternalDto.class,
|
||||||
|
OtherDtoOut.class,
|
||||||
|
OtherInternalData.class,
|
||||||
|
OtherInternalDto.class
|
||||||
|
})
|
||||||
|
public class Issue1247Test {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldCorrectlyUseMappings() {
|
||||||
|
|
||||||
|
DtoIn in = new DtoIn( "data", "data2" );
|
||||||
|
List<String> list = Arrays.asList( "first", "second" );
|
||||||
|
DtoOut out = Issue1247Mapper.INSTANCE.map( in, list );
|
||||||
|
|
||||||
|
assertThat( out ).isNotNull();
|
||||||
|
assertThat( out.getData() ).isEqualTo( "data" );
|
||||||
|
assertThat( out.getInternal() ).isNotNull();
|
||||||
|
assertThat( out.getInternal().getData2() ).isEqualTo( "data2" );
|
||||||
|
assertThat( out.getInternal().getInternalData() ).isNotNull();
|
||||||
|
assertThat( out.getInternal().getInternalData().getList() ).containsExactly( "first", "second" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldCorrectlyUseMappingsWithConstantsExpressionsAndDefaults() {
|
||||||
|
|
||||||
|
DtoIn in = new DtoIn( "data", "data2" );
|
||||||
|
List<String> list = Arrays.asList( "first", "second" );
|
||||||
|
OtherDtoOut out = Issue1247Mapper.INSTANCE.mapWithConstantExpressionAndDefault( in, list );
|
||||||
|
|
||||||
|
assertThat( out ).isNotNull();
|
||||||
|
assertThat( out.getData() ).isEqualTo( "data" );
|
||||||
|
assertThat( out.getConstant() ).isEqualTo( "someConstant" );
|
||||||
|
assertThat( out.getInternal() ).isNotNull();
|
||||||
|
// This will not be mapped by the @Mapping(target = "internal", source = "in") because we have one more
|
||||||
|
// symmetric mapping @Mapping(target = "internal.expression", expression = "java(\"testingExpression\")")
|
||||||
|
assertThat( out.getInternal().getData2() ).isNull();
|
||||||
|
assertThat( out.getInternal().getExpression() ).isEqualTo( "testingExpression" );
|
||||||
|
assertThat( out.getInternal().getInternalData() ).isNotNull();
|
||||||
|
assertThat( out.getInternal().getInternalData().getList() ).containsExactly( "first", "second" );
|
||||||
|
assertThat( out.getInternal().getInternalData().getDefaultValue() ).isEqualTo( "data2" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldCorrectlyUseMappingsWithConstantsExpressionsAndUseDefault() {
|
||||||
|
|
||||||
|
DtoIn in = new DtoIn( "data", null );
|
||||||
|
List<String> list = Arrays.asList( "first", "second" );
|
||||||
|
OtherDtoOut out = Issue1247Mapper.INSTANCE.mapWithConstantExpressionAndDefault( in, list );
|
||||||
|
|
||||||
|
assertThat( out ).isNotNull();
|
||||||
|
assertThat( out.getData() ).isEqualTo( "data" );
|
||||||
|
assertThat( out.getConstant() ).isEqualTo( "someConstant" );
|
||||||
|
assertThat( out.getInternal() ).isNotNull();
|
||||||
|
assertThat( out.getInternal().getData2() ).isNull();
|
||||||
|
assertThat( out.getInternal().getExpression() ).isEqualTo( "testingExpression" );
|
||||||
|
assertThat( out.getInternal().getInternalData() ).isNotNull();
|
||||||
|
assertThat( out.getInternal().getInternalData().getList() ).containsExactly( "first", "second" );
|
||||||
|
assertThat( out.getInternal().getInternalData().getDefaultValue() ).isEqualTo( "missing" );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
* and/or other contributors as indicated by the @authors tag. See the
|
||||||
|
* copyright.txt file in the distribution for a full listing of all
|
||||||
|
* contributors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.bugs._1247;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
public class OtherDtoOut {
|
||||||
|
|
||||||
|
private String data;
|
||||||
|
private OtherInternalDto internal;
|
||||||
|
private String constant;
|
||||||
|
|
||||||
|
public String getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(String data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OtherInternalDto getInternal() {
|
||||||
|
return internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInternal(OtherInternalDto internal) {
|
||||||
|
this.internal = internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConstant() {
|
||||||
|
return constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConstant(String constant) {
|
||||||
|
this.constant = constant;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
* and/or other contributors as indicated by the @authors tag. See the
|
||||||
|
* copyright.txt file in the distribution for a full listing of all
|
||||||
|
* contributors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.bugs._1247;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
public class OtherInternalData {
|
||||||
|
|
||||||
|
private List<String> list;
|
||||||
|
private String defaultValue;
|
||||||
|
|
||||||
|
public List<String> getList() {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setList(List<String> list) {
|
||||||
|
this.list = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDefaultValue() {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaultValue(String defaultValue) {
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
* and/or other contributors as indicated by the @authors tag. See the
|
||||||
|
* copyright.txt file in the distribution for a full listing of all
|
||||||
|
* contributors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.bugs._1247;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
public class OtherInternalDto {
|
||||||
|
|
||||||
|
private String data2;
|
||||||
|
private String expression;
|
||||||
|
private OtherInternalData internalData;
|
||||||
|
|
||||||
|
public String getData2() {
|
||||||
|
return data2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData2(String data2) {
|
||||||
|
this.data2 = data2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExpression() {
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpression(String expression) {
|
||||||
|
this.expression = expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OtherInternalData getInternalData() {
|
||||||
|
return internalData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInternalData(OtherInternalData internalData) {
|
||||||
|
this.internalData = internalData;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user